EJB with STRUTS

The following example uses a modified version of the Entity Bean Application the description of which was posted earlier.
There is no change in the contents of mysql-ds.xml, jboss.xml, jbosscmp-jdbc.xml, ejb-jar.xml and application.xml; the entity bean classes AuthorsBean.java, Authors.java. AuthorsHome.java and AuthorsKey.java. Some classes and xml-files specific to Struts and a few jsps’ have been added.

Download a binary version of Struts and unzip it into an appropriate folder. Set an environment variable STRUT_HOME pointing to this installation.

The work directory for ant has the following structure:

mysql-ds.xml
jbosscmp-jdbc.xml
ejb-jar.xml
jboss.xml
application.xml
ApplicationResources.properties
build.xml
build.properties
build.bat
struts-config.xml
web.xml
<build>
<pages>
      |authors.jsp
      |success.jsp
<src>
      |shoppingcart
            |AuthorsBean.java
            |Authors.java
            |AuthorsHome.java
            |AuthorsKey.java
            |authorsForm.java
            |authorsAction.java
<action path="/testout" type="shoppingcart.authorsAction" name="authorsForm"
	scope="request" input="/authors.jsp" validate="false">
	<forward name="successful" path="/success.jsp" />
</action>

The

<action></action>

block in the struts config.xml is the link between jsps, actions, forms and forwards.
The type=shopping.authorsAction mentions the Action class to be used in authors.jsp. The name=authorsForm mentions which form bean is to be used for authors.jsp. The form bean needs a separate definition in the struts-config.xml. This is at the beginning of the struts-config:

<form-bean name="authorsForm" type="shoppingcart.authorsForm"/>

The jsp pages mapped in the struts-config file is called thus in the action class:

return mapping.findForward("successful");

struts-config.xml looks like this:

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
	<form-beans type="org.apache.struts.action.ActionFormBean">
		<form-bean name="authorsForm" type="shoppingcart.authorsForm" />
	</form-beans>
	<action-mappings type="org.apache.struts.action.ActionMapping">
		<action path="/testout" type="shoppingcart.authorsAction" name="authorsForm"
			scope="request" validate="false">
			<forward name="successful" path="/success.jsp" />
		</action>
	</action-mappings>
	<message-resources parameter="ApplicationResources" />
</struts-config>

Modifying the web.xml file:
Modify the web.xml file for the web application to include a

<servlet>

element to define the controller servlet, and a

<servlet-mapping>

element to establish which request URIs are mapped to this servlet. Modify the WEB-INF/web.xml file of the web application to include tag library declarations for tld files from STRUT_HOME/lib/struts-*.tld
The action “/testout.matty” in authors.jsp ( in authors.jsp) is mapped to the path=“/testout” in the action mappings of struts-config.xml. “.matty” is the extension for all urls pointing to struts action classes and is set in web.xml by extension mapping.

web.xml looks like this:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!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>
	<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>*.matty</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>authors.jsp</welcome-file>
	</welcome-file-list>
	<taglib>
		<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
		<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
	</taglib>
	<taglib>
		<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
		<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
	</taglib>
	<taglib>
		<taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
		<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
	</taglib>
</web-app>

Application Resources.properties looks like this:

isbnCode.label=Enter Isbn Code of the book
author.label=Enter name of the author(only to create a record)

When compiling the Java classes that comprise the application, include the struts.jar and commons-*.jar files on the CLASSPATH that is submitted to the compiler. I did this by specifying paths in the tag of build.xml.
Struts *.tld files and struts.jar are copied to the war file during the build process.

build.xml looks like this:

