Posts Tagged ‘wip

06
Dec
09

JSF form Validation

This page describes the process of setting up validation in a JSF application.

JSF Standard Validators

JSF comes with standard validators

  1. <validateDoubleRange> : validates to see if the value is a double
  2. <validateLongRange> : validates to see if the value is a long.
  3. <validateLength> : validates to see if the string value for length.

With all of the tags above you can specify a minimum and/or maximum value.

Requirements

  • Maven
  • That’s pretty much it!

Generate the project from an archetype:

mvn archetype:generate -DarchetypeGroupId=org.vtechfw -DarchetypeArtifactId=springmvc-jsf-archetype -DarchetypeVersion=1.0-SNAPSHOT -DarchetypeRepository=http://www.vermatech.com/m2repo

groupId: com.test
artifactId: jsf-validation

The rest of the questions just hit enter choosing the defaults.

test to see if the project comes up

cd jsf-validation;
mvn jetty:run;

Navigate to the application http://localhost:8080/ It should come up with a homepage.

If it does then the test is complete You can continue with the rest of the page.

Message Resources Property File

This file contains all the error messages we will display when validation fails.

src/main/resources/com/test/jsftest/messages.properties

username_required=Username is required
password_required=Password is required
between=Value must be between 2 and 10.

In the resource bundle if the key are composed of multilple word separated by ▒??dot▒??(.),you should represent that key in the JSP page using the format #{msg[‘key’]}.This is a must because ▒??dot▒??(.) is considered as a special character in JSF expression language.

The next step is to get the message bundle property registered in the application.

src/main/webapp/WEB-INF/faces-config.xml

<application>
    <resource-bundle>
        <base-name>
            com.test.jsftest.messages
        </base-name>
        <var>msgs</var>
    </resource-bundle>
</application>

As an alternative you can also type the following in each JSP:

<f:loadBundle basename="com.test.jsftest.messages" var="msgs"/>

Create the Managed Bean Java Class

In the Reference section below get the source for UserManagedBean.java and create it in your source directory.
src/main/java/com/test/jsftest/UserManagedBean.java

package com.test.jsftest;

public class UserManagedBean {
        private String username = "";
        private String password = "";

        public String getUsername() {
                return username;
        }
        public void setUsername(String username) {
                this.username = username;
        }

        public String getPassword() {
                return password;
        }

        public void setPassword(String password) {
                this.password = password;
        }
}

Open up faces-config.xml and insert this right above the managed beans.
src/main/webapp/WEB-INF/faces-config.xml

<managed-bean>
        <managed-bean-name>userManagedBean</managed-bean-name>
        <managed-bean-class>com.test.jsftest.UserManagedBean</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

Setup the Form Page

Next we set up the form page that the user will pull up to enter the username and pssword. The complete source for this page is located in the Reference section. Please copy and paste the source into your webapp/faces directory now.

Once you are done then run the project using

mvn jetty:run

Run The Application

http://localhost:8080/faces/login.faces

Discussions

As you can see below the following is a snippit of what is defined in the login.jsp file.

                <p>Enter your username here: <br/>
                <h:inputText id="username" value="#{username}" size="35"
                        required="true" requiredMessage="#{msgs.username_required}"
                        validatorMessage="#{msgs.between}">
                        <f:validateLength minimum="2" maximum="10" />
                </h:inputText>
                <h:message for="username"/>
                </p>

I am trying to find out how to place 2 and 10 with parameter markers. If you guys know how to do this then please post a comment.

Adding Color

<h:message for="username" style="color: red;"/>

Showing Bulleted list of errors

In order to show a bulleted list of errors on top or bottom of the screen just put this tag at the desired location.

<h:messages showDetail="#{true}" showSummary="#{false}" />

For Reference

In case you got lost the complete source for each file is included here:

src/main/java/com/test/jsftest/UserManagedBean.java

package com.test.jsftest;

public class UserManagedBean {
        private String username = "";
        private String password = "";

        public String getUsername() {
                return username;
        }
        public void setUsername(String username) {
                this.username = username;
        }

        public String getPassword() {
                return password;
        }

        public void setPassword(String password) {
                this.password = password;
        }
}

src/main/webapp/WEB-INF/faces-config.xml

<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
              version="1.2">
<application>
    <resource-bundle>
        <base-name>
            com.test.jsftest.messages
        </base-name>
        <var>msgs</var>
    </resource-bundle>
</application>

<managed-bean>
        <managed-bean-name>userManagedBean</managed-bean-name>
        <managed-bean-class>com.test.jsftest.UserManagedBean</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

</faces-config>

src/main/webapp/faces/login.jsp

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>

<f:view>
    <html>
    <head>
        <title>Login Page</title>
    </head>
    <body>
        <h:messages showDetail="#{true}" showSummary="#{false}" />
    <h:form>
                <p>This is a simple login page using Faces.</p>
                <p>Enter your username here: <br/>

                <h:inputText id="username" value="#{userManagedBean.username}" size="35"
                        required="true" requiredMessage="#{msgs.username_required}"
                        validatorMessage="#{msgs.between}">
                        <f:validateLength minimum="2" maximum="10" />
                </h:inputText>
                <h:message for="username" style="color: red;"/>
                </p>
                <p>Enter your password here: <br/>
                <h:inputText id="password" value="#{userManagedBean.password}" size="35"
                        required="true" requiredMessage="#{msgs.password_required}">
                        <f:validateLength minimum="2" maximum="10" />
                </h:inputText> <h:message for="password"/>
                </p>
                <h:commandButton value="Submit" action="submit"/>
    </h:form>
    </body>
    </html>
</f:view>

src/main/resources/com/test/jsftest/messages.properties

username_required=Username is required
password_required=Password is required
between=Value must be between 2 and 10.

Thats all for now!

This site is a collaborative effort! The complete text and sourcecode for this is available on GitHub. Corrections and enhancements are welcome, please make the change and submit a pull request in the comment area below.
Advertisements
28
Nov
09

Bullet Proof MVC using Maven Multi-Module Projects

ge { margin: 0.79in } P { margin-bottom: 0.08in } –>This page will describe the process of setting up a multi-module project where each component of the MVC architecture is separated into its own sub-module. Separating each component of the MVC into modules results in protecting the code from leakage of Concerns.

Background

The model view controller architecture has been discussed for years. It was first introduced back in 1979 by a developer working on Smalltalk language. http://en.wikipedia.org/wiki/Model▒??view▒??controller

But until recently implementing it religiously has been a challenge.

Requirements

  • Basic understanding of the Spring Framework
  • Basic understanding of MVC
  • Basic understanding of Maven2

Framework’s ability to enforce MVC

Although popular MVC framework claims to help developers separate concerns in software applications, they really don’t live up to the promise.

Developers end up implementing business logic within controllers and JSP’s. If you have developed professionally you know what I am talking about. We all share horror stories of JSP’s that look like they are controlling flow, and Controllers that look like they are making business decisions and executing JDBC queries directly and passing references to HttpServletRequest and HttpServlet into model objects.

