EDIT: I figured the first part of my question out myself - to avoid closing my question and opening a new one for the second part, i recycle this question and provide the link for accessing remote EJB ont he same applicationserver:
github example, thanks to PiotrNowicki
I have a War and a ear.
The Ear contains a #Stateful EJB, using a PersistenceContext.EXTENDED for some databaseoperations. This Context is extended for access to Lazy-fetched lists in Entities outside the Persistence-bean.
The WAR has a JAX-RS REST-Interface, implemented using #Stateless Sessionbeans, which also do simple operations on other datasources. they do not require an extended context, so they use regular CMT.
the Beans in the WAR however need to call the EAR'S EJBs.
If I just Merge the Projects into one EAR and inject the beans via #EJB, the CMT cannot interact with the Extended Persistence-Context. This is expected, see JPA spec 7.6.3. (#Stateless beans attach a regular PersistenceContext to the transaction, which an extended context does not accept)
So I split the two Services and now need a Service-Interface for interaction.
My Question is:
1) Would remote EJB-calls SOLVE the Transaction-Problem, or would the JBOSS behave like the Bean was Local and try to add the Extended persistencecontext to the local transaction - resulting in the same problem?
Related
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.
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
My apologies for lengthy question.
I'm working on a EJB application. I have two EJB eclipse projects(Ejb1 and Ejb2) and other dynamic web application(Web1) which will be compiled and added to a parent EjbEar project and packaged as EjbEar.ear file.
Question1: I've first created a persistence.xml in EJb1 project's META-INF folder and this helps me inject the entitymanager into the session beans and start working. (code below)
#PersistenceContext(unitName = "ejbPersistanceunit")
private EntityManager em;
In Ejb2 I've created another session bean and injected the entitymanager same like above(here I did not configure the persistence.xml) but when I invoke from the client, I get the response from both the Ejb1 and Ejb2 projects.
Why does the EntityManger get shared between two ejbprojects? If my Ejb2 project needs another persistence.xml for a different data source, do I create another one or have it included in the existing persistence.xml? will it also be shared ? Does my Web1 project also get hold of the Entitymanager in the same way?
Question2: I have sessionbeans in Ejb1 project and their remote interfaces are created in Web1 project but what is the best approach in exposing these newly created Entities/Interfaces in an ejb project? (For more than one Ejb project in an Enterprise application)
Question3: Ejb 3.0 no longer have the home and remote interfaces correct?
Why does the EntityManger get shared between two ejbprojects?
You can disable this sharing by isoloting Ejb jars if you don't want. If jboss open jboss-deployment-structure.xml and setting the property ear-subdeployments-isolated to true
If my Ejb2 project needs another persistence.xml for a different data
source, do I create another one or have it included in the existing
persistence.xml? will it also be shared ?
It purely depends on your use case,
if you have multiple datasources in your system then I would define my persistence.xml based
the way I package my beans accessing the Persistence Unit.
In case, if all of the entities belonging to both of the datasources are packaged together then I would define 2 persistence Unit in the same persistence.xml
if they are packaged in differently in 2 jars, then any of the following is a possibility
if beans accessing the entities serviced by the same
persistenceUnit/Datasource are packaged together then I would create
2 persistence.xml with associated PersistenceUnit in 2 jars
if isolation is set to false, then I can define my persistence.xml like
above or I would define 2 persistenceUnit together in a single
persistence.xml and would make sure that the jar with
Persistence.xml is deployed first
Does my Web1 project also get hold of the Entitymanager in the same
way?
Yes, you can get access to persistenceContext
Note: I assumed your app server to be JBoss
I have sessionbeans in Ejb1 project and their remote interfaces are
created in Web1 project but what is the best approach in exposing
these newly created Entities/Interfaces in an ejb project? (For more
than one Ejb project in an Enterprise application)
As far as my knowledge goes, it depends on your system Architecture/ Design. If I were you, I would have packaged my remote interfaces and Beans together in the same EJB-Jar and I would either use Business Delegate that lookup the EJB beans or as Remote interfaces are visible in the web, I would inject the same in the web layer and use it.
Ejb 3.0 no longer have the home and remote interfaces correct?
There are no interface called home & remote but the concept is still there in the form of annotations #Remote & #Local, which means you define your interfaces and you can declare either #Remote or #Local either at the interface level or at the Bean level.
I am a newby with CDI and EJB and I've just created a jboss web application. Though, additionally, I also wanted this app to process rabbitmq messages. When processing these, I would like to do some persistence work, though, as I've been listening for rabbitmq messages from an application scoped bean that is started with the #Startup annotation, I've not been able to commit any transaction within this kind of scope, that is, as I am departing from the application scope, every bean that I will instatiate from this scope will be application scoped. When I try to perform em.getTransaction() and em.commit() the code blows up complaining that I cannot invoke getTransaction() under JTA transactions, and when I use User transactions, every operation seems to be put onto the same transaction until it finally is rolled back, or there errors complaining that there is a already a transaction underway...
CDI beans do not support transactions out of the box like EJBs do. So your options are to either:
Upon receiving RabbitMQ messages, call some EJBs (directly or through observers) that will do the persistence work.
Add transactions support to your existing CDI beans using one of the following - Apache DeltaSpike or Seam Persistence.
It is indeed quite hard to give you more details based on the info you provided. However, on the conceptual level, one of the approaches above would do the trick.
Also, the notion of event scope seems confusing. I would say you don't need it. One of the approaches above will do. Also, take a look at CDI events.
we are developing a set of components that can be used by our applications which currently run on Jboss 4.2.3.GA.
However, since JBoss 4 is quite old now, we'd like to migrate to JBoss 5+ (most likely JBoss 6.1).
In that case, we have a problems with our components containing stateless session beans annotated with the JBoss specific #PoolClass annotion, which has been renamed to #Pool as of JBoss 5.
As you can see, using that annotation in the components introduces a dependency not only on the application server but on specific versions as well. Thus I'd like to get rid of that annotation and use configuration via XML.
In that case, I'd like not to have to define a pool class per session bean, since almost all of them use the StrictMaxPool class with the same settings. If any session bean needs a different pool or different setting, it's ok to provide a specific entry, but I'd rather not do that for the majority.
The default pool class is generally defined in ejb3-interceptors-aop.xl. However, that configuration applies to all applications deployed on that server.
What I'd like to do now, is to define a default pool class (with default settings) per application, if possible without adding anything specific to the session beans in our components (like the JBoss specific #AspectDomain annotation).
Is that possible and if yes, how?
I couldn't manage to find any useful information yet, so I'd be glad if someone could point me in the right direction.
Edit: If you have information on how to do that in JBoss 5+, that would be great too, but JBoss 4 is of higher priority for now.
Seems like I found a solution:
There's a problem with JBoss AOP 1.5.6 which is used by JBoss 4.2.3.GA.
Although there's no bug filed it seems there is one preventing the scoped use of pool definitions (it looks like the source of the problem is an inverted if-condition :) ).
Upgrading to JBoss AOP 2.1.8 works like a charm.
Here's what I do:
Put a jboss-aop.xml file into the root of an ejb jar in the ear (we already have one that contains our persistence.xml).
In the jboss-aop.xml create a domain Stateless Bean that extends from the default Stateless Bean domain and inherits all bindings and definitions
Inside the extended domain override the pool class definition.