Wednesday, 8 June 2011

REST URL design principal simplified

Given the following URL sample: /resources/car?color=blue
We can say the following about this URL:
  • The URL itself identifies WHAT we want (Noun) which is car
  • The parameters define the filtering criteria (Pronoun)
  • The REST method (GET, POST, PUT or DELETE) is the verb or action we are taking

Monday, 30 May 2011

Web 2.0: Use Firefox Poster application to test REST applications

The Poster Firefox addon is used to test any REST applications as it used to construct the parameters and then submit the proper action (GET, POST, PUT or Delete). To add parameters, the easiest way is to choose “Body form parameters” and then add parameters as key=value pairs separated by &. For example:
first_name=Ahmed&last_name=fadel.

In the sample below, if you submitted the request as POST, then from sMash reference.groovy (the expected handler for /resources/reference), you can read those parameters as follows:

def onPostMember(){
logger.INFO {"Start"};
def first_name=zget("/request/params/first_name");
def last_name=zget("/request/params/last_name");

....
}

Firefox Poster

sMash: Enable trace in applications

The few lines below shows a sample from zero.config file. The first two lines control the request logging which dumps detailed information about each HTTP request submitted to application & frequently used with REST service development to check content of the HTTP requests. If your REST service provides its' own custom logging, then most probably enabling the request logging will not provide useful information. Just don't forget to disable it if you had to enable for any reason or you will end up with hundreds if not thousands of files in your application log folder (one log file per request). The subsequent lines (which are disabled) enables detailed application tracing which is very useful to trace hard problems especially those related to security configuration.

/config/requestLogging = false
/config/requestLoggingLimit = 10000

#Ahmed Fadel
#The lines below will enable detailed tracing which is very useful to trace security related problems
#/config/logging/levels = {
# "zero.core" : "FINE"
#}

sMash: Configure LDAP security

The lines below are extracts from zero.config file showing how to enable security with IBM LDAP.
Comments:
  • You need to generate a key for your application using the command zero secretkey
  • You need to set your own LDAP user principal and password and take care that the user principal should be in DN format
  • It is important to properly set the ldapGroupSearchFilterPattern so you can extract the groups a user is member of and thus control security based on group membership
  • The security/authorization.config defines which URL patterns are secured and which group can access them. In example below any URL which has has the pattern /editor or /resources (which is for REST service) or /test are secured and are available to members of GROUP1 only
  • Then those URL patterns can be further controlled by either basic authentication or form based authentication. In the example below, /resources URL pattern is authenticated using basic scheme while /editor and /test uses form based scheme.
  • The last stanza security/formLoginURL.config defines the location of the login form (which is login.gt)
  • A sample content is provided for login.gt
  • Make sure login.gt is directly under /public folder and don't put security constraints directly under /public folder

#Ahmed Fadel: Commenting the line which starts with @include
#will disable security

@include "security/enableSecurity.config"
#Ahmed Fadel: this is used in case of Basic Authentication only
/config/security/realm="myrelam"

#Ahmed Fadel: cd to the project folder and run the command
#zero secretKey
#copy the generated encrypted value to the stanza below
#The secret key will change during deployment
/config/security/secretKey="<you_secret_key>"

#Ahmed Fadel: The configuration below will work for IBM blue pages
#The security principal is currently set using ccspadmn@us.ibm.com
#which has non-expiring password
/config/security/userservice/registryType="ldap"
/config/security/userservice/ldap += {
"jndiProviderUrl" : "ldap://bluepages.ibm.com:389/",
"jndiSecurityPrincipal" : "<your_userid>,
"jndiSecurityCredentials" : “<your_passowrd>",
"ldapUserIdSearchFilterPattern" : "(&(|(mail={0}))(objectclass=ibmPerson))",
"ldapUserIdAttributeType" : "mail",
"ldapUserIdBaseDn" : "ou=bluepages,o=ibm.com",
"ldapGroupBaseDn" : "o=ibm.com",
"ldapGroupSearchFilterPattern" : "(&(uniqueMember={0}) (objectclass=groupOfUniqueNames))"
}

