Sunday, July 3, 2011

My two cents on Scrum

Scrum is an agile methodology which helps companies iterate through a product/project development to successful completion. Back in the days we all know that we were limited to the water fall model which was later extended to be known as the V-Model. Gantt charts and the like were included with these methodologies.

The practices defined within these traditional methods were concise and precise. We start off with gathering of requirements from the client, document it which usually goes as the Software Requirement Document (Known as SRS), which is later signed off by the client after user acceptance testing is done. Afterwards we have the design phase where all our class diagrams come into play as well as use case diagrams, ER diagrams and the like. Then it’s time to implement this well designed product with technologies that fit the choice. Testing and product release follows the implementation phase.

Though there were no intrinsic problems with this methodology, the problem lied in the fact that we humans are involved in every phase. In a perfect world (such as what skynet once planned) this methodology would work seamlessly and we would have picture perfect product releases. But alas, with us humans nothing is guaranteed. We all know how hard it is for us to make a decision on something at certain times. In terms of a company, when they approach a software company to build a piece of software for them, they might not know what they exactly want early on. As time goes on as they see the product they might and most usually do want something radically different to what they wanted earlier.

The problem posed by the traditional methodologies as everyone knows is that it’s very hard to go back from once phase to a previous phase as the cost and time involved in the process is of great monetary value to the company. We can’t coerce the customer to agree on our basis as client’s request are always dynamic and we as a company should have the processes in place to adapt to such changes.
This is where Scrum shines as I see. I’m quite new to the scrum process. In scrum what is usually done is that we start off with a base Product backlog which has feature tasks that the client requested. There are a few entities that are involved within the process of Scrum such as;

The Product Owner(PO) – The product owner is the one who gathers requirements from the client and creates and maintains the product backlog. Also he/she is responsible in assigning a priority to each task defined within the product backlog.
The Scrum Master(SM) – The scrum master does not involve with anything specific to the project, but acts as a supervisor helping the team and the product owner to adhere to scrum practices whenever he/she sees that they are deviating from proper processes.
The Team  – is that development team involved in the development as well as the testing of the project features.

Ok now that we have met the people involved in the Scrum, let’s see why it is so awesome. One of the eye catching points of Scrum is the fact that the team decides on the time lines rather than your project manager deciding it for you. I have been any many meetings where the developers stand there like deaf or dumb people and watch as their Project manger do the estimation giving unrealistic deadlines. In scrum the practice is that the team decides along with the PO which tasks they can take on. Usually in Scrum features are taken to fit into one sprint which is more less a month of time. This is the most efficient time as proposed by Scrum. So the team decides what they can achieve within the month and take on the tasks that fit the timeline.

The key feature to note is that they do not make the estimation based on the high level task defined within the Product backlog. They break it down to meaningful development tasks and estimate based on that. If a feature has work for more than one sprint, some features are pushed to the next release. This is a very efficient way of estimating as I see because you do not leave anything out in your estimate and are able to give credible estimates to your Product owner.

Also Scrum is dynamic in which if a customer wants a new feature added on whilst a spring is going on, though they can’t achieve it within this sprint they can always push it to the next sprint  and the wait time of the customer is minimized to just a month.

Also usually whilst a Sprint is coming to an end, the team gets together with the PO to estimate on the upcoming spring to. In scrum momentum is key, which allows teams and companies achieve its development goals in a timely manner without pressurizing the developers with unrealistic deadlines. So the team is aware of upcoming work load as well whilst within the current spring. This is a great feature of scrum the scrum practice. Planning ahead, but not too far ahead.

And also if for any reason they are unable to deliver a feature within the current Sprint they can always push it to the next Sprint and finish off.

As a couple or so Sprints go on, the team gets the feeling of the kind of work it can achieve within a particular sprint which allows them to make timely, accurate estimates on future tasks.
All in all, I believe these agile practices is the way ahead for all companies big or small as the benefits it brings along supersedes the switching costs involved with moving away from your current practices.
What are your thoughts on Scrum? Pls do leave a comment with your own thoughts on the same.

God Bless 

Font resizing and IE

Font Size mishaps

When it comes to declaring font size we know we have a variety of methods in order to achieve it. Few of them are as below;

1.    px – the size in number of pixels
2.    em – the size relative to the parent element
3.    in – the size in inches
4.    cm – the size in centi-meters
And a few others are there as well. On top of these there are a few keywords available to define text size such as;
1.    xx-small
2.    x-small
3.    small
4.    medium
5.    large
6.    x-large
7.    xx-large
In general I have seen many people using px(pixel) definition to markup your text size. Of course this works well out of the box but one caveat it brings along with it is a small scalability issue that I am going to touch upon this article.
To start off lets vamp up a test html plus a css file to go along with it.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
   
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" id="vista"> 
 
 <head>
 <title>Test my font size</title>
 <link rel="stylesheet" href="style.css" type="text/css" media="screen" />
</head>

<body>
<h1>My Awesome Article</h1>
	<p>
		Though i started the heading as my awesome article i do not actually know
		what to write about that simply could be awesome.
	</p>
</body>

</html>

body{
font-size:15px;
font-family:"Times New Roman",Georgia,Serif;
}
h1{
font-size:20px;
}
p{
font-size:18px;
}

Nothing special as you can see. It’s just a simple definition of a header and a paragraph element. And within our style sheet we have defined a font-size attribute specifying it to by 15px which will be the default size on which elements will base on. Now let’s run this and see how this looks like;






Ok looks fine to me. How about you guys? So what is the problem you might ask? You probably must be thinking I’m nuts to assume something was going to be wrong.  Though there is nothing wrong implicitly in this markup it fails in one area where if for an instance a person with bad eye sight wants to increase the default text size through the browser by going to View->Text size in Internet explorer and selecting a text size, the text in our site won’t budge. It will always stay on the default 15px size we defined.

Not what you want for your site right? A website should be accessible, readable no matter if you have a disability or not. So in this instance how are we going to fix this problem with our sites text? We want it to scale according to the user preference.

In order to do that we first need to specify the size in any one of the keywords I mentioned earlier. Afterwards any subsequent element you want to increase/decrease the size, we use percentages to define the size based on the base keyword size we defined. Ok enough words; let’s put this into action shall we?


body{
font-size:small;
font-family:"Times New Roman",Georgia,Serif;
}
h1{
font-size:180%;
}
p{
font-size:90%;
}


So now if we try to resize again we will see this time our text within the page will scale according to the user’s need. Following is a screen shot of the same;


One thing before i forget, for this to work in IE 5 you need to apply something called the Box model hack which was developed by Tantek Celik. . You need this hack because in IE 5 it displays the text one step larger than the font size keyword we define.This is the short version of the same hack defined in the site;

* html body{
font-size:x-small;/* for IE5*/
f\ont-size:small;/* for all other IE versions*/
}

That’s it guys. Most of you might already know this. So for you guys this is just a revision, for all others I hope this helped you in anyway. Comments are as usual always welcome.

God Bless


Wednesday, June 22, 2011

Local time of any country based on GMT with Java

In a recent change request for one application i was working on, it was requested to update the time stamp a certain task was done based on the location of the user. We have a separate Country table stored which has the GMT action and the GMT off set defined in minutes.

I was searching for a way to get the local time of a certain country using the Calendar object. There were many sites that gave various information which led to me finding a work around by testing with various parameters. This is what i came up with in the end.


Following i have encapsulated the final outcome into a method so it would be easier to understand and use if anyone ever needs it;

 public static final String GMT_STR = "GMT";
	public static final String COLON_STR = ":";
	public static final String ZERO = "0";
	
	/**
	 * This method will take as parameters the GMT off set in minutes
	 * as well as the GMT actions i.e + or - and based on that will
	 * output the calendar object representing that specific time in that
	 * location. The GMT is defined in minutes so that the calculation is
	 * simplified.
	 * @param gmtOffSetMins 
	 * @param gmtAction
	 * @return
	 */
	public static Calendar getLocalTime(int gmtOffSetMins,
			String gmtAction) {

		// This will get the quotient part of the division
		int gmtHours = (gmtOffSetMins / 60);
		// This will get the remainder of the division which will give us the
		// minutes portion
		Integer gmtMins = Integer.valueOf((gmtOffSetMins % 60));
		if (gmtMins < 10) {
			gmtMins = Integer.valueOf("0"+gmtMins);
		}
		
		/**
		 * This will produce a String in the format of GMT+5:30
		 */
		String gmtString = null;
		if (gmtMins == 0) {
			gmtString = GMT_STR + gmtAction + gmtHours + COLON_STR + gmtMins+ ZERO;
		} else {
			gmtString = GMT_STR + gmtAction + gmtHours + COLON_STR + gmtMins;
		}

		/**
		 * This calendar object will give you the local time of the specific country
		 * based on the gmt offset hours and the action passed. 
		 */
		return Calendar.getInstance(TimeZone.getTimeZone(TimeZone.getTimeZone(
				gmtString.trim()).getID()));

	}

Thats all you need. The returned calendar will have the local time of that specific country depending on the GMT minutes and action you passed. Note that i have given the GMT in minutes to ease the calculation. Normally you will get the GMT in hours so you will need to convert that to minutes.

Ofcourse when daylight savings come into play you will need to change this accordingly. For our application this was not needed so we didnt do that change. To handle daylight savings we will have to keep the day light saving changes somewhere and deduct or add appropriately to the base GMT.

If you guys know anyway of doing this in a much simpler way or you have any suggestions for improvements pls do leave by a comment which is as always much appreciated.

Cheers Guys!!!!

Thursday, May 5, 2011

Struts 2 and Annotations

Googling around i saw there wasnt any concise article explaining how to integrate Struts 2 with annotations. I will keep this as simple as possible because,well the struts developers have done some awesome work to make it as simple as they can. I will create a sample maven project showing you how to integrate struts 2.

Ok first off lets go ahead and create our maven project.Im going with a maven project because its just easier to create a war and dependencies required for struts as well. So below is my project root pom;

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">



 <modelVersion>4.0.0</modelVersion>

 <groupId>com.myexamples</groupId>

 <artifactId>my-struts-sample</artifactId>

 <packaging>war</packaging>

 <version>1.0-SNAPSHOT</version>

 <name>My Struts Example</name>

 <dependencies>



  





  <dependency>

   <groupId>javax</groupId>

   <artifactId>javaee-api</artifactId>

   <version>6.0</version>

   <scope>provided</scope>

  </dependency>





  



  <dependency>

   <groupId>commons-collections</groupId>

   <artifactId>commons-collections</artifactId>

   <version>3.2.1</version>

  </dependency>



  <dependency>

   <groupId>commons-logging</groupId>

   <artifactId>commons-logging</artifactId>

   <version>1.1.1</version>

  </dependency>



  <dependency>

   <groupId>commons-configuration</groupId>

   <artifactId>commons-configuration</artifactId>

   <version>1.6</version>

  </dependency>



  <dependency>

   <groupId>commons-lang</groupId>

   <artifactId>commons-lang</artifactId>

   <version>2.5</version>

  </dependency>









  <dependency>

   <groupId>org.slf4j</groupId>

   <artifactId>slf4j-log4j12</artifactId>

   <version>1.5.2</version>

   <scope>provided</scope>

  </dependency>

  <dependency>

   <groupId>log4j</groupId>

   <artifactId>log4j</artifactId>

   <version>1.2.16</version>

   <scope>provided</scope>

  </dependency>



  

  <dependency>

   <groupId>junit</groupId>

   <artifactId>junit</artifactId>

   <version>4.8.1</version>

   <scope>test</scope>

  </dependency>

  







  <dependency>

   <groupId>com.sun</groupId>

   <artifactId>tools</artifactId>

   <version>1.4.2</version>

   <scope>system</scope>

   <systemPath>${java.home}/../lib/tools.jar

   </systemPath>

  </dependency>



  <dependency>

   <groupId>org.apache.struts</groupId>

   <artifactId>struts2-core</artifactId>

   <version>2.0.6</version>

  </dependency>





  



  

  <!-- standard.jar -->

  <dependency>

   <groupId>taglibs</groupId>

   <artifactId>standard</artifactId>

   <version>1.1.2</version>

  </dependency>



  <!-- JSTL -->

  <dependency>

   <groupId>javax.servlet</groupId>

   <artifactId>jstl</artifactId>

   <version>1.1.2</version>

  </dependency>

  

 



 </dependencies>



 <build>

  <plugins>

   <plugin>

    <groupId>org.apache.maven.plugins</groupId>

    <artifactId>maven-war-plugin</artifactId>

    <version>2.0</version>

    <configuration>



     <archive>

      <manifest>

       <addClasspath>true</addClasspath>

       <classpathPrefix>lib/</classpathPrefix>

      </manifest>

     </archive>

     <webResources>

      <resource>

       <!-- this is relative to the pom.xml directory -->

       <directory>${project.basedir}/resources

       </directory>



      </resource>

     </webResources>

     <outputDirectory>${env.JBOSS_HOME}/server/default/deploy</outputDirectory>

     <warName>my-struts-sample</warName>

    </configuration>

   </plugin>

  </plugins>

 </build>



