Problem deploying EJB: Cmp-Fields not found

I have been using Java technology for quite some time, including many facets of J2EE, but have just very recently begun exploring Enterprise JavaBeans more in depth. Excuse the simplicity of my question please.

I have developed a very simple Entity EJB, but am having difficulty deploying it; more specifically, my application server always tells me that the cmp-fields as defined in my deployment descriptor are missing. The deploytool distributed w/ the J2EE SDK also does not recognize my fields, so I have obviously got something wrong.

I've simplified my code and posted it below -- please tell me what I am missing...

Remote (ejb/Test.java):/**

*/

import java.rmi.RemoteException;

import javax.ejb.*;

/**

* @version 1.0

* @authorteknologikl

* @since1.0

*/

publicinterface Test

extends EJBObject{

// Exposed ejb business methods

public String getId()

throws java.rmi.RemoteException;

public String getName()

throws java.rmi.RemoteException;

publicvoid setName(String linkName)

throws java.rmi.RemoteException;

}

Home (ejb/TestHome.java):/**

*/

import java.rmi.RemoteException;

import java.util.*;

import javax.ejb.*;

/**

* @version 1.0

* @authorteknologikl

* @since1.0

*/

publicinterface TestHome

extends EJBHome{

// Normal lifecycle methods

Test create(String name)

throws RemoteException, CreateException;

// Finder methods

Test findByPrimaryKey(Integer id)

throws RemoteException, FinderException;

Collection findByName(String name)

throws RemoteException, FinderException;

}

Implementation (ejb/TestEJB.java):/**

*/

import java.rmi.*;

import javax.ejb.*;

/**

* @version 1.0

* @authorteknologikl

* @since1.0

*/

publicclass TestEJB

implements EntityBean{

// Ejb properties

private EntityContext context =null;

private String id;

private String name;

// Ejb constructors

public TestEJB(){

}

// Ejb business methods

public String getName()

throws RemoteException{

return name;

}

publicvoid setName(String name)

throws RemoteException{

this.name = name;

}

public String getId()

throws RemoteException{

return id;

}

// Ejb lifecycle callback methods

public String ejbCreate(String name)

throws CreateException, RemoteException{

if (name ==null)

thrownew CreateException("name cannot be null");

// no errors

this.name = name;

return this.toString();

}

publicvoid ejbPostCreate(String name)

throws RemoteException{

}

publicvoid ejbActivate()

throws RemoteException{

id = (String)context.getPrimaryKey();// load the primary key

}

publicvoid ejbLoad()

throws RemoteException{

}

publicvoid ejbPassivate()

throws RemoteException{

id =null;// unset the primary key

}

publicvoid ejbRemove()

throws RemoteException{

}

publicvoid ejbStore()

throws RemoteException{

}

publicvoid setEntityContext(EntityContext context)

throws RemoteException{

this.context = context;

}

publicvoid unsetEntityContext()

throws RemoteException{

context =null;

}

public String toString(){

return"[Id: " + id +", Name: " + name +"]";

}

}

Deployment Descriptor (meta-inf/ejb.xml):<?xml version="1.0"?>

<ejb-jar>

<display-name>Test EJB</display-name>

<description>

This is simplyfor testing purposes.

</description>

<enterprise-beans>

<entity>

<display-name>Test</display-name>

<description>

...

</description>

<ejb-name>Test</ejb-name>

<persistence-type>Container</persistence-type>

<home>TestHome</home>

<remote>Test</remote>

<ejb-class>TestEJB</ejb-class>

<prim-key-class>java.lang.String</prim-key-class>

<reentrant>False</reentrant>

<cmp-field><field-name>name</field-name></cmp-field>

</entity>

</enterprise-beans>

<assembly-descriptor>

<container-transaction>

<method>

<ejb-name>Test</ejb-name>

<method-name>*</method-name>

</method>

<trans-attribute>Required</trans-attribute>

</container-transaction>

</assembly-descriptor>

</ejb-jar>

Any help would be much appreciated.

Thanks.

[9490 byte] By [teknologikl] at [2007-9-26 3:38:47]
# 1

A couple of things seem inconsistent. The deployement descriptior states that java.lang.String is your primary-key class however your home interface's findByPrimaryKey() method accepts a java.lang.Integer parameter (that parameter should match the data-type of your primary-key class). Also CMP fields must be public as per the EJB spec so change the access modifier to public in your EJB for your defined CMP field(s).

paternostro at 2007-6-29 12:12:46 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 2

The findByPrimaryKey() problem was separate and probably would have bit me in the **** at a later date, thanks for pointing it out.

The private vs. public field issue did fix the problem. Typically, it's better practice to hide the fields of a bean so that clients cannot directly access them and are forced to use getter and setter methods, so I had assumed that EJBs would be no different. I presume, however, that with cmp the container requires more control and direct manipulation with respect to fields.

Thanks for your assistance.

teknologikl at 2007-6-29 12:12:46 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 3

Traditionally, you make class attributes private and provide accessor and mutator methods to manipulate those attributes. However, since EJB client applications don't directly access an EJB (the home and remote interfaces act as a proxy to the bean) this isn't a problem. The EJB spec requires CMP fields to be public in order for the container to more easily access those attributes (via reflection) without worrying about security restrictions.

paternostro at 2007-6-29 12:12:46 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...