What we got was implementations that were ▒??sort of▒?? adhering to the model view controller pattern.

Its not the framework’s fault directly but the simple fact of allowing a developer to do bad things while working with it.

Controller leaking into Model

If there were a way to prevent the Model from even recognizing HttpServletRequest class would be adequate to stop leaking controller concerns into the model.

Controller and Model leaking into View

Many times Beans would leak into JSP’s and cause JSP’s to look like controllers. Scripts with if and while loops are a prime example of this. To turn scripting off in JSP’s you may implement the following.

Using EL instead of scriptlets

The EL is intended to replace the use of Java scriptlets in developing JSP based web applications. It▒??s possible to disable the evaluation of scriptlets through configuration parameters. This allows a developer to make sure no one uses scriptlets. This allows best practices to be enforced at an application level.

<jsp-config>
    <jsp-property-group>
        <url-pattern>*.jsp</url-pattern>
        <scripting-invalid>true</scripting-invalid>
    </jsp-property-group>
</jsp-config>

If someone were to introduce scripting elements they would get an error like this.

/results.jsp(13,5) Scripting elements ( <%!, <jsp:declaration, <%=, <jsp:expression, <%, <jsp:scriptlet ) are disallowed here.

Using Maven to enforce MVC

You will see shortly that Maven allowing with the techniques above allow to help enforce MVC. Maven allows system developers break up parts of MVC into their own sub modules. Since each module have their own dependencies you can customize what each module sees.

For example you can stop controller leaking its concerns into the model by not specifying the controller as a dependency in the Model project. To prevent the controller and Model from leaking their concerns to the view the view module does not have a Java source directory! (that’ll fix it). To prevent logic from appearing in JSP’s you may turn off scriptlets in JSP in favor of using EL.

All the components of the Model view controller come together when the application is built by Maven.

All components go into what is called the Maven Reactor. The dependencies are resolved and the final artifacts are written to the target folder. Artifacts like EAR, WAR, Jar, Tar, Zip files are written ready to be deployed.

The Demonstration

The demonstration will consist of an application that retrieves a list of products and displays them on the homepage. Although an application like this could have been implemented with just a few lines code, the point here is to demonstrate Maven’s ability separate MVC concerns into discrete modules for medium to large applications.

Key points to demonstrate

  • Exhibit that the Model is unaware of the controller and view.
  • Ability for the Controller to reference the Model
  • Ability for the view to reference the Model and Controller but only for the purpose of gluing it all together to create a single WAR file.
  • There will be no Java source directory in the view and scriptlets will be disabled in JSP’s.

Setting up the Parent Module

The parent project consists of the following sub-modules.

  1. test-model ▒?? Model layer contains a bean that retrieves data from the persistence layer.
  2. test-view ▒?? contains JSP’s and HTML files
  3. test-controller ▒?? contains servlets that will call the model layer.

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart

groupId: testPackage

artifactId: test-parent

cd test-parent

edit the pom.xml file and change the package element to say “pom”.

<packaging>pom</packaging>

Setting up the Model

The model layer strictly contains the business logic. Model objects will also call persistence classes to store data. The model should be shielded from even the control logic because most control logic is implementation specific. For this reason the controller layer is not visible for this module.

To implement the model layer we will be using the Spring framework. We will write a simple bean that will call a Data Manager in the persistence layer that returns a list of Products.

In the test-parent directory

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart
groupId: testpackage
artifactId: test-model
cd test-model
Create src/main/resources folder for the applicationContext.xml file.

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
        "-//SPRING//DTD BEAN//EN"
        "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
        <bean id="testModel" class="testpackage.TestModelImpl">
                <property name="testDataManager" ref="testDataManager"/>
        </bean>

        <bean name="testDataManager" class="testpackage.TestDataManagerImpl"/>
</beans>

Product.java

package testpackage;

public class Product {
        private Integer id;
        private String name;

        public Product(int id, String name) {
                this.id = id;
                this.name = name;
        }

        public Integer getId() {
                return id;
        }
        public void setId(Integer id) {
                this.id = id;
        }
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }
}

TestDataManager.java

package testpackage;
import java.util.List;
public interface TestDataManager {
        public abstract List<Product> fetchProductList();
}

TestDataManagerImpl.java

package testpackage;
import java.util.ArrayList;
import java.util.List;
public class TestDataManagerImpl implements TestDataManager {
        public List<Product> fetchProductList() {
                List<Product> productList = new ArrayList<Product>();
                productList.add(new Product(1, "test 1"));
                productList.add(new Product(2, "test 2"));
                productList.add(new Product(3, "test 3"));
                return productList;
        }
}

TestModel.java

package testpackage;
import java.util.List;
public interface TestModel {
        public abstract List<Product> fetchProducts(String userId);
}

TestModelImpl.java

package testpackage;

import java.util.List;

public class TestModelImpl implements TestModel {
        private TestDataManager testDataManager;

        public TestDataManager getTestDataManager() {
                return testDataManager;
        }

        public void setTestDataManager(TestDataManager testDataManager) {
                this.testDataManager = testDataManager;
        }

        /* (non-Javadoc)
         * @see testpackage.TestModel#fetchProducts(java.lang.String)
         */
        public List<Product> fetchProducts(String userId) {
                // identify the access level based on user id
                // ...

                // call the dataManger to get the filtered list of
                // products.
                List<Product> productList = getTestDataManager().fetchProductList();

                return productList;
        }
}

Setting up the View

This module will be made up of JSP, HTML, XML. It will be void of all control logic. Control logic belongs in the controller module which we will define next. Since this is strictly view only module there is no place to put Java code.

In the test-parent folder type:
mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp
groupId: testPackage
artifactId: test-view
cd test-view

open pom.xml and change packaging to war.
It should look like this:

