Wednesday Mar 23, 2011

Jersey.next

Dear Jersey users,

As you know from the last post by Paul, he left Oracle about a month ago and as a result of that lost write access to blogs.sun.com, so had to move his blog to a different location. I'd like to let you know we are going to keep this blog around as a valuable part of "internet memory" and an archive of lots of useful info.

I'd also like to use this opportunity to share a little more about the Jersey team and our future plans, since I've been receiving some questions around this recently.

Jakub Podlesak, who worked closely with Paul and Marc from the very beginning of Project Jersey, took over Paul's role of the Jersey technical lead. Next week we are planning to release Jersey 1.6 and we are resuming the 6-8 weeks release cycles (which we kind of stopped doing as we were finalizing delivery for GlassFish 3.1). Together with Pavel Bucek - another senior member of our team - they are doing their best to make sure you continue loving Jersey :), and Jon Benoit - our QA engineer is making sure whatever features we put in are well tested.

Marek Potociar, former lead of Project WSIT, took over the Jersey 2.0 prototyping work from Paul and is now working closely with Roberto Chinnici on co-driving JAX-RS 2.0. You will start seeing him more often once we push the 2.0 prototyping work to the open workspace.

Here are the team's blogs you may want to bookmark to be able to track the future progress of Jersey more closely:

And we always welcome questions and suggestions on our mailing list: users@jersey.java.net.

Thanks for your continued support!

Martin Matula
Dev. Manager, Jersey Team

Thursday Jan 27, 2011

Jersey 1.5 is released

We have recently released version 1.5 of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specification is available at the JCP web site and also available in non-normative HTML here.

For an overview of JAX-RS features read the Jersey user guide. To get started with Jersey read the getting started section of that guide. To understand more about what Jersey depends on read the dependencies section of that guide. See change log here.

In the interval between releasing Jersey 1.4 and Jersey 1.5 both the JSR 311 project and the Jersey project transitioned to the new java.net infrastructure. There are probably a few links here and there that still need updating. One noticeable improvement is the visibility of the project to search engines now that HTTPS is not the default. That means it is much easier to search for stuff in the User guide and JavaDoc. The project name is starting to compete in search ranking with the island and comes out favorably when searching for JAX-RS.

This release contains mostly bug fixes rather than features. This version, failing any showstoppers, will be shipped with GlassFish 3.1.

For feedback send email to:

users@jersey.java.net (archived here)

or log bugs/features here.

Wednesday Nov 03, 2010

Completion of Jersey and Atmosphere migration to Kenai is delayed

The Jersey and Atmosphere projects are currently in the process of being migrated from CollabNet hosted infrastructure to Kenai hosted infrastructure. While this occurs both projects are in read/only mode: no commits; and no emails :-(

For more details on the migration see here:

http://markmail.org/message/nqz3uvlbdkvjss6h?q=list:net.java.dev.jersey.users+FInal+Notice+order:date-backward&page=1

The migration started last week on Thu 28th of Oct. However, it is taking longer than expected to obtain the data to complete the migration (i.e. it should be easy to work out who is dragging their heels in this process). It may take until Tue 9th of Nov to complete!

This is extremely frustrating for the developers and the users of Jersey and Atmosphere. My apologies, hopefully this will all be sorted out by next week.

Friday Oct 15, 2010

Jersey 1.4 was released on September 11th

[This is a rather tardy announcement of the Jersey 1.4 release which occurred just before the week of JavaOne a week of vacation to decompress.]

We have recently released version 1.4 of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specification is available at the JCP web site and also available in non-normative HTML here.

For an overview of JAX-RS features read the Jersey user guide. To get started with Jersey read the getting started section of that guide. To understand more about what Jersey depends on read the dependencies section of that guide. See change log here.

Pavel integrated JRebel support with Jersey, see here.  So now it is possible to modify code, compile and JRebel will inform Jersey to reload information. Jersey needs to reload because it caches information about classes, using reflection, at runtime.

Martin and Jon improved the look and feel of the JavaDoc and user guide, added a search bar on the main page, and improved the way Google indexes the Jersey site, user guide and JavaDoc. For example if one searches for Viewable information about Jersey's Model View Controller support is displayed (note that documentation still needs to be added for this).

A client side HTTP digest authentication filter was contributed Raphael Jolivet.

Jackson was upgraded to version 1.5.5 (this project releases fast!). And Jakub added simplified configuration support for Jackson so it is not necessary to explicitly register the Jackson JAX-RS providers. See here.

The jersey-core module now bundles the classes from the jsr-311.jar so it is no longer necessary to include the latter jar in your class path. This was required so we can correctly isolate OSGi bundles using different versions of Jersey.

Roberto added support for improved CDI integration such that parameters of constructors of CDI constructed or managed beans may be injected with JAX-RS artifacts. This requires some fairly funky adaption of the CDI bean module in a CDI extension and pushes CDI and Weld to the limits. Unfortunately because of this it has introduced a regression with with GlassFish 3.1 and the current version of Weld. We tried to work around the issue but alas it sometimes fails with an NPE. However, the good news is i managed to create an alternative work around, which looks promising (thanks John Lister for verifying and providing addition feedback/patches!). The new workaround should be available in an early access release of 1.5 next week.

Martin is my manager but Martin codes :-) he added an API and SPI to make it easy to build OAuth 1.0 service providers. The default in-memory implementation of the SPI can be used for samples and tests and to guide people on how they can develop a more advanced implementation that persists credential information. See more here.

For feedback send email to:

users@jersey.dev.java.net (archived here)

or log bugs/features here.

Friday Jul 02, 2010

Jersey 1.3 is released

We have recently released version 1.3 of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specification is available at the JCP web site and also available in non-normative HTML here.

For an overview of JAX-RS features read the Jersey user guide. To get started with Jersey read the getting started section of that guide. To understand more about what Jersey depends on read the dependencies section of that guide. See change log here.

Usually this version would also be placed on the GlassFish Update Center and integrated into the GlassFish M2 release but we hit some last minute glitches with our GlassFish OSGi integration that broke the RESTful admin service. So we are working on fixing that for the next release.

This release only works with Java SE 6 or greater (still eagerly waiting for SE 7!) which greatly simplifies our build and deployment infrastructure. In addition to stopping those annoying compilation issues when developing on SE 6 but compiling on SE 5 (String.isEmpty() i am talking about you)

After seeing too many developers place asserts in JAX-RS/Jersey code to check that injection was working i simply could not stand by any longer. What had been put of for way too long is now implemented in Jersey 1.3 and dependency related errors will occur on deployment. As many errors as possible will be displayed to avoid a compile fix loop.

We added a nice little addition to Guice so that singleton-based provider classes can be injected using the @Inject semantics, see the JerseyServletModule. Unfortunately due to Guice's restriction in binding it is not currently possible to support the @\*Params in the same manner. However, IMHO, such extensions using modules is way better than the extensibility approach defined by CDI (see later). All i need to do is find the time to tweak Guice as after having looked at the code i estimate only minor changes to the API and implementation are required.

For the next release, 1.4, we are going to improve the CDI integration. Roberto is doing some seriously impressive Java magic in the Jersey CDI extension class and has it working in a branch. This will mean all JAX-RS artifacts, such as UriInfo and @QueryParam will work with @Inject. CDI has the virtue of being more extensible than Guice (with the set of shoot yourself in the foot implementations being much larger than the set of workable implementations) but IMHO the approach is not modular nor deterministic if one or more extension is present. Or to put it more succinctly: Guice is better. However, CDI is in Java EE 6 so we must make Jersey work well with CDI.

Jakub continues to improve the OSGi integration, which is proving particularly tricky as we are effectively managing 4 platforms: non-OSGI, pure OSGI (tested on Felix), GlassFish OSGi; and Web/war deployment.

Pavel has been making improvements to the test framework and recently added experimental support for JRebel. A sample will be included in the near future.

A new team member, Jon, has joined us to help work on testing, our Hudson infrastructure, and the test framework. He is already up and running tidying up niggles in our inconsistent documentation.

We continue to ensure that Atmosphere, which recently cranked out a 0.6 release with loads of stuff, works smoothly with Jersey. For 0.7 we may have something interesting to say about high-level integration with WebSocket, stay tuned for more details on that (and for a session at JavaOne).

For feedback send email to:

users@jersey.dev.java.net (archived here)

or log bugs/features here.

Monday May 10, 2010

Jersey 1.2 is released

We have just released version 1.2 of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specification is available at the JCP web site and also available in non-normative HTML here.

For an overview of JAX-RS features read the Jersey user guide. To get started with Jersey read the getting started section of that guide. To understand more about what Jersey depends on read the dependencies section of that guide. See change log here.

The main driver for this release is basic OSGi support. This has been hard work as Jakub will testify. Most of Jakub's time was spent on testing.