</project>


The structure of the project will be as follows;

    my-struts-sample
            |
            |
            --------->pom.xml
            |
            |
            ----->resources
            |        |
            |        |
            |        ----->js
            |
            ----->src
                   |
                   |
                   ------->main
                             |
                             |
                             ----->webapp
                                     |
                                     |
                                     ------->index.html
                                     |
                                     |
                                     ------->WEB-INF
                                                |
                                                |
                                                ------>web.xml
                                                |
                                                |
                                                ------>jsp
                                                        |
                                                        |
                                                        ------>test
                                                                |
                                                                |
                                                                ---->test.html

That is the normal structure of any maven project. This will create the war file and deploy it within your jboss as i have mentioned to get it from JBOSS_HOME in my pom.xml. You can change it as you need depending on your server.

Afterwards lets create our first action class given below;

package com.test..myexample;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.config.Result;
import org.apache.struts2.config.Results;
import org.apache.struts2.interceptor.ServletRequestAware;

@Results({
    @Result(name="success", value="/public/showTest")
})

public class ShowTestAction implements ServletRequestAware{
 
 private HttpServletRequest request;
 
 public void setServletRequest(HttpServletRequest request) {
  this.request = request;
 }
 
 public String  execute(){
  return "success";
 }
}


This is a simple action class. Few things to note here. Always your Action class name should end with the name Action, else it wont get recognized as an action class during package scan phase which i will explain later. For now i am only returning success. You can add more Results as you deem appropriate to handle error situations and others. I have injected the HttpServletRequest instance here as well because almost always you will require this to read your parameters or attributes. Now that you have your action class lets see how we can map out our web.xml and configure struts 2.



<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

 


 <filter>
  <filter-name>struts2</filter-name>
  <filter-class>
   org.apache.struts2.dispatcher.FilterDispatcher
  </filter-class>
  <init-param>
   <param-name>actionPackages</param-name>
   <param-value>
      com.test..myexample
          </param-value>
  </init-param>
 </filter>

 

 <filter-mapping>
  <filter-name>struts2</filter-name>
  <url-pattern>*.action</url-pattern>
 </filter-mapping>

 <servlet>
  <servlet-name>mytest</servlet-name>
  <jsp-file>/WEB-INF/jsp/test/test.html</jsp-file>
 </servlet>

 <servlet-mapping>
  <servlet-name>mytest</servlet-name>
  <url-pattern>/public/showTest</url-pattern>
 </servlet-mapping>

</web-app>

There are a few things to note here. One is that we have defined a filter called struts 2. Within that we have specified an attribute called actionPackages. This is the place where we define the package name in which our action classes reside in. If you have many packages then you can have comma separated package names specified within the param-value attribute.

Next we have specified a filter-mapping attribute. This says that all urls ending with .action should go through the org.apache.struts2.dispatcher.FilterDispatcher which in turn will search in all packages defined to see which action should be called. Hope that is clear to you guys. The rest is just normal servlet mapping which all of you should be familiar with.

Now i will show you the index.html which just does a simple redirect calling our action class which in turn will display our test.html according the success mapping name defined within the action class.


<html>
<head>My Home Page</head>
<body>


<script type="text/javascript">
location.replace('showTest.action');
</script>
</body>
</html>

Here we are saying to redirect to showTest.action. Note that your action name was ShowTestAction. But when you call it you should always make sure the name starts with a simple letter and ends with .action or else it would not be recognized by the struts Filter Dispatcher.

Thats about it guys. I did not give the implementation of the test.html because that can be anything you want. Please feel free to leave a comment if you have any doubts or clarification regarding the tutorial provided. mvn clean install and your good to go with struts 2 with annotations :)

Cheers guys

Thursday, April 28, 2011

Secure your webservices with JBoss

WS-SEC is a vast area in it self and trying to cover the whole topic in one blog post is just not possible. So ill be touching on a glimpse of it by showing you how to achieve ws-sec with Jboss with the least amount of effort.

In simplest terms WS-SEC is more or less the same as what you do when you log into a website by providing your user name and password. Only difference is in this case you provide your credentials to gain access to the web service you are trying to access.

People use WS-SEC in order to protect their web service from being used by unknown third parties. There always might be instances in which you would want to restrict access to certain web services as they process and handle confidential data. For this situation WS-SEC is a must. Adding HTTPS would guarantee transport leve security for your Web service as well. But in this article i will only focus on securing your web service through WS-SEC as there are many articles explaining how to expose it on HTTPS.

Note that i will be creating the web service using the @Webservice annotation(a.k.a code first approach). Following i have given the web service we are going to use for our example;

package com.myservices;
@WebService(serviceName = "MyService", portName = "MyServicePort", targetNamespace = "personlaservices")
@Stateless
@HandlerChain(file = "myconfigs/webservices/security_handler.xml")
public class MySecurityService {

 @WebMethod
 public String sayMyName(){
  return "Iron Man!!!";
 }

}

Note that i have just a simple method with a string output. The important thing to note here is the @HandlerChain attribute. This refers to an XML we define which i will show below which defines the class which will handle the authentication by reading the user name and password which comes in the header part of the soap message enclosed within the ws-sec tag. Note that the xml file path is relative to the classpath. I have placed the folder myconfigs within the conf directory of jboss.

The Configuration XML security_handler.xml is as follows;

<?xml version="1.0" encoding="UTF-8"?>



<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">



 <!-- Note:  The '*" denotes a wildcard. -->



 <handler-chain>

  <handler>

   <handler-name>com.myservice.security.AuthenticateHandler</handler-name>

   <handler-class>com.myservice.security.AuthenticateHandler

   </handler-class>

  </handler>

 </handler-chain>

</handler-chains>


This defines a class called AuthenticationHandler which will retrieve the user name and password contained within the soap message and do the authentication using the JBoss login module with the security realm defined which i will not go into detail as we all know how to handle security within JBoss. but you can use any authentication mechanism you want here.

/**
 * 
 */
package com.myservice.security;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.apache.log4j.Logger;



/**
 * Handler to authenticate the requests send in by the user from information provided through soap-headers.
 */
public class AuthenticateHandler implements SOAPHandler<SOAPMessageContext> {

    /** The Constant logger. */
    private static final Logger logger = Logger.getLogger(AuthenticateHandler.class);

    /** The Constant USERNAME_TOKEN_STRING. */
    private static final String USERNAME_TOKEN_STRING = "UsernameToken";

    /** The Constant USERNAME_STRING. */
    private static final String USERNAME_STRING = "Username";

    /** The Constant ARG_0_STRING. */
    private static final String ARG_0_STRING = "arg0";

    /** The Constant PASSWORD_STRING. */
    private static final String PASSWORD_STRING = "Password";


    private static final String HIGHPHEN = "-";

    /*
     * (non-Javadoc)
     * @see javax.xml.ws.handler.Handler#handleFault(javax.xml.ws.handler.MessageContext)
     */
    public boolean handleFault(SOAPMessageContext context) {
        // throw new UnsupportedOperationException("Not supported yet.");
        logger.debug("handleFault() is called");
        return true;
    }

    /*
     * (non-Javadoc)
     * @see javax.xml.ws.handler.Handler#handleMessage(javax.xml.ws.handler.MessageContext)
     */
    public boolean handleMessage(SOAPMessageContext smc) {

        SOAPMessage message = smc.getMessage();
        Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        boolean authenticated = false;

        try {

            // Let's extract information and try to log XML.
            SOAPPart sp = message.getSOAPPart();
            SOAPEnvelope envelope = sp.getEnvelope();

           
            if (!outboundProperty) {

                SOAPHeader header = envelope.getHeader();

                if (header != null) {
                    authenticated = processSOAPHeader(header);
                }

            }

        } catch (SOAPException se) {
            logger.error("SOAPException occured while processing the message", se);

        }
        return authenticated;
    }

    /**
     * Gets the sOAP message as string.
     * 
     * @param msg the msg
     * @return the sOAP message as string
     */
    private String getSOAPMessageAsString(SOAPMessage msg) {

        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            msg.writeTo(baos);
            return baos.toString();

        } catch (IOException ioe) {
            logger.warn("Could not extract XML from soap message", ioe);
            return null;
        } catch (SOAPException se) {
            logger.warn("Could not extract XML from soap message", se);
            return null;
        }
    }

    /**
     * Process soap header. This method is called by handleRequest method It retrieves the SOAP headers in the message
     * and authenticates the client.
     * 
     * @param sh the soap header
     * @return true, if successful
     */
    private boolean processSOAPHeader(SOAPHeader sh) {
        boolean authenticated = false;

        // look for authentication header element inside the HEADER block
        Iterator childElems = sh.getChildElements();

        SOAPElement child = extractUserNameInfo(childElems);

        if (child != null) {

            // call method to perform authentication
            authenticated = authenticateRequest(child);
        }
        return authenticated;
    }

    /**
     * Extract user name info.
     * 
     * @param childElems the child elems
     * @return the sOAP element
     */
    private SOAPElement extractUserNameInfo(Iterator childElems) {

        logger.debug("extractUserNameInfo called.");

        SOAPElement child = null;
        Name sName;

        // iterate through child elements
        while (childElems.hasNext()) {
            Object elem = childElems.next();

            if (elem instanceof SOAPElement) {

                // Get child element and its name
                child = (SOAPElement) elem;
                sName = child.getElementName();

                // Check whether there is a UserNameToken element
                if (!USERNAME_TOKEN_STRING.equalsIgnoreCase(sName.getLocalName())) {

                    if (child.getChildElements().hasNext()) { // TODO check logic
                        return extractUserNameInfo(child.getChildElements());
                    }
                }
            }
        }

        return child;
    }

    /**
     * Authenticate request. This method retrieves the authentication information for the request header and validates
     * it.
     * 
     * @param element the element
     * @return true, if successful
     */
    private boolean authenticateRequest(SOAPElement element) {

        logger.debug("authenticateRequest called");
        boolean authenticated = false;

        // variable for user name and password
        String userName = null;
        String password = null;
        Name sName;

        // get an iterator on child elements of SOAP element
        Iterator childElems = element.getChildElements();

        SOAPElement child;
        // loop through child elements

        while (childElems.hasNext()) {
            // get next child element
            Object elem = childElems.next();

            if (elem instanceof SOAPElement) {
                child = (SOAPElement) elem;

                // get the name of SOAP element
                sName = child.getElementName();

                // get the value of username element
                if (USERNAME_STRING.equalsIgnoreCase(sName.getLocalName())) {
                    logger.debug("---UserName =" + child.getValue());
                    userName = child.getValue();
                } else if (PASSWORD_STRING.equalsIgnoreCase(sName.getLocalName())) {
                    // get the value of password element
                    password = child.getValue();
                }

                if (userName != null && password != null) {

                   
   /**
       Note that in this instance i have used my custom used class
       called ClientLoginModule whic wraps a JBossLoginModule instance.
         You can use your own authentication mechanism as you have the user name
        and password at this point.
   **/
                        ClientLoginModule.login("WEBSERVICE" + "^" + userName, password);
                        return true;
                  

                    break;
                }

            }
        }

        if (userName == null || password == null) {
            logger.warn("Username or password is empty. userName : [" + userName + "], password : [" + password + "]");
        }

        return authenticated;

    }

    

    /**
     * Extract TCI info.
     * 
     * @param childElems the child elems
     * @return the sOAP element
     */
    private SOAPElement extractTCIInfo(Iterator childElems) {

        logger.debug("extractTCIInfo called.");

        SOAPElement child = null;
        Name sName;

        // iterate through child elements
        while (childElems.hasNext()) {
            Object elem = childElems.next();

            if (elem instanceof SOAPElement) {

                // Get child element and its name
                child = (SOAPElement) elem;
                sName = child.getElementName();

                // Check whether there is a UserNameToken element
                if (!ARG_0_STRING.equalsIgnoreCase(sName.getLocalName())) {

                    if (child.getChildElements().hasNext()) {
                        return extractTCIInfo(child.getChildElements());
                    }
                }
            }
        }

        return child;
    }

    /*
     * (non-Javadoc)
     * @see javax.xml.ws.handler.soap.SOAPHandler#getHeaders()
     */
    public Set<QName> getHeaders() {
        logger.debug("--- In AuthenticateHandler.getHeaders ()");
        // return headers;
        return null;
    }

    /*
     * (non-Javadoc)
     * @see javax.xml.ws.handler.Handler#close(javax.xml.ws.handler.MessageContext)
     */
    public void close(MessageContext context) {
        logger.debug("close() is called");
        // throw new UnsupportedOperationException("Not supported yet.");
    }

}

