Using an EJB outside container - java

I am currently creating a J2EE application and there is a part of it that is running outside the container, using a ServletContextListener to launch it.
However I also need to access the database from this part.
I currently have an Entity and a Stateless Session bean to fetch use the EntityManager.
I tested multiple things ( EntityManagerFactory, Initial Context, EJBContainer ) but I didn't manage to make any of them work.
How do I need to do it ?

You do not need EJB, actually you cannot create Ejbs outside the container. You need JPA, an OR-mapper and JDBC.
These normally are correctly configured in your EJB-Container. Outside the container you have to do that yourself.
You have to define your dependencies right, so that the correct JDBC-Driver is available and the OR-Mapper (probably eclipselink or hibernate?)
After that, you need define a presistence.xml to define the Entities to be used and to define how the DBMS is accessed via JDBC.
If that all is correctly configured EntityManagerFactory is the correct way to create an EntityManger for the persistence-unit defined in persistence.xml.
There are many examples available on the net. e.g.:
https://examples.javacodegeeks.com/enterprise-java/jpa/java-persistence-xml-example/
should work, if you are using eclipselink.
https://docs.jboss.org/hibernate/orm/3.6/quickstart/en-US/html/hibernate-gsg-tutorial-jpa.html
in case of Hibernate.

Related

JPA application managed persistence context data source configuration with java without persistence xml file

JPA specification defines two ways of how to configure and use it:
Application-managed Persistence Context
Container-managed Persistence Context
With the Application-managed Persistence Context approach, the application code directly creates EntityManager using EntityManagerFactory. With the Container-managed Persistence Context, the container is responsible for this.
Seems this is all related only to controlling of EntityManager instances (create, destroy, etc).
The question is. Why do we have two different methods in the PersistenceProvider class? (I mean with different parameters)
I mean these:
public EntityManagerFactory createEntityManagerFactory(String emName, Map map)
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map)
The first one seems for the Application managed type. And it works only with the persistence.xml file because it can take only the name of the persistence unit. The second is for Container managed type. And it can take the PersistenceUnitInfo object. Why I cannot use the Application Managed type with the custom PersistenceUnitInfo parameter? It seems both variants work with containers anyway. The difference occurs only in controlling EntityManager instances. When we are talking about the configuration of EntityManagerFactory, this object always resides inside a container, because I can inject it with the #PersistenceUnit annotation.
This seems strange, as I still can specify the data source for the Application managed type with the <jta-data-source> tag. And I can do the same with Container managed type using the java setter method. If I can do the same things, why I am limited with only XML tag in one variant and I can use java setter (java configuration) in the second?
MOST TYPICAL JPA CASES
So the "container" here in this terminology refers to a Java EE / Jakarta EE container (aka an "application server"). I think the reason this probably seems so confusing is because most documentation is geared towards the typical application developer, but you're asking about code that's typically the responsibility of the JPA provider and the container provider.
In the most typical cases, an application running in a Java EE / Jakarta EE container would not use these PersistenceProvider methods. It might inject an EntityManager (container-managed persistence context) or inject an EntityManagerFactory (app-managed persistence context).
The PersistenceProvider#createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) method is intended for a JPA provider to allow a Java EE / Jakarta EE Container to create an EMF which can probably be used for both container-managed and application-managed persistence contexts.
And in a Java SE environment, the application would call Persistence.createEntityManagerFactory(...) which would find a Provider and call its PersistenceProvider#createEntityManagerFactory method. Here too, the app wouldn't need to call PersistenceProvider itself.
So if you have a typical app and you're trying to figure out what PersistenceProvider method to call, then you probably are on the wrong track and should be starting from a better example.
SPECIAL CASES
This all works well and is handled for you, as described, when you're using the typical aproach of using the persistence.xml to load the persistence context. If your application wants to do something different and custom, however, then you get into the realm of maybe wanting to call the PersistenceProvider yourself. E.g. this is one article that discusses the subject a bit. You may end up tying your application to a specific provider with this approach.
I'm not sure exactly what the specification says about this case, if anything. I would describe it as having more of an "app-managed persistence" feel since you're certainly creating EntityManager(s) yourself but I'm not sure if that's a correct or helpful description.

Why Spring does not recognize #BatchSize annotation

