Are You Crazy Still Using JSF!

JSF stands for Java-Server-Faces which is a web technology that is underestimated by many people. I wonder why is that? And are you actually crazy if you still use JSF? I don’t think so and I will share some of my thoughts. (To get an impression about the technology see the Getting Started Blog form Rudy De Busscher.)

Jakarta EE and Java Server Faces 4.0

The Specification

First of all JSF is a specification which is an important advantage over all the other technologies that JSF is usually compared to. The specification is an open process that is accompanied by many developers for years to define a general solid standard for web applications. This specification process has recently taken place in the Eclipse Foundation, which sets up rules that follow very high quality standards. This is one of the biggest advantages, as it guarantees that your web application is build on a solid core. Of course, other web frameworks also have large communities, but often these are represented by a single company that does not always take the developers into account. Angular from Google is just one example.

Server Based Framework

But back to JSF. Why is JSF sometimes ridiculed as an outdated technology? I personally started with JSF in its early beginning in 2001. So it’s obviously an old technology. And I am an old developer too ;-). In the meantime, many other web frameworks have evolved. Many of them are based on JavaScript and follow the single page paradigm (SPA) running in the browser. The idea is to move the application logic into the browser to get applications faster. This idea came up at a time when not everyone was satisfied with JSF and JavaScript took off. Java Server Faces – as the name implies – in contrast is a server based framework. This means the application logic is executed on the server. And this is where we have the big difference. At that time it was a valid argument to reduce the load on the servers. And of course, this should still be a desirable goal today. But the people who use this as an argument against JSF are often the same ones who rave about serverless functions. Therefore, I don’t think we should consider a server-based framework as a stupid idea today.

Self-Contained Microservice

In fact, a server-based web framework offers some advantages. In this way, application logic and business logic can be easily coupled. This is achieved within Jakarta EE mainly through CDI, EJB and JPA. These technologies are the backend for JSF components. Jakarta EE provides a very clear understanding of the separation of layers and JSF fits seamlessly into this concept. The server-side implementation also hides application details from the client. In contrast in a JavaScript SPA, large parts of the application logic are usually unprotected in the browser which can be a security risk in some cases.

So rendering the application logic on the server side makes it more easy for developers responsible for both – the backend and the frontend part. And this leads to the fact that applications can be developed faster in many cases. From the point of view of the microservice architecture, a JSF application corresponds to the principle of the Self-Contained Services. This is a pattern which is commonly used in microservice architectures.

Simplicity

Since JSF is often referred to as complex and clumsy, I recently wondered if this is really true. I migrated one of my Vue.js SPA to JSF 4.0 and compared the complexity of the resulting code. So finally, I would like to show in an example the simplicity of JSF. (Note: I do not compare JavaScript code with Java here)

In JavaScript Frameworks you typically bind your HTML tags to some code by additional tagging.

<!-- Vue.js -->
<input type="text" 
       name="userwebsite" 
       v-model="userwebsite" 
       placeholder="enter your website">
Your Website is: <span>{{api}}</span>

The SPA framework resolve the tag (v-model) and place the correct value from your model written in JavaScript. It also binds the input field to track changes of your model.

The JSF counter part looks not much different:

<!-- JSF -->
<h:inputText value="#{userController.website}" 
             pt:placeholder="enter your website" />
Your Website is: <h:outputText value="#{userController.website}" />

Here you also bind your model values to input fields or output text. But the code is executed in Java on the server side which is often equal to your backend code written in Java also for SPAs.

Ajax is used by JavaScript Web frameworks out of the box. So you usually have no need to care about it. In the example above the span tag is automatically updated when the value of the input changes.

In JSF you use also Ajax, but you have more control about how it behaves. You can simple enclose a part of your page with a f:ajax tag to get the same behaviour:

<!-- JSF -->
<f:ajax>
   <h:inputText value="#{userController.website}" 
                pt:placeholder="enter your website" />
   Your Website is: <h:outputText value="#{userController.website}" />
<f:ajax>

Another example is linking. In a JavaScript framework you use again a kind of tagging to initiate a rendering life-cycle when the user clicks on an element:

<!-- Vue.js -->
<li class="nav-item" v-on:click="showSection('search')">
   <label>Search</label>
</li>

The showSection implements some business logic in your JavaScript code and is responsible for handling data and changing the layout.

JSF is not much different:

<!-- JSF -->
<li class="nav-item">
   <h:link outcome="search" >
     <label>Search</label>
</li>

The h:link tag loads a new page from the backend named ‘search.xhtml’ containing the new layout. All the model binding is handled behind the scene in the backend. For the user there is no different in behaviour.

So as you can see from the markup, there is not much difference and it is not more or less complex to write a JSF frontend as it is in JavaScript based Web frameworks.

Conclusion

