Earthly Powers
- All
- Fast Infoset
- General
- Java
- REST
GlassFish @ Oracle
Two very interesting comments on the server-side from Mike Lehman and Eduardo about GlassFish @ Oracle.
This clarifies some mis-interpretations and counters some prematurely shot FUD.
Mike states at the end of his comment:
We are very excited to have GlassFish on board at Oracle. Areas like GlassFish proper and key constituent pieces like Metro, Grizzly, Jersey etc are state of the art; there is huge incentive to shepherd them correctly. You will have to judge us on how we execute over the next few months while we realign roadmaps and delivery schedules but I hope we can surprise folks with some good turns we can do as a combined company.
Eduardo states at the end of his comment:
So, my suggestion to GlassFish fans is to please give us some time to put together that roadmap, and then use it to make your own decisions.
Posted at 11:38AM Feb 03, 2010 by Paul Sandoz in Fast Infoset | Comments[0]
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:
or log a bugs/features here.users@jersey.dev.java.net (archived here)
Posted at 06:46PM Jan 20, 2010 by Paul Sandoz in REST | Comments[3]
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.
Posted at 05:05PM Dec 10, 2009 by Paul Sandoz in REST | Comments[0]
Spin Spin Spin
In this article Steve Mills of IBM is to have said:
Oracle’s proposed acquisition of Sun Microsystems did not raise any significant antitrust issues and was likely to close soon in spite of objections raised in Brussels, according to Steve Mills, head of IBM’s software division and one of Oracle’s biggest rivals.
Then the some spinmeister is to have said:
An opponent of the deal said IBM’s comments were an indication that competition concerns were well founded.
LOL. Do you feel the cognitive dissonance :-)
The spin against Eben Moglen was, to some, more disgusting:
Isn't that disgusting? Blow his own horn much? Moglen "unimportant in a GPL context"?
The best definition of spin i have seen was proposed by Dan Dennett. The "Cannons of good spin":
- It is not a bare-faced lie.
- You have to be able to say it with a straight face
- It has to relieve skepticism without arousing curiosity
- It should seem profound
Posted at 01:42PM Dec 09, 2009 by Paul Sandoz in General | Comments[0]
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:
- when a client makes a request and the server has data, that data is returned immediately and the connection is not suspended.
- 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?
Posted at 10:09PM Dec 08, 2009 by Paul Sandoz in REST | Comments[1]
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.
Posted at 11:24AM Nov 30, 2009 by Paul Sandoz in REST | Comments[5]
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-002accept 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-005accept right hand pathjava.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-006accept 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-011accept 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-012accept 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-013matched 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:
The client enables tracing by sending a request header "X-Jersey-Trace-Accept" with any value.<init-param> <param-name>com.sun.jersey.config.feature.TracePerRequest</param-name> <param-value>true</param-value> </init-param>
Posted at 03:46PM Nov 27, 2009 by Paul Sandoz in REST | Comments[3]
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:
or log a bugs/features here.users@jersey.dev.java.net (archived here)
Posted at 11:15AM Nov 26, 2009 by Paul Sandoz in REST | Comments[3]
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:
or log a bugs/features here.users@jersey.dev.java.net (archived here)
Posted at 04:12PM Nov 12, 2009 by Paul Sandoz in REST | Comments[5]
Naming, buying and reading
The title of this blog may be misconstrued as a pithy philosophical statement about life, the universe and everything.
Naming things can be tricky and inspiration comes from many sources.
While pondering a name for this blog a reoccurring thought distracted my consciousness yet again: "I must buy and read Earthly Powers by Anthony Burgess!". Free association did the rest, and the title would serve a duel purpose as a memento.
This week my copy of Earthly Powers arrived in the post.

