Posts Tagged ‘maven



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!

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] ————————————————————————

22
Nov
09

Spring MVC application using Archetypes

The following page describes the process of creating a simple spring MVC application using an archetype. The archetype was created my me for testing purposes. All it does is print a simple message to the browser when you navigate to the application.

Requirements

Maven

Access to the command prompt

The Maven page above talks about eclipse you don’t need eclipse to install and run the simple springMVC application described here.

Creating the Project

Execute the following archetype to create the spring MVC application

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

Answer some simple questions:

Define value for groupId: : com.test2
Define value for artifactId: : vtSpringTest
Define value for version:  1.0-SNAPSHOT: :
Define value for package:  com.test2: :
Confirm properties configuration:
groupId: com.test2
artifactId: vtSpringTest
version: 1.0-SNAPSHOT
package: com.test2
 Y: :

Running the Application in Jetty

Execute the following in the project’s folder.

mvn jetty:run

Navigate to the following url http://localhost:8080/ and you should see a Welcome page come up.

Advanced Jetty Settings

The following allows jetty to serve from a different context root. It also allows the application to be reloaded 2 seconds after a change is detected to the classes or the web.xml file.

	<plugin>
		<groupId>org.mortbay.jetty</groupId>
		<artifactId>jetty-maven-plugin</artifactId>
				<version>7.0.0.v20091005</version>
		<configuration>
			<scanIntervalSeconds>2</scanIntervalSeconds>
			<webAppConfig>
				<contextPath>/biggerstrongerbetterfaster</contextPath>			
			</webAppConfig>
		</configuration>
	</plugin> 

Thats All!

15
Nov
09

Creating a new Maven Archetype and Publishing it to Nexus

This page will describe the process to create and upload a new archetype to the repository.

We will be creating an archetype of a basic spring MVC application that is pre-configured to make a test connection to a MySQL database. We will run this application using the built in servlet engine in Maven called jetty.

Before starting please review the following article to learn how to publish artifacts to remote repositories.

Requirements

Create a Archetype Template

We start by creating an archetype from well…. an archetype…

Execute the following command

mvn archetype:create -DgroupId=test -DartifactId=test-archetype -DarchetypeArtifactId=maven-archetype-archetype

cd /test-archetype

Code Your Application

In this section we will take some time to code the project that we will install into this archetype. Since creating a Spring MVC application is beyond the scope of this page please navigate to the following page to see how this application was coded. We will move this application to this archetype so that it can be used as a starting point for new projects.

MySQL Test Connection using Spring MVC

Import files into the new archetype

At this time you can copy the files from the project you created using the above link into the src/main/resources/archetype-resources/

Before we can proceed we need to make some small changes to the project we just created and imported into this archetype.

These changes are necessary because when developers create project based on archetypes they are asked a few questions.

  • group id
  • artifact id
  • version

The group id is important typically its (com.yourcompanyname). Since developers can provide anything in this field you need to modify your template code to take this parameter and place your code into the right java packages.

Modify the project’s pom.xml

Before we can proceed we need to modify the template project’s pom.xml file. Replace the groupId artifactId and version tag’s with the following

  <groupId>${groupId}</groupId>
  <artifactId>${artifactId}</artifactId>
  <version>${version}</version>

The above step is necessary since the developers that are using your archetype to create their own project can use any group artifact and version. When the project generates maven needs to create a pom.xml file for the project with the values that were specified by the developer.

Modify the archetype descriptor

The archetype descriptor contains a list of files that are part of the archetype we are creating. It is located in the following directory.

test-archetype/src/main/resources/META-INF/maven/archetype.xml

<archetype>
  <id>test-archetype</id>
  <sources>
    <source>src/main/java/test/DBParam.java</source>
    <source>src/main/java/test/HelloWorldController.java</source>
    <source>src/main/java/test/TestDBConnectionController.java</source>
  </sources>
  <resources>
    <resource>src/main/webapp/WEB-INF/jsp/dbParameters.jsp</resource>
    <resource>src/main/webapp/WEB-INF/jsp/helloWorld.jsp</resource>
    <resource>src/main/webapp/WEB-INF/jsp/success.jsp</resource>
    <resource>src/main/webapp/WEB-INF/spring-servlet.xml</resource>
    <resource>src/main/webapp/WEB-INF/web.xml</resource>
    <resource>src/main/webapp/index.jsp</resource>
  </resources>