Currently only the jersey-core, jersey-server, jersey-client and jersey-json modules have been made OSGi aware (the other modules will be completed in the next release). The following deployment scenarios work. Deploying using Grizzly or Jetty with the OSGi HTTP service (see osgi-http-service sample) and deploying OSGi war-bundles to Jetty (see helloworld-osgi-webapp sample). Deployment requires that root resource and provider classes are explicitly declared (the next release will hopefully support package scanning).

For the next release, 1.3, Jersey will only work on Java SE 6 or greater.

For feedback send email to:

users@jersey.dev.java.net (archived here)

or log bugs/features here.

Thursday Mar 11, 2010

Jersey 1.1.5.1 is released

We have just released version 1.1.5.1 of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specification is available at the JCP web site and also available in non-normative HTML here.

For an overview of JAX-RS features read the Jersey user guide. To get started with Jersey read the getting started section of that guide. To understand more about what Jersey depends on read the dependencies section of that guide. See change log here.

This release is targeted at users of the WebLogic application server and contains patches for regressions to class and package scanning algorithms that scan for root resource and provider classes.

As soon as the OSGi work is finalized (and considered suitably battle tested) we will release 1.2. Nearly there :-)

Wednesday Jan 20, 2010

Jersey 1.1.5 is released

We have just released version 1.1.5 of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.1 specification is available at the JCP web site and also available in non-normative HTML here.

It will be available soon from the GlassFish v2 and v3 update centers.

For an overview of JAX-RS features read the Jersey user guide. To get started with Jersey read the getting started section of that guide. To understand more about what Jersey depends on read the dependencies section of that guide. See change log here.

This release will align with the soon to be released of Atmosphere 0.5. 

Deployment to Google App Engine now works and we have a tracing mechanism (inspired from Hudson) to aid debugging.

In between releasing 1.1.4.1 and 1.1.5 Bill Burke's JAX-RS book has been published. I have not had a chance to look at the book in detail, but it appears generally well received from the tweets i have seen. The examples in the book require RESTEasy so Pavel, with Bill's permission, converted those samples to work with Jersey and, with much help of Alexis Moussine-Pouchkine, embedded GlassFish. The examples required minimal modifications to the web.xml (Java EE 6 solves that problem!) and some minor tweaks to reach parity with some RESTEasy specific features (specifically around configuration of URI content negotiation and human readable formatting of XML responses). Overall the portability of the examples was very good. You can find the samples here.

Jakub has made some good progress on OSGi, many thanks to the developers who have helped test and provide feedback. It is in the trunk, but we decided not to connect it up to the build and deployment process until we have more thoroughly tested the implementation and investigated some areas for further improvement. (It certainly has not been trivial to develop good and robust OSGi support!)

So when OSGi support is ready we will release the next version of Jersey, 1.2.

Meanwhile Santiago has been very busy investigating better hypermedia support for both the Jersey client and server. There is a prototype sample in a branch that reflects Santiago's current thinking.

For feedback send email to:

users@jersey.dev.java.net (archived here)

or log a bugs/features here.

Thursday Dec 10, 2009

GlassFish v3 is go

GlassFish v3 is go!

This is a biggie. It's been about 3 years in the making. It is a modularized OSGi container. It implements Java EE 6. It's 70Mb compared to 700Mb. It could make coffee if i programmed it so... but realistically is not likely to win the Nobel prize for peace (although... <joke>given the current awardee perhaps there is a chance?</joke>). Even so, i think v3 is going to be very popular.

GlassFish v3 includes Jersey 1.1.4.1 that implements JAX-RS 1.1.

Tuesday Dec 08, 2009

Simple long polling in Scala with Atmosphere

There are two styles of pushing events from servers to clients: long polling; and HTTP streaming. The former tends to be easier for developers to understand "push", especially when a bit of HTML and JavaScript is utilized, and it does not break the REST request/response constraint. So there are some advantages over HTTP streaming depending on what your requirements are.

I recently took a slight detour into Node.js, impressive stuff. A blog entry written by Simon Willison presented a simple long-polling example.

Hmm... i wonder if i can do something functionality equivalent in Scala and using Atmosphere. I might iron out some bugs in Atmosphere, learn some stuff along the way, and help developers better understand long polling and Atmosphere.

A common pattern for long polling is:

  1. when a client makes a request and the server has data, that data is returned immediately and the connection is not suspended.
  2. when a client makes a request and the server has no data, the connection is suspended, and the client waits for a response. When data is available the server returns that data and the connection is resumed.

In cases 1 or 2 the client make will another request after it has received the data, and the process repeats. Further more, there may be 2 or more clients waiting for data whose connection will be resumed when the same data is available, for example, consider the case of a chat application where a client may send a message to all other clients.

Notice that there is an interval of time when a client processes a response and makes a new request. Within that interval new data may be available. To ensure that the client does not miss out on that data the server must store that data and the client must signal to the server what data it has previously received.

To play with these concepts i wrote a very simple long polling chat server written in Scala using Atmopshere that functions as previously described, you can download it here.

The main class that acts as the chat application is as follows:

01  @Path("/chat")
02  @Singleton
03  @Produces(Array("application/json"))
04  class MessagesResource {
05  
06    var messages = List[Message]();
07  
08    @Suspend { val resumeOnBroadcast = true }
09    @GET
10    def getMessages(@QueryParam("date") lastSeenTime : long) : unit = {
11      val lastSeenDate = new Date(lastSeenTime);
12      
13      messages.filter(_.date.compareTo(lastSeenDate) > 0) match {
14        case Nil => // Suspend and wait for data
15        case x => // Return with data
16          throw new WebApplicationException(
17            Response.ok(x.reverse).build())
18      }
19    }
20  
21    @Broadcast
22    @POST
23    @Consumes(Array("application/x-www-form-urlencoded"))
24    def publishMessage(@FormParam("message") message : String) = {
25      val m = new Message(new Date(), message);
26      messages = m :: messages;
27      List(m);
28    }
29  } 

The root resource class

A JAX-RS root resource class, MessageResource, is served from the "chat" path segment as declared by the @Path annotation at line 1, and there will be one instance of this class created per the application (using the Jersey @Singleton annotation at line 2) because the messages are going to be stored in memory. All resource methods (see later) will produce JSON, as declared by the @Produces annotation at line 3.

The list of chat messages are stored in an immutable list, List[Message], a reference of which can be updated (which is why var is utilized) at line 6.

Sending a chat message

A client will send a chat message by performing a POST request to the chat resource with a representation conforming to the "application/x-www-form-urlencoded" media type, which basically is the default format used by HTML forms of name=value pairs separated by '&' characters, with a name of "message" and the value that is the chat message. Such a contract is defined at lines 22 to 24 with the JAX-RS resource method publishMessage. The JAX-RS @FormParam annotation is utilized to obtain the form parameter value whose name is "message".

Highlighted, in yellow at line 21, is the Atmopshere annotation @Broadcast. This declares that any response entity returned from the publishMessage resource method will be broadcast on all suspended connections. This is how one chat client may send a message to all other clients participating in chatting.

A new message is created, at line 25, that contains the date it was created at and the actual chat message. The date is used later to determine what messages to send back to the client. A new list of messages is then created, at line 26, by concatenating the newly created message and all the previous messages, and that new list is assigned to the messages field. Then the resource method, at list 27, returns a list with one element that contains the newly create message. A list is returned so that a JSON array will be produced with one object that contains the date and message values (more on how the JSON is created later).

Receiving a chat message

A client will receive one or more chat messages by performing a GET request to the chat resource with a query parameter declaring the date of the message it last received. Such a contract is defined at lines 9 and 10 with the JAX-RS resource method getMessages. The JAX-RS @QueryParam is utilized to obtain the query parameter whose name is "date" that corresponds to the date of the last received message.

Highlighted, in yellow at line 8, is the Atmopshere annotation @Suspend. This declares that, if the resource method returns normally, the connection will be suspended and resumed when a broadcast occurs on that connection.

For expediency i found it is easier to pass dates between the client and server as non-negative numbers thus line 11 creates a java.util.Date object (i know i should be using Joda time!) to easily compare dates of messages.

The list of messages is then filtered to obtain a list of those messages that have been broadcast after the date the client last received a message, at line 13. If the list is Nil (or empty), at line 14, the resource method returns and and the connection will be suspended until a chat message is broadcast. If the list is not empty, at line 15, then the list is reversed, so messages are ordered in increasing time from left to right, a Response is built with the list and is thrown with a WebApplicationException. The throwing of the exception tells Atmosphere the connection should not be suspended. So this is the way client may receive any pending data immediately.

The client

It is very easy to test the chat server using curl. For example, if you run the chat server, then in one terminal window type:

curl -v http://localhost:9999/app/chat 

then the connection is suspended and curl will wait for a response. Then in another terminal window type:

curl -v -d message=HELLO http://localhost:9999/app/chat

You will observe that a message similar to the following will be returned by both curl statements:

[{"message":"HELLO","date":1260295792434}] 

Then if you type the following in the first terminal window (substituting the date value as appropriate):

curl -v http://localhost:9999/app/chat?date=1260295792434

the connection will be suspended because no messages have been broadcast after the date declared in the query parameter.

A browser-based client is more interesting and some simple HTML + JavaScript can be easily created as follows (note that i am not so experienced in this area, for example i cannot work out why the heck it works with Firefox but not Safari):

01  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
02      <head>
03          <script type="text/javascript" src="jquery-1.3.2.js"></script>
04          <script type="text/javascript" src="jquery.form.js"></script>
05          <script type="text/javascript">
06              var last_date = 0;
07              function fetchLatest() {
08                  var ul = $('ul');
09                  $.getJSON('chat?date=' + last_date, function(data){
10  
11                      $.each(data, function() {
12                          ul.prepend($('<li></li>').text(new Date(this.date) + ": " + this.message));
13                          if (last_date < this.date)
14                              last_date = this.date;
15                      });
16                      
17                      setTimeout('fetchLatest()', 1);
18                  });
19              }
20          </script>
21          <script type="text/javascript">
22              $(document).ready(function() {
23                  fetchLatest();
24                  $('#publishForm').ajaxForm();
25              });
26          </script>
27      </head>
28      <body>
29          <p>
30              <form id="publishForm" action="chat" method="post">
31                  Message: <input type="text" name="message" />
32                  <input type="submit" value="Submit Comment" />
33              </form>
34          </p>
35          <p>Waiting for messages...</p>
36          <ul></ul>
37      </body>
38  </html> 

jQuery and the jQuery form plugin make it easy to perform GET and POST requests asynchronously.

Lines 30 to 33 define how the client will send chat messages to itself and other clients utilizing the POST requests. Line 24 uses the jQuery form plugin to perform the POST request asynchronously so the browser does not display the response.

Line 23 initiates long polling calling the function fetchLatest. This function, at lines 7 to 19 will use jQuery to perform a GET request asynchronously that expects a JSON array in response. The message objects in that array are iterated over and the HTML is updated for each message. Finally, at line 17 the function sets a timer to call itself (i am not sure if tail calls are optimized).

If you run the chat server and open two Firefox windows and in each go to the URL http://localhost:9999/app/ it should be possible send and receive chat messages from each window.

How messages are serialized to JSON

Instances of List[Message] are serialized where Message is as follows:

class Message(@BeanProperty val date : Date,
              @BeanProperty val message : String) {
}

The Jackson JAX-RS library is utilized to serialize a list of Message. The @BeanProperty annotation tells the Scala compiler to generate bean getter and setter methods and ths enables Jackson to workout what the bean properties are.

This is where it gets a little hacky (note that i have not investigated any Scala libraries for producing JSON). First, it is necessary to work around a bug in Atmosphere which does not take into account the media type declared in the @Produces when broadcasting (we are gong to fix that!). Second, Jackson does not know how to serialize the instances of the Scala List. So it is necessary to create a message body writer as follows:

01  @Provider
02  @Produces(Array("\*/\*"))
03  class ListProvider extends JacksonJsonProvider {
04  
05    private val arrayListClass = classOf[java.util.ArrayList[_]];
06  
07    override def isWriteable(c: Class[_],
08                             gt: Type,
09                             annotations: Array[Annotation],
10                             mediaType: MediaType) : boolean = {
11      classOf[List[_]].isAssignableFrom(c) &&
12          super.isWriteable(arrayListClass, arrayListClass,
13                            annotations, MediaType.APPLICATION_JSON_TYPE);
14    }
15  
16    override def writeTo(t: Object,
17                         c: Class[_],
18                         gt: Type,
19                         annotations: Array[Annotation],
20                         mediaType: MediaType,
21                         httpHeaders: MultivaluedMap[String, Object],
22                         entityStream: OutputStream) : unit = {
23  
24      val l = t.asInstanceOf[List[_]];
25      val al = new java.util.ArrayList[Any]();
26      for (m <- l) {
27        al.add(m);
28      }
29  
30      super.writeTo(al, arrayListClass, arrayListClass,
31                    annotations, mediaType, httpHeaders, entityStream);
32    }
33  } 

The JacksonJsonProvider is extended and the methods associated with writing entities are overridden. This writer declares that the Scala type List is supported, at line 11, and the List is converted to an instance of java.util.ArrayList that Jackson understands when writing, at lines 24 to 28.

Using the Atmosphere spade server

The application is run using the Atmosphere spade server, which in turn uses embedded Grizzly Comet:

01  object ChatServer {
02    def main(args: Array[String]) {
03      try {
04        AtmosphereSpadeServer.build(args(0), "org.atmosphere.samples.lpchat").start();
05      } catch {
06        case ex : Exception => ex.printStackTrace;
07      }
08    }
09  }

Also since i was having much fun with JAX-RS, Jersey and Scala the HTML and JavaScript is returned from the following root resource class:

01  @Path("/")
02  class FilesResource {
03  
04    @Path("jquery{id}.js")
05    @GET
06    def getJQuery(@PathParam("id") ps : PathSegment) = new File(ps.getPath());
07  
08    @GET
09    def getIndex() = new File("index.html");
10  }

Passing thoughts

While it is obvious that this example is just a toy it does IMHO get across the concept on long polling rather well and example is very concise. I think this could be a good basis for a presentation to a JUG.

Examples such as this could also serve as the basis to develop common patterns and mechanisms in Atmosphere to manage lists of messages. The main problem in this respect is how store and retrieve messages. There are a myriad of ways and Atmosphere should preferably not dictate certain solutions in this respect e.g. perhaps i could convert the chat example to store and query messages using Couch DB?

Monday Nov 30, 2009

Jersey apps can now be deployed to Google App Engine

OK, it's not very exciting but you can go to the URL http://jersey-jax-rs.appspot.com/test/resource and should be able to receive the same response, including the trace headers i previously talked about.

I wanted to upload the Sparklines sample but the AWT graphics stuff is currently blacklisted (like java.awt.image.BufferedImage).

When you deploy a Jersey application to GAE you will currently get some errors in the logs in the logs such as:

com.sun.jersey.core.spi.component.ProviderFactory __getComponentProvider: 
The provider class, class com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$App, 
could not be instantiated. Processing will continue but the class will not be utilized

This is because Jersey cannot load the JAXB-related components as JAXB related classes are currently black listed. As i understand JAXB will be supported in Google App Engine version 1.2.8. So these deployment errors will go away.

The code is in the trunk and should take a couple of hours for artifacts to be pushed to the repo.

Friday Nov 27, 2009

Tracing in Jersey

A common complaint we have been hearing is that JAX-RS/Jersey can be hard to debug when the application is not behaving as expected, for example "why the \*!@& is my resource class not matching and instead the client is receiving a 404 response?"

It is difficult for the devloper to know what is going on because there is no visibility to how the request is matched and dispatched to the application.

A number of JAX-RS and Jersey features were inspired by Stapler the underlying Web/HTTP framework for Hudson. And tracing is another idea. With Hudson it is possible set a system property and trace messages in the form of response headers will be returned to the client, as described here.

Jersey now supports the same feature implemented in 1.1.5-ea-SNAPSHOT. Adding the following servlet/filter initialization parameter enables tracing:

<init-param>
    <param-name>com.sun.jersey.config.feature.Trace</param-name>
    <param-value>true</param-value>
</init-param>

If we modify the bookstore sample to include the above initialization parameter in the web.xml and go to the URL http://localhost:8080/bookstore/items/3/tracks/2/ then analyze the response headers using firebug we can see:

Trace headers have a number associated with. Not all clients or servers may preserve the order in which headers are written (the Jersey server and client does) so the numbering is useful to re-construct the order of tracing. It also helps when referring to a particular trace statement.

Trace 001:

X-Jersey-Trace-001  match path "/items/3/tracks/2/" -> "/application\\.wadl(/.\*)?", "/happy(/.\*)?", "(/.\*)?"

presents the request path and the initial set of regular expressions that will be matched, in order from left to right.

Trace 002:

X-Jersey-Trace-002  accept right hand path 
                        java.util.regex.Matcher[pattern=(/.\*)? region=0,18 lastmatch=/items/3/tracks/2/]: 
                        "/items/3/tracks/2/" -> "" : "/items/3/tracks/2/" 

