Java Tutorial - Java Scipt : Running the TestUserEJB Application

Java Tutorial - Java Scipt :

Running the TestUserEJB Application


The application can be deployed into JBoss using the deploy task in the build.xml file. The application can then be executed with the following URL: http://localhost:8080/ch14/servlet/TestUserEJB The response should consist of the following lines:

Hello:Hello World!
 Name:John Doe 0000000-000000-00000000-0-00000000-1

Java Tutorial - Java Scipt : Compiling the TestUserEJB Application

Java Tutorial - Java Scipt :

Compiling the TestUserEJB Application


The following build.xml file can be used with Ant to compile the application and create a .war file for deployment into JBoss.

<?xml version=”1.0” encoding=”UTF-8”?>
<project basedir=”.” default=”compile” name=”ch14”>
<property name=”app.name” value=”ch14”/>
<property name=”jboss.home”
value=”C:/openjava/jboss-3.0.6_tomcat-4.1.18”/>
<property name=”jboss.deploy”
value=”${jboss.home}/server/default/deploy”/>
<property name=”lib.dir” value=”${jboss.home}/client”/>
<path id=”build.classpath”>
<fileset dir=”${lib.dir}”>
<include name=”*.jar”/>
</fileset>
</path>
<target name=”init”>
</target>
<target depends=”init” name=”compile”>
<javac
classpathref=”build.classpath”
debug=”true”
deprecation=”true”
destdir=”./WEB-INF/classes”
srcdir=”./WEB-INF/classes”>
</javac>
</target>
<target depends=”compile” name=”war”>
<war destfile=”${app.name}.war”
update=”no”
excludes=”build.xml”
webxml=”./WEB-INF/web.xml”>
<fileset dir=”.”>
<include name=”**/*.jar”/>
<include name=”**/*.class”/>
<include name=”**/*.java”/>
<include name=”**/*.xml”/>
<exclude name=”**/web.xml”/>
</fileset>
</war>
</target>
<target depends=”war” name=”all”/>
<target depends=”war” name=”deploy”>
<copy file=”${app.name}.war” todir=”${jboss.deploy}”/>
</target>
<target depends=”war” name=”undeploy”>
<delete file=”${jboss.deploy}/${app.name}.war”/>
</target>
</project>

The .war target compiles any code that still needs to be compiled and builds the .war file. Make certain you edit the jboss.home and app.name properties near the top of the file to reflect the values for your system. You can include the Java source code in your .war files so that they can be edited in place. If you do not want to include the source code, then remove the line in the .war task that reads:
<include name=”**/*.java”/>

Java Tutorial - Java Scipt : The TestUserEJB Servlet

Java Tutorial - Java Scipt :

The TestUserEJB Servlet


The next step is to create a servlet that uses the UserDelegate class. The source code for the servlet follows:

import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import com.oldfriends.user.*;
import javax.ejb.*;
public class TestUserEJB extends HttpServlet
{
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException
{
PrintWriter out = response.getWriter();
UserDelegate ud;
try
{
ud = new UserDelegate();
UserDTO udata =
ud.getUserByUserid(“0000000-000000-00000000-0-00000000-1”);
out.println(“Hello:”+ud.getHello());
out.println( “Name:”+
udata.getFirstName() + “ “ +
udata.getLastName()+” “+udata.getUserid());
}
catch( Exception e )
{
e.printStackTrace(out);
}
}
}

Note that the servlet has no knowledge that the actual implementation of UserDelegate occurs via an EJB.


Java Tutorial - Java Scipt : Rebuilding the .jar File

Java Tutorial - Java Scipt :

Rebuilding the .jar File


We do not need to make any changes to the existing Ant script to rebuild the .jar file. It will happily build the new EJB and install the new .jar file by executing the following command: ant deploy If nothing goes wrong, the output will be similar to what we saw earlier when we compiled and deployed the bean under the Compiling the Bean
section.

Java Tutorial - Java Scipt : Building the Test Client

Java Tutorial - Java Scipt :

Building the Test Client


We will add a new method to our test client to test the new session bean, as shown in the following code:
public void userSessionTest(
{
UserSessionRemote remote;
UserSessionHome home;
System.out.println(“userSessionTest:”);
try
{
System.out.println( “Getting Home Interface”);
home = (UserSessionHome)getHomeInterface(
“ejb/UserSession”,
com.oldfriends.session.UserSessionHome.class);
System.out.println( “Getting Remote Interface”);
remote = home.create();
System.out.println(remote.toString());
System.out.println( “Calling getHello”);
System.out.println(“Hello:”+remote.getHello());
System.out.println( “Retrieving Records”);
System.out.println( “getUserByUserid”);
UserDTO udata =
remote.getUserByUserid(“0000000-000000-00000000-0-00000000-1”);
System.out.println( “Name:”+
udata.getFirstName() + “ “ +
udata.getLastName()+” “+udata.getUserid());
System.out.println( “getUserByLogin”);
udata = remote.getUserByLogin(“jsmith”);
System.out.println( “Name:”+
udata.getFirstName() + “ “ +
udata.getLastName()+” “+udata.getUserid());
System.out.println( “Update User”);
udata.setFirstName(“NotJack”);
remote.updateUser(udata);
udata = remote.getUserByLogin(“jsmith”);
System.out.println( “Name:”+
udata.getFirstName() + “ “ +
udata.getLastName()+” “+udata.getUserid());
System.out.println( “Add User”);
udata.setFirstName(“One”);
udata.setLastName(“LastName”);
udata.setMi(“Z”);
udata.setMaidenName(“”);
udata.setLoginId(“lgid”);
udata.setPassword(“somepwd”);
udata.setEmail(“email@foo.bar”);
udata = remote.addUser(udata);
System.out.println( “Name:”+
udata.getFirstName() + “ “ +
udata.getLastName()+” “+udata.getUserid());
remote.remove();
}
catch( Exception ex )
{
System.err.println(
“userSessionTest: Caught an unexpected exception!”);
ex.printStackTrace();
}
finally
{
remote = null;
home = null;
System.out.println( “userSessionTest: Finally”);
}
}
The new userSessionTest method is similar to the userEntityTest method covered earlier, except that it uses the UserDTO object to move user data between the client the EJB container. We demonstrate the session bean methods for retrieving users, updating users, and adding a user to the system. We also need to make a change to the main method so that our new method is executed. The new main method follows:
public static void main(String[] args)
{
UserClient uc = new UserClient();
uc.userEntityTest();
uc.userSessionTest();
}
We can execute this from Ant without any further changes. Use the following command to run this by using Ant:
ant run-test The output will be similar to the output previously observed for the entity  bean under the Testing the Bean section.
.

Java Tutorial - Java Scipt : Changing the jboss.xml File

Java Tutorial - Java Scipt :

Changing the jboss.xml File


Because this is not an entity bean, we do not need to modify the jbosscmpjdbc. xml file. The final changes we need to make for deploying our session bean are made to the jboss.xml file. The change is the four following lines:

<session>
<ejb-name>UserSession</ejb-name>
<jndi-name>ejb/UserSession</jndi-name>
</session>

These lines should be added immediately after the </entity> tag that we put into the file earlier.

Java Tutorial - Java Scipt : Creating a Deployment Descriptor

Java Tutorial - Java Scipt :

Creating a Deployment Descriptor

Now, we need to modify the EJB deployment descriptor ejb-jar.xml to add our new session bean. We will start with the file we created earlier, and this time just focus on the additions needed to add our session bean. The first part of this addition is shown below. It should be added immediately after the closing

</entity> tag:
<session>
<display-name>UserSession</display-name>
<ejb-name>UserSession</ejb-name>
<home>com.oldfriends.session.UserSessionHome</home>
<remote>com.oldfriends.session.UserSessionRemote</remote>
<ejb-class>com.oldfriends.session.UserSessionEJB</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>

The values here are almost identical to those we have already discussed for the entity bean. There are a couple of differences here. The <session-type> can be either Stateless or Stateful. Ours is a stateless bean. The transaction
type is set for the container to manage transactions. The next section, which follows, is the <ejb-local-ref> element, which is needed so that we can find the entity bean:

<ejb-local-ref>
<ejb-ref-name>ejb/LocalUserEJB</ejb-ref-name>
<ejb-ref-type>Entity</ejb-ref-type>
<local-home>com.oldfriends.entity.UserLocalHome</local-home>
<local>com.oldfriends.entity.UserLocal</local>
<ejb-link>UserEJB</ejb-link>
</ejb-local-ref>

The <ejb- ref-name> value should be set to the JNDI name that is used in our code to retrieve the LocalHome interface of the entity bean. The <ejb-link> provides the connection between this JNDI name and the entry for the bean. This will be used in the jboss.xml file to complete the JNDI mapping. The <ejb-ref-type> tells the container whether we are referencing an entity bean or a session bean. The <local-home> and <local> elements provide the fully qualified class names for the LocalHome and local interfaces for the bean we are referencing. The next section is also a reference, but it is a resource reference that will be used to get the DataSource from the container, as you can see in the following code:

<resource-ref>
<description>DataSource for oldfriends database</description>
<res-ref-name>java:/jdbc/MySqlDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Sharable</res-sharing-scope>
</resource-ref>
</session>

The <res-ref-name> is the JNDI name that we use in our code to get the DataSource. The <res-type> element provides the fully qualified class name of the class that is returned by the lookup. The <res-auth> element says that the container has the responsibility for providing username and password needed to generate connections from the DataSource. Finally, <res-sharing-scope> says that this resource is sharable with other beans. The </session> tag ends the changes to the ejb-jar.xml file.

Java Tutorial - Java Scipt : The Remote Interface

Java Tutorial - Java Scipt :

The Remote Interface


The code remote interface is shown below. It exposes the methods of the EJB for access by the client:
package com.oldfriends.session;

import com.oldfriends.user.UserDTO;
import java.rmi.RemoteException;
import javax.ejb.*;
public interface UserSessionRemote extends javax.ejb.EJBObject
{
public String getHello()
throws RemoteException, EJBException;
public UserDTO getUserByUserid( String userid )
throws RemoteException, EJBException;
public UserDTO getUserByLogin( String login)
throws RemoteException, EJBException;
public UserDTO getUserByEmail( String login)
throws RemoteException, EJBException;
public UserDTO addUser( UserDTO user )
throws RemoteException, EJBException;
public void updateUser( UserDTO user )
throws RemoteException, EJBException;
public UserDTO[] getUsersByYear( int year )
throws RemoteException, EJBException;
public UserDTO[] getAllUsers()
throws RemoteException, EJBException;

Java Tutorial - Java Scipt : The Home Interface

Java Tutorial - Java Scipt :

The Home Interface


The following code is the home interface for our session bean. This will be used to create and return an instance of the remote interface to the client: package com.oldfriends.session;

import com.oldfriends.session.UserSessionRemote;
import java.rmi.RemoteException;
import javax.ejb.*;
public interface UserSessionHome extends EJBHome
{
UserSessionRemote create() throws RemoteException, CreateException;
}
The only method we add here is the create method.

Java Tutorial - Java Scipt : Locating Resources

Java Tutorial - Java Scipt :

Locating Resources


The ResourceLocator class provides a place to put the code that is used to look up resources in the system. Often resources only need to be looked up once and can be cached for subsequent uses. The ResourceLocator is designed so it can be used by many classes, and it caches the things that it can cache. The source code for the ResourceLocator is provided below: package com.oldfriends.utils;

import java.sql.*;
import javax.ejb.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import javax.sql.DataSource;
public class ResourceLocator
{
private static Context ctx;
private static DataSource datasource;
private static final String DSNAME = “MySqlDS”;
public static Context getInitialContext()
throws NamingException, ClassCastException
{
Context myctx;
if( ResourceLocator.ctx == null )
{
myctx = new InitialContext();
ResourceLocator.ctx = myctx;
}
else
myctx = ResourceLocator.ctx;
return myctx;
}
public static EJBHome getLocalHomeInterface(String jndiName)
throws NamingException, ClassCastException
{
Context myctx = ResourceLocator.getInitialContext();
EJBHome home = (EJBHome)myctx.lookup(jndiName);
return home;
}
public static EJBHome getHomeInterface(
String jndiName, Class theHomeClass )
throws NamingException, ClassCastException
{
EJBHome home;
Context myctx = ResourceLocator.getInitialContext();
Object obj = myctx.lookup(jndiName);
home = (EJBHome)PortableRemoteObject.narrow( obj, theHomeClass );
return home;
}
public static DataSource getDataSource( String jndiName )
throws NamingException
{
DataSource ds = null;
if( ResourceLocator.ctx == null )
{
ResourceLocator.ctx = new InitialContext();
}
ds = (DataSource)ResourceLocator.ctx.lookup(jndiName);
return ds;
}
public static Connection getConnection()
throws NamingException, SQLException
{
Connection conn;
if(datasource==null)
{
datasource = ResourceLocator
.getDataSource(ResourceLocator.DSNAME);
}
conn = datasource.getConnection();
return conn;
}
}

The ResourceLocator shown here is a very simple, almost minimalist, one. It provides methods to:

·         Retrieve and cache the initial context
·         Look up and convert LocalHome interfaces
·         Look up and convert home interfaces
·         Look up and cache DataSources
·         Get DataBase connections

Using a ResourceLocator often provides for more efficient access to resources and minimizes the knowledge needed to access the resources in various classes. Use of a ResourceLocator is considered to be a J2EE best practice.

Java Tutorial - Java Scipt : Creating a Session Façade

Java Tutorial - Java Scipt :

Creating a Session Façade


The session facade is a primary design pattern for enterprise Java development. In general, the facade pattern presents a simpler interface to a complex set of underlying interfaces. The session facade can improve performance in distributed systems. Facades are normally course grained; for example, instead of making many small network round trips to read each field of an entity bean a session facade bundles the fields up into a value bean or DTO for single network transfer. The facade can also represent a single entry point for accessing all of the data related to a particular domain object. In our case, all of the information that can be tied to a user record can be made accessible via the facade. As the underlying application becomes more complex, the facade can remain fairly simple from the client’s perspective. The facade also acts as an adapter layer between the client programs and the underlying business components. As the underlying infrastructure changes the clients are only dependent on the facade remaining the same. Our facade is a stateless session bean that accesses and uses the entity bean we have just created to provide clients with access to the information about users. This information is not necessarily limited to data in the user table. As the system is expanded, we should be able to use this session bean to retrieve information that is stored throughout the database. Following is the source code for our session bean: package com.oldfriends.session;

import com.oldfriends.entity.UserLocal;
import com.oldfriends.entity.UserLocalHome;
import com.oldfriends.user.UserDTO;
import com.oldfriends.utils.*;
import java.lang.ClassCastException;
import javax.ejb.*;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;
public class UserSessionEJB implements javax.ejb.SessionBean
{
protected UserLocalHome userHome = null;
protected SessionContext sessionCtx = null;
public UserSessionEJB() throws EJBException
{
}
public String getHello() throws EJBException
{
return “Hello from UserSessionEJB”;
}
public UserDTO getUserByUserid(String uid)
throws EJBException
{
UserLocal lu;
UserDTO user;
try
{
UserLocalHome lh = lookupUserLocalHome();
lu = lh.findByPrimaryKey(uid);
return buildUserBean( lu );
}
catch(FinderException fe )
{
throw new EJBException( “getUser: Could not findkey(“+uid+”)”,fe);
}
catch(Exception e)
{
throw new EJBException( “getUserByUserid: UID=”+uid ,e);
}
// return buildUserBean( lu );
}
public UserDTO getUserByLogin( String login )
throws EJBException
{
UserLocal lu;
try
{
UserLocalHome lh = lookupUserLocalHome();
lu = lh.findByLoginId(login);
}
catch(FinderException fe )
{
throw new EJBException( “getUser: Could not findkey(“
+ login
+ “)”,fe);
}
return buildUserBean( lu );
}
public UserDTO getUserByEmail( String email )
throws EJBException
{
UserLocal lu;
try
{
UserLocalHome lh = lookupUserLocalHome();
lu = lh.findByEmail(email);
}
catch(FinderException fe )
{
throw new EJBException( “getUser: Could not findkey(“
+ email
+ “)”,fe);
}
return buildUserBean( lu );
}
private UserDTO buildUserBean( UserLocal lu )
{
UserDTO u = new UserDTO();
u.setFirstName(lu.getFirstName());
u.setLastName(lu.getLastName());
u.setMi(lu.getMi());
u.setMaidenName(lu.getMaidenName());
u.setGradYear(lu.getGradYear());
u.setLoginId(lu.getLoginId());
u.setPassword(lu.getPassword());
u.setEmail(lu.getEmail());
u.setUserid(lu.getUserid());
return u;
}
public void updateUser( UserDTO user )
{
UserLocal lu;
try
{
UserLocalHome lh = lookupUserLocalHome();
lu = lh.findByPrimaryKey(user.getUserid());
setUser( user, lu );
}
catch(FinderException fe )
{
throw new EJBException(
“setUser: Could not findkey(“+user.getUserid()+”)”,fe);
}
catch( Exception ex )
{
throw new EJBException(
“updateUser: Unexpected Exception “,ex);
}
}
public UserDTO addUser( UserDTO user )
{
UserLocal lu;
try
{
UserLocalHome lh = lookupUserLocalHome();
lu = lh.create(user);
}
catch(CreateException cx )
{
throw new EJBException(
“addUser: could not create user”, cx);
}
return buildUserBean( lu );
}
private void setUser( UserDTO u, UserLocal lu)
throws EJBException
{
lu.setFirstName(u.getFirstName());
lu.setLastName(u.getLastName());
lu.setMi(lu.getMi());
lu.setMaidenName(u.getMaidenName());
lu.setGradYear(u.getGradYear());
lu.setLoginId(u.getLoginId());
lu.setPassword(u.getPassword());
lu.setEmail(u.getEmail());
}
private UserLocalHome lookupUserLocalHome()
throws EJBException
{
UserLocalHome home;
if( userHome != null)
return userHome;
try
{
Context ctx = ResourceLocator.getInitialContext();
home = (UserLocalHome)ctx.lookup(“ejb/LocalUserEJB”);
userHome = home;
}
catch( NamingException ne )
{
throw(
new EJBException(“UserSessionBean: Problem finding User EJB”, ne)
);
}
catch( ClassCastException cce )
{
throw(new EJBException(“UserSessionBean: Class Cast Fail”, cce));
}
catch( Exception cce )
{
throw new EJBException(
“lookupUserLocalHome: unexpected exception:”, cce);
}
return home;
}
public UserDTO[] getUsersByYear( int year )
throws EJBException
{
return null;
}
public UserDTO[] getAllUsers()
throws EJBException
{
return null;
}
public void ejbCreate()
{
}
public void ejbActivate()
throws javax.ejb.EJBException, java.rmi.RemoteException
{
}
public void ejbPassivate()
throws javax.ejb.EJBException, java.rmi.RemoteException
{
}
public void ejbRemove()
throws javax.ejb.EJBException, java.rmi.RemoteException
{
}
public void setSessionContext(SessionContext sc)
throws javax.ejb.EJBException, java.rmi.RemoteException
{
sessionCtx = sc;
}
}

This should be placed in the com.oldfriends.session directory of our project. The first interesting method here is getHello(). getHello() is used here as an aid to troubleshooting. This method should always work unless there is something wrong with your deployment. There are several private methods here that perform useful work for the bean. The private setUser() method sets the fields of a UserEJB entity bean from a User DTO object. The buildUserBean method does the opposite: it builds the UserDTO based on the contents of a UserEJB instance. The lookup UserLocalHome() method does a context lookup once and then stores the home interface for subsequent use. It uses a utility class to provide it with the InitialContext. We will look at this class after the current discussion.
The three methods are


·         getUserByUserid
·         getUserByLogin
·         getUserByEmail

These methods are all used to retrieve individual records from the user table. The record is copied into a UserDTO instance and returned to the client. The attributes of this UserDTO object can be modified, and then the object can be sent to the update user method, which retrieves the matching user record and updates it in the database. The addUser method accepts a UserDTO object and creates a new record in the database. The method returns the new record, which makes the primary key available to the client. Two methods are provided to return arrays of UserDTO objects. The first, getUsersByYear() returns an array of all of the users that share the same graduating class as passed as an argument. This method does not use the user entity bean. Instead, it performs a query directly against the MySql DataSource and converts the records in the resulting recordset to an array of UserDTO objects. This array of object is returned. getAllUsers is similar, except that it returns the entire user table as an array of UserDTO objects. The reason for doing direct queries is that for this type of data the direct query is normally more efficient than a set of individual queries on the entity beans. The rest of the methods are standard EJB life-cycle methods.