EJB – 2 Creating an entity bean

This example is deprecated.

Note that what I have described is creation and deployment of an entity bean on Jboss. For other Application Servers, the configuration process might change and EJB lookup code using JNDI as well as data source lookups might vary. Jboss mostly has manual configurations so when using an IDE such as Eclipse, the data source and other configurations might prove to be much simpler. Cheers!

For creating the entity bean, we need to first create a database table.
I am using MySQL Server 4.1 with username and password: admin, admin. The driver used is mysql-connector-java-3.1.8-bin.jar.
The entity used in this example uses a table called AUTHORS in database AUTHORS which has two fields ISBN_CODE and AUTHOR.
Here are the scripts to create the database:

--user=root mysql
GRANT ALL PRIVILEGES ON *.* TO 'admin'@'localhost' IDENTIFIED BY 'admin' WITH GRANT OPTION;
create database AUTHORS;
use AUTHORS;
CREATE TABLE authors (ISBN_CODE varchar(10) NOT NULL default '0',AUTHOR varchar(30) default NULL,PRIMARY KEY  (ISBN_CODE)) ;
insert into authors (ISBN_CODE,AUTHOR )values("1e","mattiz");
---------------------------------------------------------------
| Field               | Type           | Null    | Key | Default |
----------------------------------------------------------------
| ISBN_CODE           | varchar(10)    |         | PRI | 0       |
| AUTHOR              | varchar(30)    | YES     |     | NULL    |
---------------------------------------------------------------

Here are steps how to configure a mySQL datasource in Jboss.:
1.copy mysql-connector-java-3.1.8-bin.jar and aspectjrt.jar to jboss’s lib folder
2.Add the following to login-config.xml in jboss’s conf folder

<application-policy name="mysqlDbRealm">
	<authentication>
		<login-module
			code="org.jboss.resource.security.ConfiguredIdentityLoginModule"
			flag="required">
			<module-option name="principal">admin</module-option>
			<module-option name="userName">admin</module-option>
			<module-option name="password">admin</module-option>
			<module-option name="managedConnectionFactoryName">
				jboss.jca:service=LocalTxCM,name=dbpool</module-option>
		</login-module>
	</authentication>
</application-policy>

3.create mysql-ds.xml as follows:

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
	<local-tx-datasource>
		<jndi-name>dbpool</jndi-name>
		<connection-url>jdbc:mysql://localhost:3306/AUTHORS</connection-url>
		<driver-class>com.mysql.jdbc.Driver</driver-class>
		<user-name>admin</user-name>
		<password>admin</password>
		<security-domain>mysqlDbRealm</security-domain>
		<metadata>
			<type-mapping>mySQL</type-mapping>
		</metadata>
	</local-tx-datasource>
</datasources>

4.create jbosscmp-jdbc.xml as follows:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jbosscmp-jdbc PUBLIC "-//JBoss//DTD JBOSSCMP-JDBC 4.0//EN"

"http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_4_0.dtd">
<jbosscmp-jdbc>
	<defaults>
		<datasource>java:/dbpool</datasource>
		<datasource-mapping>mySQL</datasource-mapping>
	</defaults>
	<enterprise-beans>
		<entity>
			<ejb-name>AuthorsBean</ejb-name>
			<create-table>false</create-table>
			<table-name>Authors</table-name>
			<cmp-field>
				<field-name>isbnCode</field-name>
				<column-name>ISBN_CODE</column-name>
			</cmp-field>
			<cmp-field>
				<field-name>authorName</field-name>
				<column-name>AUTHOR</column-name>
			</cmp-field>
		</entity>
	</enterprise-beans>
</jbosscmp-jdbc>

My work folder for ANT has the following structure:

<build>
<src>
     |<shoppingcart>
          |AuthorsBean.java
          |Authors.java
          |AuthorsHome.java
          |AuthorsKey.java
          |AuthorsServlet.java
ejb-jar.xml
mysql-ds.xml
jbosscmp-jdbc.xml
jboss.xml
application.xml
web.xml
build.xml
build.properties
build.bat

ejb-jar.xml looks like this:

<?xml version="1.0"?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN" "http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd">
<ejb-jar>
	<display-name>Authors</display-name>
	<enterprise-beans>
		<entity>
			<description>Authors Entity Bean</description>
			<ejb-name>AuthorsBean</ejb-name>
			<home>shoppingcart.AuthorsHome</home>
			<remote>shoppingcart.Authors</remote>
			<ejb-class>shoppingcart.AuthorsBean</ejb-class>
			<persistence-type>Container</persistence-type>
			<prim-key-class>shoppingcart.AuthorsKey</prim-key-class>
			<reentrant>False</reentrant>
			<cmp-field>
				<field-name>isbnCode</field-name>
			</cmp-field>
			<cmp-field>
				<field-name>authorName</field-name>
			</cmp-field>
		</entity>
	</enterprise-beans>
	<assembly-descriptor>
		<container-transaction>
			<method>
				<ejb-name>AuthorsBean</ejb-name>
				<method-name>*</method-name>
			</method>
			<trans-attribute>Required</trans-attribute>
		</container-transaction>
	</assembly-descriptor>
	<resource-ref>
		<res-ref-name>jdbc/ejbPool</res-ref-name>
		<res-type>javax.sql.DataSource</res-type>
		<res-auth>Container</res-auth>
	</resource-ref>
</ejb-jar>

The ejb-jar.xml is a deployment descriptor was introduced with EJB 2.0.
It describes the entity or session beans that are included in the application.
Every ejb-jar.xml has exactly one tag, which may contain , or tags and some other optional tags .
The contains the names of the home, remote and the bean class as well as some other info.
The tag contains the descriptive name of the bean.
The tag contains the fully qualified name of the home class.
The tag contains the fully qualified name of the remote class.
The tag contains the fully qualified name of the bean class.
The tag and the are specific to session beans and is used to….
In case of entity beans there is a tag that contains the fully qualified name for the entity bean’s primary key class.
This may be a primitive data type such as java.lang.String for a simple key or a fully qualified class name for a compound key.
The tag declares whether the bean can call another bean which calls the original bean.
The tag contains a tag that describes the cmp fields in the entity bean.
Lastly the tag contains the name of the primary key field (for simple pry key types) and is not required for compound keys.

jaws.xml is required only for entity beans.

jboss.xml looks like this:

<?xml version="1.0"?>
<jboss>
	<secure>false</secure>
	<container-configurations />
	<resource-managers />
	<enterprise-beans>
		<entity>
			<ejb-name>AuthorsBean</ejb-name>
			<jndi-name>shoppingcart/Authors</jndi-name>
		</entity>
	</enterprise-beans>
	<resource-ref>
		<res-ref-name>jdbc/ejbPool</res-ref-name>
		<resource-name>java:/dbpool</resource-name>
		<jndi-name>dbpool</jndi-name>
	</resource-ref>
</jboss>

application.xml looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC '-//Sun Microsystems, Inc.//DTD J2EE Application 1.2//EN' 'http://java.sun.com/j2ee/dtds/application_1_2.dtd'>
<application>
	<display-name>Authors EJB</display-name>
	<module>
		<ejb>Authors.jar</ejb>
	</module>
	<module>
		<web>
			<web-uri>Authors.war</web-uri>
			<context-root></context-root>
		</web>
	</module>
</application>

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>AuthorsServlet</servlet-name>
		<servlet-class>shoppingcart.AuthorsServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>AuthorsServlet</servlet-name>
		<url-pattern>/AuthorsServlet</url-pattern>
	</servlet-mapping>
</web-app>

build.xml looks like this:


	<project name="Authors" default="build-all" 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="${build.classes.dir}" />
			<pathelement location="${jboss.dist}/client/javax.servlet.jar" />
		</path>

		<target name="war" depends="compile">
			<war warfile="${war}" webxml="web.xml">
				<classes dir="${build.classes.dir}">
					<include name="shoppingcart/AuthorsServlet.class" />
					<include name="shoppingcart/${appname}.class" />
					<include name="shoppingcart/${appname}Home.class" />
					<include name="shoppingcart/${appname}Key.class" />
				</classes>
				<lib dir="${jboss.client.dir}">
					<include name="jboss-client.jar" />
					<include name="jnp-client.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>
		<!-- clean all -->
		<target name="clean">
			<delete file="${jar}" />
			<delete file="${ear}" />
			<delete file="${war}" />
			<delete file="${jboss.deploy.dir}/${ear}" />
			<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


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

AuthorsBean.java

package shoppingcart;

import shoppingcart.AuthorsKey;
import shoppingcart.Authors;
import javax.ejb.EntityBean;
import javax.ejb.EntityContext;

public class AuthorsBean implements EntityBean {
	EntityContext ctx;
	public String isbnCode;
	public String authorName;

	public AuthorsKey ejbCreate(AuthorsKey key) {
		this.isbnCode = key.getIsbnCode();
		return null;
	}

	public AuthorsKey ejbFindByPrimaryKey(AuthorsKey key) {
		return key;
	}

	public void ejbPostCreate(AuthorsKey authorsKey) {
	}

	public String getAuthorName() {
		return this.authorName;
	}

	public void setAuthorName(String authorName) {
		this.authorName = authorName;
	}

	public void setEntityContext(EntityContext ctx) {
		this.ctx = ctx;
	}

	public void unsetEntityContext() {
		ctx = null;
	}

	public void ejbActivate() {
	}

	public void ejbPassivate() {
	}

	public void ejbLoad() {
	}

	public void ejbStore() {
	}

	public void ejbRemove() {
	}
}

Authors.java

package shoppingcart;

import javax.ejb.EJBObject;
import java.rmi.RemoteException;

public interface Authors extends EJBObject {
	public String getAuthorName() throws RemoteException;

	public void setAuthorName(String authorName) throws RemoteException;
}

AuthorsHome.java

package shoppingcart;

import javax.ejb.EJBHome;
import javax.ejb.CreateException;
import javax.ejb.FinderException;
import java.rmi.RemoteException;

public interface AuthorsHome extends EJBHome {
	public Authors create(AuthorsKey authorsKey) throws CreateException,
			RemoteException;

	public Authors findByPrimaryKey(AuthorsKey authorsKey)
			throws FinderException, RemoteException;
}

AuthorsKey.java

package shoppingcart;

import java.io.Serializable;

public class AuthorsKey implements Serializable {
	public String isbnCode;

	public AuthorsKey() {
		super();
	}

	public AuthorsKey(String isbnCode) {
		this.isbnCode = isbnCode;
	}

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

	public boolean equals(Object o) {
		if (o instanceof shoppingcart.AuthorsKey) {
			if (((shoppingcart.AuthorsKey) o).getIsbnCode().equals(
					this.isbnCode))
				return true;
			else
				return false;
		}
		return false;
	}

	public int hashCode() {
		return this.isbnCode.hashCode();
	}
}

AuthorsServlet.java

package shoppingcart;

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 javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import shoppingcart.Authors;
import shoppingcart.AuthorsHome;
import shoppingcart.AuthorsKey;

public class AuthorsServlet extends HttpServlet {
	private AuthorsHome authorsHome = null;

	public void init() throws ServletException {
		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);
		}
	}

	public void doPost(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {
		Authors bean = null;
		String title = "Servlet Interface to EJB";
		res.setContentType("text/html");
		PrintWriter pout = res.getWriter();
		pout.println("<html><head><title>");
		pout.println(title);
		pout.println("</title></head><body>");
		pout.println("<h1>" + title + "</h1>");
		pout.println("<h2>calling ejb...</h2>");
		try {
			pout.println("parameter Add" + req.getParameter("Add") + "<br />");
			pout.println("parameter Find  " + req.getParameter("Find") + "<br />");
			pout.println("parameter isbnCode" + req.getParameter("isbnCode")
					+ "<br />");
			pout.println("paramter Author  " + req.getParameter("author")
					+ "<br />");
			pout.println("<p>");
			if (req.getParameter("Add") != null) {
				AuthorsKey key = new AuthorsKey(
						(String) req.getParameter("isbnCode"));
				bean = authorsHome.create(key);
				if (req.getParameter("author") != null)
					bean.setAuthorName(req.getParameter("author"));
				pout.println("created  " + req.getParameter("isbnCode")
						+ "entry");
			}
			if (req.getParameter("Find") != null) {
				try {
					if (req.getParameter("isbnCode") != null
							&& req.getParameter("isbnCode").length() > 0) {
						AuthorsKey key = new AuthorsKey(
								(String) req.getParameter("isbnCode"));
						bean = authorsHome.findByPrimaryKey(key);
						pout.println("found author name   "
								+ bean.getAuthorName() + "  entry");
					}
				} catch (Exception e) {
					pout.println("not found " + "<br />");
					e.printStackTrace();
				}
			}
		} catch (Exception e) {
			pout.print(e.toString());
		} finally {
			pout.println("</body></html>");
			pout.close();
		}
	}

	public void doGet(HttpServletRequest req, HttpServletResponse res)
			throws ServletException, IOException {
		PrintWriter pout = res.getWriter();
		pout.print("<html><body>");
		pout.print("<form name='AuthorsForm' method=post action='./AuthorsServlet'>");
		pout.println("<p> Isbn code:");
		pout.println("<input type='text' name='isbnCode' size='10'>");
		pout.println("<p>  Author");
		pout.println("<input type='text' name='author' size='12'>");
		pout.println("<input type='submit' name='Add' value='Add'>");
		pout.println("<input type='submit' name='Find' value='Find'>");
		pout.println("</form>");
		pout.println("</body></html>");
	}
}

Interest.ear file has the following structure on deployment to jboss:

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
          |<meta-INF>
          |<web-INF>
               |web.xml
               |<classes>
                         |<shoppingcart>
                              |Authors.class
                              |AuthorsHome.class
                              |AuthorsKey.class
                              |AuthorsServlet.class
               |<lib>
                              |jboss-client.jar
                              |jnp-client.jar

To run the application remember to perform the following steps:
1.set JBOSS_HOME and ANT_HOME environment variables to appropriate folders containing the folder in ant and jboss. Also set / in your path variable.
2.construct work folder as described above
3.Open dos prompt at work folder to build project – “ant build-all”
To redeploy – “ant clean” – and then – “ant build-all”
When you run build.bat at the dos prompt, the files in folder are compiled and appropriate class files are placed in folder, war, jar and ear files are created and the ear file is deployed to / folder.
Start jboss
Type the following url on the browser.
http://localhost:8080/AuthorsServlet

You will be prompted by the jsp page to create or find an entry in the authors table.
To find an entry you only need to set the ISBN_CODE
To create an entry you need to set both ISBN_CODE as well as AUTHOR
In case the above criteria are not fulfilled an exception will be thrown as the program is not sophisticated enough to handle such cases. An exception is also thrown if an attempt is made to create an entity when it already exists in the database.
After creating an entry you login to the mySQL console and check the presence of the entry.
You can run the application again and check out the existence of the entry by entering the ISBN_CODE.
The output will be something like this:

Servlet Interface to EJB
calling ejb...
parameter Add null
parameter Find Find
parameter isbnCode gogo
parameter Author
found author name martin entry

I will be using this example to demonstrate how to use struts with ejb as well as some other demos.

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: