-->

November 25, 2008

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

Categories: totd, webservices


Jersey is the open source, production quality, JAX-RS (JSR 311) Reference Implementation for building RESTful Web services in the GlassFish community. It also provides an API that allows developers to extend Jersey to suite their requirements.

This Tip Of The 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:

    ~/samples/jersey >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>:

                  <plugin>
                      <groupId>org.glassfish</groupId>
                      <artifactId>maven-glassfish-plugin</artifactId>
                  </plugin>
    2. Add the following plugin repositories:
          <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:
              <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:

              <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 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″.
          <properties>
              <jersey-version>1.0</jersey-version>
          </properties>
  3. Run the application
    1. The generated source code is:

      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:

      ~/samples/jersey/helloworld-webapp >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:

    3. Clicking on “Jersey resource” redirects to “http://localhost:8080/helloworld-webapp/webresources/myresource” and shows the following output:

  4. Change the output representation to produce JSON representation
    1. Add a new JAXB bean:

      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:
      //    @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:

      Notice the output is now in JSON format.

  5. Optionally a WAR file can be created using the command:
    mvn clean package

    and the WAR file is generated in “target/helloworld-webapp.war”. If Jersey is installed using 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 Configuring JSON for RESTful Web Services in Jersey 1.0. This has certainly come a long way from 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 .

Please leave suggestions on other TOTD (Tip Of The Day) that you’d like to see. An archive of all the tips is available here.

Technorati: totd glassfish v3 embeddable jersey jsr311 rest json webservices

Share and Enjoy:
  • Print
  • Digg
  • Sphinn
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • DZone
  • StumbleUpon
  • Technorati
  • Twitter
  • Slashdot
Related posts:
  1. TOTD #57: Jersey Client API – simple and easy to use
  2. TOTD #100: Getting Started with Scala Lift on GlassFish v3
  3. TOTD #8: Generating JSON using JAXB annotations in Jersey
  4. TOTD #58: Jersey and GlassFish – how to process POST requests ?
  5. TOTD #10: Consuming JSON and XML representations generated by a Jersey endpoint in a jMaki Table widget

