1. Abstract
The WildFly JUnit Extension module (wildfly-junit-extension) provides the core testing framework with automatic server
lifecycle management, deployment handling, and resource injection. It integrates with JUnit to provide a seamless
testing experience for WildFly-based applications.
2. Overview
The extension automatically manages:
-
Server Lifecycle - Starts WildFly once before tests, stops after completion
-
Deployments - Manages per-test deployments and undeployments
-
Resource Injection - Injects server resources into test fields and parameters
-
Domain Mode - Supports testing on domain controllers
-
Manual Control - Optional manual server lifecycle management
3. Getting Started
3.1. Maven Dependency
Add the extension module to your test dependencies:
<dependency>
<groupId>org.wildfly.testing</groupId>
<artifactId>wildfly-junit-extension</artifactId>
<version>${version.org.wildfly.testing}</version>
<scope>test</scope>
</dependency>
3.2. Requirements
-
Java 17 or later
-
JUnit 6.0 or later
-
WildFly 27 or later
-
WildFly installation accessible via
jboss.homeproperty orJBOSS_HOMEenvironment variable
3.3. Basic Example
@WildFlyTest
public class HelloWorldTest {
@GenerateDeployment
public static void createDeployment(final WebArchive deployment) {
deployment.addClass(HelloServlet.class);
}
@Test
public void testHello(@ServerResource URI uri) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(uri.resolve("hello"))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
Assertions.assertEquals(200, response.statusCode());
}
}
The @WildFlyTest annotation marks a test class that requires a WildFly server.
@WildFlyTest
public class MyTest {
@Test
public void test() {
// WildFly server is automatically started
}
}
3.4. Test Tags
Tests are automatically tagged to allow selective execution:
-
@WildFlyTest- tagged withwildfly-standalone -
@WildFlyDomainTest- tagged withwildfly-domain -
@ManualMode- tagged withwildfly-manual
Examples:
# Run only standalone tests
mvn test -Dgroups=wildfly-standalone
# Run only domain tests
mvn test -Dgroups=wildfly-domain
# Run only manual mode tests
mvn test -Dgroups=wildfly-manual
# Run standalone automatic mode tests (not manual)
mvn test -Dgroups=wildfly-standalone -DexcludedGroups=wildfly-manual
# Run all non-domain tests
mvn test -DexcludedGroups=wildfly-domain
4. Creating Deployments
4.1. @DeploymentProducer
Use @DeploymentProducer to create a deployment that returns an archive:
@WildFlyTest
public class DeploymentTest {
@DeploymentProducer
public static WebArchive deployment() {
return ShrinkWrap.create(WebArchive.class, "test.war")
.addClass(TestServlet.class)
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}
@Test
public void test() {
// Test against deployed application
}
}
4.2. @GenerateDeployment
Use @GenerateDeployment to create an empty archive which is inferred from the argument type:
@WildFlyTest
public class GenerateTest {
@GenerateDeployment
public static void generate(final WebArchive war) {
war.addClass(TestServlet.class)
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}
@Test
public void test() {
// Test implementation
}
}
The name for the deployment will be the name of the test class, Class.getSimpleName(), and the appropriate extension.
In the above example, the deployment name would be GenerateTest.war.
A test can have either @GenerateDeployment or @DeploymentProducer, but not both.
|
5. Resource Injection
5.1. @ServerResource
Inject server resources into test fields or parameters:
@WildFlyTest
public class ResourceTest {
@ServerResource
private ServerManager serverManager;
@ServerResource
private URI uri;
@Test
public void test() {
Assertions.assertTrue(serverManager.isRunning());
Assertions.assertNotNull(uri);
}
}
5.2. Available Resources
-
org.wildfly.plugin.tools.server.ServerManager- Server management interface -
java.net.URI- HTTP URI to deployed application -
org.jboss.as.controller.client.ModelControllerClient- A client which can talk to the management endpoint of the server -
org.wildfly.plugin.tools.DeploymentManager- A deployment manager to deploy archives to the server
When injecting a ServerManager the start() and shutdown() methods will throw an exception if the test
is not a @ManualMode[@ManualMode] test.
|
6. Server Lifecycle
6.1. Automatic Mode (Default)
By default, the extension:
-
Starts WildFly before the first test
-
Keeps it running for all tests
-
Deploys/undeploys applications per test
-
Stops the server after all tests complete
6.2. @ManualMode
Take control of the server lifecycle:
@WildFlyTest
@ManualMode
public class ManualTest {
@ServerResource
private static ServerManager serverManager; // Must be static for @BeforeAll/@AfterAll
@BeforeAll
static void startServer() {
serverManager.start();
}
@AfterAll
static void stopServer() {
serverManager.shutdown();
}
@Test
public void test() {
// Test with running server
Assertions.assertTrue(serverManager.isRunning());
}
}
7. Domain Mode
Test deployments on a domain controller:
@WildFlyDomainTest
public class DomainTest {
@DeploymentProducer
@ServerGroup("main-server-group")
public static WebArchive deployment() {
return ShrinkWrap.create(WebArchive.class)
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}
@ServerResource
@DomainServer("server-one")
private URI uri;
@Test
public void test() {
// Test against domain deployment
}
}
7.1. Domain Mode Requirements
To use domain mode testing:
-
Know your server group name - Check
domain.xmlfor available server groups:<server-groups> <server-group name="main-server-group" profile="full"> <!-- ... --> </server-group> </server-groups> -
Know your server names - Check
host.xmlfor servers in the group:<servers> <server name="server-one" group="main-server-group"> <!-- ... --> </server> </servers> -
Use the correct annotations:
-
@WildFlyDomainTeston the test class -
@ServerGroup("server-group-name")on the deployment method (you can specify multiple server groups:@ServerGroup({"group1", "group2"})) -
@DomainServer("server-name")on@ServerResourcefields to target specific servers
-
Domain tests are automatically tagged with @Tag("wildfly-domain"). You can use this to run domain tests separately: mvn test -Dgroups=wildfly-domain
|
8. ServerManager API
The ServerManager interface provides methods for controlling and querying the WildFly server:
8.1. Lifecycle Methods
// Start the server
serverManager.start();
// Check if server is running
boolean running = serverManager.isRunning();
// Shutdown the server
serverManager.shutdown();
// Kill the server process (forceful)
serverManager.kill();
8.2. Deployment Operations
// Deploy an archive
DeploymentResult result = serverManager.deploy(archive);
// Undeploy by name
serverManager.undeploy(deploymentName);
// Redeploy
serverManager.redeploy(archive);
8.3. Management Operations
Execute management operations using the WildFly management API:
// Read an attribute
ModelNode op = Operations.createReadAttributeOperation(
Operations.createAddress("subsystem", "logging"),
"add-logging-api-dependencies"
);
ModelNode result = serverManager.executeOperation(op);
// Write an attribute
op = Operations.createWriteAttributeOperation(
Operations.createAddress("system-property", "my.property"),
"value",
"my-value"
);
serverManager.executeOperation(op);
8.4. Server Control
// Reload the server
serverManager.reload();
// Wait for server to be ready
serverManager.waitFor(30, TimeUnit.SECONDS);
// Take a configuration snapshot
String snapshotName = serverManager.takeSnapshot();
| See the ServerManager JavaDoc for the complete API reference. |
This chapter covers all configuration options for WildFly JUnit Extension.
9. Configuration Properties Reference
| Property | Type | Description | Default |
|---|---|---|---|
|
Path |
WildFly installation directory |
|
|
Path |
Java Runtime Environment path |
Current JVM ( |
|
Path |
JBoss Modules path |
|
|
Integer (seconds) |
Server startup/shutdown timeout |
|
|
String |
HTTP protocol ( |
|
|
String |
HTTP host |
|
|
Integer |
HTTP/HTTPS port |
|
|
String |
Additional JVM arguments for WildFly |
None |
|
boolean |
An empty value or a value of |
|
|
int |
If |
|
|
int |
If |
|
10. System Properties
Configuration can be set via system properties or JUnit Platform configuration parameters.
10.1. Server Location
jboss.home-
The path to the WildFly installation directory. If not set, falls back to the
JBOSS_HOMEenvironment variable, thenjboss.home.dirproperty.mvn test -Djboss.home=/opt/wildfly
10.2. Java Runtime
wildfly.java.home-
Path to a different Java Runtime Environment. Defaults to the current JVM (
java.home).mvn test -Dwildfly.java.home=/usr/lib/jvm/java-21
10.3. Java Options
wildfly.java.opts-
Additional JVM arguments passed to the WildFly server process. Multiple arguments can be space-separated. Use quotes for arguments containing spaces or special characters.
# Single option mvn test -Dwildfly.java.opts="-Xmx1024m" # Multiple options mvn test -Dwildfly.java.opts="-Xmx1024m -XX:+UseG1GC" # Options with commas or complex values (use quotes) mvn test -Dwildfly.java.opts="\"-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8787\""
10.4. Module Path
wildfly.module.path-
Alternate module path for JBoss Modules. Defaults to
${jboss.home}/modules.mvn test -Dwildfly.module.path=/custom/modules
10.5. Timeouts
wildfly.timeout-
Timeout in seconds for server startup and shutdown operations. Default:
60.mvn test -Dwildfly.timeout=120
10.6. HTTP Configuration
wildfly.http.protocol-
Protocol for HTTP connections. Can be
httporhttps. Default:http.When set, the framework configures the WildFly server to listen on the corresponding port using the appropriate
jboss.http.portorjboss.https.portsystem property. wildfly.http.host-
Host for HTTP connections used in URI resolution. Default:
localhost. wildfly.http.port-
Port for HTTP connections. Default:
8080for HTTP,8443for HTTPS.The framework passes this to WildFly as
-Djboss.http.portor-Djboss.https.portdepending on the protocol.
# HTTP on custom port
mvn test -Dwildfly.http.port=8180
# HTTPS with default port
mvn test -Dwildfly.http.protocol=https
# HTTPS on custom port
mvn test -Dwildfly.http.protocol=https -Dwildfly.http.port=9443
11. JUnit Configuration
Properties can also be set in junit-platform.properties:
jboss.home=/opt/wildfly
wildfly.timeout=120
wildfly.http.port=8080
12. Maven Configuration
Configure properties in your pom.xml:
<properties>
<jboss.home>${project.build.directory}/wildfly</jboss.home>
<wildfly.timeout>120</wildfly.timeout>
</properties>
13. Configuration Examples
13.1. Local Development
For local development with a standard WildFly installation:
# src/test/resources/junit-platform.properties
jboss.home=/opt/wildfly-38.0.1.Final
wildfly.timeout=60
13.2. CI/CD Pipeline
For continuous integration with provisioned server:
<!-- pom.xml -->
<properties>
<jboss.home>${project.build.directory}/wildfly</jboss.home>
<wildfly.timeout>180</wildfly.timeout>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<jboss.home>${jboss.home}</jboss.home>
<wildfly.timeout>${wildfly.timeout}</wildfly.timeout>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
13.3. Custom Ports
When default ports are unavailable or testing with HTTPS:
# Custom HTTP port
mvn test -Dwildfly.http.port=8180
# HTTPS on custom port
mvn test -Dwildfly.http.protocol=https -Dwildfly.http.port=9443
Or in junit-platform.properties:
wildfly.http.protocol=https
wildfly.http.port=8443
13.4. Remote Debugging
Enable remote debugging of WildFly during tests:
mvn test -Dwildfly.debug
Then attach your IDE debugger to port 8787.
| The debug agent argument contains commas, so it must be quoted to prevent argument splitting. |
13.5. Different Java Version
Test with a specific Java version:
mvn test -Dwildfly.java.home=/usr/lib/jvm/java-21-openjdk
14. Test-Specific Configuration
Override configuration in individual tests using @TestPropertySource or similar JUnit mechanisms.
15. WildFly Provisioning
When using the wildfly-maven-plugin to provision a server:
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>provision</goal>
</goals>
<configuration>
<provisioning-dir>${project.build.directory}/wildfly</provisioning-dir>
<feature-packs>
<feature-pack>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ee-galleon-pack</artifactId>
<version>${version.wildfly}</version>
</feature-pack>
</feature-packs>
</configuration>
</execution>
</executions>
</plugin>
Set jboss.home to the provisioning directory:
<properties>
<jboss.home>${project.build.directory}/wildfly</jboss.home>
</properties>
This chapter covers advanced features and extensibility points in WildFly JUnit Extension.
16. Custom Server Configurations
16.1. Standalone Configuration
Implement StandaloneConfigurationFactory to customize standalone server configuration:
@MetaInfServices
public class CustomStandaloneConfig implements StandaloneConfigurationFactory {
@Override
public ServerConfiguration create(ExtensionContext context) {
return ServerConfiguration.builder()
.configFile("standalone-custom.xml")
.jvmArgs("-Xmx2g", "-XX:+UseG1GC")
.build();
}
}
16.2. Domain Configuration
Implement DomainConfigurationFactory for domain mode:
@MetaInfServices
public class CustomDomainConfig implements DomainConfigurationFactory {
@Override
public ServerConfiguration create(ExtensionContext context) {
return ServerConfiguration.builder()
.configFile("domain-custom.xml")
.hostConfigFile("host-custom.xml")
.build();
}
}
17. Server Management Operations
Execute management operations using the ServerManager:
@WildFlyTest
@ManualMode(true)
public class ManagementTest {
@ServerResource
private static ServerManager serverManager;
@Test
public void testManagementOperation() throws Exception {
// Read system property
ModelNode op = Operations.createReadAttributeOperation(
Operations.createAddress("system-property", "test.property"),
"value"
);
ModelNode result = serverManager.executeOperation(op);
Assertions.assertTrue(Operations.isSuccessfulOutcome(result));
// Write system property
op = Operations.createWriteAttributeOperation(
Operations.createAddress("system-property", "test.property"),
"value",
"newValue"
);
result = serverManager.executeOperation(op);
Assertions.assertTrue(Operations.isSuccessfulOutcome(result));
}
}
18. Taking Snapshots
Save and restore server configuration:
@WildFlyTest
@ManualMode(true)
public class SnapshotTest {
@ServerResource
private static ServerManager serverManager;
private static String restorePath;
@BeforeAll
static void snapshot() throws Exception {
restorePath = serverManager.takeSnapshot();
}
@AfterAll
static void restore() throws Exception {
if (restorePath != null) {
ModelNode op = Operations.createOperation("reload");
op.get("server-config").set(restorePath);
serverManager.executeReload(op);
serverManager.waitFor(30L, TimeUnit.SECONDS);
serverManager.executeOperation(Operations.createOperation("write-config"));
}
}
@Test
public void testWithConfigChanges() {
// Make configuration changes
// They will be reverted after test suite completes
}
}
19. Best Practices
19.1. Resource Management
-
Use
@ServerResourcewithstaticfields in@ManualMode(true)tests when managing server lifecycle in@BeforeAll/@AfterAll -
Close client resources properly in
@AfterEachor try-with-resources -
Take snapshots before making configuration changes
19.2. Performance
-
Minimize server restarts by using per-test deployments instead of server restarts
-
Use
@ManualModeonly when necessary -
Share server instances across test classes when possible
19.3. Test Organization
-
Group tests by deployment requirements
-
Use
@Tagannotations to categorize tests (e.g., domain tests, manual mode tests)-
@WildFlyTesthas a tag with the value "wildfly-standalone" -
@WildFlyDomainTesthas a tag with the value "wildfly-domain" -
@ManualModehas a tag with the value "wildfly-manual"
-
-
Keep test deployments small and focused
19.4. Debugging
Enable debug logging for the framework by setting the org.wildfly.testing logger to DEBUG/FINE level in your logging configuration.
The exact configuration depends on your logging framework (Java Util Logging, Log4j2, Logback, etc.).
Run tests with remote debugging:
mvn test -Dwildfly.debug
Appendix A: API Reference
For complete API documentation, see the JavaDoc API Documentation and WildFly Plugin Tools Documentation.
Appendix B: Related Documentation
-
WildFly JUnit API - Conditional test execution annotations
-
WildFly Testing Tools - Deployment and module utilities
-
Main Documentation - Complete testing tools documentation
-
Troubleshooting Guide - Extension-specific troubleshooting
-
JUnit Documentation - JUnit user guide
-
WildFly Project - WildFly documentation