Archive for the ‘jsf’ Category

Serving multiple images from database as a CSS sprite

31 July 2013

Introduction

In the first public beta version of ZEEF which was somewhat thrown together (first get the minimum working using standard techniques, then review, refactor and improve it), all favicons were served individually. Although they were set to be agressively cached (1 year, whereby a reload is when necessary forced by the timestamp-in-query-string trick with the last-modified timestamp of the link), this resulted in case of an empty cache in a ridiculous amount of HTTP requests on a subject page with relatively a lot of links, such as Curaçao by Bauke Scholtz:

Yes, 209 image requests of which 10 are not for favicons, which nets as 199 favicon requests. Yes, that much links are currently on the Curaçao subject. The average modern webbrowser has only 6~8 simultaneous connections available on a specific domain. That’s thus a huge queue. You can see it in the screenshot, it took on an empty cache nearly 5 seconds to get them all (on a primed cache, it’s less than 1 second).

If you look closer, you’ll see that there’s another problem with this approach: links which doesn’t have a favicon re-requests the very same default favicon again and again with a different last-modified timestamp of the link itself, ending up in copies of exactly same image in the browser cache. Also, links from the same domain which share the same favicon, have their favicons duplicated this way. In spite of the agressive cache, this was simply too inefficient.

Converting images to common format and size

The most straightforward solution would be to serve all those favicons as a single CSS sprite and make use of CSS background-position to reference the right favicon in the sprite. This however requires that all favicons are first parsed and converted to a common format and size which allows easy manipulation by standard Java 2D API (ImageIO and friends) and easy generation of the CSS sprite image. PNG was chosen as format as that’s the most efficient and lossless format. 16×16 was chosen as default size.

As first step, a favicon parser was created which verifies and parses the scraped favicon file and saves every found image as PNG (the ICO format can store multiple images, usually each with a different dimension, e.g. 16×16, 32×32, 64×64, etc). For this, Image4J (a mavenized fork with bugfix) has been of a great help. The original Image4J had only a minor bug, it ran in an infinite loop on favicons with broken metadata, such as this one. This was fixed by vijedi/image4j. However, when an ICO file contained multiple images, this fix discarded all images, instead of only the broken one. So, another bugfix was done on top of that (which by the way just leniently returned the “broken” image — in fact, only the metadata was broken, not the image content itself). Every single favicon will now be parsed by ICODecoder and BMPDecoder of Image4J and then ImageIO#read() of standard Java SE API in this sequence. Whoever returned the first non-null BufferedImage(s) without exceptions, this will be used. This step also made us able to completely bypass the content-type check which we initially had, because we discovered that a lot of websites were doing a bad job in this, some favicons were even served as text/html which caused false negatives.

As second step, if the parsing of a favicon resulted in at least one BufferedImage, but no one was in 16×16 dimension, then it will be created based on the firstnext dimension which is resized back to 16×16 with help of thebuzzmedia/imgscalr which yielded high quality resizings.

Finally all formats are converted to PNG and saved in the DB (and cached in the local disk file system).

Serving images as CSS sprite

For this a simple servlet was been used which does basically ultimately the following in doGet() (error/cache checking omitted for simplicity):

Long pageId = Long.valueOf(request.getPathInfo().substring(1));
Page page = pageService.getById(pageId);
long lastModified = page.getLastModified();
byte[] content = faviconService.getSpriteById(pageId, lastModified);
 
if (content != null) { // Found same version in disk file system cache.
    response.getOutputStream().write(content);
    return;
}
 
Set<Long> faviconIds = new TreeSet<>();
faviconIds.add(0L); // Default favicon, appears as 1st image of sprite.
faviconIds.addAll(page.getFaviconIds());
 
int width = Favicon.DEFAULT_SIZE; // 16px.
int height = width * faviconIds.size();
 
BufferedImage sprite = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphics = sprite.createGraphics();
graphics.setBackground(new Color(0xff, 0xff, 0xff, 0)); // Transparent.
graphics.fillRect(0, 0, width, height);
 
int i = 0;
 
for (Long faviconId : faviconIds) {
    Favicon favicon = faviconService.getById(faviconId); // Loads from disk file system cache.
    byte[] content = favicon.getContent();
    BufferedImage image = ImageIO.read(new ByteArrayInputStream(content));
    graphics.drawImage(image, 0, width * i++, null);
}
 
