miércoles, 27 de abril de 2011

Speeding up a seam application from the front-end II

There are many articles in the internet about the time spent when displaying a webpage and where is wasted the most of it, an average of the time spent would be about the 20% of the time in the server side and the 80% in the front end. If you develop a web application probably these values will be more balanced since the server alos has quite an important part into the results.

Anyway we'll focus in that front end that takes around 80% of our time when browsing the web. There are 2 main things to focus on, one is the amount of request and the other the size of the response.

In the first part we focused into the amount and time spend for the http request. So in this one we'll see how to optimize the size of a request. In order to do that we'll:
  1. Components IDs:
    The id of the components, when parsed for Ajax4jsf if are not present they’ll be assigned by the parser automatically which doesn’t allow using selenium for testing in the page and the difficulty for reading for maintenance of the application is increased.

    Because of it is highly recommended to assign manually the IDs to the components, but since the Ajax parser will join all the IDs using a semicolon to differentiate them is an appropriate approach to try to keep the IDs as short as possible so the size of the page is kept small.

  2. Context Root
    The same applies to the view IDs, we need to set in the jboss-web.xml the context-root parameter so we keep it as short as possible. That way we call the app straight, for instance we can leave like <context-root>/</context-root> so we don’t put anything before the name of the page.

  3. A4J Support
    Try to use a4j:support instead of the already provided a4j commandButtons and commandLinks. The code is re-usable and the amount of code generated by the javascript library for that component is slightly smaller than the one used for the other ones.

  4. Gzip components
    When transferring HTTP request through the network, the time it takes to transfer all the data seems usually out of our control, since it relies on bandwidth. Anyway there is a thing we can do to improve the response, and is compress the components we are about to sent through the network.

    Starting with HTTP/1.1, web clients indicate support for compression with the Accept-Encoding header in the HTTP request, i.e: Accept-Encoding: gzip, deflate. If the web server sees this header in the request, it may compress the response using one of the methods listed by the client. The web server notifies the web client of this via the Content-Encoding header in the response, i.e: Content-Encoding: gzip.

    For the Jboss AS to enable the gzip compression we have to modify the file deploy/jbossweb.sar/server.xml , look for this piece of code:
    <Connector protocol="HTTP/1.1" port="8080" address="${jboss.bind.address}" connectionTimeout="20000" redirectPort="8443" />

    And change it for:
    <Connector protocol="HTTP/1.1" port="8080" address="${jboss.bind.address}" compression="on"
    compressableMimeType="text/html,text/xml,text/css,text/javascript, application/x-javascript,application/javascript"
    connectionTimeout="20000" redirectPort="8443"
    />
  5. Improve your CSS and Javascript files
    A common way to ensure that the request are the minimum as possible when developing with technologies different than Richfaces is merge all the stylesheet and script into single files, so we only have one file for CSS and one for Javascript. This way we only have to send 2 request at the beginning and the browsers will caches all the information only the first time the page is loaded.

    In RichFaces anyway we can pack all the JavaScript and CSS in its component set and deliver them in two requests on the very first page in the application and ensure that the browser caches them on all future requests. To enable this feature, add the following two context parameters to the /WEB-INF/web.xml file:
    <context-param> <param-name>org.richfaces.LoadStyleStrategy</param-name> <param-value>ALL</param-value> </context-param>
    <context-param> <param-name>org.richfaces.LoadScriptStrategy</param-name> <param-value>ALL

    Because of this approach is important to avoid CSS expressions and try to minify the Javascript and CSS. CSS expressions are the ones of type
    background-color:expression((new Date()).getHours()%2 ? "#B8D4FF":"#F08A00");

    These expressions were largely used while IE5 was released, since IE8 has been deprecated due to massive cost of rendering time, the expression was evaluated once and another every time the page was rendered, resized, scrolled or even when the user moves over the page. The expressions where anyway not possible to use with other browsers, so try to avoid them as much as possible.

    Minification is the practice of removing unnecessary characters from code to reduce its size thereby improving load times. When code is minified all comments are removed, as well as unneeded white space characters (space, newline, and tab). In the case of JavaScript, this improves response time performance because the size of the downloaded file is reduced. A tool that can be used for minification of Javascript along with CSS is YUI Compressor from Yahoo!

    Once all this is done, remember to put the stylesheet in the top of the document (template) and the Javascript at the bottom to ensure that they are loaded when it’s intended so we avoid the typical “blank” page while loading. Remember that in IE @import behaves the same as using <link> at the bottom of the page, so it's best not to use it.

    Last thing to keep in mind is try to keep the path to the css and javascript files as small as possible, anyway it is possible to reduce the size of the css including it into a gzip file, when including this file as css-stylesheet the resource will be unpacked

  6. Reduce complexity of the page
    Reduce the complexity of the page is good not only for the speed of the page but also for the reutilization of code and maintainability of the application. The easier the better is the approach that we might use here.

    A complex page means more bytes to download and it also means slower DOM access in JavaScript. It makes a difference if you loop through 500 or 5000 DOM elements on the page when you want to add an event handler for example.

    A good approach for that is to re-use as much pieces of code as possible, this way we can optimize the number of elements rendered in one piece of code and have an impact in the whole web applications. Such pieces can be menus, filters, layouts, tables’ headers and bodies…

    Also avoid fixing layout with JavaScript since accessing DOM elements with JavaScript is extremely slow.

  7. Keep cookie’s size small
    It's important to keep the size of cookies as low as possible to minimize the impact on the user's response time.

    Opposite with the cache, in the cookies, to add an early expires date or none, removes the cookie sooner, improving the user response time.

  8. Optimize images
    First of all, avoid using GIFs when possible, anything a GIF can do, a PNG can do (only animations are the difference), besides if the gif is not optimized to use the palette corresponding to the amount of colors used in the image there is some space wasted. Also, GIFs images are usually bigger than the PNG images.

    If Possible use either PNG or JPEGs, for the first one, try to run some optimization program like pngcrushjust in case there is some possible space for optimization.

    Please, don’t scale images in HTML, use an appropriate size of the image for each picture.

    Try to use CSS sprites, in order to do that follow this tutorial

