1
votes

I've set up a Spring ROO application, set persistence to OpenJPA and created some entities. Then I replaced Spring MVC with Apache Wicket. Stuff seems to be working fine and I've successfully displayed a list of Customer entities.

Next up was the editing view for the customer. For now I've made a Wicket form that uses the OpenJPA entity directly as the form model, and thus I had to make the entity class implement Serializable.

Now, I'm not sure how to correctly implement the OpenJPA persistence, what I've got now is this:

@Override
protected void onSubmit() {
    try {
        if (customer.getId()!=null) {
            customer.merge();
        }
        else {
            customer.persist();
        }
    }
    catch (Exception e) {
        throw new Error(e);
    }
    super.onSubmit();
}

That works, but only once per Customer object. Somehow. That is, I submit my form once and it works both with a new customer (.persist()) and a existing customer (.merge()). However, I submit the form again for the same customer I get this error (I added some linebreaks here):

<openjpa-2.0.0-r422266:935683 nonfatal store error>
org.apache.openjpa.persistence.OptimisticLockException:
An optimistic lock violation was detected when flushing object instance "no.magge.iumb.domain.crm.PrivateCustomer-379" to the data store.
This indicates that the object was concurrently modified in another transaction.

My question is, what is the correct way to persist with OpenJPA and why am I getting that error ?

Wicket-wise: Should I have created a separate Wicket IModel with a detachable Customer model and could that be the reason that I have these problems?

Thanks a bunch for any advice!

1
Just as a note, if you haven't already, take a look at the Open Session iv View pattern and it's implementation in Wicket + Spring.. It sounds related to your problem, but I've only worked with Hibernate, so I cant formulate an answer that'll work for you.. - Tim
Hm, yeah - might be this is related. As stated in the answer below I should really redesign the app so I can do some testing at the different application levels. I'm using OpenJPAs filter which I understood was supposed to open and close a session per request, which seems to be the essence of the Open Session in View pattern? - Magnus

1 Answers

2
votes

Do yourself a favor and separate your application layers. Code in a view should not ever access a Database.

Create a Service layer and / or a Dao layer, unit test the code of those layers to see that they are working and then inject a dao or service object into the wicket component. (I'd recommend you to use spring for that, but you can also do it manually)

With your scenario, there are so many different things that can fail in one spot, and it's nearly impossible to separate them.

Here are some pointers: