JPA Persistence with Jersey without Injection - java

I'm developing a REST API with jersey. Now I have to persist the entities with JPA and as I learned in university I "openend" a DB Connection with the following code:
EntityManagerFactory factory = javax.persistence.Persistence.createEntityManagerFactory("LootDB");
EntityManager em = factory.createEntityManager();
I'm using the code above in EVERY RESOURCE. But I think this is a bad design. Because I don't know about Spring and dependency injection, I have to create the persistence instances manually.
Is there something wrong? In the database I can observe just 2 openened connections and I never get concurrency issues.
any help is appreciated...

You can define a class which spring bean scope is singleton.For accessing that class instance use #Autowired annotation.After that you can access the factory instance with it in everywhere.

Related

Using EntityManager as an autowired field in a Spring Repository

I'm working on a legacy codebase and saw something unsettling in our custom repositories. EntityManager is autowired into the repos directly. For example:
#Repository
public class OperationRepository {
// Yikes
private final EntityManager entityManager;
private QOperation operation = QOperation.operation;
#Autowired
public OperationRepositoryImpl(EntityManager entityManager) {
this.entityManager = entityManager;
}
#Override
public Optional<Operation> findOneByIdAndType(Long operationId, OperationType type) {
JPAQuery<Operation> query = new JPAQuery<>(entityManager);
QOperation qOperation = QOperation.operation;
query.select(operation).from(operation)
.where(
operation.type.eq(type),
...
}
}
My understanding is that this is dangerous since EntityManager is not threadsafe and is being managed here as a field. I don't see an explicit definition in any of our configuration files to provide an EntityManager bean so am not sure what Spring does in this case.
I am going to start on the fix for using #PersistenceContext here instead but wanted to understand what the impact is on this being in production for so long and what consequences might have come from it.
Would we be limiting our connection pool size to the number of single entitymanagers in our repository beans? Are there any other dangers it could have caused? Or am I making too much of it?
It really depends on the configuration of your application context, which might get configured by Spring Boot if you are using that, but in general and with a typicals setup this is not a problem.
In such a setup the application context doesn't contain a single (or a limited set of) EntityManager instance but an EntityManagerFactory which can create EntityManager instances on demand.
And you don't get injected a normal EntityManager either, but a proxy which will point to different instances upon different calls, typically so that each thread has its own EntityManager and after a web request is completed the next request handled by the same thread gets a fresh instance.
If you are still concerned, I recommend to use a debugger to inspect the EntityManager and confirm that it is indeed a proxy and that it delegates to different actual instances for different threads.
You might also want to take a look at this question about Spring Scopes which is the underlying abstraction for this: Spring Bean Scopes

DAO class instance vs DAO EJB

What is the best practice in java EE?
Create an instance of the DAO class in the service (or manager) class
SalesDAO salesDao = new SalesDAOImpl();
salesDao.findCustomers();
or
Call a DAO EJB in the service (or manager) class
#EJB
private SalesDAO salesDao;
salesDao.findCustomers();
The second one is the best practice (your DAO could be a CDI bean: it doesn't have to be an EJB).
Dependency injection is what makes the code testable: you can inject a mock DAO in the service when unit-testing the service.
BTW, the DAO will also need to have a DataSource or an EntityManager injected to be able to get data from the database. This is only possible if the DAO instance is managed by the container.
I preffer the second one.
DAO talks about responsability, means manage persistent data. But there is no reason for not to use a EJB. Let the container manage instances for you.
Adam Bien, member of EJB 3.1 spec comitee said in his blog:
http://www.adam-bien.com/roller/abien/entry/generic_crud_service_aka_dao

PersistenceUnit vs PersistenceContext

In few project I have been successfully using
#PersistenceUnit(unitName = "MiddlewareJPA")
EntityManagerFactory emf;
...
EntityManager entityManager = emf.createEntityManager();
to obtain EntityManager for Database connection, but some days ago I was trying to move my project to Jboss EAP 6.2 and it couldn't create EntityManager. I was googling it and I found that I should try change #PersistenceUnit to
#PersistenceContext(unitName = "MiddlewareJPA")
private EntityManager entityManager;
to obtain EntityManager. It worked but I don't know why. What is the difference bettween PersistenceUnit and PersistenceContext? What are pros and cons of each one? Where should we be using one of them?
PersistenceUnit injects an EntityManagerFactory, and PersistenceContext injects an EntityManager. It's generally better to use PersistenceContext unless you really need to manage the EntityManager lifecycle manually.
I don't know how it works exactly in the Java EE, but in Spring, when you specify #PersistenceContext annotation, it injects EntityManager. Where does it get EntityManager? It is wrong to create one EntityManager for the whole application lifetime by calling EntityManagerFactory.createEntityManager(). So instead a special implementation of EntityManager interface is used and instantiated directly. It has an internal mutable thread-local reference to a real EntityManager. Implementations of methods just redirect calls to this real EntityManager. And there is a servlet listener, that before each request obtain EM by calling EMF.createEntityManager() and assign it to that inner reference of special EM. Also this listener manages transactions by calling getTransaction().begin(), .commit() and .rollback() on the real EM. It is very simplified description of performed work. And I believe, that JEE container does the same thing, as Spring does.
In general case it is better to inject EntityManager, because with EntityManagerFactory and #PersistenceUnit you should create/destroy EntityManager every time by hands and manage transactions too.
EntityManager obtained via #PersistenceContext is called Container Managed EntityManager as container will be responsible for managing "EntityManager". EntityManager obtained via #PersistenceUnit / entityManagerFactory.createEntityManager() is managed in the application by the developer. (for e.g. managing lifecycle of EntityManager, releasing the resources acquired by EntityManager, etc.).

Execute initialization code in EJB3.1

I am currently migrating to EJB3.1 after using Spring for many years. One thing I would like to implement in EJB, for which I couldn't find a matching pattern yet is my MigrationManager.
In Spring I had a bean that dealt with database schema and data migration. For this I implemented a Spring BeanFactoryPostProcessor because this way I had the database connection injected, but the JPA system is not yet initialized. So I could perform all migration steps and then have the application finishing starting.
How can I do something like this in EJB3.1 (Using CDI ... if this is of importance)
Chris
This is the way to run some initialization code from an EJB:
#Singleton
#Startup
public class MigrationManager {
#PostConstruct
public void migrate() {
// do work
}
}
You don't need a separate app for that (as suggested in a comment above).
EntityManagers get instantiated lazily, so as long as you don't inject an EntityManager into some other startup code, this should give you a chance to update your database schema before an EntityManager is actually hitting the database.
By the way, for database schema migration I'd recommend Liquibase, which can be triggered by a ServletContextListener.

The 'correct' way to instantiate JPA manager bean?

I'm using IBM RAD to develop some JPA entities, and from those, corresponding JPA Manager Beans. Manager beans (which are generated by RAD) have the following member:
#PersistenceUnit
private EntityManagerFactory emf;
I'm not sure how to correclty instantiate (or get a reference to) this manager bean from a stateless EJB (3.0), so I've added a constructor to manager bean where I can pass EntityManagerFactory instance to it. I get a reference to EntityManagerFactory in an EJB by using `#PersistenceUnit' annotation like so:
#PersistenceUnit
private EntityManagerFactory _entityManagerFactory;
This seems rather unnecessary and I believe there must be a way to tell the container (Websphere 7.0 in my case) to 'bootstrap' this for me somehow, so that I get a reference to JPA manager bean right away. Is it?
Update:
It seems I haven't bean elaborate enough. Sorry for that.
There are three objects involved: JPA Entity, JPA Entity Manager and a Stateless EJB.
JPA Entity Manager class (not an EJB) is created by RAD and has convinience methods (named queries) on it. It also has defined member #PersistenceUnit private EntityManagerFactory emf. I know I can use EntityManager directly, but I'd like to use MyEntityManager for it's convinience methods.
I can get a reference to EntityManager or EntityManagerFactory in a stateless EJB by using annotations described above (and also like Bozho suggests)
I would like to get a reference to JPA Entity Manager in a stateless EJB. If I 'new' it up (new MyEntityManager()), the emf field is null. The workaround is to declare #PersistenceUnit field in an EJB and then pass it to JPA Entity Manager and use that.
Come to think of it, maybe I could declare JPA Entity Manager as an EJB and be done with it... (although this again seems unnecessary). I thought there is a method along the lines PersistenceContext.getJpaManager(MyEntityManager.class) which I am perhaps missing.
#PersistenceContext
private EntityManager em;
It seems you have your custom bean that you want to inject in other beans (it needs a local interface at least):
#EJB
private MyEntityManager em;

Categories