Skip to the content.

Testing Jakarta EE 9 Applications with Arquillian and Glassfish v6

Arquillian added a new module Arquillian Container Glassfish6 to align with the changes of Jakarta EE 9 and the features introduced in the Arquillian Core 1.7.0. Arquillian Container Glassfish6 is designated to run tests on Glassfish v6, which is a full-featured Jakarta EE 9 compatible application server, so you can test all Jakarta EE 9 components using this new Arquillian Glassfish container.

In this post, we will try to run the our tests on the Glassfish container using both managed and remote adapters.

Note: The original Aruqillian Glassfish embedded container is not ported to the latest Glassfish v6 now.

Prerequisites

Note: Make sure you are using Java 8, Glassfish v6.0 does not support Java 11. Glassfish v6.1 will focus on Java 11 support.

Testing Restful Web Service

Currently, only two simple Arquillian integration tests are included in our sample project, we have introduced the CDI components in the last post.

Let’s move on the GreetingResourceTest.

@ExtendWith(ArquillianExtension.class)
public class GreetingResourceTest {
    private final static Logger LOGGER = Logger.getLogger(GreetingResourceTest.class.getName());

    @Deployment(testable = false)
    public static WebArchive createDeployment() {
        return ShrinkWrap.create(WebArchive.class)
                .addClass(GreetingMessage.class)
                .addClass(GreetingService.class)
                .addClasses(GreetingResource.class, JaxrsActivator.class)
                // Enable CDI
                .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
    }

    @ArquillianResource
    private URL base;

    private Client client;

    @BeforeEach
    public void setup() {
        this.client = ClientBuilder.newClient();
        //removed the Jackson json provider registry, due to OpenLiberty 21.0.0.1 switched to use Resteasy.
    }

    @AfterEach
    public void teardown() {
        if (this.client != null) {
            this.client.close();
        }
    }

    @Test
    public void should_create_greeting() throws MalformedURLException {
        LOGGER.log(Level.INFO, " Running test:: GreetingResourceTest#should_create_greeting ... ");
        final WebTarget greetingTarget = client.target(new URL(base, "api/greeting/JakartaEE").toExternalForm());
        try (final Response greetingGetResponse = greetingTarget.request()
                .accept(MediaType.APPLICATION_JSON)
                .get()) {
            assertThat(greetingGetResponse.getStatus()).isEqualTo(200);
            assertThat(greetingGetResponse.readEntity(GreetingMessage.class).getMessage()).startsWith("Say Hello to JakartaEE");
        }
    }
}

In the above codes.

In the should_create_greeting method, it uses Restful WS Client API to shake hands with the Restful APIs. You should add an implementation of the Restful WS Client. At the moment, only jersey completed the transformation.

