Monday, October 31, 2011

RHQ 4.2 released

The RHQ team is proud to have released version 4.2 of the systems management and monitoring framework.

 

 

This release focuses on:

  • UI enhancements / bug fixing
  • Completion of drift management (this allows you to e.g. detect changes to files on your managed platform and to alert on such drift)
  • Improvements in server config sync (you can basically take (parts of) the configuration of one RHQ server and apply it to a different RHQ server).

In addition to that, the release is the very first to have a (limited) REST interface. Another change is the added support for PostgreSQL 9.1.

We want to thank

  • Ted Won for contributing Korean installer messages
  • Rafael Torres for improvements to the Twitter plugins (OAuth support)
  • All community members that provided input and bug reports

As always check the release notes for a more complete list of changes. You can get the downloads from sourceforge. And please provide us feedback; for the REST interface we are also looking for usage examples.

 

Heiko Rupp will showcase RHQ 4.2 at the November meeting of the London JBUG.

Thursday, October 27, 2011

Evolving interface in REST with JAX-RS (updated)

[update] In the earlier version I had if (mediaType==MediaType.xxx), which is wrong. MediaType is no enum, so we need to compare via .equals()[/update]

 

So in RHQ we've introduced the REST api and one of the nice things is the ease of use like this:

  @GET
@Path("/customer/{id}")
public Customer getCustomer(@PathParam("id") int custId) ;

where the implementation code e.g. looks up a Customer object in  the database and then returns it. Clean expressive API.

Now things start getting more interesting when you consider returning XML, JSON and HTML versions of the document. The first naive way goes like this:

  @GET
@Path("/customer/{id}")
public Customer getCustomer(@PathParam("id") int custId) ;

Which fails big time for HTML as (at least RESTEasy) does not know how to serialize the Customer object into HTML. So the next version of the API could look like this:

  @GET
@Path("/customer/{id}")
@Produces({"application/json","application/xml"})
public Customer getCustomer(@PathParam("id") int custId) ;

and

 @GET
@Path("/customer/{id}")
@Produces("text/html")
public String getCustomerHtml(@PathParam("id") int custId) ;

Where both methods get the customer from the backend. The first one then returns the object directly (as above) whereas the second one renders the object with the help of Freemarker templates into a HTML string and returns this one. Just returning String in both cases is also not working as one may think. So this two methods that internally use almost the same code (actually the *Html one calls the other to retrieve the Customer object).

This works quite nicely, but now I want to start adding explicit return codes (and also caching information). JAX-RS offers the Response class for this, where you can e.g. say Response.ok() or Response.notFound(). So the interface changes to

  @GET
@Path("/customer/{id}")
@Produces({"application/json","application/xml"})
public Response getCustomer(@PathParam("id") int custId) ;

and

 @GET
@Path("/customer/{id}")
@Produces("text/html")
public Response getCustomerHtml(@PathParam("id") int custId);

Internally we have the same situation as before, but can now explicitly return the result codes we want. This is still not optimal. Luckily JAX-RS allows to inject the Request and the HttpHeaders into the called Java-method, so that we can now write

  @GET   
@Path("/customer/{id}")   
@Produces({"application/json","application/xml","text/html"})   
Response getCustomer(@PathParam("id") int custId,
@Context HttpHeaders headers);

and then in the implementation do the following:

  MediaType mediaType = headers.getAcceptableMediaTypes().get(0);
  ResponseBuilder builder = ...
  if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
String html = renderTemplate("customer", customer);
     builder = Response.ok(html, mediaType);
}
else {
builder = Response.ok(customer);
}

So now we have one method doing all the work for us without code duplication and which can then use the same logic for caching and e.g. paging or linking.

Support for caching is now only one more step away:

  @GET   
@Path("/customer/{id}")   
@Produces({"application/json","application/xml","text/html"})   
Response getCustomer(@PathParam("id") int custId,
@Context Request request,
@Context HttpHeaders headers);

and in the implementation

  // Check for conditional get
  String tagString = Integer.toString(customer.hashCode());
EntityTag eTag = new EntityTag(tagString);       
Date lastModifiedInDb = new Date(customer.getMtime();

Response.ResponseBuilder builder = request.
evaluatePreconditions(lastModifiedInDb,eTag);
  if (builder==null ) { 
    // we need to send the full resource
if (mediaType.equals(MediaType.TEXT_HTML_TYPE)) {
String html = renderTemplate("customer", customer);
     builder = Response.ok(html, mediaType);
} else {
builder = Response.ok(customer);
}
  builder.tag(eTag); // Set ETag on response

There is of course still a lot to do, but we have now achieved :

  • uniform interface independent of the media type
  • support for conditional sending and thus caching and re-validation by ETag and time stamp

The last step is to add some hints to the client how long it may cache data without the need to go out to the network to do any caching at all. Again JAX-RS has already support for that:

  // Create a cache control       
CacheControl cc = new CacheControl();       
cc.setMaxAge(300); // Customer objects are valid for 5 mins       
cc.setPrivate(false); // Proxies may cache this
builder.cacheControl(cc);
 
This gives the client a hint, that they can consider the customer object valid for 300s = 5min. Proxies on the way are also allowed to cache the returned object. In practice one may make the maxAge depending on e.g. some average update frequencies and also set the "you need to always verify" flag via cc.setMustRevalidate(true).

I am sure, this is not yet the last version of the interface, but you can see how it can evolve over time and add new features like support for conditional get. And the best part is that so far the clients don't even have to change a single line of code.

In the future we may want to introduce our own media types like appliation/vnd.rhq-customer+json that newer clients then can make use of. The server can dispatch as seen above the media type and return the appropriate representation. The existing clients, that do not know the new media type can still be serviced by the server just sending this "old" version of it.

 

Monday, October 24, 2011

RHQ and JBoss ON at JBug London (updated)

global_31838371.jpeg

I will talk on monday, Nov 28th at the London (UK) JBoss User Group about RHQ and JBoss ON. The talk will give an overview over RHQ and JBoss ON, showcase the new features in RHQ 4.2 and also talk a little bit about the new REST api.

The talk venue is the Skills matter eXchange, where the meetup page has the link to the location and also a link to the registration.

The guys from C2B2 also created a cool poster:

JBUG+November.jpg

 

Friday, October 14, 2011

Small recap of JBoss One Day Talk in Munich (updated)

Yesterday I was at JBoss One Day Talk, organized by the local JBoss Users Group. The schedule consisted of 18 sessions in three parallel tracks.

jboss-header.png

One of the main topics was of course JBoss AS 7, where Heiko Braun was giving an overview, Thomas Diesler talking about OSGi on AS7 and myself talking about management of the server doing a lot of live demoing.

Other JBoss speakers included Kris Verlaenen on JBPM5 and Sashin Shinde on Open Shift. And there was Gavin King announced to talk about Ceylon. While I was looking forward to meet Gavin again, I was also afraid that I would need to talk only to myself with the Ceylon talk being in parallel. (Un :-)fortunately Gavin was not able to make it, so I had a great audience.

My buddy Pavlo Baron was talking about Big Data (slides are available on Slideshare). While this presentation was not as technical as I hoped, it nevertheless got me thinking about some stuff we could integrate in a future version of RHQ.

This conference was organized for the second time this year and I like the intimate atmosphere a lot. And of course the speakers dinner at Löwenbräukeller :-)

Update:

The organizers of One Day Talk have posted some interviews (in German) -- and especially one with Heiko Braun