Hot questions for Using Enterprise JavaBeans in jndi

Question:

I am trying to call my EJBs in a remote environment and I am using Wildfly as my container.

Apologies but this is my first time trying to call an EJBs in a remote way.

I have used the instructions below for invoking EJBs in Wildfly. https://docs.jboss.org/author/display/WFLY8/EJB+invocations+from+a+remote+client+using+JNDI

But, I am having an error calling these EJBs and I do not know what is wrong to my configuration.

See error stack trace below:

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/Project-demo] threw exception [Request processing failed; nested exception is javax.naming.NameNotFoundException: Name [ejb: /ImageService-1.0-SNAPSHOT//GrayscaleImageServiceImpl!com.project.imageservice.ImageManipulateService] is not bound in this Context. Unable to find [ejb: ].] with root cause
javax.naming.NameNotFoundException: Name [ejb: /ImageService-1.0-SNAPSHOT//GrayscaleImageServiceImpl!com.project.imageservice.ImageManipulateService] is not bound in this Context. Unable to find [ejb: ].
    at org.apache.naming.NamingContext.lookup(NamingContext.java:820)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:168)
    at org.apache.naming.SelectorContext.lookup(SelectorContext.java:158)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at com.sketchy.remote.context.RemoteContext.lookupRemoteGrayscaleService(RemoteContext.java:30)
    at com.sketchy.controllers.ServiceController.grayscaleService(ServiceController.java:78)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)

My interface in both remote server and client side:

public interface ImageManipulateService{
    public UploadedImage manipulate(UploadedImage img) throws IOException, Exception;
}

My EJB in the remote server (Wildfly):

@Service
@Stateless
@Remote(ImageManipulateService.class)
public class GrayscaleImageServiceImpl implements ImageManipulateService{

    @Override
    public Object manipulate(Object img) throws IOException, Exception {
        ....
    }

}

Client side:

jboss-ejb-client.properties

remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false

remote.connections=default

remote.connection.default.host = localhost
remote.connection.default.port = 9090
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

I have been running my client in tomcat server (:8080) and I'm trying to invoke the EJBs on Wildfly via localhost:9090. (is it correct?)

I also have the jboss-client.jar included in my Maven dependencies. I used version 4.0.2. (jboss-client-4.0.2.jar)

I made a java class that would call the lookup of services in order to conveniently call them.

public class RemoteContext {

    public static ImageManipulateService lookupRemoteGrayscaleService() throws NamingException {
        Hashtable jndiProperties = new Hashtable();
        jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
        Context context = new InitialContext(jndiProperties);

        String appName = "";
        String moduleName = "ImageService-1.0-SNAPSHOT";
        String distinctName = "";
        String beanName = "GrayscaleImageServiceImpl";
        String viewClassName = "com.project.imageservice.ImageManipulateService";

        return (ImageManipulateService) context.lookup("ejb: " + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);
    }

    public static ImageManipulateService lookupRemoteTimestampService() throws NamingException {
        Hashtable jndiProperties = new Hashtable();
        jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
        Context context = new InitialContext(jndiProperties);

        String appName = "";
        String moduleName = "ImageService-1.0-SNAPSHOT";
        String distinctName = "";
        String beanName = "TimestampImageServiceImpl";
        String viewClassName = "com.project.imageservice.ImageManipulateService";

        return (ImageManipulateService) context.lookup("ejb: " + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName);
    }


}

Answer:

Your main problem here is that you're using the wrong jboss-client.jar. The one you have selected is for JBoss 4.0.x and will not work at all with WildFly.

If you're building with Maven then you would include the following dependency in your client application (being the war project):

    <dependency>
        <groupId>org.wildfly</groupId>
        <artifactId>wildfly-ejb-client-bom</artifactId>
        <version>10.1.0.Final</version>
        <type>pom</type>
    </dependency>

But since you don't appear to be using Maven, the alternative is to add the jboss-client.jar that you will find in the bin/client/ directory of your WildFly installation. It's an "uber-jar" containing everything that is defined by the maven dependency shown above.

Once you have this sorted out you might need some help with the JNDI name. We will be able to fix that with the deployment output from your server.log, which records all of your EJB application's JNDI names.

Question:

I am learning how to deploy EJBs on JBoss by following these two tutorials :

  1. TutorialsPoint
  2. JBoss docs

So basically I created an EJB project called "EjbComponent" in Netbeans with these two classes :

LibrarySessionBeanRemote.java

package com.test.stateless;

import java.util.List;

public interface LibrarySessionBeanRemote {

void addBook(String bookName);

List getBooks();

}

LibrarySessionBean.java

package com.test.stateless;

import java.util.List;
import java.util.ArrayList;
import javax.ejb.Stateless;
import javax.ejb.Remote;

@Stateless
@Remote(LibrarySessionBeanRemote.class)
public class LibrarySessionBean implements LibrarySessionBeanRemote {

List<String> bookShelf;

public LibrarySessionBean(){
    bookShelf = new ArrayList<String>();
}

@Override
public void addBook(String bookName){
    bookShelf.add(bookName);
}

@Override
public List<String> getBooks(){
    return bookShelf;
}
}

I then deploy them to JBoss Server successfully

21:16:13,566 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-7) JBAS015876: Starting deployment of "EjbComponent.jar" (runtime-name: "EjbComponent.jar")
21:16:13,582 INFO  [org.jboss.weld.deployer] (MSC service thread 1-5) JBAS016002: Processing weld deployment EjbComponent.jar
21:16:13,583 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-5) JNDI bindings for session bean named LibrarySessionBean in deployment unit deployment "EjbComponent.jar" are as follows:

java:global/EjbComponent/LibrarySessionBean!com.test.stateless.LibrarySessionBeanRemote
java:app/EjbComponent/LibrarySessionBean!com.test.stateless.LibrarySessionBeanRemote
java:module/LibrarySessionBean!com.test.stateless.LibrarySessionBeanRemote
java:jboss/exported/EjbComponent/LibrarySessionBean!com.test.stateless.LibrarySessionBeanRemote
java:global/EjbComponent/LibrarySessionBean
java:app/EjbComponent/LibrarySessionBean
java:module/LibrarySessionBean

21:16:13,589 INFO  [org.jboss.weld.deployer] (MSC service thread 1-5) JBAS016005: Starting Services for CDI deployment: EjbComponent.jar
21:16:13,593 INFO  [org.jboss.weld.deployer] (MSC service thread 1-4) JBAS016008: Starting weld service for deployment EjbComponent.jar
21:16:13,735 INFO  [org.jboss.as.server] (DeploymentScanner-threads - 1) JBAS015865: Replaced deployment "EjbComponent.jar" with deployment "EjbComponent.jar"

Now to use this EJB, I create a standalone java client by creating another project in Netbeans called "Test" with one class:

EJBTester.java

package com.test.client;

import com.test.stateless.LibrarySessionBeanRemote;
import com.test.stateless.LibrarySessionBean;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Hashtable;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.security.Security;
import org.jboss.sasl.JBossSaslProvider;

