I m getting mad with Jboss WildFly9 with JPA and JTA.
In my project requirements i have to implement multitenancy so i have to change dynamically datasource inside my persistence.xml.
Using jee approach this is not possibile so someone suggest me to use the classic:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("idelivery");
EntityManager em = emf.createEntityManager();
So till now it's working, i can create on by myself the enetitymanager and i can set jpa properties in a hashmap (included datasource).
Now i want to use JTA at least to handle transaction using transaction manager.
So these are the properties i set by code:
Properties properties = new Properties();
properties.put ("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
properties.put("javax.persistence.provider", "org.hibernate.jpa.HibernatePersistenceProvider");
properties.put("javax.persistence.transactionType", "JTA");
properties.put("javax.persistence.jtaDataSource", dataSourcePath);
Transaction type now is JTA. So i expect that i can use some code like:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("idelivery");
EntityManager em = emf.createEntityManager();
MyEntity exUser= new MyEntity();
try{
Context context = new InitialContext();
UserTransaction userTransaction = (UserTransaction)context.lookup("java:comp/UserTransaction");
userTransaction.begin();
em.persist(exUser);
userTransaction.commit();
Of course this code doesn't work at all as Hibernate rises an exception:
java.lang.NullPointerException at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus()
Telling me being not able to join a transaction at the creation of entity manager moment.
So ... how can i respect my project requirements... creating my own persistence with my dynamic datasouce and at the same time using the Transaction Manager?
Hibernate has its own solution for multi-tenancy. This is not part of the JPA standard, but it's compatible with and largely orthogonal to it.
It does work with managed persistence units and is compatible with JTA.
I've used the SCHEMA strategy successfully on WildFly 8.2.0.Final and 9.0.1.Final.
You just need to implement two helper classes and configure them in your persistence.xml.
If you can tell before hand how many datasources you would require then you can implement some kind of contextual selection of your entity managers by using CDI producer pattern.
Define all the possible datasources in your persistence.xml and then using some kind of producer singleton factory class to inject them based on their persistence unit.
Create a producer method which selects the correct entity manager based on your current context.
Then in your ejb or cdi beans get an instance of entitymanager through CDI injection
#Inject
private EntityManager em
Related
I really like the simplicity of spring data repository, however need to use hibernate as persistence provider for consistency and few other factors. (I am using mongodb but not using mongo template). Few things I noticed --
The HibernateJpaVendorAdapter uses "org.springframework.orm.jpa.vendor.SpringHibernateEjbPersistenceProvider"
The provider configured with the persistence unit ( ""org.hibernate.ogm.jpa.HibernateOgmPersistence" ) is not considered, while constructing the EntityManagerFactory through a "org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" bean.
If there are multiple persistence units configured for the project there is no apparent way to associate a persistence unit for a repository.
Questions:
Is there a way to use the configured persistence provider , instead of the default one ? The default provider is not working with mongodb.
Is there a way to associate a repository with a specific persistence unit ?
A partial solution was to
implement
org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter and
return an instance of
org.hibernate.ogm.jpa.HibernateOgmPersistence in
getPersistenceProvider() method
Source the jpaVendorAdapter property for entityManagerFactory
bean in spring config
However it still doesn't work good wherever there is reference to Pageable. Some design change can circumvent the issue.
Is there a way to create the EntityManagerFactory without a persistence unit defined? Can you give all the required properties to create an entity manager factory? I need to create the EntityManagerFactory from the user's specified values at runtime. Updating the persistence.xml and recompiling is not an option.
Currently I am using eclipselink dynamic persistence so i need to create the EntityManagerFactory without a persistence unit defined ? I have groups of runtime entities that need to map single group of entities to different database in runtime and no persistence unit entry is available for this runtime group of entities .
Any idea on how to do this is more than welcomed!
Your best option is most likely to access the PersistenceProvider directly and use the EJB container API to create the EntityManagerFactory from a PersistenceUnitInfo.
PersistenceProvider.createContainerEntityManagerFactory()
See,
http://www.eclipse.org/eclipselink/api/2.5/org/eclipse/persistence/jpa/PersistenceProvider.html#createContainerEntityManagerFactory%28javax.persistence.spi.PersistenceUnitInfo,%20java.util.Map%29
Just seen in the DataNucleus documentation:
import org.datanucleus.metadata.PersistenceUnitMetaData;
import org.datanucleus.api.jpa.JPAEntityManagerFactory;
PersistenceUnitMetaData pumd = new PersistenceUnitMetaData("dynamic-unit", "RESOURCE_LOCAL", null);
pumd.addClassName("org.datanucleus.test.A");
pumd.setExcludeUnlistedClasses();
pumd.addProperty("javax.persistence.jdbc.url", "jdbc:h2:mem:nucleus");
pumd.addProperty("javax.persistence.jdbc.driver", "org.h2.Driver");
pumd.addProperty("javax.persistence.jdbc.user", "sa");
pumd.addProperty("javax.persistence.jdbc.password", "");
pumd.addProperty("datanucleus.autoCreateSchema", "true");
EntityManagerFactory emf = new JPAEntityManagerFactory(pumd, null);
http://www.datanucleus.org/products/accessplatform_3_2/jpa/persistence_unit.html
I realized after writing this question I could sum it up in a few sentences. How can I manage transactions in Spring-Data-JPA with CDI the same way you would by using #Transactional in Spring itself?
First thing I did was set up Spring Data JPA CDI based on the documentation here. http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/jpa.repositories.html#jpd.misc.cdi-integration
I set this up and it is working fine for read operations but not write operations
For Example, Their example in the docs would work fine.
List<Person> people = repository.findAll();
So I have the basic setup complete.
Written by hand may have typos. This is similar to the code I execute.
#Inject
UserRepository userRepository;
User user;
#Transactional
public void signUpUserAction() {
userRepository.saveAndFlush(user);
}
Then I receive this error
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
At first I realized I did not have the #Transactional so I added it and still did not work.(I believe in spring you need to use the AOP xml file to set up #Transactional so it makes sense this does not work in EE out of the box, I just do not know how to make it work.)
FYI annotating with this does not work
#TransactionAttribute(TransactionAttributeType.REQUIRED)
Something I tried while I was writing this post and I got it to work sort of... but I don't like the code and am still interested in using #Transactinoal, this code feels dirty, I'm pretty sure #Transactional handles calling other methods that are transactional in a clean way while this code would not.
This saves and I verify it's in the database.
#Inject
EntityManager em;
#Inject
UserRepository userRepository;
private User user;
public void signUpUserAction() {
em.getTransaction().begin();
userRepository.saveAndFlush(user);
em.getTransaction().commit();
}
So in short, how can I use #Transactional or something similar to manage my transactions?
Thank you for any help.
If you run Spring Data in a CDI environment, you're not running a Spring container at all. So you'll need to use EJB session beans to work with the repositories as CDI currently does not have support for transactions out of the box. The CDI extensions shipping with Spring Data is basically providing an entry point into the JavaEE world and you'll use the standard transaction mechanisms you can use in that environment.
So you either inject a repository into an #Stateless bean directly or you inject the CDI bean into one. This will allow you to use EJB transaction annotations on the EJB then.
for everyone who have this question yet.
I have this experimental project that support #Transactional in a CDI environment.
This project uses a custom code of Narayana as interceptor and provide compatibility with it and Spring Data Jpa implementation.
Key points to take in consideration:
Custom (Spring Data) Cdi Configuration -> add a Custom Transactional Post Processor custom spring data cdi configuration
Implement a custom Transactional Post Processor:
sample of a Custom Transactional Post Processor
Implement a custom Transactional Interceptor sample of a custom transactional interceptor
Add a Cdi Producer for your custom Tx Interceptor cdi producers
Create your custom repository fragments using #Transactional (JTA) custom fragments
Compose your Repository interface extending Repository interface and your fragments with #NoRepositoryBean annotation custom repositories
Take a look at this link that have some tips:
tips
Regards,
AFAIK, there are two types of entity manager.
1. Container managed entity manager
2. Application managed entity manager
Container managed entity manager
This type of em uses JTA transaction only
Below is my code:
#PersistenceContext(unitName = "", type = Transaction)
EntityManager em;
public void persist(T entity) {
em.persist(entity)
}
Questions:
There is exception throw when execute the code : TransactionRequireException
Why there is this kind of exception? There is no TransactionRequireException happen after added #Resource UserTransaction to the method persist(). I wonder UserTransaction is belongs to JTA right.
EntityTransaction et = em.getTransaction();
Refer to the above code, Why JTA transaction type cannot invokes getTransaction() ?
Can extended JTA Transaction em use outside of EJB?
Application managed entity manager
Utilize JTA Transaction
Utilize JDBC Transaction(Resource Local Transaction)
Please anyone provide example of source code on JDBC Transaction type.
A JPA persistence unit can either be JTA or RESOURCE_LOCAL.
If you use JTA, then you must use JTA for transaction, either through SessionBeans or by accessing JTA directly.
See,
http://en.wikibooks.org/wiki/Java_Persistence/Runtime#Java_Enterprise_Edition
That may seem obvious but I've seen contradictory statements: Is JPA part of EJB 3.0? I'm no specialist and it's quite confusing for me.
If so, JPA manipulates Entity Beans? These entity beans being the interface between the persistence layer and the business layer implementing the logic with stateless beans?
The underlying question for me is how to implement a "search for user based on various criteria" function, where the "search" request -its string representation- should be built? I mean, if JPA is not part of EJB, my beans shouldn't be aware of the data model, right?
Where is the boundary?
Is JPA part of EJB 3.0 ?
Yes and no... Yes because every application server claiming to implement EJB 3.0 spec must also provide JPA implementation. No because JPA can be easily outside of EJB, in standalone applications or Spring-managed ones.
JPA manipulates Entity Beans ?
Entity beans was a scary idea in pre-3.0 EJBs. JPA uses the term entities to distinguish itself from the disgraceful history. But yes, JPA entities are a way to map database tables to plain Java objects. In principle changes made to object are propagated to database and vice-versa (oversimplification).
As I said, JPA does not have any dependency on EJB (considered as stateless and stateful session beans) and the other way around. But there is nothing preventing you from using JPA in EJB.
In your scenario you'll have a stateless EJB constructing the query and interacting with the database via JPA. Technically speaking you will call methods on EntityManager injected to your bean:
#Stateless
public class SearchService {
#PersistenceContext
private EntityManager em;
public List<User> findUsersBornAfter(Date date) {
return em.
createQuery("SELECT u FROM User u WHERE u.birthDate > :birthDate ORDER BY name").
setParameter("birthDate", date).
getResultList();
}
}
As you can see the business layer is aware of the data model (obviously), but there is no dependency on EJB/business services as far as entities are concerned. In this example JPQL (query) is formed in the service layer and User is a JPA entity. Calling getResultList() causes the JPA provider to translate JPQL to SQL, run the query and transalte the results back to User object instances.
Is the border between EJB and JPA clear now?
A couple of notes:
when it comes to the JSR, JPA 1.0 was part of EJB 3.0. See here , JPA 2.0 is a separate JSR (see here)
"entity beans" are EJB pre-3.0, and they are luckily dead. They are succeeded by JPA.
when it comes to dependencies - JPA does not depend on EJB, and EJB does not depend on JPA. However, EJB can handle injection of JPA entity manager
you can use either of them standalone
each application server supports both
Adding to BalusC's answer, from Wikipedia - Enterprise JavaBean:
Note that the current EJB 3.1 specification does not detail how an application server provides persistence (a task delegated to the JPA specification), but instead details how business logic can easily integrate with the persistence services offered by the application server.
The integration takes away some pain points from JPA, namely the rather verbose and noisy starting and committing/rollbacking a transaction and scoping the extended persistence context (that last one only for statefull session beans).
Adding to Bozho's answer:
In EJB 3.0, JPA 1.0 was part of EJB but as a sub-spec and useable outside EJB and outside Java EE.
In EJB 3.1, JPA has been completely split-off from EJB and JPA 2.0 is 100% a separate JSR.
From Wikipedia - Java Persistence API:
Enterprise JavaBeans
The EJB 3.0 specification (itself part of the Java EE 5 platform) included a definition of the Java Persistence API. However, end-users do not need an EJB container or a Java EE application server in order to run applications that use this persistence API.[1] Future versions of the Java Persistence API will be defined in a separate JSR and specification rather than in the EJB JSR/specification.
The Java Persistence API replaces the persistence solution of EJB 2.0 CMP (Container Managed Persistence).