JSF Tip #56 - Using the action based prototype in Mojarra

The JavaEE team at Oracle has been busy processing the feedback from the JavaEE 8 Community Survey

Question 6 in part one of the survey reads: "Is there any one de-facto standard technology in this space [Server side web MVC framework, aside from JSF] to which we should look for inspiration". For those respondents that answered yes to that question, fully half of them cited Spring MVC. By way of background, it's possible to classify server side web frameworks as "action based" or "component based". For some background on these terms, please see http://javaserverfaces.java.net/presentations/demystifyingjsf.odp.

To explore the possibilities for adding "action based" to the UI standard for JavaEE, we have committed some experimental prototype work to snapshot builds of Mojarra on January 9th, 2014. The current prototype allows you to use a simple annotation which would result in a call to a method on your managed bean and then dispatch the response to a regular view.

To try out the code in this blog entry, grab the latest 2.2.6-SNAPSHOT build of Mojarra from the maven.java.net snapshot repository and drop it into the GlassFish 4.0 modules directory.

You will also need to add the following dependency in the POM of your web application.


    <dependency>
        <groupId>org.glassfish</groupId>
        <artifactId>javax.faces</artifactId>
        <version>2.2.6-SNAPSHOT</version>
        <scope>provided
    </dependency>
    

Our example bean


    import com.sun.faces.action.RequestMapping;
    import javax.enterprise.context.RequestScoped;
    import java.io.Serializable;
    import javax.faces.context.FacesContext;
    import javax.inject.Named;

    @Named("myBean")
    @RequestScoped
    public class MyBean implements Serializable {
        private String value;

        @RequestMapping(value = "/form1b.xhtml")
        public String form1() {
            String inputText1 = (String) FacesContext.getCurrentInstance().
                    getExternalContext().getRequestParameterMap().get("inputText1");
            setValue("We set inputText1 manually to - " + inputText1);
            return "/form1b.xhtml";
        }

        public void setValue(String value) {
            this.value = value;
        }

        public String getValue() {
            return this.value;
        }
    }
    

Note the request mapping here is an exact mapping, but you can also do an extension mapping (using *.xx) or a prefix mapping do (using prefix/*).

Our example page (using HTML syntax)


    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <title>Facelet HTML page</title>
        <head>
        <body>
            <form action="#{request.contextPath}/action/form1b.xhtml">
                <input id="inputText1" value="#{myBean.value}"/>
                <input id="submit" type="submit" value="Submit"/>
            </form>
        </body>
    </html>
    

Our example page (using JSF syntax)


    <?xml version='1.0' encoding='UTF-8' ?>
    
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://xmlns.jcp.org/jsf/html">
        <h:head>
            <title>Facelet Title</title>
        </h:head>
        <h:body>
            <form action="#{request.contextPath}/action/form1b.xhtml">
                <h:inputText id="inputText1" value="#{myBean.value}"/>
                <input id="submit" type="submit" value="Submit"/>
            </form>
        </h:body>
    </html>
    

The example result page (using HTML syntax)


    <!DOCTYPE html>

    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>
            <title>Result page</title>
        </head>
        <body>
            We did a POST to an action based URL and the result is:
            #{myBean.value}
        </body>
    </html>
    

The example result page (using JSF syntax)


    <?xml version='1.0' encoding='UTF-8' ?>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://xmlns.jcp.org/jsf/html">
        <h:head>
            <title>Result page</title>
        </h:head>
        <h:body>
            We did a POST to an action based URL and the result is:
            <h:outputText value="#{myBean.value}"/>
        </h:body>
    </html>
    

The relevant configuration in web.xml


    <servlet>
        <servlet-name>Faces Action Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <init-param>
            <param-name>javax.faces.LIFECYCLE_ID</param-name>
            <param-value>com.sun.faces.action.ActionLifecycle</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>      
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>      
    <servlet-mapping>
        <servlet-name>Faces Action Servlet</servlet-name>
        <url-pattern>/action/*</url-pattern>
    </servlet-mapping>    
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
    </servlet-mapping> 
    

While not necessary we opted to include the regular mapping to the FacesServlet to demonstrate that the "action based" approach can coexist in a JSF web application.

Note as this code is in SNAPSHOT mode it means we might need to do some code adjustments, so consider these code samples as examples of what we might or might not be working towards.

Posted January 13, 2014

Up