2

There are several ways to lookup an EJB

I can connect to my ejb server by using this lookup, but only when I use a ConsoleClient.

 "ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName)

When I try this lookup on a tomcat application server (spring mvc project), this lookup won't work. Jboss responds with a ClassNotFoundException.

I assume there has to be another jndi lookup name? Unfortunately I couldn't find any helpful information on the web.

Edit:

my controller

@RequestMapping(value = "login", method = RequestMethod.POST)
public LoginBeanRemote logIn(){

    final Hashtable jndiProperties = new Hashtable();
    jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

    Context context = null;
    try {
        context = new InitialContext(jndiProperties);
    } catch (NamingException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }


    final String appName = "foo_business";
    final String moduleName = "foo_business";
    final String distinctName = "";
    final String beanName = "LoginBean";

    // gesucht ist die klasse vom jboss , nicht die im frontend
    final String viewClassName = "foo.business.login.LoginBeanRemote";
    System.out.println("Looking EJB via JNDI ");
    System.out.println("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);

    try {
        return (LoginBeanRemote) context.lookup("ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);
    } catch (NamingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;


}

I put a jboss-ejb-client.properties file in my spring projects root folder

endpoint.name=foo_business //project name
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=127.0.0.1
remote.connection.default.port=4447
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

first part of my LoginBean (which is deployed as a JAR file in my JBOSS;

@Stateful
@Remote(LoginBeanRemote.class)
public class LoginBean implements LoginBeanRemote {

Generated EJB lookup name:

ejb:foo_business/foo_business//LoginBean!foo.business.login.LoginBeanRemote

Error:

javax.naming.NamingException: Could not load ejb proxy class recc.business.login.LoginBeanRemote [Root exception is java.lang.ClassNotFoundException: recc.business.login.LoginBeanRemote]
at org.jboss.ejb.client.naming.ejb.EjbNamingContext.createEjbProxy(EjbNamingContext.java:108)
at org.jboss.ejb.client.naming.ejb.EjbNamingContext.lookup(EjbNamingContext.java:96)
at javax.naming.InitialContext.lookup(Unknown Source)
at recc.frontend.controller.UserController.logIn(UserController.java:161)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.ClassNotFoundException: recc.business.login.LoginBeanRemote
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1676)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1521)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)
    at org.jboss.ejb.client.naming.ejb.EjbNamingContext.createEjbProxy(EjbNamingContext.java:106)
    ... 36 foo

EDIT:

I added the ejb-project.jar to my classpath. Also I added the ejb package to my spring project and I put the LoginBeanRemote there.

So far the Project does not respond with an ClassNotFound error. When I debug the created LoginBeanRemote it contails:

Proxy for remote EJB StatelessEJBLocator{appName='foo_business', moduleName='foo_business', distinctName='', beanName='LoginBean', view='interface foo.business.login.LoginBeanRemote'}

There is no exception during lookup.

    LoginBeanRemote remote = (LoginBeanRemote) context.lookup("ejb:"
                + appName + "/" + moduleName + "/" + distinctName + "/"
                + beanName + "!" + viewClassName);
        return remote;

When I try to call a function of the bean, it will cause an exception

System.out.println(remote.helloBean());

Full Message:

   Aug 30, 2013 11:26:21 AM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [appServlet] in context with path [/test] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No EJB receiver available for handling [appName:foo_business,modulename:foo_business,distinctname:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@c7c0866] with root cause
java.lang.IllegalStateException: No EJB receiver available for handling [appName:foo_business,modulename:foo_business,distinctname:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@c7c0866
    at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:584)
    at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:119)
    at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:181)
    at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:136)
    at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:121)
    at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:104)
    at com.sun.proxy.$Proxy10.helloBean(Unknown Source)
    at foo.frontend.controller.UserController.logIn(UserController.java:167)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:166)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

EDIT: I just shut down the JBoss and the same error appeared. I don't think there is any connection with the Jboss, at all.

Edit:

I just updated my code:

    InitialContext context = null;
    try {
        final Properties initialContextProperties = new Properties();

        initialContextProperties.put(Context.INITIAL_CONTEXT_FACTORY,
                "org.jboss.naming.remote.client.InitialContextFactory");

        initialContextProperties.put(Context.PROVIDER_URL,
                "remote://localhost:4447");

        initialContextProperties.put(Context.URL_PKG_PREFIXES,
                "org.jboss.ejb.client.naming");

        initialContextProperties
                .put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT",
                        "false");

        initialContextProperties.put(Context.SECURITY_PRINCIPAL, "myapplicationrealmuser");
        initialContextProperties
                .put(Context.SECURITY_CREDENTIALS, "mypass");

        EJBClientConfiguration cc = new PropertiesBasedEJBClientConfiguration(
                initialContextProperties);
        ContextSelector<EJBClientContext> selector = new ConfigBasedEJBClientContextSelector(
                cc);
        EJBClientContext.setSelector(selector);

        context = new InitialContext(initialContextProperties);
    } catch (NamingException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }


    System.out.println("Looking EJB via JNDI ");

    try {

        LoginBeanRemote remote = (LoginBeanRemote) context
                .lookup("java:global/foo_business/LoginBean!foo.business.login.LoginBeanRemote");
        System.out.println(remote.helloBean());
    } catch (NamingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;

This will return an NameNotFoundException during lookup. I've tried all kinds of lookup names but it won't work like this. Am I missing some configuration?

error:

javax.naming.NameNotFoundException: global/foo_business/LoginBean!foo.business.login.LoginBeanRemote -- service jboss.naming.context.java.jboss.exported.global.foo_business."LoginBean!foo.business.login.LoginBeanRemote"
    at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:97)
    at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:178)
    at org.jboss.naming.remote.protocol.v1.Protocol$1.handleServerMessage(Protocol.java:127)
    at org.jboss.naming.remote.protocol.v1.RemoteNamingServerV1$MessageReciever$1.run(RemoteNamingServerV1.java:73)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

JBOSS Console JNDI Informations:

enter image description here

Edit:

I deployed the EJB as a EAR file, still receiving the same exception

javax.naming.NameNotFoundException: global/foo_business_ear-ear/foo_business_ear-ejb/LoginBean!foo.business.login.LoginBeanRemote -- service jboss.naming.context.java.jboss.exported.global.foo_business_ear-ear.foo_business_ear-ejb."LoginBean!foo.business.login.LoginBeanRemote"
    at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:97)
    at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:178)
    at org.jboss.naming.remote.protocol.v1.Protocol$1.handleServerMessage(Protocol.java:127)
    at org.jboss.naming.remote.protocol.v1.RemoteNamingServerV1$MessageReciever$1.run(RemoteNamingServerV1.java:73)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

ERROR: org.jboss.naming.remote.protocol.v1.RemoteNamingStoreV1 - Channel end notification received, closing channel Channel ID ef1b671f (outbound) of Remoting connection 6af39445 to localhost/127.0.0.1:4447
Lama
  • 2,886
  • 6
  • 43
  • 59
  • 1
    Show the code and the stack trace. Are you sure that JBoss responds at all? If a name lookup fails, there is a `NamingException`. Have you included the JBoss client jar in the .war for Tomcat? – Beryllium Aug 29 '13 at 21:07
  • I'll try to upload an example as soon as possible. The EJB Project is deployed on Jboss, the Spring Project is deployed on a Tomcat. Tomcat tries to call the Jboss EJB and I think this has to be caused by the JNDI Lookup Path. – Lama Aug 29 '13 at 23:25
  • I've added some code. Also I changed my properties files (ip, port etc) and the same error accured. – Lama Aug 30 '13 at 00:40
  • What is your ConsoleClient? Does it run as a command-line stand-alone app? Same host as JBoss? Is Tomcat on the same host as JBoss? – Beryllium Aug 30 '13 at 13:09

2 Answers2

6

Tomcat as the client has to be considered as a client which does not run in the same application server container. So you have to package all relevant classes/interfaces into the .war file which is deployed on Tomcat.

Looking at the stack trace: The JBoss server does respond, it's the JBoss client who reports that a class is missing:

at org.jboss.ejb.client.naming.ejb.EjbNamingContext.createEjbProxy

The actual error (missing class) is packaged in a NamingException.

So you have to put the relevant classes into the .war file for Tomcat: It's probably your remote interface recc.business.login.LoginBeanRemote.

I always have EJB classes (implementation) and their interfaces in two separate packages, and the EJB client gets a .jar file which just contains the interfaces (and possibly exceptions). So a .jar consisting of interfaces and possibly exceptions gets packaged into the .war for the client.


Generally speaking these items have to be checked, if a stand-alone client fails to work

  • Is jboss-client.jar in the class path?
  • Are the remote interfaces in the class path?
  • Are the properties for the InitialContext complete?
  • Is the JNDI name correct? And is that JNDI name really visible from the client?

Appendix: Properties for InitialContext:

    final Properties initialContextProperties = new Properties();

    initialContextProperties.put(Context.INITIAL_CONTEXT_FACTORY,
            "org.jboss.naming.remote.client.InitialContextFactory");

    initialContextProperties.put(Context.PROVIDER_URL,
            "remote://localhost:4447");

    initialContextProperties.put(Context.URL_PKG_PREFIXES,
            "org.jboss.ejb.client.naming");

    // See .../jboss-7/standalone/configuration/application-users.properties
    initialContextProperties.put(Context.SECURITY_PRINCIPAL, "user");
    initialContextProperties.put(Context.SECURITY_CREDENTIALS, "password");