<project name="Authors" default="clean" basedir=".">

	<property environment="env" />
	<property file="./build.properties" />

	<!-- the build path -->
	<path id="build.path">
		<pathelement location="${jboss.dist}/server/default/lib" />
		<pathelement location="${jboss.dist}/server/default/lib/jboss-j2ee.jar" />
		<pathelement location="${jboss.dist}/client/javax.servlet.jar" />
		<pathelement location="${build.classes.dir}" />
		<pathelement location="${struts.dir}" />
		<pathelement location="${struts.dir}/struts.jar" />
	</path>

	<target name="war" depends="compile">
		<war warfile="${war}" webxml="web.xml">
			<fileset dir="${basedir}/pages">
				<include name="*.jsp" />
			</fileset>
			<webinf dir="${struts.dir}">
				<include name="*.tld" />
			</webinf>
			<webinf dir="${basedir}">
				<include name="struts-config.xml" />
			</webinf>
			<classes dir="${build.classes.dir}">
				<include name="shoppingcart/*.class" />
				<exclude name="shoppingcart/${appname}Bean.class" />
			</classes>
			<classes dir="${basedir}">
				<include name="ApplicationResources.properties" />
			</classes>
			<lib dir="${jboss.client.dir}">
				<include name="jboss-client.jar" />
				<include name="jnp-client.jar" />
			</lib>
			<lib dir="${struts.dir}">
				<include name="struts.jar" />
			</lib>
		</war>
	</target>

	<target name="jar" depends="compile">
		<jar jarfile="${jar}">
			<fileset dir="${build.classes.dir}">
				<include name="shoppingcart/${appname}.class" />
				<include name="shoppingcart/${appname}Home.class" />
				<include name="shoppingcart/${appname}Bean.class" />
				<include name="shoppingcart/${appname}Key.class" />
			</fileset>
			<metainf dir="${basedir}" includes="jboss.xml,ejb-jar.xml,jbosscmp-jdbc.xml" />
		</jar>
	</target>

	<!-- build all, and copy to the jboss/deploy directory -->

	<target name="ear" depends="jar,war">
		<ear earfile="${ear}" appxml="application.xml">
			<fileset dir="${basedir}" includes="${jar},${war}" />
		</ear>
	</target>

	<!-- compilation options -->

	<target name="compile">
		<mkdir dir="${build.classes.dir}" />
		<javac srcdir="${src.dir}" destdir="${build.classes.dir}" debug="on"
			deprecation="on" classpathref="build.path" optimize="off" />
	</target>
	<target name="build-all" depends="ear">
		<copy file="${ear}" todir="${jboss.deploy.dir}" />
		<copy file="mysql-ds.xml" todir="${jboss.deploy.dir}" />
	</target>
	<target name="clean">
		<delete file="${jar}" />
		<delete file="${ear}" />
		<delete file="${war}" />
		<delete file="${jboss.deploy.dir}/${ear}" />
		<delete file="${jboss.deploy.dir}/mysql-ds.xml" />
		<delete dir="${build.classes.dir}" />
	</target>
</project>

build.properties looks like this:

appname=Authors
# get JBOSS location from environment variable
dist.root=${env.JBOSS_HOME}
jboss.dist=${dist.root}
jboss.deploy.dir=${jboss.dist}/server/default/deploy
jboss.client.dir=${jboss.dist}/client

# get STRUT_HOME location from environment variable
struts.dir=${env.STRUT_HOME}/lib
src.dir=${basedir}/src
src.docroot=${src}/docroot
build.dir=${basedir}/build
build.classes.dir=${build.dir}/classes

war=${appname}.war
jar=${appname}.jar
ear=${appname}.ear

The ejb files are the same as in the entity bean example.
Two additional classes have replaced AuthorsServlet:

authorsForm.java

package shoppingcart;

import javax.servlet.http.*;

public class authorsForm extends org.apache.struts.action.ActionForm {
	String author;
	String isbnCode;

	public void setAuthor(String author) {
		this.author = author;
	}

	public String getAuthor() {
		return this.author;
	}

	public void setIsbnCode(String isbnCode) {
		this.isbnCode = isbnCode;
	}

	public String getIsbnCode() {
		return this.isbnCode;
	}
};

authorsAction.java


package shoppingcart;

import shoppingcart.*;
import javax.naming.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Hashtable;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import org.apache.struts.action.*;
import java.util.*;

public class authorsAction extends Action {
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest req, HttpServletResponse res)
			throws java.lang.Exception {
		String auth = ((authorsForm) form).getAuthor();
		String isbn = ((authorsForm) form).getIsbnCode();
		AuthorsHome authorsHome = null;
		Authors bean = null;
		try {
			Properties p = new Properties();
			p.setProperty("java.naming.factory.initial",
					"org.jnp.interfaces.NamingContextFactory");
			p.setProperty("java.naming.provider.url", "localhost:1099");
			p.setProperty("java.naming,factory.url.pkgs",
					"org.jboss.naming:org.jnp.interfaces");
			InitialContext jndiContext = new InitialContext(p);
			Object ref = jndiContext.lookup("shoppingcart/Authors");
			authorsHome = (AuthorsHome) PortableRemoteObject.narrow(ref,
					AuthorsHome.class);
		} catch (Exception e) {
			throw new ServletException("failed to lookup shoppingcart/Authors",
					e);
		}
		req.setAttribute("author", auth);
		req.setAttribute("isbnCode", isbn);
		if (req.getParameter("add") != null) {
			try {
				AuthorsKey key = new AuthorsKey(isbn);
				bean = authorsHome.create(key);
				if (auth != null) {
					bean.setAuthorName(auth);
				}
				req.setAttribute("author", auth);
				req.setAttribute("isbnCode", isbn);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (req.getParameter("find") != null) {
			try {
				if (isbn != null) {
					AuthorsKey key = new AuthorsKey(isbn);
					bean = authorsHome.findByPrimaryKey(key);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			req.setAttribute("author", bean.getAuthorName());
			req.setAttribute("isbnCode", isbn);
		}
		return mapping.findForward("successful");
	}
}

Two new jsps have been added

authors.jsp

<html>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>
<head>
</head>
<body>
	<html:form action="/testout.matty">
		<p>
			<html:errors />
			<br />
			<bean:message key="isbnCode.label" />
			<html:text property="isbnCode" size='10' />
			<br />
			<bean:message key="author.label" />
			<html:text property="author" size='10' />
			<html:submit value='Add' property="add" />
			<html:submit value='Find' property="find" />
	</html:form>
</body>
</html>

success.jsp

<html>
<head>
</head>
<body>
	<%
		if (request.getAttribute("author") != null) {
	%>
	<h3>
		ISBN CODE
		<%=request.getAttribute("isbnCode")%></h3>
	<%
		}
	%>
	<%
		if (request.getAttribute("isbnCode") != null) {
	%>
	<h3>
		AUTHOR
		<%=request.getAttribute("author")%></h3>
	<%
		}
	%>
</body>
</html>

The ear file deployed to jboss has the following structure:

authors.ear
      |<meta-INF>
        |application.xml
      |authors.jar
        |<meta-INF>
            |ejb-jar.xml
            |jboss.xml
            |jbosscmp-jdbc.xml
        |<shoppingcart>
            |AuthorsBean.class
            |Authors.class
            |AuthorsHome.class
            |AuthorsKey.class
      |authors.war
        |authors.jsp
        |success.jsp
        |<meta-INF>
        |<web-INF>
            |struts-config.xml
            |web.xml
            |struts-bean.tld
            |struts-html.tld
            |struts-logic.tld
            |struts-nested.tld
            |struts-logic.tld
            |<classes>
                  |ApplicationResources.properties
                  |<shoppingcart>
                        |Authors.class
                        |AuthorsKey.class
                        |AuthorsHome.class
                        |authorsForm.class
                        |authorsAction.class
            |<lib>
                  |jnp-client.java
                  |jboss-client.jar
                  |struts.jar

Start the application using the following url
http://localhost:8080/authors.jsp

About cuppajavamattiz
Matty Jacob - Avid technical blogger with interests in J2EE, Web Application Servers, Web frameworks, Open source libraries, Relational Databases, Web Services, Source control repositories, ETL, IDE Tools and related technologies.

Comments are closed.

%d bloggers like this: