Remote EJB not found - java

I have an EJB deployed in an EAR:
#Stateless
#Remote(ActorProvider.class)
public class ActorServiceClient implements Serializable, ActorProvider { ... }
Here is the remote interface:
#Remote
public interface ActorProvider { ... }
Now, I have a separate WAR being deployed with the following class:
#Singleton
#Startup
public class ShiroStartup implements IShiroStartup {
#EJB
ActorProvider actorProvider;
...
}
The idea being that I deploy my actor service in an EAR, and I separately deploy a client project that gets the ActorProvider which Shiro uses for authorization (this is ancillary, but what I'm using it for).
I get an error starting the ShiroStartup (after I have deployed the EAR with the provider in it):
No EJB found with interface of type 'consumers.ActorProvider' for binding realm.ShiroStartup/actorProvider
Why can't I do this? If I put the Provider in the war with the ShiroStartup it works fine, but it will not inject across deployments. Why is that? This is Wildfly 9 using JavaEE 7.

1., The EJB and WAR modules should take place in the same EAR
or
2., Include the EJB jar into the classpath of the WAR
or :)
3., with portable JNDI names (for remote interfaces):
https://docs.oracle.com/cd/E19798-01/821-1841/girgn/index.html
In particular: java:app[/module name]/enterprise bean name[/interface name]

Related

How to deploy a jar to glassfish, which contains a main method?

I'm new to EJB. I have an ejb-jar file which contains, "Class1" and i deployed it to glassfish server. Now there is another jar file which contains only the following client file(it has a dependencey injection), so my problem is how should i execute this file?
I just deployed it to glassfish, but it doesn't work and show error in log file("it contains zero ejb").
import com.pack.Class1;
public class CreateAccoutnClient {
#EJB
private static Class1 class1;
public
static void main(String[] args) {
}
}
If anyone who have read EJB 3 in Action, i'm tring to deploy chapter3 code to glassfish with eclipse.
Thanks :)
EJB context doesn't execute any main methods, with Glassfish (and others) you must deploy a war to have entry points that run your app or methods (web services or web app).
A jar can contain MDB, remote ejbs or scheduled timers, or could be just a library. The only way to execute some initialization method at startup is to use the EJB3 #Startup annotation

Cannot put EJB in a separate jar

