Home | About Us | Stelligent  

TestEarly Weblog

Tutorial

Developer Testing and Build Management and Tutorial and Agile and /Duvall23 Sep 2008 07:02 am

gant-imageYes, this is exactly what I am frequently asked by my clients and many developers. It isn’t easy to answer this question. There are several projects using Ant. Should you run away from Ant just because there is a new cool tool out there called Gant? Should you switch to Gant just because you dislike XML? Not at all. Let’s take a closer look and see what might make you switch to Gant.

When to choose Gant?

1. Complicated Build Files. If your ant build files are becoming too complicated, and hard to manage, it’s time to see if using Gant can help. Let me explain what I mean by complicated build files. If you have too much of conditional logic within your build files, say something similar on the lines shown below in Listing 1:

Code Listing 1:


    <if>
      <isset property="sqlserver"/>
      <then>
        <do something here/>
      </then>
    </if>
    <if>
      <isset property="oracle"/>
      <then>
        <do something else here/>
      </then>
    </if>
    <if>
      <isset property="derby"/>
      <then>
       <do something for derby here/>
      </then>
    </if>
    <if>
      <isset property="db2"/>
      <then>
        <do something for db2 here/>
      </then>
    </if>

Or even something like this where you might be supporting deployment to different application servers based on some property in your build.properties or by the user as shown in listing 2.

Code Listing 2:

    <if>
      <isset property="server.jboss4"/>
      <then>
        <deploy to JBoss 4/>
      </then>
      <elseif>
        <isset property="server.weblogic10"/>
        <then>
	<deploy to web logic/>
        </then>
      </elseif>
      <elseif>
        <isset property="server.glassfish"/>
        <then>
          <deploy to GlassFish/>
        </then>
      </elseif>
      <elseif>
        <isset property="server.someother version"/>
        <then>
          <deploy to this some other version/>
        </then>
      </elseif>
    </if>

Things get out of hand when you have conditional logic as shown above in your build scripts. The listings I have are just the skeleton, imagine what happens when we start adding the actual deployment logic for all these application servers. It doesn’t matter how you refactor this, it is still going to be very complicated. Trust me, I have written build scripts which were several thousand lines, and refactoring them was not a trivial task.

2. Custom Ant Tasks. I myself am guilty of writing many of these. There are many situations which arise in projects where we create custom ant tasks. It is simple once you know how to write one, and than for every complicated task you need to perform, you involuntarily will start writing custom ant tasks.

Anyone writing a custom ant task will:
a. Create a new class that extends Ant’s org.apache.tools.ant.Task class.
b. For each attribute, write a setter method.
c. Write an execute()method that does what you want this task to do.

There isn’t anything wrong in doing the above, but imagine each time you want to make a small change you will have to make changes within your Java source code, compile, test, re-package.

3. Scripting. You can extend Ant further by not writing custom ant tasks, but by using small snippets of code written in an interpreted language like JRuby, BeanShell, or Groovy. These code snippets can be placed within your build files or in separate text files. If you are using Groovy’s Ant task, your build file might look something like this:

 <groovy classpathref="build.classpath">
  import some.package
  import another.package
  def fullpath = "${.basedir}/${defaulttargetdir}"
   def somefile = new SomeFile(projectName:"${pname}",
     buildLabel:"${label}", buildTime:"${new Date()}")
   def xml = "${fullpath}/dashboard.xml"
   new File(path).write(somefile.generateReport())
   ant.xslt(in:path,
    out:"${properties.defaulttargetdir}/some.html",
    style:"${properties.defaulttargetdir}/lib/report-style.xsl")
 </groovy>

Imagine having several lines of XML in your build files which have many of these small snippets of scripts. I myself don’t like mixing and matching build files with code snippets. If you have a team where everyone is in the same page, everything works fine. What if a team member has no clue about any of the Scripting languages? He/She will have no clue how to make minor changes when things go badly. If you have all the above or even one of the above three cases, you seriously need to consider using Gant. To quote Aristotle:

For the things we have to learn before we can do them, we learn by doing them.

So, lets see how easy it is to learn Gant and see how things can improve.

This part covers some very basics of Gant. The next part, will dive deeper into Gant by using it with a sample project to build our application, and we will also see how to use it with our CI Server.

What’s Gant?

Gant is a build tool that uses both Groovy and Ant. With Gant, you describe your build process using Groovy scripts. Stated simply, Gant allows you to specify the build logic using Groovy instead of XML. The next thing you may ask is ” Is Gant a competitor to Ant?”. Let me quote from the Gant web site to make things more clear here :

Whilst it might be seen as a competitor to Ant, Gant uses Ant tasks for many of the actions, so Gant is really an alternative way of doing builds using Ant, but using a programming language rather than XML to specify the build rules.

Download and Install Gant.

In order for Gant to work, you should have Groovy installed. You can download and follow the installation instructions for Groovy here.
As I said earlier also, in order to use Gant, you should have knowledge of Groovy as well. If you have never written Groovy code before, there are many interesting books on Groovy like:

a. Groovy in Action

b. Groovy Recipes

c. Groovy Refcardz

You can also read the getting started guide on the Groovy web site, which should give you a good starting point.

Download the latest version of Gant from here. Gant is currently at version 1.4.0. Unzip it to a folder. If you already have your GROOVY_HOME set, that’s all you need to use Gant.

Getting Started.

Open a console, and type gant. You should see a message as shown below:

meera-subbaraos-macbook-9:~ meerasubbarao$ gant
Cannot open file build.gant
meera-subbaraos-macbook-9:~ meerasubbarao$

You are all set at this point to use Gant in your projects.

