Saturday, November 7, 2009

Serving images and other resources with wicket

It took me couple of days and mailing list posts to figure out how to display images with wicket in a satisfactory way.
In my case images are stored in JCR but this could be any other repository like db or file system where arbitrary images could be added or removed over time.
I also want that images have stable (bookmarkable) URLs, which makes them suitable for indexing by web crawlers and caching by web browsers.
I first checked the wicket "bible" Wicket in Action but this use case is not treated there.

Finally it turned out wicket does provide a way to do it in simple Java - shared resource with parameters.

Define a class to serve images
Create a class e.g. Images extending WebResource. Essentially this class has to implement the method getResourceStream(), which should return an IResourceStream implementation. (IResourceStream provides the actual data stream in terms of InputStream, data size, content type, etc.) The important thing here is that Images class can call inherited method getParameters() to get the query parameters (as ValueMap) from the URL. These parameters can be used to identify the specific image to be streamed. Something like this
    String imageId = getParameters().getString("id");

Bind the image serving class
The Images class created above can be bound to a specific URL, so whenever this URL is requested, the bound object is used to stream the response. This is done in the application init() method.
    getSharedResources().add("images", new Images());
This would produce image URLs like resources/org.apache.wicket.Application/images. To shorten the URLs to resources/global/images, add this again in init() method
    getSharedResources().putClassAlias(
        org.apache.wicket.Application.class, "global");

Display an image
Finally, use this to put an image on a page
    new Image("image", new ResourceReference("images"), 
        new ValueMap("id=" + imageId))
This will result in image URL like resources/global/images?id=image105

Of course this mechanism could be used for any kind of resource (e.g. PDF documents). It is only a matter of Content-Type.

5 comments:

  1. Thanks! This is exactly what I need.

    ReplyDelete
  2. I read it too late :)

    Nice solution.

    ReplyDelete
  3. thank you for you useful post. It would be great if you describe your way to integrating JCR and wicket.

    ReplyDelete
  4. Done. I have described briefly my approach to integrating JCR and wicket. Check it out.

    ReplyDelete
  5. hello sir could you please tell me that where can I put the below code ?

    new Image("image", new ResourceReference("images"),
    new ValueMap("id=" + imageId))

    ReplyDelete