JPA EntityManager.flush() is not called by glassfish 5.1 EE container.
In Java SE environment:
EntityTransaction t = em.getTransaction();
t.begin();
// persist entities
em.persist(entity);
t.commit();
commit() will flush entities in persistence context.
Java EE environment e.g. Glassfish:
#Stateless
public class DataManagerBean {
#PersistenceContext
EntityManager em;
public void persist(Object entity) {
em.persist(entity);
}
}
JSF Bean:
#Named
#ViewScoped
public class FooBean {
#EJB
DataManagerBean dataManagerBean;
public void createFoo() {
dataManagerBean.persist(foo);
}
}
Application can not call em.getTransaction(). Transaction is managed by container. JPA provider entityManager.flush() is not called before entityManager.close() is called. As a result the entity is not created in database.
In EE environment, the database connection obtained by JPA provider EntityManager is the same as one used by container?
How does EE container tell JPA provider to flush entities to persistence if flush() is not called?
It is dependant on the way you calling your business method. In one word, beeing defaulted -- transaction begins when your flow enters FIRST business method (or Interceptor, decorating your first business method) and ends when your flow leaves last business method in the stack (or Interceptor, decorating your first business method).
You can manage transactions using #TransactionAttribute annotation with appropriate TransactionAttributeType (REQUIRED is default if not annotated). For example:
#Stateless
public class DataManagerBean {
#PersistenceContext
EntityManager em;
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void persist(Object entity) {
em.persist(entity);
}
}
In this case being called DataManagerBean.persist starts new transaction and commit and flush changes when being leaved. In case of error it will roll transaction back and throw exception you can catch at calling business method.
Related
I'm learning persistence in Java following some tutorial.
I'm using Java EE 7 and Payara server.
I noticed that each uses a different method for persistence.
Examples:
simple
#Stateless
public class BookServiceBean implements BookService {
#PersistenceContext
private EntityManager em;
public void createOrUpdate(Book book) {
em.persist(book);
}
public void remove(Book book) {
em.remove(book);
}
}
with flush(), this is used when validation strategy isn't set on "AUTO" in persistene.xml, right?
#Stateless
public class BookServiceBean implements BookService {
#PersistenceContext
private EntityManager em;
public void createOrUpdate(Book book) {
em.persist(book);
em.flush();
}
public void remove(Book book) {
em.remove(book);
em.flush();
}
}
with transaction
#Stateless
public class BookServiceBean implements BookService {
#PersistenceContext
private EntityManager em;
public void createOrUpdate(Book book) {
utx.begin();
em.persist(book);
utx.commit();
}
public void remove(Book book) {
utx.begin();
em.remove(book);
utx.commit();
}
}
When and why do I have to use the last one?
Is it necessary to use em.close() at the end of each method?
What are the good practices?
The first one, an EJB method without all that manual flush and transaction fuzz, is the canonical approach. A single EJB method call counts by default already as a single full transaction. The EJB container will transparently begin the transaction before the method is invoked and commit the transaction when the method returns (or rollback when an application exception is thrown from the method).
The manual flush in second example is unnecessary. Generally, you want to use em.flush() only when you're modifying an entity (i.e. making it "dirty") and want afterwards (indirectly) perform a SELECT on it within the very same transaction. It's rare, but there are real world use cases for it, generally when you'd like to SELECT a parent whose the dirty entity is a child of.
The manual transaction management in third example is totally unnecessary. You should already realize that after having read the first paragraph. Manual transaction management is only necessary when you aren't using JTA, but RESOURCE_LOCAL (usually, in Java SE not Java EE).
See also:
When is it necessary or convenient to use Spring or EJB3 or all of them together?
JSF request scoped bean keeps recreating new Stateful session beans on every request?
Handling service layer exception in Java EE frontend method
I'm writing a custom implementation for a Spring Data JPA repository. So I have:
MyEntityRepositoryCustom => interface with the custom methods
MyEntityRepositoryUmpl => implementation of the above interface
MyEntityRepository => standard interface which extends JpaRepository and MyEntityRepositoryCustom
My problem is this: within the implementation of MyEntityRepositoryUmpl I need to access the entity manager that was injected into Spring Data. How to get it?
I can use #PersistenceContext to get it autowired, but the problem is that this repository must work in an application that sets up more than one persistence units. So, to tell Spring which one I need, I would have to use #PersistenceContext(unitName="myUnit"). However, since my repositories are defined in a reusable service layer, I can't know at that point what will be the name of the persistence unit that the higher-level application layer will configure to be injected into my repositories.
In other words, what I would need to do is to access the entity manager that Spring Data itself is using, but after a (not so quick) look at Spring Data JPA documentation I couldn't find anything for this.
Honestly, the fact that the Impl classes are totally unaware of Spring Data, although described as a strength in Spring Data manual, is actually a complication whenever you need to access something that is usually provided by Spring Data itself in your custom implementation (almost always, I would say...).
Since version Spring Data JPA 1.9.2 you have access to EntityManager through JpaContext, see: http://docs.spring.io/spring-data/jpa/docs/1.9.2.RELEASE/reference/html/#jpa.misc.jpa-context.
Example:
#Component
public class RepositoryUtil
{
#Autowired
private JpaContext jpaContext;
public void deatach(T entity)
{
jpaContext.getEntityManagerByManagedType(entity.getClass()).detach(entity);
}
}
P.S.
This approach will not work if you have more than one EntityManager candidate for some Class, see implementation of JpaContext#getEntityManagerByManagedType -> DefaultJpaContext#getEntityManagerByManagedType.
The best I could find is to set up a "convention": my repositories declare that they expect a persistence unit named myConventionalPU to be made available. The application layer then assigns that alias to the entity manager factory that it sets up and injects into Spring Data, so my custom implementations can receive the correct EMF with autowiring by using that alias. Here's an excerpt of my application context:
<bean id="myEntityManagerFactory" name="myConventionalPU"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
[...]
</bean>
<jpa:repositories base-package="com.example"
entity-manager-factory-ref="myEntityManagerFactory"
transaction-manager-ref="transactionManager" />
And within my custom implementation:
#PersistenceContext(unitName = "myConventionalPU")
private EntityManager em;
I opened DATAJPA-669 with this requirement.
Spring Data JPA uses Auto configuration classes to auto generate entityManagerFactory, dataSource and transactionManager.
If you want get access to entityManager and control the instantiation and settings, you need to define your own PersistenceConfiguration. Below is the sample code using Java Config
#Configuration
#EnableTransactionManagement
#EnableJpaRepositories(basePackages = { "com.test.repositories.*" })
public class PersistenceJpaConfig {
#Autowired
JpaVendorAdapter jpaVendorAdapter;
#Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setName("testdb")
.setType(EmbeddedDatabaseType.HSQL)
.build();
}
#Bean
public EntityManager entityManager() {
return entityManagerFactory().createEntityManager();
}
#Bean
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
lef.setDataSource(dataSource());
lef.setJpaVendorAdapter(jpaVendorAdapter);
lef.setPackagesToScan("com.test.domain.*");
lef.afterPropertiesSet();
return lef.getObject();
}
#Bean
public PlatformTransactionManager transactionManager() {
return new JpaTransactionManager(entityManagerFactory());
}
}
If you have multiple data sources, follow this article.
We use Guice Persist to inject EntityManager in our project.
E.g.
public class MyDao{
#Inject
EntityManager em;
public void someMethod(){
//uses em instance
}
}
But it is unclear for us how injected instance of EntityManager is about to be used.
What type of EntityManager is this? (see e.g.: types of entity managers) Under the hood Guice Persist instantiates it via EntityManagerFactory.createEntityManager() so I'd say it's application-managed entity manager. But in official Wiki they write about seesion-per-transaction strategy, which suggests that EntityManager is (pseudo) transaction-scoped.
Should we invoke close() on it manually? Or Guice will take care of it?
What is the scope of first level cache? Only single transaction (like in transaction-scoped entity managers) or as long as I use the same injected instance of EntityManager (like in application managed entity managers)?
Even though the question is perfectly answered by Piotr I'd like to add some practical advise on how to use guice-persist.
I've been having issues with it which were pretty hard to debug. In my application certain threads would display outdated data and sometimes EntityManager instances were left with old dead database connections. The root cause was to be found in the way I used the #Transactional annotation (I only used them for methods that do updates/inserts/deletes, not for read-only methods). guice-persist stores EntityManager instances in a ThreadLocal as soon as you call get() on an injected Provider<EntityManager> instance (which I did for read-only methods). However, this ThreadLocal is only removed if you also call UnitOfWork.end() (which normally is done by the interceptor if #Transactional is on the method). Not doing so will leave the EM instance in the ThreadLocal so that eventually every thread in your thread pool will have an old EM instance with stale cached entities.
So, as long as you stick to the following simple rules the usage of guice-persist is straight forward:
Always inject Provider<EntityManager> instead of EntityManager directly.
For transaction-scoped semantics: always annotate each method with #Transactional (even the read-only methods). This way the JpaLocalTxnInterceptor will intercept the calls to your annotated methods making sure not only to start and commit transactions but also to set and unset EM instances in the ThreadLocal.
For request-scoped semantics: use the PersistFilter servlet filter that ships with guice-persist. It will call begin() and end() on the UnitOfWork for you before and after the request is done, thereby populating and cleaning up the ThreadLocal.
Hope this helps!
I did some research of the source code of Guice-persist and read through comments under Guice-persist wiki pages and these are the answers that I needed:
1 . Lifecycle management of EntityManager is kind of broken if it's injected via #Inject EntityManager. As stated in one of the comments on the Wiki:
I confirm that inject directly an EntityManager instead of a provider
can be dangerous. If you're not inside a UnitOfWork or a method
annotated with #Transaction, the first injection of an EntityManager
in a thread will create a new EntityManager, never destroy it, and
always use this specific EntityManager for this thread (EM are stored
thread-local). This can lead to terrible issues, like injection of
dead entityManager (connection closed, etc) So my recommendation if to
always inject a Provider, or at least to inject
directly an EntityManager only inside an opened UnitOfWork.
So example in my question isn't the most correct usage. It creates singleton instance of EntityManager (per-thread) and will inject this instance everywhere :-(.
However if I've injected Provider and used it inside #Transactional method then the instance of EntityManager would be per-transaction. So the answer to this question is: if injected and used correctly, the entity manager is transaction-scoped.
2 . If injected and used correctly then I don't need to manualy close entity manager (guice-persist will handle that for me). If used incorrectly, closing manually would be very bad idea (closed instance of EntityManager would be injected in every place when I #Inject EntityManager )
3 . If injected and used correctly then the scope of L1 cache is single transaction. If used incorrectly, the scope of the L1 cache is the lifetime of application (EntityManager is singleton)
1. It depends on you module cofiguration. There are some basic bindings:
JpaPersistanceService
public class JpaPersistanceService implements Provider<EntityManager> {
private EntityManagerFactory factory;
public JpaPersistanceService(EntityManagerFactory factory) {
this.factory = factory;
}
#Override
public EntityManager get() {
return factory.createEntityManager();
}
}
Module binding
EntityManagerFactory factory = Persistence.createEntityManagerFactory(getEnvironment(stage));
bind(EntityManager.class).annotatedWith(Names.named("request")).toProvider(new JpaPersistanceService(factory)).in(RequestScoped.class);
bind(EntityManager.class).annotatedWith(Names.named("session")).toProvider(new JpaPersistanceService(factory)).in(SessionScoped.class);
bind(EntityManager.class).annotatedWith(Names.named("app")).toProvider(new JpaPersistanceService(factory)).asEagerSingleton;
Usage
#Inject #Named("request")
private EntityManager em; //inject a new EntityManager class every request
#Inject #Named("session")
private Provider<EntityManager> emProvider; //inject a new EntityManager class each session
//This is little bit tricky, cuz EntityManager is stored in session. In Stage.PRODUCTION are all injection created eagerly and there is no session at injection time. Session binding should be done in lazy way - inject provider and call emProvider.get() when em is needed;
#Inject #Named("application")
private EntityManager em; //inject singleton
2. Yes, you should or you will use JpaPersistModule [javadoc]
3. Well, this is about JPA configuration in persistence.xml and EntityManager scope
I'm injecting a provider .... but I suspect something is wrong.
When I try to redeploy an application ALWAYS I have to restar the server because the JPA classes are cached.
It happens the following pseudo-bug
https://bugs.eclipse.org/bugs/show_bug.cgi?id=326552
Theoretically by injecting a Provider and getting an instance of EntityManager you should not close anything ....
I tried to run the simple JEE6 application generated by maven archetype groupId: org.fluttercode.knappsack , artifactID: jee6-sandbox-archetype in JBoss7.
(went through this turial, sorry, in German)
However, when calling the welcome JSF, I get the following error message:
org.jboss.weld.exceptions.IllegalProductException: WELD-000053 Producers
cannot declare passivating scope and return a non-serializable class:
[method] #Produces #DataRepository #ConversationScoped
public org.rap.jee6project.bean.DataRepositoryProducer.getEntityManager()
org.jboss.weld.bean.AbstractProducerBean.checkReturnValue(AbstractProducerBean.java:264)
org.jboss.weld.bean.AbstractProducerBean.create(AbstractProducerBean.java:362)
org.jboss.weld.context.AbstractContext.get(AbstractContext.java:122)
Indeed, the DataRepositoyProducer class which is supposed to return an EntityManager instance, is defined an annotated as follws:
#Stateless
public class DataRepositoryProducer {
private EntityManager entityManager;
#Produces #DataRepository #ConversationScoped
public EntityManager getEntityManager() {
return entityManager;
}
#PersistenceContext
public void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
}
If I use #RequestScoped, the application runs as promised. I wonder why other people who went through this tutorial didn't experience this problem? And how to fix it properly (using #RequestScoped means that the bean is recreated for each user request, right?, which I expect to be not very efficient)
The official JEE6 Tutorial says: "Beans that use session, application, or conversation scope must be serializable, but beans that use request scope do not have to be serializable" . However, that does not seem to be the problem here, since the server is not comlaining about the bean not serializable but the product of the producer bean.
It should be..
#Stateful
#ConversationScoped
public class ProducerCreator implements Serializable{
#PersistenceConText
private EntityManager entityManager;
....
}
and if you want to use the same entity context in of each conversation it should be
#PersistenceContex(type = PersistenceContextType.EXTENDED)
finally, If you want to have service layer, should create stateful and inject to conversation bean
I had same problem running the demo on a jboss7.
Just remove #ConversationScoped at getEntityManager() did the trick to me to let it deploy.
Even though there are some flaws:
javax.servlet.ServletException: javax.faces.component.StateHolderSaver cannot be cast to [Ljava.lang.Object;
javax.faces.webapp.FacesServlet.service(FacesServlet.java:606)
org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62)
I don't know exactly, if it is related, but I guess so.
Remember: EntityManager is not serializable, so it cannot be stored in ConversationScope
#Path(value = "/user")
#Stateless
public class UserService {
#Inject
private UserManager manager;
#Path(value = "/create")
#GET
#Produces(value = MediaType.TEXT_PLAIN)
public String doCreate(#QueryParam(value = "name") String name) {
manager.createUser(name);
return "OK";
}
}
here is the user manager impl
public class UserManager {
#PersistenceContext(unitName = "shop")
private EntityManager em;
public void createUser(String name) {
User user = new User();
user.setName(name);
// skip some more initializations
em.persist(user);
}
}
the problem is if i do not mark UserService as #Stateless then the manager field is null
but if i mark #Stateless, i can have the manager field injected, and the application works as i can get the data saved into db
just wondering, what is the reason behind this?
and is this the preferred way to wiring the application?
well, i am thinking to pull out the EntityManager to a producer, so that it can be shared
the problem is if I do not mark UserService as #Stateless then the manager field is null
For injection to occur, the class has to be a managed component such as Enterprise Beans, Servlets, Filters, JSF managed beans, etc or CDI managed bean (this is the new part with Java EE 6, you can make any class a managed bean with CDI).
So, if you don't make your JAX-RS endpoint an EJB, how to enable injection? This is nicely explained in JAX-RS and CDI integration using Glassfish v3:
There are two ways CDI managed beans
are enabled:
instantiated by CDI, life-cycle managed by Jersey. Annotate with
#ManagedBean and optionally annotate
with a Jersey scope annotation.
instantiated and managed by CDI. Annotate with a CDI scope annotation,
like #RequestScoped (no #ManagedBean
is required)
I also suggest checking the resources below.
and is this the preferred way to wiring the application?
I'd say yes. CDI is very nice and... don't you like injection?
well, I am thinking to pull out the EntityManager to a producer, so that it can be shared
Shared between what? And why? In you case, you should use an EntityManager with a lifetime that is scoped to a single transaction (a transaction-scoped persistence context). In other words, don't share it (and don't worry about opening and closing it for each request, this is not an expensive operation).
References
JPA 2.0 Specification
Section 7.6 "Container-managed Persistence Contexts"
Section 7.6.1 "Container-managed Transaction-scoped Persistence Context"
Section 7.6.2 "Container-managed Extended Persistence Context"
Resources
Dependency Injection in Java EE 6 - Part 1
Introducing the Java EE 6 Platform: Part 1
TOTD #124: Using CDI + JPA with JAX-RS and JAX-WS
The #Singleton annotation will help: http://www.mentby.com/paul-sandoz/jax-rs-on-glassfish-31-ejb-injection.html