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).
Related
I'm working on a REST api with Java, using JAX-RS, EJB, JPA and JasperReports, basically the API call a oracle function that return an id, with that id i make a select and generate reports with Jasper Reports, then i send the report as a response, works fine.
But, i have some questions if i should use or not use EJB, because i dont see why i should use EJB in this case, since the oracle function have commit inside of it, if something goes wrong, the rollback triggered by the EJB will not do nothing right? Also, the select that generates the report is simple, just one table, and i saw some articles saying that if you do just a select theres no need for using EJB to control the transaction.
Also, how to use CDI in this case? #Named in the classes and #Inject in the fields? I have some coworkers saying that #Named should be used just with JSF, but i'm a junior, seeking for the truth about this, after researching a lot i still dont know how to handle this, i apreciate any help.
Thanks!
Do I need EJBs for transactions?
If you are using JEE-7+ then you can use #Transactional for your CDI Beans instead of EJB-Beans with #Stateless and #TransactionManagement and #TransactionAttribute. #Transactional provides the same properties as #TransactionAttribute and makes any CDI Bean transactional without the need for an EJB Container. All of these approaches require JPA to be used, which for a simple single query is maybe an overkill.
https://docs.oracle.com/javaee/7/api/javax/transaction/Transactional.html
What can I use instead of EJBs and #Transactional?
If you don't need/want to use an EntityManager, then just use plain JDBC.
What does #Named do?
#Named makes CDI Beans accessible to Java-EL via their defined name, or if no one is defined then via their simple class name. You can also use #Named to distinguish between implementations, but I think CDI Qualifiers are more suitable to achieve that. So, if you don't need it, then don't annotate it.
How to provide CDI Beans to other CDI Beans?
In my opinion CDI Beans should be injected via Fields and not constructor arguments. Injection in constructor arguments is done because of testability, so you can test your beans without using CDI, which these days is not that hard to achieve anymore.
https://deltaspike.apache.org/documentation/test-control.html
What is the main difference between Java Persistence API(JPA) and the Java Transaction API(JTA). I read these two terms in Java EE 7 .
JPA is an object-relational mapping tool that allows mapping between entity objects which are classes with their corresponding tables and their attributes in the database. Whereas JTA is a tool that allows you to make multiple transactions in multiple schema.
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.
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,
I am developing a small (but growing) Java EE project based on the technologies EJB 3.1, JSF 2, CDI (WELD) and JPA 2 deployed on a JBOSS AS 7.1Beta1.
As a starting point I created a Maven project based on the Knappsack Maven archetypes.
My architecture is basically the same provided by the archetype and as my project grows I think this archetype seems to be reaching its limits. I want to modify the basic idea of the archetype according to my needs. But let me first explain how the project is organized at the moment.
The whole project is built around Seam like Home classes. The view is referencing them (via EL in xhtml templates). Most of the Home classes are #Named and #RequestScoped (or shortly #Model) or #ConversationScoped and Entripse Java Beans are #Injected. Basically these (normally #Local) EJBs are responsible for the database access (Some kind of DAOs) to get transactions managed automatically by the container. So every DAO class has its own EntityManager injected via CDI. At the moment every DAO integrates aspects which logically belong to each other (e. g. there is a SchoolDao in the archetype which is responsible for creating Teachers, Students and Courses).
This of course results in growing DAOs which have no well defined task and which become hard to maintain and hard to understand. And as a painful side effect the risk of duplicate code grows.
As a consequence I want to breakup this design by having only DAOs which are responsible for one specific task (a #StudentDao, a #TeacherDaoand so on). And at this point I am in trouble. As each DAO has a reference to its own EntityManager it cannot be guaranteed that something like the following will work (I think it never will :)
Teacher teacher = teacherDao.find(teacherId);
course.setTeacher(teacher);
courseDao.save(course);
The JPA implementaion complains about a null value for column COURSE.TEACHER_ID (assuming Course has a not nullable FK realtionship to Teacher). Each DAO holds its own EntityManager, the teacher is managed by the one in the TeacherDao, but the other one in the CourseDao tries to merge the Course #Entity.
Maybe the archetye I used is not suitable for larger applications. But what would be a appropriate design for such an aplication then IF the technologies I used are obligatory (EJB 3.1 for container managed transactions [and later on other business related stuff], JSF as view technologie, JPA as the database mapper and CDI as the 'must have because it's hip:)?
Edit:
I now have an EntityManager injected in the base class all other DAO classes inherit from. So all DAOs use the same instance (debugger shows same object id) but I still have the problem that all entities that I read from the database are immediately detached. This is something that makes me wonder as it means that there is either no container managed transaction or the transaction gets immediately closed after the entity was read. Each DAO is a #Local #Stateless EJB. They are injected into my JSF Beans (#Named and #RequestScoped) from where I want to make use of the CRUD operations. Is there anything I miss?
Having each DOA have its own EntityManager is a very bad design.
You should have an EntityManager per transaction/request and pass it to each DOA, or have them share the same one or get it from the context.