blog.smart-java.nl
Ordina J-Technologies – Java Blog

Archief ‘Java EE’ categorie




REST made easy with Java EE 6 and JAX-RS 1.1

Door: Stephan Oudmaijer, 19 February 2010

In my previous post I wrote about Spring 3.0 and how Spring MVC enables REST services in Spring 3.0. Java EE 6 adds support for RESTfull services by adding JAX-RS to the specification. In this post I will show how JAX-RS 1.1 will make your life easy when writing RESTfull services for JEE 6.

GlassFish v3 is an open source application server and is the first compatible implementation of the Java EE 6 platform specification. To test the examples in this article I will assume that you use GlassFish (or any other JEE6 enabled application server) to run the examples.

Maven2 dependencies

Lets start with the Maven dependencies, you can add them all to the pom.xml of your war. I have also included Sun’s Maven2 repository for downloading the JEE6 dependencies like the javaee-api and Sun’s JAX-RS 1.1 implementation called Jersey.

Both dependencies are scoped as provided because GlassFish already ships with these libraries. In fact, my war file is not bigger than 22kb. JEE6 allowes developers to package full blown JEE application as a web archive file, there is no need for an enterprise archive anymore. This makes JEE6 applications really light weight.

JAX-RS RESTfull services in JEE6

JAX-RS supports configuration through annotations, just like the Spring 3.0 REST annotations. Annotations can be added to both classes and methods. Classes in JAX-RS can be POJO`s. One thing about JAX-RS is that it does not integrate well with other JEE specification, for example the JSR-330 annotations for dependency injection are not supported by JAX-RS (yet), but there is a workaround ;-)

Because of the flexibility of JAX-RS it is possible to annotate EJB SessionBean or CDI components with JAX-RS annotations. So when a bean with JAX-RS annotation is packaged in a war file, the annotations are automatically picked up by the JAX-RS implementation (Jersey in this case). Since EJB3.1 SessionBeans and CDI components support all of the dependency injection features offered by JEE6, JAX-RS now does too!

Below is an example JAX-RS annotated class. The goal of this RESTfull service is to expose two methods of the ProductService through a RESTfull interface. The ProductService is injected using the @Inject annotation.

In JAX-RS the @Path annotation is used to map an URI to a REST service. In the example below I’ve defined the @Path annotation on the class, this will map all the URIs starting with /product to this class. I also defined the @ManagedBean (CDI) annotation on the class for the @Inject to work properly.

There are two methods within the service which are annotated with @Path, @GET and @Produces. The @Path is the same as with the class, but in this case it maps URI’s to a method. The URI of a method is relative to URI specified in the @Path annotation
on the class. So the following URLs are mapped in this example:

  • /product/category/{categoryId} which returns all products in a category
  • /product/categories which returns all product categories
  • JAX-WS allowes for mapping HTTP methods like GET, PUT, POST and DELETE to Java methods with the @GET, @PUT, @POST and @DELETE annotations. In this example only the GET method is used. In RESTfull service the HTTP GET is used to retrieve data. To map a GET request to a method you can simply annotate a method with @GET.

    The @Produces annotation specifies the Mime-Type of the response data the methods produces. In this example the methods both produce XML data, therefore we need to set the Mime-Type to application/xml. When returning an Object from a method annotated with @Produces, JAX-RS trieds to find an appropriate converter to produces the output. In this case I will use JAXB will to marshall the Objects to XML (see below).

    JAXB marshalling

    In order for JAXB to marshall the Objects returned, we need to specify JAXB annotations on the Objects returned from the methods.
    In this example I’ve added @XmlRootElement to the returned Objects to simply marshall the entire Object to XML.

    Adding Jersey to the web deployment descriptor: web.xml

    For JAX-RS to work we still need to add a Servlet to the web.xml which maps URL’s to the services. In this case we need to add the JerseyServlet to the web.xml. In the servlet-mapping all /rest/ URL patterns are mapped to Jersey. We can access the REST services using the following URIs: /rest/product/etc.

    Conclusion

    When building RESTfull services on an JEE6 enabled application server, JAX-RS really makes things easy. You will have to decide for your specific case if you want to use Spring or JAX-RS.




    JSF 2.0: The most simple CDI integration use cases

    Door: Jan-Kees van Andel, 31 January 2010

    If you have (just like me) been following the Web Beans and Contexts and Dependency Injection (CDI) work, you might be thinking (also just like I did): “That CDI is heavily over-engineered”. My “moment of clarity” was a year ago, at DeVoxx 2008.

    It was a talk by Pete Muir of JBoss. He was showing a really simple use case and tried to implement it using CDI. The talk was really technology driven and I hated it. Why? Because it wasn’t an improvement compared with the existing technologies. He wrote an application, containing several interfaces, classes (this is not bad) and custom annotations. If the goal was to show some kind of geniosity, it was a good talk. But if the goal was to show how this new technology would make our lives better… then sorry, he failed miserably.

    More than a year further, there have been a lot of movements on the CDI front. And, as an Apache MyFaces developer, I’m of course very interested how to use CDI in a JSF 2.0 application. And as an Apache fanboy, I of course prefer Apache software, in this case MyFaces with OpenWebBeans and OpenJPA.

    Configuration
    Since OpenWebBeans is still under development, you need to do some additional steps to get it to work.

    The following POM should get you up and running quickly in Tomcat:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.apache.myfaces</groupId>
        <artifactId>myfaces-example-ebanking</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>war</packaging>
    
        <dependencies>
            <!-- Compile dependencies -->
            <dependency>
                <groupId>org.apache.myfaces.core</groupId>
                <artifactId>myfaces-api</artifactId>
                <version>${myfaces-version}</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.myfaces.core</groupId>
                <artifactId>myfaces-impl</artifactId>
                <version>${myfaces-version}</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.openjpa</groupId>
                <artifactId>openjpa-all</artifactId>
                <version>${openjpa-version}</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>commons-digester</groupId>
                <artifactId>commons-digester</artifactId>
                <version>2.0</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.openwebbeans</groupId>
                <artifactId>openwebbeans-impl</artifactId>
                <version>${openwebbeans.version}</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.openwebbeans</groupId>
                <artifactId>openwebbeans-jsf</artifactId>
                <version>${openwebbeans.version}</version>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.geronimo.specs</groupId>
                <artifactId>geronimo-interceptor_1.1_spec</artifactId>
                <version>1.0.0-EA1-SNAPSHOT</version>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>javax.annotation</groupId>
                <artifactId>jsr250-api</artifactId>
                <version>1.0</version>
                <scope>compile</scope>
            </dependency>
    
            <!-- Test dependencies -->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <scope>test</scope>
                <version>${junit-version}</version>
            </dependency>
        </dependencies>
    
        <repositories>
            <repository>
                <id>Apache MyFaces beta</id>
                <name>Apache MyFaces beta</name>
                <url>http://people.apache.org/~lu4242/myfaces200beta</url>
            </repository>
        </repositories>
    
        <properties>
            <myfaces-version>2.0.0-beta</myfaces-version>
            <openwebbeans.version>1.0.0-SNAPSHOT</openwebbeans.version>
            <openjpa-version>2.0.0-M3</openjpa-version>
            <junit-version>4.7</junit-version>
        </properties>
    </project>
    

    Note some of the additional dependencies required to run in Tomcat, as opposed to a full blown appserver.

    Also, at the moment you need to build OpenWebBeans from source manually. The geronimo-interceptor_1.1_spec dependency will be downloaded to your local Maven repository on a “mvn install”. OpenJPA is not needed for this simple use case, but I use it in my project.

    Code
    And then, the real code:

    public class WebUtils {
        private static volatile String basePath;
    
        @Produces @Named public String getBasePath() {
            if (basePath == null) {
                basePath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
            }
            return basePath;
        }
    }
    

    This class contains a so-called Producer Method. As the name suggests, it produces stuff. In this case, it produces a String with Dependent scope. This means the method will be invoked every time the variable is needed. EL expressions or injection are the most common cases for this.

    I’m caching the return value, though it’s not necessary, since getting the context path is pretty cheap.

    The view could look like this (snippet):

    ...
    <link href="#{basePath}/style/default.css" rel="stylesheet" type="text/css" />
    ...
    

    Another implementation could put the variable into the Application scope, like this:

    public class WebUtils {
        @Produces @Named @ApplicationScoped public String getBasePath() {
            return FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
        }
    }
    

    As easy it might seem, the approaches shown above require some responsibility from the programmer though. With producer methods, it becomes really easy to mess things up. After all, you’re effectively creating globals. Tool support may help you here though. For example, the Dependency Analyzer in IntelliJ IDEA 9.0.1 already contains pretty decent support for JSF 2.0 and CDI. And, knowing the reputation of the JetBrains folks, I’m sure they come up with even more fancy stuff.

    A more classic implementation
    A more classic implementation could look like the following:

    @Named
    @ApplicationScoped
    public class WebBean {
        private static volatile String basePath;
    
        public String getBasePath() {
            if (basePath == null) {
                basePath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
            }
            return basePath;
        }
    }
    

    I’m not using producer methods anymore. The WebBean is now a CDI-managed bean.

    The client code becomes slightly more verbose, but who cares? I’ll put the client code in a generic template anyway!:

    ...
    <link href="#{webBean.basePath}/style/default.css" rel="stylesheet" type="text/css" />
    ...
    

    Wrapping up
    I haven’t even showed the complete tip of the iceberg. CDI offers several ways to write code and we’ve yet to find out the (anti) patterns.

    I would like to point you to the OpenWebBeans documentation for more info, but unfortunately this is still under development. The good news is that JBoss Weld already has extensive documentation.