Implementing RESTful services with JAX-RS and WebSphere 8.5 Liberty Profile

Z Jacek Laskowski - Wiki Amatora Programowania
Skocz do: nawigacji, wyszukiwania

In the forum WASdev there was a thread about Multipath form data and variable-length input forms with Strings and Files. It was about time to cross a task off from a list of TODOs to prepare a testing environment with Java API for RESTful Web Services (JAX-RS) and WebSphere Application Server V8.5 Liberty Profile.

JAX-RS is a specification defined by JSR 311: JAX-RS: The Java API for RESTful Web Services in the Java Community Process.

The article aims at providing a working environment with two sample RESTful service resource classes - HelloResource and MultipartResource - based upon JAX-RS with @GET, @POST, @Consumes with MediaType.MULTIPART_FORM_DATA and @FormParam annotations.

The development environment for the article consists of:

$ ./bin/server version
wlp-1.0.1.20130309-1525(websphere-kernel_1.0.1) on Java HotSpot(TM) 64-Bit Server VM, version 1.7.0_17-b02

Spis treści

Creating Dynamic Web Project with JAX-RS (REST Web Services) facet

In Eclipse, go to File > New > Other... and select Dynamic Web Project under Web category (start typing dynamic web project to have the wizard showed up).

Liberty-jaxrs-new-dynamic-web-project.png

Click Next >.

Click Modify... in the Configuration section to add JAX-RS (REST Web Services) support in Eclipse (via appropriate facet).

Check the JAX-RS (REST Web Services) checkbox.

Liberty-jaxrs-project-facets-jax-rs-rest-web-services-facet-checked.png

Click OK.

The Configuration should now be <custom>.

Use the following settings for the project:

  • Project name: LibertyJaxRsWeb
  • Target runtime should already be set to WebSphere Application Server V8.5 Liberty Profile (or whatever name you used to define the Liberty Profile runtime)
  • Uncheck Add project to an EAR in the EAR membership section
Liberty-jaxrs-dynamic-web-project-form-completed.png

Click Next > until you see the JAX-RS Capabilities panel.

Uncheck the Update Deployment Descriptor checkbox as unnecessary for the version of WebSphere Liberty Profile. Make sure that the type of the JAX-RS Implementation Library is IBM WebSphere Application Server Liberty JAX-RS Library.

Liberty-jaxrs-new-dynamic-web-project-jax-rs-capabilities-update-deployment-descriptor-unchecked.png

Click Finish.

Defining RESTful service resource classes

Read Overview of IBM JAX-RS to get a better understanding of what the specification offers.

"A resource is simply any data that you want to share on the web that you can identify by a Uniform Resource Identifier (URI)."

It's also strongly recommended to read Chapter 20 Building RESTful Web Services with JAX-RS in The Java EE 6 Tutorial to expand knowledge on JAX-RS.

HelloResource

In the LibertyJaxRsWeb web project, create a class called pl.japila.liberty.HelloResource.

The class defines a RESTful Root Resource Class that responds to GET and POST requests. While the GET resource method returns a fixed string response, the POST variant responds with a string as well as the X-Resource-Architect custom header.

package pl.japila.liberty;
 
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
 
@Path("/hello")
public class HelloResource {
    @GET
    public String helloGet() {
        return "[GET] Hello from JAX-RS on WebSphere Liberty Profile";
    }
 
    @POST
    public Response helloPost() {
        return Response.ok("[POST] Hello from JAX-RS on WebSphere Liberty Profile")
                       .header("X-Resource-Architect", "Jacek Laskowski")
                       .build();
    }
}

MultipartResource

Create another class pl.japila.liberty.MultipartResource that represents a RESTful multipart-enabled Root Resource Class. You may want to read the document Configuring a resource to receive multipart/form-data parts from an HTML form submission in which a more complex sample is described.

package pl.japila.liberty;
 
import java.io.File;
import java.util.List;
 
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
 
@Path("/multipart")
public class MultipartResource {
    @GET
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response handleMultipart(@FormParam("fileid") int theFileid,
                                    @FormParam("description") String theDescription,
                                    @FormParam("thefile") File theFile) {
        System.out.printf("theFileid: %s, theDescription: %s, theFile: %s%n", theFileid, theDescription, theFile);
        return Response.ok().build();
    }
 
    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response completeHandleMultipart(@FormParam("xml") String theXml,
                                            @FormParam("file") List<File> files) {
        final String response = "theXML: " + theXml + " and " + files.size() + " file(s) received";
        System.out.println(response);
        return Response.ok(response).build();
    }
 
}

