Friday, May 8, 2009

Jersey on embedded grizzly (another tomcat like server) and then on tomcat 6

<< It is about JAX-RS - JSR 311. Simply getting up and running with restful webservices quickly> >
<<remember running it on tomcat 5.x is a bit different> >
First thing first. Lets write the application first. To show the dependencies the library versions that worked for me is listed below in the form of POM file.

======================================================================
For NON MAVEN USERS: Do not worry about the pom content just look at the dependencies to get the jar files with right versions and this also says that my dev environment is Java 6 but it should work well with Java 5. You may skip the pom if you wish.
======================================================================

============================
POM.XML
============================
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>paperless-client-rest-api</groupId>
<artifactId>simple-ws-client-rest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>Simple Client REST Aplis for Java
</description>

<repositories>
<repository>
<id>maven2-repository.dev.java.net</id>
<name>Java.net Repository for Maven</name>
<url>http://download.java.net/maven/2/
</url>
<layout>default</layout>
</repository>
<repository>
<id>maven-repository.dev.java.net</id>
<name>Java.net Maven 1 Repository (legacy)</name>
<url>http://download.java.net/maven/1
</url>
<layout>legacy</layout>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-server</artifactId>
<version>1.1.0-ea</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.1.0-ea</version>
</dependency>
<dependency>
<groupId>com.sun.grizzly</groupId>
<artifactId>grizzly-servlet-webserver
</artifactId>
<version>1.9.9</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<!-- <executable>${env.JAVA_HOME}/bin/javac</executable> -->
<compilerVersion>1.6</compilerVersion>
<fork>true</fork>
<verbose>true</verbose>
</configuration>
</plugin>
</plugins>
</build>
</project><


We will have only 2 files to start with a basic and a good and a complete sample
======================
CODE: The resource class - this class will decide what you get once you access the specific URI. The uri here is /helloworld on the server root. e.g. if your server runs on localhost:9998 then the resource will be accessible at http://localhost:9998/helloworld. If you open http://localhost:9998/helloworld on your browser you will see the message helloworld - of course you have to implement the service - it is just one block away.
======================


  1. package org.paperless.client.rest.example;

  2. import javax.ws.rs.GET;
  3. import javax.ws.rs.Path;
  4. import javax.ws.rs.PathParam;
  5. import javax.ws.rs.Produces;

  6. /**
  7. * @Author Chiradip Mandal
  8. * @Copyright © Chiradip Mandal 2009
  9. * @License Apache License v2.0 http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. */
  12. // The Java class will be hosted at the URI path "/helloworld"
  13. @Path( "/helloworld" )
  14. public class HelloWorldResource {

  15. // The Java method will process HTTP GET requests
  16. @GET
  17. // The Java method will produce content identified by the MIME Media
  18. // type "text/plain"
  19. @Produces( "text/plain" )
  20. public String getMessage() {
  21. return "Hello World";
  22. }
  23. }
====================================
CODE: The RESTful service goes below. It uses the resource (HelloWorldResource).
====================================

  1. package org.paperless.client.rest.example;

  2. import java.io.IOException;
  3. import java.util.HashMap;
  4. import java.util.Map;

  5. import com.sun.grizzly.http.SelectorThread;
  6. import com.sun.jersey.api.container.grizzly.GrizzlyWebContainerFactory;

  7. /**
  8. * @Author Chiradip Mandal
  9. * @Copyright © Chiradip Mandal 2009
  10. * @License Apache License v2.0 http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. */
  13. public class Main {
  14. public static void main( String[] args ) throws IOException {

  15. final String baseUri = "http://localhost:9998/";
  16. final Map<> initParams = new HashMap<>();

  17. initParams.put( "com.sun.jersey.config.property.packages", "org.paperless.client.rest.example" );

  18. System.out.println( "Starting grizzly..." );
  19. SelectorThread threadSelector = GrizzlyWebContainerFactory.create( baseUri, initParams );
  20. System.out.println( String.format( "Jersey app started with WADL available at %sapplication.wadl\n"
  21. + "Try out %shelloworld\nHit enter to stop it...", baseUri, baseUri ) );
  22. System.in.read();
  23. threadSelector.stopEndpoint();
  24. System.exit( 0 );
  25. }
  26. }


Notice Line number 22. initParams.put( "com.sun.jersey.config.property.packages", "org.paperless.client.rest.example" ); The second part of this line is crucial. This the name of the package where all the resource (classes) will be available, either directly or under subpackage of this package.

Guess what? Just run the the above java and point your browser at http://localhost:9998/helloworld and voila you see the message appears on you browser "Hello World".

=======================
ENHANCEMENT OF THE ABOVE CODE
=======================

This is pretty static code. Lets add some dynamism here. Lets say if we access http://localhost:9998/helloworld/print/{myname} - substitute {myname} by your actual name - and we get our name printed on the browser or the caller http client.

Lets add the following lines in HelloWorldResource.java



@GET
@Produces( "text/plain" )
@Path( "print/{myname}" )
public String getTestReply( @PathParam( "myname" ) String name ) {
return "Your name: " + name;
}





One more thing is done. Lets jump into the next thing - returning a java object. Trick is here - at the server side we can return an object but at the browser or httpclient side java object does not make sense but XML does. Lets see how we can return a java object at the server side to get an XML at the client.


@GET
@Produces( "application/xml" )
@Path( "desc" )
public SimpleDescrption getDescription() {
SimpleDescrption desc = new SimpleDescrption();
desc.setMyDescOne( "My Description One" );
desc.setMyDescTwo( "My Description Two" );
return desc;
}


You guessed it right. If you access browser http://localhost:9998/helloworld/desc and you will see an XML appearing on your browser or curl or any httpclient.

One thing is left the SimpleDescription.java - it is simple just follow me below. It's a simple bean except it is marked as @XMLRootElement and thats it. Remember this marking is must to get this working.


package org.paperless.client.rest.example;

import javax.xml.bind.annotation.XmlRootElement;

/**
* @Author Chiradip Mandal
* @Copyright © Chiradip Mandal 2009
* @License Apache License v2.0 http://www.apache.org/licenses/LICENSE-2.0
*
*/
@XmlRootElement
public class SimpleDescrption {
private String myDescOne;
private String myDescTwo;

public void setMyDescOne( String myDescOne ) {
this.myDescOne = myDescOne;
}

public String getMyDescOne() {
return myDescOne;
}

public void setMyDescTwo( String myDescTwo ) {
this.myDescTwo = myDescTwo;
}

public String getMyDescTwo() {
return myDescTwo;
}
}


Use your favorite browser (I dont use my favorite browser for this as safari is bad in handling XML output ;) ). The output in firefox is as below.

<simpleDescrption>
<myDescOne>My Description One</myDescOne>
<myDescTwo>My Description Two</myDescTwo>
</simpleDescrption>