Hot questions for Using Enterprise JavaBeans in glassfish 4

Question:

I am trying to access an EJB via JSE Standalone application.

I was struggling a lot with JNDI Names not being found during lookup.

After some research without any solution I found in the Glassfish server log after a deploy a message stating something like:

"[glassfish 4.1] [INFO] [AS-EJB-00054] [javax.enterprise.ejb.container] [tid: _ThreadID=47 _ThreadName=admin-listener(4)] [timeMillis: 1424811833554] [levelValue: 800] [[ Portable JNDI names for EJB HelloBean:java:global/ponteWS/HelloBean!br.com.pontews.HelloRemote, java:global/ponteWS/HelloBean!br.com.pontews.HelloBean]]] "

I tried the remote name and voilá!!! It works.

I tried the other name and did not work.

Here comes the questions:

1-Why the JNDI name is so weird???? Is there something I can do in order to avoid the package name in front of the name of the bean? 2-What is the error I get when acessing the bean directly instead the HelloRemote Interface?

Here is the HelloRemote:

package br.com.pontews;

import javax.ejb.Remote;

@Remote
public interface HelloRemote {

    public String sayHello(String name);
}

Here is the Bean:

package br.com.pontews;
import java.io.Serializable;
import javax.ejb.LocalBean;
import javax.ejb.Remote;
import javax.ejb.Stateless;

@Stateless(name="HelloBean")
@LocalBean
@Remote
public class HelloBean implements HelloRemote, Serializable {

    /**
     * 
     */
    private static final long   serialVersionUID    = 1L;

    /**
     * Default constructor.
     */
    public HelloBean() {
    }

    public String sayHello(String name) {
        return "Hello," + name + ".!" ;
    }

}

Here is the call that works:

Object lookup = 
ctx.lookup("java:global/ponteWS/HelloBean!br.com.pontews.HelloRemote");

Here is the call that does not works:

Object lookup = 
ctx.lookup("java:global/ponteWS/HelloBean!br.com.pontews.HelloBean");

And finally the error I get with call that does not work:

