The Artima Developer Community
This article is sponsored by the Java Community Process.

Leading-Edge Java
JSF and JSP: What's New in Java EE 5
A Conversation with Ed Burns and Jan Luehe
by Frank Sommers
May 17, 2006

<<  Page 3 of 3

Advertisement

AJAX and Annotations

Frank Sommers: What AJAX-related features were added to JSF and JSP?

Ed Burns: While a lot could be done with JSF and AJAX beyond what we provide now, the JSF and JSP spec leads had to work within the constraints of time in terms of what we could do. We did make some key changes in the JSF API to help AJAX-style applications. These build on JSF's strength in state management—JSF components maintain their own state. With AJAX, you can transfer that state back and forth between server and component. There are many ways of doing that, and we don't specify one particular way in the JSF specs.

JSF's ability to maintain state within the component comes in handy in many AJAX use-cases. For instance, in a drop-down list, when the user selects a list item, that selection can cause another part of the page to show. To enable that state transfer [of the component's serialized state], the JSF state model included a hidden field that contained the component's full serialized state. We now standardized the name of that hidden field, and you can access that field from within AJAX.

Another interesting JSF feature that helps with AJAX development is life-cycle listeners. JSF provides listeners on the component life-cycle. But you can provide custom life-cycle listeners on a per servlet basis. You can have life-cycle listeners that process AJAX-based events, and events occurring in the view. Suppose you want to use Faces validation, and set a specific database validation listener on a component. With a per-view listener, you can attach a listener to the view, and use that listener to take action for validation [when some aspect of the view changes]. The benefit of the per-View phase listener is that it doesn't affect all requests, just ones to that view.

It's worth noting that there is now a growing library of AJAX-enabled JSF components. We're just now going public with a set of nine components that you can run in Java Studio Creator. The components include an AJAX file-upload component, an AJAX progress bar, a pop-up bubble. Another interesting component in this library is an AJAX validator, and this goes back to life-cycle processing. When doing client-side validation you can't take advantage of the JSF-provided life-cycle elements. Yet you often want validation to be part of a component's life-cycle. For instance, before updating the model data, you may always want to ensure that the data matches [validation requirements]. This component wraps validation into a JSF life cycle.

The validator component is handy for those cases when mere syntactic validation, as often practiced in pure client side validation, is not sufficient. For example, a credit card number can be syntactically validated to ensure that it contains sixteen digits. This can and should be done entirely on the client. However, to verify that the account is active and in good stead requires a server transaction. Requiring the user to do a full page refresh just to get this data would be a hassle. The Ajax validator component enables wrapping any JSF component with any JSF validator, and running just the validation part of the lifecycle on that specific component instance.

Frank Sommers: You mentioned dependency injection and annotations. How do annotations help a JSF and JSP developer?

Jan Luehe: You can now inject dependencies, such as resources, into JSF. An example is a managed bean. All other Web tier technologies have taken advantage of dependency injection as well: In JSP, you can inject a tag handler, in servlets, a servlet or a servlet filter. You also inject these into custom JSP tags as well.

An interesting example of how this helps is in conjunction with the new Java persistence API in Java EE 5. You can inject a persistence context or a JDNI resource into a JSP or servlet by sticking an annotation into a custom tag. This avoids having to write a lot of boiler-plate code.

Consider a servlet that increments and persists in a database the number of times the person identified by the request parameter "name" has been greeted. If the servlet was mapped to /HelloServlet in samples.war, an invocation of it might look as follows:

http://:/samples/HelloServlet?name=tom  

Prior to dependency injection, the servlet would look up and update a JNDI resource, like this:

 
InitialContext initCtx = new InitialContext();  
DataSource ds = (DataSource)  
    initCtx.lookup("java:comp/env/jdbc/PersonDB");  
Connection conn = ds.getConnection();  
PreparedStatement pst = conn.prepareStatement(  
    "update Person set hellocount=hellocount+1 where name = ?");  
pst.setString(1, name);  
pst.executeUpdate();  

With resource injection, the requested data source can be made available to the servlet right after the servlet has been instantiated:

 

@Resource private DataSource ds;  
 
Connection conn = ds.getConnection();  
PreparedStatement pst = conn.prepareStatement(  
    "update Person set hellocount=hellocount+1 where name = ?");  
