Persistence context scope in a ejb j2ee and other questions - java

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.

Related

Transactions across remote EJB Calls

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?

JPA EntityListener and persistence archive

we've a persistence archive containing only Entities and the persistence.xml. And we've an ejb module containing the ejb stuff.
Now for a specific use case we need to add an EntityListener which has access to some EJBs in the service layer.
The ejb module depends on the persistence module. However to declare the listener in the Entity the persistence module needs to know about the class in the ejb module. A cyclic dependency is not possible and having a third module containing only the JPA listener leads to cyclic dependencies as well.
So the only option I see is to merge the ejb module and the persistence archive into a single module. However that way we loose the flexibility to use the persistence archive in another application to connect to the remote interfaces without carrying the whole ejb jar's content.
Any ideas on how to solve this and stay modular (separate ejb and persistence modules?).
We're talking about a JEE7 application.
You could move the persistence.xml from your JPA project to your EJB project and then use the <jar-file>packedEntity.jar</jar-file> XML element. Check this answer.
One idea is to use your Source-Control-Management (git/svn/cvs) to import the entity package in your EJB project (+the persistence.xml file). This way, you have more flexibility on what/how you define them.
In SVN you have svn:externals. For git check out this answer.

How to correctly reference annotated EJB3 beans from JNDI in WAR-project

We have a multimodule Java EE 5 project running on Weblogic 10.3.x. One module has the EJBs and our batch processor is running from the web-module. Since we don't have CDI in JavaEE5, we have to do a JNDI-lookup on the EJBs. The EJBs are defined with #Stateless on the class and #Remote on the interface.
I have succeeded accessing the EJBs by looking the following string:
ejb/batchService#com.example.service.batch.ejb.BatchServiceRemote
However, I belive this is highly platformdependent, and I suspect I should have put something inside the web.xml and probably into the weblogic.xml at least in the web-module - maybe even in the EJB module...
Could anyone enlighten me how to do this propperly? Or is this the best way available?
JNDI format of local bean is
java:comp/env/BeanClassName
JNDI format for remote bean is
mappedName#com.package.BeanClassName
for
#Stateless(mappedName = "mappedName")
public class BeanClassName {
PS. This format supported by WebLogic 10.3. Behaviour of another application servers may be differentю
Prior to EJB 3.1 / EE 6, there are no standardized lookup strings for EJBs. Since they're not standardized, hard-coding the actual binding name of the EJB does make your project product-specific.
The best solution is to create another level of indirection: declare an <ejb-local-ref> in web.xml (or as #EJB/#EJBs on a servlet or other component class), and then use java:comp/env/xyz to lookup the ref. Then, use platform-specific bindings for the EJB ref.

JBoss 5.0 EAR: Locate #Service ejb local interface from struts 1 action in nested war with jndi lookup

I have a war (using struts 1) nested in an ear with session ejbs. If I lookup normal session beans from the war with lookup("earname/beanname/local") everything works. If I lookup a #Service ejb the same way it fails from the war with a NamingException.
To make sure I was doing the lookup correctly I looked up one #Service bean from another's start() method (instead of injecting with annotations) and the jndi lookup succeeded.
What could be the cause of this behavior? I am currently stuck with JBoss 5.0.
After going through the jmx-console like Nicholas recommended I was able to track down my mistake.
It turns out my two lookups were in fact different. The war was using the service name that I wanted, everything else (which was working) was using the class name of the implementation of the #Local interface.
To further the confusion I used #Service(objectName="blah") instead of #Service(name="blah").
I am now able to successfully lookup my #Service ejbs from my war.

Packaging EJBs in Java EE server

I have deployed an enterprise app in an EAR and a standalone web app in WAR (out side of the EAR) to the same Java EE server.
Question is can I access the local interface of the session bean in the EAR from the standalone WAR? if so can I use dependency injection (DI)?
Section 3.2.2 of the EJB 3.1 specification explicitly states that this is not portable:
Access to an enterprise bean through
the local client view is only required
to be supported for local clients
packaged within the same application
as the enterprise bean that provides
the local client view. Compliant
implementations of this specification
may optionally support access to the
local client view of an enterprise
bean from a local client packaged in a
different application. The
configuration requirements for
inter-application access to the local
client view are vendor-specific and
are outside the scope of this
specification. Applications relying on
inter-application access to the local
client view are non-portable.
In general, the solution will require at a minimum:
Some mechanism for allowing both the EAR and WAR class loaders to have visibility to the same interface class.
Some mechanism for looking up a local interface from another application. For example, java:global.
The answer anyway to both your questions is yes.
Since both the ear and war are in the same JVM, a local interface can be used. To get an instance of the session bean, you would use the global JNDI name of said bean to do either a JNDI lookup or use with the mappedName property on the #EJB annotation. Those names are standardized via the following pattern:
java:global[/<app-name>]/<module-name>/<bean-name>[!<fully-qualified-interface-name>]
Lookup would thus be if the name of your ear is my_app, your bean is MyBean.java and its local interface is com.foo.SomeBeanLocal:
InitialContext ctx = InitialContext();
SomeBeanLocal someBean = (SomeBeanLocal) ctx.lookup("java:global/my_ear/SomeBean/com.foo.SomeBeanLocal");
Injection would be:
public SomeManagedClass {
#EJB(mappedName="java:global/my_ear/SomeBean/com.foo.SomeBeanLocal")
SomeBeanLocal someBean;
}
There are two catches however:
Non-standard naming
Older Java EE implementations (e.g. JBoss AS 5.1, Glassfish 2, Websphere) used their own naming pattern. E.g. JBoss AS 5.x would use:
<app-name>/<bean-name>/local|global
E.g. with the same names as the previous example, the global JNDI name of that bean in JBoss AS 5.1 would be:
my_app/MyBean/local
As said, other old application servers might use other names.
Startup-order
Especially with injection you have to assure somehow that the application you want to inject from has been started before the application you want to inject into. I.e. in your case that the EAR has been started before the standalone WAR. There are no standard mechanisms for this. You might be just lucky that it happens to be in the right order for you. This order might be influenced by time-stamps, alphabetical order of application names, or something else entirely.
JBoss AS for example uses <depends> tags in many of its proprietary configuration files, which is perfectly suited for this although it can be hard to find out what exactly you need to depend on (the syntax can be very cryptic).

Categories