You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by "Tobias Meyer (JIRA)" <ji...@apache.org> on 2013/11/14 14:19:21 UTC

[jira] [Created] (OPENJPA-2452) Unexpected ArgumentException in flush if cascaded persist failed

Tobias Meyer created OPENJPA-2452:
-------------------------------------

             Summary: Unexpected ArgumentException in flush if cascaded persist failed
                 Key: OPENJPA-2452
                 URL: https://issues.apache.org/jira/browse/OPENJPA-2452
             Project: OpenJPA
          Issue Type: Bug
          Components: kernel
    Affects Versions: 2.2.2, 2.2.1
         Environment: Java 7
            Reporter: Tobias Meyer
            Priority: Minor


I have two entities like these:
{code}
public class A {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long oid;
	
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "A_OID", referencedColumnName = "OID", nullable = false)
    @OrderColumn(name = "POSITION")
    private List < B > bs;
}

public class B {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long oid;
	
    // value column is not null in database
    private String value;
}
{code}

The application code looks like this:
{code}
EntityManager em;
A a = new A();
B b1 = new B();
B b2 = new B();
b1.setValue("b1");
//b2's value is null
List<B> bs = new ArrayList<B>();
bs.add(b1);
bs.add(b2);
a.setBs(bs);

em.persist(a);
em.flush(); //throws org.apache.openjpa.persistence.PersistenceException because b2's value is null
{code}

The code throws a PersistenceException which is expected since the not null constraint in the database for B's value is violated, but what I wouldn't expect is that the stacktrace contains a nested Exception like this:
{code}
NestedThrowables:
<openjpa-2.2.2-r422266:1468616 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: Attempt to assign id "0" to new instance "com.capgemini.tmeyer.B@14a0414" failed; there is already an object in the L1 cache with this id. You must delete this object (in a previous transaction or the current one) before reusing its id.  This error can also occur when a horizontally or vertically mapped classes uses auto-increment application identity and does not use a hierarchy of application identity classes.
FailedObject: com.capgemini.tmeyer.B@14a0414
	at org.apache.openjpa.kernel.ManagedCache.assignObjectId(ManagedCache.java:190)
	at org.apache.openjpa.kernel.BrokerImpl.assignObjectId(BrokerImpl.java:5079)
	at org.apache.openjpa.kernel.BrokerImpl.setStateManager(BrokerImpl.java:4137)
	at org.apache.openjpa.kernel.StateManagerImpl.assertObjectIdAssigned(StateManagerImpl.java:623)
	at org.apache.openjpa.kernel.StateManagerImpl.afterFlush(StateManagerImpl.java:1074)
	at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:2207)
	at org.apache.openjpa.kernel.BrokerImpl.flushSafe(BrokerImpl.java:2082)
	at org.apache.openjpa.kernel.BrokerImpl.flush(BrokerImpl.java:1853)
	at org.apache.openjpa.kernel.DelegatingBroker.flush(DelegatingBroker.java:1045)
	at org.apache.openjpa.persistence.EntityManagerImpl.flush(EntityManagerImpl.java:663)
	at com.capgemini.tmeyer.BugTest.main(BugTest.java:29)
{code}
This nested Exception only occurs when flush is explicitly called, without it there's only the PersistenceException when the (surrounding) transaction is committed.

For me it looks like the afterFlush method doesn't correctly handle the situation when a cascaded persist failed during an explicit flush and therefore the id generated by IDENTITY couldn't be set.

I didn't observe any erroneous impact beside the fact that the nested exception is quite confusing and misleading, but perhabs someone should make sure there really isn't more to it.



--
This message was sent by Atlassian JIRA
(v6.1#6144)