16 Comments »

  1. Nice post! I have updated the published Jersey archetype, so that steps 2.1 and 2.2 should not be needed any more.

    Comment by Jakub — November 25, 2008 @ 10:02 am

  2. One more comment on generating the sample. You can also use non-interactive version:
    mvn archetype:generate -DarchetypeCatalog=http://download.java.net/maven/2 -DinteractiveMode=false -DarchetypeArtifactId=helloworld-webapp -DarchetypeGroupId=com.sun.jersey.archetypes -DgroupId=org.glassfish.samples -DartifactId=test -Dpackage=org.glassfish.samples

    Comment by Jakub — November 25, 2008 @ 10:23 am

  3. Thanks a lot Jakub, this will further simplify the development process and this blog entry. However the mvn command is throwing NPE, any idea ?

    Comment by Arun Gupta — November 25, 2008 @ 10:52 am

  4. Arun: i did not test the command previously, but this time the following should work:
    mvn archetype:generate -DarchetypeCatalog=http://download.java.net/maven/2 -DinteractiveMode=false -DarchetypeArtifactId=jersey-quickstart-webapp -DarchetypeGroupId=com.sun.jersey.archetypes -DgroupId=org.glassfish.samples -DartifactId=helloworld-webapp -Dpackage=org.glassfish.samples

    Comment by Jakub — November 25, 2008 @ 2:03 pm

  5. Hmm, getting a NPE again. Here is what I see:

    ~/samples/jersey >mvn archetype:generate -DarchetypeCatalog=http://download.java.net/maven/2 -DinteractiveMode=false -DarchetypeArtifactId=jersey-quickstart-webapp -DarchetypeGroupId=com.sun.jersey.archetypes -DgroupId=org.glassfish.samples -DartifactId=helloworld-webapp -Dpackage=org.glassfish.samples
    [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] ————————————————————————
    [ERROR] BUILD FAILURE
    [INFO] ————————————————————————
    [INFO] : java.lang.NullPointerException
    null

    Comment by Arun Gupta — November 25, 2008 @ 5:01 pm

  6. Nice blog although I would have chosen:

    Choose a number: (1/2): 1

    Much faster ;-)

    Comment by Jeanfrancois Arcand — November 25, 2008 @ 8:34 pm

  7. [Trackback] TOTD #56 explains how to create a RESTful Web service endpoint using Jersey and publish the resource using JSON representation. The blog entry showed how the endpoint can be accessed from a Web browser. This Tip Of The Day explains…

    Comment by Arun Gupta's Blog — November 26, 2008 @ 6:03 am

  8. Jeanfrancois, that is already explained in the tech tip at: http://blogs.sun.com/enterprisetechtips/entry/configuring_json_for_restful_web :)

    These blogs are prelude for a bigger blog coming up next week, stay tuned and you’ll understand the context!

    Comment by Arun Gupta — November 26, 2008 @ 6:06 am

  9. NPE again: i do not know, my maven says:
    %mvn archetype:generate -DarchetypeCatalog=http://download.java.net/maven/2 -DinteractiveMode=false -DarchetypeArtifactId=jersey-quickstart-webapp -DarchetypeGroupId=com.sun.jersey.archetypes -DgroupId=org.glassfish.samples -DartifactId=helloworld-webapp -Dpackage=org.glassfish.samples | tee mvn.out
    [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 Batch mode
    [INFO] Archetype [com.sun.jersey.archetypes:jersey-quickstart-webapp:1.0.1-SNAPSHOT -> http://download.java.net/maven/2
    [INFO] snapshot com.sun.jersey.archetypes:jersey-quickstart-webapp:1.0.1-SNAPSHOT: checking for updates from jersey-quickstart-webapp-repo
    [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: basedir, Value: /export/home/japod/workspace
    [INFO] Parameter: package, Value: org.glassfish.samples
    [INFO] Parameter: version, Value: 1.0-SNAPSHOT
    [INFO] Parameter: artifactId, Value: helloworld-webapp
    [WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/pom.xml [line 46,column 22] : ${jersey-version} is not a valid reference.
    [WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/pom.xml [line 51,column 22] : ${jersey-version} is not a valid reference.
    [WARNING] org.apache.velocity.runtime.exception.ReferenceException: reference : template = archetype-resources/pom.xml [line 62,column 22] : ${jersey-version} is not a valid reference.
    [INFO] ********************* End of debug info from resources from generated POM ***********************
    [INFO] OldArchetype created in dir: /export/home/japod/workspace/helloworld-webapp
    [INFO] ————————————————————————
    [INFO] BUILD SUCCESSFUL
    [INFO] ————————————————————————
    [INFO] Total time: 4 seconds
    [INFO] Finished at: Wed Nov 26 16:25:25 CET 2008
    [INFO] Final Memory: 11M/167M
    [INFO] ————————————————————————

    Comment by Jakub — November 26, 2008 @ 7:32 am

  10. [Trackback] Lets extend the Jersey endpoint (TOTD# 56) and client (TOTD# 57) such that it can accept a POST request and then invoke it. Add a new method to "MyResource.java" from TOTD# 56 as: &nbsp;&nbsp;&nbsp; @POST &nbsp;&nbsp;&nbsp; @Consumes("application/json…

    Comment by Arun Gupta's Blog — December 1, 2008 @ 6:31 am

  11. Jakub,

    It seems like this might be a platform specific problem, will debug later.

    Comment by Arun Gupta — December 3, 2008 @ 1:09 pm

  12. If the generated dependencies:

    <dependency> <groupId>org.glassfish.distributions</groupId>
    <artifactId>web-all</artifactId>
    <version>10.0-build-20080430</version>
    <scope>test</scope>
    </dependency>

    and

    <dependency> <groupId>org.glassfish.embedded</groupId>
    <artifactId>gf-embedded-api</artifactId>
    <version>1.0-alpha-4</version>
    <scope>test</scope>
    </dependency>

    are changed to:

    <dependency>
    <groupId>org.glassfish.distributions</groupId>
    <artifactId>web-all</artifactId>
    <version>10.0-SNAPSHOT</version>
    <scope>test</scope>
    </dependency>

    and

    <dependency>
    <groupId>org.glassfish.embedded</groupId>
    <artifactId>glassfish-embedded-all</artifactId>
    <version>3.0-Prelude-SNAPSHOT</version>
    </dependency>

    then the latest version of the embedded APIs are used.

    Comment by Arun Gupta — December 3, 2008 @ 1:16 pm

  13. [Trackback] Today Sun announces the availability of Java FX 1.0. JavaFX 1.0 is a rich client platform for creating and delivering Rich Internet Applications across all screens (desktop, browser, and mobile) of your life. It consists of the following key…

    Comment by Arun Gupta's Blog — December 4, 2008 @ 7:12 am

  14. I recently came across your blog and have been reading along. I thought I would leave my first comment. I don’t know what to say except that I have enjoyed reading. Nice blog. I will keep visiting this blog very often.

    Betty

    http://www.my-foreclosures.info

    Comment by Betty — December 16, 2008 @ 7:00 pm

  15. ThankSss

    Comment by dizi izle — February 21, 2009 @ 9:17 am

  16. thx u. perfect and beautiful expression.

    Comment by sinema izle — March 7, 2009 @ 3:32 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress
173353 visits from Sep 11, 2009