<?xml version="1.0"?><document url="http://openejb.sf.net/cmp_entity_postgresql.xml" toc="numeric">    <properties>        <title>Hello OpenEJB World!</title>        <sub-title>A basic CMP entity bean example</sub-title>    </properties>    <body>    <section title="Abstract" ref-id="abstract">    <p>    The aim of this document is to help you out with deploying container-managed persistence (CMP) entity beans into OpenEJB. The database being used is PostgreSQL 7.2.1, but the steps are described in such a way that it should be very easy to switch over to another database system (chances are that when you send a request to the OpenEJB <a href="lists.html#openejb-user">user mailing list</a> about how to enable your preffered RDBMS in OpenEJB, someone, possibly from the development group, will pick it up and modify the document, accordingly). </p><p>The first sections deal with developing a CMP entity bean. It is a CMP entity's view of Employee.You may skip them if your bean is ready and waiting to be deployed. </p><p>We will be configuring PostgreSQL afterwards and creating the table and sequence the entity bean is to be mapped to. OpenEJB interacts with databases and XML files with the help of Castor. Although Castor plays a great role in OpenEJB the document doesn't assume you are already familiar with it nor will it be described here thoroughly. It is strongly adviced to learn more about Castor, indeed. Please visit <a href="http://castor.exolab.org">Castor home page</a> to find out more.</p><p>A few words are aimed to rise your awareness of the structure of OpenEJB configuration file - openejb.conf - and how to modify it. That is going to be a very broad overview and some facts are skipped for the sake of simplicity. </p><p>The last but not least step will be to start up everything (i.e. OpenEJB, PostgreSQL) and access the Employee entity bean from the out-of-process client (i.e. the client, which is outside of JVM OpenEJB runs in). </p>    <p>Everything was tested on MS Windows 2000 with PostgreSQL 7.2.1 installed on Cygwin 1.3.12-2 as well as with Sun JDK 1.3.1_04 and PostgreSQL JDBC driver. </p></section>    <section title="Before starting" ref-id="before"><p>This example assumes you have already followed the steps outlined in the <a href="hello-world.html">basic EJB example</a>. </p></section>    <section title="Create the entity bean class" ref-id="ejbbean"><p>First, create the package where we will place our ejb and application files. </p><command>C:\> cd \my\app</command><br/><command>C:\my\app> mkdir org\acme\employee</command><p>In your favorite editor, create the file below.</p>    <p><file name="C:\my\app\org\acme\employee\EmployeeBean.java">package org.acme.employee;import javax.ejb.*;import java.rmi.RemoteException;public class EmployeeBean implements EntityBean{  public int id;  public String firstname;  public String lastname;  public String email;  public EntityContext context;  public EmployeeBean()  {  }  public Integer ejbCreate( String firstname, String lastname, String email )    throws CreateException  {    this.firstname = firstname;    this.lastname = lastname;    this.email = email;    return null;  }  public void ejbPostCreate( String firstname, String lastname, String email )    throws CreateException  {  }  public void says( String message )  {    System.out.println( "[" + firstname + " " + lastname +           "(" + id + ") " + email + "] " + message );  }  public void setEntityContext( EntityContext context )    throws EJBException, RemoteException  {    this.context = context;  }  public void unsetEntityContext()    throws EJBException, RemoteException  {  }  public void ejbActivate()    throws EJBException, RemoteException  {  }  public void ejbLoad()    throws EJBException, RemoteException  {  }  public void ejbPassivate()    throws EJBException, RemoteException  {  }  public void ejbRemove()    throws RemoveException, EJBException, RemoteException  {  }  public void ejbStore()    throws EJBException, RemoteException  {  }}                                                                                   </file></p></section>        <section title="Create the entity bean's home interface" ref-id="ejbhome"><p>In your favorite editor, create the file below.</p><p><file name="C:\my\app\org\acme\employee\EmployeeHome.java">package org.acme.employee;import javax.ejb.CreateException;import javax.ejb.EJBHome;import javax.ejb.FinderException;import java.rmi.RemoteException;public interface EmployeeHome extends EJBHome{  public Employee create( String firstname, String lastname, String email )    throws RemoteException, CreateException;  public Employee findByPrimaryKey( Integer id )    throws RemoteException, FinderException;}                                                                                   </file></p></section>        <section title="Create the entity bean's remote interface" ref-id="ejbremote"><p>In your favorite editor, create the file below.</p><p><file name="C:\my\app\org\acme\employee\Employee.java">package org.acme.employee;import javax.ejb.EJBObject;import java.rmi.RemoteException;public interface Employee extends EJBObject{  public void says( String message )    throws RemoteException;}                                                                                   </file></p></section>        <section title="Create the ejb-jar.xml" ref-id="ejb-jar.xml"><p><command>C:\my\app> mkdir META-INF</command></p>    <p>And finally it's time for the deployment descriptor of the entity bean. In your favorite editor, create the file below.</p> <p><file name="C:\my\app\META-INF\ejb-jar.xml"><![CDATA[<?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>  <enterprise-beans>    <entity>      <ejb-name>EmployeeBean</ejb-name>      <home>org.acme.employee.EmployeeHome</home>      <remote>org.acme.employee.Employee</remote>      <ejb-class>org.acme.employee.EmployeeBean</ejb-class>      <persistence-type>Container</persistence-type>      <prim-key-class>java.lang.Integer</prim-key-class>      <reentrant>False</reentrant>      <cmp-field>        <field-name>id</field-name>      </cmp-field>      <cmp-field>        <field-name>firstname</field-name>      </cmp-field>      <cmp-field>        <field-name>lastname</field-name>      </cmp-field>      <cmp-field>        <field-name>email</field-name>      </cmp-field>      <primkey-field>id</primkey-field>      <resource-ref>        <res-ref-name>jdbc/postgresql</res-ref-name>        <res-type>javax.sql.DataSource</res-type>        <res-auth>Container</res-auth>      </resource-ref>    </entity>  </enterprise-beans>  <assembly-descriptor>    <container-transaction>      <method>        <ejb-name>EmployeeBean</ejb-name>        <method-name>*</method-name>      </method>      <trans-attribute>Supports</trans-attribute>    </container-transaction>  </assembly-descriptor></ejb-jar>]]>                                                                                    </file></p></section>        <section title="Compile the EJB" ref-id="compile"><p><command>C:\my\app> javac -d . -classpath %OPENEJB_HOME%\lib\ejb-1.0.jar org\acme\employee\*.java</command></p></section>        <section title="Package the EJB" ref-id="jar"><p><command>C:\my\app> jar -cvMf employee.jar org/acme/employee/*.class META-INF</command></p></section><section title="Create necessary structures in the database (e.g. PostgreSQL)" ref-id="table"><p>The procedure outlined here describes how to prepare PostgreSQL to work with the Employee entity bean. It basically shows the SQL statements to create the structures: a table and sequence. As sequences are a few RDBMS' feature you will have to work it around if your chosen database doesn't support it or try out PostgreSQL. Will it ever be a better time to find out what PostgreSQL is really able to do? </p><p>Firstly, let's start up PostgreSQL. It's assumed you followed the procedures on how to configure PostgreSQL to allow external users connect to the system, and a database is already created. Just to make sure we are on the same track from now on the name of the database will be reffered to as <b>mydb</b>, and the user and its password are <b>username</b> and <b>password</b>, respectively. </p><p>Now, please connect to the database (i.e. invoke <command>psql mydb username</command>) and run the following SQL scripts:</p><code>create table employee (    id integer primary key,     first_name varchar(15),     last_name varchar(15),    email varchar(30)); create sequence employee_seq;</code></section>        <section title="Configure the data source" ref-id="datasource"><p>Having done everything up to that point has showed you really nothing about OpenEJB itself. As you might have guessed, we're about to change it and see how different files influence the way OpenEJB works. </p><p>When OpenEJB starts up, the default configuration file is %OPENEJB_HOME%\conf\openejb.conf. We will, however, be using another one - our own configuration file. We're doing it because: <ul>    <li>it shall get you familiar with the configuration file's elements</li>    <li>it shall avoid bothering you with log messages that do not pertain to our example</li>    <li>it shall get you a feeling of how easy (or not) is to manage OpenEJB</li></ul></p><p>Thus, here goes the configuration file - openejb.xml - which will satisfy the aforementioned requirements. </p>            <p>Create the file in the conf directory.</p><p><command>C:\my\app> mkdir conf</command></p><p>In your favorite editor, create the file below.</p><file name="C:\my\app\conf\openejb.xml"><![CDATA[<?xml version="1.0"?><openejb>  <Container id="Default CMP Container" ctype="CMP_ENTITY">    Global_TX_Database  c:/my/app/conf/postgresql.cmp_global_database.xml    Local_TX_Database   c:/my/app/conf/postgresql.cmp_local_database.xml  </Container>  <Deployments jar="c:/my/app/employee.jar"/>  <Connector id="Default JDBC Database">    JdbcDriver org.postgresql.Driver    JdbcUrl jdbc:postgresql://localhost/mydb    UserName username    Password password  </Connector>  <SecurityService id="Default Security Service"/>  <TransactionService id="Default Transaction Manager"/></openejb>]]>                                                                                    </file><p>Before we go on a few words about the structure of the file.<ul>    <li><b>Container</b> - there are 4 different container types:        <ul>        <li>CMP_ENTITY</li>        <li>BMP_ENTITY</li>        <li>STATEFUL</li>        <li>STATELESS</li>        </ul>        <p>        The type of a container determines what capabilities it provides. The         Employee entity bean is a CMP entity bean so the chosen container is of         the CMP_ENTITY type.         </p>        <p>        Since entity beans represent (in most cases) records in a table there must         be a way to point an EJB container to it. OpenEJB does it via         <b>Global_TX_Database</b> and <b>Local_TX_Database</b> parameters. The         values of the parameters are configuration files which are specific to the         underlaying platform OpenEJB depends on - Castor. Their structure is         hopefully self-explanatory thus the document will not explain it in more         details.        </p>        <p>        These files are shown right after the bullet points below.        </p>        <br/>    </li>    <li><b>Deployments</b> - the element specifies the locations of beans         to be deployed onto OpenEJB. The element may have only one of the two         attributes (they are mutually exclusive):         <br/>        <ul>        <li><b>jar</b> - points to one particular bean</li>        <li><b>dir</b> - points to a directory that contains beans</li>        </ul>        <p>        The locations may be relative or absolute paths, where the former is         constructed to be an absolute path with %OPENEJB_HOME% prepended.         </p>        <br/>    </li>    <li><b>Connector</b> - the element allows to specify what parameters         to use while connecting to the default JDBC database. The contents of the         element consists of lines which begin with the name of the parameters you         could have seen before - these constitute the required JDBC parameters to         connect to the database, i.e. PostgreSQL.         <br/>        <p>        The <b>id</b> attribute must be "Default JDBC Database" unless you         know what changes are required upon changing the value.         </p>        <br/>    </li>    <li><b>SecurityService</b> and <b>TransactionService</b> - these         elements are included in the file because they are required and without         them OpenEJB refuses to run. Nothing to configure so we skip them         silently.   </li> </ul><note>In future versions of OpenEJB, you won't be required to include the SecurityService or TransactionService lines in your config files unless there is some part of them that you wish to configure.</note></p>            <p>Create the following files in the conf directory using your favorite editor. </p><file name="C:\my\app\conf\postgresql.cmp_global_database.xml"><![CDATA[<?xml version="1.0"?><database name="Global_TX_Database" engine="postgresql">  <jndi name="java:comp/env/jdbc/postgresql" />  <mapping href="c:/my/app//conf/postgresql.cmp_or_mapping.xml" /></database>]]>                                                                                    </file><br/><file name="C:\my\app\conf\postgresql.cmp_or_mapping.xml"><![CDATA[<?xml version="1.0"?><mapping>  <class name="org.acme.employee.EmployeeBean" identity="id" key-generator="SEQUENCE">    <map-to table="employee"/>    <field name="id" type="integer" direct="true">      <sql name="id" type="integer"/>    </field>    <field name="firstname" type="string" direct="true">      <sql name="first_name" type="varchar" dirty="check"/>    </field>    <field name="lastname" type="string" direct="true">      <sql name="last_name" type="varchar" dirty="check"/>    </field>    <field name="email" type="string" direct="true">      <sql name="email" type="varchar" dirty="check"/>    </field>  </class></mapping>]]></file><br/><file name="C:\my\app\conf\postgresql.cmp_local_database.xml"><![CDATA[<?xml version="1.0"?><database name="Local_TX_Database" engine="postgresql">  <driver class-name="org.postgresql.Driver" url="jdbc:postgresql://localhost/mydb">    <param name="user" value="username"/>    <param name="password" value="password"/>  </driver>  <mapping href="C:\my\app\conf\postgresql.cmp_or_mapping.xml"/></database>]]>                                                                                    </file><p><note>    As connections to PostgreSQL are being performed through JDBC data source     PostgreSQL JDBC2 driver's classes have to be available to OpenEJB. Thus,     you need to download from <a href="http://jdbc.postgresql.org">PostgreSQL     JDBC2 driver home page</a> and save it in %OPENEJB_HOME%\lib directory as     pgjdbc2.jar. The driver will be loaded by OpenEJB at startup.</note></p></section><section title="Deploy the EJB jar" ref-id="deploy"><p>Use the OpenEJB <a href="deploy.html">Deploy Tool</a> to deploy your jar.</p><p><command>C:\my\app> cd %OPENEJB_HOME%</command><br/><command>C:\openejb> openejb deploy -a -conf c:\my\app\conf\openejb.xml c:\my\app\employee.jar</command></p><p>The tool will ask for the resource to link the bean's reference to. You should type in <b>1</b> as it points to the resource declared in our configuration file which is the "Default JDBC Database", i.e. PostgreSQL. </p><p><note>Since the OpenEJB deployment tool writes to your jar file, make sure that  no other programs are using it when you deploy (i.e. if you use an editor such as Forte for Java to create the jar file, that editor may still be using it). If you get an error such as "Error in writing existing jar file" close any programs that may be using the jar and try deploying again. </note></p></section>        <section title="A basic client application" ref-id="client"><p>Create the basic client application to access your Employee entity bean. The client looks up the entity EJBHome object, creates a user, then finds it with <i>findByPrimaryKey</i> and finally compare the references to each other in order to find out whether or not they points to the same EJBObject managed by OpenEJB. The following lines show invocation of the bussines method - <i>says</i> - and at the end removes the bean's representation from the table. </p>            <p>Please refer to the <a href="hello-world.html">basic EJB example</a> to choose proper InitialContext environment variables. </p>            <p><command>C:\openejb> cd c:\my\app</command></p>            <p>Create the file in your favorite editor.</p>            <p><file name="C:\my\app\org\acme\employee\EmployeeClient.java">package org.acme.employee;import javax.naming.Context;import javax.naming.InitialContext;import javax.rmi.PortableRemoteObject;import java.util.Properties;public class EmployeeClient{   public static void main( String[] args )           throws Exception   {      Properties env = new Properties();      <comment>//The JNDI properties you set depend</comment>      <comment>//on which server you are using.</comment>      String jndiProvider = "org.openejb.client.RemoteInitialContextFactory";      env.put( "java.naming.factory.initial", jndiProvider );      env.put( "java.naming.provider.url", "localhost:4201" );      env.put( "java.naming.security.principal", "fakeuser" );      env.put( "java.naming.security.credentials", "fakepass" );      Context ctx = new InitialContext( env );      Object obj = ctx.lookup( "EmployeeBean" );      obj = PortableRemoteObject.narrow( obj, EmployeeHome.class );      EmployeeHome home = ( EmployeeHome ) obj;      Employee empl_create = home.create( "Jacek", "Laskowski",             "OpenEJB-" + System.currentTimeMillis() + "@SF.net" );            Integer primaryKey = ( Integer ) empl_create.getPrimaryKey();      Employee empl_find = home.findByPrimaryKey( primaryKey );            System.out.println( "Are the \"create\" and \"find\" users identical ? "+             empl_create.isIdentical( empl_find ) );            empl_find.says( "Hello OpenEJB World!" );      empl_find.remove();   }}                                                                                   </file></p></section><section title="Compile the application" ref-id="compile.app"><p><command>C:\my\app> javac -d . -classpath .;%OPENEJB_HOME%/lib/ejb-1.0.jar;%OPENEJB_HOME%/lib/jndi_1.2.1.jar org\acme\employee\EmployeeClient.java</command></p></section>        <section title="Run it!" ref-id="run.it"><p>Create the file in your favorite editor.</p><file name="C:\my\app\RunIt.bat">@echo offset OPENEJB_HOME=C:\openejbset PATH=%PATH%;%OPENEJB_HOME%\binset OLD_CLASSPATH=%CLASSPATH%set CP=for %%i in (%OPENEJB_HOME%\lib\*.jar) do call cp.bat %%i for %%i in (%OPENEJB_HOME%\dist\*.jar) do call cp.bat %%i set CP=c:\my\app\employee.jar;%CP%set CLASSPATH=%JAVA_HOME%\lib\tools.jar;%CP%%JAVA_HOME%\bin\java -Dopenejb.home=%OPENEJB_HOME% org.acme.employee.EmployeeClientset CLASSPATH=%OLD_CLASSPATH%</file><p>Open the command line window and start up OpenEJB with the following command: </p><p><command>C:\> cd %OPENEJB_HOME%</command><br/><command>C:\openejb> start openejb start -conf c:\my\app\conf\openejb.xml</command>             </p><p>Now run the script!</p>            <p><command>C:\> cd \my\app</command><br/><command>C:\my\app> RunIt</command></p><p>You will see the following sample output on the out-of-process client's console:</p><code>C:\my\app>RunItAre the "create" and "find" users identical ? true</code><p>And the following on the OpenEJB server's console:</p><code>OpenEJB Remote Server 0.8.1    build: 20020731-0133http://openejb.sf.net----------------STARTUP----------------[init] OpenEJB Container System[init] OpenEJB Remote Server  ** Starting Services **  NAME             IP              PORT  ejb server       127.0.0.1       4201  admin console    127.0.0.1       4200-----------------INFO------------------To log into the admin console, telnet to: telnet 127.0.0.1 4200---------------------------------------Ready![FirstName LastName(1) OpenEJB-1029465232802@SF.net] Hello OpenEJB World !</code></section>        <section title="What if it didn't work" ref-id="problems"><p>If you ran into any problems, first check your openejb.log file at %OPENEJB_HOME%\openejb.log. Look for any lines that begin with <term>"WARN"</term>, <term>"ERROR"</term>, or <term>"FATAL"</term>. </p>            <p>There is a list of the most common problems with possible solutions: <ul><li><p><b>Problem:</b></p><code>OpenEJB Remote Server 0.8.1    build: 20020731-0133http://openejb.sf.net----------------STARTUP----------------[init] OpenEJB Container Systemjava.lang.ClassNotFoundException: org.postgresql.Driver        at java.net.URLClassLoader$1.run(URLClassLoader.java:195)        at java.security.AccessController.doPrivileged(Native Method)        ...</code><p><b>Solution:</b> Add the PostgreSQL JDBC2 driver to OpenEJB's CLASSPATH. See the <a href="#datasource">Configure the data source</a> section for more details.</p> </li></ul></p><p>If nothing has helped, email it to the OpenEJB <a href="lists.html#openejb-user"> user mailing list</a> and let people know you are using the basic CMP entity bean example. </p></section></body></document>