First of all I am new to JPA and Jax-rs, i am trying to develop a rest service. So i have created a resource class and annotated it.
#Path("/companies")
public class CompanyResource {
private EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test");
#GET
#Produces({MediaType.APPLICATION_JSON})
public List<Company> getCompanies() {
EntityManager entityManager = entityManagerFactory.createEntityManager();
return new ArrayList<>();
}
#GET
#Path("{companyId}")
#Produces({MediaType.APPLICATION_JSON})
public Company getCompany(#PathParam("companyId") int id) {
return new Company();
}
}
From what i have understood about jax-rs for every client request instance of CompanyResource will be created, that means every time new EntityManagerFactory will be created, which i guess is not a good idea, as i just need it to create entity managers, which could be done with only one instance of it. So what is a proper way to achieve this? Or is it ok to create new instance of this factory for every request?
P.S. i have seen some examples where they use #Stateless annotation and inject Entity Manager, but i guess they use EJB there(i might be wrong) and i don't want to deep into EJB right now.
I think you should inject the entitymanager itself (not the factory), and let the container take care of instantiation and scopes. What we usually do is something like
#Stateless
#Path("services")
public class MyServices {
#PersistenceContext
private EntityManager em;
// ...
apart from the #Stateless (which imho you should use, there's no need to get deep into EJB for this), it's actually quite simple.
Related
I am in a process of paying my Technical Debt and one of the problem I have facing is the uses of DAO's with CDI injection.
I did write a blog about DAO injection (using CDI, of course) and it works wonders and I will use the reference of the blog for my question. I am now in a situation where I have so many database tables (normalized, of course) and creating DAO's for each tables is not the issue. The issue is when a service (let's assume and EJB Session Bean) has "references" to many DAO's, like in the example below:
#Stateless
public class CustomerServiceEJB implements CustomerServiceLocal, CustomerServiceRemote, CustomerService {
private static final Logger LOGGER = Logger.getLogger(CustomerServiceEJB.class.getName());
#Inject #JPADAO
private CustomerDAO customerDAO;
#Inject #JPADAO
private CustomerAccountDAO customerAccountDAO;
#Inject #JPADAO
private CustumerCredentialDAO customerCredentialDAO;
//And rougly 15 more DAO's.
}
As you can see, if we need to use various DAO's, the class has "instances" of all DAO's and that means that the CDI container will have to inject all of them prior to being used.
One solution I came up with was to create a DAOManager where all references of the DAO's are listed in the manager.
Example:
public interface DAOManager {
public CustomerDAO getCustomerDAO();
public CustomerAccountDAO getCustomerAccountDAO();
public CustumerCredentialDAO getCustomerCredentialDAO();
//Etc
}
And it's JPA's representation:
#JPADAO
public class JPADAOManager implements DAOManager {
#PersistenceContext
private EntityManager entityManager;
public CustomerDAO getCustomerDAO() {
return new JPACustomerDAO(entityManager);
}
//Etc...
}
Finally, in CustomerServiceEJB, I can inject the DAO as follows:
#Inject #JPADAO
private DAOManager daoManager;
My question: Is my approach correct? If not, what is the best approach? Also, what do I need to take into consideration when using DAO's with CDI? Added question: Should JPADAOManager return a DAO in lazy-loading fashion?
My problem is actually simple but I really do not find a good solution to it.
I've currently to manage several DB in my application:
one UNIQUE admin DB (with a static name);
one client DB, with a name depending on the client.
I'm using JPA and I would like to create dynamically EntityManagers for client DB. But when I create this programmatically, I get this error:
javax.persistence.TransactionRequiredException: joinTransaction has been called on a resource-local EntityManager which is unable to register for a JTA transaction.
Here is the code:
#Stateful
public class ServiceImpl implements Service{
private EntityManagerFactory emf;
private EntityManager em;
#PostConstruct // automatically called when EJB constructed and session starts
public void init() {
emf = Persistence.createEntityManagerFactory("punit");
em = emf.createEntityManager();
}
...
And
#Stateful(mappedName = "CustomerService")
public class CustomerServiceImpl extends ServiceImpl implements CustomerService {
#Override
public void create(Customer cust) {
getEm().joinTransaction();
getEm().persist(cust);
}
More generally, I'v got problems with JPA. I just would like to connect to two databases, do some CRUD operations on them. But I really don't know how to manage transactions (my first approach was to let the container manage it...).
If someone could help me, could be great!
NB: I'm using a Glassfish Java EE server and PGSql DBs.
In jpa, you can declare several prsistenceunits in the persistence.xml file.
At the point of injection, you can do something like this:
#PersistenceContext(unitName = "unitName0", properties={#PersistenceProperty(...)}
EntityManager emClient;
#PersistenceContext(unitName = "unitName1", properties={#PersistenceProperty(...)}
EntityManager emAdmin;
This way, you dont have to create the entity managers manually, hence you get the container transaction management.
NOT TESTED:
If you have dynamic database names, you would inject EntityManagerFactory
#PersistenceContext(unitName ="name")
EntityManagerFactory emf;
//at the point you want the EntityManager
Map<String, String> props; //put the connection property for the EM here
EntityManager em = emf.createEntityManager(props);
Based on the fact that in a J2EE environment we use the concept of DataSources, and ConnectionPooling, it would be nearly impossible to implement this kind of dynamic datasources, without resorting to manual creation of entitymanagerfactory.
This is my reasoning:
The server manages the connection pooling, and the jpa provider (such as eclipselink) uses jndi to determine the connection to the database. This implies that if you were to change the database name, then it must also have a connection pooling resources, and an associated jdbc resource. This will ofcourse negate what you want to do.
Basic solution: Create EntityManagerFactory manually and manually manage transactions.
Specify in the persistence xml that the unit is non-jta for this to work.
Then you can programmatically supply connection data based on user-session:
Something of this sort:
//this must be session specific.
class PersistenceSession{
static Map<String, String> clientSessionProps;
//When new session starts and a new client has logged in.
static void setClientConnectionProperties(Client client){
.....
}
static Map<String, String> getClientSessionProps(){
return clientSessionProps;
}
}
At the ejb level.
#Stateless
public class TestEntityFacade extends AbstractFacade<TestEntity> {
private EntityManagerFactory emf;
#PostConstruct
void init(){
emf = Persistence.createEntityManagerFactory("name");
}
#Override
protected EntityManager getEntityManager() {
return emf.createEntityManager(PersistenceSession.getClientSessionProps());
}
public TestEntityFacade() {
super(TestEntity.class);
}
void add(Entity e){
EntityManager em = getEntityManager();
em.getTransaction().begin();
.....
em.getTransaction().commit();
}
}
Actually very neat way how to do this is with CDI Producers, you can define a bean which will produce for your any number of custom Entity Managers, see the example.
#SessionScoped
public class EntityManagerProducer {
#Produces
#AdminDB
#PersistenceContext(unitName = "adminDB")
public EntityManaged adminDB;
#Produces
#UserDB
#PersistenceContext(unitName = "userDB")
public EntityManaged userDB;
}
This means that these two EntityManagers get created within every user session and than you can inject them to any bean with
#Inject
#UserDB
private EntityManager em; //if you want to use UserDB now
#UserDB and #AdminDB are your own defined Qualifiers. This leads to much more easier and readable code.
Let's suppose I have a simple lib named db-utils, which has a CrudService CDI bean (requestScoped) that's used by my web applications to perform CRUD operations.
I also have an EJB project named grad-db, which has the entities mapped from database. Grad-db also has the producer used to set the entityManager in db-utils' CrudService.
I already tried it and apparently it works fine. My question is: is that a bad practice? Is there any consequence of producing a CDI bean inside a stateless session bean and passing the EJB stateless bean as a parameter to the CrudService?
My code:
EJB Bean (grad-db):
#Stateless
public class CrudServiceCae extends AbstractCrud implements Serializable {
private static final long serialVersionUID = 1L;
#PersistenceContext(unitName = "cae-pu")
EntityManager em;
#Override
public EntityManager getEntityManager() {
return em;
}
#Produces
#Database(Schema.CAE)
public CrudService createCrudServiceCou() {
return new CrudService(this);
}
}
CrudService (db-utils):
#Named("crudService")
public class CrudService implements Serializable {
private static final long serialVersionUID = -2607003150201349553L;
private AbstractCrud crud;
public CrudService(AbstractCrud abstractCrud) {
this.crud = abstractCrud;
}
...
}
Edit:
Actually it worked only for queries. When I tried to insert data I got javax.persistence.TransactionRequiredException. Apparently I'm going to have to use inheritance instead of CDI in this case.
The EJBs are responsable for business processes/logic (i.e: methods), and are able to orchestrating others CDI controllers, is not so common let the EJB create objects, for that you would prefer a CDI POJO Producer.
In your case is leaner to use a CDI object and produce the object that you need from there, looks like a DAO and could be used (i mean, injected) into the EJB.
Think of EJBs on terms of a Boundary Pattern, using specialized controllers.
Notes:
#Stateless is not required to implements Serializable, these are pooled, and its lifecycle does not allow serialization.
In general you dont want to use a getter to the entity manager of an EJB, you should prefer write a method and use the em internally.
The persistence context is easier to manipulate if uses JTA
Your #Stateless should begins the transactions and let them propagated along the controllers
The em with package visibility is a good idea, lets you mock your facade / boundary easily
I'm trying to figure out how to setup a Service/Dao layer in my application. I've found a few dozen resources all with different ways on how to do it and decided to follow the model found here: How should EntityManager be used in a nicely decoupled service layer and data access layer?
I can't figure out what I'm missing that's causing this NPE.
Usage:
#Path("/helloworld")
public class MyController {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
WorkflowService workflowService = new WorkflowService();
workflowService.save(workflow);
return "Workflow ID:";
}
}
My Dao:
#Stateless
public class WorkflowDao {
#PersistenceContext(unitName = "unit")
private EntityManager entityManager;
public int save(Workflow workflow) {
entityManager.persist(workflow);
return workflow.getId();
}
}
My Service:
#Stateless
public class WorkflowService {
#EJB
WorkflowDao workflowDao;
public int save(Workflow workflow) {
int id = workflowDao.save(workflow); //throws NullPointerException because workflowDao is null
return id;
}
}
This is my first time setting up a Java project (only have worked on 1 before and it used Spring) so please keep that in mind if this looks horribly wrong.
WorkflowDao is not an EJB, it's a POJO with a#Stateless annotation. So naturally, injecting it with #EJB fails, creating a null workflowDao attribute and eventually producing a NullPointerException.
To make WorkflowDao into a full-fledged EJB, besides having a #Stateless or #Stateful annotation it needs to implement a local, remote or both interfaces, and those interfaces must be annotated respectively with #Local and #Remote. Please refer to the tutorial for details.
Also, quite possibly (this can be application server-dependent) you'll have to register the EJB in the application's xml descriptor files - for instance, in web.xml's <ejb-local-ref> element.
As a side note - it's not a good idea to use an EJB as a DAO, an EJB is typically used for implementing business logic (true, persist/merge operations can be called from here) but the actual persistence layer nowadays is implemented using JPA. In other words, WorkflowService should be the EJB service, there's no need to inject an EJB into it, and there's no need for a separate DAO layer - JPA entities fulfill this role.
If you instantiate your WorkflowService manually, the container wont perform any injection, since your WorkflowService is not managed by the Container.
I suggest you:
Annotate your Jax-RS Resource #Stateless
Inject your WorkfloService via #EJB as a member
Implementing a Local or Remote Interface is not necessary anymore
#Path("workflows")
#Stateless
public class WorkFlowResource{
#EJB
WorkflowService workflowService;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String TestRequest() {
Workflow workflow = new Workflow();
workflow.setName("test");
workflowService.save(workflow);
return "Workflow ID:";
}
}
Considering there is no #PersistenceContext available to inject the EntityManager, plus you need to manually manage Transactions, what is the best way to design such an application?
For the EntityManagerFactory/EntityManager, as far as I can see, you must have each DAO accepting an EntityManager in the costructor e.g.
public class DAOImpl implements DAO
{
private EntityManager em;
DAOImpl(EntityManager em){
this.em = em;
}
//all CRUD operations follow
}
The first question that rises is when do you call EntityManager#close()?
Point A: The way I see it, you are better off doing this in a Filter at the end of the request cycle, which implies that you associate the EntityManager with the current thread (using ThreadLocal?)
Second question is, how and when do you inject the EntityManager?
Considering there is a ServletContextListener where we create and close the EntityManagerFactory, we could have a static method as follows
public static EntityManager createEntityManager(){
return entityManagerFactory.createEntityManager(PERSISTENT_NAME);
}
but since we want to encapsulate creating the DAO, we could use a factory e.g.
public class DAOFactory
{
public static DAO dao(){
//return a new DAO
}
}
As per Point A we should use a ThreadLocal to create the DAO using the EntityManager for the current Thread.
For managing Transactions.
The best way I can think of (which mimics the JPA spec) is to create your own Transaction annotation and use reflection to inject the begin/commit/rollback operations.
You should then return a Proxy from the DAOFactory which handles the transactions
I wouldn't do all that. Why try to recreate the whole JPA spec yourself? You just need to be able to use JPA without a container.
Spring can help you with this. Try it.