4 Replies Latest reply on Apr 3, 2004 4:47 AM by aloubyansky

    DuplicateKeyException threw wrongly - Exception handling BUG

    romilsoncarvalho

      Hi,
      I have the follow table :

      HOUSE (
      CODE NUMBER(38) PK NOT NULL
      NAME VARCHAR2(100) NOT NULL
      CITY_CODE NUMBER(38) FK NOT NULL
      )

      I have other table CITY that is not important in this report, but that have a relation with this table, througt the CITY_CODE FK column.

      When I create my (Entity Bean CMP 2.0) HouseBean, without inform the City Code, a DuplicateKeyException is threw.

      My HOUSE table is empty, and my PK is assigned with a valid value.

      I have not a CMR relation between House and City, because this is not important too.

      The expected exception was a CreateException encapsulating a SQLException with the Oracle Error:
      ORA-02291: integrity constraint (J2EE.FK_MUNI) violated - parent key not found

      But a DuplicateKeyException:Entity with primary key already exists is threw instead.

      Inspecting inside the Jboss source code, we has notice that the method JDBCAbstractCreateCommand.performInsert(...) catch the SQLException:

      } catch(SQLException e) {
      if(exceptionProcessor != null && exceptionProcessor.isDuplicateKey(e)) {
      throw new DuplicateKeyException("Entity with primary key already exists");
      } else {
      log.error("Could not create entity", e);
      throw new CreateException("Could not create entity:" + e);
      }
      }

      We supose that the real problem is in exceptionProcessor.isDuplicateKey that evals...:

      public final class SQLExceptionProcessor extends ServiceMBeanSupport implements SQLExceptionProcessorMBean {

      private static final String DUPLICATE_CODE = "23000";

      /**
      * Return true if the exception indicates that an operation failed due to a
      * unique constraint violation. This could be from any unique constraint
      * not just the primary key.
      *
      * @param e the SQLException to process
      * @return true if it was caused by a unique constraint violation
      * @jmx.managed-operation
      */
      public boolean isDuplicateKey(SQLException e)
      {
      return DUPLICATE_CODE.equals(e.getSQLState());
      }
      }

      For some reason, the equals comparation results in True, and the code considers the NOT NULL FOREIGN KEY Constraint Violation As a Unique or PrimaryKey Constraint Violation. And so , threw DuplicateKeyException.

      The SQLState 23000 is applied to:

      ORA-01400: cannot insert NULL into ("J2EE"."IMOVEL_TS"."COD_MUNI")
      ORA-02291: integrity constraint (J2EE.FK_MUNI) violated - parent key not found

      ORA-00001: unique constraint (J2EE.PK_IMOVEL) violated "DuplicateK..."

      Really, may be there are no others ways to diference this errors. But throw a DuplicateKeyException when I insert Null in a Not Null Column, is very wrong way to resolve this question !!!!!

      And this problem is enforced because the SQLException is not Logged ! And simply its stack trace is ignored .....

      So please, if there are not a better way to resolve this, then include Log debug to save the stack trace. This way, the developers will know that the Enity Bean is not with a existent Priimary Key, but a NULL Field has not been assigned or a Wrong Foreign Key is set.

      Thans a lot.

      - Romilson C. Carvalho
      - Marcelo William
      Unisys Brazil.


      ---------------------------------------------------
      javax.ejb.DuplicateKeyException: Entity with primary key already exists
      at org.jboss.ejb.plugins.cmp.jdbc.JDBCAbstractCreateCommand.performInsert(JDBCAbstractCreateCommand.java:298)
      at org.jboss.ejb.plugins.cmp.jdbc.JDBCAbstractCreateCommand.execute(JDBCAbstractCreateCommand.java:138)
      at org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager.createEntity(JDBCStoreManager.java:554)
      at org.jboss.ejb.plugins.CMPPersistenceManager.createEntity(CMPPersistenceManager.java:208)
      at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.createEntity(CachedConnectionInterceptor.java:269)
      at org.jboss.ejb.EntityContainer.createLocalHome(EntityContainer.java:581)
      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.EntityContainer$ContainerInterceptor.invokeHome(EntityContainer.java:1043)
      at org.jboss.ejb.plugins.AbstractInterceptor.invokeHome(AbstractInterceptor.java:88)
      at org.jboss.ejb.plugins.EntitySynchronizationInterceptor.invokeHome(EntitySynchronizationInterceptor.java:197)
      at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invokeHome(CachedConnectionInterceptor.java:214)
      at org.jboss.ejb.plugins.AbstractInterceptor.invokeHome(AbstractInterceptor.java:88)
      at org.jboss.ejb.plugins.EntityInstanceInterceptor.invokeHome(EntityInstanceInterceptor.java:89)
      at org.jboss.ejb.plugins.EntityLockInterceptor.invokeHome(EntityLockInterceptor.java:61)
      at org.jboss.ejb.plugins.EntityCreationInterceptor.invokeHome(EntityCreationInterceptor.java:28)
      at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:88)
      at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:267)
      at org.jboss.ejb.plugins.TxInterceptorCMT.invokeHome(TxInterceptorCMT.java:98)
      at org.jboss.ejb.plugins.SecurityInterceptor.invokeHome(SecurityInterceptor.java:92)
      at org.jboss.ejb.plugins.LogInterceptor.invokeHome(LogInterceptor.java:120)
      at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invokeHome(ProxyFactoryFinderInterceptor.java:93)
      at org.jboss.ejb.EntityContainer.internalInvokeHome(EntityContainer.java:483)
      at org.jboss.ejb.Container.invoke(Container.java:720)
      at org.jboss.ejb.plugins.local.BaseLocalProxyFactory.invokeHome(BaseLocalProxyFactory.java:293)
      at org.jboss.ejb.plugins.local.LocalHomeProxy.invoke(LocalHomeProxy.java:110)
      at $Proxy43.create(Unknown Source)

      --------------------------------------------------------------------------