I have tested these settings, and it's confirmed by JBoss AS7 JNDI & EJB 3.1 Naming changes. There is no need neither for jndi.properties nor for jboss-ejb-client.properties.

Related: JBoss AS7 JNDI reference

Beryllium
  • 12,808
  • 10
  • 56
  • 86
  • Great answer, thank you. I forgot to add the jar file to my classpath and I put the LoginBeanRemote in a package with a different name than the ejb-project. Unfortunately I still can't run the ejb. Can you take a look on my updated question? – Lama Aug 30 '13 at 09:29
  • I am not sure if your JNDI name builder is correct (distinctName is empty, so there is a "//" somewhere, and if the "ejb:" scop is visible for a remote client. Please have a look at [JNDI Lookup on JBoss AS 6.0](http://stackoverflow.com/a/18423210/2390083). This is applicable as well to JBoss 7, so try "java:global/...", because this scope is globally visible. And double check that the JNDI name you use turns up in the JBoss admin console as well. Please add the method of the EJB you are calling. – Beryllium Aug 30 '13 at 11:45
  • The "//" works on my console client and is also mentioned in official jboss documentation. I tried "java:global/.." It's causing an error, that "java:global" is not bound to the context, do you have any Idea what's missing? BTW: I have no EAR file in my deployment folder, I just deploy the .jar file – Lama Aug 30 '13 at 12:31
  • Is `jboss-ejb-client.properties` really in the class path of the .jar for Tomcat? – Beryllium Aug 30 '13 at 13:16
  • Have a look at [JBoss AS7 JNDI ref](https://docs.jboss.org/author/display/AS71/JNDI+Reference). Instead of "Remote JNDI using ejb:" try "Remote JNDI using remote:". This explains as well the problems you have had and you are having now. – Beryllium Aug 30 '13 at 13:27
  • I have added the settings for the `InitialContext` to the answer. – Beryllium Aug 30 '13 at 13:44
  • Okay, we're almost there! Looks like I can setup a connection with the jboss but I'm still facing some issues during lookup. Can you take a look at my updated question? – Lama Aug 31 '13 at 14:52
  • Try `java:global///!`: `java:global/foo_business/foo_business/LoginBean!foo.business.login.LoginBeanRemote` (this is the case, if you have a foo_business.jar (containing the stateful session bean) in a foo_business.ear. Double check the JNDI tree in the JBoss admin console, it must turn up there (Profile - Container - Naming). – Beryllium Aug 31 '13 at 18:17
  • this is exactly my ejb lookup name. I also checked the JBoss Console and I couldn't find anything odd. I updated the question and added a screenshot of the console – Lama Aug 31 '13 at 19:39
  • Looking at the screenshot: The first name is `recc_business`: `java:global/recc_business/LoginBean!foo.business.login.LoginBeanRem‌​ote`. You still have no .ear. So this only applies, if the SSB is in that .jar (I am not sure, I always deploy as an .ear). – Beryllium Aug 31 '13 at 19:56
  • I created a new ear project, copied the ejb package into the recc_business_ear-ejb and deployed it. It still returns the javax.naming.NameNotFoundException. Is there anything else I could have missed? – Lama Aug 31 '13 at 23:58
  • I deployed the package as an ear project, The ejb:... Jndi name works fine after I did some configuration. Thank you very much! – Lama Sep 02 '13 at 11:55
  • You're welcome. Thanks for the bounty, a very noble gesture indeed. – Beryllium Sep 02 '13 at 12:38
  • Since you saved me a lots of research and maybe a heart attack you more than deserved this bounty. By the way, if you like you can take a look at my next problem ;) http://stackoverflow.com/questions/18582063/jboss-returns-exception-when-i-look-up-ejb-for-second-time – Lama Sep 02 '13 at 23:34
  • @Goot "I deployed the package as an ear project, The ejb:... Jndi name works fine after I did some configuration." Would you please explain which configuration changes you did? – Sunny Gupta Oct 03 '13 at 17:15
  • Further details on configuring Remote EJB calls that has been useful to me is http://blog.jonasbandi.net/2013/08/jboss-remote-ejb-invocation-unexpected.html and the related example https://github.com/jbandi/JavaExamples/tree/master/ejbremote – Carlo Bonamico Oct 20 '14 at 10:12
0

I saw you have mentioned @Stateful as the Annotation to your class - LoginBeanRemote.

However, you are trying to do a loopkup as for Stateless class - ejb:foo_business/foo_business//LoginBean!foo.business.login.LoginBeanRemote

Could you try putting lookup as like this - ejb:foo_business/foo_business//LoginBean!foo.business.login.LoginBeanRemote**?stateful**

This has been explained here