public class EJBTester {

BufferedReader brConsoleReader = null;

{
    brConsoleReader = new BufferedReader(new InputStreamReader(System.in));
}

public static void main(String[] args) {
    EJBTester ejbTester = new EJBTester();
    ejbTester.testStatelessEjb();
}

private void showGUI(){
    System.out.println("*************************");
    System.out.println("Welcome to the Book Store");
    System.out.println("*************************");
    System.out.print("Options \n1. Add Book\n2. Exit \nEnter Choice:");
}

private void testStatelessEjb(){
    try{
        Hashtable jndiProperties = new Hashtable();
        jndiProperties.put("jboss.naming.client.ejb.context", true);
        jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
        final Context context = new InitialContext(jndiProperties);
        final String appName = "";
        final String moduleName = "EjbComponent";
        final String distinctName = "";
        final String beanName = LibrarySessionBean.class.getSimpleName();
        final String viewClassName = LibrarySessionBeanRemote.class.getName();
        final String lookupPath = "ejb:" + appName + "/" + moduleName + "/" + distinctName + "/" + beanName + "!" + viewClassName;
        LibrarySessionBeanRemote libraryBean = (LibrarySessionBeanRemote)context.lookup(lookupPath);
        System.out.println(lookupPath);
        int choice = 0;
        while (choice != 2) {
            String bookName;
            showGUI();
            String strChoice = brConsoleReader.readLine();
            choice = Integer.parseInt(strChoice);
            if (choice == 1) {
               System.out.print("Enter book name: ");
               bookName = brConsoleReader.readLine();
               libraryBean.addBook(bookName);          
            } else if (choice == 2){
               break;
            }
        }
        List<String> booksList = libraryBean.getBooks();
        System.out.println("Book(s) entered so far: " + booksList.size());
        for(String book: booksList){
            System.out.println(book);
        }
        System.out.println("**********Using second lookup to get library statless object");
        LibrarySessionBeanRemote libraryBean1 = (LibrarySessionBeanRemote)context.lookup(lookupPath);
        booksList = libraryBean1.getBooks();
        System.out.println("Book(s) entered so far: " + booksList.size());
        for(String book: booksList){
            System.out.println(book);
        }
        context.close();
    }catch(Exception e){
        e.printStackTrace();
    }finally{
        try{
            if(brConsoleReader != null)
                brConsoleReader.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}    
}

jboss-ejb-client.properties

endpoint.name=client-endpoint
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

remote.connection.default.username=app1
remote.connection.default.password=pass123

When I try to run this application, I get the following error :

run:
Jul 03, 2015 9:28:42 PM org.jboss.ejb.client.EJBClient <clinit>
INFO: JBoss EJB Client version 1.0.30.Final-redhat-1
ejb:/EjbComponent//LibrarySessionBean!com.test.stateless.LibrarySessionBeanRemote
*************************
Welcome to the Book Store
*************************
Options 
1. Add Book
2. Exit 
Enter Choice:1
Enter book name: abcd

java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:, moduleName:EjbComponent, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@7aec35a
     at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:747)
     at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:116)
     at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)
     at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255)
     at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200)
     at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183)
     at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146)
     at com.sun.proxy.$Proxy0.addBook(Unknown Source)
     at com.test.client.EJBTester.testStatelessEjb(EJBTester.java:58)
     at com.test.client.EJBTester.main(EJBTester.java:25)
 BUILD SUCCESSFUL (total time: 7 seconds)

Can anyone tell me where I am making the mistake? I've read the other threads on stackoverflow listing the same problem and tried all their solutions like including the following in my code

jndiProperties.put("jboss.naming.client.ejb.context", true);
context.close();

but still get the error.

My Configuration details:

  • Netbeans IDE 8.0.2
  • JBoss EAP 6.4
  • Java 1.8.0_45
  • Ubuntu 14.04 64 bit

Answer:

I was able to reproduce the error with a missing jboss-ejb-client.properties file. Ensure that it is placed correctly in your project.

To resolve in my case I placed it in:

java/src

Hope that helps

Question:

I would like to know how to look up a EJB located into a WildFly server from a remote client using JNDI.

Here is what I use to initialize the context

jndiProps.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
jndiProps.put(Context.PROVIDER_URL, "http-remoting://192.168.0.15:8080");
jndiProps.put("jboss.naming.client.ejb.context", true);
Context ctx = new InitialContext(jndiProps);

And this is the console output when I deploy the server:

21:08:29,352 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-10) JNDI bindings for session bean named DataBaseServiceImpl in deployment unit deployment "AnalyseExcelServeur.war" are as follows:

java:global/AnalyseExcelServeur/DataBaseServiceImpl!serveur.database.DataBaseService
java:app/AnalyseExcelServeur/DataBaseServiceImpl!serveur.database.DataBaseService
java:module/DataBaseServiceImpl!serveur.database.DataBaseService
java:jboss/exported/AnalyseExcelServeur/DataBaseServiceImpl!serveur.database.DataBaseService
java:global/AnalyseExcelServeur/DataBaseServiceImpl
java:app/AnalyseExcelServeur/DataBaseServiceImpl
java:module/DataBaseServiceImpl

I have try a lot of combination but every time I get a javax.naming.NameNotFoundException:

javax.naming.NameNotFoundException: exported/AnalyseExcelServeur/DataBaseServiceImpl!serveur.database.DataBaseService -- service jboss.naming.context.java.jboss.exported.exported.AnalyseExcelServeur."DataBaseServiceImpl!serveur.database.DataBaseService"
at org.jboss.as.naming.ServiceBasedNamingStore.lookup(ServiceBasedNamingStore.java:104)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:202)
at org.jboss.as.naming.NamingContext.lookup(NamingContext.java:179)
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(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)

I have not defined an app name nor a module name.

  • The project name of the server is : AnalyseExcelServeur
  • The name of the EJB is DataBaseServiceImpl
  • The EJB implements DataBaseService which is located in the package serveur.database

Here is how I declare the EJB:

@Stateless
@Remote(DataBaseService.class)
public class DataBaseServiceImpl extends SessionDB implements DataBaseService

On the client side the implementation of the DataBaseService interface is located in the package compte.remote.ejb

I don't know if I have to use ejb:/appname/modulename/bean/location or just /appname/modulename/bean/location or anything else...

Maybe I have to put a file into the .war to declare the EJB...


Answer:

Maybe you should take a look at the documentation :

https://docs.jboss.org/author/display/WFLY8/EJB+invocations+from+a+remote+client+using+JNDI

Question:

Just a shot in the dark, but do I need a local interface to call a remote stateless EJB?

when I try call the bean remotely through Netbeans:

Netbeans doesn't allow a remote call, or any call, on this bean. Why not?

Trying to do it manually, as below:

What is the jndi global remote name for the Remote EJB which is deployed on glassfish?

INFO:   visiting unvisited references
INFO:   visiting unvisited references
INFO:   EJB5181:Portable JNDI names for EJB MyRemoteSessionClass: [java:global/RemoteSalutation-ejb/MyRemoteSessionClass!net.bounceme.dur.glassfish.MyRemoteSession, java:global/RemoteSalutation-ejb/MyRemoteSessionClass]
INFO:   RemoteSalutation-ejb was successfully deployed in 941 milliseconds.

If possible, I would rather specify the class in the properties file rather than hard-coded. In any event, different variations result in a lookup failure. Here's the stack-trace:

run-deploy:
Copying 1 file to /home/thufir/NetBeansProjects/RemoteLookup/dist
Copying 2 files to /home/thufir/NetBeansProjects/RemoteLookup/dist/RemoteLookupClient
Warning: /home/thufir/NetBeansProjects/RemoteLookup/dist/gfdeploy/RemoteLookup does not exist.
Sep 13, 2014 1:35:41 AM net.bounceme.dur.remote.RemoteLookup run
INFO: java.naming.factory.initial   com.sun.enterprise.naming.impl.SerialInitContextFactory
Sep 13, 2014 1:35:41 AM net.bounceme.dur.remote.RemoteLookup run
INFO: java.naming.factory.url.pkgs  com.sun.enterprise.naming
Sep 13, 2014 1:35:41 AM net.bounceme.dur.remote.RemoteLookup run
INFO: java.naming.factory.state com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl
Sep 13, 2014 1:35:46 AM net.bounceme.dur.remote.RemoteLookup main
SEVERE: Lookup failed for ' java:comp/env//RemoteSalutation-ejb/MyRemoteSessionClass!net/bounceme/dur/glassfish/MyRemoteSession' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, remote=net.bounceme.ix.Foo, org.omg.CORBA.ORBInitialHost=localhost, java.naming.security.principal=user, org.omg.CORBA.ORBInitialPort=3700, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.provider.url=server.local:1199, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.security.credentials=password}
javax.naming.NamingException: Lookup failed for ' java:comp/env//RemoteSalutation-ejb/MyRemoteSessionClass!net/bounceme/dur/glassfish/MyRemoteSession' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, remote=net.bounceme.ix.Foo, org.omg.CORBA.ORBInitialHost=localhost, java.naming.security.principal=user, org.omg.CORBA.ORBInitialPort=3700, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.provider.url=server.local:1199, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.security.credentials=password} [Root exception is javax.naming.NameNotFoundException:  java:comp]
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:491)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:438)
    at javax.naming.InitialContext.lookup(InitialContext.java:411)
    at net.bounceme.dur.remote.RemoteLookup.run(RemoteLookup.java:34)
    at net.bounceme.dur.remote.RemoteLookup.main(RemoteLookup.java:18)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.glassfish.appclient.client.acc.AppClientContainer.launch(AppClientContainer.java:446)
    at org.glassfish.appclient.client.AppClientFacade.main(AppClientFacade.java:166)
Caused by: javax.naming.NameNotFoundException:  java:comp
    at com.sun.enterprise.naming.impl.TransientContext.resolveContext(TransientContext.java:299)
    at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:207)
    at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:66)
    at com.sun.enterprise.naming.impl.RemoteSerialContextProviderImpl.lookup(RemoteSerialContextProviderImpl.java:109)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie.dispatchToMethod(ReflectiveTie.java:143)
    at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie._invoke(ReflectiveTie.java:173)
    at com.sun.corba.ee.impl.protocol.ServerRequestDispatcherImpl.dispatchToServant(ServerRequestDispatcherImpl.java:528)
    at com.sun.corba.ee.impl.protocol.ServerRequestDispatcherImpl.dispatch(ServerRequestDispatcherImpl.java:199)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleRequestRequest(MessageMediatorImpl.java:1549)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleRequest(MessageMediatorImpl.java:1425)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleInput(MessageMediatorImpl.java:930)
    at com.sun.corba.ee.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(RequestMessage_1_2.java:213)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleRequest(MessageMediatorImpl.java:694)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.dispatch(MessageMediatorImpl.java:496)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.doWork(MessageMediatorImpl.java:2222)
    at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
    at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)

run:
BUILD SUCCESSFUL (total time: 17 seconds)

client code:

package net.bounceme.dur.remote;

import java.util.Enumeration;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class RemoteLookup {

    private static final Logger log = Logger.getLogger(RemoteLookup.class.getName());
    private final MyProps p = new MyProps();

    public static void main(String... args) {
        try {
            new RemoteLookup().run();
        } catch (NamingException ex) {
            Logger.getLogger(RemoteLookup.class.getName()).log(Level.SEVERE, ex.getExplanation(), ex);
        }
    }

    private void run() throws NamingException {
        Properties jndi = p.getJNDI();
        Enumeration e = jndi.propertyNames();
        while (e.hasMoreElements()) {
            String key = (String) e.nextElement();
            String val = jndi.getProperty(key);
            log.info(key + "\t" + val);
        }
        Context ic = new InitialContext();
        //    Object o = ic.lookup(" java:comp/env/RemoteSalutation-ejb/MyRemoteSessionClass");
        Object o = ic.lookup(" java:comp/env//RemoteSalutation-ejb/MyRemoteSessionClass!net/bounceme/dur/glassfish/MyRemoteSession");
    }
}

the remote EJB:

package net.bounceme.dur.glassfish;

import javax.ejb.Stateless;

//@LocalBean
@Stateless(mappedName = "salutationBean")
public class MyRemoteSessionClass implements MyRemoteSession {

    @Override
    public String SayHello() {
        return "hello from glassfish..";
    }

    @Override
    public String SayBye() {
        return "goodbye..";
    }
}

note that the interface is remote, ie: it's literally a Java class library. Correct? This makes the EJB remote.

referencing:

https://netbeans.org/kb/docs/javaee/entappclient.html

although I changed the names a bit..otherwise should be exactly as the tutorial.


Answer:

Try Object o = ic.lookup("salutationBean"); Note that mappedName specifies the name to use in JNDI for a remote access.

Question:

I have two stateless EJBs that implement an interface. To load an implementation I'm using InitialContext but it always fails with NamingException.

The interface

package app.ejb.login;

public interface UserValidation {

    public static final int DBValidation = 1;
    public static final int LDAPValidation = 2;

    public int validateUser(String userid, String password) throws InvalidAccessException;

}

The first implementation

package app.ejb.login;

@Stateless
public class LDAPUserValidationImpl implements UserValidation {

    @Override
    public int validateUser(String userid, String password) throws InvalidAccessException {
            ........................
    }

}

and the second implementation

package app.ejb.login;

@Stateless
public class DBUserValidationImpl implements UserValidation {

    @Override
    public int validateUser(String userid, String password) throws InvalidAccessException {
            ..................
    }

}

This is the code that calls the implementation depending on a configuration:

package app.ejb.login;

@Stateless
public class LoginBean {
.....
.....
UserValidation userValidation = null;
InitialContext ic = null;
try {
    ic = new InitialContext();
    if (flag == 1)
        userValidation = (UserValidation) 
            ic.lookup("java:comp/env/app/ejb/login/DBUserValidationImpl");
    else 
        userValidation = (UserValidation) 
            ic.lookup("java:comp/env/app/ejb/login/LDAPUserValidationImpl");
    }
    catch (NamingException e) {
            System.out.println("Error in InitialContext: " + e.getMessage());

This code prints:

Error in InitialContext: env/app/ejb/login/DBUserValidationImpl -- service jboss.naming.context.java.comp."app-2.0"."app-ejb-2.0".LoginBean.env.app.ejb.login.DBUserValidationImpl

What is the correct JNDI to load the bean? Isn't the full package path?

I also tried with java:module/app/ejb/login/DBUserValidationImpl but got the same error.


Answer:

This worked:

java:module/DBUserValidationImpl

Question:

Calling my EJB from class Main:

MyService myService = (MyService) ctx.lookup(MyService.class.getName());

Gives error:

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:350)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at com.ejb.calculator.Main.main(Main.java:26)

How can I call my EJB?

Tried two different JNDI calls:

JNDI_NAME = "java:global/ejb/MyService";
MyService myService = (MyService) ctx.lookup(JNDI_NAME);

and

MyService myService = (MyService) ctx.lookup(MyService.class.getName());

Code:

Source link

https://bitbucket.org/powder366/ejb/src/master/ 

Glassfish commands:

asadmin start-domain --verbose
asadmin stop-domain --verbose 
http://localhost:8080/
http://localhost:4848/common/index.jsf
mvn package
asadmin deploy ejb-1.0-SNAPSHOT.jar

Screenshots:

Note:

My test cases works with the embedded container, but I can't call my external running container.

Used versions are Java8, EJB3.0, Glassfish5.0.1, Java EE8.0.1

Update1: Added log during deplyoment container-deploy-log.txt. See git remote.

Update2: Pushed the working changes to git remote.

Update3: Pushed MDB example to git remote.


Answer:

First of all, if you want to access your EJB from an external client, you need to declare a remote view.

As your EJB only has the @Local annotation, it only offers a local view. You should add the @Remote annotation.

@Local
@Remote
@Stateless
public class MyService implements IMyService {
    public String getMessage() {
        return "Hello!";
    }
}

The global JNDI name is formed by:

java:global/[EAR module]/[EJB module]/[EJB name]

in your case, as there is no EAR, would be:

java:global/ejb-1.0-SNAPSHOT/MyService

This test should work:

Context ctx = new InitialContext();
IMyService myService = (IMyService) ctx.lookup("java:global/ejb-1.0-SNAPSHOT/MyService");
Assert.assertEquals(myService.getMessage(), "Hello!");

UPDATE

You also need to add the glassfish client libraries to the classpath to run the Main class.

I originally tested it with a JUnit test, it worked for me because the project already declared a test dependency on glassfish-embeded-all that includes the glassfish client. But IntelliJ doesn't add test libraries when running a Main class.

You could either change the scope of glassfish-embeded-all to runtime or add a new dependency:

<dependency>
    <groupId>org.glassfish.main.appclient</groupId>
    <artifactId>gf-client</artifactId>
    <version>5.1.0</version>
    <scope>runtime</scope>
</dependency>

Question:

I just learning ejb remote on wildfly 12 server. I have successfully connected to ejb in my the same computer with jboss-ejb-client.properties when accessing the same JVM with localhost (Working example) :

remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port=8080

when I try to access the same ejb using 127.0.0.1 than localhost , it waits so long and nothing happens without displaying any erroe. Here is the jboss-ejb-client.properties when accessing server on the same JVM with 127.0.0.1 (Failure example) :

