Skip to main content

TOTD #56: Simple RESTful Web service using Jersey and Embeddable GlassFish - Text and JSON output

Posted by arungupta on November 25, 2008 at 6:39 AM PST


cellspacing="2">
href="http://jersey.dev.java.net"> style="border: 0px solid ; width: 64px; height: 52px;" alt=""
src="https://jersey.dev.java.net/images/Jersey_yellow.png">
Jersey
is the open source, production quality, href="https://jsr311.dev.java.net/nonav/releases/1.0/index.html">JAX-RS
(JSR 311) Reference Implementation for building RESTful Web services in
the GlassFish
community. It also provides an href="https://jersey.dev.java.net/source/browse/*checkout*/jersey/tags/jersey-1.0/api/jersey/index.html">API
that allows developers to extend Jersey to suite their requirements.



This Tip style="font-weight: bold;">Of style="font-weight: bold;">The style="font-weight: bold;">Day (TOTD) shows how
to create a simple RESTful Web service using Jersey and run it using
embeddable GlassFish (glassfish:run). Maven is used to create and run
the application. It also shows how the output format can be easily
coverted from Text to JSON.



Lets get started!

  1. Create a simple web app using Maven as:


    style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
    cellpadding="2" cellspacing="2">
    ~/samples/jersey > style="font-weight: bold;">mvn archetype:generate
    -DarchetypeCatalog=http://download.java.net/maven/2

    [INFO] Scanning for projects...

    [INFO] Searching repository for plugin with prefix: 'archetype'.

    [INFO]
    ------------------------------------------------------------------------

    [INFO] Building Maven Default Project

    [INFO]    task-segment: [archetype:generate]
    (aggregator-style)

    [INFO]
    ------------------------------------------------------------------------

    [INFO] Preparing archetype:generate

    [INFO] No goals needed for project - skipping

    [INFO] Setting property: classpath.resource.loader.class =>
    'org.codehaus.plexus.velocity.ContextClassLoaderResourceLoader'.

    [INFO] Setting property: velocimacro.messages.on => 'false'.

    [INFO] Setting property: resource.loader => 'classpath'.

    [INFO] Setting property: resource.manager.logwhenfound =>
    'false'.

    [INFO] [archetype:generate]

    [INFO] Generating project in Interactive mode

    [INFO] No archetype defined. Using maven-archetype-quickstart
    (org.apache.maven.archetypes:maven-archetype-quickstart:1.0)

    Choose archetype:

    1: remote -> jersey-quickstart-grizzly (Archetype for creating a
    RESTful web application with Jersey and Grizzly)

    2: remote -> jersey-quickstart-webapp (Archetype for creating a
    Jersey based RESTful web application WAR packaging)

    Choose a number:  (1/2): 2

    [INFO]
    snapshot
    com.sun.jersey.archetypes:jersey-quickstart-webapp:1.0.1-SNAPSHOT:
    checking for updates from jersey-quickstart-webapp-repo

    Define value for groupId: : org.glassfish.samples

    Define value for artifactId: : helloworld-webapp

    Define value for version:  1.0-SNAPSHOT: :

    Define value for package: : org.glassfish.samples


    Confirm properties configuration:

    groupId: org.glassfish.samples

    artifactId: helloworld-webapp

    version: 1.0-SNAPSHOT

    package: org.glassfish.samples

     Y: :

    [INFO]
    ----------------------------------------------------------------------------

    [INFO] Using following parameters for creating OldArchetype:
    jersey-quickstart-webapp:1.0.1-SNAPSHOT

    [INFO]
    ----------------------------------------------------------------------------

    [INFO] Parameter: groupId, Value: org.glassfish.samples

    [INFO] Parameter: packageName, Value: org.glassfish.samples

    [INFO] Parameter: package, Value: org.glassfish.samples

    [INFO] Parameter: artifactId, Value: helloworld-webapp

    [INFO] Parameter: basedir, Value: /Users/arungupta/samples/jersey

    [INFO] Parameter: version, Value: 1.0-SNAPSHOT

    [INFO] ********************* End of debug info from resources from
    generated POM ***********************

    [INFO] OldArchetype created in dir:
    /Users/arungupta/samples/jersey/helloworld-webapp

    [INFO]
    ------------------------------------------------------------------------

    [INFO] BUILD SUCCESSFUL

    [INFO]
    ------------------------------------------------------------------------

    [INFO] Total time: 21 seconds

    [INFO] Finished at: Mon Nov 24 14:09:27 PST 2008

    [INFO] Final Memory: 12M/30M

    [INFO]
    ------------------------------------------------------------------------
  2. Edit the generated "pom.xml" to add dependencies on
    GlassFish plugin
    1. Add the following plugin in the "pom.xml" under
      <build>/<plugins>:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
                 
      <plugin>

                     
      <groupId>org.glassfish</groupId>

                     
      <artifactId>maven-glassfish-plugin</artifactId>

                 
      </plugin>
    2. Add the following plugin repositories:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
         
      <pluginRepositories>

             
      <pluginRepository>

                 
      <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>

             
      </pluginRepository>

             
      <pluginRepository>

                 
      <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>

             
      </pluginRepository>

          </pluginRepositories>
    3. Optionally, if the generated dependencies in "pom.xml" as
      shown below:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
             
      <dependency>

                 
      <groupId>org.glassfish.distributions</groupId>

                 
      <artifactId>web-all</artifactId>

                 
      <version>10.0-build-20080430</version>

                 
      <scope>test</scope>

             
      </dependency>

             
      <dependency>

                 
      <groupId>org.glassfish.embedded</groupId>

                 
      <artifactId>gf-embedded-api</artifactId>

                 
      <version>1.0-alpha-4</version>

                 
      <scope>test</scope>

             
      </dependency>



      are changed to:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
             
      <dependency>

                 
      <groupId>org.glassfish.distributions</groupId>

                 
      <artifactId>web-all</artifactId>

                 
      <version>10.0-SNAPSHOT</version>

                 
      <scope>test</scope>

             
      </dependency>

             
      <dependency>

                
      <groupId>org.glassfish.embedded</groupId>

                
      <artifactId>glassfish-embedded-all</artifactId>

                
      <version>3.0-Prelude-SNAPSHOT</version>

             
      </dependency>



      then the latest version of href="http://embedded-glassfish.dev.java.net/">Embedded
      GlassFish APIs are used.

    4. Also optionally, if you want to run against Jersey 1.0
      bits
      then change the following property from "1.0.1-SNAPSHOT" to "1.0".


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
         
      <properties>

             
      <jersey-version>1.0</jersey-version>

          </properties>
  3. Run the application
    1. The generated source code is:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      package org.glassfish.samples;



      import javax.ws.rs.GET;

      import javax.ws.rs.Path;

      import javax.ws.rs.Produces;



      // The Java class will be hosted at the URI path "/helloworld"

      @Path("/myresource")

      public class MyResource {

         

          // The Java method will process HTTP GET
      requests

          @GET

          // The Java method will produce content
      identified by the MIME Media

          // type "text/plain"

          @Produces("text/plain")

          public String getIt() {

             
      return "Hi there!";

          }

      }



      Invoking "mvn glassfish:run" starts the embedded GlassFish and shows
      the following output:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      ~/samples/jersey/helloworld-webapp > style="font-weight: bold;">mvn glassfish:run

      [INFO] Scanning for projects...

      [INFO] Searching repository for plugin with prefix: 'glassfish'.

      [INFO]
      ------------------------------------------------------------------------

      [INFO] Building helloworld-webapp Jersey Webapp

      [INFO]    task-segment: [glassfish:run]

      [INFO]
      ------------------------------------------------------------------------

      [INFO] Preparing glassfish:run

      [INFO] [resources:resources]

      [INFO] Using default encoding to copy filtered resources.

      [INFO] [compiler:compile]

      [INFO] Compiling 1 source file to
      /Users/arungupta/samples/jersey/helloworld-webapp/target/classes

      [INFO] [glassfish:run]

      Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup
      run

      INFO: HK2 initialized in 229 ms

      Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup
      run

      INFO: com.sun.enterprise.naming.impl.ServicesHookup@2470b02c Init done
      in 237 ms

      Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup
      run

      INFO: com.sun.enterprise.v3.server.Globals@13b3d787 Init done in 239 ms

      Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup
      run

      INFO: com.sun.enterprise.v3.server.SystemTasks@61bedd7d Init done in
      244 ms

      Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup
      run

      INFO: com.sun.enterprise.v3.services.impl.HouseKeeper@2b9f7952 Init
      done in 245 ms

      Nov 24, 2008 2:36:05 PM com.sun.enterprise.v3.server.AppServerStartup
      run

      INFO:
      com.sun.enterprise.v3.services.impl.CmdLineParamProcessor@5249d560 Init
      done in 248 ms

      JMXMP connector server URL = service:jmx:jmxmp://localhost:8888

      Nov 24, 2008 2:36:05 PM
      com.sun.enterprise.v3.services.impl.GrizzlyProxy start

      INFO: Listening on port 8080

      Nov 24, 2008 2:36:06 PM com.sun.enterprise.v3.server.AppServerStartup
      run

      INFO: com.sun.enterprise.v3.services.impl.GrizzlyService@1baa56a2
      startup done in 551 ms

      Nov 24, 2008 2:36:06 PM
      com.sun.enterprise.v3.services.impl.ApplicationLoaderService
      postConstruct

      INFO: loader service postConstruct started at 1227566166208

      Nov 24, 2008 2:36:06 PM com.sun.enterprise.v3.server.AppServerStartup
      run

      INFO: Application Loader startup done in 740 ms

      Nov 24, 2008 2:36:06 PM com.sun.enterprise.v3.server.AppServerStartup
      run

      INFO: Glassfish v3 started in 740 ms

      Nov 24, 2008 2:36:07 PM com.sun.enterprise.web.WebModuleContextConfig
      authenticatorConfig

      SEVERE: webModuleContextConfig.missingRealm

      Nov 24, 2008 2:36:07 PM com.sun.jersey.api.core.PackagesResourceConfig
      init

      INFO: Scanning for root resource and provider classes in the packages:

        org.glassfish.samples

      Nov 24, 2008 2:36:07 PM com.sun.jersey.api.core.PackagesResourceConfig
      init

      INFO: Root resource classes found:

        class org.glassfish.samples.MyResource

      Nov 24, 2008 2:36:07 PM com.sun.jersey.api.core.PackagesResourceConfig
      init

      INFO: Provider classes found:

      Hit ENTER for redeploy



      Notice how GlassFish v3 starts up in sub-second (740 ms in this case).

    2. "http://localhost:8080/helloworld-webapp" shows the
      following output:



      alt=""
      src="http://blogs.sun.com/arungupta/resource/images/jersey10-helloworld-webapp-default-output.png">
    3. Clicking on "Jersey resource" redirects to
      "http://localhost:8080/helloworld-webapp/webresources/myresource" and
      shows the following output:



      alt=""
      src="http://blogs.sun.com/arungupta/resource/images/jersey10-helloworld-webapp-text-output.png">
  4. Change the output representation to produce JSON
    representation
    1. Add a new JAXB bean:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      package org.glassfish.samples;



      import javax.xml.bind.annotation.XmlRootElement;



      /**

       * @author arungupta

       */

      @XmlRootElement

      public class Greeting {

          public String greeting;



          public Greeting() { }

          public Greeting(String greeting) {

             
      this.greeting = greeting;

          }

      }
    2. Change the method implementation in MyResource as:


      style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
      cellpadding="2" cellspacing="2">
      //   
      @Produces("text/plain")

          @Produces("application/json")

          public Greeting getIt() {

             
      return new Greeting("Hi there!");

          }
    3. And now
      "http://localhost:8080/helloworld-webapp/webresources/myresource" shows
      the following output:



      src="http://blogs.sun.com/arungupta/resource/images/jersey10-helloworld-webapp-json-output.png">



      Notice the output is now in JSON format.
  5. Optionally a WAR file can be created using the command:


    style="text-align: left; background-color: rgb(204, 204, 255); width: 100%;"
    cellpadding="2" cellspacing="2">
    mvn clean package



    and the WAR file is generated in "target/helloworld-webapp.war". If
    Jersey is installed using  href="http://blogs.sun.com/japod/entry/jersey_1_0_available_on">GlassFish
    v3 Update Center then you can use "maven-assembly-plugin" to
    customize packaging of WAR and drastically reduce the size.

The JSON representation can be configured in multiple ways as explained
in href="http://blogs.sun.com/enterprisetechtips/entry/configuring_json_for_restful_web">Configuring
JSON for RESTful Web Services in Jersey 1.0. This has
certainly come a long way from href="http://blogs.sun.com/arungupta/entry/totd_8_generating_json_using">TOTD
#8 and is much more effecient now.



The Jersey
Wiki
 documents an extensive set of resources to get
started.



Send all your questions to href="mailto:users@jersey.dev.java.net">users@jersey.dev.java.net.



Please leave suggestions on other TOTD ( style="font-weight: bold;">Tip style="font-weight: bold;">Of style="font-weight: bold;">The style="font-weight: bold;">Day) that
you'd like to see.
An archive of all the tips is available href="http://blogs.sun.com/arungupta/tags/totd">here.




Technorati: totd
glassfish
v3 href="http://technorati.com/tag/embeddable">embeddable
jersey
jsr311
rest href="http://technorati.com/tag/json">json href="http://technorati.com/tag/webservices">webservices

Related Topics >>