This class extracts the user name and password as you can see within the method authenticateRequest() and authenticates the user. If authentication fails it will return false from within handleMessage(). Note that i have used a class called ClientLoginModule. This is a class i have written which extends JBoss Login Module. I did not go into much detail with that due to the fact that it is already known to anyone who has dealt with jboss user security handling.

Now that we have these two methods you just need to bundle this up and run jboss which will expose the wsdl of this service. In jboss you can see what current web services are being hosted on your server by going to the URL http://localhost:8080/jbossws/services where 8080 is the port you expose your jboss on.

After you get your wsdl you need to generate the stubs by running any tool such as wsimport which does the wsdl to java transformation for you. Check here for more information.

Assuming you got your stubs generated and constructed a jar containing your code i will show you how to consume this ws-sec enabled webservice through a client.


try {
            URL wsdlLocation = new URL("http://localhost:8080/MyService");

            QName qName = new QName("personlaservices", "MyService");

            Service service = null;
            service = Service.create(wsdlLocation, qName);
            
     /**
  HeaderHandlerResolve will pass this information to a HeaderHandler implementation
  class which will embed the user name and password passed in to the ws-security
  header within the soap header element
     **/
            HeaderHandlerResolver handlerResolver = new HeaderHandlerResolver("myusername","mypassword");
            service.setHandlerResolver(handlerResolver);

            MySecurityService servicePort = service.getPort(MySecurityService.class);

     System.out.println(servicePort.sayMyName());
        } catch (MalformedURLException mue) {
            logger.warn("An error occurred while getting the wsdl location.", mue);
        }

Here i first create an instance of the javax.xml.ws.Service class using the URL, namespace and the service name we provided within our web service implementation we specified earlier. Next the important thing to note here is we define a custom HeaderHandlerResolver which we set to the service. I will show you the implementation of the HeaderhandlerResolver as well as the HeaderHandler which is used within the HeaderHandlerResolver class so that you can understand what happens.

/**
 * 
 */
package com.myservice.client;

import java.util.ArrayList;
import java.util.List;

import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;

/**
 * Taken from www.javadb.com and modified.
 * 
 * @author www.javadb.com
 */
public class HeaderHandlerResolver implements HandlerResolver {

    private String userName;

    private String password;

    public HeaderHandlerResolver() {
        super();

    }

    public HeaderHandlerResolver(String userName,String password) {
        super();
 this.userName = userName;
 this.password = password;
    }

    @SuppressWarnings("unchecked")
    public List<Handler> getHandlerChain(PortInfo portInfo) {
        List<Handler> handlerChain = new ArrayList<Handler>();

        HeaderHandler hh = new HeaderHandler(userName,password);

        handlerChain.add(hh);

        return handlerChain;
    }
}


The Header Handler implementation is the one which embeds the ws-security header to the soap header as you can see from the below code;


/**
 * 
 */
package com.myservice.client;

import java.io.ByteArrayOutputStream;
import java.util.Set;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.apache.log4j.Logger;



/**
 * Taken from www.javadb.com and modified.
 * 
 * @author www.javadb.com
 */