Scenario:
I'm supporting an Enterprise application that runs in Wildfly10. The application (.war) uses J2EE technologies (EJBs, JPA, JAX-RS) and SpringBoot features (like, SpringMVC, SpringRest, SpringData, SpringRestData) ... Both stacks co-exists "happily" because they don't interact between them; however, they do share common classes, like utility or Entity Classes (the stacks map to the same database model). Why the application uses those stacks is out the scope of the question.
Currently, I'm trying to improve the performance of a #RestController that pulls some data from the database using a JPA Spring Repository. I found that we're suffering the N + 1 queries problem when calling the #RestController. In past projects (where there were only J2EE technologies), I have used the #BatchSize hibernate annotation to mitigate this problem with total success.
But, in this project, Spring seems to be skipping such annotation. How do I know that? Because I turned on the hibernate SQL logging (hibernate.show_sql) and I can see the N + 1 queries is still happening ...
Key Points:
Here are some insights about the application that you must know before providing (or trying to guess) any answer:
The application has many sub-modules encapsulated as libraries inside WAR file (/WEB-INF/lib) ... Some of these libraries are the jars that encapsulate the entity classes; others are the jars that encapsulate the REST Services (that could be JAX-RS services or Spring Controllers).
The Spring configuration is done in the classes defined in the WAR artifact: in there, we have a class (that extends from SpringBootServletInitializer) annotated with #SpringBootApplication and another class (that extends from RepositoryRestConfigurerAdapter) annotated with #Configuration. Spring customization is done is such class.
The application works with multiple datasources, which are defined in the Wildly server. Spring DATA JPA must address any query pointing to the right datasource. To accomplish this requirement, the application (Spring) was configured like this:
#Bean(destroyMethod="")
#ConfigurationProperties(prefix="app.datasource")
public DataSource dataSource() {
// the following class extends from AbstractRoutingDataSource
// and resolve datasources using JNDI names (the wildfly mode!)
return new DataSourceRouter();
}
#Bean("entityManagerFactory")
public LocalContainerEntityManagerFactoryBean getEntityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean lemfb;
lemfb = new LocalContainerEntityManagerFactoryBean();
lemfb.setPersistenceUnitName("abcd-pu");
lemfb.setDataSource(dataSource());
return lemfb;
}
The last #Bean declaration favors the use of a persistence.xml file, which we do have in the route /WEB-INF/classes/META-INF/ (i.e. Spring does find this file!) ... In such file, we define our domain classes, so that Spring JPA can see such entities. Also, we can define special JPA properties like: hibernate.show_sql and hibernate.use_sql_comments without issues (this is how I detected the N + 1 queries problem in the first place) ...
What I have done so far?
I tried to add the #BatchSize annotation to the problematic collection. No luck!
I created a new JAX-RS Service whose purpose was to mimic the behavior of the #RestController. I confirmed that the #BatchSize annotation does work in the application's deployment, at least, in JAX-RS Services! (NOTE: the service uses it own persistence.xml) ...
Test details (Updated 2020/07/30): What I did here was to create a new JAX-RS Service and deployed it inside the WAR application, next to the #RestController that presents the problem (I mean, it is the same WAR and the same physical JVM). Both services pull from database the same entity (same class - same classloader), which has a lazy Collection annotated with #BatchSize! ... If I invoke both services, the JAX-RS honors the #BatchSize and pulls the collection using the expected strategy, the #RestController does not ... So, what it is happening here? The only thing different between the services is that each one has a different persistence.xml: the persistence.xml for the JAX-RS is picked by Wildfly directly, the other one is picked by Spring and delegated to Wildfly (I guess) ...
I tried to add the properties: hibernate.batch_fetch_style (=dynamic) and hibernate.default_batch_fetch_size (=10), to the persistence.xml read by Spring ... No luck. I debug the Spring startup process and I saw that such properties are passed to the Spring Engine, but Spring does not care about them. The weird thing here is that properties like: hibernate.show_sql, Spring does honor them ... For those who are asking: "What does these properties do?" Well, they are global equivalent to apply #BatchSize to any JPA lazy collection or proxy without declaring such annotation in any entity.
I setup a small SpringBoot Project using the same Spring version as enterprise application (which is 1.5.8.RELEASE, by the way) and both the annotation and properties approach worked as supposed to.
I've been stuck with this issue for two days, any help to fix this will be appreciated ... thanks!
There are 2-3 possible issues that I can think off.
For some reason, whatever you modify isnt picked up by wildfly - Wildfly classpath resolution is a separate Topic and some missing configuration can cause you a nightmare. This you can identify if you have access to debug the query, and in if you put a breakpoint in the constructor of your Entity class, you will get a chance to evaluate the entity configuration being used, somewhere in the execution conetxt.
BatchSize doesnt work on OneToOne, It only works on OneToMany relationships.
A typical way to define BatchSize is to do along with Lazy load as mentioned in the example here. If you are not using Lazy fetch, hibernate assumes that you are willing to make an eager load and makes another select query to fetch all the details.Please confirm you are using the same syntax as given in the example above.
New Addition:
Put Conditional Breakpoints in PropertyBinder#setLazy() function, and may be backtrace it and put relavent breakpoints in CollectionBinder and AnnotationBinder. then restart/redeploy the server and see what data you are getting for the relavent properties. That will give you fair idea where it is failing..
Why conditional breakpoint? Its because you will have thousands of properties and if you do not add condition to the breakpoint, you will take 1 hour to reach your actual breakpoint
What should be the condition - If its property binder, the condition shoud be like `this.name == . For other classes also you can use the same approach.
Sorry for too detailed description on conditional breakpoints, you might find it redundent.
Looks like the only way to debug your problem is to debug hibernate framework from server startup, then only we will be able to find out the rootcause

#EntityListeners configured from container

I have a EntityListener that needs to be configurable (typical data source info: driver, user, password), but I´d like to avoid adding one more properties file to the project. Is there any way to retrieve from some standard configuration place such as web.xml? It seems that injection via #Resource will be only available in JPA 2.1 (I am using JPA 2.0).
UPDATE - to make this clear
In my entity bean, I have an annotation #EntityListeners(MyEntityListener.class). So MyEntityListener may have methods annotated with #PostPersist for example. When my entity bean is gonna be persisted, this method is called. What I want is to retrieve the data for MyEntityListener initialization without using another configuration file.
http://openjpa.apache.org/builds/2.2.1/apidocs/org/apache/openjpa/audit/Auditor.html does the trick. It works (my bad, it was a misconfiguration of mine). Actually it works pretty well.
<property name="openjpa.Auditor" value="com.acme.Auditor(param2=10,param2='hello')"/>

Porting my hibernate Dao layer in a stand-alone java app?

I have a spring mvc application that I am using Hibernate with.
I am using the sessionFactory.getCurrentSession in my Dao methods (not hibernate support).
What I want to know is, what do I have to do to be able to use my hibernate database layer
in a non-web application?
I have a stand-alone java application (that runs via main) where I load spring's application context
programatically and then get my service layer (which depends on my hibernate db layer).
Do I need to do anything special in my spring.xml file to setup hibernate's session?
In my spring mvc web app, I did annotate my Dao methods with the #Transactional annotation.
(I want the transaction on a per call basis, not for a group of db calls).
P.S In my web app, how are sessions created/destroyed, is it per request?
You can get hold of the spring ApplicationContext from main method. it will behave exactly the same as the one in web.
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
YourDAO yDao = (YourDAO)context.getBean("yourDAO");
yDao.callYourSpecialMethod();
So, from this point there is no dependancy for hibernate, it should work automatically. here just the view gets changed, no logical or structural changes. So the transactions and other things should work as usual.

Application vs Container Managed EntityManager

I am currently having a problem with understanding a concept of JPA.
I am currently using/developing recent EclipseLink, Glassfish, Derby database to demonstrate a project.
Before I develop something in much bigger picture, I need to be absolutely sure of how this PersistingUnit work in terms of different scopes.
I have bunch of servlets 3.0 and currently saving user's associated entity classes in the request.session object (everything in the same war file). I am currently using Application-managed EntityManager using EntityManagerFactory and UserTransaction injection. It works smooth when it is tested by myself. The different versions of entities occur when 2 people accessing the same entities at the same time. I want to work with managed beans cross the same WAR, same persistence unit if possible.
I have read http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html and bunch of explanations of those scopes which don't make sense at all for me.
Long story short, what are the usage and difference of app and container managed EntityManagers?
When you say application managed transaction it means its your code which is supposed to handle the transaction. In a nutshell it means:
You call:
entityManager.getTransaction().begin(); //to start a transaction
then if success you will ensure to call
entityManager.getTranasaction().commit(); //to commit changes to database
or in case of failure you will make sure to call:
entityManager.getTransaction().rollBack();
Now imagine you have a container, which knows when to call begin(), commit() or rollback(), thats container managed transaction. Someone taking care of transaction on your behalf.
You just need to specify that.
Container managed transaction(CMT) could be regarded as a kind of declarative transaction, in which case, transaction management is delegated to container (normally EJB container), and much development work could be simplified.
If we are in a Java EE environment with an EJB container, we could use CMT directly.
If we are in a Java SE environment, or a Java EE environment without an EJB container, we could still take advantage of CMT, one way is to use Spring, which uses AOP to implement declarative transaction management; Another way is to use Guice, which uses a PersistFilter to implement declarative transaction.
In CMT, a container (whatever an EJB container, Spring or Guice) will take care of the transaction propagation and commit/rollback stuff;
Application managed transaction (AMT) differs from CMT in that we need to handle transactions programmatically in our code.

Categories