pst.setString(1, name);  
pst.executeUpdate();  
To simplify things further, a person's record could be implemented as an Entity bean, as follows:
 
@Entity  
public class Person {  
    
    @Id protected String name;  
    
    protected int hellocount;  
 
    protected Person() {  
    }  
 
    public Person(String name) {  
        this.name = name;  
    }  
 
    public void incrementHelloCount() {  
        hellocount++;  
     }  
}  

and accessed and updated using the new Persistence framework in Java EE 5, like this:

@PersistenceUnit private EntityManagerFactory emf;  
@Resource private UserTransaction utx;  
 
utx.begin();  
EntityManager em = emf.createEntityManager();  
Person p = em.find(Person.class, name);  
if (p != null) {  
    p.incrementHelloCount();  
}  
utx.commit();  

APPENDIX

The following code examples show three versions of the same servlet. Listing 1 shows how a data source is obtained via a JNDI lookup. Listing 2 injects the data source as a dependency into the servlet, alleviating the need to use JNDI. Listing 3 shows how the same servlet can use EJB 3 persistence to further simplify what a developer has to write.

Listing 1. HelloServlet.java

import java.io.*;
import java.sql.*;
import javax.naming.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.sql.*;

public class HelloServlet extends HttpServlet {

    public void service(HttpServletRequest req, HttpServletResponse res)
            throws IOException, ServletException {

        String name = req.getParameter("name");
        if (null == name) {
            return;
        }

        Connection conn = null;
	try {
            InitialContext initCtx = new InitialContext();
            DataSource ds = (DataSource)
                initCtx.lookup("java:comp/env/jdbc/PersonDB"); 
            conn = ds.getConnection();
            PreparedStatement pst = conn.prepareStatement(
                "update Person set hellocount=hellocount+1 where name = ?");
            pst.setString(1, name);
            pst.executeUpdate();
        } catch (NamingException namingEx) {
            throw new ServletException(namingEx);
        } catch (SQLException sqlEx) {
            throw new ServletException(sqlEx);
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException ex) {
                    // ignore
                }
            }
        }
    }
}

Listing 2. HelloServletResourceInjection.java

import java.io.*;
import java.sql.*;
import javax.annotation.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.sql.*;

public class HelloServletResourceInjection extends HttpServlet {

    @Resource private DataSource ds;
    
    public void service(HttpServletRequest req, HttpServletResponse res)
            throws IOException, ServletException {

        String name = req.getParameter("name");
        if (null == name) {
            return;
        }

        Connection conn = null;
	try {
            conn = ds.getConnection();
            PreparedStatement pst = conn.prepareStatement(
                "update Person set hellocount=hellocount+1 where name = ?");
            pst.setString(1, name);
            pst.executeUpdate();
        } catch (SQLException ex) {
            throw new ServletException(ex);
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException ex) {} // ignore
            }
        }
    }
}

Listing 3. HelloServletPersistence.java

import java.io.*;
import javax.annotation.*;
import javax.persistence.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.transaction.*;

public class HelloServletPersistence extends HttpServlet {

    @PersistenceUnit private EntityManagerFactory emf;
    @Resource private UserTransaction utx;

    public void service(HttpServletRequest req, HttpServletResponse res)
            throws IOException, ServletException {

        String name = req.getParameter("name");
        if (null == name) {
            return;
        }

        try {
            utx.begin();
        } catch (Exception e) {
            throw new ServletException(e);
        }

        EntityManager em = emf.createEntityManager();
        try {
            Person p = em.find(Person.class, name);
            if (p != null) {
                p.incrementHelloCount();
            }
            utx.commit();
        } catch (Exception e) {
            try {
                utx.rollback();
            } catch (Exception ee) {} // log exception
            throw new ServletException(e);
        } finally {
            em.close();
        }
    }
}

Listing 4. Person.java

import javax.persistence.*;

@Entity
public class Person {
    @Id protected String name;
    protected int hellocount;

    protected Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    public void incrementHelloCount() {
        hellocount++;
    }
}

Talk back!

Have an opinion about the new JSP and JSF features? Discuss this article in the Articles Forum topic, JSF and JSP: What's New in Java EE 5?.

Resources

About the author

Frank Sommers is Artima's Senior Editor.

<<  Page 3 of 3


This article is sponsored by the Java Community Process.

Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us