Help Information: Open a console, and type gant -h. This will provide you with all the necessary help information you need as shown below:

meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$ gant -h
usage: gant [option]* [target]*
-c,–usecache Whether to cache the generated class and

perform modified checks on the file before re-compilation.
-n,–dry-run Do not actually action any tasks.
-C,–cachedir The directory where to cache generated
classes to.
-D = Define to have value .
Creates a variable named for use in the scripts and a property
named for the Ant tasks.
-L,–lib
Add a directory to search for jars and
classes.
-P,–classpath
Specify a path to search for jars and
classes.
-T,–targets Print out a list of the possible targets.
-V,–version Print the version number and exit.
-d,–debug Print debug levels of information.
-f,–file Use the named build file instead of the
default, build.gant.
-h,–help Print out this message.
-l,–gantlib
A directory that contains classes to be used
as extra Gant modules,
-p,–projecthelp Print out a list of the possible targets.
-q,–quiet Do not print out much when executing.
-s,–silent Print out nothing when executing.
-v,–verbose Print lots of extra information.

Create a new file called build.gant at the root of your project. gant-project

Did a similarity between Ant and Gant strike you here? Ant build files are usually called build.xml, and they are created as a common practice within the root of your project folder as well.

If you have written or even modified Ant build files, you will know that it contains one project element, which in turn contains a name,the default target and the base directory.

Code Listing 4:

<project name="GantSamples" basedir="." default="compile">

So for example, sayHello target in Ant would look something like this:

<target name="sayHello" description="Saying Hello">
	<echo message="Hello from Stelligent"/>
</target>

Lets create the sayHello target, and also see how to set it as the default target in Gant as well.

A Gant target has a name and a description:

Code Listing 5:
target ( target-name : target-description ) {
groovy code sequence
}

The above sayHello target in Gant would translate as shown below:
target(sayHello:"Saying hello"){
Ant.echo(message:"Hello from Stelligent")
}

Now, open a command window and type gant at the root of the project where the build.gant file exists. You should be able to see a output like:

meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$ gant
Target default does not exist.

Gant is complaining that we haven’t set a Default target. Lets see how to do the same:

Default target: Within Ant, you define the default target from within the project element as seen in Listing 4. The default target is the target called if no target is specified from the command line. There however is no project tag within Gant. There are two ways of specifying the default target as shown below