<?xml version="1.0"?>
<project
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
        xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <artifactId>test-parent</artifactId>
                <groupId>testpackage</groupId>
                <version>1.0-SNAPSHOT</version>
        </parent>
        <artifactId>test-view</artifactId>
        <packaging>war</packaging>
        <name>test-view Maven Webapp</name>
        <url>http://maven.apache.org</url>
        <build>
                <finalName>test-view</finalName>
                <plugins>

                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-compiler-plugin</artifactId>
                                <version>2.0.2</version>
                                <configuration>
                                        <source>1.5</source>
                                        <target>1.5</target>
                                </configuration>
                        </plugin>

                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-eclipse-plugin</artifactId>
                                <configuration>
                                        <downloadSources>true</downloadSources>
                                        <downloadJavadocs>true</downloadJavadocs>
                                        <wtpapplicationxml>true</wtpapplicationxml>
                                        <wtpversion>1.5</wtpversion>

                                        <classpathContainers>
                                                <classpathContainer>org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v6.0</classpathContainer>
                                                <classpathContainer>org.eclipse.jst.j2ee.internal.web.container</classpathContainer>
                                                <classpathContainer>org.eclipse.jst.j2ee.internal.module.container</classpathContainer>
                                        </classpathContainers>
                                        <additionalProjectFacets>
                                                <jst.web>2.5</jst.web>
                                        </additionalProjectFacets>
                                </configuration>
                        </plugin>
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-war-plugin</artifactId>
                        </plugin>

                        <plugin>
                                <groupId>org.mortbay.jetty</groupId>
                                <artifactId>jetty-maven-plugin</artifactId>
                                <version>7.0.0.v20091005</version>
                                <configuration>
                                        <scanIntervalSeconds>1</scanIntervalSeconds>
                                </configuration>
                        </plugin>
                </plugins>
        </build>
        <dependencies>
                <dependency>
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
                        <version>3.8.1</version>
                        <scope>test</scope>
                </dependency>
                <dependency>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-web</artifactId>
                        <version>2.5.6</version>
                </dependency>
                <dependency>
                        <groupId>testpackage</groupId>
                        <artifactId>test-controller</artifactId>
                        <version>${version}</version>
                </dependency>
                <dependency>
                        <groupId>testpackage</groupId>
                        <artifactId>test-model</artifactId>
                        <version>${version}</version>
                </dependency>
                <dependency>
                        <groupId>javax.servlet</groupId>
                        <artifactId>jstl</artifactId>
                        <version>1.1.2</version>
                </dependency>
                <dependency>
                        <groupId>taglibs</groupId>
                        <artifactId>standard</artifactId>
                        <version>1.1.2</version>
                </dependency>
        </dependencies>
</project>

The following is what is in web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">

  <display-name>Archetype Created Web Application</display-name>

        <context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:testpackage/applicationContext.xml</param-value>
        </context-param>

<!-- starts the spring framework for the model layer -->
        <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>

        <servlet>
                <servlet-name>testServlet</servlet-name>
                <servlet-class>testpackage.TestServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
                <servlet-name>testServlet</servlet-name>
                <url-pattern>*.do</url-pattern>
        </servlet-mapping>

        <welcome-file-list>
                <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
        <jsp-config>
            <jsp-property-group>
                <url-pattern>*.jsp</url-pattern>
                <scripting-invalid>true</scripting-invalid>
            </jsp-property-group>
        </jsp-config>
</web-app>

The following is the JSP that displays the results.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
 <head>
  <title>XHTML 1.0 Strict Template</title>
  <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
  <meta http-equiv="Content-Language" content="en-us" />
 </head>

 <body>
        <table border="1">
                <%--  <%="testing 123" %> Uncomment this to verify that scripts are disallowed --%>
                <h3>Products</h3>
                <c:forEach items="${productList}" var="product" varStatus="status">
                        <c:if test="${status.first}"><tr><th>Id</th><th>Name</th></tr></c:if>
                        <tr><td><c:out value="${product.id}"/></td><td><c:out value="${product.name}"/></td></tr>
                </c:forEach>
        </table>
</body>
</html>

Setting up the Controller

To keep things simple will define an application using standard servlets. Persistence layer won’t be visible from here

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart
groupId: testPackage
artifactId: test-controller
cd test-controller

web.xml

<?xml version="1.0"?>
<project
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
        xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <modelVersion>4.0.0</modelVersion>
        <parent>
                <artifactId>test-parent</artifactId>
                <groupId>testpackage</groupId>
                <version>1.0-SNAPSHOT</version>
        </parent>
        <artifactId>test-controller</artifactId>
        <name>test-controller</name>
        <url>http://maven.apache.org</url>
        <dependencies>
                <dependency>
                        <groupId>testpackage</groupId>
                        <artifactId>test-model</artifactId>
                        <version>1.0-SNAPSHOT</version>
                </dependency>
                <dependency>
                        <groupId>org.apache.geronimo.specs</groupId>
                        <artifactId>geronimo-servlet_2.5_spec</artifactId>
                        <version>1.2</version>
                        <type>jar</type>
                        <scope>compile</scope>
                </dependency>
                <dependency>
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
                        <version>3.8.1</version>
                        <scope>test</scope>
                </dependency>
                <dependency>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring</artifactId>
                        <version>2.5.6</version>
                </dependency>
                <dependency>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-web</artifactId>
                        <version>2.5.6</version>
                </dependency>
        </dependencies>
</project>

The following is the servlet.

package testpackage;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

public class TestServlet extends HttpServlet {
        private TestModel testModel;

        @Override
        public void init(ServletConfig config) throws ServletException {
                ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(config.getServletContext());
                testModel = (TestModel) context.getBean("testModel");
                super.init(config);
        }
        // Direct access to the data persistence layer is prevented
        // class is not visible
        // private TestDataManagerImpl testDataManager;

        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                        throws ServletException, IOException {
                System.out.println("servlet was called.");
                List<Product> productList = testModel.fetchProducts("test123");
                req.setAttribute("productList", productList);
                req.getRequestDispatcher("/results.jsp").forward(req, resp);
        }
}

Running the project

If you are using jetty to run the project then place the following into the test-view modules pom.xml

At this point you have 2 options to run the project. You can run it it Jetty. This is the easiest way but you need to do a mvn install on the parent each time you make a change to the code.

mvn install

cd test-view

mvn jetty:run

Or you can read the following page and setup the project to run in Tomcat 6 using Eclipse WTP.

Navigate to http://localhost:8080/ if using jetty and /test-view/a.do if you are using tomcat 6 in WTP.

Conclusion

The project we just ran demonstrates the ability to separate the various components of the MVC into modules. It was also demonstrated that these modules are moderately protected by leakage of concerns.

Taking it a step further

The Model object above contains the business logic and its all clumped together in one module (jar). There is nothing really stopping anyone from creating multiple modules each representing a different concept. For example if you are creating a portal project for a sky diving company. You can write one module to handle the weather forecasting section, another one to handle scheduling and the other to handle life insurance calculations. In this scenario each model component is protected from one model leaking its concerns to the other.

This site is a collaborative effort! The complete text and sourcecode for this is available on GitHub. Corrections and enhancements are welcome, please make the change and submit a pull request in the comment area below.
26
Nov
09

Spring and JSF Integrated

This page describes the process of integrating the Spring framework with JSF. We will take an application that already has JSF and Spring components fully initialized and ready to go.

On this page we will cover 2 aspects of Spring JSF integration.

  1. Getting a JSF managed Bean to deligate to a Spring Managed Bean.
  2. Use a pure Spring Managed Bean in place of the JSF bean.

Requirements

  • Maven2
  • Basic understanding of IOC and The Spring
  • Basic understanding of JSF

Before we can start we need to create the sample project. We are going to use a maven archetype.

Creating the Project

We will create this project using an archetype and walk thru the different parts that make this all work.

generate

