I'm working on EJB application, and i'm trying to use lookup approach but it fails at Runtime moment,
Here my code and configuration :
weblogic.xml
<ejb-reference-description>
<ejb-ref-name>
RechercheClientSMBean
</ejb-ref-name>
<jndi-name>
*****-ejb/RechercheClientSMBean/local
</jndi-name>
</ejb-reference-description>
Local Interface
#Local
public interface IRechercheClientFacade extends Facade {}
Bean Implementation
#Stateless(name="RechercheClientSMBean", mappedName="RechercheClientSMBean")
public class RechercheClientSMBean extends AbstractBean implements IRechercheClientFacade { }
web.xml
<ejb-ref>
<ejb-ref-name>RechercheClientSMBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>com.*****.***.app.service.common.client.RechercheClientSMBean</home>
</ejb-ref>
Bean Lookup Code
InitialContext ctx = new InitialContext();
iRechercheClientFacade= (IRechercheClientFacade)ctx.lookup("java:comp/env/RechercheClientSMBean");
It results into the following Exception :
weblogic.deployment.EnvironmentException:
The ejb-link 'RechercheClientSMBean' declared in the ejb-ref or ejb-local-ref 'RechercheClientSMBean' in the application module 'pfi.war' could not be resolved. The target EJB for the ejb-ref could not be found. Please ensure the link is correct.
I checked every possible configuration, every naming possibility but i keep getting this same problem.
PS: the project is divided into multiple modules, the lookup method is made from web container.
Many thanks in advance.
Have you tried the following:
ctx.lookup("java:comp/env/ejb/RechercheClientSMBean");
Related
I have a working Glassfish 5 setup inside of Eclipse.
I have modules set up like this:
common
contains remote interface for singleton bean with #remote and #local annotation
included in all other modules as a pom dependency
core
contains a singleton bean that implements the interface in common
intended to contain service classes stored in JNDI that allow any number of clients to lookup and store data and/or access other service logic
builds a war file that deploys onto GlassFish
desktop
does an InitialContext lookup of the singleton bean. (I intend to abstract this into the Service Lookup design pattern).
intended to be a desktop client that remotely accesses beans stored on the server.
Right now, I'm just trying to get it to remotely access the service in core and print some text to the console proving it worked.
I think my problem stems from a misunderstanding of how to store a custom bean in JNDI in the first place. I looked on Google, but I mostly find articles and answers to questions telling me to add name and mappedName to the Singleton annotation or they only show how to add a predefined bean into JDNI such as a Boolean or String, and not something custom defined.
My bean is defined like this:
#Singleton(name = "BookService", mappedName = "ejb/BookService")
public class BookServiceImpl implements BookService {
private static final long serialVersionUID = 1L;
which results in this on the Glassfish server:
Core Server Screenshot
but nothing appears in JNDI:
JNDI Screenshot
The client does it's InitialContext lookup like this (I've tried multiple ways of writing the JNDI name):
BookService bookService = (BookService) initialContext.lookup("java:global/core/BookService");
using these configurations (I defined my domain with a base port of 8000, so every port is 8000 + something):
glashfishEnvironmentTable = new Hashtable<String, String>();
glashfishEnvironmentTable.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.enterprise.naming.impl.SerialInitContextFactory");
glashfishEnvironmentTable.put(Context.STATE_FACTORIES,
"com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
glashfishEnvironmentTable.put(Context.URL_PKG_PREFIXES, "com.sun.enterprise.naming");
//glashfishEnvironmentTable.put(Context.PROVIDER_URL, "ejbd://localhost:8080/");
// on a different host than the appserver
glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialHost", "localhost");
// optional. Defaults to 3700. Only needed if target orb port is not 3700.
glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialPort", "8037");
I get an error like this when I run it:
Exception in thread "main" javax.naming.CommunicationException: Communication exception for SerialContext[myEnv={org.omg.CORBA.ORBInitialPort=8037, java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, org.omg.CORBA.ORBInitialHost=localhost, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl} [Root exception is java.rmi.MarshalException: CORBA MARSHAL 1330446343 No; nested exception is:
org.omg.CORBA.MARSHAL: FINE: 00810007: Underflow in BufferManagerReadStream after last fragment in message vmcid: OMG minor code: 7 completed: No]
I think my InitialContext is configured properly because when I manually define the bean in JNDI like this (The ServiceFactory doesn't do anything, because I don't know how to properly extend ObjectFactory):
Bean defined in JNDI
I get this:
Exception in thread "main" java.lang.ClassCastException: javax.naming.Reference cannot be cast to common.service.BookService
Is there simple fix to this I am missing, or am I mixing oil and water trying to get an EJB Singleton into JNDI? Or am I missing something big like an EJBHome or a Servlet?
Do I need to extend the factory class to add my service classes into JDNI, or should ObjectFactory work? If I must extend the factory class, how would I go about it?
I hope I've defined the scope of the question well enough, but this is all new to me, so if anybody has experience implementing something like this, I appreciate any input that gets me closer to doing it right.
I figured it out. I did two things I shouldn't have.
I forgot to maven install my common module before building my war file... doh!
It seems that the #Remote and the #Local annotations cannot be in the same interface or it will fail (which is a shame, because I was trying to set it up so I didn't have to have two nearly identical interfaces).
Here are some more details in case someone else has a similar issue and needs to see something that works (I haven't done #Local here, because I haven't tried it yet. It should be trivial to add though):
For remote execution, you need an interface annotated with #Remote that extends Serializable (Serialization is required for Client/Server interface).
import java.io.Serializable;
public interface Remote extends Serializable{
}
import javax.ejb.Remote;
#Remote
public interface BookServiceRemote extends Remote {
public String readBook();
}
Your war file needs to contain the BookServiceImpl
import javax.ejb.Singleton;
import us.boggs.template.common.service.BookServiceRemote;
#Singleton(name = "BookService")
public class BookServiceImpl implements BookServiceRemote {
private static final long serialVersionUID = 1L;
#Override
public String readBook() {
return "Read the book.";
}
}
Your client pom.xml must include the common module and this:
<dependency>
<groupId>org.glassfish.main.appclient</groupId>
<artifactId>gf-client</artifactId>
<version>5.1.0</version>
</dependency>
Your client main method can use this by creating an InitialContext and doing a lookup(My base port was 8000, so my ORBInitialPort is 8000+37=8037):
private static Hashtable<String, String> glashfishEnvironmentTable;
static {
glashfishEnvironmentTable = new Hashtable<String, String>();
glashfishEnvironmentTable.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.enterprise.naming.impl.SerialInitContextFactory");
glashfishEnvironmentTable.put(Context.STATE_FACTORIES,
"com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
glashfishEnvironmentTable.put(Context.URL_PKG_PREFIXES, "com.sun.enterprise.naming");
glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialHost", "localhost");
// optional. Defaults to 3700. Only needed if target orb port is not 3700.
glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialPort", "8037");
}
InitialContext initialContext = new InitialContext(glashfishEnvironmentTable);
BookServiceRemote bookService = (BookServiceRemote) initialContext.lookup("java:global/core/BookService");
System.out.println(bookService.readBook());
I'm not sure if this is a generic JEE6 question or if it is a Wildfly 10/JBoss7 EAP implementation specific question.
I'm trying to specify/override the default beanName used in my EJB JNDI mapping to something more meaningful to me.
For example:
LoginManagerBean:
#Stateless
public class LoginManagerBean extends BaseManagerBean implements LoginManager {
....
}
LoginManager:
#Local
public interface LoginManager{
....
}
In this context, WF10 will automatically create a JNDI mapping for this EJB as:
ejb:myApp/myJar/LoginManagerBean!LoginManager
In the Wildfly 10 documentation for EJB naming conventions, it says
For stateless beans:
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fully-qualified-classname-of-the-remote-interface>
.... ....
bean-name : This is the name of the bean for which you are doing the
lookup. The bean name is typically the unqualified classname of the
bean implementation class, but can be overriden through either
ejb-jar.xml or via annotations. The bean name part cannot be an empty
string in the JNDI name.
However, I cannot seem to find which annotation to use to specify the bean name in an annotation. If I read the docs for #EJB it states that the beanName parameter is:
The ejb-name of the Enterprise Java Bean to which this reference is mapped
So from the docs, it does not seem that the beanName is the right parameter to use.
So how can I rename my EJB beanName in the mapping to something of my choice? For instance, what annotation can I use to make the mapping read:
ejb:myApp/myJar/MyReallyCoolName!LoginManager
If you're using JBossEAP 7/WildFly 10.x then this is JavaEE 7, although the same answer applies to Java EE 6.
You only appear to be using Local interfaces, so none of the instructions that you linked apply because they are only for remote EJB clients. Therefore these statements:
In this context, WF10 will automatically create a JNDI mapping for this EJB as:
ejb:myApp/myJar/LoginManagerBean!LoginManager
are completely incorrect.
When you deploy your application all of the JNDI names are logged in the server console:
java:global/serverapp/LoginManagerBean!com.stackoverflow.p43282192.LoginManager
java:app/serverapp/LoginManagerBean!com.stackoverflow.p43282192.LoginManager
java:module/LoginManagerBean!com.stackoverflow.p43282192.LoginManager
java:global/serverapp/LoginManagerBean
java:app/serverapp/LoginManagerBean
java:module/LoginManagerBean
Most of the time you should not care about the JNDI names because in general each EJB is unique and the server will find the right implementation:
public class LoginClient {
#EJB
private LoginManager loginManager;
...
}
If you want to use JNDI lookups and you want to create more work for yourself then you can specify the bean name:
#Stateless(name="Foo")
public class LoginManagerBean implements LoginManager {
...
which yields:
java:global/serverapp/Foo!com.stackoverflow.p43282192.LoginManager
java:app/serverapp/Foo!com.stackoverflow.p43282192.LoginManager
java:module/Foo!com.stackoverflow.p43282192.LoginManager
java:global/serverapp/Foo
java:app/serverapp/Foo
java:module/Foo
and you can look these up if you must:
LoginManager loginManager = (LoginManager)(new InitialContext().lookup("java:app/serverapp/Foo"));
or using injection:
#EJB(beanName="Foo")
private LoginManager loginManager;
BTW, I'm just deploying the sample EJB jar here (serverapp.jar). Some of the names have an additional path element if you're using an EAR file.
Im writing JavaEE application, which contains of three modules.
In web module I need to inject ejb bean (in Stripes action bean method), which is located in ejb module.
So i followed this tutorial
http://www.stripesframework.org/display/stripes/Stripes+Injection+Enricher
My code goes like this>
#EJB
private CustomerServiceLocal customerService; //service layer for customer
and after deploying on GlassFish it returns following exception>
No EJB found in JNDI, tried the following names:
list of JNDI that it tried.
The bean is declared as follows>
#Stateless
#Local(value=CustomerServiceLocal.class)
#LocalBean
public class CustomerService implements CustomerServiceLocal {
interface>
#Local
public interface CustomerServiceLocal
I dont know what code could be relevant, so if I missed something just tell me what should I copied here.
So do you have any idea how to solve it ? How to set EJB Bean in different module in Stripes ActionBean method ?
It seems that stripes injection enricher is somehow wrongly configurated.
The problem is I need that service layer make work, since it is responsible for work with DB, and without it, I can just work with temporal local objects, which is useless.
Best regards,
OSiRiS
I have a stateless Bean with following heirarchy and present
accountserver , accountserverBean implements accountserver.
with there corresponding ejb-jar.xml and weblogicjar.xml
Then I have my spring Bean with the following
payload.java with corressponding spring.xml
So Inside the spring libs folder I have added account.jar
So how can I call method present in accountserverBean from payload class????
Also I have used the below Code in payload.java
Context ctx=new InitialContext();
accountserver as=(accountserver)ctx.lookup("java:com/accountserver");
But this doesnt work.
Since both are in same context I can call the EJB method
Please provide me with solution
I guess you want to integrate EJB and Spring applications. Did you try this: http://static.springsource.org/spring/docs/2.5.x/reference/ejb.html ?
Being completely new to Java EE (but not to Java itself) I'm trying to build a very simple "Enterprise Application" with Hibernate as JPA provider and JSF as the actual UI framework. For this purposes I'm using the NetBeans 7 with GlassFish 3.1.
{ApplicationName}-ejb:
I've accomplished to generate entity classes from database and local sesssion beans for these entities. Beans.xml is in place.
#Stateless
public class QuestFacade extends AbstractFacade<Quest> implements QuestFacadeLocal {
// some methods here as well as EntityManager injection ...
}
{ApplicationName}-war:
I've created a simple POJO as a backing bean for the JSF page. I've annotated it with javax.inject.#Named and javax.enterprise.context.#SessionScoped. This backing bean is now accessible from the JSF page as well as being injected when the actual page is accessed. Beans.xml is in place as well.
#Named
#SessionScoped
public class QuestBean implements Serializable {
#EJB
protected QuestFacade questFacade;
// several methods delegating lookups to the questFacade ...
}
Having this deployed and page accessed, I'm, however, getting an error from GlassFish that the QuestFacade cannot be looked up by the JNDI.
The stacktrace is quite long but the initial cause could be enough:
Caused by: javax.naming.NamingException: Lookup failed for 'model.session.QuestFacade#model.session.QuestFacade' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NameNotFoundException: model.session.QuestFacade#model.session.QuestFacade not found]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:518)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:455)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at javax.naming.InitialContext.lookup(InitialContext.java:392)
at com.sun.ejb.EjbNamingReferenceManagerImpl.resolveEjbReference(EjbNamingReferenceManagerImpl.java:173)
... 74 more
Caused by: javax.naming.NameNotFoundException: model.session.QuestFacade#model.session.QuestFacade not found
at com.sun.enterprise.naming.impl.TransientContext.doLookup(TransientContext.java:248)
at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:215)
at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:77)
at com.sun.enterprise.naming.impl.LocalSerialContextProviderImpl.lookup(LocalSerialContextProviderImpl.java:119)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:505)
... 78 more
I understand that I'm persuading GlassFish to inject an EJB from a different module within the same application. Should the #Remote interface be used instead? I've also tried to explicitely specify the name for both #Stateless and #EJB annotation but without any success.
I believe that I'm doing something fundamentaly wrong, but I cannot find out what.
Any suggestion or would be greatly appreciated!
I believe that I'm doing something fundamentaly wrong, but I cannot find out what.
What you're doing wrong is that if you implement a business interface (either #Local or #Remote), then you must declare the variable where injection takes place as having the type of that interface, not of the actual bean class.
So in your case:
#Named
#SessionScoped
public class QuestBean implements Serializable {
#EJB
protected QuestFacadeLocal questFacade;
// several methods delegating lookups to the questFacade ...
}
However, a business interface is not required in EJB when you're doing local (in-jvm) communication. As you discovered, if you don't specify a business interface at all for your EJB, you can inject the bean class itself. This is because you then automatically get the so-called no-interface view.
If you want, you can optionally declare that you want BOTH the local view and the no-interface view. In that way, you can inject your bean class in places whether either the bean type itself is declared or its business interface. For this you use the #LocalBean.
#Stateless
#LocalBean
public class QuestFacade extends AbstractFacade<Quest> implements QuestFacadeLocal {
// some methods here as well as EntityManager injection ...
}
Injection can thus happen in two ways now:
#Named
#SessionScoped
public class QuestBean implements Serializable {
#EJB
protected QuestFacadeLocal questFacade; // possible because of local view
#EJB
protected QuestFacade questFacadeN; // possible because of no-interface view
// several methods delegating lookups to the questFacade ...
}
In practice I didn't found much use for having both methods available at the same time though, but maybe this adds to your understanding.
Apparently the problem was that I generated #Local session beans. Per this tutorial it is no longer necessary (?) to specify the #Local or #Remote interface. I still not completely understand the problem though.
I Hope this answer could potentialy save up some time to somebody :-)
Jarda