public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {

    /** The Constant logger. */
    private static final Logger logger = Logger.getLogger(HeaderHandler.class);

    /** The Constant WS_SECURITY_SECEXT_URI. */
    private static final String WS_SECURITY_SECEXT_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";

    /** The Constant WS_SECURITY_UTILITY_URI. */
    private static final String WS_SECURITY_UTILITY_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";

    /** The Constant WS_PASSWORD_TYPE_URI. */
    private static final String WS_PASSWORD_TYPE_URI = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";

    /** The Constant WSSE_PREFIX. */
    private static final String WSSE_PREFIX = "wsse";

    /** The Constant SECURITY_LOCAL_NAME. */
    private static final String SECURITY_LOCAL_NAME = "Security";

    /** The Constant USERNAME_TOKEN_LOCAL_NAME. */
    private static final String USERNAME_TOKEN_LOCAL_NAME = "UsernameToken";

    /** The Constant LOCAL_PART_XMLNS_WSU. */
    private static final String LOCAL_PART_XMLNS_WSU = "wsu";

    /** The Constant USERNAME_LOCAL_NAME. */
    private static final String USERNAME_LOCAL_NAME = "Username";

    /** The Constant PASSWORD_LOCAL_NAME. */
    private static final String PASSWORD_LOCAL_NAME = "Password";

    /** The Constant PASSWORD_ATTRIBUTE_TYPE. */
    private static final String PASSWORD_ATTRIBUTE_TYPE = "Type";

    private static final String HIGHPHEN = "-";

    private String userName;

    private String password;

    public HeaderHandler(String userName,String password) {
        this.userName = userName;
 this.password = password;
    }

    /*
     * (non-Javadoc)
     * @see javax.xml.ws.handler.Handler#handleMessage(javax.xml.ws.handler.MessageContext)
     */
    public boolean handleMessage(SOAPMessageContext smc) {

        Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        SOAPMessage message = smc.getMessage();

        try {

            // Let's extract information and try to log XML.
            SOAPPart sp = message.getSOAPPart();
            SOAPEnvelope envelope = sp.getEnvelope();

         

            if (outboundProperty.booleanValue()) {

                SOAPHeader header = envelope.getHeader();

                if (header != null) {
                    header.detachNode();
                }

                header = envelope.addHeader();

                SOAPElement security = header.addChildElement(SECURITY_LOCAL_NAME, WSSE_PREFIX, WS_SECURITY_SECEXT_URI);

                SOAPElement usernameToken = security.addChildElement(USERNAME_TOKEN_LOCAL_NAME, WSSE_PREFIX);

                QName qName = new QName(XMLConstants.NULL_NS_URI, LOCAL_PART_XMLNS_WSU);
                usernameToken.addAttribute(qName, WS_SECURITY_UTILITY_URI);

                SOAPElement username = usernameToken.addChildElement(USERNAME_LOCAL_NAME, WSSE_PREFIX);

                username.addTextNode(userName);

                SOAPElement password = usernameToken.addChildElement(PASSWORD_LOCAL_NAME, WSSE_PREFIX);
                password.setAttribute(PASSWORD_ATTRIBUTE_TYPE, WS_PASSWORD_TYPE_URI);

                password.addTextNode(password);

            }

        } catch (SOAPException se) {
            logger.error("SOAPException occured while processing the message", se);

        }

        return outboundProperty;

    }

    /**
     * Gets the sOAP message as string.
     * 
     * @param msg the msg
     * @return the sOAP message as string
     */
    private String getSOAPMessageAsString(SOAPMessage msg) {

        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            msg.writeTo(baos);
            return baos.toString();

        } catch (Exception e) {
            logger.warn("Could not extract XML from soap message");
            return null;
        }
    }

    /*
     * (non-Javadoc)
     * @see javax.xml.ws.handler.soap.SOAPHandler#getHeaders()
     */
    public Set<QName> getHeaders() {
        // throw new UnsupportedOperationException("Not supported yet.");
        logger.info("getHeaders() is called");
        return null;
    }

    /*
     * (non-Javadoc)
     * @see javax.xml.ws.handler.Handler#handleFault(javax.xml.ws.handler.MessageContext)
     */
    public boolean handleFault(SOAPMessageContext context) {
        // throw new UnsupportedOperationException("Not supported yet.");
        logger.info("handleFault() is called");
        return true;
    }

    /*
     * (non-Javadoc)
     * @see javax.xml.ws.handler.Handler#close(javax.xml.ws.handler.MessageContext)
     */
    public void close(MessageContext context) {
        logger.info("close() is called");
        // throw new UnsupportedOperationException("Not supported yet.");
    }
}


Thats about it guys. Withing the handleMessage() method in the above class you can see we are embedding the user name and password to the ws-security header element which is part of the soap header. So now when you call your web service the message wil go through the HeaderHandlerResolver which will pass it on to the Header Handler which in turn will embed the ws-security header before passing on the soap request.

If you have any questions or if there are any areas of improvement you see please do leave a comment which is as always highly appreciated.


Cheers Guys!!!

Thursday, March 31, 2011

JBoss clustering Quick Reference Guide

So i was involved in clustering two JBoss instances and for some reason i had lost my guide i made for myself last time i did a clustering implementation. This time i thought ill blog it so as to keep it as a reference for myself as well as anyone who might need to quickly do JBoss Clustering as we all know how time critical all IT projects are. I will put this in a step by step approach to make it easier to read and comprehend. Note that this approach assumes you are clustering the all configuration in JBoss.

  • Locate the cluster-service.xml located within the deploy folder. Open it and locate the attribute PartitionName within the first mbean you see in that file and change the value ${jboss.partition.name:DefaultPartition} to ${jboss.partition.name}. As in delete the part DefaultParition. 
  •  Find the mbean code which equals to org.jboss.ha.jndi.HANamingService and org.jboss.ha.hasessionstate.server.HASessionStateService. Within that locate the tag   . Chane the value jboss:service=${jboss.partition.name:DefaultPartition} to jboss:service=${jboss.partition.name}. Also add the following to both the mbeans mentioned above ${jboss.partition.name}.
  • In your application jndi reference make sure to change the port to 1100 because in a clustered environment HA-JNDI(High availability JNDI) is used to look up resource. So localhost:1099 should be localhost:1100. Also you have to give the jndi in a comma separated way indicating all servers being clustered. This is needed in a case where if one server goes down still look ups will not fail as you have specified all servers. Say for example you have two servers named ABC and XYZ. Then if you only specify your jndi url as ABC:1100, this will work but in the event that ABC goes down all your other look ups will also fail. So to avoid that kind of situations make sure to define it as ABC:1100,XYZ:1100. This will make sure to try the other server in the case one fails.
  • In all your EJBs make sure to put the Annotation @Clustered(partition="mypartition"). The name we specify should be specified in your run script which i will give in the end of this article.
  • If you running on Redhat make sure the HA-JNDI port is open by issuing the following commands to open port 1100;


     

iptables -A INPUT -i eth0 -p tcp --sport 1100 -m state --state ESTABLISHED -j ACCEPT

/etc/init.d/iptables restart


service iptables restart

Next i would like to get your attention on a draw back in JNDI failover and how to overcome it. Say for example you have two servers named serverA and serverB, If serverA shuts down then serverB should handle the whole load. This works out of the box from JBoss. But if serverA starts again and serverB goes down then you are screwed because you will be getting an error as java.lang.RuntimeException: Unreachable?: Service unavailable.

To overcome this there is a work around. Open the file standardjboss.xml locate in the all/conf directory. Within that file locate the text clustered-stateless-rmi-invoker. Now within that you will see number of elements. In one of these you will find something called org.jboss.proxy.ejb.SingleRetryInterceptor. You will find two instances of this. You need to change it to org.jboss.proxy.ejb.RetryInterceptor. What this does is it will keep retrying to connect infinitely until the other server comes up. Ofcourse this is not a perfect solution but just a work around. Note that this is with respect to Jboss 4.2.3 that i am talking about. This might have been fixed in later releases which im not aware of.

So the change will look as below;

<invoker-proxy-binding>
      <name>clustered-stateless-rmi-invoker</name>
      <invoker-mbean>jboss:service=invoker,type=jrmpha</invoker-mbean>
      <proxy-factory>org.jboss.proxy.ejb.ProxyFactoryHA</proxy-factory>
      <proxy-factory-config>
        <client-interceptors>
          <home>
            <interceptor>org.jboss.proxy.ejb.HomeInterceptor</interceptor>
            <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
            <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>
            <interceptor>org.jboss.proxy.ejb.RetryInterceptor</interceptor>
            <interceptor call-by-value="false">org.jboss.invocation.InvokerInterceptor</interceptor>
            <interceptor call-by-value="true">org.jboss.invocation.MarshallingInvokerInterceptor</interceptor>
          </home>
          <bean>
            <interceptor>org.jboss.proxy.ejb.StatelessSessionInterceptor</interceptor>
            <interceptor>org.jboss.proxy.SecurityInterceptor</interceptor>
            <interceptor>org.jboss.proxy.TransactionInterceptor</interceptor>
            <interceptor>org.jboss.proxy.ejb.RetryInterceptor</interceptor>
            <interceptor call-by-value="false">org.jboss.invocation.InvokerInterceptor</interceptor>
            <interceptor call-by-value="true">org.jboss.invocation.MarshallingInvokerInterceptor</interceptor>
          </bean>
        </client-interceptors>
      </proxy-factory-config>
    </invoker-proxy-binding> 

Lastly i present to you the jboss_redhat_init.sh file which sets the jboss partition name to be used across the application which is the same name used in the @Clustered annotation.


#!/bin/sh
#
# $Id: jboss_init_redhat.sh 71252 2008-03-25 17:52:00Z dbhole $
#
# JBoss Control Script
#
# To use this script run it as root - it will switch to the specified user
#
# Here is a little (and extremely primitive) startup/shutdown script
# for RedHat systems. It assumes that JBoss lives in /usr/local/jboss,
# it's run by user 'jboss' and JDK binaries are in /usr/local/jdk/bin.
# All this can be changed in the script itself. 
#
# Either modify this script for your requirements or just ensure that
# the following variables are set correctly before calling the script.

#define where jboss is - this is the directory containing directories log, bin, conf etc
JBOSS_HOME=${JBOSS_HOME:-"/opt/xyz/jboss-4.2.3.GA"}

#define the user under which jboss will run, or use 'RUNASIS' to run as the current user
JBOSS_USER=${JBOSS_USER:-"RUNASIS"}

#make sure java is in your path
JAVAPTH=${JAVAPTH:-"/usr/java/jdk1.6.0_16/bin"}

#configuration to use, usually one of 'minimal', 'default', 'all'
JBOSS_CONF=${JBOSS_CONF:-"all"}

#if JBOSS_HOST specified, use -b to bind jboss services to that address
JBOSS_BIND_ADDR=${JBOSS_HOST:+"-b $JBOSS_HOST"}

#define the script to use to start jboss
JBOSSSH=${JBOSSSH:-"$JBOSS_HOME/bin/run.sh -b 172.2.23.2 -c $JBOSS_CONF $JBOSS_BIND_ADDR -Djboss.partition.name=mypartition"}

if [ "$JBOSS_USER" = "RUNASIS" ]; then
  SUBIT=""
else
  SUBIT="su - $JBOSS_USER -c "
fi

if [ -n "$JBOSS_CONSOLE" -a ! -d "$JBOSS_CONSOLE" ]; then
  # ensure the file exists
  touch $JBOSS_CONSOLE
  if [ ! -z "$SUBIT" ]; then
    chown $JBOSS_USER $JBOSS_CONSOLE
  fi 
fi

if [ -n "$JBOSS_CONSOLE" -a ! -f "$JBOSS_CONSOLE" ]; then
  echo "WARNING: location for saving console log invalid: $JBOSS_CONSOLE"
  echo "WARNING: ignoring it and using /dev/null"
  JBOSS_CONSOLE="/dev/null"
fi

#define what will be done with the console log
JBOSS_CONSOLE=${JBOSS_CONSOLE:-"/dev/null"}

JBOSS_CMD_START="cd $JBOSS_HOME/bin; $JBOSSSH"

if [ -z "`echo $PATH | grep $JAVAPTH`" ]; then
  export PATH=$PATH:$JAVAPTH
fi

if [ ! -d "$JBOSS_HOME" ]; then
  echo JBOSS_HOME does not exist as a valid directory : $JBOSS_HOME
  exit 1
fi

echo JBOSS_CMD_START = $JBOSS_CMD_START

function procrunning() {
   procid=0
   JBOSSSCRIPT=$(echo $JBOSSSH | awk '{print $1}' | sed 's/\//\\\//g')
   for procid in `/sbin/pidof -x "$JBOSSSCRIPT"`; do
       ps -fp $procid | grep "${JBOSSSH% *}" > /dev/null && pid=$procid
   done
}


stop() {
    pid=0
    procrunning
    if [ $pid = '0' ]; then
        echo -n -e "\nNo JBossas is currently running\n"
        exit 1
    fi

    RETVAL=1

    # If process is still running

    # First, try to kill it nicely
    for id in `ps --ppid $pid | awk '{print $1}' | grep -v "^PID$"`; do
       if [ -z "$SUBIT" ]; then
           kill -15 $id
       else
           $SUBIT "kill -15 $id"
       fi
    done

    sleep=0
    while [ $sleep -lt 120 -a $RETVAL -eq 1 ]; do
        echo -n -e "\nwaiting for processes to stop";
        sleep 10
        sleep=`expr $sleep + 10`
        pid=0
        procrunning
        if [ $pid == '0' ]; then
            RETVAL=0
        fi
    done

    # Still not dead... kill it

    count=0
    pid=0
    procrunning

    if [ $RETVAL != 0 ] ; then
        echo -e "\nTimeout: Shutdown command was sent, but process is still running with PID $pid"
        exit 1
    fi

    echo
    exit 0
}

case "$1" in
start)
    cd $JBOSS_HOME/bin
    if [ -z "$SUBIT" ]; then
        eval $JBOSS_CMD_START >${JBOSS_CONSOLE} 2>&1 &
    else
        $SUBIT "$JBOSS_CMD_START >${JBOSS_CONSOLE} 2>&1 &" 
    fi
    ;;
stop)
    stop
    ;;