 remote.connections=default
 remote.connection.default.host=127.0.0.1
 remote.connection.default.port=8080

I also deploy the same ejb service to another computer with ip 192.168.1.101 and changed host and set password credientials accordingly and try to access but the same endless wait happen again. Here is the jboss-ejb-client.properties when accessing to another server at 192.168.1.101 (Failure example):

remote.connections=default
remote.connection.default.host=192.168.1.101
remote.connection.default.port=8080
remote.connection.default.username=username
remote.connection.default.password=**password
remote.connection.default.connect.timeout=3000

build.gradle is :

// https://mvnrepository.com/artifact/org.jboss.spec.javax.transaction/jboss-transaction-api_1.2_spec
api  group: 'org.jboss.spec.javax.transaction', name: 'jboss-transaction-api_1.2_spec', version: '1.1.1.Final'
       // https://mvnrepository.com/artifact/org.jboss.spec.javax.ejb/jboss-ejb-api_3.2_spec
    api group: 'org.jboss.spec.javax.ejb', name: 'jboss-ejb-api_3.2_spec', version: '1.0.1.Final'
        // https://mvnrepository.com/artifact/org.jboss/jboss-ejb-client
    api group: 'org.jboss', name: 'jboss-ejb-client', version: '4.0.10.Final'
        // https://mvnrepository.com/artifact/org.jboss.xnio/xnio-api
    api group: 'org.jboss.xnio', name: 'xnio-api', version: '3.6.3.Final'
        // https://mvnrepository.com/artifact/org.jboss.xnio/xnio-nio
    api group: 'org.jboss.xnio', name: 'xnio-nio', version: '3.6.3.Final'
        // https://mvnrepository.com/artifact/org.jboss.remoting/jboss-remoting
    api group: 'org.jboss.remoting', name: 'jboss-remoting', version: '5.0.7.Final'
        // https://mvnrepository.com/artifact/org.jboss.sasl/jboss-sasl
    api group: 'org.jboss.sasl', name: 'jboss-sasl', version: '1.0.5.Final'
        // https://mvnrepository.com/artifact/org.jboss.marshalling/jboss-marshalling-river
    api group: 'org.jboss.marshalling', name: 'jboss-marshalling-river', version: '2.0.5.Final'

And context lookup procedure :

 Properties props = new Properties();
    props.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

InitialContext ic = new InitialContext(props);
Calculator calc = (Calculator) ic.lookup("ejb:/ejbtest-service-1.0/CalculatorService!com.testejb.model.Calculator");

Is there some thing missing ?


Answer:

I would recommend following this example project

https://github.com/wildfly/quickstart/tree/12.x/ejb-remote

The default mode us using local auth (which works on file permissions) where as the HTTP example uses true auth

This example shows how to use auth as well

https://github.com/wildfly/quickstart/blob/12.x/ejb-security/src/main/resources/wildfly-config.xml

Where as the first example (https://github.com/wildfly/quickstart/blob/12.x/ejb-remote/client/src/main/resources/META-INF/wildfly-config.xml) used

 <property key="wildfly.sasl.local-user.quiet-auth" value="true" />

Question:

Recommended way of invoking a EJB local interface method is to perform a lookup:

<code>
Context ic = new IntialContext(); 
ic.lookup(objectJndiName);
</code>

However, I browse the complete JNDI tree at the start of application and at the end I am able to create a map of all objects with:

<code> 
   Map <String,Object> 
</code>

with key ObjectName and object of required Interface Implementation. I search the object with key and invoke the required method on interface like this:

method.invoke(bean, args);

Is this method ok? or should I perform lookup for the required ejb everytime?


Answer:

JNDI lookups is not the recommended way for instantiating references of Local Interfaces of Stateless beans, as from EE5 and above. Simply injecting the bean with @EJB annotation or CDI's @Inject will do the job fine.

Question:

i have a problem with a JNDI configuration end EJB 3.1 And Oracle 12.1 DB. my code:

    private static NewSessionBeanRemote lookupRemoteSessionBean() throws NamingException {

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

    final Context context = new InitialContext(jndiProperties);
    final String appName = "";
    final String moduleName = "EjbComponent";
    final String distinctName = "";
    final String beanName = NewSessionBean.class.getSimpleName();
    final String viewClassName = NewSessionBeanRemote.class.getName();
    System.out.println("ejb:" + appName + "" + moduleName + "" + distinctName + "/" + beanName + "!" + viewClassName);
    return (NewSessionBeanRemote) context.lookup("ejb:" + appName + "" + moduleName + "" + distinctName + "/" + beanName + "!" + viewClassName);
}

ERROR when i try to lookup jndi:

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:662)
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:313)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:350)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at com.studio.java.client.EjbTester.lookupRemoteSessionBean(EjbTester.java:73)
at com.studio.java.client.EjbTester.invokeStatelessBean(EjbTester.java:51)
at com.studio.java.client.EjbTester.main(EjbTester.java:41)

Answer:

Besides your Context.URL_PKG_PREFIXES you also need to set the following properties:

jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
jndiProperties.put(Context.PROVIDER_URL, "http-remoting://127.0.0.1:8080");

Also, if you have any type of authentication, you have to set it through Context.SECURITY_PRINCIPAL and Context.SECURITY_CREDENTIALS:

jndiProperties.put(Context.SECURITY_PRINCIPAL, "username");
jndiProperties.put(Context.SECURITY_CREDENTIALS, "password");

Question:

When doing a remote EJB lookup (from JBoss 4.3) in J2SE, I'm encountering the following exception:

Exception in thread "main" java.lang.NoClassDefFoundError: LLog;
    at java.lang.Class.getDeclaredFields0(Native Method)
    at java.lang.Class.privateGetDeclaredFields(Class.java:2499)
    at java.lang.Class.getDeclaredField(Class.java:1951)
    at java.io.ObjectStreamClass.getDeclaredSUID(ObjectStreamClass.java:1659)
    at java.io.ObjectStreamClass.access$700(ObjectStreamClass.java:72)
    at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:480)
    at java.io.ObjectStreamClass$2.run(ObjectStreamClass.java:468)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:468)
    at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:365)
    at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:602)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1622)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1517)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1771)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
    at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1706)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1344)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
    at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1990)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1915)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1798)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1350)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
    at java.rmi.MarshalledObject.get(MarshalledObject.java:159)
    at org.jnp.interfaces.MarshalledValuePair.get(MarshalledValuePair.java:72)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:737)
    at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:654)
    at javax.naming.InitialContext.lookup(InitialContext.java:411)
    at com.example.ShoppingBasketServiceClient.main(ShoppingBasketServiceClient.java:44)
Caused by: java.lang.ClassNotFoundException: Log
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 32 more

Here is teh codez, line 44 is the one doing the lookup:

package com.example;

import java.util.Properties;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class ShoppingBasketServiceClient {

    public static void main(String[] args) throws NamingException {

        Properties props = new Properties();            
        props.setProperty("java.naming.factory.initial",  "org.jnp.interfaces.NamingContextFactory");
        props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
        props.setProperty("java.naming.provider.url", "jnp://localhost:1099");
        String Lookup = "ejb/ShoppingBasketService/remote";

        try {
            InitialContext ic = new InitialContext(props);
            // ShoppingBasketServiceRemote shoppingBasketService = (ShoppingBasketServiceRemote) ic.lookup(Lookup);
            Object shoppingBasketService = (Object) ic.lookup(Lookup);

        } catch (NamingException e) {
            System.out.println("Exception:" + e);
        }
    }
}

I'm confused as to why it's looking for a Log class (and why the exception is not package-qualified)?

ShoppingBasketServiceRemote is just an interface that imports the javax.ejb.Remote annotation and extends another interface - neither make any reference to a Log class? Additionally, you'll see my example only casts the result to Object (but the result is the same if I swap out for the service interface)?