mvn archetype:generate -DarchetypeGroupId=org.vtechfw -DarchetypeArtifactId=springmvc-jsf-archetype -DarchetypeVersion=1.0-SNAPSHOT -DarchetypeRepository=http://www.vermatech.com/m2repo

Ignore the warning about checksum file for now. (trying to figure out how to fix that. If you know then please comment)

Maven will prompt you for some information. It is best to answer like the following.

groupId: testpackage
artifactId: springJSF

Hit enter for defaults for the rest of the questions.

Run

cd to the project’s directory. (cd springJSF)

mvn jetty:run

View the project

Navigate to the following page: http://localhost:8080/

  1. The spring mvc configuration is read applicationContext.xml and spring-servlet.xml
  2. The faces configuration file is read faces-config.xml

The system completes the initialization and the web application is ready to serve requests at http://localhost:8080

The application displays a welcome page with 2 links. One points to the Faces JSP file that displays a text box that allows the user to enter values and submit. The second link displays a welcome page that is rendered by the SpringMVC framework.

1. Having JSF Managed Beans Delegate to Spring Managed Beans

You would typically want to do this if you already have jsf managed beans defined in the faces-config.xml file.

If you are starting fresh and purely want to use Spring beans as JSF managed beans then skip to section 2.

The DelegatingVariableResolver class provides the ability for Spring managed beans to be injected into JSF managed beans. This is a powerful technique to allow business logic that is managed in the spring container available for JSF applications to use.

How to get JSF to use Spring Beans

Enable the JSF system to use DelegatingVariableResolver.

Add the following in the faces-config.xml

<application>
   <variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
</application>

Create a Spring Managed Bean

Actually you dont need to create one if you already generated the project. For documentation purposes the bean is listed here.

package testpackage.quickstart.springmvc;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.stereotype.Service;

@Service("datePrintModel")
public class DatePrintModelImpl implements DatePrintModel {
        private DateFormat dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");

        public String getDateAsString() {
                System.out.println("getDataAsString called.");
                return dateFormat.format(new Date());
        }
}

Setup the JSF Managed Bean

Add the DatePrintModel and its setters and getters to the managed been below.

After the change it should look something like this.

package testpackage.jsftest;

import javax.faces.event.ValueChangeEvent;

import testpackage.quickstart.springmvc.DatePrintModel;

public class MessageModel {

        private DatePrintModel datePrintModel;

        public DatePrintModel getDatePrintModel() {
                return datePrintModel;
        }

        public void setDatePrintModel(DatePrintModel datePrintModel) {
                this.datePrintModel = datePrintModel;
        }

        public void printMessage(ValueChangeEvent e) {
                System.out.println("old value was: " + e.getOldValue());
                System.out.println("new value is: " + e.getNewValue());
        }

        public void callSpringModel() {
                System.out.println("calling the spring model...");
                datePrintModel.getDateAsString();
        }
}

Modify the faces-config.xml to look like this…

<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
              version="1.2">

<managed-bean>
        <managed-bean-name>message</managed-bean-name>
        <managed-bean-class>java.lang.String</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
        <managed-bean-name>messageModel</managed-bean-name>
        <managed-bean-class>testpackage.jsftest.MessageModel</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
        <managed-property>
                <property-name>datePrintModel</property-name>
                <value>#{datePrintModel}</value>
        </managed-property>
</managed-bean>
</faces-config>

As you can see above the managed-bean property has been added.

Modify the JSP

helloWorld.jsp

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>

<f:view>
    <html>
    <head>
        <title>Hello World JSF Example</title>
    </head>
    <body>
    <h:form>
                <p>This is a simple hello world page using Faces.</p>
                <p>Enter your message here: <br/>
                <h:inputText valueChangeListener="#{messageModel.printMessage}" value="#{message}" size="35"/></p>
                <h:commandButton value="Submit" action="#{messageModel.callSpringModel}"/>
    </h:form>
    <p>after submit check server console for output.</p>
    </body>
    </html>
</f:view>

Run and view The Project

mvn jetty:run

http://localhost:8080

2. Use a pure Spring Managed Bean in place of the JSF bean.

Getting JSF to Purely use Spring Bean

As you have seen above you can take an existing managed bean and inject spring managed beans. This next section will show you how to use a spring managed bean as a JSF backing bean.

Doing it this way simplifies the faces-config.xml.

Create the following file in
src/java/main/com/test/quickstart/springmvc/SpringManagedBean.java

package com.test.quickstart.springmvc;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

@Controller("springManagedBean")
@Scope("session")
public class SpringManagedBean {
        private String message;
        public String getMessage() {
                return message;
        }
        public void setMessage(String message) {
                this.message = message;
        }
        public void testMethod() {
                System.out.println("test method ran with message: " + message);
        }
}

Insert the following into your spring configuration…

<context:component-scan base-package="com.test.quickstart.springmvc"/>

Create the following jsp:

src/main/webapp/springManagedBean.jsp

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>

<f:view>
    <html>
    <head>
        <title>Spring Managed Bean Example</title>
    </head>
    <body>
    <h:form>
                <p>This is a simple hello world page using Faces and Spring Managed Bean.</p>
                <p>Enter your message here: <br/>
                <h:inputText value="#{springManagedBean.message}" size="35"/></p>
                <h:commandButton value="Submit" action="#{springManagedBean.testMethod}"/>
    </h:form>
    <p>after submit check server console for output.</p>
    </body>
    </html>
</f:view>

Run and view The Project

mvn jetty:run

Navigate to:
http://localhost:8080/springManagedBean.faces

This site is a collaborative effort! The complete text and sourcecode for this is available on GitHub. Corrections and enhancements are welcome, please make the change and submit a pull request in the comment area below.
25
Nov
09

Creating a JSF application in 10 minutes

This page describes the process of setting up a JSF project on Eclipse using Maven. We will create a sample project and verify that each of the wizards and JSF views provided by eclipse are in working order. This page also contains a sample application you may copy and paste right into your project. You may run this with the built in jetty plug-in or since this is a Eclipse WTP project you may also run it with Apache Tomcat or on the IBM Websphere Test Environment.

Requirements

  • Maven 2
  • Java 5
  • Servlet Spec 2.5
  • Covers JSF 1.2

Generate the web application

First we start with a maven archetype

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp

For the group id enter: test

For the artifactId enter: jsfTestWeb

cd to the project▒??s folder
Next we create the src/main/java folder since this is not done for us using the archetype.

on unix you type: mkdir /src/main/java