</archetype>

Modify the source files

During the creation of a project maven asks the user for the groupId. Maven uses this to place the source files into packages that represent the user’s groupId. For this reason we need to modify each of the source packages and change them to look like this…

package ${package}.test;

So go ahead and modify the three java source files and spring-servlet.xml. replace the package statement with what you see above.

  • src/main/java/test/DBParam.java
  • src/main/java/test/HelloWorldController.java
  • src/main/java/test/TestDBConnectionController.java
  • src/main/webapp/WEB-INF/spring-servlet.xml

Relocate Source If Necessary

Also you may need to relocate the .java files so they represent the package statement. This means if you replaced the following with a ${package} statement then everything under that must be moved to the highlevel folder.

com.mycompany.mygroup.program -> ${package}.program

In the above example the program package and everything under it needs to be moved to the top level (/src/main/java) folder.

The xml file needs to be modified because we need to tell spring to scan a different package for controller beans.

	<context:component-scan base-package="${package}.test"/>

Installing the archetype into Nexus

Make sure the nexus repository is up and running.

Before we publish the archetype we need to define the location of the Nexus repository.

We do this in the archetype’s pom.xml file

After adding this section your pom.xml file 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>test-archetype</artifactId>
  <version>1.0-SNAPSHOT</version>
  <name>Archetype - test-archetype</name>
  <url>http://maven.apache.org</url>

<distributionManagement>
	<repository>
		<id>releases</id>
		<url>http://localhost:8081/nexus/content/repositories/releases</url>
	</repository>

	<snapshotRepository>
		<id>snapshots</id>
		<name>Internal Snapshots</name>
		<url>http://localhost:8081/nexus/content/repositories/snapshots</url>
	</snapshotRepository>
</distributionManagement>
</project>
mvn deploy

Open up the Nexus repository and verify that the archetype has been added. If it has not please review the instructions above before continuing.

Running the Archetype

In this section we will generate a project from an archetype we just created above.

open up the command line and navigate to a clean working directory.

mvn archetype:create \
  -DarchetypeGroupId=test \
  -DarchetypeArtifactId=test-archetype \
  -DarchetypeVersion=1.0-SNAPSHOT \
  -DgroupId=yourgroup \
  -DartifactId=your-project

You can also use the new format to generate a project form an archetype:

mvn archetype:generate \
  -DarchetypeGroupId=test \
  -DarchetypeArtifactId=test-archetype \
  -DarchetypeVersion=1.0-SNAPSHOT

Running your newly generated project

cd your-project
mvn jetty:run

At this point you can navigate to all the urls listed below:

http://localhost:8080/

http://localhost:8080/app/helloWorld

http://localhost:8080/app/dbParameters

Publishing your Archetype to a Website

Good News! You don’t need a Nexus server. Maven artifacts can be published to plain old web sites.

To test this I have uploaded the test-archetype to the following location and used the following command to generate a project based on the archetype.

mvn archetype:generate \
  -DarchetypeGroupId=test \
  -DarchetypeArtifactId=test-archetype \
  -DarchetypeVersion=1.0-SNAPSHOT \
  -DarchetypeRepository=http://your static site hostname/directory of your repository

Maven makes a Http connection to the above archetypeRepository and gets all the data necessary to create the project.

Summary

As you can see creating an archetype is not much difficult. You can use this technique to create templates of small projects you find yourself creating often. Archetypes can be posted not only to Nexus repositories but static html sites as well.

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!

08
Nov
09

Create Web Project using Maven Archetypes

This page describes the process of creating a standard web project using maven Archetypes. Afterwards we will run the web application in the built-in servlet container called jetty and an external one with Tomcat 6.

Requirements

  1. Eclipse J2EE IDE
  2. Tomcat installed and integrated with eclipse WTP.
  3. Maven 2
  4. Ability to command line on your machine

We start by creating the project

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

By default the archetype does not create a javasource folder so go ahead and create the following directory under the project.

src/main/java

Also by default the web application is not a WTP application, it has no idea how to run itself under jetty and does not know how to regenerate itself as an eclipse project.