My personal conclusion is that JSF gives me a clearer and more consistent concept for writing my code within a framework. Backend logic and application design are combined in one technology resulting in a pattern also known as self-contained microservice.

To me, this is a valid concept even for modern web applications. And computing application logic on the server side is not crazy at all.

With JSF Version 4.0 you will find a modern and well designed Web technology embedded into the latest Jakarta EE 10 framework.

JSF Best Practice

I do developing with Java Server Pages (JSF) since the early beginning with version 1.0. Today , 17 years later,  we have version 2.3 and thus a lot of improvements and new features.  I’ve made many mistakes in using this standard web framework in my own applications. And therefore I would like to show some best practice rules in this Blog. And I hope this will simplify the work with JSF – for you and also for me – during refactoring my own applications. Most of which I write here comes from the great book ‘ The Definitive Guide to JSF in Java EE 8’ written by Bauke Scholtz (BalusC) and Arjan Tijms. I recommend you to buy this book if you have had already made experience with JSF.  So let’s start…

Continue reading “JSF Best Practice”

How to use JSF 2.0 as an Action-Based-Framework

JSF is a common used and widely spread Web-Framework with a lot of powerful features and a great community. But JSF also follows a concept which is not comparable to Action-Based or Request-Based Frameworks like MVC 1.0 or Spring MVC. The concept behind JSF is a so called Event- or Component-Based Framework (alternative therm is MVC-Pull). This approach gives you a lot of flexibility in developing web applications, but it also includes some problems. What you often see in JSF  applications is, that URLs are not bookmarkable and you can not use the browsers History-Back button. This makes the behavior of JSF a little bit clumsy to the end-users.  I will explain  in this post how to solve this ‘problem’ in an elegant way without abusing JSF.

The Problem

The problem with the non bookmarkable URLs and the ugly situation that we can not use the Browser History-Back Button in a JSF application is founded in the so called Postback mechanism.  Each time you use a JSF Command-Action like a <h:commandButton> or a <h:commandLink>, JSF generates a Form Post, computes the resulting web site internally and posts back the markup to the browser. This is the natural behavior of the HTTP POST method and very efficient because the browser is not forced to load a new page. But if you want to change the page content/url the user is faced with a usability problem. The following two pages illustrating the problem:

page1.xhtml:

...
<h:body>
 <h:form>
 <h1>Page1</h1>
 <h:commandLink action="/page2">Go to Page2</h:commandLink>
 </h:form>
</h:body>

page2.xhtml:

...
<h:body>
 <h:form>
 <h1>Page2</h1>
 <h:commandLink action="/page1">Go to Page1</h:commandLink>
 </h:form>
</h:body>

If you test this page example you will see that the browser URL did not correspond with the page you see. Command-Actions are very powerful and we need them in situations where we want to submit the user input. But for simple navigation there is another tag introduced in JSF 2.0 which should be used instead of a command action. The <h:link> and <h:button>. In the next example you can see how the two pages work when we use this new JSF component:

page1.xhtml:

...
<h:body>
 <h1>Page1</h1>
 <h:link outcome="/page2">Link to Page2</h:link>
</h:body>

page2.xhtml:

...
<h:body>
 <h1>Page2</h1>
 <h:link outcome="/page1">Link to Page1</h:link>
</h:body>

Now when the user clicks on one of the page links the browser url is updated correctly because a HTTP GET request is initiated. This is the correct way to implement a page navigation in JSF.

Rule No. 1: Never use a command-action to navigate between pages

 

The Action Controller

In most situations it is not sufficient to simply navigate between to pages. What we need is business logic to be called when the user clicks on the navigation link to open a new page. Command Actions providing a lot of functionality to solve this problem. And this is also the reason why command actions are often used in JSF.  To control the outcome of a page after the user clicks on a action link is called an Action Controller. A Action Controller is in most cases a request-scoped CDI bean. So what we can do here is to bind the outcome attribute of the <h:link> component to a CDI Bean method like seen in the following example:

page1.xhtml:

...
<h:body>
 <h1>Page1</h1>
 <h:link outcome="#{myActionController.action1()">Link to Page2</h:link>
</h:body>

MyActionController.java:

@Named
@RequestScoped
public class MyActionController implements Serializable {
 private static final long serialVersionUID = 1L;
 public String action1() {
 // your code goes here.....
 return "/page2";
 }
}

The ugly part of this solution is that the action controller have to know the page name. So the action controller is tightly coupled to our JSF pages. (By the way, we see exactly the same coupling in MVC 1.0 examples.) In addition in this solution we need to make sure hat every link navigating to page2 is calling our action method. But a more complicating problem is that the action controller is not called if the user opens the page2 form a bookmarked URL!