#-- Bluepages LDAP Auth
#-- Conditions define what path(s) are to be protected (req login)
#-- Groups list the groups that are allowed access to this url path
#Ahmed Fadel security is controlled for all paths which starts with /editor or /test or /resources
#Members of the blue group SERVICE_WORKS_EDITOR are allowed to access those resources
#Any file put directly under /public will not be available for everyone

@include "security/authorization.config" {
"conditions": "(/request/path =~ /editor(/.*)?) || (/request/path =~ /resources(/.*)?) || (/request/path =~ /test(/.*)?)",
"groups" : ["GROUP1"]
}

#Form based authentication is enabled for /editor or /test paths only
@include "security/formAuthentication.config" {
"conditions": "(/request/path =~ /editor(/.*)?) || (/request/path =~ /test(/.*)?)"
}

#Basic authentication is enabled for /resources only. This is used to protect service in case someone tried
#to connect directly to REST service without using the editor
@include "security/basicAuthentication.config" {
"conditions": "/request/path =~ /resources(/.*)?"
}

#-- Login form
@include "security/formLoginURL.config"{
"formLoginPage" : "/login.gt"
}

Sample content for login.gt

<html>
<head>
<title>Login Test</title>
<style>
@import "<%=getRelativeUri('/theme.css')%>";
</style>
</head>
<body>
<% if( zget("/request/headers/in/Referer") =~ zget("/request/uri") ){ %>
<div class='error'>
<h2>Invalid user ID or password</h2>
Please verify your ID and password and try again.
</div>
<% } %>
<p>Login using your normal user ID and password:</p>
<form method="POST" action="" name="loginForm">
<!-- optional hidden field to force the target redirect
after login -->
<!--
<input type="hidden" name="postLoginTargetURI" value="/my">
-->
<label for="zeroUserName">User ID:</label><br/>
<input type="text" name="zeroUserName" size='20' /><br/>
<label for="zeroPassword">Password:</label><br/>
<input type="password" name="zeroPassword" size='12' /><br/><br/>
<input type="submit" value="Submit" />
</form>
</body>
</html>

Escape double quote when storing a string in database

Problem:
When you read a variable which contains double quotes e.g. <a href="abc.pdf">test</a>
and you try to save it in a database column of type varchar, you will get an error similar to the one below:

Error: [pdq][10107][2.7.116] An error prevented the update operation from completing successfully.; Caused by: com.ibm.db2.jcc.am.io: [jcc][1091][10404][3.57.82] Invalid data conversion: Parameter instance <a href="abc.pdf">test</a> is invalid for the requested conversion. ERRORCODE=-4461, SQLSTATE=42815 ]

Resolution:
You need to escape the double quotes as shown below before trying to store the variable in database to avoid the error.

def link = zget("/request/params/link");
if(link !=null){
link=link.replaceAll('"','\\"');
}

Saturday, 28 May 2011

sMash: Deployment instructions to update existing application deployed on server

If you have a WebSphere sMash application deployed on a server e.g. production or staging, and you need to replace the deployed version with a newer one e.g. after solving some defects, then you need to follow those steps:

  1. Open Rational Application Developer/Eclipse 
  2. Open project folder & then open ivy.xml
  3. Increment the revision number e.g. from 1.0.0 to 1.0.1 (for more major changes, you can change to 1.1.0 and so on)
  4. Save
  5. Open command line window and set zero environment properly
  6. Go to the project directory under Eclipse workspace
  7. Invoke the command "zero package" & a zip file will be generated under the export directory
  8. FTP the file to the target server e.g. to /home/fadela/export
  9. Login to target server
  10. Set the zero environment on staging server for your own account (check how below)
  11. invoke the command "zero publish", for example:
    • zero publish -f=/home/fadel/export/<project_module>-1.0.1.zip
  12. Finally run the command "zero update". This forces the sMash to reference the new version you just deployed instead of the existing one.
  13. Issue command zero stop followed by zero start to recycle the application for new changes to take effect.

Update revision number