What kind of transaction context does an injected EntityManager have in an EJB whose transaction context is TransactionAttributeType.NOT_SUPPORTED? - jpa

Suppose I have an EJB that is annotated with:
#TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
Suppose further that it has an EntityManager injected into it:
#PersistenceContext
private EntityManager em;
If I perform various operations on the EntityManager, will a resource-local transaction be started and committed for each such operation? Or will there be one for all of them? Or is this behavior undefined by the JPA specification? I could not find a suitable paragraph either way in either the JPA 2.0 specification or the EJB 3.1 specification.
I understand that there will not be a JTA transaction started for the EJB method, but I am not clear on what kinds of transactions will be in effect for the underlying EntityManager. I am presuming that the behavior is undefined but I'm hoping that someone from the larger StackOverflow community knows better, or has insight into this area of the specification, or into the discussions that dealt with this area.

Below are the few excerpts from JSR 318 & section 13.6.5 might clear most of the questions.
13.6.2.1 NOT_SUPPORTED
The container invokes an enterprise bean method whose transaction
attribute is set to the NOT_SUPPORTED value with an unspecified
transaction context.
If a client calls with a transaction context, the container suspends
the association of the transaction context with the current thread
before invoking the enterprise bean’s business method. The container
resumes the suspended association when the business method has
completed. The suspended transaction context of the client is not
passed to the resource managers or other enterprise bean objects that
are invoked from the business method.
If the business method invokes other enterprise beans, the container
passes no transaction context with the invocation.
13.6.5 Handling of Methods that Run with “an unspecified transaction context”
The EJB specification does not prescribe how the container should
manage the execution of a method with an unspecified transaction
context—the transaction semantics are left to the container
implementation. Some techniques for how the container may choose to
implement the execution of a method with an unspecified transaction
context are as follows (the list is not inclusive of all possible
strategies):
The container may execute the method and access the underlying resource managers without a transaction context.
The container may treat each call of an instance to a resource manager as a single transaction (e.g. the container may set the
auto-commit option on a JDBC connection).
The container may merge multiple calls of an instance to a resource manager into a single transaction.
The container may merge multiple calls of an instance to multiple resource managers into a single transaction.
If an instance invokes methods on other enterprise beans, and the invoked methods are also designated to run with an unspecified
transaction context, the container may merge the resource manager
calls from the multiple instances into a single transaction.
Any combination of the above.
As mentioned above in specification section 13.6.2.1, the context interaction between the client & container is being described.
In section 13.6.5, the underlying mechanism of container for handling such transaction is being described, but it depends on the implementation.

As pointed by Nayan Wadekar, the EntityManager will have no transaction associated.
In your example you specified a transaction-scoped EntityManager (default value if not specified otherwise). This implies that methods requiring an active transaction will throw a TransactionRequiredException, like persist:
[Throws] TransactionRequiredException - if invoked on a container-managed entity manager of type PersistenceContextType.TRANSACTION and there is no transaction

Related

How do database connections get managed for Spring Data JPA repositories?

I have a question about how Spring Data repositories are handling the datasource connections. Assuming Spring Data repositories open and close the connection and the connection when the method executes, how does the transaction started by declaring #Transactional in my service layer span across multiple repository calls?
Who handles the database connections? The #Transactional annotation or the JPA repository?
tl;dr
Ultimately it's the Spring JPA / Transaction infrastructure managing the connection via the thead-bound management of EntityManager instances. The scope of the transaction is controlled by #Transactional annotations in the user code but ultimately defaulted in Spring Data JPA's repository implementation. Connection acquisition is performed eagerly in case an OpenEntityManagerInViewFilter is used (enabled by default in Spring Boot 1.x and 2.x).
Details
SimpleJpaRepository is equipped with Spring's #Transactional annotations so that it will make sure it runs transactions in cases JPA requires them (e.g. to execute a call to EntityManager.persist(…) or ….merge(…)). Their default configuration makes sure, they automatically take part in transactions started at higher levels of abstraction. I.e. if you have a Spring component that's #Transactional itself, repositories will simply participate in the already running transaction:
#Component
class MyService {
private final FirstRepository first;
private final SecondRepository second;
// Constructor omitted for brevity
#Transactional
void someMethod() {
… = first.save(…);
… = second.save(…);
}
}
Both repositories participate in the transaction and a failure in one of them will roll back the entire transaction.
To achieve that, the JpaTransactionManager will use the transaction management API exposed by JPA's EntityManager to start a transaction and acquire a connection for the lifetime of the EntityManager instance. See JpaTransactionManager.doBegin(…) for details.
The role of an OpenEntityManagerInViewFilter or –Interceptor
Unless explicitly deactivated, Spring Boot 1.x and 2.x web applications run with an OpenEntityManagerInViewFilter deployed. Its used to create an EntityManager and thus acquire a connection pretty early and keep it around until very late in the request processing, namely after the view has been rendered. This has the effect of JPA lazy-loading being available to the view rendering but keeps the connection open for longer than if it was only needed for the actual transactional work.
That topic is quite a controversial one as its a tricky balance between developer convenience (the ability to traverse object relations to loaded lazily in the view rendering phase) at the risk of exactly that triggering expensive additional queries and keeping the resources in use for a longer time.

When does flush and clear commit?

I'm using JPA EclipseLink 2.0 with Glassfish 3.1.2.2
I want to know if after I call
em.flush()
em.clear()
The objects are immediatly commited to the database. My problem is I'm doing so many transactions that I'm getting OutOfMemory. I want to avoid this by flushing the transaction's objects.
After I flush and clear, I can't see any immediate entity commited to the database, I can only see them AFTER the whole process is done, which tells me this isn't actually commiting.
If flush and clear doesn't commit:
1) What does it actually do?
2) Why am I no longer getting OutOfMemory?
Please tell me if I'm right:
The objects that were allocated in my RAM are sent to the database, but changes are not yet commited. This only means I cleared my RAM, the objects are now in the DB server but the transaction is not yet commited.
Entities are synchronized to the connected database at transaction commit time. If you only have n = 1 ongoing transaction (here: JTA/container managed), changes on one or more entities get written to the DB the moment you call flush() on the EntityManager instance.
However, changes become "visible" only after the transaction has been properly executed by the container (here: Glassfish) which is responsible for transaction handling. For reference, see. section 7.6.1 (p. 294) of JPA Spec 2.0 which defines:
A new persistence context begins when the container-managed entity manager is invoked (Specifically, when one of the methods of the EntityManager interface is invoked) in the scope of an active JTA transaction, and there is no current persistence context already associated with the JTA transaction. The persistence context is created and then associated with the JTA transaction.
The persistence context ends when the associated JTA transaction commits or rolls back, and all entities that were managed by the EntityManager become detached.
In section 3.2.4 (Synchronization to the Database) of the JPA Spec 2.0 we find:
The state of persistent entities is synchronized to the database at transaction commit.
[..]
The persistence provider runtime is permitted to perform synchronization to the database at other times as well when a transaction is active. The flush method can be used by the application to force synchronization.
It applies to entities associated with the persistence context. The EntityManager and Query setFlushMode methods can be used to control synchronization semantics. The effect of FlushModeType.AUTO is defined in section 3.8.7. If FlushModeType.COMMIT is specified, flushing will occur at transaction commit; the persistence provider is permitted, but not required, to perform to flush at other times. If there is no transaction active, the persistence provider must not flush to the database.
Most likely in your scenario, the container (Glassfish) and/or your application is configured for FlushModeType.COMMIT(*1). In case FlushModeType.AUTO is in place, it is up to the Persistence Provider (EclipseLink) which "is responsible for ensuring that all updates to the state of all entities in the persistence context which could potentially affect the result of the query are visible to the processing of the query." (Section 3.8.7, p. 122)
By contrast, the clear() method does NOT commit anything by itself. It simply detaches all managed entities from the current persistence context, thus causing any changes on entities which have not been flushed (committed) to get lost. For reference, see p. 70 of the linked JPA Spec.
With respect to the OutOfMemoryError, it's hard to tell what's causing this under which circumstances, as you did not provide much detail either. However, I would:
read the aforementioned sections of the JPA specification
check how your environment is configured and
reevaluate how your application is written/implemented, potentially making false assumptions on the transaction handling of the container it is running in.
Related to 2., you might check your persistence.xml whether it configures
<property name="eclipselink.persistence-context.flush-mode" value="COMMIT" />
and change it to AUTO to see if there is any difference.
Hope it helps.
Footnotes
*1: But that's a good guess, as you did not provide that much detail on your setup/environment.
On JPA transaction commit, JPA is doing flush automatically. You should see object in DB right after first transaction end, not only after whole process end. Check if really do more transactions or just one.

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

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.

EJB Session beans/methods transaction attributes

I am became in charge EJB 3.1/JPA part of our project running on Glassfish 4.0. I am quite new to EJB and so not very confident in Session beans(and/or their methods) transaction attributes. I am dealing with stateless session beans.
I read that NOT_SUPPORTED, NEVER, SUPPORTS transaction attributes should be used with caution because their behavior varies app server vendor. Actually, I could not find statements like that in other sources. Are they really vendor specific? Also, is that correct that not annotating method or bean defaults to REQUIRED transaction attribute for it?
And also here the situation. Let's I have transaction T and two stateless beans A and B with methods mA and mB. mA calls mB. What are the possible combinations for the transaction attributes of these methods so that the transaction T will go successfully? I know that if mA has REQUIRED and mB has NEVER the exception throw. Is SUPPORTS on mB good for any kind for incoming transaction - like a safe option to make sure any transaction will go through this method without error?
Thank you
GlassFish 4.0 is the reference implementation of Java EE 7 and according to the release notes it supports Enterprise JavaBeans 3.2 (JSR-345).
I read that NOT_SUPPORTED, NEVER, SUPPORTS transaction attributes should be used with caution because their behavior varies app server vendor. I could not find alerts in other sources rather than the one i mentioned. Please advice me If I should concerned about that.
Basically EJB specification says what to implement not how to implement thus there still may be some rare corner cases since we are not living in a perfect world. I suppose this is why you have been alerted. From the other hand I wouldn't concern about that as GlassFish is widely used across the world and it surely conforms the JSR specification.
Also, is that correct that not annotating method or bean defaults to REQUIRED transaction attribute?
Yes, this is correct. According to EJB 3.2 Specification, chapter 8.3.7 Specification of the Transaction Attributes for a Bean’s Methods:
By default, the value of the transaction attribute for a method of a
bean with container-managed transaction demarcation is the REQUIRED
transaction attribute, and the transaction attribute does not need to
be explicitly specified in this case.
Can you please advice a me source where I can find correct or in incorrect combinations of the transaction attributes on different methods of different EJBs in one call stack for one given transaction.
The ultimate source of knowledge is the mentioned EJB Specification (chapter 8.6 to be more specific) but you will find a lot of useful posts around.
In general take a closer look at transaction propagation and transaction demarcation related topics.
Will SUPPORTS attribute adapt method/bean to a calling method/bean with whatever transaction attribute, so that no error will occur?
Not really. I would say SUPPORTS propagates a transaction context (if any) of a calling method/bean, so you may safely query data within but you should avoid operations that change the persistence context.

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.