So lets look on a better solution: We can place the ActionController directly into the page view. This  can be done by the new JSF 2.0 component <f:event> inside a the JSF component <h:view>. With the f:event type we can specify the jsf life-cycle phase where the action controller should be called.  See the next example:

page1.xhtml:

...
<h:body>
 <f:view>
  <f:event type="preRenderView" listener="#{myActionController.init()}" />
   <h1>Page1</h1>
   <h:link outcome="/page2">Link to Page2</h:link>
 </f:view>
</h:body>

MyActionController.java:

@Named
@RequestScoped
public class MyActionController implements Serializable {
 private static final long serialVersionUID = 1L;
 public void init() {
 System.out.println("...initializing action controller....");
 }
}

This solution ensures that your ActionController is always called before the page is rendered.

Rule No. 2: Avoid binding controller methods to a navigation link

If you do some tests with the ActionController example you will notice that the init() method of the ActionController is not called if the user clicks the Browser History-Back Button to enter the page. This again is not a problem of JSF but of the caching behavior of Web Browsers. See a good blog post about this topic here.

The JSF Command-Action and Postbacks

Now lets take a look on the JSF command action. As I mentioned earlier the JSF command actions are useful if you want to submit the users input from a input form.

<h:form>
 <h1>Form1</h1>
 <h:inputText value="#{myActionController.orderDate}" >
    <f:convertDateTime pattern="dd.MM.yyyy" timeZone="CET"/>
 </h:inputText>
 <h:commandButton action="#{myActionController.submitOrder}" value="submit"/>
 </h:form>

In this example the submit action button triggers our action controller method ‘submitOrder()’. Thus a method typically implements our business logic to persist or update data. JSF exepcts a public method returning a String which points to the resulting page outcome. See the following example:

 public String submitOrder() {
   // your code goes here....
   return "/page2";
 }

If you do some tests, you will see that a click on the submit button will produce a HTTP POST method call and the page content will result in the markup of page2. As this was a postback the browser URL has not updated. Another problem seen here is that we now have again the situation where our Action Controller have to now the page name.

To avoid this problems simple make use of another JSF command action attribute called ‘actionListener’. With EL 2.2 we can call any method of a CDI bean with or without parameter. The action attribute itself can now be used for the navigation part. In case we want to navigate to another page we still have the Postback problem. But JSF 2.0 allows to force a redirect by adding the query parameter ‘?faces-redirect=true’ at the end of the navigation path.

<h:commandButton actionListener="#{myActionController.submitOrderByListener()}"
 action="page2?faces-redirect=true" value="submit"/>

ActionListener method:

 public void submitOrderByListener() {
   // your code goes here....
   System.out.println("ActionListener called...");
 }

The result of the faces-redirect=true is also known as the Postback/Redirect/Get (PRG) pattern. The browser will receive a HTTP result 302 with the new URL to be redirected to.

Rule No. 3: Use faces-redirect=true to force Posteback/Redirect/Get pattern

Conclusion

As you can see, JSF 2.0 is a powerful framework which can be used also to implement web application with a request-based behavior as it is typically for modern web applications. Take care of the following rules:

Rule No. 1: Never use a command-action to navigate between pages
Rule No. 2: Avoid binding controller methods to a navigation link
Rule No. 3: Use faces-redirect=true to force Posteback/Redirect/Get pattern

I hope this blog post will help someone to get out the most of JSF. If you have any ideas or questions post your comments.

JSF and Transactioncontext

Today I want to talk about a detail in the JSF Framework, which is on the first view not obviously. In different to Spring, business logic placed in a JSF front-end controller (JSF Backing Beans) did not initializes a separate transaction context. Normally business logic which need to be transaction save should be spread out into EJBs. EJBs are the recommended place for business logic. So in JSF/EJB business logic should be put into stateless session EJBs and controlled the page flow of a web application through the so called front end controllers  – JSF Backing beans. As I mentioned before spring starts a transaction context also in front-end controllers, but jsf does not.

So what is the problem here? When you look at the following JSF example, you maybe will not recognize the problem at first:

//jsf bean...
@EJB ejb1;
...
public String process(businessobject) {
 ejb1.op1(businessobject);
 ejb1.op2(businessobject);
 ....
}

The JSF front-end controller method ‘process(businessobject)’ injects an EJB and calls two ejb methods. This will propaply work without any side effects. But it can produce errors in some cases. The problem in this pattern is that the front-end controller performed two apparently dependent business actions completely separately. If these two methods need to be transaction save but are operating on the same database entities this can result in serious problems. In a high concurrent system indeed this pattern can cause a corrupted DB state even if you thought JPA will solve all the transaction stuff for you.

The reason for the unexpected behavior is the missing wrapping transaction. Each ejb method starts it own transaction with all the transaction control provided by the ejb container. But the hole business method is not transaction save.

To solve this you have two possible solutions:

1) add a UserTranaction context to the front-end controller:

//jsf bean...
@Resource UserTransaction tx;
@EJB ejb1;
...
public String process(businessobject) {
 try {
   tx.begin();
   ejb1.op1(businessobject);
   ejb1.op2(businessobject);
 finaly {
   tx.commit();
 }....
}

In this example now the jsf controller starts itself the UserTransaction. As a result both EJB methods (with default transaction mode ‘mandatory’) run in the same transaction context. Even operations on the database in a high concurrent system will be transaction save.

2) Merge the EJB Methods into one transaction save business method

The second solution merges both ejb methods into a single EJB method call:

// JSF bean calls new ejb method...
public String process(Entity entity) {
 ejb1.op1op2(entity);
 // ...
}

with the following ejb implementation:

// EJB
public void op1op2(Entity entity) {
 op1(entity);
 op2(entity);
}

Now the new ejb method is transaction save an there is no need to fiddle with UserTransaction in the jsf fornt-end controller.

The second solution is recommended because there is no more risk that the transaction context is split by the front-end. And you can reuse the new ejb method easily with now need to think about the transaction context scenarios.

Maybe this will help you solving some problems with jsf transaction context in the future.

How to use a jquery dialog in jsf 2.0

Combining JSF 2.0 and jQuery / jQuery-UI is in my opinion the best choice to build modern web applications. Your JSF web application becomes much smaller as using one of the JSF component libraries. Also with jQuery you got a lot of flexibility designing your pages.

But things become interesting when you try to integrate a jQuery Dialog box with JSF 2.0. I am talking here about a Dialog Box which contains a JSF form with input elements to be submitted – independent from the current page flow. For example: you have a normal jsf form with input components and a link to open another form (in my case a user-profile dialog) also with data which can be submitted. It takes me some time to figure out the best way to manage this. But with JSF 2.0 and ajax support things are not so difficult.

So here is my Solution:

THE DIALOG FORM

I put my Dialog into a JSF faclet to separate all the dialog stuff in one xhtml element which can be included in the main pages. The interesting thing is here the JSF validation which is also supported. The dialog will not close if a validation error occurs. There for I check the #{facesContext.validationFailed} and save the state in a JavaScript variable. The ajax method ‘processCompleteEvent’ checks if a validation exception was thrown. In that case the dialog stays open, otherwise it will be closed after submit. The command button triggers a JSF 2.0 ajax request to avoid any changes on the main page behind the dialog.

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html">

	<script type="text/javascript">
		/*<![CDATA[*/
		$(document).ready(function() {
			// setup dialog
			$("#dialog-myprofile").dialog({
				resizable : false,
				width : 530,
				modal : true,
				autoOpen : false
			});
		});

		// auto close dialog and check validation... 
		var validationError=false;
		function processCompleteEvent(e) {
	          if (e.status == 'success') {
	        	if (!validationError) {
	        	 	$("#dialog-myprofile").dialog("close");
	       	 	}
	          }
	        }
		// open dialog
	 	function openMyProfile() {
			$("#dialog-myprofile").show();
			$("#dialog-myprofile").dialog("open");			
	    	}
		/*]]>*/
	</script>

	<div id="myprofile_view">
		<!-- Dialog Box -->
		<div id="dialog-myprofile" title="#{message['profile.title']}">
			<h:form id="dialog-myprofile-form">
				<ui:include src="/pages/error_message.xhtml" />
				<script>validationError=#{facesContext.validationFailed};</script>
				<h:inputText
					value="#{userController.workitem.item['txtusername']}"
					style="width: 260px;" />

				<!-- Save Action -->
				<h:commandButton actionListener="#{userController.doProcess}"
					 value="#{message.save}">					
					<f:ajax execute="@form" render="@form"
						onevent="processCompleteEvent">
					</f:ajax>
				</h:commandButton>
				<input type="button"
					onclick="$('#dialog-myprofile').dialog('close');"
					value="#{message.close}" />
			</h:form>
		</div>
	</div>
</ui:composition>

 

HOW TO OPEN THE DIALOG FROM THE MAIN PAGE

To open the Dialog from my main template I use a h:commandLink with an onclick event to open the jQuery dialog. See the following code snippet:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:c="http://java.sun.com/jsp/jstl/core"
	xmlns:f="http://java.sun.com/jsf/core"
<h:head>
.....
	<script type="text/javascript" src="../jquery-ui-1.10.0.custom.min.js"></script>
	<script type="text/javascript" src="../jquery-1.9.0.js"></script>
.....
</h:head>
<h:body>
   <f:view id="main_view">
.....
	<h:form id="main_form">
...
		<h:commandLink onclick="openMyProfile();">
			<h:outputText id="profile_userlink"
				value="#{message.open_profile}" />
			<f:ajax render=":dialog-myprofile-form" />
		</h:commandLink> 
	</h:form>
...
	<ui:include src="/pages/profile/myprofile_dialog.xhtml" />
   </f:view>
</h:body>
</html>

The trick here is again the ajax integration of the commandLink.

<f:ajax render=":dialog-myprofile-form" />

The f:ajax tag will rerender the dialog form. This is an important part of this solution, because you need to reset the old data of the dialog when the dialog is reopened. For example when the user opens the dialog, types in some data and close the dialog without submitting the data. In this scenario it is necessary to reload the dialog form data. This is done by the ajax render command.

So that’s it. I hope this will help someone.

Using @multipartconfig in a servlet running on GlassFish 3.2.2

Today I run into a problem with a custom JSF component using the @MultipartConfig. Trying to use my FileUpload Bean (http://www.imixs.org/jsf/fileupload.html) results in the following error message:

[#|2013-04-26T15:37:21.769+0200|WARNING|glassfish3.1.2|javax.enterprise.system.container.web.com.sun.enterprise.web|_ThreadID=20;_ThreadName=Thread-2;|StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception
java.lang.IllegalStateException: PWC4016: Request.getParts is called without multipart configuration.  Either add a @MultipartConfig to the servlet, or a multipart-config element to web.xml

It seems that this error did not be thrown on a GlassFish 3.2.1 server.

Finally I was able to fix the problem when adding the following servlet configuration into the web.xml file for my Faces Servlet.

 ...
	<!-- Facelets -->
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>0</load-on-startup>		
		<multipart-config>
	    	  <location>/tmp</location>
	    	  <max-file-size>20848820</max-file-size>
	    	  <max-request-size>418018841</max-request-size>
	    	  <file-size-threshold>1048576</file-size-threshold>
		</multipart-config>
        </servlet>
.....

 

 

How to Submit an Embedded Form in jQuery Dialog using AJAX

Today I searched for a solution to submit a form embedded into a jQuery dialog with ajax.

My situation is the following: I use a jQuery UI Dialog to display a feedback-form in my web application. The feedback form should not change the state of the page the user worked before.

So my first approach was to change my form post action into a ajax post action. This can be done easily during the initialisation of the dialog. See the following code snippet:

/**
 * Method to initialize the feedback dalog.
 * @see contact_dialog.xhtml
 */
function initContactDialog() {
    // set default settings for profile dialog
    $("#dialog-contact").dialog({
        resizable : false,
        height : 530,
        width : 550,
        modal : true,
        autoOpen : false
    });


    // hide contact dialog per default
    $("#dialog-contact").hide();
        
    // the following method modifies the submit request into a ajax request
    // So the dialog will be closed after the submit was successfull without
    // affects to the main page.
    $('#dialog-contact-form').submit(function() {
        
        // show up waiting panel
        $(".ajax-wait-panel").addClass("ajax-waiting"); 
   
        $.ajax({
               type: "POST",
               url: "http://localhost:8080/myrestservice",
               data: $("#dialog-contact-form").serialize(), // serializes the form's elements.
               success: function(data)
               {
                   $(".ajax-wait-panel").removeClass("ajax-waiting"); 
                   $("#dialog-contact").dialog("close");
               },
               error: function(data)
               {
                   alert('An error occured. Could not send data!'); // show response from post.
                   $(".ajax-wait-panel").removeClass("ajax-waiting"); 
               }
             });

        return false; // avoid to execute the actual submit of the form.
    });
    
}

With the initContactDialog() method I initialize the dialog and bind a function to the submit event of my form. The function changes the submit into a ajax call and closes the dialog after the ajax request was finished.

This is quite easy and the dialog will automatically close when the Ajax submit was finished.

Here is the html part of my dialog form:

    <!-- Dialog Box -->
        <div id="dialog-contact"  title="#{global.contact_title}">
            <form id="dialog-contact-form" method="post" name="contact_form">

                <h:panelGrid columns="2">

                    <h:panelGroup>
                        <dl>
                            <dt>#{global.contact_firstname}:</dt>
                            <dd>
                                <input type="text" name="txtfirstname" value="" />
                            </dd>
                        </dl>
                    </h:panelGroup>
                    <h:panelGroup>
                        <dl style="">
                            <dt>#{global.contact_lastname}:</dt>
                            <dd>
                                <input type="text" name="txtlastname" value="" />
                            </dd>
                        </dl>
                    </h:panelGroup>
                    <h:panelGroup>
                        <dl style="">
                            <dt>#{global.contact_email}:</dt>
                            <dd>
                                <input type="text" name="txtemail" value="" />
                            </dd>
                        </dl>
                    </h:panelGroup>
                </h:panelGrid>
                <dl style="margin: 0 0 0 0px;">
                    <dt>#{global.contact_message}:</dt>
                    <dd>
                        <textarea style="width: 450px; height: 80px;" name="_description" />
                    </dd>
                </dl>
                <input type="submit" value="send" />

            </form>
            <div>
                <h2>#{global.please_wait}</h2>
            </div>
        </div>

I open the dialog with the following JavaScript function:

 /**
 * helper method to open the contact dialog. 
 * The method creates a new empty contact workitem.
 */
function openContact() {    
   $("#dialog-contact").show();
   $("#dialog-contact").dialog("open");
}

AJAX ‘WAIT-PANEL’

As you can see in my script and in the html snippet I have added a div section with the class ‘ajax-wait-panel’. This div overlays the form of my dialog when the ajax call is started. So the user will see a ‘Please wait’ message until the ajax request is finished. I simply add the class ‘ajax-waiting’ to the div section in the moment the request starts and remove the class when the submit was finished. So this is the css part of my solution:

/* Ajax-wait-panel can be useded in jquery dialogs
   for long runnign ajax request.
   Start by setting display:none to make this hidden.
   Background we set to 80% white with
   our animation centered, and no-repeating */
 .ajax-wait-panel {
    display:    none;
    position:   absolute;
    z-index:    1000;
    top:        0;
    left:       0;
    height:     100%;
    width:      100%;
    background: rgba( 255, 255, 255, .6 ) 
                url('ajax-loader.gif') 
                50% 50% 
                no-repeat;
    cursor: wait;
}

.ajax-wait-panel  h2 {
    position: absolute;
    top: 50%;
    margin-top: -80px;
    color: #666;
    text-align: center;
    width: 100%;
}
/* Class to be added when ajax wait panel should 
   be displayed */
.ajax-waiting {
     display: block;
}

jQuery Dialog – how to submit a form with ajax

Today I searched for a solution to submit a form embedded into a jQuery dialog with ajax.

My situation is the following: I use a jQuery UI Dialog to display a feedback-form in my web application. The feedback form should not change the state of the page the user worked before.

So my first approach was to change my form post action into a ajax post action. This can be done easily during the initialisation of the dialog. See the following code snippet:

/**
 * Method to initialize the feedback dalog.
 * @see contact_dialog.xhtml
 */
function initContactDialog() {
    // set default settings for profile dialog
    $("#dialog-contact").dialog({
        resizable : false,
        height : 530,
        width : 550,
        modal : true,
        autoOpen : false
    });

    // hide contact dialog per default
    $("#dialog-contact").hide();

    // the following method modifies the submit request into a ajax request
    // So the dialog will be closed after the submit was successfull without
    // affects to the main page.
    $('#dialog-contact-form').submit(function() {

        // show up waiting panel
        $(".ajax-wait-panel").addClass("ajax-waiting"); 

        $.ajax({
               type: "POST",
               url: "http://localhost:8080/myrestservice",
               data: $("#dialog-contact-form").serialize(), // serializes the form's elements.
               success: function(data)
               {
                   $(".ajax-wait-panel").removeClass("ajax-waiting"); 
                   $("#dialog-contact").dialog("close");
               },
               error: function(data)
               {
                   alert('An error occured. Could not send data!'); // show response from post.
                   $(".ajax-wait-panel").removeClass("ajax-waiting"); 
               }
             });

        return false; // avoid to execute the actual submit of the form.
    });

}

With the initContactDialog() method I initialize the dialog and bind a function to the submit event of my form. The function changes the submit into a ajax call and closes the dialog after the ajax request was finished.

This is quite easy and the dialog will automatically close when the Ajax submit was finished.

Here is the html part of my dialog form:

    <!-- Dialog Box -->
        <div id="dialog-contact"  title="#{global.contact_title}">
            <form id="dialog-contact-form" method="post" name="contact_form">

                <h:panelGrid columns="2">

                    <h:panelGroup>
                        <dl>
                            <dt>#{global.contact_firstname}:</dt>
                            <dd>
                                <input type="text" name="txtfirstname" value="" />
                            </dd>
                        </dl>
                    </h:panelGroup>
                    <h:panelGroup>
                        <dl style="">
                            <dt>#{global.contact_lastname}:</dt>
                            <dd>
                                <input type="text" name="txtlastname" value="" />
                            </dd>
                        </dl>
                    </h:panelGroup>
                    <h:panelGroup>
                        <dl style="">
                            <dt>#{global.contact_email}:</dt>
                            <dd>
                                <input type="text" name="txtemail" value="" />
                            </dd>
                        </dl>
                    </h:panelGroup>
                </h:panelGrid>
                <dl style="margin: 0 0 0 0px;">
                    <dt>#{global.contact_message}:</dt>
                    <dd>
                        <textarea style="width: 450px; height: 80px;" name="_description" />
                    </dd>
                </dl>
                <input type="submit" value="send" />

            </form>
            <div>
                <h2>#{global.please_wait}</h2>
            </div>
        </div>

I open the dialog with the following JavaScript function:

 /**
 * helper method to open the contact dialog. 
 * The method creates a new empty contact workitem.
 */
function openContact() {    
   $("#dialog-contact").show();
   $("#dialog-contact").dialog("open");
}

AJAX ‘WAIT-PANEL’

As you can see in my script and in the html snippet I have added a div section with the class ‘ajax-wait-panel’. This div overlays the form of my dialog when the ajax call is started. So the user will see a ‘Please wait’ message until the ajax request is finished. I simply add the class ‘ajax-waiting’ to the div section in the moment the request starts and remove the class when the submit was finished. So this is the css part of my solution:

/* Ajax-wait-panel can be useded in jquery dialogs
   for long runnign ajax request.
   Start by setting display:none to make this hidden.
   Background we set to 80% white with
   our animation centered, and no-repeating */
 .ajax-wait-panel {
    display:    none;
    position:   absolute;
    z-index:    1000;
    top:        0;
    left:       0;
    height:     100%;
    width:      100%;
    background: rgba( 255, 255, 255, .6 ) 
                url('ajax-loader.gif') 
                50% 50% 
                no-repeat;
    cursor: wait;
}

.ajax-wait-panel  h2 {
    position: absolute;
    top: 50%;
    margin-top: -80px;
    color: #666;
    text-align: center;
    width: 100%;
}
/* Class to be added when ajax wait panel should 
   be displayed */
.ajax-waiting {
     display: block;
}

JSF f:ajax – How to locate componets outside the current context

Using JSF 2.0 and Ajax simplifies the web design and provides a lot of cool tricks to extend the user experience. With the render and execute tags form the f:ajax tag it is use to update components dynamically.

But in the past I run often into problems when trying to update a component outside the current ui context. For example when you try to update a part of your form for a single row in h:datatable component you will typically see log messages like this one:

f:ajax contains an unknown id 'j_idt90:painelTabela' - cannot locate it in the context of the component j_idt75

To solve such kind of problems you need to specify the full component id to be rendered or executed. This is not always as easy at it sounds. When your component is nested in a complex component tree the component id can be prafixed with a long list of parent component ids. This happens typically in h:datatables, ui:repeats or c:forEach sections.

One solution is to navigate back in the tree to the correct ui node and get the componentID using an EL syntax like this:

<f:ajax render=":#{component.parent.parent.parent.parent.clientId}:new-minute-panel:" />

This looks not really nice and it creates new problems when you redesign or move your ui components into a new structure on your jsf page.

A simple trick to solve the problem is to bind the component which need to be rendered into a ui param. So you can reference its full clientId in the ajax context. See the following example:

<h:panelGroup layout="block" id="mylist" binding="#{myListComponent}">                
   <ui:repeat var="attachment" value="#{myController.myList}">
       ....
       <!-- some ajax functionality... -->
       <f:ajax render=":#{myListComponent.clientId}">
           <h:commandLink actionListener="#{myController.soSomething}">click me</h:commandLink>
       </f:ajax>
 ...
   </ui:repeat>
....

In this example I use the binding tag to bind the panelGroup to a param named ‘myListComponent’. Inside the ui:repeat I can now access the outer component and render the component fom my f:ajax element accessing the clientId

<f:ajax render=":#{myListComponent.clientId}"

As a result the ajax component no longer depends on the position in my page and I can reuse it in any part of my jsf page.

TRANSFER CLIENTIDS TO SUBFORMS

Another solution using the binding is to transfer a component into a subform. See the following example:

 <h:panelGroup id="my_panel" binding="#{myListComponent}">
     <h:dataTable id="mydatatable" value="#{myController.myList}" var="child">
       .....
        <ui:include src="/forms/sub_myeditor.xhtml" >
            <ui:param name="myPanel" value="#{myListComponent}" />            
        </ui:include>
       .....
     </h:dataTable>

In this example I transfer the ui:component containing my h:datatable to a subpage ‘sub_myeditor.xhtml’  which is included inside the table. Now I can access the panelGroup inside my subpage and render it after an ajax event:

<h:commandButton ....  >
       <f:ajax render=":#{myListComponent.clientId}" 
                execute=":#{myListComponent.clientId}"/>
</h:commandButton>

Also in this example the component in the ajax tag is addressed with its absolute path.

JSF 2.0 – ajax suggestion box

Since JSF 2.0 has introduced the ajax support it is quite simple to implement functional widgets like a suggestion input box. The following short tutorial shows how to build your own suggestion widget using JSF 2.0 and it’s ajax capabilities.

1. THE HTML FORM

First you need a simple input field where the user can type in a search phrase. This can be done wit the h:inputText element. After the user typed in some character a suggestion widget should start a backend search and provide the user with a list of suggestions (you can see this behaviour when searching for something on google.com). To connect your inputText element with a backend component you can use the new build-in ajax feature provided by JSF 2.0. So your input element looks something like this:

<h:panelGroup layout="block" style="margin-bottom:5px;">
     <h:inputText value="#{suggestController.input}">
        <f:ajax event="keyup"  render="suggest_box" /> 
     </h:inputText>
</h:panelGroup>

 

2. DEFINE THE SUGGEST BOX

With the ‘render’ attribute of the f:ajax tag you specify which part of your page should be rerendered after the ajax event was fired. In this case an element with the ID ‘suggest_box’ will be updated. This is the part where you can display the results of your backend search:

<h:panelGroup id="suggest_box">
	<ul>
		<ui:repeat var="entry" value="#{suggestController.result}">
			<li>#{entry}</li>
		</ui:repeat>
	</ul>
</h:panelGroup>

 

To bind you backend component (suggestController) to the event just use the listener tag:

 <f:ajax event="keyup" render="suggest_box"
	listener="#{suggestController.search}" >
</f:ajax>

Your suggest controller implementation can look like this:

....
public void search(AjaxBehaviorEvent event) {
	....
	result=new ArrayList<String>();
	....
}

public List<String> getResult() {
	return result;
}

If you are working with EL 2.2 support (GlassFish 3.1) you can also pass params as method arguments:

<f:ajax event="keyup" render="suggest_box"
	listener="#{suggestController.search('abc')}" >
</f:ajax>
public void search(String param) {
       ..
}

 

3) LAYOUT

Now you can do some layout stuff. Typically the suggestion box should only be displayed with a user typed in a search phrase. And the suggestion box should hidden if the focus is lost. This can be done with some css definition:

.suggestbox {
	position: relative;
}

.suggestbox .resultlist {
	display: block;
	position: absolute;
	z-index: 1;
	left: 2px;
	top: 22px;
	border: 1px solid #CCC;
	background-color: #EEE;
}

To hide the resultlist you can use the f:ajax event ‘blur’

 <f:ajax event="blur" render="suggest_box"
                    listener="#{suggestController.reset}" />

The listener is bound to a backend method which resets the result list. So you can display the complete box in order of the current result. This is the complete code:

JSF Code:

<h:panelGroup layout="block">
	<!-- Process references -->
	<h:panelGroup layout="block" style="margin-bottom:5px;">
		<h:inputText value="#{suggestController.input}">
			<f:ajax event="keyup" render="suggest_box"
				listener="#{suggestController.search('')}" />
			<f:ajax event="blur" render="suggest_box"
				listener="#{suggestController.reset}" />
		</h:inputText>
	</h:panelGroup>
	<h:panelGroup id="suggest_box">
		<h:panelGroup id="suggest_resultlist"
			rendered="#{! empty suggestController.result}">
			<ul>
				<ui:repeat var="entry" value="#{suggestController.result}">
					<li>#{entry}</li>
				</ui:repeat>
			</ul>
		</h:panelGroup>
	</h:panelGroup>
</h:panelGroup>

 SuggestController:

@Named("suggestController")
@RequestScoped
public class SuggestController implements Serializable {

	private static final long serialVersionUID = 1L;
	private List<String> result=null;
	private String query = null;
	private String input =null;
	
	public SuggestController() {
		super();
		result = new ArrayList<String>();
	}

	public String getQuery() {
		return query;
	}

	public void setQuery(String query) {
		this.query = query;
	}

	public String getInput() {
		return input;
	}

	public void setInput(String input) {
		this.input = input;
	}
	
	public void reset(AjaxBehaviorEvent event) {
		 result=new ArrayList<String>();
	}
	
	public void search(String query) {
    	result=new ArrayList<String>();
		result.add("Hallo "  + System.currentTimeMillis());
		result.add("World "+ + System.currentTimeMillis());

	}
	
	public List<String> getResult() {
		return result;
	}

}

4) DELAY AJAX EVENTS

Maybe you run into a problem with the onblur ajax call to hide your overlay section. If the section contains h:command links or buttons the action and actionListeners will not be called because the ajax blur event hides the overlay to early.

With a trick from BalusC you can delay the blur event a little bit. So just add the following jQuery code into your page:

$(document).ready(function() {
	$(".suggestinput").each(function(index, input) {
	    var onblur = input.onblur;
	    input.onblur = null;
	
	    $(input).on("blur", function(event) {
	        delay(function() { onblur.call(input, event); }, 300);
	    });
	    // turn autocomplete of
	    $(this).attr('autocomplete','off');
	});

});

var delay = (function() {
    var timer = 0;

    return function(callback, timeout) {
        clearTimeout(timer);
        timer = setTimeout(callback, timeout);
    };
})();