In order to make this project do all those cool things we need to add a couple lines of code in the plugins section of the pom.xml file.

		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-war-plugin</artifactId>
			<configuration>
				<warName>${artifactId}</warName>
			</configuration>
		</plugin>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-eclipse-plugin</artifactId>
			<configuration>
				<projectNameTemplate>${artifactId}</projectNameTemplate>
				<wtpapplicationxml>true</wtpapplicationxml>
				<downloadSources>true</downloadSources>
				<downloadJavadocs>true</downloadJavadocs>
				<wtpversion>1.5</wtpversion>
				<classpathContainers>
					<classpathContainer>org.eclipse.jst.j2ee.internal.web.container</classpathContainer>
					<classpathContainer>org.eclipse.jst.j2ee.internal.module.container</classpathContainer>
				</classpathContainers>
			</configuration>
		</plugin>
		<plugin>
			<groupId>org.mortbay.jetty</groupId>
			<artifactId>jetty-maven-plugin</artifactId>
				<version>7.0.0.v20091005</version>
		</plugin>

By default the pom.xml that is created by this archetype does not specify to the other plugins what jvm version we will be using: In the build section of the pom.xml file put the following.

	<pluginManagement>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
		<configuration>
			<source>1.6</source>
			<target>1.6</target>
		</configuration>
			</plugin>
		</plugins>
	</pluginManagement>

In order to create a web application you need additional dependencies to be added

<dependency>
	<groupId>org.apache.geronimo.specs</groupId>
	<artifactId>geronimo-servlet_2.5_spec</artifactId>
	<version>1.2</version>
	<type>jar</type>
	<scope>provided</scope>
</dependency>

Regenerate the eclipse project

mvn eclipse:clean eclipse:eclipse

Return to eclipse and refresh the project.

Creating a servlet

Create a test Servlet.

package com.test;

import java.io.IOException;

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

public class TestServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("servlet ran successfully");
		request.getRequestDispatcher("/index.jsp").forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	}

}

Modify the xml to look like this:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <servlet>
  	<servlet-name>TestServlet</servlet-name>
  	<display-name>TestServlet</display-name>
  	<description></description>
  	<servlet-class>
  	com.test.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>TestServlet</servlet-name>
  	<url-pattern>/TestServlet</url-pattern>
  </servlet-mapping>
</web-app>

Running the Web Project in Jetty

In the project top level directory start the jetty servlet engine.

mvn jetty:run

Open browser and navigate to http://localhost:8080/ You should be seeing a hello world page. To test the servlet navigate to http://localhost:8080/TestServlet

When you run the servlet you should see “servlet ran successfully” printed to the console and the same Hello World message in the browser.

When you are done with the test, shut down the jetty server by hitting CTRL-C on the command line window.

Running the Web Project in Tomcat 6

Please make sure you have shut-down jetty before proceeding… Unless you changed them both jetty and tomcat 6 run on the default port of 8080. They both can not run at the same time.

Using Eclipse WTP all you need to do is make sure that Tomcat is defined and you are able to start and stop it. Right click on the project and click “Run On Server” option. Tomcat should show some output on the terminal. Follow the same steps you did while testing jetty. You should get the same results as above.

Congratulations

You have just configured a simple web application project using archetypes and hosted the application using both the built in web-app server called jetty and Tomcat 6 under eclipse using WTP.

You can also try out the following post. This is a simpler way to start a Spring MVC application from an archetype.

Thats all for now!

07
Nov
09

Multi-module projects using Maven and Eclipse

Maven allows the programmer to create multi-module projects. A multi-module project is a special type of maven project – it does not produce any artifact. Its main purpose is to host modules – single maven projects – and to perform group operations for all modules. Each module specifies a parent-module. When parent modules are built they import all child modules into what maven calls a “reactor”. When modules are inside the reactor they are build in the proper order. The proper order is determined by looking at each child module’s dependencies.

Requirements

Maven Multi Modules projects in Eclipse

Maven by default generates multi-module projects using a tree structure. The main project is at the top level and sub modules are nested below it.

As of Eclipse 3.4 and Maven 2.0.9 when you use the eclipse plugin to generate the project it will take a maven project that has sub modules nested within it and flatten it out. However it will create soft links to the sub-modules of the parent. Therefore maven can keep its nested project structure and eclipse is happy. The m2 eclipse plugin tricks eclipse into thinking that all the projects are defined in the workspace directory at the top level.