presents what regular expression was matched in trace 001, "(/.\*)?". It is called "accept right hand path" because some left hand path of the request URI has been matched by an @Path declaration, "", leaving some right hand path of the request URI, "/items/3/tracks/2/", to be further matched (the URI matching process will terminate when there is no right hand path left).

Trace 003:

X-Jersey-Trace-003  accept resource: "" -> @Path("/") com.sun.jersey.samples.bookstore.resources.Bookstore@9f9655 

presents the resource that matched the left hand path in trace 002. In this case it is the Bookstore resource that is annotated with @Path("/").

Trace 004:

X-Jersey-Trace-004  match path "/items/3/tracks/2/" -> "/items/([\^/]+?)(/.\*)?", ""

presents a further match on the right hand path in trace 002.

Trace 005:

X-Jersey-Trace-005  accept right hand path 
                        java.util.regex.Matcher[pattern=/items/([\^/]+?)(/.\*)? region=0,18 lastmatch=/items/3/tracks/2/]: 
                        "/items/3/tracks/2/" -> "/items/3" : "/tracks/2/"

presents the left hand path, "/items/3", and the right hand path, "/tracks/2", that matched the regular expression, "/items/([\^/]+?)(/.\*)?", from the ordered set in trace 004.

Trace 006:

X-Jersey-Trace-006  accept sub-resource locator: "" : "items/3/" -> @Path("/items/{itemid}/") 
                        com.sun.jersey.samples.bookstore.resources.Bookstore@9f9655.getItem(java.lang.String) = 
                        com.sun.jersey.samples.bookstore.resources.CD@73a337 

presents the sub-resource locator that was invoked on the Bookstore resource. In this case it is the Java method getItem annotated with @Path("/items/{itemsid}"). This sub-resource locator returns an instance of the CD resource to match more of the right hand path, "/tracks/2".

The same pattern for traces 004 to 006 repeats itself for traces 007 to 009 with a sub-resource locator being matched on the CD resource that returns a Track resource.

Trace 010 indicates that URI matching has completed because there is no right hand path left and resource methods are ready to be matched.

Trace 011:

X-Jersey-Trace-011  accept resource methods: "items/3/tracks/2/", GET -> 
                        com.sun.jersey.samples.bookstore.resources.Track@6fb5ef

presents that resource methods will be matched on the Track resource for the GET request.

Trace 012

X-Jersey-Trace-012  accept implicit view: "" -> com.sun.jersey.samples.bookstore.resources.Track@6fb5ef, 
                      /com/sun/jersey/samples/bookstore/resources/Track/index.jsp 

presents that an implicit view has been selected to process the GET request. The Track resource is the controller and the model, the JSP "/com/sun/jersey/samples/bookstore/resources/Track/index.jsp" is the view that processes the model.

Trace 013

X-Jersey-Trace-013  matched message body writer: com.sun.jersey.spi.template.ResolvedViewable@817f19, 
                        "text/html;qs=5" -> com.sun.jersey.server.impl.template.ViewableMessageBodyWriter@9f17b1 

presents that a message body writer was matched to process the response entity returned by the implicit view in trace 012. The ViewableMessageBodyWriter is selected to write a ResolvedViewable with the media type "text/html;qs=5".

The above traces present how Jersey is returning an HTML page to the browser. Curl can be utilized to obtain XML instead:

$ curl -i http://localhost:8080/bookstore/items/3/tracks/2/
HTTP/1.1 200 OK
X-Powered-By: Servlet/3.0
Server: GlassFish v3
X-Jersey-Trace-000: accept root resource classes: "/items/3/tracks/2/"
X-Jersey-Trace-001: match path "/items/3/tracks/2/" -> "/application\\.wadl(/.\*)?", "/happy(/.\*)?", "(/.\*)?"
X-Jersey-Trace-002: accept right hand path 
                        java.util.regex.Matcher[pattern=(/.\*)? region=0,18 lastmatch=/items/3/tracks/2/]: 
                        "/items/3/tracks/2/" -> "" : "/items/3/tracks/2/"
X-Jersey-Trace-003: accept resource: "" -> @Path("/") com.sun.jersey.samples.bookstore.resources.Bookstore@19d1c871
X-Jersey-Trace-004: match path "/items/3/tracks/2/" -> "/items/([\^/]+?)(/.\*)?", ""
X-Jersey-Trace-005: accept right hand path 
                        java.util.regex.Matcher[pattern=/items/([\^/]+?)(/.\*)? region=0,18 lastmatch=/items/3/tracks/2/]: 
                        "/items/3/tracks/2/" -> "/items/3" : "/tracks/2/"
