2
votes

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
2
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
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
I've added some code. Also I changed my properties files (ip, port etc) and the same error accured.Lama
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

2 Answers

6
votes

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

0
votes

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