Tuesday Mar 22, 2011

Jersey 1.x Plans

It has been a long time i posted anything about the Jersey project here. As Paul has left Oracle, and i am taking over his leadership role for Jersey 1.x, i think it is the right time to start blogging again. This post should give you an overview of what are the plans for the Jersey 1.x in the near future.

We want to improve Jersey integration with both GlassFish and WebLogic application servers, with focus on the following areas:

  • Multiple Jersey versions running simultaneously within one container
  • EJB integration
  • Monitoring
  • Client injection

Another important thing we want to work on is non-blocking asynchronous web client, including support for WebSocket and HttpStreaming. For the client generally, we want to look at the possibilities to get them automatically generated from WADL, which probably includes also some WADL related work on the server side (XSD inclusion).

Besides the areas mentioned above, we will also be continuing on bug fixing and working with the community on any other stuff. Jersey 1.x might still be a playground for emerging JAX-RS 2.0 features. Another, often underestimated thing, is the project infrastructure. We are willing to continue improving it. Pavel recently added Maven 3 support, and Jersey now builds faster.

Last but not least, we would like to get back to the 6-8 week release cycle. The next, 1.6 version, release is planned for the end of this week.

Saturday Oct 17, 2009

Přednáška o JAX-RS a Jersey na WebExpo konferenci

WebExpo je údajně největší česká konference zaměřená na web. Za chvíli tam mám prezentovat JAX-RS a potažmo Jersey a už se moc těším. Je to vlastně poprvé, kdy budu prezentovat mimo Java komunitu, a moc mě zajímá, jak na to budou lidi reagovat. Taky jsem zvědavý na přednášky ostatních.

Věším slajdy na http://blogs.sun.com/japod/resource/Jersey-WebExpo-Praha.pdf a vrhám se do víru konference...

WebExpo 2009

Monday Apr 27, 2009

Jersey 1.0.3 GlassFish V3 packages split up

Jersey version 1.0.3 is now available also to GlassFish V3 Prelude users via GFv3 update center. I am writing this, because several changes happened about how things work there.

As you can see at the snapshot, the first big change relates to number of Jersey packages. Started from the 1.0.3 version, we are providing two separate packages.

We are going to integrate with GlassFish V3 bits, so that people would not need to install Jersey separately. And as we wanted to lower the Jersey footprint in GlassFish V3, we have broken the original Jersey package down into two separate modules:

  • Jersey Core
  • Jersey Examples and Documentation

The "Jersey Core" package contains OSGI modules for jersey-bundle, jettison, and jackson-asl libraries. This should be sufficient for you to deploy Jersey based web applications to GlassFish V3 Prelude without a need to bundle any Jersey related jars with your application WAR file and should be good for production.

"Jersey Examples and Documentation" package contains Jersey API javadocs and some examples. This package should be useful especially for developers, who want to learn Jersey, and see how it works before developing their own RESTful web applications. If you choose this package, the UC client will automatically install also the "Jersey core" module, and you will get installed everything you need to start up.

A rather cosmetic change happened to location, where jersey subdirectory gets installed into. It has moved from $AS_HOME/jersey to $AS_HOME/glassfish/jersey.

When upgrading from earlier versions of Jersey, you could be a bit confused with consequences of the above described changes. So if you upgraded into a newer Jersey version and try to figure out, where all Jersey examples and docs went, just install "Jersey Examples and Documentation" in addition and it should re-appear in $AS_HOME/glassfish/jersey.

Wednesday Apr 22, 2009

Jersey aplication sharing Grizzly with static content and servlets

I was asked the question some time ago by one of my colleges here at SUN, and the same question was asked again recently at our user mailing list: "I want to run Jersey based application on Grizzly web server, but i want to also run another servlet from there, and possibly also serve some static content using the very same Grizzly sever instance. How do i do that?"

The answer is as simple as follows. Having imported

import com.sun.grizzly.http.embed.GrizzlyWebServer;
import com.sun.grizzly.http.servlet.ServletAdapter;
import com.sun.jersey.spi.container.servlet.ServletContainer;

You can just use:

        // static content is linked from here
        GrizzlyWebServer gws = new GrizzlyWebServer(8080, "/var/www");

        // Jersey web resources
        ServletAdapter jerseyAdapter = new ServletAdapter();
        jerseyAdapter.addInitParameter("com.sun.jersey.config.property.packages",
                "com.example");
        jerseyAdapter.setContextPath("/jersey");
        jerseyAdapter.setServletInstance(new ServletContainer());
        
        // Another non-Jersey servlet
        ServletAdapter simpleServletAdapter = new ServletAdapter();
        simpleServletAdapter.setContextPath("/simple");
        simpleServletAdapter.setServletInstance(new SimpleServlet());

        // register all above defined adapters
        gws.addGrizzlyAdapter(jerseyAdapter, new String[] {"/jersey"});
        gws.addGrizzlyAdapter(simpleServletAdapter, new String[] {"/simple"});

        // let Grizzly run
        gws.start();

Your Jersey resource classes are placed in com.example package, and will become accessible at http://localhost:8080/jersey base. Your static content for http://localhost:8080/ is taken from /var/www directory and a SimpleServlet will become available at http://localhost:8080/simple.

The only dependency you will need to include other than Jersey dependencies itself is

        <dependency>
            <groupId>com.sun.grizzly</groupId>
            <artifactId>grizzly-servlet-webserver</artifactId>
            <version>1.9.10</version>
        </dependency>

If you are interested in some more advanced scenarios, you can get inspired at Jean-Francois Arcand's blog post

Friday Feb 13, 2009

Configuring JSON for RESTful Web Services in Jersey 1.0.2

This is an update for a tech tip on configuring JSON in Jersey, which i wrote in October 2008. The way of JSON configuration, suggested in the tech tip, is now deprecated (but still functioning). Here i would like to describe the new API, which will hopefully last (and be supported) a way longer.

Notice: you will need to bundle jaxb-impl-2.1.10.jar with your application in order to take advantage of the recently added JSON NATURAL convention

Deprecated Configuration

Configuring JSON format, as described in the tech tip, meant to implement a JAXBContext resolver class returning an instance of JSONJAXBContext. This principle have not changed. What changed is a way, how the JSONJAXBContext itself is being configured. Lets look at the sample code below (using the deprecated API):

   @Provider
   public class MyJAXBContextResolver implements ContextResolver<JAXBContext> {

       private JAXBContext context;
       private Class[] types = {StatusInfoBean.class, JobInfoBean.class};

       public MyJAXBContextResolver() throws Exception {
           Map props = new HashMap<String, Object>();
           props.put(JSONJAXBContext.JSON_NOTATION, JSONJAXBContext.JSONNotation.MAPPED);
           props.put(JSONJAXBContext.JSON_ROOT_UNWRAPPING, Boolean.TRUE);
           props.put(JSONJAXBContext.JSON_ARRAYS, new HashSet<String>(1){{add("jobs");}});
           props.put(JSONJAXBContext.JSON_NON_STRINGS, new HashSet<String>(1){{add("pages"); add("tonerRemaining");}});
           this.context = new JSONJAXBContext(types, props);
       }

       public JAXBContext getContext(Class<?> objectType) {
           return (types[0].equals(objectType)) ? context : null;
       }
   }

There you needed to create a property bag, put appropriate configuration options into it, and then pass it to the JSONJAXBContext constructor.

Jersey 1.0.2 JSON Configuration

In the currently available 1.0.2 Jersey version, a new JSONConfiguration class was introduced to became a central point for JSON configuration options. For creating a new JSONConfiguration instance, a builder pattern is employed. It is not only more user friendly, but also ensures only meaningful JSON options could be combined together. You can compare the following code, with the deprecated example above:

   @Provider
   public class MyJAXBContextResolver implements ContextResolver<JAXBContext> {

       private JAXBContext context;
       private Class[] types = {StatusInfoBean.class, JobInfoBean.class};

       public MyJAXBContextResolver() throws Exception {
           this.context = new JSONJAXBContext(
                   JSONConfiguration.mapped()
                                      .rootUnwrapping(true)
                                      .arrays("jobs")
                                      .nonStrings("pages", "tonerRemaining")
                                      .build(),
                   types);
       }

       public JAXBContext getContext(Class<?> objectType) {
           return (types[0].equals(objectType)) ? context : null;
       }
   }

You can look at JSONConfiguration javadoc for detailed information on various configuration options.

Further Simplification

If you go a bit further, you can ask if the configuration could be simplified even more. Imagine you have much bigger number of JAXB beans in your model, and they are more complex. It could easily become unmanageable to maintain a reasonable JSON configuration as described so far. Then if you happen to have conflicting non-string/string values and/or arrays/non-arrays elements in your set, you could easily run out of options there.

A natural way to overcome above mentioned issues, is to simply use recently introduced Jersey NATURAL JSON notation. Then you need only to:

   @Provider
   public class MyJAXBContextResolver implements ContextResolver<JAXBContext> {

       private JAXBContext context;
       private Class[] types = {StatusInfoBean.class, JobInfoBean.class};

       public MyJAXBContextResolver() throws Exception {
           this.context = new JSONJAXBContext(
                   JSONConfiguration.natural().build(),
                   types);
       }

       public JAXBContext getContext(Class<?> objectType) {
           return (types[0].equals(objectType)) ? context : null;
       }
   }

Such configuration is simple from user point of view, but yet very powerful. You do not need to keep various configuration options in sync with your actual JAXB beans, and be worried what options to actually use (what exact names, etc.). Jersey will automatically take care about serializing Java collections/arrays as JSON arrays, Java booleans as JSON booleans, Java ints as JSON integers,and so on.

Wednesday Jan 28, 2009

Jersey Based Java Client Talking to SmugMug

Jersey provides a great, easy-to-use REST client API. Recently someone wrote to our mailing list the opposite. We probably need to advertise better.

Paul initially introduced the API in this blog post almost a year ago. But it is, of course, not the only place to look at. Javadoc for Jersey Client API could be found here.

The Jersey Client API could be used pretty easily. However, instead of describing the API in detail, i would just like to present here a real life example. A Jersey based client talking to a 3rd party server application. The server application happens to be SmugMug. A photo sharing service application. I wrote the client application during the last Xmas break, because what was provided by SmugMug did not work well for me. I am happy with my Solaris, but sometimes i wish i have chosen another OS for my laptop ;-)

Putting together a functional prototype took me only a couple of hours, and this was mainly thanks to user friendliness of the Jersey Client API designed by Paul. Following is a screenshot of the main screen of the client.

I promised not to dig into details, but just for your curiosity. Only the very last statement of the java code below has anything to do with actual invocation of SmugMug API from java using Jersey Client API. All the rest is only about computing a digest for the file being sent, as SmugMug API requires it sent in a special HTTP request header.

MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
File picFile = new File(picDir, pic);
fis = new FileInputStream(picFile);
byte[] buf = new byte[8196];
int l;
while ((l = fis.read(buf)) > -1) {
  digest.update(buf, 0, l);
}
String md5hash = asHex(digest.digest());

cr = uploadWebResource
         .path(pic)
         .header("Content-MD5", md5hash)
         .header("X-Smug-SessionID", sessionId)
         .header("X-Smug-Version", "1.2.0")
         .header("X-Smug-ResponseType", "JSON")
         .header("X-Smug-AlbumID", car.album.id)
         .put(ClientResponse.class, picFile);
About

Jakub Podlesak

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today