Exception in thread "main" javax.naming.CommunicationException: Communication exception for SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl} [Root exception is java.rmi.RemoteException: CORBA NO_IMPLEMENT 1398079489 Maybe; nested exception is: org.omg.CORBA.NO_IMPLEMENT: ----------BEGIN server-side stack trace---------- org.omg.CORBA.NO_IMPLEMENT: WARNING: 01000001: Missing local value implementation vmcid: SUN minor code: 1 completed: Maybe : : : Caused by: java.lang.ClassNotFoundException: br.com.pontews.EJB31_Generated__HelloBean__Intf____Bean (no security manager: RMI class loader disabled)

Thanks


Answer:

The name you are using to lookup () has the format as specified by the EJB specification.

In case of glassfish it should also be possible to use the fully qualified name of the remote business interface to lookup the bean (https://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#SessionBeanGlobalJNDINameAssignment). In your case this would be

br.com.pontews.HelloRemote

If you still have problems on the lookup the instructions here might help: (from https://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB)

Step 1. Use the no-arg InitialContext() constructor in your code.

The most common problem developers run into is passing specific JNDI bootstrapping properties to InitialContext(args). Some other vendors require this step but GlassFish does not. Instead, use the no-arg InitialContext() constructor.

Step 2. Pass the global JNDI name of the Remote EJB to InitialContext.lookup()

Stand-alone java clients do not have access to a component naming environment (java:comp/env) or to the @EJB annotation, so they must explicitly use the global JNDI name to lookup the Remote EJB. (See here for more information on how global JNDI names are assigned to EJB components) Assuming the global JNDI name of the Remote EJB is "FooEJB" :

For Beans with a 3.x Remote Business interface :

Foo foo = (Foo) new InitialContext().lookup("FooEJB");

Note that in the EJB 3.x case the result of the lookup can be directly cast to the remote business interface type without using PortableRemoteObject.narrow().

For EJB 2.1 and earlier session/entity beans :

Object homeObj = new InitialContext().lookup("FooEJB");

FooHome fooHome = (FooHome) PortableRemoteObject.narrow(homeObj,FooHome.class);

Foo foo = fooHome.create(...) Step 3. Include the appropriate GlassFish .jars in the java client's classpath.

For GlassFish 3.

Include $GLASSFISH_HOME/glassfish/lib/gf-client.jar in the client's classpath.

E.g., assuming the application classes are in /home/user1/myclasses and the main client class is acme.MyClient :

java -classpath $GLASSFISH_HOME/glassfish/lib/gf-client.jar:/home/user1/myclasses acme.MyClient

Note that the Java EE 6 API classes are automatically included by gf-client.jar so there is no need to explicitly add javaee.jar to the classpath. gf-client.jar refers to many other .jars from the GlassFish installation directory so it is best to refer to it from within the installation directory itself rather than copying it(and all the other .jars) to another location.

Note: gf-client.jar is located in $GLASSFISH_HOME/modules/gf-client.jar in GlassFish v3.

Question:

According to official documentation there are two states of stateless EJB: doesnt-exists and ready. But that's all it says about lifecycle.

I use glassfish 4 and I need to know exactly

  1. when stateless EJB instance is created - at moment when domain started or when I inject my EJB to some point or?
  2. when non used stateless EJB is destroyed - at moment when domain stopped or after some idle time or?

Please, help me.


Answer:

I think it's necessary to read the following glassfish settings from http://docs.oracle.com/cd/E18930_01/html/821-2431/abeea.html :

The EJB pool settings are:

Initial and Minimum Pool Size: the initial and minimum number of beans maintained in the pool. Valid values are from 0 to MAX_INTEGER, and the default value is 8. The corresponding EJB deployment descriptor attribute is steady-pool-size.

Set this property to a number greater than zero for a moderately loaded system. Having a value greater than zero ensures that there is always a pooled instance to process an incoming request.

Maximum Pool Size: the maximum number of connections that can be created to satisfy client requests. Valid values are from zero to MAX_INTEGER., and the default is 32. A value of zero means that the size of the pool is unbounded. The potential implication is that the JVM heap will be filled with objects in the pool. The corresponding EJB deployment descriptor attribute is max-pool-size.

Set this property to be representative of the anticipated high load of the system. An very large pool wastes memory and can slow down the system. A very small pool is also inefficient due to contention.

Pool Resize Quantity: the number of beans to be created or deleted when the cache is being serviced by the server. Valid values are from zero to MAX_INTEGER and default is 16. The corresponding EJB deployment descriptor attribute is resize-quantity.

Be sure to re-calibrate the pool resize quantity when you change the maximum pool size, to maintain an equilibrium. Generally, a larger maximum pool size should have a larger pool resize quantity.

Pool Idle Timeout: the maximum time that a stateless session bean, entity bean, or message-driven bean is allowed to be idle in the pool. After this time, the bean is destroyed if the bean in case is a stateless session bean or a message driver bean. This is a hint to server. The default value is 600 seconds. The corresponding EJB deployment descriptor attribute is pool-idle-timeout-in-seconds.

If there are more beans in the pool than the maximum pool size, the pool drains back to initial and minimum pool size, in steps of pool resize quantity at an interval specified by the pool idle timeout. If the resize quantity is too small and the idle timeout large, you will not see the pool draining back to steady size quickly enough.

Question:

I am learning about EJB and I would like to get the following code working but so far no success. Here's my EJB project code:

@Stateless
public class CalcBean implements ICalcRemote {

    private static final long serialVersionUID = 5571798968598315142L;

    @Override
    public int add(int a, int b) {
        return a + b;
    }

}


package com.ejb.test.pckg;

import javax.ejb.Remote;

@Remote
public interface ICalcRemote extends ICalculator {

}


package com.ejb.test.pckg;

import java.io.Serializable;

public interface ICalculator extends Serializable {

    public int add(int a, int b);

}

I run glassfish-4.1.1 in Eclipse Neon.

When I deploy the EJB project, I can see the following in the log:

    2017-02-24T21:18:09.036-0400|Info: Portable JNDI names for EJB CalcBean: [java:global/EJBDemo/CalcBean, java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote]

    2017-02-24T21:18:09.036-0400|Info: Glassfish-specific (Non-portable) JNDI names for EJB CalcBean: [com.ejb.test.pckg.ICalcRemote#com.ejb.test.pckg.ICalcRemote, com.ejb.test.pckg.ICalcRemote]

This is my client code:

    import java.util.Properties;

    import javax.naming.Context;
    import javax.naming.InitialContext;

    import com.ejb.test.pckg.ICalcRemote;

    public class Main {
        public static void main(String[] args) {

            try {

                Properties props = new Properties();
                props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
                props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
                props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
                //
                props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
                props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");

                Context ctx = new InitialContext();
                ICalcRemote calc = (ICalcRemote) ctx.lookup("java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote");
                System.out.println(calc.add(5, 7));

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        /*
         * (non-Java-doc)
         *
         * @see java.lang.Object#Object()
         */
        public Main() {
            super();
        }

    }

But I am having no luck. Any suggestions how to get this working?

Thank you!

EDIT:

This is my main (client) which includes info from the EJBDemo deployment log:

import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;

import com.ejb.test.pckg.ICalcRemote;

public class Main {
    public static void main(String[] args) {

        try {

            Properties props = new Properties();
            props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
            props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
            props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
            //
            // props.setProperty("org.omg.CORBA.ORBInitialHost", "localhost");
            // props.setProperty("org.omg.CORBA.ORBInitialPort", "3700");

            /*
             * THIS IS from Glassfish log of EJBDemo deployment 
             * 
             * 2017-02-25T20:41:47.100-0400|Info: Portable JNDI names for EJB CalcBean: [java:global/EJBDemo/CalcBean,
             * java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote] 2017-02-25T20:41:47.100-0400|Info: Glassfish-specific (Non-portable) JNDI names for EJB CalcBean:
             * [com.ejb.test.pckg.ICalcRemote#com.ejb.test.pckg.ICalcRemote, com.ejb.test.pckg.ICalcRemote]
             *
             *
             */
            Context ctx = new InitialContext();
            ICalcRemote calc = (ICalcRemote) ctx.lookup("java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote");
            System.out.println(calc.add(5, 7));

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /*
     * (non-Java-doc)
     *
     * @see java.lang.Object#Object()
     */
    public Main() {
        super();
    }

}

Answer:

I finally got things working! Since it's been quite a process despite reading many posts related to this issue. Here are the details of my configuration. Hopefully, this will be useful to somebody.

OS: win 10 IDE: Eclipse Neon App server: Glassfish 4.1.1 JDK: 1.8.0_111

I need to mention this article which eventually led me to the answer:

http://mavicode.com/2014/08/a-standalone-client-for-ejbs-running-on-glassfish-4/

So, thanks and kudos.

First, create the EJB Demo project:

package com.ejb.test.pckg;

import java.io.Serializable;

public interface ICalculator extends Serializable {

    public int add(int a, int b);

}


package com.ejb.test.pckg;

import javax.ejb.Remote;

@Remote
public interface ICalcRemote extends ICalculator {

}

package com.ejb.test.pckg;

import javax.ejb.Stateless;

// @Stateless(mappedName = "chester")
@Stateless
public class CalcBean implements ICalcRemote {

    private static final long serialVersionUID = 5571798968598315142L;

    @Override
    public int add(int a, int b) {
        return a + b;
    }

}

Deploy it on the server (run as > run on the server) > check the log to see the JDNI info. It should look like something like this:

2017-02-25T20:41:47.100-0400|Info: Portable JNDI names for EJB CalcBean: [java:global/EJBDemo/CalcBean, java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote] 2017-02-25T20:41:47.100-0400|Info: Glassfish-specific (Non-portable) JNDI names for EJB CalcBean: [com.ejb.test.pckg.ICalcRemote#com.ejb.test.pckg.ICalcRemote, com.ejb.test.pckg.ICalcRemote]

After that, create Application Client Project. Main.java will be created automatically. This is my main:

import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;

import com.ejb.test.pckg.ICalcRemote;

public class Main {
    public static void main(String[] args) {

        try {

            Properties props = new Properties();
            props.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory");
            props.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming");
            props.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");

            Context ctx = new InitialContext();
            ICalcRemote calc = (ICalcRemote) ctx.lookup("java:global/EJBDemo/CalcBean!com.ejb.test.pckg.ICalcRemote");

            System.out.println(calc.add(5, 43));

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /*
     * (non-Java-doc)
     *
     * @see java.lang.Object#Object()
     */
    public Main() {
        super();
    }

}   

At this point, my project looks like this:

And here comes the key part. Add a new external library from the Glassfish lib directory. !!! IMPORTANT: Don't just copy and paste to the path! The .jar apparently uses/references other classes in other GF jars. So just add it to the build path as an external jar instead of copy/paste.

You should be set now. Run the Main as a Java application.

This is what I get.

Question:

I have a class with interface and a new class for which I call new ojbClass(params) - which contains an ejb call (code below). When it get's to call the ejb from that class, i get null point exception.

Class calling EJB method inside

public class ProfileDTO {

    private Profile profileEntity;

    @EJB
    private ProfileRemoteBean profileBean; //remote bean is interface name

    public ProfileDTO(String firstName, String lastName, Date birthDate, String gender, String country, String district, String city, String identificationNo, String idCardNo, String phone) {

        createProfile();

    }

    public void createProfileEntity() {

        Profile profileEntity = new Profile();

        //deleted code for stackoverflow
        //...................................
        this.profileEntity = profileEntity;
    }

    public Profile getProfileEntity(){
        return this.profileEntity;
    }

    private void createProfile() {
        createProfileEntity();
        profileBean.addProfile(getProfileEntity()); // profile bean null point here
    }

}

EJB Interface

@Remote
public interface ProfileRemoteBean {
    public List<Profile> getProfile();
}

EJB Class

@Stateless
public class ProfileBean implements ProfileRemoteBean,Serializable{

    @PersistenceContext(unitName = "com.ulbs.admission.core_AdmissionCoreDBEJB_ejb_1.0-SNAPSHOTPU", type = PersistenceContextType.TRANSACTION)
    private EntityManager entityManager;



    @Override
    public List<Profile> getProfile() {
     TypedQuery<Profile> query = entityManager.createNamedQuery("Profile.findAll", Profile.class);
     return query.getResultList();
    }
}

Can you please give me some hints or a solution?

Thanks!


Answer:

What you are trying is not supposed to work: You can't inject an EJB in a DTO because it is not a managed class.

Either refactor your dependency injection or pass the ProfileRemoteBean to the ProfileDTO via the constructor.

Question:


Answer:

Afaik, JBoss > Glassfish or Tomcat.

You could try fine tuning your enterprise application or better still, run a benchmark between JBoss and Glassfish, check the performance between the two in a production environment.

Am sure the test scenario would give you enough insight into performance tuning/upgrading your application to a version closer to JavaEE 6/7+ and a JBoss supported version.