> Hi,
>
> I didn't do it before, so am not able to describe the steps required to
> get it up and running. However, as OpenEJB relies on Castor to persist
> CMP's state look at Castor's documentation where I'm quite sure you'll
> find the answer. That's the best direction I can now think of.
>
> Give us a chance to find it out as well once you've sorted it out.


Hi Jacek,

After substantial reading and testing I could not accomplish it the Castor
way.
I may be wrong (i hope i am wrong) and perhaps somebody with more openejb
knowledge could point me my mistake,
but it seems that openejb looses collection/ArrayList data. The other
bean-persistent-fields are ok.

I use the student-course paradigm: many students have many courses and many
courses have many students.
Castors way is to put an Arraylist students in the class Course and an
ArrayList courses in the class Student.
You have to make set-, get- and addCourses subroutines in Student and set-,
get- and addStudents subroutines in Course. Finally you have to put a
many-table paragraph in the mapping.xml and create the crosstable
course_student in your database. When persisting both Student and Course
objects, Castor will populate the crosstable and hence persists the
ArrayLists data.

My best guess, why it does not work, is that both beans must be persisted in
the same JDO transaction (between begin() and commit(). If openejb persist
per bean ( I did not look at the source) this demand would not be met. But
it is just a guess...

Here is some trace output of the client application after adding two
students to one course:

Course.setEntityContext : course(null).students.size() 0
Course.setCourseName : course(null).students.size() 0
Course.ejbCreate : course(null).students.size() 0
Course.ejbPostCreate : course(11).students.size() 0
Course.addStudents 1 : course(11).students.size() 0
Course.addStudents 2: added studentId 13
Course.addStudents 3: course.students.size() 1
                                  ^^^^^^^^^^ note: ArrayList students size =
1
Course.addStudents 1 : course(11).students.size() 0
                                  ^^^^^^^^^^ note: ArrayList students size =
0
Course.addStudents 2: added studentId 14
Course.addStudents 3: course.students.size() 1

I think I just have to wait for Geronimo (EJB2.0 container) with CMR
relation fields.
Meanwhile I will use a crosstableBean.

Best regards,

Roy

Here are the code and the config:
----------------------------------------------------------------------------
-------------
sql
----------------------------------------------------------------------------
-------------
DROP TABLE student ;
CREATE TABLE student
(
    student_id INTEGER,
    s_name VARCHAR(80)
) ;

DROP SEQUENCE student_seq ;
CREATE SEQUENCE student_seq ;


DROP TABLE course ;
CREATE TABLE course
(
    course_id INTEGER ,
    c_name VARCHAR(80)
) ;

DROP SEQUENCE course_seq ;
CREATE SEQUENCE course_seq ;


DROP TABLE course_student ;
CREATE TABLE course_student
(
    course_id INTEGER ,
    student_id INTEGER
) ;

DROP SEQUENCE course_student_seq ;
CREATE SEQUENCE course_student_seq ;
----------------------------------------------------------------------------
-------------
mapping file:
----------------------------------------------------------------------------
-------------
<!DOCTYPE databases PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"

"http://castor.exolab.org/mapping.dtd";>

<mapping>

     <!--  Mapping for StudentBean  -->
     <class name="org.acme.crosstable.StudentBean" identity="studentId"
key-generator="SEQUENCE">
         <map-to table="student"/>
         <field name="studentId" type="integer" direct="true">
             <sql name="student_id" type="integer"/>
         </field>
         <field name="studentName" type="string" direct="true">
             <sql name="s_name" type="varchar" dirty="check"/>
         </field>

         <!-- Student has reference to Course, many Course's per Student -->

         <field name="courses" type="org.acme.crosstable.CourseBean"
collection="arraylist" direct="true">
             <sql name="course_id" many-table="course_student"
many-key="student_id"/>
         </field>
     </class>

     <!--  Mapping for CourseBean  -->
     <class name="org.acme.crosstable.CourseBean" identity="courseId"
key-generator="SEQUENCE">
         <map-to table="course"/>
         <field name="courseId" type="integer" direct="true">
             <sql name="course_id" type="integer"/>
         </field>
         <field name="courseName" type="string" direct="true">
             <sql name="c_name" type="varchar" dirty="check"/>
         </field>

         <!-- Course has reference to Student, many Students per Course-->
         <field name="students" type="org.acme.crosstable.StudentBean"
collection="arraylist" direct="true">
             <sql name="student_id" many-table="course_student"
many-key="course_id"/>
         </field>
     </class>

</mapping>
----------------------------------------------------------------------------
-------------
ejb-jar.xml file:
----------------------------------------------------------------------------
-------------
<?xml version="1.0" encoding="US-ASCII"?>

<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise
JavaBeans 1.1//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd";>

<ejb-jar>

  <description>
     application.
  </description>

  <enterprise-beans>

    <entity>
      <description>
         blah
      </description>
      <ejb-name>StudentBean</ejb-name>
      <home>org.acme.crosstable.StudentHome</home>
      <remote>org.acme.crosstable.Student</remote>
      <ejb-class>org.acme.crosstable.StudentBean</ejb-class>
      <persistence-type>Container</persistence-type>
      <prim-key-class>java.lang.Integer</prim-key-class>
      <reentrant>False</reentrant>
      <cmp-field>
        <field-name>studentId</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>studentName</field-name>
      </cmp-field>
      <primkey-field>studentId</primkey-field>
      <ejb-ref>
        <ejb-ref-name>CourseBean</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <home>org.acme.crosstable.CourseHome</home>
        <remote>org.acme.crosstable.CourseBean</remote>
        <ejb-link>CourseBean</ejb-link>
      </ejb-ref>
      <resource-ref>
        <description>
        reference to myDB postgresql database
        </description>
        <res-ref-name>jdbc/postgresql</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
      </resource-ref>
    </entity>

    <entity>
      <description>
      ######################################################
      ID:  org.acme.crosstable/CourseBean
      ######################################################
      </description>
      <ejb-name>CourseBean</ejb-name>
      <home>org.acme.crosstable.CourseHome</home>
      <remote>org.acme.crosstable.Course</remote>
      <ejb-class>org.acme.crosstable.CourseBean</ejb-class>
      <persistence-type>Container</persistence-type>
      <prim-key-class>java.lang.Integer</prim-key-class>
      <reentrant>False</reentrant>
      <cmp-field>
        <field-name>courseId</field-name>
      </cmp-field>
      <cmp-field>
        <field-name>courseName</field-name>
      </cmp-field>
      <primkey-field>courseId</primkey-field>
      <ejb-ref>
        <ejb-ref-name>StudentBean</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <home>org.acme.crosstable.StudentHome</home>
        <remote>org.acme.crosstable.StudentBean</remote>
        <ejb-link>StudentBean</ejb-link>
      </ejb-ref>
      <resource-ref>
        <description>
        reference to postgresql database
        </description>
        <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>StudentBean</ejb-name>
        <method-name>*</method-name>
      </method>
      <trans-attribute>Supports</trans-attribute>
    </container-transaction>

    <container-transaction>
      <method>
        <ejb-name>CourseBean</ejb-name>
        <method-name>*</method-name>
      </method>
      <trans-attribute>Supports</trans-attribute>
    </container-transaction>

  </assembly-descriptor>

</ejb-jar>

----------------------------------------------------------------------------
-------------
openejb-jar.xml
----------------------------------------------------------------------------
-------------
<?xml version="1.0"?>

<openejb-jar xmlns="http://www.openejb.org/openejb-jar/1.1";>

    <ejb-deployment ejb-name="StudentBean" deployment-id="StudentBean"
container-id="PostgreSQL CMP Container">
        <resource-link res-ref-name="jdbc/postgresql" res-id="PostgreSQL
JDBC Database"/>
    </ejb-deployment>

    <ejb-deployment ejb-name="CourseBean" deployment-id="CourseBean"
container-id="PostgreSQL CMP Container">
        <resource-link res-ref-name="jdbc/postgresql" res-id="PostgreSQL
JDBC Database"/>
    </ejb-deployment>

</openejb-jar>
----------------------------------------------------------------------------
-------------
local-database.xml
----------------------------------------------------------------------------
-------------
<!DOCTYPE databases PUBLIC "-//EXOLAB/Castor JDO Configuration DTD Version
1.0//EN"
                           "http://castor.exolab.org/jdo-conf.dtd";>

<database name="Local_TX_Database" engine="postgresql">
    <driver class-name="org.postgresql.Driver"
url="jdbc:postgresql://localhost/myDB">
      <param name="user" value="pgsql"/>
      <param name="password" value=""/>
    </driver>
    <mapping href="/usr/local/openejb/apps/src-cmp/mapping.xml" />
</database>
----------------------------------------------------------------------------
-------------
global-database.xml
----------------------------------------------------------------------------
-------------
<!DOCTYPE databases PUBLIC "-//EXOLAB/Castor JDO Configuration DTD Version
1.0//EN"
                           "http://castor.exolab.org/jdo-conf.dtd";>
<database name="Global_TX_Database" engine="postgresql">
    <jndi name="java:comp/env/jdbc/postgresql" />
    <mapping href="/usr/local/openejb/apps/src-cmp/mapping.xml" />
</database>
----------------------------------------------------------------------------
-------------
org/acme/crosstable/Student.java
----------------------------------------------------------------------------
-------------
package org.acme.crosstable;

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

public interface Student extends EJBObject
{
    public Integer getStudentId() throws RemoteException;
    public void    setStudentId(Integer studentId) throws RemoteException;

    public String  getStudentName() throws RemoteException;
    public void    setStudentName(String name) throws RemoteException;

    public void      setCourses(ArrayList courses) throws RemoteException;
    public void      addCourses(Course course) throws RemoteException;
    public ArrayList getCourses() throws RemoteException;
}
----------------------------------------------------------------------------
-------------
org/acme/crosstable/StudentBean.java
----------------------------------------------------------------------------
-------------
package org.acme.crosstable;

import java.util.*;
import javax.ejb.*;
import javax.naming.*;

public class StudentBean implements EntityBean
{

    private EntityContext context;

    // When ussing Castors direct binding, persitent fields must be public

    public Integer   studentId;
    public String    studentName;
    public ArrayList courses = new ArrayList();

    // business methods
    // Access methods for persistent fields

    public Integer  getStudentId(){ return this.studentId; }
    public void     setStudentId(Integer studentId) { this.studentId =
studentId; }

    public String getStudentName(){ return this.studentName; }
    public void setStudentName(String studentName){ this.studentName =
studentName; }

    // Castor many-table set/add/get methods

    public void setCourses(ArrayList courses)
    {
        this.courses = courses;
    }

    public void addCourses(Course course) throws java.rmi.RemoteException
    {
        courses.add(course);
    }

    public ArrayList getCourses()
    {
        return this.courses;
    }

    // EntityBean methods

    public Integer ejbCreate ( String name ) throws CreateException
    {
        setStudentName(name);

        return null;
    }

    public void ejbPostCreate ( String name ) throws CreateException
    {
    }

    public void setEntityContext( EntityContext context ) throws
EJBException
    {
        this.context = context;
    }

    public void unsetEntityContext() throws EJBException
    {
        context = null;
    }

  public void ejbActivate() throws EJBException
  {
  }

  public void ejbLoad() throws EJBException
  {
  }

  public void ejbPassivate() throws EJBException
  {
  }

  public void ejbRemove() throws RemoveException, EJBException
  {
  }

  public void ejbStore() throws EJBException
  {
  }
}
----------------------------------------------------------------------------
-------------
org/acme/crosstable/StudentHome.java
----------------------------------------------------------------------------
-------------
package org.acme.crosstable;

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

public interface StudentHome extends EJBHome
{
  public Student create( String name ) throws RemoteException,
CreateException;

  public Student findByPrimaryKey( Integer id ) throws RemoteException,
FinderException;
}
----------------------------------------------------------------------------
-------------
org/acme/crosstable/Course.java
----------------------------------------------------------------------------
-------------
package org.acme.crosstable;

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

public interface Course extends EJBObject
{
    public Integer getCourseId() throws RemoteException;
    public void    setCourseId(Integer CourseId) throws RemoteException;

    public String  getCourseName() throws RemoteException;
    public void    setCourseName(String courseName) throws RemoteException;

    public void       setStudents(ArrayList students) throws
RemoteException;
    public void       addStudents(Student newstudent) throws
RemoteException;
    public ArrayList getStudents() throws RemoteException;
}
----------------------------------------------------------------------------
-------------
org/acme/crosstable/CourseBean.java
----------------------------------------------------------------------------
-------------
package org.acme.crosstable;

import java.util.ArrayList;
import java.rmi.RemoteException;
import java.sql.*;
import javax.ejb.*;

public class CourseBean implements EntityBean
{

    private EntityContext context;

    // When ussing Castors direct binding, persitent fields must be public

    public Integer    courseId;
    public String     courseName;
    public ArrayList students = new ArrayList();

    // business methods
    // Access methods for persistent fields

    public Integer getCourseId()
    {
        trace("getCourseId");
        return this.courseId;
    }

    public void setCourseId(Integer courseId)
    {
        trace("setCourseId");
        this.courseId = courseId;
    }

    public String getCourseName()
    {
        trace("getCourseName");
        return this.courseName;
    }

    public void setCourseName(String courseName)
    {
        trace("setCourseName");
        this.courseName = courseName;
    }

    // Castor many-table set/add/get methods

    public void setStudents(ArrayList students)
    {
        this.students = students;
        trace("setStudents");
    }

    public void addStudents( Student newstudent ) throws RemoteException
    {
        trace("addStudents 1");
        this.students.add(newstudent);
System.out.println("Course.addStudents 2: added studentId " +
newstudent.getStudentId());
System.out.println("Course.addStudents 3: course.students.size() " +
this.students.size());
    }

    public ArrayList getStudents()
    {
        trace("getStudents");
        return this.students;
    }

    // EntityBean methods

    public Integer ejbCreate(String name) throws CreateException
    {
        setCourseName(name);
        trace("ejbCreate");
        return null;
    }

    public void ejbPostCreate(String courseName) throws
javax.ejb.CreateException
    {
        trace("ejbPostCreate");
    }

    public void ejbLoad() throws EJBException, RemoteException
    {
        trace("ejbLoad");
    }

    public void setEntityContext(EntityContext ctx) throws EJBException,
RemoteException
    {
        context = ctx;
        trace("setEntityContext");
    }

    public void unsetEntityContext()
    {
        context = null;
        trace("unsetEntityContext");
    }

    public void ejbStore() throws EJBException, RemoteException
    {
        trace("ejbStore");
    }

     public void ejbActivate() throws EJBException
     {
         trace("ejbActivate");
     }

     public void ejbPassivate() throws EJBException
     {
         trace("ejbPassivate");
     }

     public void ejbRemove() throws RemoveException, EJBException
     {
         trace("ejbRemove");
     }

     private void trace(String method)
     {
         System.out.println("Course."+ method + " : course(" + this.courseId
+ ").students.size() " + students.size());
     }
}
----------------------------------------------------------------------------
-------------
org/acme/crosstable/CourseHome.java
----------------------------------------------------------------------------
-------------
package org.acme.crosstable;

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

public interface CourseHome extends EJBHome
{

    public Course create(String name) throws CreateException,
RemoteException;

    public Course findByPrimaryKey(Integer primarykey) throws
CreateException, RemoteException;
}
----------------------------------------------------------------------------
-------------
org/acme/crosstable/Client.java
----------------------------------------------------------------------------
-------------
package org.acme.crosstable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import java.util.Properties;

public class Client
{
   public static void main( String[] args )
           throws Exception
   {
      Properties env = new Properties();


      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 sobj = ctx.lookup( "StudentBean" );
      sobj = PortableRemoteObject.narrow( sobj, StudentHome.class );
      StudentHome shome = ( StudentHome ) sobj;
      Student student1 = shome.create( "Roy" );
      Student student2 = shome.create( "Glasius" );

      Object cobj = ctx.lookup( "CourseBean" );
      cobj = PortableRemoteObject.narrow( cobj, CourseHome.class );
      CourseHome chome = ( CourseHome ) cobj;
      Course course1 = chome.create( "BeansCourse" );

      course1.addStudents(student1);
      student1.addCourses(course1);

      course1.addStudents(student2);
      student2.addCourses(course1);
   }
}




-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
SourceForge.net hosts over 70,000 Open Source Projects.
See the people who have HELPED US provide better services:
Click here: http://sourceforge.net/supporters.php
_______________________________________________
http://OpenEJB.sf.net
OpenEJB-user mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/openejb-user

Reply via email to