Wednesday, January 30, 2008

EJB Application Using Struts

by Balakrishnan

My aim is to write about EJB2.0 in JBOSS3.2 using STRUTS FRAMEWORK.

The EJB specification provides Enterprise-level services. Typical services provided by the EJB Container are as follows.

1.Persistence
2.Declarative transactions
3.Security
4.Connection pooling
5.Support for messaging services

The most famous EJB-Servers in the market are:

BEA ..WebLogic Server
JBoss Application server
IBM … .WebSphere-5
Oracle AS

Of these , JBoss 3.2 & 4 are OpenSource and Free.
JBOSS application sever has become recognized leader in the java application server market and to date is the major application server.

Different kinds of Enterprise Beans are
1. Session Bean
2. Entity Bean
3. MessageDriven Bean (MDB)


Session Bean
Session Bean can be defined as function bean called in RMI-IIOP style from Enterprise container. Two types of session bean are stateless session bean, stateful session bean.
A stateless session bean does not maintain conversation state but stateful session bean maintains conversation state

Entity Bean
Entity Bean is a value bean with setter and getter methods representing one row of data in a table, invoked in RMI style from Enterprisecontainer in Enterprise data store. Two types of Entity Beans are CMP (Container Managed Persistence), BMP(Bean Managed Persistence). In CMP, persistence code need not be written by the programmer. But In BMP Persistence code has to be written by the programmer .CMP is not satisfactory for really complex enterprise situations. ( CMP is an ORM technology ( Object-Relational Mapping Technology … like Hibernate. and Hibernate is considered to be better than CMP).

Message Driven Bean
Session Bean and Entity bean are based on RPC mechanism. But,
Message Driven Bean is based on Asynchronous messaging . MDB have no conversational state with the client and can be pooled like stateless session bean. Unlike other types of EJB, MDB have no home or remote interfaces.
Messaging is like email whereas RPC is like phone call. In enterprise environment there will be heavy traffic and RPC may fail to create connection. In such situations messaging is more reliable.

What is Struts?

Struts is a very famous ready made framework which implements MVC (Model View Controller) Architecture. It is open source and free. Struts frame work was developed by Craig MacLanahan in 2002 subsequently handed over to Apache Jakarta projects group. Struts is a frame work for building really complex Enterprise level applications .

Struts provide its own Controller component and integrates with other technologies to provide the Model and the View. For the Model, Struts can interact with standard data access technologies, like JDBC and EJB, as well as most any third-party packages, like Hibernate, iBATIS, or Object Relational Bridge. For the View, Struts works well with JavaServer Pages, including JSTL and JSF, as well as Velocity Templates, XSLT, and other presentation systems

Purpose of the Struts

When the user fills the form and submits the form, if the values entered by the user are wrong then the user must be presented with the samepage with suitable error messages and the values already entered by the user should be preserved.
If there is no error, ( validation test is passed), then the business logic is executed..
Installation

Struts1.1 is zip file. Extract it. In Struts1.1 folder, there is a folder name called lib. There are many war files.
One of the war file names, is struts-blank.war.
Copy that struts-blank.war file to c:\tomcat5\webapps. Start the tomcat server. Now struts-blank folder is created .
Copy that struts-blank folder and paste it in desktop. Rename the folder as ‘ bala ’ ..
Now, place that folder( ‘ bala ’ ) in c:\tomcat5\webapps.( Assuming that we have installed tomcat5 in C drive). Here ‘ bala ’ folder is our context. Restart the tomcat server.. Open the Browser, type the URL as ‘ http://localhost:8080/bala. Now the ‘ welcome ’ page will appear. This means that our installation process is correct.
We require jboss3.2 and JDK1.4.2 for developing this exercise
-----------------------------------------------------------------------------------------------------------
The following lesson illustrates the method of connecting to a stateless session bean in jboss3.2 server through a Struts-based program.
We have installed jboss3.2 and JDK1.4.2 in D:\drive . Create a folder ‘ strutsejbdemo ’ in D drive. This is our working directory.
We have already created the context ‘ bala ’ in tomcat5 as mentioned above. .
Copy that ‘ bala ’ context folder to E:\jboss32\server\default\deploy as bala.war
In this lesson, we have created two packages namely demo and demo1. For this we have created the two folders namely demo and demo1 in D:\jboss32\server\default\deploy\bala.war\web-inf\classes to copy the class files

D:\>cd strutsejbdemo
D:\strutsejbdemo>
When we use struts the concept of package is very important.
D:\strutsejbdemo>md demo1
Here demo1 is our package
D:\strutsejbdemo>cd demo1
Next we create a batch file to set path and classpath
D:\strutsejbdemo\demo1>edit setpath.bat
set path=c:\windows\system32;d:\jdk1.4.2\bin;d:\bea\weblogic700\server\bin
( I am using WindowsXP. If you are using Windows-2000, the path to edit program should be : c:\winnt\system32.)


Usually we give a class path to working directory. When we use package we giveclasspath to parent directory. This is very important.
D:\strutsejbdemo\demo1\edit setcpath.bat
set classpath=d:\ejbdemo;d:\jboss32\client\Log4j.jar;d:\jboss32\client\jboss-j2ee.jar;d:\jboss32\client\jboss-common-client.jar;d:\jboss32\client\jnp-client.jar;d:\jboss32\client\jboss-system-client.jar;d:\jboss32\client\jboss-client.jar;d:\jboss32\client\jbosssx-client.jar;d:\jboss32\client\jboss-transaction-client.jar;


After creating batch files in the working folder,
Give the following command:
d:\strutsejbdemo\demo1>setpath
This will set the path for the window
d:\strutsejbdemo\demo1>setcpath


( This will set the classpath for the window ).
Checkup as follows:
D:\strutsejbdemo\demo1>path
D:\strutsejbdemo\demo1>echo %classpath%

Now edit the following files

1.cityguide.java
2.ciyRemote.java
3.cityHome.java
4.cityBean.java


D:\strutsejbdemo\demo1>edit cityguide.java
package demo1;
import java.util.*;
public class cityguide
{
public String listcities(String a)
{
Vector vector1=new Vector();
if(a.equals("TAMILNADU"))
{
vector1.addElement("Madras");
vector1.addElement("Trichy");
vector1.addElement("Madurai");
}
if(a.equals("KERALA"))
{
vector1.addElement("Cochin");
vector1.addElement("Quicon");
vector1.addElement("Trivandrum");
}
if(a.equals("KARNATAKA"))
{
vector1.addElement("Mysore");
vector1.addElement("Bangalore");
vector1.addElement("Hubli");
}
String r="";
int n=vector1.size();
for(int j=0;j<n;j++)
{
String v=(String)vector1.elementAt(j);
r=r+v+"<br>";
}
return r;
}
}
//----------------------------------------------------------------------------------------------------------
D:/strutsejbdemo/demo1>edit cityRemote.java
package demo1;
import javax.ejb.*;
import java.rmi.*;
public interface cityRemote extends EJBObject
{
public String showcities(String s)
throws RemoteException;
}
//----------------------------------------------------------------------------------------------------------
D:/strutsejbdemo/demo1>edit cityHome.java
package demo1;
import javax.ejb.*;
import java.rmi.*;
public interface cityHome extends EJBHome
{
public cityRemote create()
throws CreateException, RemoteException;
}
//---------------------------------------------------------------------------------
D:/strutsejbdemo/demo1>edit cityBean.java
package demo1;
import javax.ejb.*;
public class cityBean implements SessionBean
{
public String showcities(String s)
{
cityguide guide1= new cityguide();
String r = guide1.listcities(s);
return r;
}
public void ejbCreate() {}
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(SessionContext sc) {}
}
//----------------------------------------------------------------------------------------------------------
We have already set the specified path and classpath. Compile all the above files
D:\strutsejbdemo\demo1>javac *.java
D:\ejbstrutsdemo\demo1>copy *.class d:\jboss32\server\default\deploy\bala.war\web-inf\classes\demo1
D:\strutsejbdemo>demo1\cd..
D:\strutsejbdemo>md META-INF
When we use package META-INF folder is created in parent folder. It should be in uppercase ie.,META-INF not meta-inf
Now edit the ejb-jar.xml and jboss.xml in META-INF
D:\strutsejbdemo\META-INF>edit ejb-jar.xml
<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC
"-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN"
"http://java.sun.com/dtd/ejb-jar_1_1.dtd">
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>city</ejb-name>
<home>demo1.cityHome</home>
<remote>demo1.cityRemote</remote>
<ejb-class>demo1.cityBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
//--------------------------------------------------------------------------------------------------
D:\strutsejbdemo\META-INF >edit jboss.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss>
<enterprise-beans>
<session>
<ejb-name>city</ejb-name>
<jndi-name>cityJndi</jndi-name>
</session>
</enterprise-beans>
</jboss&gt
;
//----------------------------------------------------------------------------------
Now, cd back to D:\strutsejbdemo\
Create the jar file as follows:
D:\strutsejbdemo\>jar cf city.jar demo1\*.class META-INF\*.xml
Carefully note that the jar file is created in parent directory.
Now, we copy the jar file to the jboss folder as shown below.
D:\strutsejbdemo> copy city.jar D:\jboss32\server\default\deploy
Start the jboss server as shown below
Go to new window to start the jboss server.
D:\jboss32\bin\>set JAVA_HOME=D:\JDK1.4.2
D:\jboss3.2\bin\>run
The server will start now. If our jar file namely city.jar is deployed correctly deployed city.jar message will appear in the server.
The development of the EJB and its deployment in JBOSS server is over.
//----------------------------------------------------------------------------------------------------------Now we develop the Struts client program for the above EJB.
D:\ejbstrutsdemo>md demo
D:\ejbstrutsdemo>demo
D:\strutsejbdemo\demo>edit setcpath.bat
set classpath=%classpath%;d:\strutsejbdemo;e:\struts1.1\lib\struts.jar;
D:\strutsejbdemo\demo>setcpath
We use the following six files, in this demo package,

1. balaSubmit.jsp
2. balaForm.java(derived from ActionForm)
3. balaAction.java(derived from Action)
4. balahelper.java ( a utility bean)
5. balaresult.java ( a value bean)
6. balaOutput.jsp


( besides the web.xml ,struts-config.xml files & application.properties file)
D:\ejbstrutsdemo\demo1>edit balaSubmit.jsp
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
<body bgcolor=cyan>
<center>
<h1>STRUTS CLIENT FOR STATELESS</h1>
</center>
<html:errors/>
<html:form action="bala"
name="balaForm"
type="demo.balaForm" >
State <br>
<h1>Whick State Do you want to tour?</h1>
<h2>TAMILNADU?KERALA?KANADA?</h2>
<html:text property="state" />
<br>
<html:submit />
</html:form>
</body>
</html>
//----------------------------------------------------------------------------------------------------------
When the user submits the balaSubmit.jsp, the formbean is automatically filled up with the values from the jsp-page and the flow goes to the ActionServlet.
<html:errors/> tag is used to displaying error messages.

D:\strutsejbdemo\demo>edit balaForm.java

package demo;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class balaForm extends ActionForm
{
String state =null;
public String getState()
{
return state;
}
public void setState(String a)
{
state=a;
}
public void reset(ActionMapping mapping,
HttpServletRequest request)
{
state=null;
}
public ActionErrors validate (ActionMapping mapping, HttpServletRequest request)
{
ActionErrors errors = new ActionErrors();
if( state.length()= =0)
{
errors.add("state", new ActionError("errors.nullstate"));
}
return errors;
}
}
//----------------------------------------------------------------------------------------------------------
D:\strutsejbdemo\demo>edit balahelper.java
package demo;
import java.util.*;
import javax.ejb.*;
import javax.rmi.*;
import javax.naming.*;
import java.rmi.*;
import java.io.*;
public class balahelper
{
public String callejb(String s)
{
String r;
try
{
System.out.println("Please Wait...");
Properties props=new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jnp.interfaces.NamingContextFactory");
props.put(Context.PROVIDER_URL,"localhost");
props.put(Context.URL_PKG_PREFIXES,
"org.jboss.naming:org.jnp.interfaces");
Context context=new InitialContext(props);
System.out.println("Connection OK");
demo1.cityHome home=
(demo1.cityHome)context.lookup("cityJndi");
System.out.println("HOME LOCATED");
demo1.cityRemote remote= home.create();
System.out.println("REMOTE READY");
r=remote.showcities(s);
}
catch(Exception e1){ r=""+e1; }
return r;
}
}
//-------------------------------------------------------------------------------------------------
D:\strutsejbdemo\demo>edit balaresult.java
package demo;
public class balaresult
{
String value;
public balaresult()
{
value=" ";
}
public String getValue(){
return value;
}
public void setValue(String v){
value=v;
}
}
//----------------------------------------------------------------------------------------------------
The Action Class is part of the Model and is a wrapper around the business logic. The purpose of Action Class is to translate the HttpServletRequest to the business logic
In our case, the action class instance is using a helper to perform the business logic. This is the bettter and recommended practice.

D:\strutsejbdemo\demo>edit balaAction.java

package demo;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class balaAction extends Action
{
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
balaForm balaform =(balaForm) form;
String a = balaform.getState();
if(a.equals("TAMILNADU") a.equals("KERALA") a.equals("KARNATAKA"))
{
balahelper helper = new balahelper();
String r = helper.callejb(a);
balaresult kr = new balaresult();
kr.setValue(r);
String m = kr.getValue();
System.out.println(m);
HttpSession session= request.getSession();
session.setAttribute("result",kr);
return (mapping.findForward("success"));
}
else
{
ActionErrors errors = new ActionErrors();
errors.add (ActionErrors.GLOBAL_ERROR, new ActionError("errors.wrongname"));
saveErrors(request,errors);
return(mapping.findForward("failure"));
}
}
}

----------------------------------
------------------------
D:\strutsejbdemo\demo>edit balaOutput.jsp
<html>
<body bgcolor=orange>
<h1>
<jsp:useBean id="result" scope="session" class="demo.balaresult" />
<br>
<jsp:getProperty name="result" property="value" />
</h1>
</body>
</html>

Now we are ready to compile the above programs.class path are already specified

D:\strutsejbdemo\demo>javac *.java
D:\strutsejbdemo\demo>copy *.jsp
d:\jboss32\server\default\deploy\bala.war
D:\strutsejbdemo\demo>copy *.class
d:\jboss32\server\default\deploy\bala.war\web-inf\classes\demo
The deployment process is over
Go to another window. cd to
D:\jboss32\server\default\deploy\bala.war\web-inf>edit struts-config.xml


In the struts-config.xml file, we make two entries. One entry is for the instance of balaForm and the other entry is for the instance of balaAction class.
------------------------------------------
( this is the part dealing with the formbean)
<form-bean
name="balaForm"
type="demo.balaForm" />
The next segment of mapping in
struts-config.xml deals with the action mapping for QueryAction.
<action path="/bala"
type="demo.balaAction"
name="balaForm"
input="/balaSubmit.jsp"
scope="session"
validate= " true " >
<forward name="success"
path="/balaOutput.jsp"/>
<forward name="failure"
path="/balaSubmit.jsp"/>
</action>
There is a file known as 'Application.properties' in 'WEB-INF\classes\resources' and at the end of that file we will add the following lines.
errors.nullstate=<li><h1> ENTER YOUR STATE<h1></li>
errors.wrongname=<li><h1>SORRY … .., SERVICE NOT PROVIDED FOR THIS STATE</h1> </li>
Therefore, we will get the specified error messages.
Start the jboss server as usual.
Open the browser and type URL as http://localhost:8080/bala/balaSubmit.jsp
Type the name of the state ( TAMILNADU/KERALA/KARNATAKA)in the
text box & then click ‘ submit ’ . If the name of the state is correct then result will be displayed. Otherwise the home page remains with the values entered and also with the error message. As the main purpose of this note is just to explain how to connect to stateless ejb using Struts, I am leaving out Validation Framework details.
Acknowledgements:


The following articles from back issues of DeveloperIQ.
1) Packaged EJB by Farihah Noushene.
2) Developing EJB in Weblogic 7 by R.S.Ramaswamy
**************************************************************************