I have an EJB with some JPA logic that I use in my java EE projects.
Instead of copying the class in every project I'm trying to put it in a separate jar, so I have this structure:
Java EE project with EJB and WAR projects in it
JPALogic: JAR project with JPALogic class in it
RemoteServices: JAR project with beans interfaces
Services: EJB project with beans, including JPALogic and RemoteServices as libraries
Frontend: WAR project with frontend, including RemoteServices as library.
JPALogic is used only in the EJB project and there's no reference to it in other parts of the Java EE app. In JPALogic library I've my JPALogic bean:
#Stateless
#LocalBean
public class JPALogic {
#Resource
private EJBContext ejbContext;
#Inject #ShardedPersistenceContext
private EntityManager em;
public JPALogic() {
}
[...lots of methods...]
}
It works perfect if JPALogic code is directly in the EJB project, but when I put it in the external library deployment become very unstable (netbeans 8 + glassfish 4) and almost every deploy fail with this error:
Exception while deploying the app [app] : Cannot resolve reference [Remote ejb-ref name=com.my.autenticacion.services.AutRolBackendServices/jpa,Remote 3.x interface =com.my.infraestructura.jpa.JPALogic,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session] because there are [2] ejbs in the application with interface com.my.infraestructura.jpa.JPALogic.
I've search but it seems this kind of error appear when an interface have more than one implementation, and this is not the case: there's only one bean named "JPALogic" and, inspecting the ear, JPALogic.jar appear one time only.
I'm doing something wrong?
If you jar contains EJB annotations (#Singleton, #Stateless, #Stateful component-defining annotations), its not a simple jar, but an ejb-jar, and should be packaged as a module.
Solution:
You should reference the JPALogic.jar in application.xml as an EJB module.
You can also add a "Class-Path: JPALogic.jar" in the META-INF/MANIFEST.MF of the referencing modules to garantee visibility. It could be visibile, depending on the container.
Like this:
application.EAR
META-INF/application.xml
(must have a reference to the JPALogic.jar EJB module)
JPALogic.jar (EJB-JAR)
remoteservices.jar
services.jar
META-INF/MANITESF.MF Class-Path: JPALogic.jar
remoteservices.jar
frontend.war
For a more details, refer to the JAVA EE 6 specification, chapter EE.8:
EE.8.3.2 EJB Container Class Loading Requirements
EE.8.5.2 Deploying a Java EE Application

Calling EJB from a WAR inside the same EAR

I am using Glassfish 4. And I have an EAR which has a WAR and a JAR (with the EJBs).
I want to call the EJBs from my WAR but am not really sure if I need to use Local or Remote interfaces.
Inside my JAR, my Bean looks like this :
#Stateless
public class Test implements TestLocal {
#Override
public void testing() {
}
}
And my local :
#Local
public interface TestLocal {
void testing();
}
Inside my WAR I have a web service and it looks like this :
#WebService(serviceName = "TestWS")
public class TestWS {
private #EJB TestLocal testBean;
#WebMethod(operationName = "test")
public String test() {
testBean.test();
}
}
Both of these are packaged into an EAR.
When I call my WebService method I get an AccessLocalException :
Warnung: javax.ejb.AccessLocalException: Client not authorized for
this invocation at
com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:1895)
at
com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:210)
Firstly :
Is this the correct way to call the EJB. Can a WAR inside an EAR use Local interfaces from an included JAR?
If so then does anyone know what I am doing wrong? Do I need to setup some kind of security configuration?
To look up a remote EJB, it must have a remote interface exposed. Include that remote interface into your war.
The GlassFish documentation has an entry for this error:
javax.ejb.AccessLocalException: Client Not Authorized Error
Description
Role-mapping information is available in Sun-specific XML (for example, sun-ejb-jar.xml), and authentication is okay, but the following error message is displayed:
[...INFO|sun-appserver-pe8.0|javax.enterprise.system.container.ejb|...|
javax.ejb.AccessLocalException: Client not authorized for this invocation.
at com.sun.ejb.containers.BaseContainer.preInvoke(BaseContainer.java:...
at com.sun.ejb.containers.EJBObjectInvocationHandler.invoke(...)
Solution
Check whether the EJB module (.jar) or web module (.war) is packaged in an application (.ear) and does not have role-mapping information in application level, Sun-specific, sun-application.xml. For any application (.ear), security role-mapping information must be specified in sun-application.xml. It is acceptable to have both module-level XML and application-level XML.
#Remote is usefull if you deploy separately your jar which contain your EJBs on a different server, for example.
There, war and jar are in the same ear so you just have to use the Local annotation.
Tips : since EJB 3.1 interfaces are not required, you can use #LocalBean directly on your "Test" class and remove the TestLocal interface.
To call a ejb method into a class which is your war, you firstly have to create a link between war and jar. Being in the same ear is not enough.
If you use Maven, you can simply add the jar reference into your dependencies in the pom of your war.

#EJB inject from different jar

I'm trying to inject a bean located in a different jar file then the bean i'm trying to inject it into. Both beans are just basic #Stateless beans with local and remote interfaces.
If i use the normal injection
#EJB
IBean injectedBean;
or
#EJB
IBeanLocal injectedBean;
i get a NullPointerException when deploying the application.
If i use:
#EJB(mappedName="Bean")
IBean injectedBean;
or
#EJB(mappedName="Bean")
IBeanLocal injectedBean;
everything works and JBoss throws no deployment errors.
I might mention i use JBoss 5.
The bean class i'm injecting is declared as:
#Remote
public interface IBean
#Local
public interface IBeanLocal extends IBean
#Stateless(name = "Bean")
public class Bean implements IBean, IBeanLocal
My problem is that as specified in the documentation the mappedName property is vendor-specific. Is there any other way i could get this to work?
SOLVED:
I managed to solve the problem.
The problem was that i tried to deploy both jars individually which meant that each would get it's own ClassLoader in JBoss so that they couldn't find each other and would return a NullPointerException when trying to inject the bean.
The sollution was to add the jars to an ear and add an META-INF containing an application.xml looking like this:
<application xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/application_1_4.xsd"
version="1.4">
<display-name>Simple example of application</display-name>
<module>
<ejb>ejb1.jar</ejb>
</module>
<module>
<ejb>ejb2.jar</ejb>
</module>
</application>
I also had to change some JNDI lookups i made to match the new structure by adding the ear name before the classes: "ear-name/bean"
After this i just added the jars to the ear and everything deployed nicely.
You need to declare the local interface in order to have JBoss find the bean based on the interface only (assuming you're using EJB 3.0):
#Stateless(name = "Bean")
#Local ( IBeanLocal.class )
#Remote ( IBean.class )
public class Bean implements IBean, IBeanLocal { ... }
Edit: IBean is a remote interface (see comment).
Try injecting your bean with #EJB(beanName = "Bean")
Not sure if it'll work, but we had a similar issue and it was caused by the lack of the beanName attribute.

Weblogic Ear deployment fails to inject entity manager

The issue I am currently experiencing is that my entityManager fails to be injected during the execution of a web application deployed within an ear.
The ear is setup as follows:
/META-INF -application.xml (EJBJar +
WAR)
-MANIFEST.MF
-weblogic-application.xml (currently just the default one that eclipse
generates)
/APP-INF
-lib
-EJBClientJar (interfaces + pojos)
-other jars
-classes
EJBJar
/META-INF
-persistence.xml
/src
-Annotated classes
WAR
-Service classes
Classes are as follows:
DAO inside EJBJar
#Stateless(mappedName="AwesomeBean")
public class Awesome implements AwesomeRemote //AwesomeRemote in EJBClientJar
{
#PersistenceContext
EntityManager em;
}
public class AwesomeService //Inside WAR
{
AwesomeRemote = context.lookup (Awesome.path.to.AwesomeRemote) //Is found
}
The call stack is like this:
War -> EJBClientJar -> EJBJar
On the EJB jar the entity manager is null. Question being how do I ensure that the PersistenceContext gets injected? The JNDI lookup succeeds on the AwesomeRemote Interface. The Interface has no annotations on it.
It's probably due to the fact that you try to inject on POJO class, not on managed component. Could you try to mark it as #Stateless and public and check whether it works?
For simple testing you can also add #WebService annotation and invoke your bean with SoapUI for example.
You should read about "packaging" part of ejb specifications.
This structure should be sufficient and work:
/
/lib
EJBClientJar (interfaces + pojos)
/META-INF
persistence.xml
application.xml
EJBJar.jar
WAR.war
As some formatting was lost, I'm not sure about what wasn't right in yours.
If this still doesn't work, try removing the only tricky part from above: put all classes from EJBClientJar in root. You the just have the most simple EAR packaging possible, it just will work.
Also, if you don't use your session bean outside a web application, you could use #Local instead of #Remote .

Categories

Resources