restart)
    $0 stop
    $0 start
    ;;
*)
    echo "usage: $0 (start|stop|restart|help)"
esac


The part to note here is -Djboss.partition.name=mypartition which sets the name of the cluster as an application wide property.

Thats it guys. If you have any issues or improvements please leave a comment which is as always much appreciated.

Wednesday, March 16, 2011

Its time for some code review

I know some of us just hate it when we hear the word code review. The thought of some one else going through our code is somewhat offensive to some people. I myself have come across many. But for me this is a good thing given that my reviewer knows what to look for and have a set of parameters set out as a base for him/her to review on. So in this article i would like to highlight a few mistakes i have come across when doing code reviews. Most of them are common but we tend to often miss out on those. This is not the end of them. So if you guys have come across any thing other than what is highlighted here please do leave a comment as it would be beneficial for me as well as the other readers.




Integer myVal = new Integer(10);

Ofcourse by the look of this code there is nothing intrinsically wrong with it. The thing is in this code snippet you create an instance of a new Integer wrapper class. You can enhance this as follows;

Integer myVal = Integer.valueOf(10);

Using the valueOf method is better performance wise as this method returns the value from the in memory cache rather than creating a new object. Check here for what the java api says in this regard.

String records = "";

        for (int i = 0; i < 10; i++) {
            records+="new record"+i;
        }

Ok the issue here is as some of you already might have guessed is string concatenation. Though this works there is an issue with performance with respect to string concatenation. For those of you who do not know, when you concatenate two strings what really happens internally is a new string buffer is created and the new string is assigned to it and toString() is called on that string buffer object. Now this happens on every loop call. So you can understand the performance impact this will have.

Ofcourse prior to java 1.6 you would have argued about so many objects being created on the heap as a result of this. But with java 1.6 escape analysis, any object created within the scope of a method is created on the stack and not on the heap. And hence that argument is invalid. So a better way to handle this situation is to use StringBuilder as follows;



StringBuilder records = new StringBuilder(100);

        for (int i = 0; i < 10; i++) {
            records.append("new record").append(i);
        }

Note that i have also specified an initial size to the String Builder within the constructor. We do this for efficiency because if you do not define an initial size the default size of 16 characters is given by default. Whenever your buffer exceeds this limit a new StringBuilder object is created and the whole String that was in the old buffer is copied to the new one. To avoid such transactions taking place we give an initial capacity that we deem appropriate.

int i=0;
       .......
       .......
       .......
       .......
       .......
       .......
       .......
       .......
       
       i = 2+4;

This is a common mistake i see many people make. You define a variable at one point and afterwards you do various other method calls and at a latter point in that method you manipulate that variable you defined early on in the method. As a best practice always use the variable as soon as it is defined. This provides much clarity to your code and keeps it clean.

Using the same example i would like to point out another thing. See that the code above defines an integer called "i". This is ok to use within a for loop but if this is in the context of a method then always use meaningful names as this will self describe your code minimizing the code commenting you need to do.

/**
     * Blah blah blah blah blah blah blah
     * Blah blah blah blah blah blah blah
     * Blah blah blah blah blah blah blah
     * Blah blah blah blah blah blah blah
     * Blah blah blah blah blah blah blah
     * Blah blah blah blah blah blah blah
     * Blah blah blah blah blah blah blah
     * Blah blah blah blah blah blah blah
     * 
     */
    public void myTestMethod() {
        
    }


Please stop writing lengthy code comments. In my point of view is this is just an utter waste of time. The fact that you need to write such a lengthy explanation to me disseminates the fact that this method does more than what it should do. Write a short description on what your method does. A simple explanation of business logic is more than enough. Make your code readable which reduces the time you have to comment.


/**
     * Sets the name
     * @param name
     */
    public void setMyName(String name) {
        this.name = name;
    }

Wow what a code comment. The author says it sets the name variable. Wow really? Thank goodness for that comment else i would not have known what was going on in that method :) . Seriously stop making useless code comments. It just clutters your code and does no use for anyone reading it. Dont comment on getter/setter methods as the name it self implies what is happening.

public void doProcess()throws MyServiceException {
        
        try {
            service.doProcess();
        }catch(MyServiceException e) {
            log.error("Error occured");
            throw e;
        }
    }

Ok whats wrong here? Problem here is that this method catches a MyServiceException and logs the error and rethrows the same exception back from the method. Why would you catch an exception if you are going to rethrow the same? It just does not make sense. Proper way to handle such a thing is to let the caller handle the exception and log the error at that end rather than you trying to handle it. Anyway it is recommended now to throw Runtime exceptions rather than checked exceptions if the error you throw is like a DB exception or IO exception as these kind of exceptions does not make sense to the client.


public void doProcess()throws MyServiceException {
        
            log.debug("Started method");
            service.doProcess();
            log.debug("Method processed");


    }

Here the issue lies in the debug log statement. Often times in a production environment your log level will mostly be set to INFO or ERROR. But when your code has debug logs the Logger will try to process this which results in unnecessary executions. You can avoid this by checkin if debug is enabled as shown in the below code snippet;

public void doProcess() throws MyServiceException {

        if (log.isDebugEnabled()) {
            log.debug("Started method");
        }
        service.doProcess();
        if (log.isDebugEnabled()) {
            log.debug("Method processed");
        }

    }



if(server.equals("TEST")) {
            //do something
        }else if(server.equals("TEST123")) {
            //do something
        }else if(server.equals("TEST1234")) {
            //do something
        }else if(server.equals("TEST12345")) {
            //do something
        }else if(server.equals("TEST123456")) {
            //do something
        }

In an instance where you are tangled in multiple if/else statement it is always much cleaner to use switch statements and use enums to hold the constants.With JDK 1.7 you are allowed to use Strings in a switch statement. So your code above will look like this with use of enums and switch statement;

switch (server) {
        case TEST:
            // do something
            break;

        case TEST123:
            // do something
            break;
        case TEST1234:
            // do something
            break;
        case TEST12345:
            // do something
            break;
        case TEST123456:
            // do something
            break;
        }

Those are few of the things that came to my mind at the time of writing this post. Ofcourse there are many more which i will follow in subsequent posts. Pls do leave a comment which will be an additions to this post that you deem appropriate for a code review session.


Cheers Guys