lunes, 25 de abril de 2011

Speeding up the seam application from the front side I

There are many articles in the internet about the time spent when displaying a webpage and where is wasted the most of it, an average of the time spent would be about the 20% of the time in the server side and the 80% in the front end. If you develop a web application probably these values will be more balanced since the server alos has quite an important part into the results.

Anyway we'll focus in that front end that takes around 80% of our time when browsing the web. There are 2 main things to focus on, one is the amount of request and the other the size of the response.

In this first part we'll focus in the amount and time spend for the http request. To optimize that we'll follow these points:
  1. Minimize HTTP Requests:
    The most of the time when rendering a web page if everything is ok with the back-end is spent in the front-end, because of that is important to reduce its time as much as possible. An important and key way to achieve this is reduce the amount of components needed in the page, since each component needs a request for it, reduce the number of them improves in an important way the time it takes to load the page.

    There are several ways to achieve this, the most important are to combine the scripts, stylesheets, or images into singles files. Also using expires or cache control header for components reduces significantly the amount of requests needed to render a page when the page has been visited at least once before.

  2. Using Expires or a Cache-Control Header
    A first-time visitor to your page may have to make several HTTP requests, but by using the Expires header you make those components cacheable. This avoids unnecessary HTTP requests on subsequent page views. Expires headers are most often used with images, but they should be used on all components including scripts, stylesheets, and Flash components.

    Browsers (and proxies) use a cache to reduce the number and size of HTTP requests, making web pages load faster. A web server uses the Expires header in the HTTP response to tell the client how long a component can be cached. This is a far future Expires header, telling the browser that this response won't be stale until April 15, 2015.
    Expires: Thu, 15 Apr 2015 20:00:00 GMT
    If your server is Apache, use the ExpiresDefault directive to set an expiration date relative to the current date. This example of the ExpiresDefault directive sets the Expires date 10 years out from the time of the request.
    ExpiresDefault "access plus 10 years"
    For Seam applications using Richfaces it can be set through web.xml for instance for 1 year:
    <context-param>
    <param-name>org.ajax4jsf.DEFAULT_EXPIRE</param-name>
    <param-value>31536000</param-value>
    </context-param>

    Anyway due to a “bug” in Jboss Web which at the end of the day is a fork of Tomcat Without the "public" parameter on Cache-control header tag, under a HTTPS connection, the browser will NOT perform disk cache, this is important because that means that every time my user restart the browser and come into my web application all of my Richfaces resources's will be sent to him again, that way no matters what I set on "org.ajax4jsf.DEFAULT_EXPIRE" context parameter, the maximum time for the cache will be determined by the browser restart.

    With the "public" parameter the browser will do the disk cache and if I want that the Richfaces resources be cached for 6 months, they will be.

    There is a workaround which is available since JBoss-3.2.6+ which supports a WEB-INF/context.xml descriptor who allows to customize a war context. This way we can disable the Cache-Control header setting the property “disableProxyCaching” to false
    <Context>http://www.blogger.com/img/blank.gif
    <Valve className="org.apache.catalina.authenticator.FormAuthenticatorhttp://www.blogger.com/img/blank.gif"
    disableProxyCaching="false" ></Valve>
    </Context>
    Anyway in IE there is a bug where the pdfs and other Microsoft Offices items are not possible to cache for download under SSL connections, the bug is well described here anyway most of the issues for this using Richfaces will be solved when Richfaces 4.0.0 will be out as can be seen in this JIRA issue. Keep in mind, if you use a far future Expires header you have to change the component's filename whenever the component changes. A good approach is attaching to the filename the version number of the web application deployed.

  3. Avoid Redirects
    Redirects slow down the user experience. Inserting a redirect between the user and the HTML document delays everything in the page since nothing in the page can be rendered and no components can start being downloaded until the HTML document has arrived.

    To do it in our Jboss Seam application we have 2 options, either use URLRewrite Filter or follow the instructions for JBoss Web. I rather prefer the first one since its more flexible and portable even do the 2nd one is probably faster.

  4. Post-load and Pre-load Components
    We can check what needs to be loaded initially with our webapp and load in the background the other stuff later. The users are more likely to wait for something concrete to load than wait for a “blank” page until it finishes loading. This is known as Post-load.

    In order to perform this with Seam and JSF we write a Javascript Function to reload the part of the page that we want to be post-loaded until the value of the fields are there.

    Pre-load occurs when we have finished loading a page and the browser is idle. In order to use that idle time for later we can start loading resources in the background that we are going to use afterwards, same way Google.com works, that way we can simulate and effect of “instant” loading when the user navigates to the next expected page.

    There are actually several types of preloading:

    • Unconditional preload - as soon as onload fires, you go ahead and fetch some extra components. Check google.com for an example of how a sprite image is requested onload. This sprite image is not needed on the google.com homepage, but it is needed on the consecutive search result page.

    • Conditional preload - based on a user action you make an educated guess where the user is headed next and preload accordingly. On search.yahoo.com you can see how some extra components are requested after you start typing in the input box.

    • Anticipated preload - preload in advance before launching a redesign. It often happens after a redesign that you hear: "The new site is cool, but it's slower than before". Part of the problem could be that the users were visiting your old site with a full cache, but the new one is always an empty cache experience. You can mitigate this side effect by preloading some components before you even launched the redesign. Your old site can use the time the browser is idle and request images and scripts that will be used by the new site.
  5. Don't use iframe
    The use of iframes blocks the page onload and are costly even if blank, despite of the benefits it could have it is better to avoid the use of it when possible.

  6. Use sub domains for components
    When the browser makes a request for a static image and sends cookies together with the request, the server doesn't have any use for those cookies. So they only create network traffic for no good reason. You should make sure static components are requested with cookie-free requests. Create a subdomain and host all your static components there.

    If your domain is www.example.org, you can host your static components on static.example.org. However, if you've already set cookies on the top-level domain example.org as opposed to www.example.org, then all the requests to static.example.org will include those cookies. In this case, you can buy a whole new domain, host your static components there, and keep this domain cookie-free. Yahoo! uses yimg.com, YouTube uses ytimg.com, Amazon uses images-amazon.com and so on.

    Another benefit of hosting static components on a cookie-free domain is that some proxies might refuse to cache the components that are requested with cookies. On a related note, if you wonder if you should use example.org or www.example.org for your home page, consider the cookie impact. Omitting www leaves you no choice but to write cookies to *.example.org, so for performance reasons it's best to use the www sub domain and write the cookies to that sub domain.

  7. Be careful when adding eventListeners
    In order to fulfill the requirements of the point 10 we should avoid to implement many event listeners, since each one of them will be attached to the DOM tree, instead it’s a much clever approach to implement just one and navigate through the elements once we have it in the code. This can be done for instance adding an EventListener to the a4j:form and checking in there which element fired the listener.

  8. Wacth out favicon.ico
    The favicon.ico is an image that stays in the root of your server. It's a necessary evil because even if you don't care about it the browser will still request it, so it's better not to respond with a 404 Not Found. Also since it's on the same server, cookies are sent every time it's requested. This image also interferes with the download sequence, for example in IE when you request extra components in the onload, the favicon will be downloaded before these extra components.

    So to mitigate the drawbacks of having a favicon.ico make sure:
    • It's small, preferably under 1K
    • Set Expires header with what you feel comfortable (since you cannot rename it if you decide to change it). You can probably safely set the Expires header a few months in the future. You can check the last modified date of your current favicon.ico to make an informed decision