X-Jersey-Trace-006: accept sub-resource locator: "" : "items/3/" -> @Path("/items/{itemid}/") 
                        com.sun.jersey.samples.bookstore.resources.Bookstore@19d1c871.getItem(java.lang.String) = 
                        com.sun.jersey.samples.bookstore.resources.CD@4eb24759
X-Jersey-Trace-007: match path "/tracks/2/" -> "/tracks/([\^/]+?)(/.\*)?", ""
X-Jersey-Trace-008: accept right hand path 
                        java.util.regex.Matcher[pattern=/tracks/([\^/]+?)(/.\*)? region=0,10 lastmatch=/tracks/2/]: 
                        "/tracks/2/" -> "/tracks/2/" : ""
X-Jersey-Trace-009: accept sub-resource locator: "items/3/" : "tracks/2/" -> @Path("/tracks/{num}/") 
                        com.sun.jersey.samples.bookstore.resources.CD@4eb24759.getTrack(int) = 
                        com.sun.jersey.samples.bookstore.resources.Track@435792a0
X-Jersey-Trace-010: match path "" -> ""
X-Jersey-Trace-011: accept resource methods: "items/3/tracks/2/", GET -> 
                        com.sun.jersey.samples.bookstore.resources.Track@435792a0
X-Jersey-Trace-012: matched resource method: public com.sun.jersey.samples.bookstore.resources.Track 
                        com.sun.jersey.samples.bookstore.resources.Track.getXml()
X-Jersey-Trace-013: matched message body writer: com.sun.jersey.samples.bookstore.resources.Track@435792a0, 
                        "application/xml" -> com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$App@27cce278
Content-Type: application/xml

The traces are the same as previously presented up to trace 012. Trace 012 presents the resource method getXml that is invoked on the Track resource. Trace 013 presents that XMLRootElementProvider has been selected to serialize out Track with the media type "application/xml".

Like Stapler/Hudson Jersey also supports per-request tracing. Adding the following servlet/filter initialization parameter enables per-request tracing:

<init-param>
    <param-name>com.sun.jersey.config.feature.TracePerRequest</param-name>
    <param-value>true</param-value>
</init-param>
The client enables tracing by sending a request header "X-Jersey-Trace-Accept" with any value.

Thursday Nov 26, 2009

Jersey 1.1.4.1 is released

We have just released version 1.1.4.1 of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.0 specification and the 1.1 change log is available at the JCP web site and also available in non-normative HTML here.

This is a bug fix release for bugs that were found by community members who quickly tested the 1.1.4 release. Many thanks to Ari, Chris, Herak and Ian for reporting issues.

It will be available soon from the GlassFish v2 and v3 update centers, is included in the latest GlassFish v3 builds and, assuming there are no show stoppers, this version will be included in the final GlassFish v3 release scheduled for December 10th.

Looks like we are getting more demands to work on Google App Engine (based on comments on my previous blog and on the Jersey users list). This is going to require some re-factoring of certain functionality that utilizes javax.naming. But first i need to get a GAE account!

For feedback send email to:

users@jersey.dev.java.net (archived here)

or log a bugs/features here.

Thursday Nov 12, 2009

Jersey 1.1.4 is released

We have just released version 1.1.4 of Jersey, the open source, production quality, reference implementation of JAX-RS. The JAX-RS 1.0 specification and the 1.1 change log is available at the JCP web site and also available in non-normative HTML here.

It will be available soon from the GlassFish v2 and v3 update centers, is included in the latest GlassFish v3 builds and, assuming there are no show stoppers, this version will be included in the final GlassFish v3 release scheduled for December 10th.

For an overview of JAX-RS features read the Jersey user guide. To get started with Jersey read the getting started section of that guide. To understand more about what Jersey depends on read the dependencies section of that guide.

This release integrates with other Java EE 6 technologies such as Servlet 3.0, EJB 3.1, managed beans and JCDI 1.0 and contains many bug fixes. See change log here.

The next release, 1.1.5, is tentatively scheduled for December or January. Hopefully this time we can fully resolve the OSGi'ification of Jersey that we have been promising for a while. In addition, now that the Java EE 6 features are done, we hope to resume some experimentation and new features and ensure we have good integration with Atmosphere.

For feedback send email to:

users@jersey.dev.java.net (archived here)

or log a bugs/features here.
About

sandoz

Search

Categories
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