1. You simply create a target whose name is default.
target ( 'default' , 'The default target.' ) { aTarget ( )
2. or even simply:
setDefaultTarget ( aTarget )

In order to get our sayHello target working, we need to add one of the above scirpts to our build.gant file.

Code Listing 6:
setDefaultTarget(sayHello)
or
target ("default": "The default target." ) {
sayHello ( )
}

Complete listing of build.gant:
target(sayHello:"Saying hello"){
Ant.echo(message:"Hello from Stelligent")
}
/*
target ("default": "The default target." ) {
sayHello ( )
}
*/
setDefaultTarget(sayHello)

And you should be able to see:

meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$ gant
[echo] Hello from Stelligent
meera-subbaraos-macbook-9:CodeMetricsProject meerasubbarao$

That was easy! If you have build files and it is becoming unmanageable by your team, there is a tool out there which can convert your Ant scripts to Gant scripts as well. I haven’t used it, but you can try it here.

In this part of the series, we learned when to move over from Ant to Gant, downloaded and installed Gant, and finally wrote a simple gant build file. In the next part of this series, we will see Gant in Action within a simple Java project.

And as always, keep us posted here if you are encountering any problems getting started with Gant. Stay tuned.

Developer Testing and Continuous Integration and Tutorial and Agile and /Duvall10 Sep 2008 09:43 am

In the last two articles, “UML Diagrams within Javadocs” and “Visual Documentation of Ant Dependencies in 3 Simple Steps” we saw how easy and valuable it was to automate technical documentation. By using open source tools, we were easily able to provide good technical documentation within a few minutes, and at no cost at all. We were also able to keep this up-to date by adding additional tasks to our Ant build files, and run them from our CI Server(Hudson in our case) on commit and nightly builds, and also publish the results.

In this article, I will be showing you how to use yet another tool called Dxoygen for generating technical documentation based on your source code. We all have used Javadoc and have been using it for a long time, right? So, you may ask what’s the need to have another tool which produces the same HTML documentation? Doxygen has a slight edge over Javadoc and here are a few reasons why you should consider using the same:

1. With Javadoc you have to remember all the HTML tags, you need to embed within your code comments. However, with Doxygen code comments are much more concise and polished, without the need for any HTML.

2. Doxygen can also generate a variety of diagrams, we will take a look at some of them later.

3. Doxygen also provides a structured view on the source code. As I mentioned in 2 above in the form of various diagrams, cross-referenced and syntax highlighted code.

4. You get all the above benefits even if the code does not have any comments at all.

5. Last but not the least, Doxygen is a documentation system not for just Java but also for various other languages like C++, C, Java, Objective-C, Python, IDL (Corba and Microsoft flavors), Fortran, VHDL, PHP, C#.

So, without wasting further time, lets see what we need to get started with Doxygen.

Step 1. Download, Install Doxygen

Download the binary distribution for Doxygen for the operating system you are using. I downloaded the binary distribution for Mac OS X called Doxygen-1.5.6.dmg. Installation is very simple, just drag the doxygen icon from this folder to the Applications folder, or wherever you want to keep it; as shown below. I dropped it within my Applications folder. Just be sure to remember where you dragged it. To uninstall, just delete the file. It is completely self-contained.
doxygen-setup

Step 2: Configure Doxygen.
To generate documentation using Doxygen, you will need a configuration file called the Doxyfile. You can generate this file in two ways; either by using the Doxygen wizard or by using the command line option. Lets see how to use both these options to generate the configuration file:

a. Command line.
Open a command window and type the following as shown below:
doxygen-console

You should be able to locate the configuration file created within your default user folder. The file looks like this:

# Doxyfile 1.5.6

# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project
#
# All text after a hash (#) is considered a comment and will be ignored
# The format is:
# TAG = value [value, …]
# For lists items can also be appended using:
# TAG += value [value, …]
# Values that contain spaces should be placed between quotes (” “)

#—————————————————————————
# Project related configuration options
#—————————————————————————

# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all
# text before the first occurrence of this tag. Doxygen uses libiconv (or the
# iconv built into libc) for the transcoding. See
# http://www.gnu.org/software/libiconv for the list of possible encodings.

DOXYFILE_ENCODING = UTF-8

# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
# by quotes) that should identify the project.

PROJECT_NAME =

# The PROJECT_NUMBER tag can be used to enter a project or revision number.
# This could be handy for archiving the generated documentation or
# if some version control system is used.

PROJECT_NUMBER =

b. Wizard Option.
Launch the Doxygen application, and you should be able to create the configuration file using the wizard approach as shown below.
doxygen-wizard
The user interface is quite intuitive so I am going to skip explaining this in detail.
The wizard approach was the one I used to get the initial settings for the configuration file, which you can always modify later.

A few options in my Doxygen configuration file are as follows:

# Doxyfile 1.5.6

#—————————————————————————
# Project related configuration options
#—————————————————————————
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = PetStore
PROJECT_NUMBER = 1.0
#—————————————————————————
# Build related configuration options
#—————————————————————————
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
#—————————————————————————
# configuration options related to the HTML output
#—————————————————————————
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
GENERATE_TREEVIEW = YES

Step 3. Doxygen and Ant.

In order to use Doxygen, we need an Ant task. There is already an Ant task written for Doxygen which you can download from here.
As always, since using Mac, when I downloaded the binaries and tried to use them, I got the ever famous error message :

java.lang.UnsupportedClassVersionError: Bad version number in .class file

So, had to do download the source, compile, and jar it up. Copy this library to your projects folder. So, lets start making changes to our build file.

3.a: Lets define the Doxygen task:

<taskdef name="doxygen" classname="org.doxygen.tools.DoxygenTask" classpath="lib/ant_doxygen.jar" />

3.b: To generate HTML documentation:

<target name="generate-doxygen-docs">
<taskdef name="doxygen" classname="org.doxygen.tools.DoxygenTask"
classpath="lib/ant_doxygen.jar" />
<doxygen configFilename="reports/Doxyfile">
<property name="INPUT" value="${srcdir}" />
<property name="RECURSIVE" value="yes" />
</doxygen>
</target>

3.c: Lets combine them in a target and run the same:

[doxygen] Exec: /Applications/Doxygen.app reports/Doxyfile

BUILD FAILED
/CodeMetricsProject/build.xml:91: Doxygen not found on the PATH.

Total time: 7 seconds

3.d: So, to launch Doxygen not in the path, we make changes to the doxygen task as shown below:

<doxygen doxygenPath="/Applications/Doxygen.app/Contents/Resources/doxygen" configFilename="reports/Doxyfile">

Lets run the target again and see if it fixed things. Yes indeed.

generate-doxygen-docs:
[doxygen] Exec: /Applications/Doxygen.app/Contents/Resources/doxygen reports/Doxyfile

BUILD SUCCESSFUL
Total time: 8 seconds

4. Integrate with Hudson.

4.a Hudson Job and Ant Target.
Once you have an Ant target working, calling this from your CI server is trivial. Within Hudson, select your Job, click on configure and add this new target to be called when running the build.
hudson-ant

4.b Publish the Reports.
hudson-reports

4. c: Sample Reports.

Force a build, and take a detailed look at the reports generated by Doxygen as shown below:

main-page

Report-Page1

Report-Page2

I have given you a brief overview of Doxygen in this article, how to configure the same, and use it effectively to generate technical documentation on a continuous basis; either on commit builds or nightly builds. The Doxygen web site has lots of information on how to use it with other programming languages and also has tutorials in languages other than English as well.

As always, if you are having trouble getting Doxygen to work, leave a comment or check out the Doxygen web site.

Developer Testing and Tutorial and Agile and /Duvall14 Aug 2008 08:44 am

This tutorial takes a look at SOAP Message handlers and how easy it is to write handlers using JAX-WS 2.0. JAX-WS 2.0 allows both regular Java classes and stateless EJBs(Session beans) to be exposed as web services. The JAX-WS 2.0 is the core specification that defines the web services standard for Java EE 5 specification. JAX-WS 2.0 is an extension of the Java API for XML-RPC (JAX-RPC) 1.0.

SOAP message handlers are used to intercept the SOAP message as they make their way from the client to the end-point service and vice-versa. These handlers intercept the SOAP message for both the request and response of the Web Service. If you are familiar with EJB interceptors, handlers are similar to EJB interceptors and are defined in an XML file.

A few typical scenarios where you would be using SOAP Message handlers are: for encrypting and decrypting messages, to support logging, caching and in some cases auditing, and in rare cases to provide transaction management as well.

So much for the theory. Lets see the three basic steps to use a simple log handler to intercept and print our SOAP messages (request and response).

In this tutorial, we are going to expose an EJB 3 stateless session bean as a web service which is so simple and can be done by simply adding the @WebService annotation. So, here comes the source code for the interface as well as the implementation class which is self explanatory:

package com.ws;

import javax.ejb.Remote;

/**
 *
 * @author meerasubbarao
 */
@Remote
public interface HelloWebServiceRemote {

    String sayHello(String name);

}
package com.ws;

import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

/**
 *
 * @author meerasubbarao
 */
@WebService
@Stateless
public class HelloWebServiceBean implements HelloWebServiceRemote {

    @WebMethod(operationName = "sayHello")
    public String sayHello(@WebParam(name = "name") String name) {
        return "Hello " + name;
    }

}

You can package the two source files shown above into a jar, deploy to your application server, and test it as well. I am using GlassFish V2 and SoapUI to test my web services. So, shown below are the request and response from SoapUI:

Now that we know our web services work, lets start writing the message handler, which I said earlier is just 3 steps. So, what are these SOAP message handlers? They are simple Java classes that can easily modify SOAP messages; both request as well as response. These handlers have access to both the SOAP header as well as the body of the message.

soapui-test

Step 1. Implement the SOAPHandler interface.

package com.ws;

import java.io.IOException;
import java.util.Collections;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

/**
 *
 * @author meerasubbarao
 */
public class LogMessageHandler implements SOAPHandler<SOAPMessageContext> {

    public boolean handleMessage(SOAPMessageContext messageContext) {
         return true;
    }

    public Set<QName> getHeaders() {
        return Collections.EMPTY_SET;
    }

    public boolean handleFault(SOAPMessageContext messageContext) {
        return true;
    }

    public void close(MessageContext context) {
    }

}

The handleMessage method is invoked for both incoming as well as outgoing messages. Lets add a new method called log() and invoke this method from the handleMessage method. Shown below are both the methods:

    private void log(SOAPMessageContext messageContext) {
           SOAPMessage msg = messageContext.getMessage(); //Line 1
        try {
            msg.writeTo(System.out);  //Line 3
        } catch (SOAPException ex) {
            Logger.getLogger(LogMessageHandler.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(LogMessageHandler.class.getName()).log(Level.SEVERE, null, ex);
        }
  }

In line 1, we are retrieving the SOAPMessage from the message context. Line 3 will print the incoming and outgoing messages in our GlassFish console.

Invoke this method from within the handleMessage as shown:

    public boolean handleMessage(SOAPMessageContext messageContext) {
        log(messageContext);
        return true;
    }

Step 2: Create the XML file for the Handler Chain.
Create this XML file in the same package as the web service with the name LogMessage_handler.xml.

<?xml version="1.0" encoding="UTF-8"?>
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
  <handler-chain>
    <handler>
      <handler-name>com.ws.LogMessageHandler</handler-name>
      <handler-class>com.ws.LogMessageHandler</handler-class>
    </handler>
  </handler-chain>
</handler-chains>

So, let me explain about the various elements used above:

1. handler-chains is the root element that will contain a list of all handler chains that are defined for the Web Service.
2. The handler-chain child element of the handler-chains element lists all the handlers in the handler chain.
3. Within the handler-chain element is defined the handler, each handler element must in turn specify the name and also the fully qualified name of the Java class that implements the handler. If you have more than one handler, specify each one of them within the handler-chain element.

Step 3: Invoking the Handler
The @HandlerChain annotation is used to define a set of handlers that are invoked in response to a SOAP message. So, within our HelloWebServiceBean implementaion, you need to make a simple change to invoke the Log Handler as shown below:

package com.ws;

import javax.ejb.Stateless;
import javax.jws.HandlerChain;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

/**
 *
 * @author meerasubbarao
 */
@WebService
@Stateless
@HandlerChain(file = "LogMessage_handler.xml") // Line 1
public class HelloWebServiceBean implements HelloWebServiceRemote {

    @WebMethod(operationName = "sayHello")
    public String sayHello(@WebParam(name = "name") String name) {
        return "Hello " + name;
    }
 }

Now, that we have added the annotation, recompile, package and deploy the application.

Lets invoke the web services and see if it works, if it did, we should be able to see the request and response logged in our GlassFish console window, right?

So, here comes the output:
**RemoteBusinessJndiName: com.ws.CustomerManagerRemote; remoteBusIntf: com.ws.CustomerManagerRemote
LDR5010: All ejb(s) of [EJBWebServices] loaded successfully!
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.com/"><soapenv:Header/><soapenv:Body><ws:sayHello>
<name>Javalobby</name>
</ws:sayHello></soapenv:Body></soapenv:Envelope>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:sayHelloResponse xmlns:ns2="http://ws.com/"><return>Hello Javalobby</return></ns2:sayHelloResponse></S:Body></S:Envelope>

In this article, we saw how simple and easy it was to use SOAP Handlers to intercept request and response of SOAP messages. We implemented the SOAPHandler interface, wrote minimal XML to define the handler chain, and finally one simple annotation to the web service. We also were able to test these web service using SoapUI.

In Part 2 of this series, we will see how to actually parse the SOAP Headers, and also use multiple handlers.

Developer Testing and Tutorial07 Aug 2008 03:14 pm

Spring 2.0 introduced comprehensive support to use dynamic languages. It supports three different scripting languages; JRuby, Groovy and BeanShell. The scripting language used in this article is Groovy; which I think was designed for Java developers. As Scott Davis says in his book, Groovy Recipes” Groovy is Java at the end of the day”. “Spring Recipes - A Problem -Solution Approach” written by Gary Mak has a complete chapter dedicated to Scripting in Spring. The author covers all the three dynamic languages supported by Spring; JRuby, Groovy and BeanShell.

There are times when in your application you have certain modules that require frequent changes, and based on these changes you need to change the business logic within your modules. If these modules were written in Java, you can imagine what needs to be done at this point; recompile, package, redeploy. This is where modules written in these dynamic languages come in handy, there is no need to recompile, or redeploy for these changes to take effect. In most cases, you want the Spring container to be able to detect these changes and also pick up the new state from the changed script source. Spring allows you to do this as well by setting one simple attribute.

Hello World Example: It is customary to start any tutorial by writing a simple HelloWorld program, right? We are going to use Groovy in this tutorial. This tutorial assumes you have some knowledge of Spring and Groovy. I used Eclipse IDE for this tutorial, and to work with Spring and Groovy in Eclipse, you need the following libraries in your build path.

java-build-path

So, lets begin with the HelloWorld example here.

Step 1: Lets define an interface for our HelloWorld Service:

package com.springandgroovy;

public interface HelloWorldService {

	String sayHello();

}

Step 2 : Implement the interface in Groovy.
Next, we implement this interface in Groovy by creating a simple script within the com.springandgroovy package as such:

import com.springandgroovy.HelloWorldService;

class HelloWorldServiceImpl implements HelloWorldService {

	String name

   String sayHello()
   {
   		"Hello $name. Welcome to Scripting in Groovy."
   }
}

Step 3: Make changes to Spring’s configuration file.
Here comes the Spring’s bean configuration file, in which you have to include the lang schema to use the custom dynamic language tags.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:lang="http://www.springframework.org/schema/lang"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/lang
        http://www.springframework.org/schema/lang/spring-lang-2.5.xsd">

the bean definition for the Groovy backed HelloWorldService looks like this:

<lang:groovy id="helloWorldService"
			 script-source="classpath:com/springandgroovy/HelloWorldServiceImpl.groovy">
			 <lang:property name="name" value="meera"/>
</lang:groovy>

That’s all you need to use Groovy backed beans in Spring. So, how do we know this works, right? Lets write a simple Main class and test it within our IDE:

Step 4: Run the HelloWorldService.

package com.springandgroovy;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

   public static void main(String[] args) throws Exception {

     ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
     HelloWorldService service = (HelloWorldService) context.getBean("helloWorldService");

     System.out.println(service.sayHello());

    }

}

And you should be able to see output in the console as such:

console-window

Step 5: Refreshable Beans.
As I mentioned earlier also, to turn on this feature we have to specify one simple attribute refresh-check-delay on the element of our bean definition as such:

<lang:groovy id="helloWorldService"
			 script-source="classpath:com/springandgroovy/HelloWorldServiceImpl.groovy"
			 refresh-check-delay="5000">
			 <lang:property name="name" value="meera"/>
</lang:groovy>

Again, how do we know this works when we make changes to our Groovy Script? A small change in our Main class and, and you should be set to test that this works as well:

package com.springandgroovy;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

    public static void main(String[] args) throws Exception {

    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    HelloWorldService service = (HelloWorldService) context.getBean("helloWorldService");
    System.in.read();
    System.out.println(service.sayHello());

    }

}

