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

Archief voor February, 2010




Using Unified Expression Language in Maven-Jetty-Plugin

Door: Jan-Kees van Andel, 27 February 2010

I like the maven-jetty-plugin. If I download an Open Source project, I usually first look for this baby, because it allows me to quickly run the code in a tested environment. This saves me from a lot of configuration, which would otherwise cause me to lose interest. This often doesn’t take long… :-)

Also, you can completely configure the server in your POM, centralizing configuration and making it thus easy to store server settings in version control. Also, the mvn-jetty-plugin benefits from your existing Maven project configuration, like dependencyManagement.

Some of my buddies at Apache even use the maven-jetty-plugin on a daily basis for their real work. I never got this far, mostly because I’m more familiar with Tomcat, but also because I didn’t really see it as a mature development tool. However, today I decided to give it a chance.

The first attempt
So, I created a simple webapp in my favorite IDE: IntelliJ IDEA and added a Maven2 POM to enable Maven2 support. All well so far.

This was the initial version of my POM:

All was fine, my test app was running, but I needed to enable Unified EL to test MyFaces BeanValidator.

Adding UEL libraries
So, I added a dependency to the UEL API and Impl in my POM, but there was an issue. Every web container already provides the old Expression Language in the jsp-api.jar. So I’m not allowed to package my own EL libraries.

However, I’m quite stubborn, so I tried anyway:

So, let’s give it a try:

mvn jetty:run-exploded

(MyFaces 2.0 requires exploded deployment in Jetty).

Result? BOOOM!

The fix, replacing libraries
The error is completely appropriate. You’re just not allowed to package your own version of the servlet libraries. That’s the job of the servlet container. Failing to do so will result in the error shown above.

So we need to fix this issue by somehow replacing the Jetty libraries or at least changing the way Jetty loads its jsp-api.jar. This is no trivial task however, since jetty is initialized by Maven and doesn’t have a fixed directory structure on disk.

So we need to have some way in Maven to configure the Jetty libraries.

First, Jetty doesn’t have an endorsed mechanism, so that’s a no-go.

But the fix is actually quite easy, just pass some dependencies into the jetty plugin in the POM.

The final POM looks like this:

As you can see, Maven takes care of the heavy lifting. You only need to specify your dependencies and they will override any dependencies with the same groupId, artifactId and type.

So, now I don’t have any reason not to use mvn-jetty-run to test my code!

Happy coding!




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.

    Orginal article posted here.




    DefaultMessageListenerContainer troubles in Websphere

    Door: Michel.Schudel, 3 February 2010

    Using the Spring DefaultMessageListenerContainer makes it easy for you to connect to a jms resource like a Queue so you can pick up messages from that queue.

    Using this container in Websphere (6.0, 6.1, 7) some problems occur when you want to do the following:

    • You use a resource environment reference for your destination, specified in the web.xml, for the Destination.
    • You use the property destinationName on the DefaultMessageListenerContainer in combination with a JndiDestinationResolver to look up your resource environment reference like this: java:comp/env/jms/(your destination)

    problem
    When you try to start the application, you will get an exception like this: javax.naming.NameNotFoundException: Name "comp/env/jms/(your destination)" not found in context "java:"., although you are sure that your resource environment reference is defined correctly.

    cause
    The cause of this problem lies in the fact that the lookup occurs in a Thread started by the DefaultMessageListenerContainer, which is unmanaged by Websphere. This thread will not have the jndi queue bindings in its InitialContext.

    solution
    You can either:

    1. Specifiy the jndi object beforehand with a JndiObjectFactoryBean, or a
      <jee:jndi-lookup id="myqueue" jndi-name="java:comp/env/jms/(your destination)"/>
      , and then
      setting the destination property of the DefaultMessageListenerContainer to the ref myqueue, so no actual lookup occurs within the thread of the listener itself.
    2. Delegate the listener’s thread to Websphere with the help of the Spring class WorkManagerTaskExecutor. You can then set the property taskExecutor on the message listener container to reference this class. See the IBM article here for details on how to do this.