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.

Glassfish and Active Directory

Running JEE Applications on Glassfish can be easily connected to an existing Microsoft Active Directory Structure.

To authenticate a JEE application against Active Directory (AD) you can setup a LDAPRealm in Glassfish. Use the folowing example settings:

  •  JAAS Context: ‘ldapRealm’
  • Direcotry : ldap://your-ad-server:389
  • Base DN: ‘DC=mycompany,DC=local’

Additional to these standard connection settings (you should use your own environment configuration) you need to add the following additioanl Properties:

  • search-filter = (&(objectClass=user)(sAMAccountName=%s))
  • group-search-filter = (&(objectClass=group)(member=%d))
  • search-bind-dn = some-technical-account (do not use distinguished name)
  • search-bind-password = your-technical-account-password
  • java.naming.referral = follow

The property ‘java.naming.referral = follow’ is necessary in most cases to avoid internal exceptions during a search request.

Thats it.

HOW TO CONFIGURE AN  EXTERNAL JNDI RESOURCE

You can also use the AD to lookup additional ldap attributes from you application code. There for you need to add a external JNDI Resource which can be configured from the GlassFish console. Use the following example settings:

  • JNDI Name : you-custom-resource-name
  • Resource Type: javax.naming.ldap.LdapContext
  • Factory CLass: com.sun.jndi.ldap.LdapCtxFactory
  • JNDI Lookup: ‘DC=mycompany,DC=local’

Also here you should add some additional properties:

  • java.naming.provider.url = ldap://your-ad-server:389
  • java.naming.security.authentication = simple
  • java.naming.security.principal = some-technical-account (do not use distinguished name)
  • java.naming.security.credentials = your-technical-account-password
  • java.naming.referral = follow

The property ‘java.naming.referral = follow’ again is important here.

To lookup the external resource from your application you can use the either a annotation:

@Resource(name = "you-custom-resource-name")
private DirContext ldapConn;

You can also do a programatic lookup like this:

Context initCtx = new InitialContext();
ldapCtx = (LdapContext) initCtx.lookup("you-custom-resource-name");

 

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);
    };
})();

 

JEE6 – How to package an EAR – Part II.

As I explained in my previous blog entry about JEE6 ear packaging, there is a flexible and powerful way to deploy EARs containing JEE component libraries.

Using maven makes it much easy to build such ear deployment units. The interessting part of the pom.xml of the ear module looks something like this:

 

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-ear-plugin</artifactId>
                <version>2.6</version>
                <configuration>
                    <version>6</version>
                    <modules>
                        <webModule>
                            <groupId>myweb</groupId>
                            <artifactId>imixs-web</artifactId>
                            <contextRoot>/test</contextRoot>
                        </webModule>
                        <ejbModule>
                            <groupId>myejb</groupId>
                            <artifactId>imixs-ejb</artifactId>
                        </ejbModule>
                        <JarModule>
                            <groupId>org.imixs.workflow</groupId>
                            <artifactId>imixs-workflow-engine</artifactId>
                            <bundleDir>/</bundleDir>
                        </JarModule>                        
                    </modules>
                </configuration>
            </plugin>
        </plugins>
 ....

In this example the artefact ‘imixs-workflow-engine’ is a component library containingg EJBs. You can refere to those libraries from your ejb module (in this example ‘myejb’) by using the ‘manifestEntries’ tag in your maven ejb module configuration. This is what I explained here.

But what if you need some more additional external libraries containing non-jee-components (simple pojo’s like for example apache commons-xx.jars) ?

You can add those dependencies to your ear pom.xml – so these jars will also become part of the ear root directory. But now you need to add them again to the manifest file of your ejb module if you need access to these libraries. And this will result in a strange situation because indirect dependencies will make it impossible for you to manage your manifest file manually.

I run in this situation when a need the apache fop-1.0 library in one of my ejb components.

But the solution is again quite simple when using maven and the ear-plugin. The plugin provides a configuration tag named ‘defaultLibBundleDir’. And you simply need to the the value to ‘lib’ to get all your libraries moved in the default lib directory of an ear:

<plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-ear-plugin</artifactId>
       <version>2.6</version>
       <configuration>
            <version>6</version>
            <defaultLibBundleDir>lib</defaultLibBundleDir>
            <modules> 
         .....
  ....
</plugin>

But you need to be careful because also your jee-component libraries will be moved into that location if you did not overwrite the default behaviour now.  You can do this by declaring each of your jee component libraries as a ‘JarModule’ where you specifiy the ‘bundleDir’ with ‘/’:

....
<module>
 ....
  <JarModule>
       <groupId>org.imixs.workflow</groupId>
       <artifactId>imixs-workflow-core</artifactId>
       <bundleDir>/</bundleDir>
  </JarModule>
</module>
...

This will result in a ear structure where your own jee-components will become part of the root of your ear, and all other library dependencies will be moved to the /lib directory of your ear. So any libary can be seen from your ejb, web and component modules. And you jee-component.jars will still be parsed for JEE annotations during deployment.

I hope this helps you to build you own custom enterprise applications using all the strength of JEE.

 

Glassfish – 3.1.X – CDIExtension not found

Today I run into a problem when trying to deploy a EAR with more than one web modules using CDI. Deploying such a EAR on Glassfish 3.1.1 or 3.1.2 will fail with the following exception:

Root exception is javax.naming.NameNotFoundException: CDIExtension not found

As you can read in this posting this is a known bug.

http://www.java.net/forum/topic/glassfish/glassfish/gf-311-jdk1716-linux-64bit-application-running-windows-7-does-not-deploy-linux

 

http://java.net/jira/browse/JERSEY-601

 

You can solve the problem when setting the system-property “com.sun.jersey.server.impl.cdi.lookupExtensionInBeanManager=true”.

This can be done from the GlassFish server console.

  • Select the node ->Configuration->server-config->JVM Settings
  • change to the tab ‘JVM Options’
  • add a new entry
    -Dcom.sun.jersey.server.impl.cdi.lookupExtensionInBeanManager=true
  • restart your server

This will solve the deployment problem.

 

JSF 2.0 and the xmlns:c namespace

If you are working with JSF 2.0 there is a important change concerning the JSF core tags (<c:….>). These tags will not work if you are using the following namespace declaration:

<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:c="http://java.sun.com/jstl/core" 
    xmlns:h="http://java.sun.com/jsf/html">

This works in JSF 1.2 but well, but did no longer work in JSF 2.0. The reason is that the namespace uri for the jstl/core has changed. Use the following namespace definition if you are working with jsf 2.0

<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:c="http://java.sun.com/jsp/jstl/core"
    xmlns:h="http://java.sun.com/jsf/html">

 

JSF 2.0 – The action event model

If you are working with JSF 2.0 there are different ways to interact with backend methods and passing params to action methods. A useful link for this topic can also seen here.

So for example if you have a JSF page with the following command link you use different ways to bound your backing bean:

<h:commandLink action="#{workflowController.editAction(workitem)}"
               actionListener="#{workflowController.doEdit}">
         <h:outputText value="click me" />
         <f:setPropertyActionListener
               target="#{workflowController.workitem}" value="#{workitem}" />
</h:commandLink>

The important thing here is the order which the jsf framework will trigger the differnt methods of the backingBean ‘worklfowController’

  1. The actionListener method will be called
  2. The setPropertyActionListener will trigger the setter method of the property ‘workitem’
  3. The action method with a custom param will be called

So in this case you backingBean can look something like this – note that there are two different ways to pass a param:

 

   // first the actionListener method will be called   
   public void doEdit(ActionEvent event) throws Exception {
        // do something...
       .....
    }

   // next the setter for the property will be called
   public void setWorkitem(Data aworkitem) {
        // do something    
   }

   // last the action method will be called
   public String editAction(String action) {
        // do something
        return action;      
    }

 

JUnit and Glassfish 3.1.1 – remote ejb tests

Trying to run a JUnit Test with remote EJB lookups from a GlassFish server 3.1.1 it is a little bit tricky. It seems to me that it is not possible to get the maven dependencies working. The gf_client.jar can not be included using a dependency, although the artefact can be located using the glassfish repository from java.net :

    .....
      <!-- Glassfish -->
          <repository>
                 <id>glassfish-repository</id>
                 <name>Java.net 
                 Repository for Glassfish</name>
                <url>http://download.java.net/maven/glassfish</url>
          </repository>
.....

..and adding a dependecy:

    ...
    <dependency>
            <groupId>org.glassfish.appclient</groupId>
            <artifactId>gf-client</artifactId>
            <version>3.1.1</version>
            <scope>test</scope>
        </dependency>
....

But after all this wont work for me. So the best way is to add the gf_client.jar directly into your classpath.

The gf_client.jar is located in your Glassfish Installation at

$GLASSFISH_HOME/glassfish/lib/gf-client.jar

 

Now you can write a JUnit test with a remot ejb lookup. See the following example for a remote lookup to Imixs Entity Service

 public class TestEntityService {
    EntityServiceRemote entityService = null;

    @Before
    public void setup() {
        try {
            // set jndi name
            String ejbName = "java:global/imixs-workflow-web-sample-0.0.5-SNAPSHOT/EntityService!org.imixs.workflow.jee.ejb.EntityServiceRemote";
            InitialContext ic = new InitialContext();
            entityService = (EntityServiceRemote) ic.lookup(ejbName);
        } catch (Exception e) {
            e.printStackTrace();
            entityService = null;
        }
    }

    @Test
    @Category(org.imixs.workflow.jee.ejb.EntityServiceRemote.class)
    public void testService() {
        Assert.assertNotNull(entityService);
        //....

    }

Note: To run this JUnit test you have to first deploy your test application. After that you junit test can be run.

TESTING SECURED EJBS

If your remote ejb is annotated with the security annotation @RolesAllowed you need to authenticate your remote lookup.

In GlassFish this can be done using the programmatic Login. To setup a programmatic login in your JUnit test first create a File named ‘auth.conf’. The content of that file should look like this:

default { 
com.sun.enterprise.security.auth.login.ClientPasswordLoginModule required debug=false; 
};

Now you can add the programmatic login into your test setup

     @Before
    public void setup() {

        try {
            // set jndi name
            String ejbName = "java:global/imixs-workflow-web-sample-0.0.5-SNAPSHOT/EntityService!org.imixs.workflow.jee.ejb.EntityServiceRemote";
            // setup programmatic login for GlassFish 3
            System.setProperty("java.security.auth.login.config", "/home/rsoika/eclipse_37/imixs-workflow/imixs-workflow-engine/src/test/resources/auth.conf"); 
            ProgrammaticLogin programmaticLogin = new ProgrammaticLogin(); 
            // set password
            programmaticLogin.login("Anna", "anna"); 
            InitialContext ic = new InitialContext();
            entityService = (EntityServiceRemote) ic.lookup(ejbName);
        } catch (Exception e) {
            e.printStackTrace();
            entityService = null;
        }
    }

Note: the username/password is defined in this case in a file realm which is the default security realm of my GlassFish

Here are some helpful links:

http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB

http://www.coderanch.com/t/476090/EJB-JEE/java/EJB-Realms-Remote-Clients

 

GlassFish – Heapsize settings

After playing around with some VM settings in my GlassFish 3.1.1 environment (development and productive) I came to a setup which brings up my glassfish server much faster. Here are my settings

Development (3GB RAM)

-client
-XX:+AggressiveHeap
-Xmx1024m
-Xms1024m
-Xss128k
-XX:+DisableExplicitGC

 

Productiv (4GB Ram)

-server
-XX:+AggressiveHeap
-Xmx2048m
-Xms2048m
-Xss128k
-XX:+DisableExplicitGC

Here is also a useful link for further performance settings:

http://jfarcand.wordpress.com/2009/11/27/putting-glassfish-v3-in-production-essential-surviving-guide/