Now, run the Main class in your IDE, it halts because of the System.in.read line, make a few changes within your script, save it, hit enter in your console window in your IDE. The Spring container read our new changes and prints the results within the console window.

The script change can be as simple as adding a few special characters as such within the sayHello() method:

   String sayHello()
   {
   		"Hello $name!!!. Welcome to Scripting in Groovy."
   }

And the console window reflects these changes:

updated-console-window

Step 6: Inline Scripts
Spring also allows you to embed scripts directly within the Spring bean definitions inside your Spring configuration file. I am no fan of doing this, because it has a drawback; the refresh attribute is not applicable for inline scripts. Lets take a look at this in case you need to use this feature:

Copy the script we wrote in Step 2 and paste it within the lang:inline-script element as such:

   <lang:groovy id="helloWorldService">
        <lang:inline-script>
        <![CDATA[
 import com.springandgroovy.HelloWorldService;
  class HelloWorldServiceImpl implements HelloWorldService {

	String name

   String sayHello()
   {
   		"Hello $name. Welcome to Scripting in Groovy"
   }
}
        ]]>
        </lang:inline-script>
        <lang:property name="name" value="meera" />
    </lang:groovy>

Run the Main class and you should see the same output in your console window.

console-window

In this tutorial we learned how to use Groovy with Spring using an external script source file, how to refresh changes when a script source file is changed, and finally saw an inline script which was embedded within the Spring configuration file.