ByteArrayOutputStream output = new ByteArrayOutputStream();
ImageIO.write(sprite, "png", output);
content = output.toByteArray();
faviconService.saveSprite(pageId, lastModified, content); // Store in disk file system cache.
response.getOutputStream().write(content);

To see it in action, you can get all favicons of the page Curaçao by Bauke Scholtz (which has page ID 18) as CSS sprite on the following URL: https://zeef.com/favicons/page/18.

Serving the CSS file containing sprite-image-specific selectors

In order to present the CSS sprite images at the right places, we should also have a simple servlet which generates the desired CSS stylesheet file containing sprite-image-specific selectors with the right background-position. The servlet should basically ultimately do the following in doGet() (error/cache checking omitted to keep it simple):

Long pageId = Long.valueOf(request.getPathInfo().substring(1));
Page page = pageService.getById(pageId);
 
Set<Long> faviconIds = new TreeSet<>();
faviconIds.add(0L); // Default favicon, appears as 1st image of sprite.
faviconIds.addAll(page.getFaviconIds());
 
long lastModified = page.getLastModified().getTime();
int height = Favicon.DEFAULT_SIZE; // 16px.
 
PrintWriter writer = response.getWriter();
writer.printf("[class^='favicon-']{background-image:url('../page/%d?%d')!important}", 
    pageId, lastModified);
int i = 0;
 
for (Long faviconId : faviconIds) {
    writer.printf(".favicon-%s{background-position:0 -%spx}", faviconId, height * i++);
}

To see it in action, you can get the CSS file of the page Curaçao by Bauke Scholtz (which has page ID 18) on the following URL: https://zeef.com/favicons/css/18.

Note that the background-image URL has the page’s last modified timestamp in the query string which should force a browser reload of the sprite whenever a link has been added/removed in the page. The CSS file itself has also such a query string as you can see in HTML source code of the ZEEF page, which is basically generated as follows:

<link id="favicons" rel="stylesheet" 
    href="//zeef.com/favicons/css/#{zeef.page.id}?#{zeef.page.lastModified.time}" />

Also note that the !important is there to overrule the default favicon for the case the serving of the CSS sprite failed somehow. The default favicon is specified in general layout CSS file layout.css as follows:

#blocks .link.block li .favicon,
#blocks .link.block li [class^='favicon-'] {
    position: absolute;
    left: -7px;
    top: 4px;
    width: 16px;
    height: 16px;
}
 
#blocks .link.block li [class^='favicon-'] {
    background-image: url("#{resource['zeef:images/default_favicon.png']}");
}

Referencing images in HTML

It’s rather simple, the links were just generated in a loop whereby the favicon image is represented via a plain HTML <span> element basically as follows:

<a id="link_#{linkPosition.id}" href="#{link.targetURL}" title="#{link.defaultTitle}">
    <span class="favicon-#{link.faviconId}" />
    <span class="text">#{linkPosition.displayTitle}</span>
</a>

The HTTP requests on image files have been reduced from 209 to 12 (note that 10 non-favicon requests have increased to 11 non-favicon requests due to changes in social buttons, but that’s not further related to the matter):

It took on an empty cache on average only half a second to download the CSS file and another half a second to download the CSS sprite. Per saldo, that’s thus 5 times faster with 197 connections less! On a primed cache it’s even not requested at all. Noted should be that I’m here behind a relatively slow network and that the current ZEEF production server on a 3rd party host isn’t using “state of the art” hardware yet. The hardware will be handpicked later on once we grow.

Reloading CSS sprite by JavaScript whenever necessary

When you’re logged in as page owner, you can edit the page by adding/removing/drag’n’drop links and blocks. This all takes place by ajax without a full page reload. Whenever necessary, the CSS sprite can during ajax oncomplete be forced to be reloaded by the following script which references the <link id="favicons">:

function reloadFavicons() {
    var $favicons = $("#favicons");
    $favicons.attr("href", $favicons.attr("href").replace(/\?.*/, "?" + new Date().getTime()));
}

Basically, it just updates the timestamp in the query string of the <link href> which in turn forces the webbrowser to request it straight from the server instead of from the cache.