Answer:

ShoppingBasketServiceRemote is just an interface that imports the javax.ejb.Remote annotation and extends another interface - neither make any reference to a Log class?

  • Examine all the objects referenced in the interface & their transitive dependencies. Something will point to the "Log" class.
  • Also check the remote server for errors, maybe the error is on the remote server
  • Try doing a simple Class.forName("ShoppingBasketServiceRemote") - you might see it failing with the same error.

Additionally, you'll see my example only casts the result to Object (but the result is the same if I swap out for the service interface)?

Casting the object happens after your jvm is able to load the object returned by ic.lookup(Lookup) - so the error will happen whether you cast or not.

Question:

I'm trying to run ejb Helloworld program and my JNDI[1] but I’m getting bellow error[2] I’m running Jboss AS 7 final and AS output list[3]. anyone guide on this to me what my mistake?

[1]

Properties prop = new Properties();
prop.setProperty("java.naming.factory.url.pkgs","org.jboss.ejb.client.naming");
return new InitialContext(prop);

[2]

javax.naming.NameNotFoundException: Name [org.wso2.carbon.custom.ejb-1.0-SNAPSHOT/HelloBean] is not bound in this Context. Unable to find [ejb:].
at org.apache.naming.NamingContext.lookup(NamingContext.java:819)
at org.apache.naming.NamingContext.lookup(NamingContext.java:167)
at org.wso2.carbon.context.internal.CarbonContextDataHolder$CarbonInitialJNDIContext.lookup(CarbonContextDataHolder.java:705)
at javax.naming.InitialContext.lookup(InitialContext.java:411)
at org.wso2.carbon.connector.EJBConnector.callEJB(EJBConnector.java:69)
at org.wso2.carbon.connector.EJBConnector.connect(EJBConnector.java:40)
at org.wso2.carbon.connector.core.AbstractConnector.mediate(AbstractConnector.java:32)
at org.apache.synapse.mediators.ext.ClassMediator.mediate(ClassMediator.java:78)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:81)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:48)
at org.apache.synapse.mediators.template.TemplateMediator.mediate(TemplateMediator.java:97)
at org.apache.synapse.mediators.template.InvokeMediator.mediate(InvokeMediator.java:129)
at org.apache.synapse.mediators.template.InvokeMediator.mediate(InvokeMediator.java:78)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:81)
at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:48)
at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:149)
at org.apache.synapse.core.axis2.ProxyServiceMessageReceiver.receive(ProxyServiceMessageReceiver.java:185)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
at org.apache.synapse.transport.passthru.ServerWorker.processNonEntityEnclosingRESTHandler(ServerWorker.java:317)
at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:149)
at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)

[3]

java:global/org.wso2.carbon.custom.ejb-1.0-SNAPSHOT/HelloBean!org.wso2.carbon.custom.ejb.HelloIF
java:app/org.wso2.carbon.custom.ejb-1.0-SNAPSHOT/HelloBean!org.wso2.carbon.custom.ejb.HelloIF
java:module/HelloBean!org.wso2.carbon.custom.ejb.HelloIF
java:jboss/exported/org.wso2.carbon.custom.ejb-1.0-SNAPSHOT/HelloBean!org.wso2.carbon.custom.ejb.HelloIF
java:global/org.wso2.carbon.custom.ejb-1.0-SNAPSHOT/HelloBean
java:app/org.wso2.carbon.custom.ejb-1.0-SNAPSHOT/HelloBean
java:module/HelloBean

Answer:

i solved this issue after long search. this because of classloder issue in glassfish. so added a method to solve the classloding issue then its work fine.

 Thread currentThread = Thread.currentThread();
    ClassLoader oldClassLoader = currentThread.getContextClassLoader();
    try {
        //switching the classloader to prevent class loading glassfish classloading issues
        currentThread.setContextClassLoader(getClass().getClassLoader());
        //method to run
        callEJBStateful(messageContext);
    } catch (Exception e) {
        handleException("Error calling EJB Service from EJBConnector", e, messageContext);
    } finally {
        if (oldClassLoader != null) {
            //resetting the classloader
            currentThread.setContextClassLoader(oldClassLoader);
        }
    }

Question:

I have created a simple EJB 3.0 application, deployed in JBOSS 7.1.1 final.

Here is the code:

EJB 1:

Interface

package com.example.server.local.bean;

import javax.ejb.Local;

@Local
public interface UtilLocalBeanLocal {

    public String addString();
}

Class implementing this interface:

package com.example.server.local.bean;

import javax.ejb.Local;
import javax.ejb.Stateless;

@Stateless
@Local(value=UtilLocalBeanLocal.class)
public class UtilLocalBean implements UtilLocalBeanLocal {

    public UtilLocalBean() {

    }

   @Override
   public String addString() {

        return "Added from Local bean"; 
    }
}

So, this EJB i am creating to be "locally" used by another EJB.

EJB 2:

Interface

package com.example.bean.session;

import javax.ejb.Remote;

@Remote
public interface FirstBeanRemote {

    public String callMe();
}

Class implementing this interface.

package com.example.bean.session;

import javax.ejb.EJB;
import javax.ejb.Remote;
import javax.ejb.Stateless;

import com.example.server.local.bean.UtilLocalBeanLocal;

@Stateless
@Remote(value=FirstBeanRemote.class)
public class FirstBean implements FirstBeanRemote {

    @EJB
    private UtilLocalBeanLocal utilLocalBeanLocal;

    public FirstBean() {

    }

    @Override
    public String callMe() {

        return "Hi there!" + utilLocalBeanLocal.addString();
    }
}
When i start the JBOSS, the JNDI bindings i get are like this:
00:34:15,928 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-5) JNDI bindings for session bean named FirstBean in deployment unit subdeployment "EJB30TestProj.jar" of deployment "EJB30TestProjEAR.ear" are as follows:

java:global/EJB30TestProjEAR/EJB30TestProj/FirstBean!com.example.bean.session.FirstBeanRemote
java:app/EJB30TestProj/FirstBean!com.example.bean.session.FirstBeanRemote
java:module/FirstBean!com.example.bean.session.FirstBeanRemote
java:jboss/exported/EJB30TestProjEAR/EJB30TestProj/FirstBean!com.example.bean.session.FirstBeanRemote
java:global/EJB30TestProjEAR/EJB30TestProj/FirstBean
java:app/EJB30TestProj/FirstBean
java:module/FirstBean
However in the remote client when I try to use any of these above JNDI binding values, it is not working, and what actually works (after lot of google) is:
ejb:EJB30TestProjEAR/EJB30TestProj//FirstBean!com.example.bean.session.FirstBeanRemote

It is difficult to understand how this JNDI bindings work. JBOSS outputs a different JNDI and in reality what works is different one.

Can anyone please demystify this? (how to decide which JNDI bindings will work in different scenarios and any further pointers)


Answer:

The binding values that you mention are prepared for lookup locally, let say into the server that you publish the ejb. global, module, app are the scopes limit and in which you can use each one. For example, you could lookup a ejb from other ejb of the same ejb-module using module scope but you couldn't lookup it from another ejb-module even being modules of the same app (ear or war), you must use at least app scope for that, and you can use app or global in both scenarios.

I strongly suggest you to take the time to read Jboss AS7 JNDI Referencia but to know about remote lookup go to Remote JNDI section

Question:

Previous attempts were to have Netbeans deploy an EJB module, which builds as a JAR rather than an EAR, onto the Glassfish server which Netbeans has access to. However, deploying that JAR to Glassfish through the CLI with asadmin possibly runs into a bug.

The EAR deploys through the CLI without issue -- however, the JNDI names for the EJB doesn't appear to work. What is the discrepancy?

32.4.1.1 Portable JNDI Syntax

Three JNDI namespaces are used for portable JNDI lookups: java:global, java:module, and java:app.

The java:global JNDI namespace is the portable way of finding remote enterprise beans using JNDI lookups. JNDI addresses are of the following form: java:global[/application name]/module name /enterprise bean name[/interface name ] Application name and module name default to the name of the application and module minus the file extension. Application names are required only if the application is packaged within an EAR. The interface name is required only if the enterprise bean implements more than one business interface.

http://docs.oracle.com/javaee/7/tutorial/doc/ejb-intro004.htm

What is the correct syntax to lookup this bean? Is it java:global/HelloEAR/HelloEAR-ejb/greetings.GreetingsBeanRemote? I've tried more than a few variants of that without success.

deploying the app:

thufir@dur:~$ 
thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin list-applications
HelloEAR  <ear, ejb>  
Command list-applications executed successfully.
thufir@dur:~$ 
thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin undeploy HelloEAR
Command undeploy executed successfully.
thufir@dur:~$ 
thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin list-applications
Nothing to list.
No applications are deployed to this target server.
Command list-applications executed successfully.
thufir@dur:~$ 
thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin deploy NetBeansProjects/HelloEAR/dist/HelloEAR.ear 
Application deployed with name HelloEAR.
Command deploy executed successfully.
thufir@dur:~$ 

the server.log:

thufir@dur:~$ 
thufir@dur:~$ tail glassfish-4.1/glassfish/domains/domain1/logs/server.log -n 15
[2014-09-22T04:58:42.666-0700] [glassfish 4.1] [INFO] [AS-EJB-00055] [javax.enterprise.ejb.container] [tid: _ThreadID=650 _ThreadName=admin-listener(9)] [timeMillis: 1411387122666] [levelValue: 800] [[
  Glassfish-specific (Non-portable) JNDI names for EJB GreetingsBean: [greetings.GreetingsBeanRemote#greetings.GreetingsBeanRemote, greetings.GreetingsBeanRemote]]]

[2014-09-22T04:58:43.619-0700] [glassfish 4.1] [WARN] [] [org.jboss.weld.Event] [tid: _ThreadID=650 _ThreadName=admin-listener(9)] [timeMillis: 1411387123619] [levelValue: 900] [[
  WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.]]

[2014-09-22T04:58:43.628-0700] [glassfish 4.1] [WARN] [] [org.jboss.weld.Event] [tid: _ThreadID=650 _ThreadName=admin-listener(9)] [timeMillis: 1411387123628] [levelValue: 900] [[
  WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.]]

[2014-09-22T04:58:43.634-0700] [glassfish 4.1] [WARN] [] [org.jboss.weld.Event] [tid: _ThreadID=650 _ThreadName=admin-listener(9)] [timeMillis: 1411387123634] [levelValue: 900] [[
  WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.]]

[2014-09-22T04:58:44.757-0700] [glassfish 4.1] [INFO] [] [javax.enterprise.system.core] [tid: _ThreadID=650 _ThreadName=admin-listener(9)] [timeMillis: 1411387124757] [levelValue: 800] [[
  HelloEAR was successfully deployed in 2,312 milliseconds.]]

thufir@dur:~$     

attempting the lookup:

thufir@dur:~$ 
thufir@dur:~$ glassfish-4.1/glassfish/bin/appclient -client NetBeansProjects/RemoteJNDI/dist/RemoteJNDI.jar 
javax.naming.NamingException: Lookup failed for '[greetings.GreetingsBeanRemote' in SerialContext[myEnv={org.omg.CORBA.ORBInitialPort=3700, java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, Context.SECURITY_CREDENTIALS=pass123, 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, Context.SECURITY_PRINCIPAL=user1} [Root exception is javax.naming.NameNotFoundException: [greetings.GreetingsBeanRemote not found]
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:491)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:438)
    at javax.naming.InitialContext.lookup(InitialContext.java:411)
    at net.bounceme.dur.jndi.RemoteJNDI.main(RemoteJNDI.java:15)
Caused by: javax.naming.NameNotFoundException: [greetings.GreetingsBeanRemote not found
    at com.sun.enterprise.naming.impl.TransientContext.doLookup(TransientContext.java:237)
    at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:204)
    at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:66)
    at com.sun.enterprise.naming.impl.RemoteSerialContextProviderImpl.lookup(RemoteSerialContextProviderImpl.java:109)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie.dispatchToMethod(ReflectiveTie.java:143)
    at com.sun.corba.ee.impl.presentation.rmi.ReflectiveTie._invoke(ReflectiveTie.java:173)
    at com.sun.corba.ee.impl.protocol.ServerRequestDispatcherImpl.dispatchToServant(ServerRequestDispatcherImpl.java:528)
    at com.sun.corba.ee.impl.protocol.ServerRequestDispatcherImpl.dispatch(ServerRequestDispatcherImpl.java:199)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleRequestRequest(MessageMediatorImpl.java:1549)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleRequest(MessageMediatorImpl.java:1425)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleInput(MessageMediatorImpl.java:930)
    at com.sun.corba.ee.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(RequestMessage_1_2.java:213)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.handleRequest(MessageMediatorImpl.java:694)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.dispatch(MessageMediatorImpl.java:496)
    at com.sun.corba.ee.impl.protocol.MessageMediatorImpl.doWork(MessageMediatorImpl.java:2222)
    at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
    at com.sun.corba.ee.impl.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)
thufir@dur:~$ 

Answer:

Why is the invocation of the bean without "java:" or anything like that?

success:

thufir@dur:~$ 
thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin list-applications
Nothing to list.
No applications are deployed to this target server.
Command list-applications executed successfully.
thufir@dur:~$ 
thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin deploy NetBeansProjects/HelloEAR/dist/HelloEAR.ear 
Application deployed with name HelloEAR.
Command deploy executed successfully.
thufir@dur:~$ 
thufir@dur:~$ glassfish-4.1/glassfish/bin/asadmin list-applications
HelloEAR  <ear, ejb>  
Command list-applications executed successfully.
thufir@dur:~$ 
thufir@dur:~$ glassfish-4.1/glassfish/bin/appclient -client NetBeansProjects/RemoteJNDI/dist/RemoteJNDI.jar 
hello world
thufir@dur:~$ 
thufir@dur:~$ 

client code:

package net.bounceme.dur.jndi;

import greetings.GreetingsBeanRemote;
import java.util.logging.Logger;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class RemoteJNDI {

    private static final Logger log = Logger.getLogger(RemoteJNDI.class.getName());

    public static void main(String... args) {
        try {
            InitialContext ctx = new InitialContext();
//            Object obj = ctx.lookup("java:global/HelloEAR/HelloEAR-ejb/greetings.GreetingsBeanRemote");
            Object obj = ctx.lookup("greetings.GreetingsBeanRemote");
            GreetingsBeanRemote gbr = (GreetingsBeanRemote) obj;
            System.out.println(gbr.hi());
        } catch (NamingException ex) {
            ex.printStackTrace();
        }
    }

}

ejb:

package greetings;

import javax.ejb.Stateless;

@Stateless
public class GreetingsBean implements GreetingsBeanRemote {

    @Override
    public String hi() {
        return "hello world";
    }

    @Override
    public String bye() {
        return "bye";
    }

}

interface:

package greetings;

import javax.ejb.Remote;

@Remote
public interface GreetingsBeanRemote {

    public String hi();

    public String bye();
}

server log:

[2014-09-22T17:55:56.091-0700] [glassfish 4.1] [INFO] [] [javax.enterprise.system.tools.deployment.common] [tid: _ThreadID=40 _ThreadName=admin-listener(3)] [timeMillis: 1411433756091] [levelValue: 800] [[
  visiting unvisited references]]

[2014-09-22T17:55:56.233-0700] [glassfish 4.1] [INFO] [AS-EJB-00054] [javax.enterprise.ejb.container] [tid: _ThreadID=40 _ThreadName=admin-listener(3)] [timeMillis: 1411433756233] [levelValue: 800] [[
  Portable JNDI names for EJB GreetingsBean: [java:global/HelloEAR/HelloEAR-ejb/GreetingsBean!greetings.GreetingsBeanRemote, java:global/HelloEAR/HelloEAR-ejb/GreetingsBean]]]

[2014-09-22T17:55:56.235-0700] [glassfish 4.1] [INFO] [AS-EJB-00055] [javax.enterprise.ejb.container] [tid: _ThreadID=40 _ThreadName=admin-listener(3)] [timeMillis: 1411433756235] [levelValue: 800] [[
  Glassfish-specific (Non-portable) JNDI names for EJB GreetingsBean: [greetings.GreetingsBeanRemote#greetings.GreetingsBeanRemote, greetings.GreetingsBeanRemote]]]

[2014-09-22T17:55:56.321-0700] [glassfish 4.1] [WARN] [] [org.jboss.weld.Event] [tid: _ThreadID=40 _ThreadName=admin-listener(3)] [timeMillis: 1411433756321] [levelValue: 900] [[
  WELD-000411: Observer method [BackedAnnotatedMethod] public org.glassfish.jms.injection.JMSCDIExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.]]

[2014-09-22T17:55:56.341-0700] [glassfish 4.1] [WARN] [] [org.jboss.weld.Event] [tid: _ThreadID=40 _ThreadName=admin-listener(3)] [timeMillis: 1411433756341] [levelValue: 900] [[
  WELD-000411: Observer method [BackedAnnotatedMethod] org.glassfish.sse.impl.ServerSentEventCdiExtension.processAnnotatedType(@Observes ProcessAnnotatedType<Object>, BeanManager) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.]]

[2014-09-22T17:55:56.349-0700] [glassfish 4.1] [WARN] [] [org.jboss.weld.Event] [tid: _ThreadID=40 _ThreadName=admin-listener(3)] [timeMillis: 1411433756349] [levelValue: 900] [[
  WELD-000411: Observer method [BackedAnnotatedMethod] private org.glassfish.jersey.gf.cdi.internal.CdiComponentProvider.processAnnotatedType(@Observes ProcessAnnotatedType<Object>) receives events for all annotated types. Consider restricting events using @WithAnnotations or a generic type with bounds.]]

[2014-09-22T17:55:56.819-0700] [glassfish 4.1] [INFO] [] [javax.enterprise.system.core] [tid: _ThreadID=40 _ThreadName=admin-listener(3)] [timeMillis: 1411433756819] [levelValue: 800] [[
  HelloEAR was successfully deployed in 842 milliseconds.]]

thufir@dur:~$ 

Question:

After fighting passwords on Glassfish 4.x remotely on Ubuntu 14.04 Tahr, I'm ready to proceed to installing my first remote EJB module -- just want make sure I'm on the right path. Going from the Netbeans example Creating and Running an Application Client on the GlassFish Server, How would I make a client for the EJB module which is deployed remotely?

The Netbeans example assumes that Glassfish is running on the localhost. The exact mechanics are unclear to me, as it's not explicitly configured for localhost. Presumably it's implicitly configured for localhost...

I would like to use the ACC to connect to, not a local, but rather a remote Glassfish server. For context, the ACC is:

Introducing the Application Client Container

The Application Client Container (ACC) includes a set of Java classes, libraries, and other files that are required for and distributed with Java client programs that execute in their own Java Virtual Machine (JVM). The ACC manages the execution of Java EE application client components (application clients), which are used to access a variety of Java EE services (such as JMS resources, EJB components, web services, security, and so on.) from a JVM outside the Oracle GlassFish Server. The ACC communicates with the GlassFish Server using RMI-IIOP protocol and manages the details of RMI-IIOP communication using the client ORB that is bundled with it. Compared to other Java EE containers, the ACC is lightweight. For information about debugging application clients, see Application Client Debugging.

GlassFish Server Open Source Edition Application Development Guide Release 4.0

see also:

https://stackoverflow.com/questions/25830149/how-to-package-a-stand-alone-remote-ejb-application-client

From a client application, how does the ACC remotely invoke the EJB module?

There must be a configuration. Does the ACC pick this up from jndi.properties? I can't find much documentation or examples on ACC usage. If the ACC is unsuitable, then, of course, I'll use a different approach. Presumably there's a way to specify a remote Glassfish server for the ACC.


Answer:

How do you intend to deploy your application?

In my days when i use to develop application clients for the ACC, i used to bundle everything in an EAR (I will still do that, cause it is easier).

Glassfish deploys the artifacts, generates required configurations (You can override configurations in application.xml anyway).

One thing that the ACC takes care is the CORBA properties needed for remote connection.

When you download the client jar from the glassfish admin, you download a java webstart application, that downloads all required libraries as appropriate and a configuration is automatically set from which host (paramount that you set glassfish domain host properly, or this will be an internal IP or localhost) it was downloaded from.

Question:

What are the possible property names for a jndi.properties key? I cannot find documentation as to what all the possible key names are.

How do I output the principal, credentials and remote key/value pairs for jndi.properties?

-run:
     [java] Sep 12, 2014 6:36:43 PM dur.bounceme.net.remotelookup.RemoteLookup run
     [java] INFO: java.naming.factory.initial   com.sun.enterprise.naming.impl.SerialInitContextFactory
     [java] Sep 12, 2014 6:36:43 PM dur.bounceme.net.remotelookup.RemoteLookup run
     [java] INFO: java.naming.factory.url.pkgs  com.sun.enterprise.naming
     [java] Sep 12, 2014 6:36:43 PM dur.bounceme.net.remotelookup.RemoteLookup run
     [java] INFO: java.naming.factory.state com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl

run:

BUILD SUCCESSFUL
Total time: 13 seconds
thufir@dur:~/NetBeansProjects/LegacyEJB$ 
thufir@dur:~/NetBeansProjects/LegacyEJB$ cat src/java/jndi.properties 
java.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=server.local\:1199
java.naming.security.principal=user
java.naming.security.credentials=password
remote=net.bounceme.ix.Foo
thufir@dur:~/NetBeansProjects/LegacyEJB$ 

as can be seen, not all the key/value pairs are being output. Why?

For the "remote" name and value, should that go in a different properties file?

Main class:

package dur.bounceme.net.remotelookup;

import java.util.Enumeration;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class RemoteLookup {

    private static final Logger log = Logger.getLogger(RemoteLookup.class.getName());
    private final MyProps p = new MyProps();

    public static void main(String... args) {
        try {
            new RemoteLookup().run();
        } catch (NamingException ex) {
            Logger.getLogger(RemoteLookup.class.getName()).log(Level.SEVERE, ex.getExplanation(), ex);
        }
    }

    private void run() throws NamingException {
        Properties jndi = p.getJNDI();
        Enumeration e = jndi.propertyNames();
        while (e.hasMoreElements()) {
            String key = (String) e.nextElement();
            String val = jndi.getProperty(key);
            log.info(key + "\t" + val);
        }
        Context ic = new InitialContext();
//        MyRemote mr = (MyRemote) ic.lookup("java:comp/env/ejb/Foo");  //
    }
}

to read properties files, has worked in the past:

package dur.bounceme.net.remotelookup;

import java.io.IOException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MyProps {

    private static final Logger log = Logger.getLogger(MyProps.class.getName());
    private final Properties jndi = new Properties();

    public MyProps() {
        try {
            loadJNDI();
            String name = jndi.getProperty("name");
        } catch (IOException ex) {
            Logger.getLogger(MyProps.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public Properties getJNDI() {
        return jndi;
    }

    private void loadJNDI() throws IOException {
        jndi.load(MyProps.class.getResourceAsStream("/jndi.properties"));
    }

}

more to the point, what should the key be named as for the values?

------------------------------------------------------edit-------------------------

java.naming.factory.initial=TO_BE_CHANGED_BY_USER java.naming.factory.object=TO_BE_CHANGED_BY_USER java.naming.factory.state=TO_BE_CHANGED_BY_USER java.naming.factory.control=TO_BE_CHANGED_BY_USER java.naming.factory.url.pkgs=TO_BE_CHANGED_BY_USER java.naming.provider.url=TO_BE_CHANGED_BY_USER java.naming.dns.url=TO_BE_CHANGED_BY_USER

from:

http://www.pressinganswer.com/433577/how-to-access-datasource-in-geronimo-via-jndi-by-remote-client-application


Answer:

You need to look in the documentation for each provider, in your case, the COSNaming provider, on the JNDI documentation page.

Question:

The server I'm using is GlassFish, but this problem also occurs on Weblogic as well.

My client machine begins a transaction, looks up several EJBs from the server, and begins some work which takes a while to complete. During the process, the client machine dies (let's say a powercut).

The database queries opened by the client machine are never closed (because the client terminated) and this causes deadlocks and other issues.

Is there any way to detect this dead transaction and reclaim all the resources?

Pseudocode example below

transaction.begin();

MyBean bean = (MyBean)ctx.lookup("MyBean");

bean.doComplicatedWorkPart1();

bean.writeResultsToTheDatabase();

// Client dies during this method (powercut), so the transaction
// is simply left hanging.
bean.doComplicatedWorkPart2();

bean.writeResultsToTheDatabase();

transaction.commit();

Answer:

IIRC this is can't be easily handled. It depends on the database you use what you need to do use the DB administration to find the hanging transactions.

To have a more relyable environment you should create a server side bean for this, here it is more unlikely that the process died or loose connection somewhere during the transaction.

Question:

How to map a DataSource Resource Ref Name to a JNDI Name in EJB in WildFly?

I know that in JBoss 4.2.3 it is done in jboss.xml but it is not working in WildFly.

Here is my test:

I am working with Java 1.7, XDoclet 1.2.3, WildFly 8.2.1.Final, Dynamic Web Module 2.5, EJB 2.1 in Eclipse Luna.

In WildFly I have a DataSource named SchedulerDS whose JNDI name is java:jboss/datasources/SchedulerDS. It is using jTDS JDBC Driver and connecting to a MS SQL Server 2008 R2 database.

In Eclipse I created these projects:

  1. an Enterprise Application project named Z01_EAR.
  2. a Dynamic Web Project named Z01_WAR.
  3. a EJB Project named Z01_EJB.
  4. a EJB Client Project named Z01_EJBClient.

In Z01_EJB project, I create a XDoclet Stateless Session Bean (EJB 2.1) named SLS01. In it I define a DataSource Resource Ref named jdbc/chumbo. And I define its mapping to JNDI Name java:jboss/datasources/SchedulerDS.

This is the ejb-jar.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar_1" 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/ejb-jar_2_1.xsd" version="2.1">
   <description><![CDATA[Z01_EJB generated by eclipse wtp xdoclet extension.]]></description>
   <display-name>Z01_EJB</display-name>
   <enterprise-beans>
      <session id="Session_SLS01">
         <description><![CDATA[An EJB named SLS01]]></description>
         <display-name>SLS01</display-name>
         <ejb-name>SLS01</ejb-name>
         <home>com.z01.ejb.SLS01Home</home>
         <remote>com.z01.ejb.SLS01</remote>
         <local-home>com.z01.ejb.SLS01LocalHome</local-home>
         <local>com.z01.ejb.SLS01Local</local>
         <ejb-class>com.z01.ejb.SLS01Session</ejb-class>
         <session-type>Stateless</session-type>
         <transaction-type>Container</transaction-type>
         <resource-ref id="ResRef_1">
            <res-ref-name>jdbc/chumbo</res-ref-name>
            <res-type>javax.sql.DataSource</res-type>
            <res-auth>Container</res-auth>
         </resource-ref>
      </session>
   </enterprise-beans>
   <assembly-descriptor id="AssemblyDescriptor_1">
   </assembly-descriptor>
   <ejb-client-jar>Z01_EJBClient.jar</ejb-client-jar>
</ejb-jar>

This is the jboss.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 4.0//EN" "http://www.jboss.org/j2ee/dtd/jboss_4_0.dtd">
<jboss>
   <enterprise-beans>
      <session>
         <ejb-name>SLS01</ejb-name>
         <jndi-name>SLS01</jndi-name>
         <local-jndi-name>SLS01Local</local-jndi-name>
         <resource-ref>
            <res-ref-name>jdbc/chumbo</res-ref-name>
            <jndi-name>java:jboss/datasources/SchedulerDS</jndi-name>
         </resource-ref>
        <method-attributes>
        </method-attributes>
      </session>
   </enterprise-beans>
   <assembly-descriptor>
   </assembly-descriptor>
   <resource-managers>
   </resource-managers>
</jboss>

In EJB I wrote a method to test

public void testRetrieve() {

    String dataSourceLookupString = null;
    InitialContext initialContext = null;
    DataSource dataSource = null;       
    Connection connection = null;
    String sql = null;
    Statement statement = null;
    ResultSet resultSet = null;
    long employeeId = -1;


    try {
        dataSourceLookupString = "java:comp/env/jdbc/chumbo";           
        initialContext = new InitialContext();
        dataSource = (DataSource) initialContext.lookup(dataSourceLookupString);
        connection = dataSource.getConnection();
        sql = "select top 1 employee_id from employee";
        statement = connection.createStatement();           
        resultSet = statement.executeQuery(sql);            
        if (resultSet != null && resultSet.next()) {
            employeeId = resultSet.getLong(1);
            System.out.println("testRetrieve(): employeeId=" + employeeId);
        }           
    } catch (NamingException e) {
        e.printStackTrace();            
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        try {
            if (statement != null) {
                statement.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

        try {
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();                
        }
    }       
}

It did not work and I got this error:

2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) org.h2.jdbc.JdbcSQLException: Table "EMPLOYEE" not found; SQL statement: 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) select top 1 employee_id from employee [42102-173] 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.message.DbException.getJdbcSQLException(DbException.java:331) 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.message.DbException.get(DbException.java:171) 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.message.DbException.get(DbException.java:148) 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.command.Parser.readTableOrView(Parser.java:4864) 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.command.Parser.readTableFilter(Parser.java:1107) 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.command.Parser.parseSelectSimpleFromPart(Parser.java:1713) 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.command.Parser.parseSelectSimple(Parser.java:1821) 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.command.Parser.parseSelectSub(Parser.java:1707) 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.command.Parser.parseSelectUnion(Parser.java:1550) 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.command.Parser.parseSelect(Parser.java:1538) 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.command.Parser.parsePrepared(Parser.java:405) 2015-12-14 18:54:50,403 ERROR [stderr] (MSC service thread 1-6) at org.h2.command.Parser.parse(Parser.java:279) 2015-12-14 18:54:50,419 ERROR [stderr] (MSC service thread 1-6) at org.h2.command.Parser.parse(Parser.java:251) 2015-12-14 18:54:50,419 ERROR [stderr] (MSC service thread 1-6) at org.h2.command.Parser.prepareCommand(Parser.java:218) 2015-12-14 18:54:50,419 ERROR [stderr] (MSC service thread 1-6) at org.h2.engine.Session.prepareLocal(Session.java:428) 2015-12-14 18:54:50,419 ERROR [stderr] (MSC service thread 1-6) at org.h2.engine.Session.prepareCommand(Session.java:377) 2015-12-14 18:54:50,419 ERROR [stderr] (MSC service thread 1-6) at org.h2.jdbc.JdbcConnection.prepareCommand(JdbcConnection.java:1138) 2015-12-14 18:54:50,419 ERROR [stderr] (MSC service thread 1-6) at org.h2.jdbc.JdbcStatement.executeQuery(JdbcStatement.java:72) 2015-12-14 18:54:50,419 ERROR [stderr] (MSC service thread 1-6) at org.jboss.jca.adapters.jdbc.WrappedStatement.executeQuery(WrappedStatement.java:344) 2015-12-14 18:54:50,419 ERROR [stderr] (MSC service thread 1-6) at com.z01.ejb.SLS01Bean.testRetrieve(SLS01Bean.java:197)

Now I change my code to lookup to JNDI Name directly:

dataSourceLookupString = "java:jboss/datasources/SchedulerDS";

And it worked perfect. So this means jboss.xml is not working in my case. How can I map a DataSource Resource Ref Name to a JNDI Name in this case?

Thanks


Answer:

Figure out that instead of jboss.xml I have to use jboss-ejb3.xml for WildFly.