Defining JAX-RS Application - DemoApplication

With these two service resources defined, you're going to create a JAX-RS application that will configure them in the Java EE application server - WebSphere Liberty Profile.

An "empty" (no methods overriden) implementation of javax.ws.rs.core.Application tells the runtime environment that the service resources are packaged in the web archive (WAR) and should be scanned for at deployment.

In the LibertyJaxRsWeb project create a class called pl.japila.liberty.DemoApplication.

package pl.japila.liberty;
 
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
 
@ApplicationPath("/rest")
public class DemoApplication extends Application {
}

Liberty Profile configuration - jaxrs-1.1 feature

The application is already defined and the only missing piece is to configure WebSphere Liberty Profile so it's capable of hosting RESTful services.

Add the jaxrs-1.1 feature to the server.xml configuration file of the WebSphere Liberty Profile server.

Create a new server instance (use the Runtime Explorer view) and then use WebSphere Developer Tools' server configuration editor to add the feature. Double-click Feature Manager jsp-2.2 node of the server in the Servers view and use Add... to add jaxrs-1.1.

Liberty-jaxrs-server-configuration-jax-rs-1-1-feature.png

Save the change.

Taking REST to test

Deploy the LibertyJaxRsWeb web project to the WebSphere Liberty Profile server.

GETting HelloResource

Browse to http://localhost:9080/LibertyJaxRsWeb/rest/hello.

Liberty-jaxrs-get-hello.png

The above screenshot shows the result from sending a GET request to HelloResource that's "mounted" to /hello URL. The request executes in turn the helloGet method of the HelloResource service resource.

POSTing to HelloResource

$ curl -D- -X POST http://localhost:9080/LibertyJaxRsWeb/rest/hello
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0
Content-Type: application/atom+xml
X-Resource-Architect: Jacek Laskowski
Content-Length: 53
Date: Mon, 01 Apr 2013 13:58:20 GMT
Server: WebSphere Application Server
 
[POST] Hello from JAX-RS on WebSphere Liberty Profile

Note the X-Resource-Architect: Jacek Laskowski header and the output itself. The result came from executing the helloPost method of the HelloResource service resource.

Requesting WADL service description with OPTIONS - HelloResource

In Using WADL to generate service documentation you can read that "a WADL document can be requested for a particular resource by invoking an HTTP OPTIONS request for any Java API for RESTful Web Services (JAX-RS) URL".

Web Application Description Language (WADL) is described at http://www.w3.org/Submission/wadl/.

The below output from running curl against the hello resource was manually pretty-formatted to easy reading.

$ curl -D- -X OPTIONS http://localhost:9080/LibertyJaxRsWeb/rest/hello
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0
Allow: POST, GET, OPTIONS, HEAD
Content-Type: application/vnd.sun.wadl+xml
Content-Language: en-US
Content-Length: 392
Date: Tue, 02 Apr 2013 15:06:47 GMT
Server: WebSphere Application Server
 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://wadl.dev.java.net/2009/02">
  <resources base="http://localhost:9080/LibertyJaxRsWeb/rest/">
    <resource path="hello">
      <method name="POST">
        <response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
      </method>
      <method name="GET">
        <response status="200" />
      </method>
    </resource>
  </resources>
</application>

Note the Allow response header whose value is the set of HTTP methods supported by the resource.

POSTing multipart/form-data to MultipartResource

For the MultipartResource case we're going to use WizTools RESTClient with http://localhost:9080/LibertyJaxRsWeb/rest/multipart.

As of this writting there's the 3.1 version available. Download restclient-ui-3.1-jar-with-dependencies.jar and run it with java -jar command as described in the Running document.

Specify POST in the Method tab as well as appropriate body in the Body tab. Click the two-green-arrow button to execute the resource.

Liberty-jaxrs-wiztools-restclient-post-multipart-response.png

Requesting WADL service description with OPTIONS - MultipartResource

$ curl -X OPTIONS http://localhost:9080/LibertyJaxRsWeb/rest/multipart
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://wadl.dev.java.net/2009/02">
  <resources base="http://localhost:9080/LibertyJaxRsWeb/rest/">
    <resource path="multipart">
      <method name="GET">
        <response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
      </method>
      <method name="POST">
        <response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" />
      </method>
    </resource>
  </resources>
</application>

That's all there is to it. Thanks for participating.

Questions? Suggestions? Ideas? You're very welcome to send me an email to jacek@japila.pl. I'd appreciate it. Thanks!

Osobiste
Przestrzenie nazw

Warianty
Działania
Nawigacja
Narzędzia