Note that in case of newly added links which do not exist in the system yet, favicons are resolved asynchronously in the background and pushed back via Server-Sent Events. In this case, the new favicon is still downloaded individually and explicitly set as CSS background image. You can find it in the global-push.js file:

function updateLink(data) {
    var $link = $("#link_" + data.id);
    $link.attr("title", data.title);
    $link.find(".text").text(data.text);
    $link.find("[class^='favicon-']").attr("class", "favicon")
        .css("background-image", "url(/favicons/link/" + data.icon + "?" + new Date().getTime() + ")");
    highlight($link);
}

But once the HTML DOM representation of the link or block is later ajax-updated after an edit or drag’n’drop, then it will re-reference the CSS sprite again.

The individual favicon request is also done in “Edit link” dialog. The servlet code for that is not exciting, but for the case you’re interested, the URL is like https://zeef.com/favicons/link/354 and all the servlet basically does is (error/cache checking omitted for brevity):

Long linkId = Long.valueOf(request.getPathInfo().substring(1));
Link link = linkService.getById(linkId);
Favicon favicon = faviconService.getById(link.getFaviconId());
byte[] content = favicon.getContent();
response.getWriter().write(content);

Note that individual favicons are not downloaded by their own ID, but instead by the link ID, because a link doesn’t necessarily have any favicon. This way the default favicon can easily be returned.


This article is also posted on balusc.blogspot.com.

What’s new in JSF 2.2?

1 September 2012

jsf 2.2

Sample CRUD application with JSF and RichFaces

30 March 2012

During my thesis project I will be using JavaServer Faces. Therefore it is important I get familiar with the framework. To get familiar I made a small CRUD (Create Read Update Delete) application. It is a simple application that makes it possible to keep track of users. It consists of a user list, a page to add/edit users and a page to delete a user.

The code

The research project will focus on when it is beneficial to use client-side scripting instead of/complementary to server side programming. To get up to speed a small CRUD application has been made without the use of client-side scripting and the same CRUD application was adapted to use client-side scripting by using RichFaces. The client-side scripting was added to the editing form to allow validating the form, without the need of making requests to the server.

The structure of the source project is as follows:

  • backing
    • Index.java – Backing for index.xhtml
    • UserDelete.java – Backing for UserDelete.xhtml
    • UserEdit.java – Backing for UserEdit.xhtml
  • constraints
    • Email.java –  Validation annotation for fields. Fields with this annotation are validated to be a proper email address.
    • EmailConstraintValidator.java – Performs the validation for email addresses.
  • ejb
    • UserDAO.java – Data Access Object for users.
  • entities
    • User.java – Bean object for a user. The fields of this object are annotated with validators.
    • UserConvertor.java – Converts a userId to a user.
  • util
    • Messages.java – Utility object that helps with sending messages between pages.

The following JSF pages are in the project:

  • index.xhtml – Page with a list with all users
  • user_delete.xhtml – Page used to confirm whether a user should be validated
  • user_edit.xhtml – Page used for adding and editing users

While creating this application, I tried as much as possible to adhere to best practices. For examples, to go from the master (list) view to the detail (edit) view a GET request is used with the user id as parameter. The user is modified via POST and there’s a redirect and GET back to the master view (PRG pattern).

Both applications make use of Enterprise Java Beans, Bean Validation and Java Persistence API. EJB is used to inject persistence in the managed beans. Bean validation is used to ensure the data is consistent with the business rules.

In the RichFaces version user_edit.xhtml is updated to have client-side validations. Only the email address cannot be validated on the client. For that field is Ajax used.

The code of the project has been uploaded to Google Code so it can viewed by everyone. The code without the use of client-side scripting is put in the default branch and the code with client-side scripting is put in the RichFaces branch.

Demo

The compiled applications have been uploaded to OpenShift. It makes showing your work to the public very easy. This is a free cloud platform which runs a JBoss server. The projects can be directly uploaded from Eclipse to the OpenShift server. The live demo can be viewed here.

To upload your project yourself to OpenShift it is first required to make an account at OpenShift. Then register your public key at OpenShift. When you have the OpenShift plug-in installed in Eclipse you can add the OpenShift server to the server view in Eclipse. From there you can get the default project from OpenShift. This project is only used to send the war files to server, not to hold the code. By adding the JSF project to the OpenShift server it automatically places the war file in the OpenShift project during a publish. By pushing the OpenShift project to the server using GIT, the application is put in the cloud and is ready to use. The detailed process to upload to OpenShift from Eclipse is available here.

So wrapping up, I’ve made a small project to get familiar with the code, I have uploaded the code to Google Code and I’ve put the application OpenShift.

Mark van der Tol

JSF 2.0, a glance

27 August 2008

Having been recently thrown into the deep waters of JSF and Facelets it seemed natural to do an evaluation of where this technology is going. JSF is currently at version 1.2. Version 2.0 is scheduled for release with Java EE 6. So what goodies will this bring us?

The main goals of the revision is to make development easier by integrating into the core system many tools/frameworks which were built on top of previous JSF versions. Ajax support, facelets-like templating, improved development support and better performance are all things that are mentioned in the specifications.

These are the highlights of what is coming:

I’m sure everyone is familiar with Ajax. JSF 2.0 includes Ajax in its life cycle and offers more direct support for its use. The view state can now be partially updated to reflect that only part of the view has changed. Ajax will make use of the new resource handler scheme. This isn’t very exciting in and of itself. A natural progression in the way one would expect this technology to mature.

Facelets is another technology needing to be incorporated into 2.0. Facelets allows us to define our pages in a different way by using XML and templating. The way to write these pages is very close to the the way we already work, which makes it easy to learn. The added usefulness of templating allows us to write less cluttered pages. It also increases code reuse. The popularity of this approach and its obvious usefulness make it inevitable that this would be included in JSF 2.0. This is currently referred to as ‘page description language’ in the JSF specification. While the name is less exciting than Facelets it is accurate and there is no doubt that this is a welcome addition to JSF

Development for JSF is getting some support through the ‘Project_Stage’ feature. This is no more or less than a context parameter. Now many people are excited by this, but I don’t quite seem to share the sentiment. Theoretically this will allow for actions dependent on where the project is in its life. Is it in production, unit test, system test or development? The options are limited, though probably enough. What I am wondering is what it is doing in JSF. While there is a use for a setting like this, indeed it seems common in many disparate projects, it seems to me to be a higher level setting than JSF level. JSF should support it, but not claim it.

Another interesting feature is the Resource Handler. Resources are anything that could be included in a component that is required for the component to be rendered correctly to the user-agent. Think about images, JavaScript or css files. The Resource Handler enforces a structure on your resources which in and of itself just helps in organizing your project. This will also make it easier for component developers. They know exactly where to put or look for resources without having to know what application is using them. Locale and versioning are handled automatically. Another advantage is that replacing resources runtime will be much cleaner. No restart of the system should be needed.

There are some things about resources I don’t like however. First of all the specification only specifies a structure for webapps. Implementations for other platforms are even invited to do whatever they want. It seems an unfortunate choice since you really want a standard to be standard. Another is the relocatable resource. Now you can tell certain resources where they are supposed to be. Put the tag in the body but tell it to be rendered in the head. I don’t understand the reasoning for this. Perhaps if it is based on some conditional programming elsewhere on the page….but quite frankly your page is probably getting to complicated at that point. If something needs to be in the head (body, wherever), just put it there. I wonder if I am not missing some essential insight with which I will all of a sudden see what a great and useful feature this is.

One argument for relocatable resource is that components may wish to write things in locations which are outside of their direct knowledge. The head of an HTML document is an example. A component, possibly called by other components, could decide it wanted to change the head of a document. This is completely undesirable behavior. If the component is generic it should never bother with anything outside its scope. If it isn’t generic then its use is limited anyway and one could ask why it is even a component. Thinking specifically of style information I would say that this should never be overwritten at component level. Scripts can be included in the body and shouldn’t require anything beyond what exists in the component anyway. Apparently the community desires this functionality. To me it seems a harmful construct which should not be supported.

All in all I think JSF 2.0 will be an improvement of the technology. It has listened and learned from what the community has built on top of JSF and incorporated the features that were most used. As well it improves its internal workings which is never a bad thing from a user perspective. While I may not yet understand all the choices made it is obvious that the changes were well thought out and planned. Assuming the implementation is improved as well then JSF 2.0 will be pretty much what you want from version 2.0.

Jasper Floor

useful links:

css.php best counter