<!-- Jersey -->
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-sse</artifactId>
    <version>${jersey.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-binding</artifactId>
    <version>${jersey.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.inject</groupId>
    <artifactId>jersey-hk2</artifactId>
    <version>${jersey.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.core</groupId>
    <artifactId>jersey-client</artifactId>
    <version>${jersey.version}</version>
    <scope>test</scope>
</dependency>

In the above code, there are some dependencies added.

Before configuring the Arquillian Glassfish container support, please make sure you have added Arquillian Jarkarta EE 9 and JUnit 5 dependencies.

Configuring Glassfish Managed Container Adapter

Add arquillian-glassfish-managed-6 dependency into your project.

<dependency>
    <groupId>org.jboss.arquillian.container</groupId>
    <artifactId>arquillian-glassfish-managed-6</artifactId>
    <version>${arquillian-glassfish6.version}</version>
    <scope>test</scope>
</dependency>

Create a container configuration in the arquillian.xml file.

<container qualifier="arq-glassfish-managed">
    <configuration>
        <property name="allowConnectingToRunningServer">false</property>
        <!--            <property name="glassFishHome">target/${glassfish.home}</property>-->
        <property name="adminHost">localhost</property>
        <property name="adminPort">4848</property>
        <property name="enableDerby">${enableDerby:true}</property>
        <property name="outputToConsole">true</property>
    </configuration>
</container>

You can define a glassFishHome property in the arquillian.xml file to specify the location of the existing Glassfish server in your local system.

Alternatively, to get a clean environment to run your tests every time, you can configure a Dependency Maven Plugin to download a copy of Glassfish, and use it to run your tests. This is a great option to run the tests continuously in your CI servers.

 <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-dependency-plugin</artifactId>
     <version>${maven-dependency-plugin.version}</version>
     <executions>
         <execution>
             <id>unpack</id>
             <phase>pre-integration-test</phase>
             <goals>
                 <goal>unpack</goal>
             </goals>
             <configuration>
                 <artifactItems>
                     <artifactItem>
                         <groupId>org.glassfish.main.distributions</groupId>
                         <artifactId>glassfish</artifactId>
                         <version>${glassfish.version}</version>
                         <type>zip</type>
                         <overWrite>false</overWrite>
                         <outputDirectory>${project.build.directory}</outputDirectory>
                     </artifactItem>
                 </artifactItems>
             </configuration>
         </execution>
     </executions>
</plugin>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-failsafe-plugin</artifactId>
    <version>${maven-failsafe-plugin.version}</version>
    <configuration>
        <environmentVariables>
            <GLASSFISH_HOME>${project.build.directory}/glassfish6</GLASSFISH_HOME>
        </environmentVariables>
    </configuration>
</plugin>

Execute the following command to run the tests against a Glassfish container that managed by Arquillian.

mvn clean verify -Parq-glassfish-managed

In the managed mode, Arquillian is responsible for starting and stopping the Glassfish container.

Configuring Glassfish Remote Container Adapter

With Arquillian Glassfish remote container, you can run the tests against a running Glassfish server, esp. it is running on a different server.

Adding the following arquillian-glassfish-remote-6 dependency instead.

<dependency>
    <groupId>org.jboss.arquillian.container</groupId>
    <artifactId>arquillian-glassfish-remote-6</artifactId>
    <version>${arquillian-glassfish6.version}</version>
    <scope>test</scope>
</dependency>
// the jersey client depdenceies are omitted.

And add a container section in the arquillian.xml file for this remote container, and configure the adminHost adminPort, adminUser , adminPassword if they are different from the default value.

 <container qualifier="glassfish-remote">
        <configuration>
            <!--Supported property names:
            [adminHttps,
            remoteServerHttpPort,
            libraries,
            type,
            remoteServerAddress,
            target,
            retries,
            remoteServerAdminPort,
            remoteServerAdminHttps,
            adminUser,
            authorisation,
            waitTimeMs,
            adminPort,
            properties,
            adminPassword,
            adminHost]-->
            <property name="adminHost">localhost</property>
            <property name="adminPort">4848</property>
            <property name="adminUser">admin</property>
            <!-- if https is enabled via `asadmin enable-secure-admin` on a remote server -->
            <!-- <property name="adminHttps">true</property>-->
            <!-- if admin password is changed via `asadmin change-admin-password` -->
            <!--<property name="adminPassword">adminadmin</property>-->
            <!-- default is empty -->
            <property name="adminPassword"></property>
        </configuration>
    </container>

Before executing the tests, make sure the target Glassfish server is running.

Execute the following command to run tests against the running Glassfish server.

mvn clean verfiy -Parq-glassfish-managed

Securing administration

By default, Glassfish does not set a password for admin user, you can change it by executing command asadmin change-admin-password on the Glassfish server side, do not forget to change the value of the adminPasswordproperty in the above arquillian.xml file.

To deploy applications on a remote Glassfish server, it is better to enable secure connections on the remote Glassfish server. Execute asadmin enable-secure-admin on Glassfish side to enable secure connections. Correspondingly, set the adminHttps to true in the arquillian.xml file.

Once the adminHttps is set, when running the tests, you could get a SSL certification related exception, the reason is the client JVM can not recognize the certificate used in the Glassfish server. Try to follow the following steps to to overcome this barrier.

Firstly, export the cert from [Glassfish install dir]/glassfish/domains/domain1/config/keystore.jks using keytooltools which is shipped with JDK.

keytool -export -alias default -file testwlp.crt -keystore [Glassfish install dir]/glassfish/domains/domain1/config/keystore.jks

And import it into the JVM you are using to run the tests.

keytool -import -trustcacerts -keystore ${JAVA_HOME}/jre/lib/security/cacerts -storepass changeit -alias testwlp -file testwlp.crt -noprompt

Now run the tests again, the certificate exception should be disappeared.

Grab a copy of the source codes from my Github, and exploring them yourself.