Example Application

We will create a Web service Client that calls a web service that when passed a ip address it will return the location of an IP address. To demonstrate the capabilities of developing multi module projects using eclipse and Maven we will build 3 different front-ends for this web service.

  1. Java Main application (run from command line)
  2. Swing Application (run from command line)
  3. Web application (run from the integrated jetty app server)

Lets create a simple project in eclipse to start. This will be the parent project that will contain information about its one Web service and 3 front end modules.

Parent Module

This is the pom.xml file of the main module

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

Answer a few more questions. See responses below…

32/33/34/35/36/37/38/39/40/41) 15: :
Define value for groupId: : com.test
Define value for artifactId: : parent
Define value for version:  1.0-SNAPSHOT: :
Define value for package:  com.test: :
Confirm properties configuration:
groupId: com.test
artifactId: parent
version: 1.0-SNAPSHOT
package: com.test
 Y: :

After the project gets generated, cd to the parent directory and edit the pom.xml file. Change the packaging to pom

  <packaging>pom</packaging>

Also add this to bottom of the file right before the end tag

  <build>
  	<pluginManagement>
  		<plugins>
  			<plugin>
  				<groupId>org.apache.maven.plugins</groupId>
  				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
  			</plugin>
  		</plugins>
  	</pluginManagement>
  </build>

save and exit.

Type the following command.

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

Choose the same option as above and enter the same responses except the artifactId field: specify ip2GeoService. AFter returning to the command prompt type the following:

mvn eclipse:clean eclipse:eclipse

Open up eclipse and right click on the project explorer view and select import then import maven projects. Browse and select the parent project to import. Maven will automatically find the sub projects and import them as well to the top level. They are really not at the top level they just appear that way.

Enable Apache CXF web service framework

We will be hosting a web service for this exercise so we will host it using the popular Apache CXF framework. If you want to read more about apache CXF and how you can import web services you can read the following article.

Open the ip2GeoService/pom.xml file and add the following dependencies.

		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf</artifactId>
			<version>2.1</version>
			<type>pom</type>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>2.2.4</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>

		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http-jetty</artifactId>
			<version>2.2.4</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>

Save the file and regenerate the eclipse project: mvn eclipse:clean eclipse:eclipse

Return to eclipse and refresh the parent and ip2GeoService project. Right click properties and observe the build classpath. YOu will notice that the ip2GeoService class has some additional jar files in the classpath while the parent project remains untouched.

The next few steps I am going to copy and paste from my other blog page. These instructions are used to create a web service.

open the ip2GeoService/pom.xml file and insert the following in the plugin tag in the build section of the pom.xml file.

  <build>
  	<plugins>
<plugin>
	<groupId>org.apache.cxf</groupId>
	<artifactId>cxf-codegen-plugin</artifactId>
	<version>2.2.4</version>
	<executions>
		<execution>
			<id>generate-sources</id>
			<phase>generate-sources</phase>
			<configuration>
				<sourceRoot>generated/cxf</sourceRoot>
				<wsdlOptions>
					<wsdlOption>
						<wsdl>document.wsdl</wsdl>
					</wsdlOption>
				</wsdlOptions>
			</configuration>
			<goals>
				<goal>wsdl2java</goal>
			</goals>
		</execution>
	</executions>
</plugin>
  	</plugins>
  </build>

Next obtain the wsdl file and save it to the document.wsdl in the root of the ip2GeoService project folder.

Run the following command to generate a web service client classes from the WSDL.
regenerate the eclipse project
mvn eclipse:clean eclipse:eclipse

Refresh the project in eclipse and you will notice that the code for the web service has been generated and put into the classpath. At this point the web service is ready to be called by our clients that we will be coding up shortly.

Java Main Application sub module

The first application we will be coding up is a simple java main() application that will run the web service via command line.

return to the parent project and type the following:
mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart

Modify the pom.xml file and add the following

		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>2.2.4</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>

Add the ip2GeoService as a dependency

		<dependency>
			<groupId>com.test</groupId>
			<artifactId>ip2GeoService</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>

create a src/main/resources directory under the project.

mvn eclipse:clean eclipse:eclipse on the subproject

refresh the eclipse project

create an app-context.xml file inside src/main/resources folder

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <jaxws:client id="ip2Geo"
                  serviceClass="com.cdyne.ws.IP2GeoSoap"
                  address="http://ws.cdyne.com/ip2geo/ip2geo.asmx" />
</beans>

Modify the com.test.App class that was generated for you by maven and make it look like this…

package com.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.cdyne.ws.IP2GeoSoap;
import com.cdyne.ws.IPInformation;

/**
 * Hello world!
 *
 */
public class App
{
    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
		ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"app-context.xml"});

		IP2GeoSoap ip2Geo = (IP2GeoSoap) context.getBean("ip2Geo");
		IPInformation ipInformation = ip2Geo.resolveIP("12.12.12.12", "0");

		System.out.println("City: " + ipInformation.getCity());
		System.out.println("State: " + ipInformation.getStateProvince());
		System.out.println("Country: " + ipInformation.getCountry());

    }
}

Save and run the java main application by running the following command:
mvn install
mvn exec:java -Dexec.mainClass=com.test.App

you should see output on your screen like this

City: Anchorage
State: AK
Country: United States

You have successfully created a standalone Java main application that is calling a web service thru a module dependency with IP2GeoService module. You may modify the java main application to get the ip address to pass to the web service thru the args[] string array.

Web Application sub module

To create a web application we will use the following command

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp
Answer the questions like this:

[INFO] Generating project in Interactive mode
Define value for groupId: : com.test
Define value for artifactId: : ip2GeoWeb
Define value for version:  1.0-SNAPSHOT: :
Define value for package:  com.test: :
Confirm properties configuration:
groupId: com.test
artifactId: ip2GeoWeb
version: 1.0-SNAPSHOT
package: com.test
 Y: :

mvn eclipse:clean eclipse:eclipse

In eclipse right click on the parent project Refresh then select import. By default maven will not make the project a WTP compatible project. To make the web project easier to manage from within the eclipse environment we will enable WTP.

Open the pom.xml file and edit the build section to look similar to the following:

	<build>
	<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<configuration>
					<warName>${artifactId}</warName>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-eclipse-plugin</artifactId>
				<configuration>
					<projectNameTemplate>${artifactId}</projectNameTemplate>
					<wtpapplicationxml>true</wtpapplicationxml>
					<downloadSources>true</downloadSources>
					<downloadJavadocs>true</downloadJavadocs>
					<wtpversion>1.5</wtpversion>
					<outputDirectory>WebContent/WEB-INF/classes</outputDirectory>
					<classpathContainers>
						<classpathContainer>org.eclipse.jst.j2ee.internal.web.container</classpathContainer>
						<classpathContainer>org.eclipse.jst.j2ee.internal.module.container</classpathContainer>
					</classpathContainers>
				</configuration>
			</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>
    <finalName>ip2GeoWeb</finalName>
  </build>

We will also need to add the following 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>

Create a simple servlet that prints hello world.

To test the web application we will be using a built in servlet engine called jetty.

mvn jetty:run

Close the server and implement the following code from within the goGet method of the servlet

package com.test.web;

import java.io.IOException;

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.context.support.ClassPathXmlApplicationContext;

import com.cdyne.ws.IP2GeoSoap;
import com.cdyne.ws.IPInformation;

public class IP2GeoServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	private ApplicationContext context;

	@Override
    public void init() throws ServletException {
		context = new ClassPathXmlApplicationContext(new String[] {"app-context.xml"});
    	super.init();
    }
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		request.setAttribute("ipInformation", new IPInformation());
		request.getRequestDispatcher("/enterIp.jsp").forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		IP2GeoSoap ip2Geo = (IP2GeoSoap) context.getBean("ip2Geo");
		String ipAddress = (String) request.getParameter("ipAddress");
		IPInformation ipInformation = new IPInformation();

		if(ipAddress != null && !"".equals(ipAddress.trim())) {
			System.out.println("finding location for: " + ipAddress);
			ipInformation = ip2Geo.resolveIP(ipAddress, "0");
			if("".equals(ipInformation.getCity())){
				ipInformation.setCity("web service returned a blank response");
			}
		}
		request.setAttribute("ipInformation", ipInformation);
		request.getRequestDispatcher("/enterIp.jsp").forward(request, response);
	}
}