Now i have to remind myself to read it, and an opportunity presents itself. I am on holiday from the 8th September for 2 weeks. This is a big tome, 650 pages of small print, requiring sustained concentration and time, both of which are a scarce commodity when an energetic toddler demands a 100% of both. So... we shall see...
Posted at 02:25PM Sep 05, 2009 by Paul Sandoz in General | Comments[0]
Guice 2.0 is almost there, but not quite
Guice 2.0 is a clean and well-thought-out framework for modularization and dependency injection. It is really good, but it could be really really good with a couple of tweaks.
James Strachan created GuiceyFruit in an effort to move Guice from "really good" to "really really good", or say from 95% there to 99% there. Some patches from GuiceFruit got accepted in Guice 2.0 but some are still pending so GuiceyFruit maintains a patched version of Guice 2.0 for it's own needs.
Jersey depends on GuiceyFruit and the patched Guice 2.0 for it's Guice support (although it is possible to use "native" Guice if you are not using any GuiceyFruit features).
Currently with Guice 2.0 i cannot integrate support for the binding of JAX-RS types and annotations. I would like to be able to do the the following with Guice/Jersey/JAX-RS:
@RequestScoped
@Encoded
public class MyResource {
private final String q;
@Inject
public class MyResource(@DefaultValue("foo") @QueryParam("q") String q) {
this.q = q;
}
}
But, currently as far as i am aware, it is not possible for two reasons:
- a provider binding does not have any context to what it is providing to; and
- an annotation that is not meta-annotated with @BindingAnnotation cannot be utilized as a binding annotation.
A good example of the complexity that results due to lack of support for 1) is presented in the section on Custom Injections of the Guice User's Guide. This section presents an example of how to support injection of a org.apache,log4j.Logger instance with fields annotated with the custom annotation @InjectLogger. The logger instance is initiated with the declaring class of the field.
The developer is required to implement a TypeListener that iterates through the fields of the class to find an appropriate field to inject a Logger, and a MembersInjector that injects the instance of the Logger onto the appropriate field.
While these interfaces are useful they are over-complex for such a use-case and the developer cannot use @Inject with Logger for constructor, method and field injection.
The injection of Logger can be reduced to a provider method of a module if Guice could support the injection of InjectionPoint:
@Provides
public Logger providerLogger(InjectionPoint ip) {
return Logger.getLogger(ip.getMember().getDeclaringClass());
}
With respect to the JAX-RS example a provider of the String type annotated with @QueryParam requires access to the annotations declared on the constructor parameter and the annotations declared on the defining class (it does not appear possible to get access to the former with InjectionPoint so that would require some tweaks as well).
Moving on to reason 2). If Guice supported the following binding in a module:
declareAnnotationAsBindingAnnotation(QueryParam.class); bind(String.class) .annotatedWith(QueryParam.class) .toProvider(QueryParamProvider.class);
then it would be possible for Jersey to supply a Jersey-specific Guice module that supported all the Jersey and JAX-RS annotations in addition to enabling developers to easily add their own providers for such annotations.
If Guice could do that it would be 99% there IMHO and would be a really really good dependency injection framework.
Posted at 03:30PM Aug 28, 2009 by Paul Sandoz in Java | Comments[1]
Jersey 1.0.3.1 and 1.1.2-ea are released
We have just released versions 1.0.3.1 and 1.1.2-ea of Jersey, the open source, production quality, reference implementation of JAX-RS.
Version 1.0.3.1
Version 1.0.3.1 implements the JAX-RS 1.0 API. The JAX-RS 1.0 specification is available here.
It will be available soon from the GlassFish v2 and v3 update centers, and will ship with GlassFish v2.1.1.
To get started read the getting started document. For an overview of JAX-RS features read the Jersey user guide. To understand more about what Jersey depends on read the dependencies document.
This release contains a few important fixes (most notably a security fix for XML processing). See change log here.
Version 1.1.2-ea
Version 1.1.2-ea of Jersey, implements the draft JAX-RS 1.1 API. The draft JAX-RS 1.1 specification is available here.
It will be available soon from the GlassFish v2 and v3 update centers, and will ship with Glassfish v3 Milestone 6 (see schedule) in addition to the nightly and promoted builds.
To get started with Jersey read the getting started document. For an overview of JAX-RS features read the Jersey user guide. To understand more about what Jersey depends on read the dependencies document.
This is mostly a minor enhancement and bug fixing release. See change log here.
Naresh and I worked on improving the Jersey Test Framework. This breaks compatibility with the previous version in 1.1.1-ea but hopefully developers will see the improvements (note that many but not all Jersey samples use the test framework and eventually all samples will use it). See the API here.
Pavel worked on integrating some very basic GlassFish probes into the hierarchical matching algorithm and has wired them up to the GlassFish monitoring framework so it is possible to report simple statistics on which resource classes get matched to request URIs.
Two interesting developments of note:
- The Glassfish v3 RESTful interface for management and monitoring is progressing nicely. It needs to use a Jersey container request filter to massage the Accept header such that if HTML and XML-based media types are present the former always has the higher quality. Then the HTML representations will be returned when Safari is used.
- Akka is an Actor-based framework with Software Transactional Memory that is written in Scala. It can expose it's components RESTfully using Jersey and Cometfully ( ;-) ) using Atmosphere.
Next release
The next release, 1.1.3, is tentatively scheduled for the final release of Glassfish v3 in November and is dependent on alignment with other EE 6 technologies such as Servlet 3.0 and JSR 299/330. In addition we plan to implement full OSGi support thanks to the help and guidance of Richard Wallace (unfortunately we had no time to implement that for 1.1.2).
For feedback send email to:
or log a bugs/features here.users@jersey.dev.java.net (archived here)
Posted at 02:44PM Aug 26, 2009 by Paul Sandoz in REST | Comments[0]
The course of true love never did run smooth
Posted at 07:47PM Jul 16, 2009 by Paul Sandoz in Java | Comments[0]
Jersey 1.1.1-ea is released
We have just released version 1.1.1-ea of Jersey, the open source, production quality, reference implementation of the draft JAX-RS 1.1 API. 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, and will be shipped with the latest GlassFish v3 builds.
To get started with Jersey read the getting started document. For an overview of JAX-RS features read the Jersey user guide. To understand more about what Jersey depends on read the dependencies document.
Between releases there has been some very interesting developments with a "sister" projected called Atmosphere. If you are interested in portable Comet support and how to avail of high-level ease of use support with Jersey check out JFA's latest blog entries.
This release took a little longer than expected with holidays post JavaOne, alignment with a version of JAXB for JSON namespace related features, a last minute XML-related security fix, and being hindered by the java.net infrastructure:
- Jakub has implemented the eagerly anticipated JSON namespace support for "mapped" (the default) and the "natural" conventions. In addition we have re-factored the JSONJAXBContext such that developers can use it to marshal and unmarshal JSON with JSONMarshaller and JSONUnmarshaller respectively.
- Paul Bryan and Hubert Le Van Gong have added OAuth which comprises Jersey client and server support that leverages an OAuth signature library. The modules are currently located here, but for 1.1.2-ea-SNAPSHOT and future releases they are located here.
- James Strachen has integrated support for lift templates with Jersey's MVC framework. The module is located here. To see Jersey, Scala and lift in action check out the RestMQ project.
See change log here.
The next release, 1.1.2-ea or 1.1.2, is tentatively scheduled for late August 2009 and is dependent on alignment with other EE 6 technologies such as Servlet 3.0 and JSR 299/330. In addition we plan to implement full OSGi support thanks to the help and guidance of Richard Wallace.
For feedback send email to:
users@jersey.dev.java.net (archived here)
or log a bugs/features here.
Posted at 05:02PM Jul 15, 2009 by Paul Sandoz in REST | Comments[9]
Devoxx 2008 interview with Ted Neward
Hot on the heals of the my JAX-RS Devoxx 08 presentation on Parleys (2,094 views so far, that is my biggest audience yet :-) ) is the interview i did with Ted Neward. This was the first time i have done something like that, but i found Ted put me at ease and i enjoyed the discussion.
Posted at 11:27AM Jun 29, 2009 by Paul Sandoz in REST | Comments[0]