It is quite possible many developers have run into this problem with Jersey, not really a problem, but limitations of a programming language. I remember from school days where C++ Templates had quite a few reference books and it always kept me away from using STL containers 🙂

In Java, we have Generics since 1.5 which looks lot like C++ Templates, but they are not the same. I am not going to cover the details here, just google it. But, Generics have grown in such complexity that it has dedicated 500+ pages FAQ written and maintained by Angelika Langer for years (JLS 3rd edition is only 684 pages).

Long story short: Generics provides compile time type safety and thus eliminating the need for casts. It is achieved through a compile time phenomenon called type erasure. The Generics FAQ explains everything in detail and it is the Java Generics Bible at least for me.

There are cases when we need to return parameterized types from a JAXRS resource method in the Response. Due to type erasure, it requires special handling in Jersey runtime to determine the generic type that is required to select a suitable MessageBodyWriter.

There are couple options available for JAX-RS developers using Jersey and I am going discuss each one of them in detail.

Let us consider a simple domain model, Employee.

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "employee")
public class EmployeeBean {
    private Long id;
    private String firstName;
    private String lastName;

    public EmployeeBean() {
        // required for JAXB
    }

    public EmployeeBean(Long id, String firstName, String lastName) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

The employee resource shows an example implementation.

@Path("/employees")
public class EmployeeResource {

    @GET
    public Collection<EmployeeBean> getEmployees() {
        EmployeeBean emp = new EmployeeBean(1L, "John", "Doe");
        return Collections.singletonList(emp);
    }
}

In this case, we return the Collection of EmployeeBean from the resource method. The following XML is produced on accessing this resource at http://localhost:9998/employees.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employeeBeans>
    <employee>
        <firstName>John</firstName>
        <id>1</id>
        <lastName>Doe</lastName>
    </employee>
</employeeBeans>

I would expect to see the list of employees inside <employees> tag instead of <employeeBeans> tag. Hmm, it requires some tweaks to produce that format. So, lets write Employees POJO which embeds the Collection.

@XmlRootElement
public class Employees {
    private List<EmployeeBean> employee;

    public Employees(List<EmployeeBean> employee) {
        this.employee = employee;
    }

    public Employees() {
        // required for JAXB
    }

    public List<EmployeeBean> getEmployee() {
        return employee;
    }

    public void setEmployee(List<EmployeeBean> employee) {
        this.employee = employee;
    }
}

Let us add couple methods to the EmployeeResource using Customers POJO that produces a more relevant XML.

    @GET
    @Path("test1")
    public Employees getEmployees1() {
        EmployeeBean emp = new EmployeeBean(1L, "John", "Doe");
        Employees employees = new Employees(Collections.singletonList(emp));
        return employees;
    }

    @GET
    @Path("test2")
    public Response getEmployees2() {
        EmployeeBean emp = new EmployeeBean(1L, "John", "Doe");
        Employees employees = new Employees(Collections.singletonList(emp));
        return Response.ok(employees).build();
    }

Now, accessing http://localhost:9998/employees/test1 or http://localhost:9998/employees/test2 should produce the following XML.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employees>
    <employee>
        <firstName>John</firstName>
        <id>1</id>
        <lastName>Doe</lastName>
    </employee>
</employees>

But, do we need this silly logic to produce this output? Not anymore, this has been improved in Jersey 1.2 release. Enabling FEATURE_XMLROOTELEMENT_PROCESSING feature in resource configuration should produce this format out of the box. So, accessing http://localhost:9998/employees/test1 should produce this format of XML. This property is disabled by default.

Now, lets dive into our actual problem of type erasure in case of a parameterized type returned in the JAX-RS Response. I have added another method to our EmployeeResource.

