Should a GWT RequestFactory Locator method expect a passed-in JPA entity to be attached or detached? - gwt

Right now I have to call JPA merge() at the end of my service method to persist changes. I'm doing this because our servlets do not start a transaction before the Locator.find() runs. They start them later in the service method.
I know that RequestFactory uses my Locator find() and updates the object based on what the client sent to the server, so I was just wondering if maybe that object should be an attached object and therefore allow JPA to handle the changes "naturally" rather than explicitly call merge().
Or perhaps this just depends on the situation?

I don't know JPA much, but I confirm that you SHOULD scope your transactions to your service methods: a RequestContext is a batch of requests that can each succeed or fail independently, putting them all in a single transactions would violates that principle. There are also cases where your Localor#find can be called, changes applied to the entity, but then the entity is never passed to any service method: you wouldn't want the changes to be persisted in this case.

Related

What are the differences of using value proxies for my entities instead of entity proxies?

So far i understand that i will have no more need to define an #version field in my entitites and no more need to use an entity locator. And for value proxies i will have to usenormal editors. Any other diffrences, advantages, disadvantages? What about in the context of using request factory in conjunction with spring
The main difference is that with EntityProxy, the client can send a diff of changes rather than the entire object graph. This is made possible because EntityProxys have an identity, so the server can fetch the identity from the datastore and then apply the diff/patch sent from the client, and only then the entity will be passed to your service methods.
With ValueProxy you basically have an equivalent of GWT-RPC: the object is reconstructed from scratch on the server, and not associated with your datastore (in the case of JPA for instance, it's not attached to the session). Depending on your datastore API, this can make things more complex to handle in your service methods.
Other than that, you'll also lose the EntityProxyChange events.

JPA entities PrePersist and PreRemove callbacks, are they fired only once per life time of an application?

The JPA 2.0 specification talks about the PrePersist and PreRemove callbacks on page 95:
The PrePersist and PreRemove callback methods are invoked for a given
entity before the respective EntityManager persist and remove
operations for that entity are executed. For entities to which the
merge operation has been applied and causes the creation of newly
managed instances, the PrePersist callback methods will be invoked for
the managed instance after the entity state has been copied to it.
These PrePersist and PreRemove callbacks will also be invoked on all
entities to which these operations are cascaded. The PrePersist and
PreRemove methods will always be invoked as part of the synchronous
persist, merge, and remove operations.
My mother tongue is not English, so I may misunderstand what would be quite clear for another dude. Or the quote could use a clarification or two. But I fail to understand:
Will the PrePersist and PreRemove callback be called only once per life time of a running Java EE application?
If the callbacks are fully synchronized with calls to EntityManager#persist(java.lang.Object) and EntityManager#remove(java.lang.Object), then yes I expect the callbacks to be fired only once. I usually don't persist my entities more than once, nor do I delete them over and over again just for the fun of it. Alas this is "just" my reasoning.
But! Say you have code that shall persist one entity at the beginning of a new transaction, then within the same transaction you hook the entity up with some new and non persisted entities. It would be intuitive and certainly not wrong to provoke a cascading persist operation on all those relationships with a secondary smooth call to EntityManager#persist on the owning entity before the transaction commit. In that case.. would the PrePersist callback be called again, a secondary time?

How to get a detached object from JPA

In my application I need most objects fetched in detached mode (fetched with the find API).
I'm wondering if there is a way to ask a detached object from the JPA provider and save the extra call to detach() API.
In additional I would expect the object created in such mode to be less expensive since the JPA provider doesn't need to add it to the entity manager context.
Is there a way to achieve this with JPA APIs?
Is there a way to achieve such functionality with query results?
Specifically I'm using Eclipse Link so if there is a specific way to do it with this implementation it will be helpful as well.
You can fetch a detached entity without an extra call to detach() if you fetch it outside a transaction. If you are not using container-managed transactions, it's trivial, simply do not start a transaction.
If you are using CMT, you have to make sure the requesting object is not a transaction-enabled EJB:
if in an EJB, suspend the transaction by annotating the appropriate method with:#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED),
or
call the EntityManager from a POJO. You dont have to call it directly, it only impotrant that the query result will end in a non-EJB object.
AFAIK, there is no performance gain to be expected, since the query result will always be put in the current persistence context, however shortlived it may be.
EDIT: There is another possibility to get detached objects which does not depend on transaction demarcations: JPA constructor expressions:
List<DTO> dtos = em.createQuery("SELECT NEW com.example.DTO( o.title, o.version) FROM Entity o").getResultList();
The constructed type must have a constructor with all the relevant attributes. The objects in the list, entities or not, will always be created detached. However there is a small overhead of instantiating a new object.

Is is possible to attach EntityProxy to another RequestContext ? And should I?

I have a little form that edits my entity. I create that entity using one instance of RequestContext and then in handler of "save" button I'm trying to persist it using another instance of RequestContext.
Attempt to persist fails with expected exception: java.lang.IllegalArgumentException: Attempting to edit an EntityProxy previously edited by another RequestContext
The questions are:
Is is possible to attach EntityProxy to another RequestContext ?
Is it right thing to do ? Or I should reuse one RequestContext saving it
as property of my class ?
Reuse the existing one. If you need a new one, merge them. But it really doesn't make sense to make a new one. Here's why:
When you make a RF call to the server, it goes through several steps, as it is geared mostly toward how to read and persist entities, and the various value properties they work with.
Create or retrieve any of the instances to be dealt with
Apply setters to these instances, new or existing, and validate them
Run the service invocations, either as methods invoked on the entities, static calls, or service calls.
These three steps are done in this order to ensure that the object modified and then passed to a service call makes sense when it gets there. Future calls (i.e. other requests) then probably do not need to make those same changes to the same entities, and if they do, then they need to make the changes themselves.
A given RequestContext consists of all of these things then. If you had two requests, and one represented the setters to be called (the edits from the form) and the other the service request, firing one means only calling the setters, but not the service call to save it, while firing the other means only call save without the service call.
After an EntityProxy has been marked as being edited by one request context, attempting to use it in another one is almost certainly an error, so the exception you are seeing is thrown. Use the existing one, or use RequestContext.append if needed to switch to a new RequestContext type to actually run the save operation.
RequestFactory isn't RPC - your objects aren't just Java Beans, but are proxies (either EntityProxy or ValueProxy) of some server object, and requests are used to manipulate them asynchronously.

How to persist JPA entities even when EJB method throws an exception?

I have an EJB, whose method (among other things) persists JPA entity. If the method throws an error, the transaction is rolled back and the entity is not persisted.
However, I do want that entity to be persisted regardless of any exceptions, that might occur in the EJB method.
I'm using WebSphere 7.0, EJB3.0, JPA 1.0 (OpenJPA that is in WAS), DB2, if it matters.
I tried setting #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) on top of EJB; with that, entity is not persisted even if there is no exception. I also tried commiting transaction myself (em.getTransaction().commit()), but getTransaction() throws exception (because transactions are managed by container).
Use bean-managed transactions.
#Stateless
#TransactionManagement(TransactionManagementType.BEAN)
public class MyEJB {
#PersistenceContext(unitName="...")
private EntityManager _em;
#Resource
private UserTransaction _utx;
public void myEJBMethod() {
_utx.begin();
// Use _em
_utx.commit();
// Do other work that might throw an exception.
}
}
Alternatively, use TransactionAttributeType.REQUIRES_NEW as suggested by edalorzo.
I am not an expert on EJBs, but I have been dealing with JPA and transactions for a few days now.
I recently answered another question about how entities resided in a context, and how this works in Java EE applications, the context is linked with your JTA transaction.
You can see details of this answer by clicking here. I think it is useful to understand how to context works in order to comprehend the nature of problems like the one you describe.
If you do not provide transaction support, then there is nothing to persist from the container standpoint, and therefore, your changes to the context are transient.
Also you have to consider that once an exception occurs, your context becomes invalid, and the entities in it get detached. (There are a few exceptions to this, like NoResultException).
Thus, from that point on, if you want to commit something, you need a new JTA transaction, with a new fresh JPA context in order to be able to commit changes to the database.
As I said, I am not an expert in EJBs, but if your method fails due to exceptions and you still would like to retry the transaction again by re-invoking the method, then you could force a new transaction to be created every time the method is invoked and by this, you would create a new fresh JPA context.
On the other hand, if you want your modifications to the entities to be persisted, regardless of exceptions in the method, then you might like to consider moving the code that is updating the entities to a new EJB method defined to start a new transaction (TransactionAttributeType.REQUIRES_NEW) every time you invoke it.
By the time this second inner method finishes, your work over the transactions will be automatically flushed to the database, regardless of the outer method of you EJB failing.
Basically, you would be providing a new context for your entities, and linking such context to a new transaction, scoped to commit when the inner method completes.
The natural behavior in EJB containers, as far as I understand, is that ever method joins the already existing transaction, and this is what you might like to prevent, from my point of view.
Another alternative: if you want to control your context using a different transaction support then you might like to consider providing a resource-local based persistence unit and you can manually instantiate your entity manager and control transaction scope as you wish. But honestly, this does not sound like a good idea to me, at least no in the context of the problem that you described.