Additional Resources:

1. JRuby
2. Groovy
3. BeanShell
4. Spring
5. Spring Recipes

Developer Testing and Tutorial23 Jul 2008 10:21 am

Is this even possible? Yes, trust me, if I can do it, so can you. You may ask, from Groovy and Grails in one day, how did I shift gears to web services. It all started while I was reading and working the samples from chapter 9 Web Services of “Beginning Groovy and Grails from Novice to Professional“. With the help of the sample provided in the book, I was able to get a RESTful web services for the Grails application.

However, I wanted to learn more about the same and write a simple RESTful web service in Java. It is traditional to start with a Hello World example while learning any new technology, right? So, lets not break the tradition and continue with the Hello World example I tried.

To follow this tutorial, you need the following software and resources.

1. NetBeans IDE 6.x, I had the latest 6.5 M1 version downloaded.
2. JDK version 5 or 6
3. GlassFish V2 Application Server
4. Last but not the least, knowledge about REST. Here are some links to get you started:

Creating a New Project:
1. Choose File -> New Project. Select Web within the Categories and select Web Application under Projects and click Next.

New-Project

2. In the next screen, enter the project name as “HelloWorldRestWS”. Leave the rest as default as shown below:
Project-Name.

3. In the screen shown below, select GlassFish V2 as the server, Java EE 5 as the Java Version, and HelloWorld as the context path and click Finish.
context-path

Creating a Web Resource:
Now, that we have our web application, lets create a simple Java Class for our web resource. To do this:

1. Right click on the project node, and select New - RESTful Web Services from Patterns… This will bring up a wizard as shown below, select the Singleton Pattern and click Next.
select-pattern

2. Next, specify all the details required for the Resource class and click Finish. Don’t forget to change the MIME Type from application/xml to text/plain.
Specify-resource-class

3. At this point, take a look at the source code generated by the IDE, which looks like:

/*
 *  HelloWorldResource
 *
 * Created on July 23, 2008, 10:13 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.stelligent.ws;

import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.ProduceMime;
import javax.ws.rs.ConsumeMime;

/**
 * REST Web Service
 *
 * @author meerasubbarao
 */

@Path("helloWorld")
public class HelloWorldResource {
    @Context
    private UriInfo context;

    /** Creates a new instance of HelloWorldResource */
    public HelloWorldResource() {
    }

    /**
     * Retrieves representation of an instance of com.stelligent.ws.HelloWorldResource
     * @return an instance of java.lang.String
     */
    @GET
    @ProduceMime("text/plain")
    public String getText() {
        //TODO return proper representation object
        throw new UnsupportedOperationException();
    }

    /**
     * PUT method for updating or creating an instance of HelloWorldResource
     * @param content representation for the resource
     * @return an HTTP response with content of the updated or created resource.
     */
    @PUT
    @ConsumeMime("text/plain")
    public void putText(String content) {
    }
}

Testing the RESTful Web Services:
1. Let’s try this application and see first hand if it works. Right click on the project node and select “Test RESTful Web Services“. The GlassFish V2 application server starts, our web application is deployed, and at this point you should see a link for the web service as shown below, choose the GET method to test.
test-rest-ws

2. Oops, something went wrong, Internal Server Error?
error

3. No problem, we can fix this. Let’s fix our getText method which is the culprit for our error.
It was:

    /**
     * Retrieves representation of an instance of com.stelligent.ws.HelloWorldResource
     * @return an instance of java.lang.String
     */
    @GET
    @ProduceMime("text/plain")
    public String getText() {
        //TODO return proper representation object
        throw new UnsupportedOperationException();
    }

 

Let’s change it to:

    /**
     * Retrieves representation of an instance of com.stelligent.ws.HelloWorldResource
     * @return an instance of java.lang.String
     */
    @GET
    @ProduceMime("text/plain")
    public String sayHello(){
        //TODO return proper representation object
        return "Hello World from REST web services generated in 60 seconds";
    }

 

4. At this point, run the application again and you should get a valid response back.
valid-response

That’s it. We were able to successfully create, deploy and test RESTful web services. Give it a try, it is just a matter of 60 seconds.

Developer Testing and Tutorial and Agile18 Jul 2008 10:12 am

book-coverJust yesterday, I posted a detailed review of the book “Persistence in the Enterprise: A Guide to Persistence Technologies” on Java Zone and a few other relevant zones. I wanted to share with you two very unique aspects of this book that are sure to help every developer.

1. If you are a CTO, an architect, a developer or even a tester, this book will help you ask the right kind of questions before you choose a persistence framework; comparing JDBC™, Apache iBATIS, Hibernate Core, Apache OpenJPA, and pureQuery. With this book, you’ll learn how to define requirements for your persistence tier, choose the right solution for your organization, and build and test enterprise systems that help maximize both performance and value.

2. source-and-testThe next thing that makes this book so unique is the tests written for each of these frameworks. The authors have free source code download, and you can learn how to write tests using JUnit and DBUnit for all these persistence frameworks. I have seen developers at a loss when writing unit tests for their persistence tier. This book gives you complete step by step instructions on how to run these samples and tests; via a common example application.

So, lets get started writing tests and see that we get at least 80% code coverage(strive for 100%) for our persistence tier.

P.S: For those of you who are Safari Books Online subscribers, the book is available there in:
http://safari.informit.com/9780131587564. I read the hard copy the hard way. :)

Developer Testing and Tutorial14 May 2008 08:33 am

For any developer looking to test web services, there are a number of tools out there that seem to fit the bill. When you need one that allows you to interact and create functional and load tests with relative ease, soapUI is bound to be the tool you can’t live without.

To help get you started, Meera Subbarao has authored a how-to series on testing web services using soapUI. Published by JavaLobby and entitled, “Functional Web Services Testing Made Easy with SoapUI,” the series is broken up into three installments; with each article demonstrating an important soapUI feature that will make web services development easier for you.

Part 1 explores soapUI basics including how to write functional tests for your web services and how to add assertions to these tests. In short, soapUI emphasizes a good balance between simplicity and rich features and as Subbarao notes in Part 1,

Once soapUI has been downloaded and installed, you can have functional tests up and running in minutes.

For more elaborate programming tasks, Part 2 examines soapUI’s relationship with Groovy. Groovy is used in soapUI primarily for test setup, test teardown, and to decide which steps to start based on the results of the older ones. If you know Java, writing Groovy scripts with the UI will make your testing even easier.

soapUI also includes command-line utilities for running tests and mocks in a continuous integration environment so you’re able to run the test cases you’ve created within it and above all fail the build just like you would when any other unit test fails. Stayed tuned for the third and final part of this series which will cover integrating tests with your build tool, running these tests as part of your builds, and creating JUnit reports.

Developer Testing and Continuous Integration and Tutorial30 Nov 2007 11:43 am

On the IBM developerWorks site, there’s a new tutorial demonstrating how to set up a Continuous Integration process. Authored by Andrew Glover, “Spot defects early with Continuous Integration” lays out a complete step-by-step guide to creating a best-of-breed CI environment using Hudson, Ant and Subversion. The resulting build process will run both tests and software inspections and will report back violations almost as quickly as they occur.

Thanks to the tutorial you’ll soon discover that Hudson is very easy to setup and get going. What’s more, even though the tutorial assumes Ant and Subversion as the build tool and repository, you’ll see that you can easily plug in Gant or Maven, CVS or ClearCase, etc.

For more articles addressing best practices for ensuring your code is the best it can be, check out the acclaimed “In pursuit of code quality” series or the accompanying discussion forum for assistance with code metrics, test frameworks, and the creation of quality-focused code.

Developer Testing and Code Complexity and Code Metrics and Tutorial and Agile11 Jun 2007 04:05 pm

Who cares about software metrics? As a Java developer, I do. Measuring certain aspects of my code lets me quantify my schedule, work effort, product size, project status, and code quality. Oh, and then my project manager cares too. If I don’t measure my current status (number of classes, dependencies to other modules, complexity, code coverage, defects as well as code smells - yes, we all know when we have code smells) and use the data to improve my code and my future work estimates, those estimates will just be guesses. And my project manager expects a little better than guesses.

Metrics is an Eclipse plugin that helps me take a holistic view of various aspects of my code. I use it on a daily basis to see how my project grows and if there are any deviations from the reference architecture. The plugin lets me take a closer look at:

  • Number of Classes
  • Method Lines of Code
  • Number of Methods
  • Nested Block Depth - Is nice, I like!
  • Depth of Inheritance Tree - nobody wants to traverse a 16-node deep tree trying to find what they need. 1-5 maybe, but 16….too many levels…
  • Afferent Coupling, Efferent Coupling - yea, whatever… we saw this here…same story…
  • Cyclomatic Complexity - If my code is simpler than Paul’s does that make me look “simpler” too?
  • …and more…

Quick Tutorial

  1. Download and start Eclipse 3.2
  2. Navigate to Help | Software Updates | Find and Install
  3. Select Search for new features to install
  4. Add a new remote site Metrics and point it to http://metrics.sourceforge.net/update
  5. Finish the wizard and restart Eclipse
  6. Download the sample solarsystem project from http://www.testearly.com/resources/agile/solarsystem.zip. Open the project in Eclipse. Note that this sample requires Java SDK 6.0.
  7. Build the project
  8. In the Package Explorer, right-click the solarsystem project and open the Properties dialog. Locate Metrics and check Enable Metrics
  9. Rebuild solarsystem
  10. Navigate to Window | Show View | Metrics | Metrics View
  11. You are looking at a table of various metrics covering the solarsystem project
  12. metrics001
  13. Feel free to dig down on each metric as it goes from source folder to package to class down to the method
  14. Notice all metrics for this simple project are in blue and there are no exclamation marks in the source code indicating any problems. Let’s change that and make life difficult for ourselves.
  15. Open the preferences page for Metrics and check Enable out-of-range warnings. Drill one level down to Safe Ranges, locate Nested Block Depth and enter 5 as the Max value. Similarly, enter 10 as the Max value for McCabe Cyclomatic Complexity
  16. In a Java Perspective open PlanetUtil.java and add the following method:
    public void thisIsAComplexMethod() {
            if (true) {
                    if (false) {
                            if (true) {
                                    if (false) {
                                            if (true) {
                                                    System.out.println("This is a deeply nested if sequence.");
                                            }
                                    } else {
    
                                    }
                            }
                    }
            }
    
            if (true) {
                    if (false) {
                            if (true) {
                                    if (false) {
                                            if (true) {
                                                    System.out.println("This is a deeply nested if sequence.");
                                            }
                                    } else {
    
                                    }
                            }
                    }
            }
    }
    
  17. Rebuild solarsystem and return to the Metrics View. You now see two red lines in the results table and an exclamation mark in the code editor. Clearly the new code failed the cyclomatic complexity and nested statements rules of Metrics and therefore was marked red. The cyclomatic complexity of the method is 11, while the if statements nest for 6 levels. Both values are out of the acceptable ranges we defined earlier.
  18. metrics002
  19. Locate the Dependency Graph View icon in the Metrics View. It can be found on the upper right corner and it is denoted by four dots connected in a square. Click the icon to open the graphical dependency view of Metrics.
  20. metrics003
  21. The packages in the project are denoted by boxes in different colors. Blue means normal relationship; red means cycles and orange denotes the selected node. There is also a circle in the middle, the tangle center, which displays the number of packages in a particular tangle and the longest walk. In general, the longer the walk the more layers are involved and therefore there may be refactoring opportunities. Similarly, the existence of red nodes and tangles indicates cycles in the package dependencies and that’s also something that may be avoided with a little care. Finally, every node and the tangle center provide right-click menus to drill-down for more details.
  22. The reason for this tangle (cycle) is the JUnit test PlanetUtilTest, which is located in com.solarsystem.jupiter. Let’s do something about this.
  23. In the Package Explorer, locate PlanetUtilTest, right-click and select Refactor | Move. Move the test into a new package com.solarsystem.test.jupiter.
  24. Rebuild the project. Open the Metrics View. Click the graph icon. Everything should be blue. There should be no tangles. No tangle centers. Blue is better than red. Life is good…
  25. metrics004
  26. Enjoy.
Developer Testing and Code Complexity and Code Metrics and Tutorial and Agile07 Jun 2007 02:42 pm

What does dependency analysis mean to you? To me it mostly translates to the fact that Common Services (CS) packages should not depend on any of their clients. Does that happen in practice? More than enough to make the case for dependency analysis.

Just like the other tools in this series JDepend can be used in Eclipse or as part of a Continuous Integration cycle. I like to see what’s going on in terms of dependencies and other architectural metrics all the time, so I use both. JDepend calculates:

  • Total number of classes and interfaces - number of concrete and abstract classes (and interfaces) in the package is an indicator of the extensibility of the package. How many?
  • Afferent couplings (Ca) - number of other packages that depend upon classes within the package is an indicator of the package’s responsibility. Who depends on me?
  • Efferent couplings (Ce) - number of other packages that the classes in the package depend upon is an indicator of the package’s independence. Who do I depend on?
  • Abstractness (A) - the ratio of the number of abstract classes (and interfaces) in the analyzed package to the total number of classes in the analyzed package. The range for this metric is 0 to 1, with A=0 indicating a completely concrete package and A=1 indicating a completely abstract package. How abstract I am? If I change today, how many of my dependents have to change with me?
  • Instability (I) - the ratio of efferent coupling (Ce) to total coupling (Ce + Ca) such that I = Ce / (Ce + Ca). This metric is an indicator of the package’s resilience to change. The range for this metric is 0 to 1, with I=0 indicating a completely stable package and I=1 indicating a completely instable package. How stable am I? Do I change often?
  • Distance to Main Sequence (D) - the perpendicular distance of a package from the idealized line A + I = 1. This metric is an indicator of the package’s balance between abstractness and stability. A package squarely on the main sequence is optimally balanced with respect to its abstractness and stability. Ideal packages are either completely abstract and stable (x=0, y=1) or completely concrete and instable (x=1, y=0). The range for this metric is 0 to 1, with D=0 indicating a package that is coincident with the main sequence and D=1 indicating a package that is as far from the main sequence as possible.
  • Package dependency cycles - dependency cycles are reported along with the hierarchical paths of packages participating in package dependency cycles. If I depend on you and you depend on me, we have to work hard to adapt to each other’s changes, don’t we?

The JDepend4Eclipse plugin is an implementation of the JDepend tool. It follows the same principles and provides visual analysis inside Eclipse. One thing to note is that the plugin works on compiled java bytecode, so its important for your project to build. Related to this is the fact that if you’re following the same package/folder structure for your unit tests as your source code it might be a good idea to compile them into a separate output folder, separate all unit tests into another Eclipse project or just change the unit test package names (by appending the name test for example ), like I show below.

Quick Tutorial

  1. Download and start Eclipse 3.2
  2. Navigate to Help | Software Updates | Find and Install
  3. Select Search for new features to install
  4. Add a new remote site JDepend4Eclipse and point it to http://andrei.gmxhome.de/eclipse/
  5. Finish the wizard and restart Eclipse
  6. Download the sample solarsystem project from http://www.testearly.com/resources/agile/solarsystem.zip. Open the project in Eclipse. Note that this sample requires Java SDK 6.0.
  7. Build the project
  8. In the Package Explorer, right-click the source folder src/main/java and select Run JDepend analysis
  9. In the newly opened JDepend perspective click on com.solarsystem.jupiter. Notice how the dependencies, packages with cycles, efferent and afferent dependencies and the metrics views get populated
  10. Notice in the Dependencies view that the com.solarsystem.jupiter package has 3 Concrete Classes (CC), 1 Abstract Class (AC), 4 Afferent Dependencies (Ca) and 7 Efferent Dependencies.(Ce) Also the Abstractness (A) is 0.25 while the Instability (I) is 0.63. Finally, the Distance (D) to the main sequence is 0.11 which is denoted by a green dot in the Metrics view. Also in this view, notice that the package is marked as having a cycle. This is because the unit test PlanetUtilTest resides in the same package. JDepend works on compiled java code and therefore it picks up everything in the target/classes folder, including any unit tests. There is plenty of theory behind the various metrics gathered by JDepend and they are beyond the scope of this quick tutorial. It suffices to say that for any given package the shorter the Distance (D) to the main sequence, the better. In the above case the com.solarsystem.jupiter is used by four other packages, thus Ca=4. The package depends on 7 other packages, including junit.framework, therefore the Ce=7.
  11. Generally speaking cycles between packages indicate complex interdependencies and should be avoided. In this step, let’s eliminate the cycles in the project.
  12. In the Package Explorer locate src/test/java anc right-click on PlanetUtilTest
  13. Select Refactor | Move…
  14. Create a new package com.solarsystem.test.jupiter and click OK
  15. JDepend4Eclipse
  16. Return back to src/main/java. Right-click and select Run JDepend analysis. All cycles are gone. While we eliminated the cycles, notice also that the distance jumped to 33 from 11 and is now denoted by a black dot.
  17. In Java Browsing perspective select File | New | Interface. Enter a name, IBogus, select the package com.solarsystem.jupiter and click OK. This is just an empty interface.
    package com.solarsystem.jupiter;
    
    public interface IBogus {
    
    }
    
  18. Build the project
  19. In Package Explorer, right-click the source folder src/main/java and select Run JDepend analysis
  20. Notice the Distance is now 16 and the dot turned green. But what did the IBogus interface add to the package? Nothing. It just fooled the tool. This is where special care must be taken. Sometimes emty or unused abstract classes can negatively impact the static analysis and make one belive that the package is in a better state than it actually is. My recommendation is to use other tools that detect unused classes and imports and get the whole system cleaned-up before each dependency analysis.
  21. Enjoy.

Next Page »