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)

Reply via email to