modify the pom.xml file. It should look like this…

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>test</groupId>
        <artifactId>jsfTestWeb</artifactId>
        <packaging>war</packaging>
        <version>1.0-SNAPSHOT</version>
        <name>jsfTestWeb Maven Webapp</name>
        <url>http://maven.apache.org</url>
        <dependencies>
                <dependency>
                        <groupId>junit</groupId>
                        <artifactId>junit</artifactId>
                        <version>3.8.1</version>
                        <scope>test</scope>
                </dependency>
                <dependency>
                        <groupId>org.apache.myfaces.core</groupId>
                        <artifactId>myfaces-api</artifactId>
                        <version>1.2.2</version>
                </dependency>
                <dependency>
                        <groupId>org.apache.myfaces.tomahawk</groupId>
                        <artifactId>tomahawk</artifactId>
                        <version>1.1.9</version>
                </dependency>
                <dependency>
                        <groupId>org.apache.myfaces.core</groupId>
                        <artifactId>myfaces-impl</artifactId>
                        <version>1.2.2</version>
                </dependency>
                <dependency>
                        <groupId>javax.servlet</groupId>
                        <artifactId>jstl</artifactId>
                        <version>1.1.2</version>
                </dependency>
                <dependency>
                        <groupId>taglibs</groupId>
                        <artifactId>standard</artifactId>
                        <version>1.1.2</version>
                </dependency>
                <dependency>
                        <groupId>org.apache.geronimo.specs</groupId>
                        <artifactId>geronimo-servlet_2.5_spec</artifactId>
                        <version>1.2</version>
                        <scope>provided</scope>
                </dependency>
        </dependencies>
        <build>
                <finalName>jsfTestWeb</finalName>
                <plugins>
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-compiler-plugin</artifactId>
                                <version>2.0.2</version>
                                <configuration>
                                        <source>1.5</source>
                                        <target>1.5</target>
                                </configuration>
                        </plugin>
                        <plugin>
                                <groupId>org.mortbay.jetty</groupId>
                                <artifactId>jetty-maven-plugin</artifactId>
                                <version>7.0.0.v20091005</version>
                                <configuration>
                                        <scanIntervalSeconds>2</scanIntervalSeconds>
                                </configuration>
                        </plugin>
                        <plugin>
                                <groupId>org.apache.maven.plugins</groupId>
                                <artifactId>maven-eclipse-plugin</artifactId>
                                <configuration>
                                        <wtpapplicationxml>true</wtpapplicationxml>
                                        <wtpversion>1.5</wtpversion>
                                        <downloadSources>true</downloadSources>
                                        <downloadJavadocs>true</downloadJavadocs>
                                        <classpathContainers>
                                                <classpathContainer>org.eclipse.jst.j2ee.internal.web.container</classpathContainer>
                                                <classpathContainer>org.eclipse.jst.j2ee.internal.module.container</classpathContainer>
                                        </classpathContainers>
                                        <additionalProjectFacets>
                                                <jst.web>2.5</jst.web>
                                                <jst.jsf>1.2</jst.jsf>
                                        </additionalProjectFacets>
                                </configuration>
                        </plugin>
                </plugins>
        </build>
</project>

mvn eclipse:clean eclipse:eclipse

Import the Existing project (generated project) into eclipse.

Modify the src/main/webapp/WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        id="WebApp_ID" version="2.5">
  <display-name>Archetype Created Web Application</display-name>

  <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 Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>

  <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>

</web-app>

Create a src/main/webapp/WEB-INF/faces-config.xml

<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
              version="1.2">

<managed-bean>
        <managed-bean-name>message</managed-bean-name>
        <managed-bean-class>java.lang.String</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
        <managed-bean-name>messageModel</managed-bean-name>
        <managed-bean-class>test.MessageModel</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>

Create / Modify
src/main/webapp/index.jsp

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<body>
<h2>JSF Test Application</h2>
<p><a href="<c:url value='helloWorld.jsf'/>">JSF Test Page</a></p>
</body>
</html>

Create a jsp src/main/webapp/helloWorld.jsp

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>

<f:view>
    <html>
    <head>
        <title>Hello World JSF Example</title>
    </head>
    <body>
    <h:form>
                <p>This is a simple hello world page using Faces.</p>
                <p>Enter your message here: <br/>
                <h:inputText valueChangeListener="#{messageModel.printMessage}" value="#{message}" size="35"/></p>
                <h:commandButton value="Submit" action="submit"/>
    </h:form>
    </body>
    </html>
</f:view>

Create a managed Bean

src/main/java/test/MessageModel.java

Create the test directory below if it does not exist.
src/main/java/test/MessageModel.java

package test;

import javax.faces.event.ValueChangeEvent;

public class MessageModel {
        public void printMessage(ValueChangeEvent e) {
                System.out.println("old value was: " + e.getOldValue());
                System.out.println("new value is: " + e.getNewValue());
        }
}

Run the JSF application

Save all files and run the application in jetty.

mvn jetty:run

The application should come up when you point your browser to http://localhost:8080

Type in some text and you should see some output on the console window.

Right click on the page and click view source. You will notice JSF generated code.

Faces Configuration Editor

At this time you can close the faces-config.xml and open it again. This time around it should open using the Faces Configuration Editor. Take some time to get acquainted with the features of this editor.

JSF JSP Editor

Enable the Palette View by going to Windows -> show View -> Search for palette.

Create a new JSP and you should be able to drag and drop JSF components from the palette onto the page.

At this time you have an application that is ready for development. If you choose to proceed you will find a sample application you can integrate into the project you created above.

That’s all for Now!

This site is a collaborative effort! The complete text and sourcecode for this is available on GitHub. Corrections and enhancements are welcome, please make the change and submit a pull request in the comment area below.
23
Nov
09

Hello Enterprise Application

This page will show you how to create an Jave Enterprise application using Maven’s multi-module and archetype capabilities.

Requirements

  • Maven
  • Eclipse IDE
  • Java 5 or above
  • Access to the Command Prompt

Hello Enterprise

In the example we will name the application HelloEnterprise. This will be the parent project. The project will have 3 sub-projects listed below.

  1. HelloModel – contains the business logic
  2. HelloWeb – contains the Web application flow control logic
  3. HelloEar – small sub-project used simply to create the ear

Create the Parent Project

The first step we will do is to create the parent project. This project will contain the others. Name the project something that is generic to the problem at hand.

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart

Define value for groupId: : test
Define value for artifactId: : hello-enterprise
Define value for version:  1.0-SNAPSHOT: :
Define value for package:  test: :
Confirm properties configuration:
groupId: test
artifactId: hello-enterprise
version: 1.0-SNAPSHOT
package: test
 Y: :

cd hello-enterprise
Edit the pom.xml and change the packaging to say pom instead of jar.

Create the Model project

For this step we will create a very simple model project that simply contains a single Model class. Though this is a very simple project it does show you how you can combine sub-modules into one ear file in the end.

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart

This time answer the artifact id should be “hello-enterprise-model”.

Go ahead and create the model class

cd hello-enterprise-model

mvn eclipse:eclipse

Import the project into eclipse and create the following class and interface

Bean

package test;

import java.math.BigDecimal;

public class Product {
        private Integer id;
        private String name;
        private BigDecimal price;

        public Product(Integer id, String name, BigDecimal price) {
                this.id = id;
                this.name = name;
                this.price = price;
        }

        public Integer getId() {
                return id;
        }
        public void setId(Integer id) {
                this.id = id;
        }
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }
        public BigDecimal getPrice() {
                return price;
        }
        public void setPrice(BigDecimal price) {
                this.price = price;
        }
}

Interface

package test;

import java.util.List;

public interface ProductDataManager {

        public abstract List<Product> getAllProducts();

}

Class

package test;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class ProductDataManagerImpl implements ProductDataManager {
        /* (non-Javadoc)
         * @see test.ProductDataManager#getAllProducts()
         */
        public List<Product> getAllProducts() {
                List<Product> list = new ArrayList<Product>();

                list.add(createProduct(1, "test1", BigDecimal.valueOf(12)));
                list.add(createProduct(2, "test2", BigDecimal.valueOf(13)));
                list.add(createProduct(3, "test3", BigDecimal.valueOf(14)));

                return list;
        }
        private Product createProduct(Integer id, String name, BigDecimal price) {
                Product product = new Product(id, name, price);
                return product;
        }
}

cd ..

Create the web project

To create the web project we will use an existing archetype that was created my me. It is an archetype of a very simple spring MVC application that prints some static text on the screen.

mvn archetype:generate -DarchetypeGroupId=com.vermatech \
-DarchetypeArtifactId=springmvc-archetype -DarchetypeVersion=1.0-SNAPSHOT \
-DarchetypeRepository=http://www.vermatech.com/m2repo

Answer the questions like this:

Define value for groupId: : test
Define value for artifactId: : hello-enterprise-web
Define value for version:  1.0-SNAPSHOT: :
Define value for package:  test: :
Confirm properties configuration:
groupId: test
artifactId: hello-enterprise-web
version: 1.0-SNAPSHOT
package: test
 Y: :

You may test the project you just created from an archetype by typing mvn jetty:run from the hello-enterprise-web folder. Point your browser to: http://localhost:8080/ and verify everything is ok.

When you are done return to the command prompt and cd to the hello-enterprise directory again.

Create the Ear Project

Finally we will create an EAR project that will allow us to create an EAR file.

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart

Edit pom.xml and make sure it looks like the following.

hello-enterprise/hello-enterprise-ear/pom.xml

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <artifactId>hello-enterprise</artifactId>
    <groupId>test</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <groupId>test</groupId>
  <artifactId>hello-enterprise-ear</artifactId>
  <packaging>ear</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>hello-enterprise-ear</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>test</groupId>
      <artifactId>hello-enterprise-model</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    <dependency>
      <groupId>test</groupId>
      <artifactId>hello-enterprise-web</artifactId>
      <version>1.0-SNAPSHOT</version>
      <type>war</type>
    </dependency>

  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-ear-plugin</artifactId>
        <version>2.3.2</version>
        <!-- configuring the ear plugin -->
        <configuration>
          <modules>
            <webModule>
              <groupId>test</groupId>
              <artifactId>hello-enterprise-web</artifactId>
            </webModule>
          </modules>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Save and exit. Return to the hello-enterprise (parent) directory and run the following command:

Start the build process

mvn package

You will see a bunch of stuff happen and at the end you will see the following results.

[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] ------------------------------------------------------------------------
[INFO] hello-enterprise ...................................... SUCCESS [1.194s]
[INFO] hello-enterprise-model ................................ SUCCESS [0.938s]
[INFO] springmvc-quickstart Maven Webapp ..................... SUCCESS [1.078s]
[INFO] hello-enterprise-ear .................................. SUCCESS [0.647s]
[INFO] ------------------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------

At this time you can open the ear project’s target folder and you will see the newly created ear.

Deploy The Ear file

Deploy the Ear to your Application server and do an application checkout.

That’s All

[INFO] ————————————————————————
[INFO] Reactor Summary:
[INFO] ————————————————————————
[INFO] hello-enterprise ……………………………….. SUCCESS [1.194s]
[INFO] hello-enterprise-model ………………………….. SUCCESS [0.938s]
[INFO] springmvc-quickstart Maven Webapp ………………… SUCCESS [1.078s]
[INFO] hello-enterprise-ear ……………………………. SUCCESS [0.647s]
[INFO] ————————————————————————
[INFO] ————————————————————————
[INFO] BUILD SUCCESSFUL
[INFO] ————————————————————————

This site is a collaborative effort! The complete text and sourcecode for this is available on GitHub. Corrections and enhancements are welcome, please make the change and submit a pull request in the comment area below.
09
Nov
09

Spring Web Flow 2 Hello World

Wizards are sequence of pages that allow the user to progress thru a work flow. Each step of the way the user provides additional information. This information can be used to walk the user thru steps (possibly skiping steps along the way if necessary). This page describes the process of setting up a simple 4 step wizard application.

The steps of the wizard we will be coding are as follows.

  • Step 1 – Personal Info
  • Step 2 – Custom Message
  • Step 3 – Shipping Info
  • Step 4 – Confirmation

User will be allowed to navigate forward and backward between the first 3 steps. The confirmation page will show the results of the operation and allow the user to return to the main index.jsp page for the application or return to start a new workflow on step 1.

Lets get Started

Create a web application project following these instructions.

Open the pom.xml file and add the following dependencies

                <!-- Spring WEb Flow specific -->
                <dependency>
                        <groupId>org.springframework.webflow</groupId>
                        <artifactId>spring-binding</artifactId>
                        <version>2.0.8.RELEASE</version>
                </dependency>
                <dependency>
                        <groupId>org.springframework.webflow</groupId>
                        <artifactId>spring-js</artifactId>
                        <version>2.0.8.RELEASE</version>
                </dependency>
                <dependency>
                        <groupId>org.springframework.webflow</groupId>
                        <artifactId>spring-webflow</artifactId>
                        <version>2.0.8.RELEASE</version>
                </dependency>
                <dependency>
                        <groupId>ognl</groupId>
                        <artifactId>ognl</artifactId>
                        <version>2.7.3</version>
                        <type>jar</type>
                        <scope>compile</scope>
                </dependency>
                <dependency>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring</artifactId>
                        <version>2.5.6</version>
                </dependency>
                <dependency>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-webmvc</artifactId>
                        <version>2.5.6</version>
                </dependency>
                <!-- These are to enable JSTL in jsp's -->
                <dependency>
                        <groupId>javax.servlet</groupId>
                        <artifactId>jstl</artifactId>
                        <version>1.1.2</version>
                </dependency>
                <dependency>
                        <groupId>taglibs</groupId>
                        <artifactId>standard</artifactId>
                        <version>1.1.2</version>
                </dependency>

regenerate the eclipse project: mvn eclipse:clean eclipse:eclipse

Refresh the eclipse project.

Modify the WEB-INF/web.xml file. It should look similar to this one.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
        id="WebApp_ID" version="2.5">

        <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>

        <servlet>
                <servlet-name>spring</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
        </servlet>

        <servlet-mapping>
                <servlet-name>spring</servlet-name>
                <url-pattern>/app/*</url-pattern>
        </servlet-mapping>

        <welcome-file-list>
                <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
</web-app>

WEB-INF/spring-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
        "-//SPRING//DTD BEAN//EN"
        "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
        <!-- Define the default handler adapter in Spring MVC -->
        <!-- Enables plain Controllers -->
        <bean
                class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />

        <!--
                Its important to declare this since spring MVC will not look for it if
                you have already defined the FlowHandlerMapping
        -->
        <bean
                class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
                <property name="order" value="0" />
        </bean>

        <bean name="/helloWorld" class="test.HelloWorldController"/>

        <bean id="viewResolver"
                class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/WEB-INF/jsp/" />
                <property name="suffix" value=".jsp" />
        </bean>

        <!-- We import the flow-config.xml located in the same directory -->
        <import resource="flow-config.xml"/>
        <!-- Importing allows us to keep this configuration file simple. -->

</beans>

WEB-INF/flow-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:webflow="http://www.springframework.org/schema/webflow-config"
        xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/webflow-config
           http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">

        <!--
                The following 2 entries are common no matter what framework you use.
                (spring mvc, struts etc...)
        -->
        <webflow:flow-registry id="flowRegistry" base-path="/WEB-INF">
                <webflow:flow-location path="/flows/letterPrinting/printLetter.xml" />
        </webflow:flow-registry>

        <!-- FlowExecutor is the central service for executing flows: -->
        <webflow:flow-executor id="flowExecutor"
                flow-registry="flowRegistry" />

        <!-- Enables FlowHandler URL mapping -->
        <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerAdapter">
                <property name="flowExecutor" ref="flowExecutor" />
        </bean>

        <!--
                Maps request paths to flows in the flowRegistry; e.g. a path of
                /hotels/booking looks for a flow with id "hotels/booking"
        -->
        <bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
                <property name="flowRegistry" ref="flowRegistry" />
                <property name="order" value="1" />
        </bean>

</beans>

Create a WEB-INF/applicationContext.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
        "-//SPRING//DTD BEAN//EN"
        "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<!-- Blank for now, but who knows, maybe we will have some business logic beans here. -->
</beans>

Create a folder under WEB-INF called flows/letterPrinting. This folder will contain the steps of our wizard.
Add the following files there.
WEB-INF/flows/letterPrinting/printLetter.xml

<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/webflow
                          http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

        <view-state id="enterPersonalDetails">
                <transition on="next" to="enterCustomMessage"/>
        </view-state>

        <view-state id="enterCustomMessage">
                <transition on="next" to="enterShippingAddress"/>
                <transition on="prev" to="enterPersonalDetails"/>
                <transition on="startOver" to="enterPersonalDetails"/>
        </view-state>

        <view-state id="enterShippingAddress">
                <transition on="next" to="confirm"/>
                <transition on="prev" to="enterCustomMessage"/>
                <transition on="startOver" to="enterPersonalDetails"/>
        </view-state>

        <end-state id="confirm" view="confirmPage.jsp" />
</flow>

The above file is the xml file that describes the steps of this flow. It describes all the steps in the wizard and the associated events. On each event it describes what the next state will be. In these examples we use a submit button to generate events. But these events could have been generated by html links or hidden form fields.

WEB-INF/flows/letterPrinting/enterPersonalDetails.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
 <head>
  <title>Enter Personal Details</title>
  <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
  <meta http-equiv="Content-Language" content="en-us" />
 </head>

<body>
<h2>Step 1</h2>
<h3>Enter Personal Details</h3>
<form action="" method="post">
<input type="text"/><br/>
<input type="submit" name="_eventId_next" value="next"/>

</form>
</body>
</html>

WEB-INF/flows/letterPrinting/enterCustomMessage.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
 <head>
  <title>Enter Custom Message</title>
  <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
  <meta http-equiv="Content-Language" content="en-us" />
 </head>

<body>
<h2>Step 2</h2>
<h3>Enter Custom Message</h3>
<form action="" method="post">
<input type="text"/><br/>
<input type="submit" name="_eventId_next" value="next"/><br/>
<input type="submit" name="_eventId_prev" value="prev"/> Try clicking this to go back<br/>
<input type="submit" name="_eventId_startOver" value="startOver"/><br/>

<p>Hint: Also try clicking the browser back button... Web flows don't allow you to suffer with those annoying messages that ask you to "Repost"</p>

</form>
</body>
</html>

WEB-INF/flows/letterPrinting/enterShippingAddress.jsp

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
 <head>
  <title></title>
  <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
  <meta http-equiv="Content-Language" content="en-us" />
 </head>

<body>
<h2>Step 3</h2>
<h3>Enter Shipping Address</h3>
<form action="" method="post">
<input type="text"/><br/>
<input type="submit" name="_eventId_next" value="next"/>
<input type="submit" name="_eventId_prev" value="prev"/><br/>
<input type="submit" name="_eventId_startOver" value="startOver"/><br/>

</form>
</body>
</html>

WEB-INF/flows/letterPrinting/confirmPage.jsp

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

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
 <head>
  <title></title>
  <meta http-equiv="Content-type" content="text/html; charset=iso-8859-1" />
  <meta http-equiv="Content-Language" content="en-us" />
 </head>

<body>
<h3>Print Confirmation</h3>

<p>This is the last page of the Wizard.</p>
<a href="<c:url value='/app/flows/letterPrinting'/>">Start new Wizard Flow</a>

<p>This is the end state of this flow. Notice when you click the above link or click the back button it will
it will start a new flow regardless.... </p>

<p>No matter what you do you can not mess up what was submitted in step 3.</p>
</body>
</html>

Save all the files and start up your servlet container. Navigate to http://localhost:8080/ if you are using jetty. The page should come up and ask you to start. If you are using tomcat be sure to include the context root of where you installed the application.

After the app comes up navigate the wizard by clicking next and prev.

That’s all for now!

This site is a collaborative effort! The complete text and sourcecode for this is available on GitHub. Corrections and enhancements are welcome, please make the change and submit a pull request in the comment area below.
01
Nov
09

Using JAXB to convert between XML and POJO’s

Introduction

There are many products out there that allow for conversions of XML to java and Back. One of the popular tools I have used in the past is Betwixt from the Apache commons project. Other tools out there include XStream. The following page describes how to use JAXB to convert xml to java and Java to XML. If you have used web services you know what I am talking about.

With the introduction of the Java 5 Annotations and the new JAX-WS standard I thought it would be a good idea to learn more about JAXB. Betwixt was great for small projects but some heavy weight stuff like web services I would use something like the following.

Example 1: Marshalling a simple Customer POJO

In this example we will marshal a customer pojo object from java to XML and un-marshal it from xml back to Java.

Start by creating a Customer.java class in the customer package.

package customerpackage;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * Represents a customerpackage
 */
@XmlRootElement
public class Customer {
        private Integer id;
        private String firstName;
        private String lastName;
        private String SSN;

        public Integer getId() {
                return id;
        }
        public void setId(Integer id) {
                this.id = id;
        }
        @XmlElement(nillable=true)
        public String getFirstName() {
                return firstName;
        }

        public void setFirstName(String firstName) {
                this.firstName = firstName;
        }
        @XmlElement(nillable=true)
        public String getLastName() {
                return lastName;
        }
        public void setLastName(String lastName) {
                this.lastName = lastName;
        }
        @XmlElement(name="socialSecurityNumber")
        public String getSSN() {
                return SSN;
        }
        public void setSSN(String sSN) {
                SSN = sSN;
        }
        public String toString() {
                StringBuffer sb = new StringBuffer();
                sb.append("FirstName: " + this.firstName);
                sb.append("\nLastName: " + this.lastName);
                sb.append("\nSSN: " + this.SSN);
                return sb.toString();

        }
}

In order for the JAXB to work you need to have an ObjectFactory.java class in the customer package;

package customerpackage;

import javax.xml.bind.annotation.XmlRegistry;

@XmlRegistry
public class ObjectFactory {

        public ObjectFactory() {
        }

        public Customer createCustomer() {
                return new Customer();
        }
}

Create a simple java main application to test.

package customerpackage;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

/**
 * Simple java main class that runs our example
 *
 */
public class JAXApp {

        public static void main(String args[]) throws Exception {
                objectToXML();

                //xmlToObject();
        }

        /**
         * Marshall information into an xml file.
         */
        private static void objectToXML() throws Exception {
                JAXBContext jc = JAXBContext.newInstance( "customerpackage" );
                Customer cust = new Customer();
                cust.setId(1);
                cust.setFirstName("Neeraj");
                cust.setLastName("Verma");
                cust.setSSN("123-45-6789");
                Marshaller m = jc.createMarshaller();
                m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
                m.marshal( cust, System.out );

        }

        private static void xmlToObject() throws Exception {
                JAXBContext jc = JAXBContext.newInstance( "customerpackage" );
                Unmarshaller u = jc.createUnmarshaller();
                Customer customer = (Customer)u.unmarshal( ClassLoader.getSystemResourceAsStream("customer.xml") );
                System.out.println(customer);
        }

}

Result

Running the above application should print something like this to the console.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer>
    <firstName>Neeraj</firstName>
    <id>1</id>
    <lastName>Verma</lastName>
    <socialSecurityNumber>123-45-6789</socialSecurityNumber>
</customer>

Example 2: Marshalling a POJO containing a list of Other Objects

In this example we will marshal a Manager object that contains a list of Employee’s.

Create a package named workpackage and put the following classes in it:

Manager.java

package workpackage;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Manager {
        private Integer managerId;
        private String firstName;
        private String lastName;
        private List<Employee> employees = new ArrayList<Employee>();

        public Integer getManagerId() {
                return managerId;
        }
        public void setManagerId(Integer managerId) {
                this.managerId = managerId;
        }
        public String getFirstName() {
                return firstName;
        }
        public void setFirstName(String firstName) {
                this.firstName = firstName;
        }
        public String getLastName() {
                return lastName;
        }
        public void setLastName(String lastName) {
                this.lastName = lastName;
        }
        public List<Employee> getEmployees() {
                return employees;
        }
        public void setEmployees(List<Employee> employees) {
                this.employees = employees;
        }

        public String toString() {
                StringBuffer buffer = new StringBuffer();
                buffer.append("Manager Name: " + firstName + "\n");
                buffer.append("employees: \n");
                buffer.append(employees);
                return buffer.toString();
        }
}

Employee.java

package workpackage;

public class Employee {
        private Integer id;
        private String firstName;

        public Employee() {
        }

        public Employee(Integer id, String firstName, String lastName) {
                this.id = id;
                this.firstName = firstName;
                this.lastName = lastName;
        }

        public Integer getId() {
                return id;
        }
        public void setId(Integer id) {
                this.id = id;
        }
        public String getFirstName() {
                return firstName;
        }
        public void setFirstName(String firstName) {
                this.firstName = firstName;
        }
        public String getLastName() {
                return lastName;
        }
        public void setLastName(String lastName) {
                this.lastName = lastName;
        }
        private String lastName;

        public String toString() {
                return "id: "+ id + " Name: " + firstName + " " + lastName;
        }
}

The following is the main application that is used to test. Be sure to enable the correct line in the main method.

ManagerApp.java

package workpackage;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class ManagerApp {
        public static void main(String args[]) throws Exception {
                // enable the next line to print xml to the console
                //objectToXML();

                // copy the output to the console to manager.xml

                // enable the following line to read from manager.xml in the root of the project.
                xmlToObject();
        }

        /**
         * Marshall information into an xml file.
         */
        private static void objectToXML() throws Exception {
                JAXBContext jc = JAXBContext.newInstance( "workpackage" );
                Manager manager = new Manager();
                manager.setManagerId(1);
                manager.setFirstName("Neeraj");
                manager.setLastName("Verma");
                manager.getEmployees().add(new Employee(1, "John", "Doe"));
                manager.getEmployees().add(new Employee(2, "Jane", "Doe"));

                Marshaller m = jc.createMarshaller();
                m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
                m.marshal( manager, System.out );

        }

        private static void xmlToObject() throws Exception {
                JAXBContext jc = JAXBContext.newInstance( "workpackage" );
                Unmarshaller u = jc.createUnmarshaller();
                Manager manager = (Manager)u.unmarshal( ClassLoader.getSystemResourceAsStream("manager.xml") );
                System.out.println(manager);
        }

}

should print something like this on the console:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<manager>
    <employees>
        <firstName>John</firstName>
        <id>1</id>
        <lastName>Doe</lastName>
    </employees>
    <employees>
        <firstName>Jane</firstName>
        <id>2</id>
        <lastName>Doe</lastName>
    </employees>
    <firstName>Neeraj</firstName>
    <lastName>Verma</lastName>
    <managerId>1</managerId>
</manager>

The second method should print something like this to the console:

Manager Name: Neeraj
employees:
[id: 1 Name: John Doe, id: 2 Name: Jane Doe]

Excluding fields from the xml

If you don’t want some fields from your bean to show just use the following annotation.

        @XmlTransient
        public String getDontWantThis() {
                return dontWantThis;
        }

The above will exclude a field from the output.

Thats all for now!

This site is a collaborative effort! The complete text and sourcecode for this is available on GitHub. Corrections and enhancements are welcome, please make the change and submit a pull request in the comment area below.



Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 77 other followers

November 2017
S M T W T F S
« Oct    
 1234
567891011
12131415161718
19202122232425
2627282930  

Blog Stats

  • 842,358 hits