Problem with One to One Unidirectional Relationship
darpan May 22, 2004 12:11 AMEnvironment
JDK 1.4.2, JBoss 3.2.3, MySQL
Problem
Unable to implement a One-to-One Unidirectional Relationship using CMP Entity Beans
Error Stacktrace
The EJB container is expecting a userDetails column in the UserLogin table which is not present. The UserLogin CMP EJB class contains a getUserDetails() and setUserDetails() method which is supposed to return a LocalInterface to the UserDetails CMP Entity bean. However, the following stacktrace is displayed
09:56:41,066 ERROR [LogInterceptor] TransactionRolledbackLocalException in method: public abstract int com.bugzero.ejb.user.EBUserLoginLocal.getCid(), causedBy:
java.sql.SQLException: Column not found, message from server: "Unknown column 'userDetails' in 'field list'"
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:1626)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:886)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:945)
at com.mysql.jdbc.Connection.execSQL(Connection.java:1844)
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1458)
at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:304)
at org.jboss.ejb.plugins.cmp.jdbc.JDBCLoadEntityCommand.execute(JDBCLoadEntityCommand.java:158)
at org.jboss.ejb.plugins.cmp.jdbc.JDBCLoadEntityCommand.execute(JDBCLoadEntityCommand.java:72)
at org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager.loadEntity(JDBCStoreManager.java:612)
at org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager.loadEntity(JDBCStoreManager.java:594)
at org.jboss.ejb.plugins.CMPPersistenceManager.loadEntity(CMPPersistenceManager.java:381)
at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.loadEntity(CachedConnectionInterceptor.java:352)
at org.jboss.ejb.plugins.EntitySynchronizationInterceptor.invoke(EntitySynchronizationInterceptor.java:239)
at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:185)
at org.jboss.ejb.plugins.EntityReentranceInterceptor.invoke(EntityReentranceInterceptor.java:114)
at org.jboss.ejb.plugins.EntityInstanceInterceptor.invoke(EntityInstanceInterceptor.java:163)
at org.jboss.ejb.plugins.EntityLockInterceptor.invoke(EntityLockInterceptor.java:89)
at org.jboss.ejb.plugins.EntityCreationInterceptor.invoke(EntityCreationInterceptor.java:54)
at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:84)
at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:267)
at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:128)
at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:118)
at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:191)
at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
at org.jboss.ejb.EntityContainer.internalInvoke(EntityContainer.java:489)
at org.jboss.ejb.Container.invoke(Container.java:700)
at org.jboss.ejb.plugins.local.BaseLocalProxyFactory.invoke(BaseLocalProxyFactory.java:375)
at org.jboss.ejb.plugins.local.EntityProxy.invoke(EntityProxy.java:38)
at $Proxy45.getCid(Unknown Source)
at com.bugzero.ejb.user.UserProfileBean.validateLogin(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.java:683)
at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:185)
at org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterceptor.java:72)
at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:84)
at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:267)
at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:128)
at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:118)
at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:191)
at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
at org.jboss.ejb.StatelessSessionContainer.internalInvoke(StatelessSessionContainer.java:331)
at org.jboss.ejb.Container.invoke(Container.java:700)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.jboss.mx.capability.ReflectedMBeanDispatcher.invoke(ReflectedMBeanDispatcher.java:284)
at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:546)
at org.jboss.invocation.local.LocalInvoker.invoke(LocalInvoker.java:101)
at org.jboss.invocation.InvokerInterceptor.invoke(InvokerInterceptor.java:90)
at org.jboss.proxy.TransactionInterceptor.invoke(TransactionInterceptor.java:46)
at org.jboss.proxy.SecurityInterceptor.invoke(SecurityInterceptor.java:45)
at org.jboss.proxy.ejb.StatelessSessionInterceptor.invoke(StatelessSessionInterceptor.java:100)
at org.jboss.proxy.ClientContainer.invoke(ClientContainer.java:85)
Current Implementation Details
The MySQL Database contains two tables viz. UserLogin and UserDetails created as follows:
CREATE TABLE USERLOGIN (
ID int(5) NOT NULL auto_increment,
CID int(5) default '0',
DEFPID int(5) unsigned default '0',
FIRSTNAME varchar(40) NOT NULL default '',
LASTNAME varchar(40) NOT NULL default '',
JOBTITLE varchar(50) NOT NULL default '',
EMAIL varchar(80) NOT NULL default '',
USERID varchar(20) NOT NULL default '',
PASSWD varchar(15) NOT NULL default '',
AUTONOTIFY char(1) NOT NULL default '',
PRIMARY KEY (ID)
) TYPE=InnoDB;
CREATE TABLE USERDETAILS (
ID int(5) NOT NULL auto_increment,
UID int(5) NOT NULL default '0',
COMPANY varchar(80) NOT NULL default '',
BUSADDR varchar(80) NOT NULL default '',
PHONE varchar(15) default '0',
EXT varchar(5) default NULL,
FAX tinyint(3) unsigned default '0',
ROLE varchar(20) NOT NULL default '',
PRIMARY KEY (ID)
) TYPE=InnoDB COMMENT='User Profile Details';
NOTE: The UID column in USERDETAILS is the foreign key (although a FOREIGN Key constraint is not present at the table level) which will hold the value of ID column which is a PRIMARY KEY in USERLOGIN table.
I have created the following entity bean classes to manage persistence for the above tables:
CMP Classes related to UserLogin
public interface EBUserLoginHome extends EJBHome
{
...
...
}
public interface EBUserLoginLocal extends EJBLocalObject
{
...
...
public abstract EBUserDetailsLocal getUserDetails();
public abstract void setUserDetails(EBUserDetailsLocal user);
...
...
}
public abstract class EBUserLoginBean implements EntityBean
{
...
...
public abstract EBUserDetailsLocal getUserDetails();
public abstract void setUserDetails(EBUserDetailsLocal user);
...
...
}
public class EBUserLoginPK implements Serializable
{
...
...
}
CMP Classes related to UserDetails
public interface EBUserDetailsLocal extends EJBLocalObject
{
...
...
}
public interface EBUserDetailsLocalHome extends EJBLocalHome{
...
...
}
public abstract class EBUserDetailsBean implements EntityBean{
...
...
}
public class EBUserDetailsPK implements Serializable{
...
...
}
Deployment Descriptors and JBOSSCMP-JDBC Settings
EJB-JAR.XML
<ejb-relation>
<ejb-relation-name>UserLogin-UserDetails</ejb-relation-name>
<ejb-relationship-role>
<ejb-relationship-role-name>UserHasUserDetails</ejb-relationship-role-name>
One
<relationship-role-source>
<ejb-name>EBUserLoginEJB</ejb-name>
</relationship-role-source>
<cmr-field>
<cmr-field-name>userDetails</cmr-field-name>
</cmr-field>
</ejb-relationship-role>
<ejb-relationship-role>
<ejb-relationship-role-name>UserDetailsPartOfUserLogin</ejb-relationship-role-name>
One
<relationship-role-source>
<ejb-name>EBUserDetailsEJB</ejb-name>
</relationship-role-source>
</ejb-relationship-role>
</ejb-relation>
JBOSSCMP-JDBC.XML
<ejb-relation>
<ejb-relation-name>UserLogin-UserDetails</ejb-relation-name>
<foreign-key-mapping/>
<ejb-relationship-role>
<ejb-relationship-role-name>UserHasUserDetails</ejb-relationship-role-name>
<key-fields>
<key-field>
<field-name>id</field-name>
<column-name>uid</column-name>
</key-field>
</key-fields>
</ejb-relationship-role>
<ejb-relationship-role>
<ejb-relationship-role-name>UserDetailsPartOfUserLogin</ejb-relationship-role-name>
</ejb-relationship-role>
</ejb-relation>
NOTE: The multiplicity tag is getting removed during submitting of this POST and therefore you might see only "One" instead of (multiplicity)One(/multiplicity) in angled brackets
I would appreciate if you could review the above mentioned details and provide inputs on what is wrong with the approach I am using to implement the One-to-One Unidirectional relationship. Also, please indicate in case any additional information is required.