JBoss Community

Re: Embedded AS

created by Kabir Khan in JBoss AS7 Development - View the full discussion
What I have so far can be found at https://github.com/kabir/jboss-as/commits/demos-test-embedded-cleaned. I still need to go through and add privileged actions etc. before this can be pushed, but some feedback before finalizing this would be great.
The embedded stuff can be used with either flat or modular classloading. I'll talk about flat first since that is the simplest.
To start up an embedded server you simply create an instance of org.jboss.as.embedded.FlatEmbeddedServer and start that up as shown in org.jboss.test.as.embedded.flat.RunServerTestCase in embedded/flat:
        System.setProperty("jboss.embedded.server.home", Utils.getASHome().getAbsolutePath());
        System.setProperty("jboss.embedded.server.modules", new File(Utils.getASHome(), "modules").getAbsolutePath());
        FlatEmbeddedServer server = new FlatEmbeddedServer();
        try {
            server.start();
            ServerModel model = server.getClient().getServerModel();
            Assert.assertNotNull(model);
        } finally {
            System.clearProperty("jboss.embedded.server.home");
            System.clearProperty("jboss.embedded.server.modules");
            server.shutdown();
        }
The thing I had to do here to get it to work is to take the jboss.embedded.server.modules location, and copy that to a new location replacing the module.xml for each module with:
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="urn:jboss:module:1.0" name="org.jboss.logging">
    <dependencies>
        <module name="system" export="true"/>
    </dependencies>
</module>
So every module delegates to the system classloader. If the default module loader could be swapped out somehow in jboss-modules, I could come up with a more elegant solution for this if deemed important.
To run using modular classloading you need two projects:
1) The implementation which starts the server and does the useful stuff. It contains all the dependencies to be able to compile that. This can be found in testsuite/modular/impl and depends on the stuff from embedded/modular/server
2) The bootstrap which is used to construct the module loader seeing the as modules and additional modules created per test. This does not have the implementation on the classpath but loads this up via modules. The bootstrap lives in testsuite/modular/test and has a simple classpath just containing things needed to be able to load the classes to be able to construct the test modules with no dependencies on things that should be loaded up via modules (found in embedded/modular/bootstrap).
The main way to run a test is shown in testsuite/modular/test/org.jboss.test.as.modular.demos.test.DemosTestCase:
@TestSetup(
    implClass="org.jboss.test.as.modular.demos.impl.DemosTestImpl",
    testModule="test.demos",
    tcclModule="test.demos.tccl",
    systemPropertyProvider=DemoSystemPropertyProvider.class,
    modules= {
        @ModuleDef(
                name="test.demos",
                packages={@PackageResource(directory="${demo.impl.classes}", packages={"org.jboss.test.as.modular.demos.impl"})},
                jars=@JarResource (directory="${project.root}/demos/target", jar="jboss-as-demos.*(?<!sources)\\.jar", expand=true),
                dependencies= {@Dependency("javaee.api"), @Dependency("org.hornetq"), @Dependency("org.jboss.as.messaging"), @Dependency("javax.jms.api")}),
        @ModuleDef (
                name="test.demos.tccl",
                dependencies= {@Dependency("org.jboss.logging"), @Dependency("test.demos")})
        }
)
@RunWith(ModularJunitTestRunner.class)
public class DemosTestCase {
}
The ModularJunitTestRunner picks up @TestSetup and creates:
-a module called 'test.demos' with some classes from testsuite/impl project and the jar from the demos project. Since this is the same name as 'testModule' the dependencies needed to start a server are added automatically, but since we need access to some more classes to run the demos that have been ported so far some more are added using the 'dependencies'.
-a module called 'test.demos.tccl' that is used as the TCCL when running each test (Shrinkwrap currently relies on TCCL)
ModularJunitTestRunner then loads up org.jboss.test.as.modular.demos.impl.DemosTestImpl from the test.demos module and runs that which contains the real tests:
public class DemosTestImpl  {
    static ModularEmbeddedServer starter = new ModularEmbeddedServer(getASHome());
    @BeforeClass
    public static void startServer() throws Exception {
        starter.start(JMSSubsystemElement.JMS_CF_BASE.append("InVmConnectionFactory").getCanonicalName());
    }
    @AfterClass
    public static void stopServer() throws Exception {
        starter.shutdown();
    }
    @Test
    public void testSar() throws Exception {
        SarTestRunner runner = new SarTestRunner(starter);
        runner.test();
    }
    …
}
testsuite/modular/test/org.jboss.test.as.modular.embedded.test.ModuleBuilderTestCase shows how to use the ModuleLoaderBuilder directly (not recommended) or the more friendly ModularEmbeddedServerBuilder for users who want to bootstrap an AS instance from their code.

What I have so far can be found at https://github.com/kabir/jboss-as/commits/demos-test-embedded-cleaned. I still need to go through and add privileged actions etc. before this can be pushed, but some feedback before finalizing this would be great.

 

The embedded stuff can be used with either flat or modular classloading. I'll talk about flat first since that is the simplest.

 

To start up an embedded server you simply create an instance of org.jboss.as.embedded.FlatEmbeddedServer and start that up as shown in org.jboss.test.as.embedded.flat.RunServerTestCase in embedded/flat:

 

        System.setProperty("jboss.embedded.server.home", Utils.getASHome().getAbsolutePath());

        System.setProperty("jboss.embedded.server.modules", new File(Utils.getASHome(), "modules").getAbsolutePath());

        FlatEmbeddedServer server = new FlatEmbeddedServer();

        try {

            server.start();

            ServerModel model = server.getClient().getServerModel();

            Assert.assertNotNull(model);

        } finally {

            System.clearProperty("jboss.embedded.server.home");

            System.clearProperty("jboss.embedded.server.modules");

            server.shutdown();

        }

 

The thing I had to do here to get it to work is to take the jboss.embedded.server.modules location, and copy that to a new location replacing the module.xml for each module with:

 

<?xml version="1.0" encoding="UTF-8"?>

<module xmlns="urn:jboss:module:1.0" name="org.jboss.logging">

    <dependencies>

        <module name="system" export="true"/>

    </dependencies>

</module>

 

So every module delegates to the system classloader. If the default module loader could be swapped out somehow in jboss-modules, I could come up with a more elegant solution for this if deemed important.

 

To run using modular classloading you need two projects:

  1. The implementation which starts the server and does the useful stuff. It contains all the dependencies to be able to compile that. This can be found in testsuite/modular/impl and depends on the stuff from embedded/modular/server
  2. The bootstrap which is used to construct the module loader seeing the as modules and additional modules created per test. This does not have the implementation on the classpath but loads this up via modules. The bootstrap lives in testsuite/modular/test and has a simple classpath just containing things needed to be able to load the classes to be able to construct the test modules with no dependencies on things that should be loaded up via modules (found in embedded/modular/bootstrap).

 

The main way to run a test is shown in testsuite/modular/test/org.jboss.test.as.modular.demos.test.DemosTestCase:

 

@TestSetup(

    implClass="org.jboss.test.as.modular.demos.impl.DemosTestImpl",

    testModule="test.demos",

    tcclModule="test.demos.tccl",

    systemPropertyProvider=DemoSystemPropertyProvider.class,

    modules= {

        @ModuleDef(

                name="test.demos",

                packages={@PackageResource(directory="${demo.impl.classes}", packages={"org.jboss.test.as.modular.demos.impl"})},

                jars=@JarResource (directory="${project.root}/demos/target", jar="jboss-as-demos.*(?<!sources)\\.jar", expand=true),

                dependencies= {@Dependency("javaee.api"), @Dependency("org.hornetq"), @Dependency("org.jboss.as.messaging"), @Dependency("javax.jms.api")}),

        @ModuleDef (

                name="test.demos.tccl",

                dependencies= {@Dependency("org.jboss.logging"), @Dependency("test.demos")})

        }

)

@RunWith(ModularJunitTestRunner.class)

public class DemosTestCase {

}

 

The ModularJunitTestRunner picks up @TestSetup and creates:

-a module called 'test.demos' with some classes from testsuite/impl project and the jar from the demos project. Since this is the same name as 'testModule' the dependencies needed to start a server are added automatically, but since we need access to some more classes to run the demos that have been ported so far some more are added using the 'dependencies'.

-a module called 'test.demos.tccl' that is used as the TCCL when running each test (Shrinkwrap currently relies on TCCL)

 

ModularJunitTestRunner then loads up org.jboss.test.as.modular.demos.impl.DemosTestImpl from the test.demos module and runs that which contains the real tests:

public class DemosTestImpl  {

 

    static ModularEmbeddedServer starter = new ModularEmbeddedServer(getASHome());

 

    @BeforeClass

    public static void startServer() throws Exception {

        starter.start(JMSSubsystemElement.JMS_CF_BASE.append("InVmConnectionFactory").getCanonicalName());

    }

 

    @AfterClass

    public static void stopServer() throws Exception {

        starter.shutdown();

    }

 

    @Test

    public void testSar() throws Exception {

        SarTestRunner runner = new SarTestRunner(starter);

        runner.test();

    }

    …

}

 

 

testsuite/modular/test/org.jboss.test.as.modular.embedded.test.ModuleBuilderTestCase shows how to use the ModuleLoaderBuilder directly (not recommended) or the more friendly ModularEmbeddedServerBuilder for users who want to bootstrap an AS instance from their code.

Reply to this message by going to Community

Start a new discussion in JBoss AS7 Development at Community