Speeding up a seam application from the server side

Usually when developing a seam's based web application, one of the main complaints from the developers and users is how slow seems to be the webapp. This makes sense, since seam is a heavy stateful framework quite big with hundred of different files and option to optimize.

I always tought that the first thing before start coding a single line is try to understand what do you want and how you want to have it done with the tools at your disposal. Just to try to make it as easy as possible i'll write down some "tricks" or practices that could be applied so the application is properly tunned:

1. Conditional Rendering
The conditional rendering in JSF is extremely heavy in its use, because the expression is evaluated four or five times every time is called. A good practice in order to have the best performance possible is group the rendered attributes using a h:panelgroup tag so the attribute is only applied once per row or Item. Anyway if we need the rendered attribute in an item one option would be to use the facelets expression c:if, but since it is not a true JSF component it wont be rerender conditionally, because the tree is already resolved when we go to JSF handler. Also when a rendered expression is resolved it goes trough a huge amount of interceptors so we can avoid them using:

  • @BypassInterceptors: This annotation is intended to be used on methods that read the state of a component, as opposed to a method with behavior. After all, Seam is a stateful framework and espouses using objects as they were intended, to have behavior and state. The only problem is that Seam relies on interceptors to restore the state of conversation-scoped components, at least in Seam 2.0. In Seam 2.1, this behavior is disabled by default, so you could just add @BypassInterceptors to the method. Do not use in conversation-scoped components.
  • @Out: This annotation outjects a seam component, so it should be put in the object you want to outject. Outjection is a mechanism in Seam that takes the value of a JavaBean property on a component and assigns it directly to the name of a variable in the specified scope (such as the conversion scope). This should be used as much as possible when evaluating a property of a Seam Component.
  • The cost of use of rendered="#{benthicMsmntEditor.editing(_item)}" and rendered="#{_item == benthicMsmntEditor.itemInEditMode}" is pretty much the same, since the EL Resolver is quite fast and the Java Reflections works quite ok. Anyway for this issue we will explain a better approach later in the section 2.4.
Anyway if the forms are rendered conditionally, and some via Ajax, the reference data can be retrieved at the same time the forms are activated. So we avoid the huge loading at the beginning.

2. Not conditional Rendering
If you must display a form unconditionally, think about the most efficient way to prepare the data (it’s about time to use a cache).

3. Interceptors
An interceptor transfers the values of all fields holding references to entity instances directly into the conversation context, and then nullifies the values of those fields. It reverses the process at the beginning of the next call. The consequence is that without interceptors, your conversation-scoped object is missing state. Because of that, when working with large datasets inside of data tables or similar the performance can be seriously affected by these interceptors.

Rather than worrying about whether to use this interceptor, or locking the design of your application into its absence, it's best just to avoid the need to disable interceptors. Besides, there are still other interceptors that may need to be enabled on a component's methods (its all or nothing when you disable them) and working with outjected data is the fastest approach anyway. You can feel comfortable calling methods on Seam components in other areas of your page, but you should avoid doing so inside of a data table. So, don't call intercepted methods inside a data table (or in excess).

4. ConversationContext
When trying to resolve the value of a variable from the EL resolver chain its important to understand that jsf first and seam after will try to go through a chain of places to look for the value of the variable, this means that if the value is null, the time to resolve the variable is going to be significantly bigger than with a variable with value. In fact the standard EL resolver looks in the request, session and application scope; the seam EL resolver will check also the components, factories, seam namespace, seam context, and so on.
The solution to avoid this and at the same time be able to use null as value for our variables is look for the variable into the conversation context straight, so it goes much faster. But the conversation context is registered as an imported variable that seams takes some time to find, so what we can do is register a seam component called conversationScope which is associated with the conversation Context. So the steps are:

  • In components.xml add factory name="conversationScope" value="#{conversationContext}"
  • Call to the property as follows rendered="#{_item == conversationScope.get('itemInEditMode')}"

5. Consider the cost of your logic
Sometimes the cost of using logic within a table or page is significant enough to consider not using the logic at all. But the requirements needs it, how to do it then? One option is make 2 different pages, this is quite useful in the case of editing items, for instance, if we want to show different information when a table is in “edit mode” than if it is in “view mode” it’s a much better approach to use 2 tables and render one or another than using a single table with multiple rendered fields.

6. Use Ajax to load of portions of the page
Since the response speed from the server side is already tuned we can continue with the improvement trying to add ajax for the parts of the pages which are most likely that could be used. Ajax allows us to perform a load of some content of a page independently of the rest of the page. Said in other words, allows us to change the content of some part of a page without need of re-load the whole page.

The cost attached to it, as always there is some side effect, is the size of the page which is increased since the inclusion of embedded and external javascript code. So when using ajax we must focus in optimizing the size of our response.

It's preferable to use Ajax-based autocomplete rather than select menus with a large list of options, since making this switch can drastically reduce the speed of the initial rendering of the form. The user will likely be more patient when working on the field with autocomplete, and you can even keep the number of options delivered to a minimum as the user types.

miércoles, 20 de abril de 2011

Contexts in JBoss Seam

One of the main goals when Seam was created at first was to offer an statefuf framework which would answer the requeriments coming from many web application developers of have a more web specific framework rather than a general one as it was, and still is, Spring.

I've been told many times that all that seam can do, spring can do too. While i don't disagree at this matter, i'll also point that seam does what is needed with much lesser effort. Everything needed for build a web application is already included in seam, so we can spend more time developing the actual web application than configuring it and searching for documentation of how to do some special really hard-to-find trick for something. At the end of the day, all you can do with a technology, you can do with other too, is only a matter of preferences and simplicity.

Among one of those things needed long ago in a web application and which wasn't easy to find was an special scope which covers not only an event, page or session, but a concrete use case, a group of actions and request made by the user for a determined bussines purpose. In seam, they've got this challenge and they created a new concept of context or scope, called "coversation".

When developing a web application is important to have clear this concept in the mind so we won't waste the time saved by the tools seam provide us into silly stuff like concurrent conversations errors and so on. Every now and then you'll probably see some process for create users implemented with an scope session or a process for display a simple list with scope conversation. Because of that i'll try to explain the different context we can use with seam, first of all, thanks for some of the info taken from the seam's reference guide.

1. Event Context
The event context is the “narrowest” of the stateful context, and is a generalization of the web request context, in fact, most commonly it corresponds to the lifecycle of a JSF request. Components associated with the event context are destroyed at the end of the request, but their state is available and well-defined for at least the lifecycle of the request.

2. Page Context
The Page context allows you to associate state with a particular instance of a rendered page. The state is initialized when the page is rendered and is accessible during any event originated from that page. The state is serialized in the client, what is means that is extremely robust with respect to multi-window operation and the back button. An example of this would be a clickable list, where the list is backed by changing data on the server side.

3. Conversation Context
The conversation context is probably the most important to consider in a web application developed using Seam. The conversation scope is a particular scope included in Seam which was not present into other framework is a slice of the HTTP session that is managed by Seam and associated with a sequence of pages through the use of a special request token (known as the conversation id). The conversation provides the developer the convenience of using the HTTP session without the memory leakage concerns, since the conversation has a much shorter lifetime and is kept isolated from other parallel conversations in the same session.

In order words, is a use case which covers a specific business requirement, using single or several pages for that purpose.

Please also consider that conversation can be nested inside another one, so we can have several conversational components running at the same time. Seam implements configurable conversation timeout, automatically destroying inactive conversations, and thus ensuring that the state held by a single user login session does not grow without bound if the user abandons conversations. Seam also serializes processing of concurrent requests that take place in the same long-running conversation context, in the same process.

Alternatively, Seam may be configured to keep conversational state in the client browser.

We chose to leverage the conversation for three reasons:

  • to reduce the number of times the database needs to be queried
  • to ensure the record remains managed by the persistence context while being edited
  • to maintain the search criteria and pagination offset
Using the conversation has the added bonus of making previously viewed result pages load faster since the records are already sitting in the persistence context (i.e., the first-level cache). An example of this would be creating an order or user, returning an item or displaying a list where we want to make some actions like edit a number or a name.

4. Session Context
A session context holds state associated with the user login session. While there are some cases where it is useful to share state between several conversations, we generally frown on the use of session context for holding components other than global information about the logged in user.

In a portal environment, the session context represents the portlet session.


5. Business Context
The business process context holds state associated with the long running business process. This state is managed and made persistent by the BPM engine (JBoss jBPM). The business process spans multiple interactions with multiple users, so this state is shared between multiple users, but in a well-defined manner. The current task determines the current business process instance, and the lifecycle of the business process is defined externally using a process definition language, so there are no special annotations for business process demarcation.

6. Application Context
An Application context is familiar with the servlet context from the servlet specs. It is useful for holding static information as configuration data or metamodels. Alternatively it can be used to hold lists which are huge and have relatively little change like locations or users, in this case we avoid making more queries to database than needed and we should combine it with cache in order to render the results as fast as possible.