LeXXXa
LeXXXa

Reputation: 71

Obtaining Context from an embedded Glassfish 3.1

Does anyone now a way to obtain server Context using Embeddable API (using org.glassfish.embeddable.GlassFish, not javax.ejb.embeddable.EJBContainer)? It would be possible if there's a way to obtain EJBContainer from a running Glassfish, but I can't find even the list of services available for lookup.

Upvotes: 5

Views: 1719

Answers (2)

Vineet Reynolds
Vineet Reynolds

Reputation: 76709

As far as I know, you can initialize the InitialContext class to obtain a context, that can further be used to perform the lookup. This was tested, and found to work in the context of looking up an EJB, deployed in the embedded container. The EJB was not configured to allow access to specific roles, in which case the com.sun.appserv.security.ProgrammaticLogin class (not exposed via the Embeddable EJB API) might help; this was not tested, but is the recommended way to initialize the Principal for the thread accessing an EJB.

A more or less complete example that runs from Maven and uses the embedded Glassfish dependency in a POM (not reproduced here, for brevity) follows:

The EJB interface:

public interface EchoManager
{
    String echo(String message);
}

The Session Bean:

@Local(EchoManager.class)
@Stateless
@EJB(name="java:global/glassfish-ejb-validation/EchoManager",beanInterface=EchoManager.class)
public class EchoManagerBean implements EchoManager
{

    public String echo(String message)
    {
        return message;
    }

}

The unit test:

public class EchoManagerTest
{

    @Rule
    public TestName testMethod = new TestName();

    private static final Logger logger = Logger.getLogger(EchoManagerTest.class.getName());

    @Test
    public void testEchoWithGlassfishRuntime() throws Exception
    {
        logger.info("Starting execution of test" + testMethod.getMethodName());

        GlassFish glassFish = null;
        Deployer deployer = null;
        String appName = null;
        try
        {
            //Setup
            BootstrapProperties bootstrapProps = new BootstrapProperties();
            GlassFishRuntime glassFishRuntime = GlassFishRuntime.bootstrap(bootstrapProps);

            GlassFishProperties gfProps = new GlassFishProperties();

            glassFish = glassFishRuntime.newGlassFish(gfProps);
            glassFish.start();

            deployer = glassFish.getDeployer();
            ScatteredArchive archive = new ScatteredArchive("glassfish-ejb-validation", Type.JAR);
            archive.addClassPath(new File("target", "classes"));
            archive.addClassPath(new File("target", "test-classes"));

            appName = deployer.deploy(archive.toURI(), "--force=true");

            // Setup the context
            InitialContext context = new InitialContext();

            //Execute (after lookup the EJB from the context)
            EchoManager manager = (EchoManager) context.lookup("java:global/glassfish-ejb-validation/EchoManager");
            String echo = manager.echo("Hello World");

            //Verify
            assertEquals("Hello World", echo);
        }
        finally
        {
            if(deployer != null && appName != null)
            {
                deployer.undeploy(appName);
            }
            if(glassFish != null)
            {
                glassFish.stop();
                glassFish.dispose();
            }
            logger.info("Ending execution of test" + testMethod.getMethodName());
        }
    }
}

Note that the EJB is deployed with a explicit portable JNDI name (via the @EJB annotation), as I have other tests that use the public embeddable EJB API in other tests, and it is more or less difficult to specify an application name in such tests; each test execution might result in a different JNDI name for the EJB, thus necessitating an explicit JNDI name to be specified.

Upvotes: 0

LeXXXa
LeXXXa

Reputation: 71

Here's a workaround - we can obtain InitialContext as an external client. For the full explanation check EJB_FAQ . This way at least remote EJBs could be tested:

So the full example will look like:

//Start GF
GlassFishRuntime gfRuntime = GlassFishRuntime.bootstrap();
GlassFish gf = gfRuntime.newGlassFish();
gf.start();
//Deploy application with EJBs
Deployer deployer = gf.getService(Deployer.class);
String deployedApp = deployer.deploy(new File(...), "--force=true");
//Create InitialContext
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");
InitialContext ic = new InitialContext(props);
//Lookup EJBs
ic.lookup(...)
//Stop GF
gf.stop();
gfRuntime.shutdown();
//CORBA stuck thread, have to kill it manually
System.exit(0);

Note there's a System.exit(0) at the end - com.sun.corba.ee.impl.javax.rmi.CORBA.Util.KeepAlive thread is running even after the server stop preventing JVM from stopping...

Upvotes: 1

Related Questions