    @GET
    @Path("test3")
    @Produces(MediaType.APPLICATION_XML)
    public Response getEmployees3() {
        EmployeeBean emp = new EmployeeBean(1L, "John", "Doe");
        List<EmployeeBean> list = new ArrayList<EmployeeBean>();
        list.add(emp);
        return Response.ok(list).build();
    }

Now, accessing this method at http://localhost:9998/employees/test3 should spit the following exception. I believe this exception trace is familiar to most Jersey/JAX-RS users.

SEVERE: A message body writer for Java class java.util.ArrayList, and Java type class java.util.ArrayList, and MIME media type application/xml was not found
Jul 24, 2010 11:58:55 PM com.sun.jersey.spi.container.ContainerResponse write
SEVERE: The registered message body writers compatible with the MIME media type are:
application/xml ->
  com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$App
  com.sun.jersey.core.impl.provider.entity.DocumentProvider
  com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter
  com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$App
  com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$App
*/* ->
  com.sun.jersey.core.impl.provider.entity.FormProvider
  com.sun.jersey.server.impl.template.ViewableMessageBodyWriter
  com.sun.jersey.core.impl.provider.entity.StringProvider
  com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
  com.sun.jersey.core.impl.provider.entity.FileProvider
  com.sun.jersey.core.impl.provider.entity.InputStreamProvider
  com.sun.jersey.core.impl.provider.entity.DataSourceProvider
  com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.ReaderProvider
  com.sun.jersey.core.impl.provider.entity.DocumentProvider
  com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider
  com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter
  com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General

Jul 24, 2010 11:58:55 PM com.sun.jersey.spi.container.ContainerResponse traceException
SEVERE: Mapped exception to response: 500 (Internal Server Error)
javax.ws.rs.WebApplicationException

To fix this, we need to somehow tell the JAX-RS runtime the type of the response entity, in this case a Collection of Employees. JAX-RS API GenericEntity comes to the rescue. GenericEntity can be used to represent a response entity of a generic type. The EmployeeResource method is updated to use the GenericEntity class when returning a Collection type.

    @GET
    @Path("test4")
    @Produces(MediaType.APPLICATION_XML)
    public Response getEmployees4() {
        EmployeeBean emp = new EmployeeBean(1L, "John", "Doe");
        List<EmployeeBean> list = new ArrayList<EmployeeBean>();
        list.add(emp);
        GenericEntity entity = new GenericEntity<List<EmployeeBean>>(list) {};
        return Response.ok(entity).build();
    }

Accessing http://localhost:9998/employees/test4 should produce the desired output.

In addition to this approach, Jersey 1.2 introduced a new API JResponse to support this better. JResponse is a type safe alternative to Response that preserves the type information of response entity thus it is not necessary to utilize GenericEntity.

The updated Employee resource using JResponse is shown below.

    @GET
    @Path("test5")
    @Produces(MediaType.APPLICATION_XML)
    public JResponse<List<EmployeeBean>> getEmployees5() {
        EmployeeBean emp = new EmployeeBean(1L, "John", "Doe");
        List<EmployeeBean> list = new ArrayList<EmployeeBean>();
        list.add(emp);
        return JResponse.ok(list).build();
    }

Accessing http://localhost:9998/employees/test5 should produce the desired output.

Both these approaches are easy to implement. The major difference is GenericEntity is a JAX-RS API while JResponse is a Jersey API, which may not work with other JAX-RS implementations and thus not portable. If you are just using Jersey, then JResponse is the preferred way as it is type safe and provides all capabilities of the Response.

Here is the Server code that uses Grizzly (provided for completion) :

import com.sun.grizzly.http.SelectorThread;
import com.sun.jersey.api.container.grizzly.GrizzlyWebContainerFactory;
import com.sun.jersey.core.util.FeaturesAndProperties;

import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;

public class Main {

    private static int getPort(int defaultPort) {
        String port = System.getenv("JERSEY_HTTP_PORT");
        if (null != port) {
            try {
                return Integer.parseInt(port);
            } catch (NumberFormatException e) {
            }
        }
        return defaultPort;
    }

    private static URI getBaseURI() {
        return UriBuilder.fromUri("http://localhost/").port(getPort(9998)).build();
    }

    public static final URI BASE_URI = getBaseURI();

    protected static SelectorThread startServer() throws IOException {
        final Map<String, String> initParams = new HashMap<String, String>();

        initParams.put("com.sun.jersey.config.property.packages", "com.employee.resources");
        initParams.put(FeaturesAndProperties.FEATURE_XMLROOTELEMENT_PROCESSING, "true");

        System.out.println("Starting grizzly...");
        SelectorThread threadSelector = GrizzlyWebContainerFactory.create(BASE_URI, initParams);
        return threadSelector;
    }

    public static void main(String[] args) throws IOException {
        SelectorThread threadSelector = startServer();
        System.out.println(String.format("Jersey app started with WADL available at "
                + "%sapplication.wadl\nTry out %shelloworld\nHit enter to stop it...",
                BASE_URI, BASE_URI));
        System.in.read();
        threadSelector.stopEndpoint();
    }
}

I hope this clarifies some of the underlying behavior of handling parameterized types in JAX-RS applications.

Possibly Related Posts:


SSL enabled RESTful services are quite easier to develop and test using Jersey, Grizzly and RestTemplate.

Jersey (resource development)
Grizzly Web Server (resource configuration and deployment)
Spring 3 RestTemplate backed by Commons HTTP Client (resource access)

In a moment, you will notice how all these nicely fit the bill. Let us start with the POM for the maven fans.

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>org.springframework.web</artifactId>
            <version>3.0.0.M4</version>
        </dependency>
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.1.2-ea</version>
        </dependency>
        <dependency>
            <groupId>com.sun.grizzly</groupId>
            <artifactId>grizzly-servlet-webserver</artifactId>
            <version>1.9.18a</version>
        </dependency>
        <dependency>
            <groupId>org.apache.log4j</groupId>
            <artifactId>com.springsource.org.apache.log4j</artifactId>
            <version>1.2.15</version>
        </dependency>
    </dependencies>

Configuring Log4j is very useful as you could see the commons Client debug messages and http wire headers which are quite useful for debugging in case if you were lost in translation.

Putting together all these pieces working did not take much of my time. I did not have to do anything fancy here as I just reused most of the sample code from the Jersey HTTPS sample and Commons HTTP Client SSL sample.

Lets dive into the Spring Config, which does most of the wiring of HTTP Client and RestTemplate.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="sslClient" class="spring3.restclient.RestSSLClient">
        <constructor-arg ref="restTemplate"/>
        <constructor-arg ref="credentials"/>
    </bean>

    <bean id="httpClientParams" class="org.apache.commons.httpclient.params.HttpClientParams">
        <property name="authenticationPreemptive" value="true"/>
        <property name="connectionManagerClass"
                  value="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager"/>
    </bean>
    <bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
        <constructor-arg ref="httpClientParams"/>
    </bean>
    <bean id="credentials" class="org.apache.commons.httpclient.UsernamePasswordCredentials">
        <constructor-arg value="admin"/>
        <constructor-arg value="adminadmin"/>
    </bean>
    <bean id="httpClientFactory" class="org.springframework.http.client.CommonsClientHttpRequestFactory">
        <constructor-arg ref="httpClient"/>
    </bean>

    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
        <constructor-arg ref="httpClientFactory"/>
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            </list>
        </property>
    </bean>
</beans>

The below code configures a Grizzly Server with SSL support for server side certificates, Basic Auth filter and Jersey resource servlet.

import com.sun.grizzly.SSLConfig;
import com.sun.grizzly.http.embed.GrizzlyWebServer;
import com.sun.grizzly.http.servlet.ServletAdapter;
import com.sun.jersey.api.container.filter.RolesAllowedResourceFilterFactory;
import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.spi.container.servlet.ServletContainer;
import com.sun.jersey.samples.https_grizzly.auth.SecurityFilter;

import javax.ws.rs.core.UriBuilder;
import java.io.IOException;
import java.net.URI;

public class GrizzlyServer {

    private static GrizzlyWebServer webServer;

    public static final URI BASE_URI = getBaseURI();

    private static URI getBaseURI() {
        return UriBuilder.fromUri("https://localhost/").port(getPort(4463)).build();
    }

    private static int getPort(int defaultPort) {
        String port = System.getenv("JERSEY_HTTP_PORT");
        if (null != port) {
            try {
                return Integer.parseInt(port);
            } catch (NumberFormatException e) {
            }
        }
        return defaultPort;
    }

    protected static void startServer() {

        webServer = new GrizzlyWebServer(getPort(4463), ".", true);

        // add Jersey resource servlet

        ServletAdapter jerseyAdapter = new ServletAdapter();
        jerseyAdapter.addInitParameter("com.sun.jersey.config.property.packages", "server.https.auth;server.https.resource");
        jerseyAdapter.setContextPath("/");
        jerseyAdapter.setServletInstance(new ServletContainer());

        // add security filter (which handles http basic authentication)
        jerseyAdapter.addInitParameter(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, SecurityFilter.class.getName());
        // add authorization filter
        jerseyAdapter.addInitParameter(ResourceConfig.PROPERTY_RESOURCE_FILTER_FACTORIES, RolesAllowedResourceFilterFactory.class.getName());

        webServer.addGrizzlyAdapter(jerseyAdapter, new String[]{"/"});


        // Grizzly ssl configuration
        SSLConfig sslConfig = new SSLConfig();

        sslConfig.setNeedClientAuth(true); // don't work - known grizzly bug, will be fixed in 2.0.0

        // set up security context
        String keystore_server = Thread.currentThread().getContextClassLoader().getResource("keystore_server").getFile();
        String truststore_server = Thread.currentThread().getContextClassLoader().getResource("truststore_server").getFile();

        sslConfig.setKeyStoreFile(keystore_server); // contains server keypair
        sslConfig.setKeyStorePass("secret");
        sslConfig.setTrustStoreFile(truststore_server); // contains client certificate
        sslConfig.setTrustStorePass("secret");

        webServer.setSSLConfig(sslConfig);

        // turn server side client certificate authentication on

//        ((SSLSelectorThread) webServer.getSelectorThread()).setNeedClientAuth(true);

        try {
            // start Grizzly embedded server //
            System.out.println(String.format("Jersey app started with WADL at %sapplication.wadl", BASE_URI));
            webServer.start();
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }

    protected static void stopServer() {
        webServer.stop();
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        startServer();
        System.out.println("Hit return to stop...");
        System.in.read();
        stopServer();
    }
}

Here’s slightly modified version of the sample Jersey Security filter which would handle the HTTP basic authentication on the server. The auth helper classes (AuthenticationExceptionMapper, AuthenticationException) are found here.

package com.sun.jersey.samples.https_grizzly.auth;

import com.sun.jersey.api.container.MappableContainerException;
import com.sun.jersey.core.util.Base64;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerRequestFilter;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;
import java.security.Principal;

public class SecurityFilter implements ContainerRequestFilter {

    @Context
    UriInfo uriInfo;
    private static final String REALM = "HTTPS Example authentication";

    public ContainerRequest filter(ContainerRequest request) {
        User user = authenticate(request);
        request.setSecurityContext(new Authorizer(user));
        return request;
    }

    private User authenticate(ContainerRequest request) {
        // Extract authentication credentials
        String authentication = request.getHeaderValue(ContainerRequest.AUTHORIZATION);
        if (authentication == null) {
            throw new MappableContainerException
                    (new AuthenticationException("Authentication credentials are required", REALM));
        }
        if (!authentication.startsWith("Basic ")) {
            return null;
            // additional checks should be done here
            // "Only HTTP Basic authentication is supported"
        }
        authentication = authentication.substring("Basic ".length());
        String[] values = new String(Base64.base64Decode(authentication)).split(":");
        if (values.length < 2) {
            throw new WebApplicationException(400);
            // "Invalid syntax for username and password"
        }
        String username = values&#91;0&#93;;
        String password = values&#91;1&#93;;
        if ((username == null) || (password == null)) {
            throw new WebApplicationException(400);
            // "Missing username or password"
        }

        // Validate the extracted credentials
        User user = null;

        if (username.equals("john") && password.equals("secret")) {
            user = new User("john", "user");
            System.out.println("USER 'John Doe' AUTHENTICATED");
        } else if (username.equals("jane") && password.equals("secret")) {
            user = new User("jane", "user");
            System.out.println("USER 'Jane Doe' AUTHENTICATED");
        } else if (username.equals("admin") && password.equals("adminadmin")) {
            user = new User("admin", "admin");
            System.out.println("ADMIN AUTHENTICATED");
        } else {
            System.out.println("USER NOT AUTHENTICATED");
            throw new MappableContainerException(new AuthenticationException("Invalid username or password\r\n", REALM));
        }
        return user;
    }

    public class Authorizer implements SecurityContext {

        private User user;
        private Principal principal;

        public Authorizer(final User user) {
            this.user = user;
            this.principal = new Principal() {

                public String getName() {
                    return user.username;
                }
            };
        }

        public Principal getUserPrincipal() {
            return this.principal;
        }

        public boolean isUserInRole(String role) {
            return (role.equals(user.role));
        }

        public boolean isSecure() {
            return "https".equals(uriInfo.getRequestUri().getScheme());
        }

        public String getAuthenticationScheme() {
            return SecurityContext.BASIC_AUTH;
        }
    }

    public class User {

        public String username;
        public String role;

        public User(String username, String role) {
            this.username = username;
            this.role = role;
        }
    }
}
&#91;/sourcecode&#93;

The resource class is very simple. The resource methods are access controlled using the JSR-250 annotation @RolesAllowed. The methods are self-explanatory and they are just coded for illustration, not a fool-proof implementation. In this sample, the Grizzly server would perform server-side certificate authentication and HTTP Basic authentication, in addition to basic authorization checks.

&#91;sourcecode language='java'&#93;
import com.sun.jersey.core.util.Base64;

import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/")
public class HttpsResource {

    @GET
    @RolesAllowed({"admin"})
    @Path("/locate/{username}")
    public Response getUserLocation(@Context HttpHeaders headers, @PathParam("username") String username) {
        // you can get username from HttpHeaders
        System.out.println("Service: GET / User Location for : " + username + " requested by " + getUser(headers));
        return Response.ok("Billings, Montana").type(MediaType.TEXT_PLAIN).build();
    }

    @GET
    @RolesAllowed({"admin", "user"})
    public Response getUserPin(@Context HttpHeaders headers) {
        // you can get username from HttpHeaders
        System.out.println("Service: GET / User Pin for: " + getUser(headers));
        return Response.ok("1234").type(MediaType.TEXT_PLAIN).build();
    }

    private String getUser(HttpHeaders headers) {
        String auth = headers.getRequestHeader("authorization").get(0);

        auth = auth.substring("Basic ".length());
        String&#91;&#93; values = new String(Base64.base64Decode(auth)).split(":");

        String username = values&#91;0&#93;;
        String password = values&#91;1&#93;;

        return username;
    }
}
&#91;/sourcecode&#93;

The following steps guide to create sample client and server certificates using the JDK keytool utility. The self-signed certificates are used for demonstration purposes only. In reality, this would be performed by a Certificate Authority (for ex: Verisign).

<strong><ul>generate client and server keys:</ul></strong>

keytool -genkey -keystore keystore_client -alias clientKey -dname "CN=www.aruld.info, OU=R&D, O=Vasun Technologies, L=Billings, ST=Montana, C=US"
keytool -genkey -keystore keystore_server -alias serverKey -dname "CN=www.aruld.info, OU=R&D, O=Vasun Technologies, L=Billings, ST=Montana, C=US"

<strong><ul>generate client and server certificates:</ul></strong>

keytool -export -alias clientKey -rfc -keystore keystore_client > client.cert
keytool -export -alias serverKey -rfc -keystore keystore_server > server.cert

<strong><ul>import certificates to corresponding truststores:</ul></strong>

keytool -import -alias clientCert -file client.cert -keystore truststore_server
keytool -import -alias serverCert -file server.cert -keystore truststore_client


SSL helper classes (AuthSSLProtocolSocketFactory, AuthSSLX509TrustManager, AuthSSLInitializationError) for the client-side are used from the Commons Client SSL <a href="http://svn.apache.org/viewvc/httpcomponents/oac.hc3x/trunk/src/contrib/org/apache/commons/httpclient/contrib/ssl/">contrib</a> samples.

RestTemplate is injected into the RestSSLClient which uses the Commons Client APIs to set the credentials and configures the keystore and truststore on the client-side.


import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.contrib.ssl.AuthSSLProtocolSocketFactory;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.springframework.http.client.CommonsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.net.MalformedURLException;
import java.net.URL;
import java.net.URISyntaxException;
import java.util.Map;
import java.util.HashMap;

public class RestSSLClient {
    private final RestTemplate restTemplate;
    private final HttpClient client;
    private Credentials credentials;
    private static final int HTTPS_PORT = 4463;
    private static final String HTTPS_GET = "https://localhost:4463/";
    private static final String HTTPS_GET_LOCATION = "https://localhost:4463/locate/{username}";
    private static final String HTTPS = "https";
    private static final String HTTPS_HOST = "localhost";

    public RestSSLClient(RestTemplate restTemplate, Credentials credentials) {
        this.restTemplate = restTemplate;
        this.credentials = credentials;
        CommonsClientHttpRequestFactory factory = (CommonsClientHttpRequestFactory) restTemplate.getRequestFactory();
        this.client = factory.getHttpClient();
        client.getState().setCredentials(AuthScope.ANY, credentials);
        try {
            URL keystore_client = Thread.currentThread().getContextClassLoader().getResource("keystore_client").toURI().toURL();
            URL truststore_client = Thread.currentThread().getContextClassLoader().getResource("truststore_client").toURI().toURL();
            ProtocolSocketFactory protocolSocketFactory = new AuthSSLProtocolSocketFactory(keystore_client, "secret",
                    truststore_client, "secret");
            Protocol authhttps = new Protocol(HTTPS, protocolSocketFactory, HTTPS_PORT);
            Protocol.registerProtocol(HTTPS, authhttps);
            client.getHostConfiguration().setHost(HTTPS_HOST, HTTPS_PORT, authhttps);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    public void setCredentials(String user, String pass) {
        this.credentials = new UsernamePasswordCredentials(user, pass);
        client.getState().setCredentials(AuthScope.ANY, credentials);
    }

    public String get() {
        return restTemplate.getForObject(HTTPS_GET, String.class);
    }

    public String getLocation(String user) {
        Map<String, String> vars = new HashMap<String, String>();
        vars.put("username", user);
        return restTemplate.getForObject(HTTPS_GET_LOCATION, String.class, vars);
    }
}

The test code which invokes the SSL configured resource is shown below.

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

public class Spring3RestSSLClient {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-ssl.xml");
        RestSSLClient client = applicationContext.getBean("sslClient", RestSSLClient.class);
        System.out.println("John's Location : " + client.getLocation("john"));
        System.out.println("Jane's Location : " + client.getLocation("jane"));
        client.setCredentials("john", "secret");
        System.out.println("John Doe's Pin : " + client.get());
        client.setCredentials("jane", "secret");
        System.out.println("Jane Doe's Pin : " + client.get());
    }
}

WADL for this resource can be accessed from https://localhost:4463/application.wadl. You could access the URL from a browser as the server side client certificate authentication is disabled in the GrizzlyServer. (Uncommenting line # 70 would enable server side client cert auth, but this would force the browser to use the generated client keys). Test it yourself, you would be presented with a basic auth dialog (valid user/pass/role: admin/adminadmin/admin, john/secret/user, jane/secret/user) and you could access the resource methods with specified roles. I have tested with Firefox and Chrome. Enjoy!

Possibly Related Posts:


The central API for accessing RESTful services in Spring 3 is RestTemplate. It is like any other template mechanism provided by Spring for the client side access. The default implementation uses the java.net package for creating HTTP requests. RestTemplate can be backed by Commons HttpClient using ClientHttpRequestFactory. Using Commons HttpClient as the backend implementation supports basic authentication in the requests. The javadocs were the single source of information for Spring3 REST support until M2, but you can find the latest reference documentation with M3 release here. Chapter 18 covers REST support in Spring 3. You can also read Arjen’s blog posts here and here which outlines the REST support in Spring 3 both on the server-side and client-side.

I was playing with the RestTemplate and was quite impressed with it as it comes handy for Spring developers. But, this implementation is no different than most other REST Client APIs. Long story short, this is yet another attempt to provide a non-standard Client for accessing RESTful resources. I am leaning more towards the need for a standard JAX-RS client API and I hope JAX-RS 2.0 fuels that interest. Lets explore with an example how Spring 3 provides native support for accessing RESTful resources using RestTemplate.

Twitter is one of the most widely used service which has a decent REST API with basic authentication.

Lets start with the POM dependencies. I had built the latest Spring3 M3 snapshot on my box, but you should be able to fetch them from Spring maven snapshots repository.

<repositories>
    <repository>
        <id>SpringSource Enterprise Bundle Repository - External Bundle Milestones</id>
        <url>http://repository.springsource.com/maven/bundles/milestone</url>
    </repository>
    <repository>
        <id>SpringSource Enterprise Bundle Repository - SpringSource Bundle Releases</id>
        <url>http://repository.springsource.com/maven/bundles/release</url>
    </repository>
    <repository>
        <id>SpringSource Enterprise Bundle Repository - External Bundle Releases</id>
        <url>http://repository.springsource.com/maven/bundles/external</url>
    </repository>
</repositories>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.6</source>
                <target>1.6</target>
            </configuration>
        </plugin>
    </plugins>
</build>
<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>org.springframework.web</artifactId>
        <version>3.0.0.M3</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.ws</groupId>
        <artifactId>org.springframework.xml</artifactId>
        <version>1.5.5.A</version>
    </dependency>
    <dependency>
        <groupId>org.apache.log4j</groupId>
        <artifactId>com.springsource.org.apache.log4j</artifactId>
        <version>1.2.15</version>
    </dependency>
    <dependency>
        <groupId>commons-httpclient</groupId>
        <artifactId>commons-httpclient</artifactId>
        <version>3.1</version>
    </dependency>
</dependencies>

The Spring configuration defines the beans required for this sample.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:oxm="http://www.springframework.org/schema/oxm"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">
    <bean id="twitterClient" class="spring3.restclient.TwitterClient">
        <constructor-arg ref="restTemplate"/>
        <constructor-arg ref="credentials"/>
    </bean>

    <bean id="httpClientParams" class="org.apache.commons.httpclient.params.HttpClientParams">
        <property name="authenticationPreemptive" value="true"/>
        <property name="connectionManagerClass"
                  value="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager"/>
    </bean>
    <bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
        <constructor-arg ref="httpClientParams"/>
    </bean>
    <bean id="credentials" class="org.apache.commons.httpclient.UsernamePasswordCredentials">
        <constructor-arg value="username"/>
        <constructor-arg value="password"/>
    </bean>
    <bean id="httpClientFactory" class="org.springframework.http.client.CommonsClientHttpRequestFactory">
        <constructor-arg ref="httpClient"/>
    </bean>

    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
        <constructor-arg ref="httpClientFactory"/>

        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                    <property name="marshaller" ref="jaxbMarshaller"/>
                    <property name="unmarshaller" ref="jaxbMarshaller"/>
                </bean>
                <bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
            </list>
        </property>
    </bean>

    <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="classesToBeBound">
            <list>
                <value>twitter.model.Statuses</value>
            </list>
        </property>
    </bean>
</beans>

MarshallingHttpMessageConverter is used to marshal/unmarshal JAXB beans. Statuses is a JAXB bean which is bound to the response returned by GET on the Twitter URI https://twitter.com/statuses/friends_timeline.xml. FormHttpMessageConverter is used to construct form parameters to POST on the Twitter URI https://twitter.com/statuses/update.xml.

Now, we will see the RestTemplate in action. You can see the code is just a one liner.

import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.auth.AuthScope;
import org.springframework.http.client.CommonsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import org.springframework.util.MultiValueMap;
import org.springframework.util.LinkedMultiValueMap;
import twitter.model.Statuses;

import java.util.HashMap;
import java.util.Map;

public class TwitterClient {

    private final RestTemplate restTemplate;

    private final Credentials credentials;

    private static final String twitterGet = "https://twitter.com/statuses/friends_timeline.xml?count={count}";
    private static final String twitterPost = "https://twitter.com/statuses/update.xml";

    public TwitterClient(RestTemplate restTemplate, Credentials credentials) {
        this.restTemplate = restTemplate;
        this.credentials = credentials;
        CommonsClientHttpRequestFactory factory = (CommonsClientHttpRequestFactory) restTemplate.getRequestFactory();
        HttpClient client = factory.getHttpClient();
        client.getState().setCredentials(AuthScope.ANY, credentials);
    }

    public Statuses getStatuses() {
        Map<String, String> vars = new HashMap<String, String>();
        vars.put("count", "5");
        return restTemplate.getForObject(twitterGet, Statuses.class, vars);
    }

    public void setStatus(String status) {
        MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
        map.add("status", status);
        restTemplate.postForLocation(twitterPost, map);
    }
}

The test code which posts the status to your Twitter account is shown below.

public class Spring3RestClientTest {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        TwitterClient twitter = applicationContext.getBean("twitterClient", TwitterClient.class);
        twitter.setStatus("Spring RestTemplate rocks!");
        Statuses statuses = twitter.getStatuses();
        for (Statuses.Status status : statuses.getStatus()) {
            System.out.println("Text : " + status.getText());
            System.out.println("User : " + status.getUser().getScreenName());
        }
    }
}

Here is an example output of the above test which lists recent five status messages from Twitter:
=====================================================
Text : Spring RestTemplate rocks!
User : aruld
Text : Just finished celebrating with the SpringSource & Hyperic teams at Tres Agaves. Really good to meet everyone! http://twitpic.com/4l1hb
User : cbeams
Text : 8 Java Puzzlers for JavaOne done. Wow. Soon we’ll scrape right through the bottom of the barrel.
User : gafter
Text : Disappointed my Maredsous 8 is all gone. I should’ve bought more.
User : dandiep
Text : Headed to San Francisco for a week of Core Spring training & looking forward to it!
User : cbeams
=====================================================

RestTemplate does serves its purpose, but it could be improved to support additional convenient methods for accessing URIs with query parameters. The other thing I noticed is about making HTTP POST with a name-value pair using postForLocation API. I could not find any details from the documentation so far. For instance, I would like to do a post to the URI http://twitter.com/statuses/update.xml with the form data “status=This is my current status” sent in the HTTP body. I am not sure whether this is possible with the current implementation. I will dig into this further and keep posted on what I find.

Update (5/4): Thanks to Arjen for clarifying the URITemplate use within query parameters and the FormHttpMessageConverter for using Form parameters. The blog has been updated to use these techniques. You could POST a twitter message just fine 🙂

Update (5/10): Updated the reference documentation to the official M3 build from SpringSource and updated the maven POM to use the M3 dependency.

Possibly Related Posts:


Jersey 1.0.3 was released this week. This release has quite a few interesting new features and improvements to some of its existing functionality. Paul’s blog entry gives the specifics of this release. One of the cool features in this release is the ability to inject WadlApplicationContext in resources. This provides access to the WADL JAXB representation for your restful application. Paul already discussed about its usage in the Jersey dev mailing list. I wanted to see all these in action and you won’t believe that it took just few minutes to see styled WADL documentation in action.

The following URI paths renders XSL styled WADL documentation for resources :

http://localhost:9998/application.wadl

http://localhost:9998/wadl

Here is a preview of the documentation (This works in Chrome out of the box, no luck with Firefox and IE):

Jersey WADL documentation

I used Mark’s WADL to HTML documentation stylesheet for styling the documentation.

The HTTP response for WADL GET recorded by Firebug:

HTTP Response for WADL GET

Here is the POM for interested:

    <dependencies>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.1.10</version>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.0.3</version>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey.test.framework</groupId>
            <artifactId>jersey-test-framework</artifactId>
            <version>1.0.3</version>
            <scope>test</scope>
        </dependency>

The WadlResource below shows how the WadlApplicationContext injection happens and the JAXBContext is retrieved from WadlApplicationContext. The marshaller allows you to set the property which can be used to specify an XML preamble, in this case WADL to HTML documentation stylesheet embedded in the XML headers. The rest all is the usual stuff you know.

@Produces({"application/vnd.sun.wadl+xml", "application/xml"})
@Singleton
@Path("wadl")
public class WadlResource {

    private static final Logger LOGGER = Logger.getLogger(WadlResource.class.getName());

    private static final String XML_HEADERS = "com.sun.xml.bind.xmlHeaders";

    private WadlApplicationContext wadlContext;

    private Application application;

    private byte[] wadlXmlRepresentation;

    public WadlResource(@Context WadlApplicationContext wadlContext) {
        this.wadlContext = wadlContext;
        this.application = wadlContext.getApplication();
    }

    @GET
    public synchronized Response getWadl(@Context UriInfo uriInfo) {
        if (wadlXmlRepresentation == null) {
            if (application.getResources().getBase() == null) {
                application.getResources().setBase(uriInfo.getBaseUri().toString());
            }
            try {
                final Marshaller marshaller = wadlContext.getJAXBContext().createMarshaller();
                marshaller.setProperty(XML_HEADERS, "<?xml-stylesheet type='text/xsl' href='http://www.mnot.net/webdesc/wadl_documentation.xsl'?>");
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                final ByteArrayOutputStream os = new ByteArrayOutputStream();
                marshaller.marshal(application, os);
                wadlXmlRepresentation = os.toByteArray();
                os.close();
            } catch (Exception e) {
                LOGGER.log(Level.WARNING, "Could not marshal wadl Application.", e);
                return javax.ws.rs.core.Response.ok(application).build();
            }
        }
        return Response.ok(new ByteArrayInputStream(wadlXmlRepresentation)).build();
    }
}

MyWadlResource extends from WadlResource with the relative URL at “application.wadl”. There is already a patch submitted by James Strachan which will allow using WADL with implicit views. I hope this becomes available for the next 1.1.0-ea release.

@Path("application.wadl")
public class MyWadlResource extends WadlResource {
  public MyWadlResource(@Context WadlApplicationContext wadlContext) {
    super(wadlContext);
  }
}

The usual standalone Server code is shown below.

public class Server {
    public static void main(String[] args) throws IOException {
        final String baseUri = "http://localhost:9998/";
        final Map<String, String> initParams = new HashMap<String, String>();
        initParams.put("com.sun.jersey.config.property.packages", "jersey.wadl.resources");
        System.out.println("Starting grizzly...");
        SelectorThread threadSelector = GrizzlyWebContainerFactory.create(baseUri, initParams);
        System.out.println(String.format("Jersey app started with WADL available at %sapplication.wadl or %swadl\n"
                + "Try out %s\nHit enter to stop it...", baseUri, baseUri, baseUri));
        System.in.read();
        threadSelector.stopEndpoint();
        System.exit(0);
    }
}

Here is a simple test written using the new Jersey test framework and by default it deploys the resources to the Grizzly container. The Application class is serialized as a JAXB bean. You then have access to all the WADL components.

public class WadlTest extends JerseyTest {

  public WadlTest() throws Exception {
    super("jersey.wadl.resources");
  }

  @Test
  public void wadlGet() {
    ClientResponse cr = webResource.path("wadl").get(ClientResponse.class);
    Application a = cr.getEntity(com.sun.research.ws.wadl.Application.class);
    Method m = (Method)a.getResources().getResource().get(0).getMethodOrResource().get(0);
    Response r = m.getResponse();
    List<JAXBElement<RepresentationType>> representations = r.getRepresentationOrFault();
    for (JAXBElement<RepresentationType> representation : representations) {
      RepresentationType type = representation.getValue();
      System.out.println("MediaType : " + type.getMediaType());
    }
  }
}

The other notable support in this release is integration with Guice 2.0. Maturity and quality is always the driving factor behind every Jersey release. No compromises whatsoever. Well done Paul and team!

The project sources can be downloaded from here.

Possibly Related Posts:


LoanDB is a loan originations system reference implementation. This project will be developed using Java technology frameworks such as Spring (Web Beans in future?), Hibernate (JPA), CXF (JAXWS) and Jersey (JAXRS). The concepts are based on my original toy implementation for the loan processing NetBeans tutorial. The tutorial was primarily focused on developing JPA and web services based applications in NetBeans IDE, so you won’t find the real meat. I am thinking of designing various modules around the LoanDB core and I am expecting this to be more useful for Java developers in understanding how these frameworks help in solving traditional enterprise application integration problems and further help in developing less maintainable code, which is rather more critical in enterprises. Loan Originations system is a very good candidate for implementing SOA based solution and typically involves integration with many heterogeneous systems within network and outside the network. This is going to be real fun developing this project.

I plan to blog more about the frameworks used in this project shortly. Currently, I am in the process of designing the persistence layer, which is the core of this project. Some prototype code out there in SVN. But remember, right now there are too many moving parts before I flush out something concrete, so I have no release plans yet 🙂

Possibly Related Posts:


Spring Framework 3.0 M1 was released last week during the SpringOne Americas event, which looks very promising with EL and REST becoming top themes. Lot of coverage on the event has been blogged, and you can find one of my favorite entry by Solomon here. Juergen outlines some of the new features implemented in this milestone release here.

SVN repository for Spring Framework 3.0 is hosted by SpringSource at https://src.springframework.org/svn/spring-framework/trunk.
The build requires JDK 6, but Spring Framework 3.0 requires Java 5 or above. Not sure how this would work when building with a later Java version.

Other interesting note is that some parts of Spring JavaConfig will be merged with Spring Core. SJC is really powerful and you can almost do everything XML configuration can do. It would be nice to see both XML and Java configuration part of the core framework.

Possibly Related Posts:


Jersey Today, Paul announced in his blog about the availability of Jersey 1.0. I have been waiting for this release like many others. The Jersey team delivered a pretty solid implementation and this implementation has been tested by the user community to a greater extent. This project can be considered as a blueprint for similar JSR implementations. Feedbacks were incorporated and the team was very responsive to user community and you can see more users using Jersey than any other JAX-RS implementations (RESTEasy, Restlet, Apache CXF). Jersey is considered to be more stable than its counterpart as it fully conforms to the JSR311 API and has support for Spring and houses a Jersey Client modeled around the resource concept. NetBeans 6.5 Beta has a decent tooling support for JAX-RS using Jersey.

Kudos to team Jersey!

Possibly Related Posts:


In my earlier blog entry on Jersey, I used HTTPClient API and curl command line utility as the clients. I had not mentioned about the Jersey Client API. It is part of the Jersey distribution. I would prefer using Jersey Client API as it is modeled around the concepts of JAX-RS spec. Let us quickly re-write our client using the Jersey API and see how easy is to write a client in Java.


import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource;
import restful.impl.jaxb.MovieCollection;
import restful.impl.jaxb.MovieDetails;

import static java.lang.System.out;

public class JerseyClient {
    public static void main(String args[]) {
        Client client = Client.create();
        WebResource r = client.resource("http://localhost:9090/boxoffice/movies");
        MovieCollection movies = r.accept("application/xml").get(MovieCollection.class);
        for (MovieDetails movie : movies.getMovie()) {
            out.println("Title : " + movie.getTitle());
            out.println("Genres : " + movie.getGenres());
            out.println("Directed By : " + movie.getDirectedBy());
            out.println("Rank : " + movie.getRank());
        }        
    }
}

This program will print all the top box office movie details in the console. I will be discussing more about this client API in future posts.

The Jersey user forum is the first place to check for any Jersey related issues. The Jersey team is amazingly helpful in resolving any issues. You can also visit Paul’s blog here, Marc’s blog here and Jakub’s blog here. You can bookmark these blogs as they are really informative. Grab the Jersey team’s JavaOne 2008 presentation slide deck here.

You can download the NetBeans project for this sample movie application here.

Possibly Related Posts:


Apache CXF is an open services framework. It is more than just a Web Services stack. Its simple, powerful, and promising. Today, the CXF project graduated from incubation as a top-level Apache project. It has made several stable releases since its incubation. I know projects which still prefer to use first generation Axis due to its simplicity. XFire is also popular like Axis, but made a significant difference in providing highly performing XML based web services. The power and simplicity of XFire and feature rich Celtix (branded as ESB) merged to form Apache CeltixXFire (CXF).

IMO, CXF wins over Axis2 programming model. CXF documentation is an area for improvement. It has a lot of powerful undocumented features. The primary source of getting these information is cxf-user mailing list. The people are amazingly helpful. It features most of its core developers offering their timely help to the user community.

I developed a simple loan processing application based on JPA and CXF using the NetBeans 6.1. This is a simple standalone Java application, but still demonstrates the power of persistence and integration technologies in combination with a powerful IDE which provides a platform for developing quality software. I specifically used NetBeans for this illustration because its very productive and intuitive for developer of any class. MySQL support in NetBeans 6.1 has improved phenomenally. You can manage the MySQL database from within NetBeans IDE. This is yet another useful integration for RAD apart from many of its other key offerings which I am not going to discuss in this post.

You can access this step-by-step tutorial in the NetBeans community website.

Rock with NetBeans 6.1 today and contribute to the community.

NetBeans 6.1

(4/30/08 Update): Changed the new Apache CXF project URL. Also, updated the tutorial to use Apache CXF 2.1 release and NetBeans 6.1 final release and used soapUI plugin for testing secure web services. Thanks to Vidhya for suggesting soapUI tool. Nice tooling around web services testing.

Possibly Related Posts:


I was recently using the 1.1 release of Craig MacKay’s Spring Module for NetBeans which supports the latest Spring Framework 2.5. Spring Framework tutorial hosted at NetBeans.org provides details on how to use this module in NetBeans IDE. Thomas Risberg’s Developing a Spring Framework MVC Application Step-by-Step tutorial is a good one which explains end-to-end web application development using Spring Framework 2.5. The sample in this tutorial was developed using Eclipse 3.3 and the application was deployed to Apache Tomcat 6.0.14. Spring supports JEE technologies, this sample application should run on any JEE compatible servers without much porting effort. I was able to run this tutorial using NetBeans IDE 6.0 and GlassFish V2 UR1 without any hassle. In fact, this combination worked out great for me with Craig MacKay’s plugin. A very useful plugin for Spring development on NetBeans IDE. I modified the original tutorial to use NetBeans and GlassFish infrastructure, and these tools should definitely help increase the productivity for Spring developers.

You can access the tutorial “Developing a Spring Framework MVC application step-by-step using NetBeans and GlassFish” here.

[Update: 11/09/09 – NetBeans wiki is missing the tutorial page since their recent migration to the new NetBeans.org infrastructure. I have removed the original redirect to the NB wiki, so you could access the tutorial directly from my website. The project can be downloaded from here].

Possibly Related Posts: