Exactly 50% of ejbCreate() failing
cecchet Jan 9, 2002 8:26 PMI have an application that already works fine with other application servers and I tried to port it to JBoss. I only have a problem with ejbCreate() that first succeeds then fails then succeeds then fails and so on ...
I use JBoss 2.4.3 and MySQL. For my primary key field, I use the auto_increment facility of MySQL. I have a user table that looks like that :
CREATE TABLE users (
id INTEGER UNSIGNED NOT NULL UNIQUE AUTO_INCREMENT,
firstname VARCHAR(20),
lastname VARCHAR(20),
nickname VARCHAR(20) NOT NULL UNIQUE,
password VARCHAR(20) NOT NULL,
email VARCHAR(50) NOT NULL,
rating INTEGER,
balance FLOAT,
creation_date DATETIME,
region INTEGER UNSIGNED NOT NULL,
PRIMARY KEY(id)
);
The ejbCreate() method of the UserBean is as follows :
public UserPK ejbCreate(String userFirstName, String userLastName, String userNickName, String userEmail,
String userPassword, Integer userRegionId) throws CreateException, RemoteException, RemoveException
{
id = null; // Let the database auto-increment the value
firstName = userFirstName;
lastName = userLastName;
nickName = userNickName;
password = userPassword;
email = userEmail;
regionId = userRegionId;
creationDate = TimeManagement.currentDateToString();
return null;
}
This way I let the DB assign unique id's. If you implement properly your primary key class to check for null values, it works fine. But with JBoss, on the second call to ejbCreate() (in fact after every call to ejbCreate() that was successfull) I get the following error :
[User] XAException: tx=XidImpl [FormatId=257, GlobalId=sci20//9944, BranchQual=] errorCode=XA_UNKNOWN(0)
[User] javax.transaction.xa.XAException: Rollback failed: General error: Warning: Some non-transactional changed tables couldn't be rolled back
[User] at org.jboss.pool.jdbc.xa.wrapper.XAResourceImpl.rollback(XAResourceImpl.java:219)
[User] at org.jboss.tm.TxCapsule.rollbackResources(TxCapsule.java:1539)
[User] at org.jboss.tm.TxCapsule.rollback(TxCapsule.java:394)
[User] at org.jboss.tm.TransactionImpl.rollback(TransactionImpl.java:88)
[User] at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:352)
[User] at org.jboss.ejb.plugins.TxInterceptorCMT.invokeHome(TxInterceptorCMT.java:86)
[User] at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:103)
[User] at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:106)
[User] at org.jboss.ejb.EntityContainer.invokeHome(EntityContainer.java:420)
[User] at org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker.invokeHome(JRMPContainerInvoker.java:372)
[User] at java.lang.reflect.Method.invoke(Native Method)
[User] at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:241)
[User] at sun.rmi.transport.Transport$1.run(Transport.java:152)
[User] at java.security.AccessController.doPrivileged(Native Method)
[User] at sun.rmi.transport.Transport.serviceCall(Transport.java:148)
[User] at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:465)
[User] at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:706)
[User] at java.lang.Thread.run(Thread.java:484)
[User] TRANSACTION ROLLBACK EXCEPTION:INSERTING AN ALREADY EXISTING BEAN, ID = edu.rice.rubis.beans.UserPK@0; nested exception is:
java.lang.IllegalStateException: INSERTING AN ALREADY EXISTING BEAN, ID = edu.rice.rubis.beans.UserPK@0
[User] java.lang.IllegalStateException: INSERTING AN ALREADY EXISTING BEAN, ID = edu.rice.rubis.beans.UserPK@0
[User] at org.jboss.ejb.plugins.AbstractInstanceCache.insert(AbstractInstanceCache.java:247)
[User] at org.jboss.ejb.plugins.EntityInstanceInterceptor.invokeHome(EntityInstanceInterceptor.java:171)
[User] at org.jboss.ejb.plugins.EntityLockInterceptor.invokeHome(EntityLockInterceptor.java:108)
[User] at org.jboss.ejb.plugins.TxInterceptorCMT.invokeNext(TxInterceptorCMT.java:135)
[User] at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:307)
[User] at org.jboss.ejb.plugins.TxInterceptorCMT.invokeHome(TxInterceptorCMT.java:86)
[User] at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:103)
[User] at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:106)
[User] at org.jboss.ejb.EntityContainer.invokeHome(EntityContainer.java:420)
[User] at org.jboss.ejb.plugins.jrmp.server.JRMPContainerInvoker.invokeHome(JRMPContainerInvoker.java:372)
[User] at java.lang.reflect.Method.invoke(Native Method)
[User] at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:241)
[User] at sun.rmi.transport.Transport$1.run(Transport.java:152)
[User] at java.security.AccessController.doPrivileged(Native Method)
[User] at sun.rmi.transport.Transport.serviceCall(Transport.java:148)
[User] at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:465)
[User] at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:706)
[User] at java.lang.Thread.run(Thread.java:484)
The warning about the rollback failing is ok since I use non-transactional tables in MySQL.
I don't really understand the problem with the primary keys and especially why it works again just after throwing this exception (something is resetted ?).
If it can help, here is the UserPK code:
public class UserPK implements java.io.Serializable {
public Integer id;
public UserPK() {}
public UserPK(Integer uniqueId)
{
id = uniqueId;
}
public int hashCode()
{
if (id == null)
return 0;
else
return id.intValue();
}
public boolean equals(Object other)
{
boolean isEqual = false;
if (other instanceof UserPK)
{
if (id != null)
isEqual = (id == ((UserPK)other).id);
else
isEqual = (id.intValue() == ((UserPK)other).id.intValue());
}
return isEqual;
}
}
Note that in the reference UserPK@0 printed in the stack trace, the 0 corresponds to the hashCode value. If I return a random number instead of 0 if id is null, it still does not work (every 2 calls) but I can see different UserPK@xxx in the stack trace.
Any help will be greatly appreciated. At least it also works once every 2 calls ! :-)
Emmanuel