ou’ll find plenty written about building and deploying EJB, and perhaps equally as much about building applications with the Struts framework. But what about leveraging EJB and Struts together? This tutorial lays out a complete step-by-step guide to integrating these two technologies, developing EJB components and incorporating them into Struts.
What You Need |
---|
JBoss 3.2.3 |
Eclipse 2.1.3 |
Jakarta Struts 1.1 |
Java 2 Platform, Standard Edition (J2SE 1.3+) |
Installation
First, you need to download the necessary tools. Before anything else, make sure you have an installation of Eclipse. This article uses Eclipse 2.1.3.
Next, verify that your Eclipse installment is using the full JDK located at JAVA_HOME, not just the Java Runtime Environment (JRE):
- Go to Window -> Preferences, expand the Java node, and click Installed JRE.
- Click Add, and then click the Browse button for the JRE Home Directory. Go to your JAVA_HOME directory, and click OK.
- Type in JDK under JRE Name, and click OK. Make sure that JDK is checked and click OK to exit Windows -> Preferences (see Figure 1).
![]() | |
Figure 1: Use the Full JDK Rather Than the JRE |
Now, download the JBoss Plug-in:
- Open Eclipse. On the top menu, click Help->Software Updates->Find and Install.
- Select Search for new features to install and click Next.
- Click Add Update Site, and in the new box, type JBoss Plug-in under name and the URL http://jboss.sourceforge.net/jbosside/updates. The entry JBoss Plug-in (or whatever you entered under the text field name) now appears; make sure it is checked and click Next.
- You will now see a list of different JBoss-IDE versions. This tutorial uses version 1.2.3.
- Click Next, accept the license agreement, and install.
Next, download JBoss. For this tutorial, choose JBoss 3.2.3, the latest stable release at the time of this writing. Unzip the .zip file to your computer. Note that since JBoss 3.2.1, Tomcat has replaced Jetty as the default Web container.
To test if everything is in working order, go to the /bin directory of your JBoss installation, and execute the run.bat/run.sh that corresponds to your operating system. After the server tells you it has started, go to this URL in your browser: http://localhost:8080/jmx-console/index.jsp. You should see the JMX Management Console page, along with a JBoss logo on the right-hand side.
Finally, download the Jakarta Struts Framework and unzip the .zip file to your computer. (Struts 1.1 was the latest stable version at the time of this article.)
Okay! Now you are all set up and ready to rock and roll.
Create a Project
First create a Java Project in Eclipse:
- Click File -> New -> Project. Choose Java Project and click Next.
- Under Name, type StrutsEJBTutorial. Click Finish.
Import Struts
Now, incorporate Struts into your project. The easiest way is to import the struts-blank.war file:
- Right click on your project StrutsEJBTutorial in the package explorer of Eclipse.
- Select Import, then choose Zip file.
- Click browse and navigate to the location where you unzipped your Struts download. Once there, navigate to the /webapps directory.
- Under file name, type *.war and press enter. You should see a selection of war files. Choose struts-blank.war, press enter, and then click Finish (see Figure 2).
Figure 2: Import a struts-blank.war File
Modify Project Properties
Now you are ready to modify your project properties:
- Right click on your project StrutsEJBTutorial in the package explorer of Eclipse.
- Select properties, and Click Java Build Path.
- Modify your source folder. For this tutorial, keep intact the directory structure of a Struts project. Click StrutsEJBTutorial and click Add Folder. Expand the WEB-INF node, then expand the src node, check java, and click OK. Make sure that WEB-INF and src are not checked; otherwise, Eclipse will try to recognize these as source folders as well.
- Modify your output folder. Click the Browse button on the bottom right, expand StrutsEJBTutorial and WEB-INF, and select classes. Click OK. Figure 3 displays a screenshot of how your source and output directories should look.
Figure 3: Source and Output Directories - Click the Libraries tab. Click Add JARs, and expand StrutsEJBTutorial, WEB-INF, and lib. Select all the jar files and click OK. Now click Add External JARs, and navigate to JBoss_directory/server/default/lib. Select jboss-j2ee.jar and javax.servlet.jar, click Open, and then click OK. Figure 4 shows the libraries you should include in your buildpath.
Figure 4: Libraries in Your Buildpath
The Application
Your application will do a simple bean retrieval, based on a user requesting stock information. It involves a simple JSP, which requests that the user select a stock and submit. Your action class will then create a façade object and retrieve the information requested from your simple session bean (EJB).
You will first build the Struts components of the application, and then integrate EJB into the framework.
Create the JSP and Interface for Static Values
Create a stockquery.jsp under the /pages directory in your project. The following is the JSP I created:
<%@ page language="java" %><%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %><%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %><%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %><%@ page import="lum.staticvalues.*" %> Retrieve Stock InformationChoose a Stock action ="stockselect.do"> property ="ticker"> value ="<%=StaticValues.SUNW%>">Sun Microsystems value ="<%=StaticValues.IBM%>">International Business Machines value ="<%=StaticValues.CSCO%>">Cisco Systems
column="2"> Ticker Symbol property="stocks.tickerSymbol"/> Change property="stocks.change"/> Days Range property="stocks.daysRange"/> Fifty Two Week Range property="stocks.fiftyTwoWeekRange"/> Volume property="stocks.volume"/> Avg Volume (3 months) property="stocks.avgVol"/> Market Cap property="stocks.marketCap"/>
Notice in the JSP code that you import an interface called StaticValues
to hold the ticker symbols. In the event that a stock’s ticker symbol changes?which certainly happens?you naturally want to make the change in only one place. Create the interface with the following code, with a package name of lum.staticvalues:
package lum.staticvalues;public interface StaticValues { public static final String SUNW = "SUNW"; public static final String IBM = "IBM"; public static final String CSCO = "CSCO";}
Create the Bean Class
Create a simple bean, Stocks.java, under your source directory (WEB-INF/src/java) with a package name of lum.stock (see Listing 1).
Create the Action Class
Now, create an action class called StockAction
under your source directory, and keep it in the package stock lum.stock.action:
package lum.stock.action;import org.apache.struts.action.*;import org.apache.struts.validator.*;import javax.servlet.http.*;import lum.stock.Stocks;import lum.stock.facade.StockFacade;import java.rmi.RemoteException;public class StockAction extends Action { public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { DynaValidatorForm dvf = (DynaValidatorForm) form; String ticker = (String)dvf.get("ticker");
// if (ticker!= null || !ticker.equals("")) { StockFacade sf = new StockFacade(); Stocks stks = new Stocks(); try { stks = sf.getStockBean(ticker); } catch(RemoteException re){ System.out.println("Caught Remote Exception from Stockbean"); } dvf.set("stocks", stks);
//sets via } return mapping.findForward("success"); }}
Edit struts-config.xml
You need to insert only two entries into struts-config.xml to get the application running. Between the beginning and end
name ="stockDynaValidateForm" type="org.apache.struts.validator.DynaValidatorForm"> name ="ticker" type="java.lang.String"/> name ="stocks" type="lum.stock.Stocks"/>
Notice that I use DynaValidatorForm
. I don’t include any validation rules for the page. I leave that to you, should you decide to expand upon this application.
Your second entry is the action. Insert the following between the beginning and end
path ="/stockselect" type="lum.stock.action.StockAction" name="stockDynaValidateForm" validate="true" scope="request"> name ="success" path="/pages/stockquery.jsp"/> name ="failure" path="/pages/stockquery.jsp"/>
At this point, you’ve finished developing your Struts framework. Now it’s time to develop your EJB components and incorporate them into Struts.
Create the EJB
As mentioned previously, this EJB will be a stateless session bean. For the sake of simplicity, it has just one method, which is passed the argument from the stockquery.jsp. It then returns the requested stock data, which is stored inside the bean itself.
Create the class under your source directory with a package name of lum.stock.ejb.bean (see Listing 2).
Notice the javadoc in this code. It is essential, as you will use XDoclet to generate several files (including your deployment descriptors) and both home and remote interfaces for the StockBean. (I discuss the steps for generating your files via XDoclet later.)
A closer look into the javadoc also reveals that I used a local interface for the bean.
WebDoclet JavaDoc Class
Your next step is to create a class composed of only javadoc, specifically for use by XDoclet. Creating the class ensures that your web.xml and jboss-web.xml files are refreshed/recreated every time you run XDoclet. Create the following class under your source directory with a package name of lum.webdoclet:
package lum.webdoclet;/** * @web.ejb-ref name="ejb/Stock" * type="Session" * home="lum.stock.ejb.interfaces.StockHome" * remote="lum.stock.ejb.interfaces.Stock" * description="Reference to the Stock EJB" * @jboss.ejb-ref-jndi ref-name="ejb/Stock" * jndi-name="lum/stock/ejb/bean/Stock" */public class WebDoclet {}
Create the Façade Class
If you follow MVC, your EJB should be called from your action classes when you integrate it into a Struts framework. Looking at this application, you can see that indeed EJB creation and its method calls are performed in the StockAction
class. Though on closer inspection you’ll notice that a class called StockFacade
actually wraps the EJB. This technique is known as façade and is based on the GOF façade pattern.
Take a closer look at the GOF façade and J2EE session façade patterns. You should ostensibly use the GOF façade pattern when you create a simple interface to provide access into a complex part of an application. The session façade is fundamentally the GOF design pattern applied to EJB. Whereas this application uses a simple java class as its façade and the stateless session bean as its complex component, the session façade pattern uses a stateless session bean as its façade, which in turn usually accesses multiple entity beans. Table 1 highlights the differences between this application’s façade and the session façade.
This Application | Session Façade Pattern | |
---|---|---|
Façade | StockFacade class | Stateless Session Bean |
EJB | StockBean | Entity Bean(s) |
The following is the StockFacade
class:
package lum.stock.facade;import lum.stock.Stocks;import lum.stock.ejb.interfaces.*;import javax.naming.*;import javax.naming.InitialContext;import javax.rmi.PortableRemoteObject;import java.rmi.RemoteException;public class StockFacade { private StockHome home; public StockFacade() {} public Stocks getStockBean(String p_ticker) throws RemoteException { lookupStockBean(); Stock bean = createStockBean(); return bean.retrieveStockInfo(p_ticker); } private void lookupStockBean() { try { Context context = new InitialContext(); Object ref = context.lookup("java:/comp/env/ejb/Stock"); home = (StockHome)PortableRemoteObject.narrow(ref, StockHome.class); } catch (Exception e) { System.out.println("Lookup of java:/comp/env/ejb/Stock failed"); } } private Stock createStockBean() { Stock bean = null; try { bean = home.create(); } catch (Exception e) { System.out.println("Exception thrown on creation of bean from home interface"); } return bean; }}
You have now finished the coding portion; the rest of this article will focus on how to generate the necessary files using XDoclet, as well as packaging and deploying your application.
XDoclet to Generate Deployment Descriptors and Interfaces for StockBean
Many good tutorials out there go into further detail on XDoclet, but this article shows you how to use XDoclet only to generate your Web and EJB deployment descriptors and your interfaces for the StockBean
.
To generate these files, XDoclet takes the javadoc declared in your StockBean and uses it to generate jboss.xml, ejb-jar.xml, and the interfaces for StockBean
:
- Right click on your project StrutsEJBTutorial in the package explorer, click properties, and then click XDoclet Configurations.
- Right click in the upper white space area on the right-hand side, and click Add.
- A popup telling you to enter a configuration name will appear. Type EJB and click OK. Figure 5 shows a screenshot of what you should see.
- Make sure EJB is highlighted in the upper box, and then right click in the lower left white space. Select ejbdoclet and click OK.
- Make sure that ejbdoclet is checked, and then check the box for destDir and set the value to WEB-INF/src/java. Next, check ejbSpec and set that value to 2.0. Figure 6 shows the results.
Figure 6: Ejbdoclet Has Been Added - Right click ejbdoclet in the left white box. Click Add, choose deploymentdescriptor, and click OK. Now select deploymentdecriptor (you may have to expand the ejbdoclet node if you don’t see it), check destDir, and set the value to META-INF. See Figure 7 for the results.
Figure 7: Add the deploymentdescriptor to ejbdoclet - Right click ejbdoclet. Click Add, choose jboss, and click OK. Select jboss, check destDir, and set the value to META-INF (see Figure 8).
Figure 8: Add jboss to ejbdoclet - Right click ejbdoclet. Click Add, choose packageSubstitution, and click OK. Select packageSubstitution, check packages, and set the value to bean. Next, check substituteWith and set the value to interfaces (see Figure 9).
Figure 9: Add packageSubstitution to ejbdoclet - Right click ejbdoclet. Click Add, choose fileset, and click OK. Select fileset, make sure dir is checked, and set the value to WEB-INF/src/java. Uncheck excludes. Next, make sure includes is checked and set the value to **/*Bean.java (see Figure 10).
Figure 10: Add fileset to ejbdoclet - Right click ejbdoclet. Click Add, choose remoteinterface, and click OK. Right click ejbdoclet again, click Add, and choose homeinterface (see Figure 11). No values need to be checked or set for remoteinterface and homeinterface.
Figure 11: Add homeinterface and remoteinterface to ejbdoclet - Now click OK on the bottom right corner. Eclipse will generate an xdoclet-build.xml file. To run your XDoclet file, right click on your project StrutsEJBTutorial in the package explorer, and click Run XDoclet.
- On closer inspection, you will see that XDoclet generated both your home and remote interfaces in lum.stock.ejb.interfaces, and you have jboss.xml and ejb-jar.xml in your /META-INF directory. If you updated your XDoclet definitions, you should have jaws.xml too, but this file is not necessary for this application.
![]() | |
Figure 5: EJB Configuration for XDoclet |
Create a Merge Directory
Before you generate your Web deployment descriptors, you should create a merge directory and split up the original web.xml that came with the struts-blank.war import. To do so, create several XML files. When you run XDoclet, it will take these other XML files and re-generate web.xml. Alternatively, you can simply generate the web.xml entries in another file, and then paste them into your original web.xml. However, for a longer-term solution that eliminates the need to continually copy and paste these entries, I recommend creating the merge directory and splitting up the original web.xml:
- Create a new directory called merge under your project root.
- Create a servlet-mappings.xml file under the merge directory and enter the following:
*.do - Create a servlets.xml file under the merge directory and enter the following:
org.apache.struts.action.ActionServlet /WEB-INF/struts-config.xml 2 2 2 - Create a taglibs.xml file under the merge directory and enter the following:
/WEB-INF/struts-bean.tld /WEB-INF/struts-html.tld /WEB-INF/struts-logic.tld /WEB-INF/struts-nested.tld /WEB-INF/struts-tiles.tld - Create a welcomefiles.xml file under the merge directory and enter the following:
Create Application.xml File
You also need to deploy an application.xml file with your .ear file. Create one under your /META-INF directory:
application PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE Application1.3//EN" "http://java.sun.com/dtd/application_1_3.dtd"> Stock Application StockEJB.jar StockWeb.war /stock
Generate Web Deployment Descriptors
Now you are ready to generate web.xml and jboss-web.xml with XDoclet:
- Right click on your project StrutsEJBTutorial in the package explorer. Click properties, and then click XDoclet Configurations.
- Right click in the upper white space area on the right-hand side, and click Add.A popup telling you to enter a configuration name will appear. Type Web and click OK.
- Make sure Web is highlighted in the upper box, and right click in the lower left white space. Select webdoclet and click OK.
- Make sure that webdoclet is checked. Now check the box for destDir and set the value to WEB-INF. Next, check mergeDir and set that value to merge (see Figure 12).
Figure 12: Add webdoclet to the Web Configuration - Right click webdoclet in the left white box. Click Add, choose deploymentdescriptor, and click OK. Now select deploymentdecriptor (you may have to expand the webdoclet node if you don’t see it), check destDir, and set the value to WEB-INF. Next, check mergeDir and set that value to merge (see Figure 13).
Figure 13: Add deploymentdescriptor to the webdoclet - Right click webdoclet. Click Add, choose jbosswebxml, and click OK. Select jbosswebxml, make sure destDir is checked, and set the value to WEB-INF. Set Version to 3.0 and check it. Click OK (see Figure 14).
Figure 14: Add jbosswebxml to the webdoclet - Right click webdoclet. Click Add, choose fileset, and click OK. Select fileset, make sure destDir is checked, and set the value to WEB-INF/src/java. Uncheck excludes. Next, make sure includes is checked and set the value to lum/webdoclet/WebDoclet.java. Click OK (see Figure 15).
Figure 15: Add fileset to the webdoclet - Now, click OK at the bottom right corner. Eclipse will generate an xdoclet-build.xml file. To run your XDoclet file, right click on your project StrutsEJBTutorial in the package explorer, and then click Run XDoclet.
- You will see that XDoclet generated both your Web deployment descriptors, web.xml and jboss-web.xml, in your /WEB-INF directory. You’ll also notice that XDoclet used the various XML files in your /merge directory to recreate your original web.xml file.
Package for Deployment
Now you’re ready to package your application and deploy it to the JBoss application server. You can package your application in many ways, but this tutorial uses the packaging capability within Eclipse.
Create the EJB.jar file
- Right click on your project StrutsEJBTutorial in the package explorer, click properties, and then click Packaging Configurations.
- Right click in the large white space on the right, click Add Archive, and name the file StockEJB.jar. Click OK (see Figure 16).
Figure 16: Dialog box for Adding StockEJB.jar - Right click on StockEJB.jar and choose Add Folder. Click Project Folder, select WEB-INF/classes, and then click OK. In the Includes text box type: lum/stock/ejb/bean/*.class,lum/stock/ejb/interfaces/*.class,lum/staticvalues/*.class,lum/stock/*.class, and click OK (see Figure 17).
Figure 17: Dialog Box for Adding the WEB-INF/classes Folder - Right click on StockEJB.jar and choose Add File. Click Project Folder, and select ejb-jar.xml under the /META-INF directory. In the prefix box, type: META-INF (see Figure 18).
Figure 18: Dialog Box for Adding the ejb-jar.xml File - Right click on StockEJB.jar and choose Add File. Click Project Folder, and select jboss.xml under the /META-INF directory. In the prefix box, type: META-INF. Click OK.
Create the EJB-client.jar File
- Right click in the large white space on the right, click Add Archive, and name the file StockEJB-client.jar. Click OK.
- Right click on StockEJB-client.jar and choose Add Folder. Click Project Folder, select WEB-INF/classes, and then click OK. In the Includes text box, type: lum/stock/ejb/interfaces/*.class, and click OK.
- Right click on StockEJB-client.jar and choose Add File. Click Project Folder, and select ejb-jar.xml under the /META-INF directory. In the prefix box, type: META-INF. Click OK.
- Right click on StockEJB-client.jar and choose Add File. Click Project Folder, and select jboss.xml under the /META-INF directory. In the prefix box, type: META-INF. Click OK (see Figure 19).
Figure 19: StockEJB-client.jar Structure
Create the .war File
- Right click in the large white space on the right, click Add Archive, and name the file StockWeb.war. Click OK.
- Right click on StockWeb.war and choose Add Folder. Click Project Folder, select WEB-INF, and then click OK. In the Includes text box, type: *.xml,*.tld, and in Prefix, type: WEB-INF. Click OK (see Figure 20).
Figure 20: Dialog Box When Adding WEB-INF - Right click on StockWeb.war and choose Add File. Click Project Folder, and select index.jsp. Click OK.
- Right click on StockWeb.war and choose Add File. Click Project Folder, and select application.properties under the /WEB-INF/classes/resources/ directory. In the prefix box, type: WEB-INF/classes/resources, and click OK (see Figure 21).
Figure 21: Structure After Adding application.properties - Right click on StockWeb.war and choose Add Folder. Click Project Folder, select pages, and then click OK. In the Prefix, type: pages, and click OK.
- Right click on StockWeb.war and choose Add Folder. Click Project Folder, select WEB-INF/classes, and then click OK. In the Includes text box, type: lum/staticvalues/*.class,lum/stock/*.class,lum/stock/action/*.class,lum/stock/facade/*.class, and in the Prefix, type: WEB-INF/classes, and click OK.
- Right click on StockWeb.war and choose Add File. Click Project Folder, and type: /StockEJB-client.jar after your project name. Here, you’re telling Eclipse to package your EJB-client.jar in the .war file, even though you have not created it yet. In the prefix box, type: WEB-INF/lib and click OK (see Figure 22).
Figure 22: Manually Inputting StockEJB-client.jar - Right click on StockWeb.war and choose Add Folder. Click Project Folder, select WEB-INF/lib, and then click OK. In the Prefix, type: WEB-INF/lib, and click OK (see Figure 23).
Figure 23: Structure After Adding WEB-INF/lib
Create the .ear File
- Right click in the large white space on the right, click Add Archive, and name the file Stock.ear. Click OK.
- Right click on Stock.ear and choose Add File. Click Project Folder, and select application.xml under the /META-INF directory. In the Prefix, type: META-INF, and click OK.
- Right click on Stock.ear and choose Add File. Click Project Folder, and type: /StockEJB.jar after your project name. Again, you are telling Eclipse to package a file that you have not yet created. Click OK (see Figure 24).
Figure 24: Adding StockEJB.jar to Your .ear - Right click on Stock.ear and choose Add File. Click Project Folder, and type: /StockWeb.war after your project name. Again, you are telling Eclipse to package a file that you have not yet created. Click OK (see Figure 25).
Figure 25: Adding StockWeb.war to Your .ear - Click OK in the bottom right corner. You’ll notice that Eclipse has created a packaging-build.xml file for you.
- To run your packaging file, right click on your project StrutsEJBTutorial in the package explorer, and click Run Packaging.
Deploy the Application
You are almost there!
- Click the Run menu item, and click Debug. Click JBoss 3.2.x and then click New in the bottom left-hand corner. Under Name, type: JBoss 3.2.3. Under Home Directory, navigate to the location where you unzipped JBoss (see Figure 26).
Figure 26: A Debug Session for JBoss - Click Apply, and then Debug. This will start the JBoss server, which you can see in the Console window.
- In the Package Explorer window, right click Stock.ear, and go to Deployment -> Deploy To… . In the popup box, choose (default) and click OK. You will now see a green arrow on the Stock.ear file (see Figure 27).
Figure 27: Deploy the .ear file to Default Directory of JBoss Server - Open a browser and type in http://localhost:8080/stock/pages/stockquery.jsp.
At this point, you can see the application return its data, and you can set breakpoints in the application, including within the StockBean EJB.
Leverage Struts and EJB
You can integrate both Struts and EJB in various ways, using various tools. This tutorial has illustrated just one of the methods. Being able to integrate the two will give you a good foundation for the popular Struts architecture. Perhaps next you’d like to try your luck at building an entity bean within the framework.
If you still have problems with installation, a number of good online resources can walk you through it, including: