Chapter 5. Basic concepts of the Ajax4jsf Framework

Chapter 5. Basic concepts of the Ajax4jsf Framework

5.1. Introduction

The framework is implemented as a component library which adds AJAX capability into existing pages, so you don't need to write any JavaScript code or to replace existing components with new AJAX widgets. Ajax4jsf enables page-wide AJAX support instead of the traditional component-wide support. So, you can define the event on the page that invokes an AJAX request and the areas of the page that should be synchronized with the JSF Component Tree after the AJAX request changes the data on the server according to the events fired on the client.

Next Figure shows how it works:

Figure 5.1. Request Processing flow

Ajax4jsf allows to define (by means of JSF tags) different parts of a JSF page you wish to update with an AJAX request and provide a few options to send AJAX requests to the server. Also JSF page doesn't change from a "regular" JSF page and you don't need to write any JavaScript or XMLHttpRequest objects by hands, everything is done automatically.

5.2. Architecture Overview

Next figure lists several important elements of the Ajax4jsf framework

Figure 5.2. Ajax4jsf component structure

Ajax Filter. To get all benefits of Ajax4jsf, you should register an AJAX Filter in web.xml file of your application.The AJAX Filter recognizes multiple request types. The sequence diagram on Figure 3 shows the difference in processing of a "regular" JSF request and an AJAX request.

In the first case the whole JSF tree will be encoded, in the second one option it depends on the "size" of the AJAX region (you can define AJAX region by using the <a4j:region>). As you can see, in the second case the filter parses the content of an AJAX response before sending it to the client side.

Have a look at the next picture to understand these two ways:

Figure 5.3. Request Processing sequence diagram

In both cases, the information about required static or dynamic resources that your application requests is registered in the ResourseBuilder class.

When a request for a resource comes (Figure 4), the AJAX filter checks the Resource Cache for this resource and if it is there, the resource is sent to the client. Otherwise, the filter searches for the resource among those that are registered by the ResourceBuilder. If the resource is registered, the AJAX filter will send a request to the ResourceBuilder to create (deliver) the resource.

Next Figure shows the ways of resource request processing.

Figure 5.4. Resource request sequence diagram

AJAX Action Components.  There are four AJAX Action Components: AjaxCommandButton, AjaxCommandLink, AjaxPoll and AjaxSupport. You can use them to send AJAX requests from the client side.

AJAX Containers.  AjaxContainer is an interface that describes an area on your JSF page that should be decoded during an AJAX request. AjaxViewRoot and AjaxRegion are implementations of this interface.

JavaScript Engine.  Ajax4jsf JavaScript Engine runs on the client-side. It knows how to update different areas on your JSF page based on the information from the Ajax response. Do not use this JavaScript code directly, as it is available automatically.

5.3. Limitations and Rules

In order to create AJAX4JSF applications properly, keep the following points in mind:

  • The AJAX framework should not append or delete, but only replace elements on the page. For successful updates, an element with the same ID as in the response must exist on the page. If you'd like to append any code to a page, put in a placeholder for it (any empty element). For the same reason, it's recommended to place messages in the "AjaxOutput" component (as no messages is also a message).
  • Don't use <f:verbatim> for self-rendered containers, since this component is transient and not saved in the tree.
  • AJAX requests are made by XMLHttpRequest functions in XML format, but this XML bypasses most validations and the corrections that might be made in a browser. So, create only a strict standards-compliant code for HTML and XHTML, without skipping any required elements or attributes. Any necessary XML corrections are automatically made by the XML filter on the server, but lot's of unexpected effects can be produced by an incorrect HTML code.

5.4. How To...

5.4.1. Send an AJAX request

There are different ways to send AJAX requests from your JSF page. You may use <a4j:commandButton>, <a4j:commandLink>, <a4j:poll> or <a4j:support> tags.

All these tags hide the usual JavaScript activities that are required for an XMHttpRequest object building and an AJAX request sending. Also, they allow you to decide which components of your JSF page are to be re-rendered as a result of the AJAX response (you can list the IDs of these components in the "reRender" attribute).

<a4j:commandButton> and <a4j:commandLink> tags are used to send an AJAX request on "onclick" JavaScript event.

<a4j:poll> tag is used to send an AJAX request periodically using a timer.

The <a4j:support> tag allows you to add AJAX functionality to standard JSF components and send AJAX request onto a chosen JavaScript event: "onkeyup", "onmouseover", etc.

Most important attributes of components that provide AJAX request calling features are:

  • "reRender" attribute as it was mentioned before specifies components to be reRendered after AJAX response. The attribute can be specified using EL expression and formed dynamicaly on the server side (see FAQ chapter).
  • "RequestDelay" attribute is used for a requests frequency regulation.
<h:inputText size="50" value="#{bean.text}">
        <a4j:support event="onkeyup" RequestDelay="3"/>
</h:inputText>

So every next request from the frequent keyboard events will be delayed on 3 ms to reduce the number of requests.

  • "EventsQueue" is a queue that stores the next request.
  • "LimitToList" attribute is used to regulate updatable regions. Setting it to true limits the updatable areas only to ones specified in a reRender list, in other case all Output Panels of the region are updated.
  • "ajaxSingle" attributes specify regions to be sent with a request, if "false" it is a full region, in other case it's is only a control caused event.

5.4.2. Decide What to Send

You may describe a region on the page you wish to send to the server, in this way you can control what part of the JSF View is decoded on the server side when you send an AJAX request.

The easiest way to describe an AJAX region on your JSF page is to do nothing, because the content between the <f:view> and </f:view> tags is considered the default AJAX region.

You may define multiple AJAX regions on the JSF page (they can even be nested) by using the <a4j:region> tag.

If you wish to render the content of an AJAX response outside of the active region then the value of the "renderRegionOnly" attribute should be set to "false". Otherwise, your AJAX updates are limited to elements of the active region.

5.4.3. Decide What to Change

Using IDs in the "reRender" attribute to define "AJAX zones" for update works fine in many cases.

But you can not use this approach if your page contains, e.g. a <f:verbatim> tag and you wish to update its content on an AJAX response.

The problem with the <f:verbatim/> tag as described above is related to the value of the transientFlag of JSF components. If the value of this flag is true, the component must not participate in state saving or restoring of process.

In order to provide a solution to this kind of problems, Ajax4jsf uses the concept of an output panel that is defined by the <a4j:outputPanel> tag. If you put a <f:verbatim> tag inside of the output panel, then the content of the <f:verbatim/> tag and content of other panel's child tags could be updated on AJAX response. There are two ways to control this:

  • By setting the "ajaxRendered" attribute value to "true".
  • By setting the "reRender" attribute value of an Action Component to the output panel ID.

5.5. Request Errors and Session Expiration Handling

Ajax4jsf allows to redefine standard handlers responsible for processing of different exceptional situations. It helps to define own JavaScript, which is executed when this situations occur.

5.5.1. Request Errors Handling

To execute your own code on the client in case of an error during AJAX request, it's necessary to redefine the standard "A4J.AJAX.onError " method:

A4J.AJAX.onError = function(req,status,message) { 
          // Custom Developer Code 
};

The function defined this way accepts as parameters:

  • req - a params string of a request that calls an error
  • status - the number of an error returned by the server
  • message - a default message for the given error

Thus, it's possible to create your own handler that is called on timeouts, inner server errors, and etc.

5.5.2. Session Expired Handling

Beginning with Ajax4jsf version 1.0.5 it's possible to redefine also the "onExpired" framework method that is called on the "Session Expiration" event.

Example:

A4J.AJAX.onExpired = function(loc,expiredMsg){ 
          // Custom Developer Code 
};

Here the function receives in params:

  • loc - URL of the current page (on demand can be updated)
  • expiredMsg - a default message on "Session Expiration" event.

Note:

Until the version 1.0.5 the method can't be redefined on "Session Expiration", a confirmation dialog with a request for view reloading was always called.

5.6. FAQ

5.6.1. What should I change on the server side?

As it was mentioned before, the list of zones to be reRendered can be specified as EL expression. But there is a question that must be specified more exactly.

The list of Ids is formed during beforePhase of RENDER_RESPONSE. Therefore, in this case one can point reRender to the Set type Bean's property and fill the Set during a tracking request.

It's the way to form a list of updatable areas dynamically.

5.6.2. How to check sending request conditions? Custom JavaScript before request "OnSubmit" attribute.

To check on the client some terms of request sending, the "onSubmit " attribute is added to all components, which may cause the request.

Example:

<h:inputText id="i" value="#{beanText.kennung}">
            <a4j:support event="onfocus" onsubmit="doSomething();" reRender="panelToReRender"/>
</h:inputText>

So in this case "doSomething()" function is executed before the AJAX request.

Besides, if this function returns "false", AJAX request isn't fired.

Note:

Behavior of our "onsubmit" slightly differs from the standard one. Do not return "true" if you want to fire the request - because <xxx><a4j:support event="onclick" onsubmit="return true;"> is transformed into <xxx onclick="return true; A4J.Submit(.... );" > and the request isn't fired also in this case (but the standard event processing fired). You must only return "false" if your conditions weren't completed or perform some actions (if needed) without any returns in case you need to fire it.

5.6.3.  What is differences of "onCompelete" attribute after release 1.0?

To avoid differences with other JavaScript attributes, a function placement in a JavaScript call is changed, instead of simple inserting of attribute content (..oncomplete :anotherFunction(this)..), it places (oncomplete: function(){anotherFunction(this);}..) in anonymous function, to allow put "chain" of statements in attribute.

Since, "this" keyword will point to a parameters map instead of a control element as it was before. You may use document.findElementById() to get references to this object after a request is processed as when a page is updated in AJAX you will have reference to a control, removed from a DOM tree.

Or, if you are sure that your element is not updated, you can add "onsubmit" in <a4j:support> (or onclick in <a4j:commandLink/Button> ) to place reference to known variable ( <a4j:commandLink onclick="var myControl=this;" oncomplete="anotherFunction(myControl)"/> ).

New:

The onComplete syntax now is:

	<someAjaxActionComponent ...oncomplete="myFunc(req,event,data)".../>
            

where the event is a variable where the JS event copy that fires the request is placed into. One may use it to get the element instead of this. and data is a variable that contains deserialized value from the data attribute.

5.6.4. Is it possible to use InvokeOnComponent with JSF 1.2?

Ajax4jsf currently does not use invokeOnComponent because of the 2 reasons:

  • Compatibility with JSF 1.1 and MyFaces applications is kept, due to a big amount of code used in corporate applications.
  • InvokeOnComponent works with already known clientId, and works fine for communication between widget and backed component, or updates content of already rendered component. But there are some troubles to use this method for more complex use-cases implemented in Ajax4jsf, as there is a choice for updatable components in application logic, where it's necessary to navigate in a components tree by the native id, with findComponent() methods.

Thus, for example, only entire dataTable can be updated in response (but all AJAX action components inside table work properly).

5.6.5. How to avoid generating exception for "keepAlive" component?

To avoid exception, don't forget that the component stores beans in serialized view, but your bean should implement java.io.Serializable.

5.6.6. Why does filter usage damage an application layout?

Ajax4jsf uses filters for correction of xhtml code received on an AJAX response, because when a response is recieved from the server, Ajax4jsf makes direct changes in DOM tree and browser doesn't make any corrections in generated xhtml. There are two ways for setting filters that could be used in an Ajax4jsf-based application.

The first one:

Example:

<context-param filter>
  <display-name>Ajax4jsf Filter</display-name>
  <filter-name>ajax4jsf</filter-name>
  <filter-class>org.ajax4jsf.Filter</filter-class>
</filter>

This filter is based on Tidy Filter usage and recommended for applications with complicated or non-standard markup, as all the necessary xhtml code corrections are made by the filter when a response comes from the server.

Anyway, some obvious errors could damage a layout, if it happens, make sure that the markup corresponds to the xhtml-strict specification.

The second one:

Example:

<filter>
  <display-name>org.ajax4jsf.FastFilter</display-name>
  <filter-name>ajax4jsf</filter-name>
  <filter-class>org.ajax4jsf.FastFilter</filter-class>
</filter>

This filter is based on the Nekko pacer. In this case an output xhtml code isn't strictly verified and it also could cause lot's of errors and corrupt a layout as a result. Though if you sure that your application markup is really strict for this filter, the filter considerably accelerates all AJAX requests processing.

Extra information.

forceParcer parameters setting for filters:

Example:

<filter>
...
<init-param>
<param-name>forceparser</param-name>
<param-value>false</param-value>
</init-param>
...
</filter>

The "false" setting for initialization parameter switches off application of filters for non-AJAX requests, if "true" is chosen, the filter checks all requests.

Changes for Ajax4jsf 1.1.0

forceparser parameter default value is false from this version.

5.6.7. Why form isn't submitted or setter isn't called after AJAX request?

This situation could happen because of conversion/validation errors on form submission. In order to verify this, it's necessary to place this updating via an AJAX error message inside a form:

Example:

<a4j:outputPanel ajaxRendered="true">
   <h:messages/>
</a4j:outpurPanel>

5.6.8. How to create "a4j delayed render zone"?

The <a4j:support> component has a "requestDelay" attribute where you can define the delay.

More information about this problem could be found on the Ajax4Jsf Users Forum.

5.6.9. How to stop "a4j:poll"?

More information about this problem could be found on the Ajax4Jsf Users Forum.

5.6.10. How to use IgnoreDupResponses and requestDelay?

The "IgnoreDupResponses" attribute appeared from 1.0.4 RC1 version and is used on the client for response ignoring after an AJAX request if a newer request has been already sent.

The additional information could be found here.

"RequestDelay" attribute also defines the client behavior. It sets the time delay, after which another request could be sent, all other requests are taken away from a queue except the last one.

5.6.11. How to refresh an image using <a4j:support> component?

More information about this problem could be found on the Ajax4Jsf Users Forum.

5.6.12. How to use "EventQueue" attribute?

The "EventQueue" attribute defines the query name where the requests are saved before their sending to the server. The queue is created for redundant requests deleting during frequent events, which call several requests forming one after another. The queue cuts redundant requests and send only the last one. The queue is created in any case and named on default, the attribute usage only re-defines this name.

5.6.13. Is <a4j:page> component required or not?

<4j:page> is a component used for solving of incompatibility problems in early Ajax4jsf and MyFaces versions. The component encodes the full html page structure.

More information about this problem could be found on the Ajax4Jsf Users Forum.

5.6.14. Can I have several <a4j:status> components on one page?

Yes, you can. More information about this problem could be found on the JBoss Ajax4jsf Online Demos.

5.6.15. Can I use <a4j:region> within <a4j:repeat>?

<a4j:region> can't work inside iteration components like <h:dataTable> and <a4j:repeat>.

The details could be found here.

5.6.16. How to reRender only particular row(s) of dataTable?

If you use dataTable then you may use ajaxKeys attribute to bind the rowKeys to be reRendered there. After you need to point reRender on the whole table and only specified rows will be reRedered. Also the example of usage of <a4j:repeat> component are available here.

5.6.17. How to reRender single dataTable column?

More information about this problem could be found on the Ajax4Jsf Users Forum.

5.6.18. Why does reRendering fail? Hide/Show components using rendered.

During "show/hide" functionality implementation the main error happens because of the "reRender" attribute of some AJAX Action Component is set on a component that depends on rendered properties, i.e. a component that is to be hidden/rendered is tried to be updated. The problem is that if rendered="false" in this moment, the component isn't in the DOM tree and can't be updated because of the general limitations described in the Ajax Processing chapter.

The correct variant of functionality implantation:

  1. With the rendered attribute wrap the component that is to be hidden or rendered on AJAX in a wrapper component (e.g. a4j:outputPanel)

  2. Set reRender of an AJAX Action component on this wrapper component instead of the component itself.

Example:

...
<a4j:outputPanel id="panel"> 
	<h:panelGroup rendered="#{bean.rendered}">
		<!--Some nested content to be hidden/shown depending on bean.rendered -->
	</h:panelGroup>
</a4j:outputPanel>
...
<a4j:commandButton action=".." value=".." reRender="panel"/>
...

In this case the wrapper component always presents in the DOM tree and its inner content could be updated dynamically on AJAX.

5.6.19. Why does JavaScript call don't work in <a4j:include>?

More information about this problem could be found on the Ajax4Jsf Users Forum.

5.6.20. What does ResourceNotRegistered Exception mean?

Ajax4jsf registers its resources (scripts, images) after an application is accessed and then accesses it via a generated URL. During an application development when a developer constantly updates it on the server, it could happen that Ajax4jsf re-registers its resources after every server restart and a browser tries to access them via cashed URL.

The problem is solved with browser cash update (e.g. CTRL+F5).

5.7. Other Relevant Resources

Introduction to Ajax4Jsf by Shunmuga Raja

JBoss Ajax4jsf Downloads

Want additional assistance?
Contact Support Services.
Show details