The JSP looks like this…

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

<jsp:useBean id="ipInformation" type="com.cdyne.ws.IPInformation" scope="request"/>

<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>
<form action="" method="post">
	<label>ip address: </label>
	<input type="text" name="ipAddress" value="12.12.12.12"/><br/>
	<input type="submit" value="submit"/><br/>
</form>
<hr />

Results:<br/>
City: <jsp:getProperty property="city" name="ipInformation"/><br/>
State: <jsp:getProperty property="stateProvince" name="ipInformation"/><br/>
Country: <jsp:getProperty property="country" name="ipInformation"/><br/>

</body>
</html>

you will notice that you get build errors. 2 reasons.
1. spring is not listed as a dependency in the web application’s pom.xml file.
2. the ip2GeoService is not listed as a dependency

Modify the pom.xml file to add these two dependencies. (spring will be brought in as a transitive dependency)

		<dependency>
			<groupId>com.test</groupId>
			<artifactId>ip2GeoService</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>

Copy over the app-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <jaxws:client id="ip2Geo"
                  serviceClass="com.cdyne.ws.IP2GeoSoap"
                  address="http://ws.cdyne.com/ip2geo/ip2geo.asmx" />
</beans>

cd to parent/ip2GeoWeb

mvn jetty:run

navigate to: http://localhost:8080/IP2GeoServlet and you will see the output of the web service.

Swing Application sub module

Start the swing application by executing the following command:

cd to the parent project
mvn archetype:generate -DarchetypeArtifactId=maven-archetype-quickstart

Answer the questions like this:

Define value for groupId: : com.test
Define value for artifactId: : ip2GeoSwing
Define value for version:  1.0-SNAPSHOT: :
Define value for package:  com.test: :
Confirm properties configuration:
groupId: com.test
artifactId: ip2GeoSwing
version: 1.0-SNAPSHOT
package: com.test
 Y: :

Create a directory inside the swing project
src/main/resources

mvn eclipse:clean eclipse:eclipse
refresh the parent project in eclipse and right click import the newly generated project.

put the following file in the resource folder that was just created

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <jaxws:client id="ip2Geo"
                  serviceClass="com.cdyne.ws.IP2GeoSoap"
                  address="http://ws.cdyne.com/ip2geo/ip2geo.asmx" />
</beans>

Finally create the JFrame class that will run the web service and display the results.

package com.test;

import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextField;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.cdyne.ws.IP2GeoSoap;
import com.cdyne.ws.IPInformation;

public class App extends JFrame {
	private JButton jButton;
	private JTextField ipAddress;

	private JTextField city;
	private JTextField state;
	private JTextField country;

	private static final ApplicationContext context = new ClassPathXmlApplicationContext(
			new String[] { "app-context.xml" });

	private static final IP2GeoSoap ip2Geo = (IP2GeoSoap) context.getBean("ip2Geo");

	public App() {
		initFrame();

	}

	private JButton getWebServiceButton() {
		JButton jButton = new JButton("execute Web Service");
		jButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String ipValue = ipAddress.getText();
				System.out.println("validating ip: " + ipValue);

				IPInformation ipInformation = ip2Geo.resolveIP(ipValue, "0");

				System.out.println("City: " + ipInformation.getCity());
				System.out.println("State: " + ipInformation.getStateProvince());
				System.out.println("Country: " + ipInformation.getCountry());
				city.setText(ipInformation.getCity());
				state.setText(ipInformation.getStateProvince());
				country.setText(ipInformation.getCountry());

			}
		});

		return jButton;
	}

	private void initFrame() {
		this.setSize(400, 150);
		Container content = this.getContentPane();
		content.setBackground(Color.white);
		content.setLayout(new FlowLayout());
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});

		content.add(this.getWebServiceButton());
		ipAddress = new JTextField("12.12.12.12");
		content.add(ipAddress);

		city = new JTextField("City");
		state = new JTextField("State");
		country = new JTextField("Country");

		content.add(city);
		content.add(state);
		content.add(country);

		this.setVisible(true);
	}

	public static void main(String[] args) {
		App app = new App();
	}

}

Wrap Up

In Maven a parent project can have any number of sub projects under it. This makes management of each project easier. As you have seen we created a Web Service Client, and 3 different types of front ends for the web service client. In the real world the Web service sub-project would represent the Model layer. All common business logic would be available to all sub projects under the parent project.

Maven’s capabilities that were exhibited above have really brought the Development in the Java Platform to another level. Code re-use can be maximized with thoughtful designs that separate projects out into their own areas.

For the Web applications Excel in allowing multiple users to access the application thru a very light weight medium. The Java main applications can be run from a non-interactive environments like distributed batch servers. Swing applications can be run where users require the updates to the screen which only a thick client application can provide.

It is difficult to create a Single Java project that can accomplish all those responsibilities. But if you break up the project into parts where each sub-project handles its area of expertise and use the common business logic layer as a dependency, you can get the maximum code re-use.

28
Oct
09

Maven for Eclipse IDE Platform Developers

Maven is a great build tool. There are many resources out there describing this topic in detail. There are many examples of how to generate eclipse projects on this site however they cover the more advanced cases. This page describes how to generate a simple standalone project using a simple pom.xml file.

Quick History about Maven

Maven was originally started as an attempt to simplify the build processes in the Jakarta Turbine project. The developers of the Turbine project thought that this tool can be used to build any project and worked on generalizing it for use by the general development community.

A complete description about Maven is available here

Maven is used to Generate Eclipse Projects

On this site I use Maven to generate eclipse projects. The advantage for doing it this way is that the projecs are uniform no matter what platform they are on. Since the dependencies are well documented within the Maven’s main config file called pom.xml you dont need to worry yourselves with downloading them from third party websites.

A typical project will start by you the developer creating a new project. The second step is to place a pom.xml file (seen a the end of the post) into the main directory of the project. Then you will drop the command line and cd to the project’s folder and type mvn eclipse:clean eclipse:eclipse

Before you can start generating your own eclipse projects you need to install Maven. Please follow the instructions

Once that is complete you need to execute the following command

mvn -Declipse.workspace=<path to your workspace> eclipse:add-maven-repo

Once installation of maven is complete you can continue and create the pom file.
The following is the pom.xml file that was used to generate the above project

<?xml version="1.0" encoding="UTF-8"?>
<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>TestProject</artifactId>
	<packaging>jar</packaging>
	<version>1.0.1-SNAPSHOT</version>
	<name>TestProject</name>

	<build>
		<sourceDirectory>src</sourceDirectory>
		<resources>
			<resource>
				<directory>src</directory>
			</resource>
		</resources>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.0.2</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-eclipse-plugin</artifactId>
				<configuration>
					<downloadSources>true</downloadSources>
					<downloadJavadocs>true</downloadJavadocs>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring</artifactId>
			<version>2.5.5</version>
		</dependency>
	</dependencies>
</project>

cd /workspace
mvn eclipse:clean eclipse:eclipse

verma@verma-desktop:~/workspace/TestProject$ pwd
/home/verma/workspace/TestProject
verma@verma-desktop:~/workspace/TestProject$ mvn eclipse:clean eclipse:eclipse
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'eclipse'.
[INFO] ------------------------------------------------------------------------
[INFO] Building TestProject
[INFO]    task-segment: [eclipse:clean, eclipse:eclipse]
[INFO] ------------------------------------------------------------------------
[INFO] [eclipse:clean]
[INFO] Deleting file: .project
[INFO] Deleting file: .classpath
[INFO] Deleting file: .wtpmodules
[INFO] Deleting file: .component
[INFO] Deleting file: org.eclipse.wst.common.component
[INFO] Deleting file: org.eclipse.wst.common.project.facet.core.xml
[INFO] Deleting file: org.eclipse.jdt.core.prefs
[INFO] Deleting file: org.eclipse.ajdt.ui.prefs
[INFO] Preparing eclipse:eclipse
[INFO] No goals needed for project - skipping
[INFO] [eclipse:eclipse]
[INFO] Using Eclipse Workspace: /home/verma/workspace
[INFO] no substring wtp server match.
[INFO] Using as WTP server : Apache Tomcat v6.0
[INFO] Adding default classpath container: org.eclipse.jdt.launching.JRE_CONTAINER
[INFO] Resource directory's path matches an existing source directory. Resources will be merged with the source directory src
[INFO] Wrote settings to /home/verma/workspace/TestProject/.settings/org.eclipse.jdt.core.prefs
[INFO] Wrote Eclipse project for "TestProject" to /home/verma/workspace/TestProject.
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1 second
[INFO] Finished at: Wed Oct 28 21:31:31 EST 2009
[INFO] Final Memory: 20M/437M
[INFO] ------------------------------------------------------------------------

Return to eclipse and click refresh on the project. You will now have a fresh new project with all the dependencies in the build classpath of the project. You will not need to download those from third party websites. Maven will retrieve them from the central Maven repository.

Screenshot-Properties for TestProject

The text of the whole book that describes Maven is available online.

click here to view the site

That’s all for now!

07
Sep
09

Struts 1 Lesson 1 Hello World with Maven 2

Introduction

This page explains how you can get a basic struts hello world application up and running using Maven 2.

Lets start with the pom file and use it to regenerate our eclipse project.

Implementation

Start by creating a project from a Maven archetype.

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

Answer the rest of the questions like this…

Define value for groupId: : com.test
Define value for artifactId: : strutsTest
Define value for version:  1.0-SNAPSHOT: :
Define value for package:  com.test: :

Hit enter for the rest of the defaults.

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

Next we generate the eclipse project (optional). The project is still not ready however this step makes editing the pom.xml file easier.

mvn eclipse:clean eclipse:eclipse

Import the Existing project (generated project) into eclipse.

Next steps are to typically modify the pom.xml file and insert the rest of the dependencies and regenerate the eclipse project by re-typing the above command and clicking refresh on the eclipse project.

Update your pom.xml file to 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>com.test</groupId>
  <artifactId>strutsTest</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>strutsTest 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>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.struts</groupId>
			<artifactId>struts-core</artifactId>
			<version>1.3.10</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>strutsTest</finalName>
        <plugins>
            <plugin>
                <groupId>org.mortbay.jetty</groupId>
                <artifactId>jetty-maven-plugin</artifactId>
                <version>7.0.0.v20091005</version>
                        <configuration>
                         <scanIntervalSeconds>2</scanIntervalSeconds>
                        </configuration>
            </plugin>
        </plugins>    
  </build>
</project>

It all starts with the web.xml

In the above code you see spring included as a dependency. Lets leave it there for now since this example is used to build a project that uses spring with struts together.

Next we will modify the web.xml file

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>strutsTest</display-name>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

	<servlet>
		<servlet-name>action</servlet-name>
		<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
		<init-param>
			<param-name>config</param-name>
			<param-value>
         /WEB-INF/struts-config.xml
        </param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>

	</servlet>

	<servlet-mapping>
		<servlet-name>action</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>

</web-app>

Next comes the struts-config.xml file. Both the web.xml and this file belong in the /WEB-INF folder.

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

<?xml version="1.0" encoding="ISO-8859-1" ?>
    <!DOCTYPE struts-config PUBLIC
          "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
          "http://struts.apache.org/dtds/struts-config_1_3.dtd">

<struts-config>
	<action-mappings>
		<action path="/HelloWorld"  type="com.test.HelloWorldAction">
			<forward name="success" path="/helloWorld.jsp"></forward>
		</action>
	</action-mappings>
</struts-config>

Next is the hello world struts action
src/main/java/com/test/HelloWorldAction.java

package com.test;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

public class HelloWorldAction extends org.apache.struts.action.Action {

    private final static String SUCCESS = "success";

    public ActionForward execute(ActionMapping mapping,ActionForm form,
           HttpServletRequest request,HttpServletResponse response) throws Exception {

        return mapping.findForward(SUCCESS);

    }
}

Next we will create the JSP’s used to display the pages.

src/main/webapp/index.jsp

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
<title>Your Page Title</title>
<meta http-equiv="REFRESH" content="0;url=<c:url value='/HelloWorld.do'/>"></HEAD>
<BODY>
Optional page text here.
</BODY>
</HTML>

Next is the Hello World page

src/main/webapp/helloWorld.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>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>
Struts Hello World.
 <body>
</body>
</html>

Test the application

Start up jetty and test your application

mvn jetty:run

navigate to http://localhost:8080/

You should see a Hello World message.

In the next section we will step thru the process of integrating spring with this simple struts application.




Follow

Get every new post delivered to your Inbox.

Join 49 other followers