WildFly Swarm Get Start Tips
System Properties
swarm.debug.bootstrap
Add -Dswarm.debug.bootstrap=true
before start swarm Container will enable bootstrap modules related detailed log.
swarm.project.stage.file
Add -Dswarm.project.stage.file=/path/to/stage-file
before start swarm Container will use a pre-configured stage file, more details about Project Stages refer to Configuration overlays using stage properties.
swarm.http.eager
Add -Dswarm.http.eager=true
to enable eagerly Open
swarm.node.id
Add -Dswarm.node.id={node id}
define the swarm node id, alternatively.
swarm.bind.address
Add -Dswarm.bind.address={ip addr}
to bind servers, defaults to 0.0.0.0
swarm.port.offset
Add -Dswarm.port.offset={number}
to set a global port adjustment, defaults to 0
swarm.http.port
Add -Dswarm.http.port={port}
to set he HTTP port to be used, defaults to 8080.
Develop Tips
How to enable more log
System properties with the prefix swarm.log.
can enable more log, eg: -Dswarm.log.org.wildfly.swarm=DEBUG
All available log levels are:
NONE
ERROR
WARN
INFO
DEBUG
TRACE
ALL
How to debug swarm jar
Add -agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=y
before run -swarm.jar
java -agentlib:jdwp=transport=dt_socket,address=8787,server=y,suspend=y -jar NAME-swarm.jar
Maven plugins in swarm
wildfly-swarm-fraction-plugin
A fraction in wildfly-swarm-fraction-plugin represent a maven assets, which consisted by groupId, artifactId and version. wildfly-swarm-fraction-plugin has defined several mojo goals, including:
- fraction-list - Used to generate fractions descriptors, refer to how fraction list works for details.
- process - Used to generate internal modules system, refer to how process works for details
how fraction-list works
If configu fraction plugin as below
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-fraction-plugin</artifactId>
<executions>
<execution>
<id>fraction-list</id>
<phase>generate-resources</phase>
<goals>
<goal>fraction-list</goal>
</goals>
</execution>
</executions>
</plugin>
then the plugin mainly do 2 apsects work:
Firstly, the plugin
- collect all dependencies which defined in dependencyManagement
- filter all dependencies which groupId start with
org.wildfly.swarm
- convert all dependencies to MavenProjects
- filter all MavenProjects which project has defined any of these 3 properties(
swarm.fraction.stability
,swarm.fraction.tags
,swarm.fraction.internal
). - convert all MavenProjects to fractions and keep in a map(groupId:artifactId -> fraction)
- create a org.wildfly.swarm, container fraction, and put it to map, and set all fractions dependent on container fraction.
Secondly, generate fractions descriptors
- generate a
fraction-list.txt
under classspath, a example line infraction-list.txt
:
org.wildfly.swarm:jaxrs:2016.7-SNAPSHOT = org.wildfly.swarm:ee:2016.7-SNAPSHOT, org.wildfly.swarm:request-controller:2016.7-SNAPSHOT, org.wildfly.swarm:security:2016.7-SNAPSHOT, org.wildfly.swarm:naming:2016.7-SNAPSHOT, org.wildfly.swarm:undertow:2016.7-SNAPSHOT, org.wildfly.swarm:io:2016.7-SNAPSHOT, org.wildfly.swarm:logging:2016.7-SNAPSHOT, org.wildfly.swarm:container:2016.7-SNAPSHOT
org.wildfly.swarm:connector:2016.7-SNAPSHOT = org.wildfly.swarm:container:2016.7-SNAPSHOT
NOTE:
fraction-list.txt
contain all fractions and it’s depdencies, in above,jaxrs
depend onee
,request-controller
,security
,naming
,undertow
,io
,logging
,container
. andconnector
only depend oncontainer
.
- generate a
fraction-list.json
under classpath, a example line infraction-list.json
:
{
"groupId" : "org.wildfly.swarm",
"artifactId" : "jaxrs",
"version" : "2016.7-SNAPSHOT",
"name" : "JAX-RS",
"description" : "RESTful Web Services with RESTEasy",
"tags" : "JavaEE,Web",
"internal" : false,
"stabilityIndex" : 3,
"stabilityDescription" : "stable"
},
{
"groupId" : "org.wildfly.swarm",
"artifactId" : "connector",
"version" : "2016.7-SNAPSHOT",
"name" : "Connector",
"description" : "Connector",
"tags" : "",
"internal" : true,
"stabilityIndex" : 3,
"stabilityDescription" : "stable"
}
NOTE:
fraction-list.json
contains all fractions, as above arejaxrs
andconnector
fractions.
- generate a
fraction-list.js
under classpath, this file only contain one line, as below
fractionList = [{"groupId":"org.wildfly.swarm","artifactId":"jaxrs","version":"2016.7-SNAPSHOT","name" :"JAX-RS","description":"RESTful Web Services with RESTEasy","tags":"JavaEE,Web","internal":false,"stabilityIndex":3,"stabilityDescription":"stable"},{"groupId":"org.wildfly.swarm","artifactId":"connector","version":"2016.7-SNAPSHOT" ,"name":"Connector","description":"Connector","tags":"","internal":true,"stabilityIndex":3,"stabilityDescription":"stable"}]
NOTE: fractionList in
fraction-list.js
contains all fractions, in above only containjaxrs
andconnector
fractions.
how process works
If configu fraction plugin as below
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-fraction-plugin</artifactId>
<executions>
<execution>
<id>process</id>
<phase>process-classes</phase>
<goals>
<goal>process</goal>
</goals>
</execution>
</executions>
</plugin>
then the process task do the following:
1. Generate modules
This step against on compiled project’s source code, usually under target/classes
path, these code are categorized by path and add into one module with 3 slots, in other words, in this section, 3 module.xml will generate
- main - the parent follder of a *Fraction.java, eg,
org.wildfly.swarm.teiid
- api - under the main module
- runtime - under the main module
NOTE: This step depend on a
module.conf
file which under project base directory. In this file, every line define a module, eg,org.jboss.teiid
. All this lines of modules be added as new created modules’ dependencies.
An example of generated module.xml
- target/classes/modules/org/wildfly/swarm/teiid/main/module.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<module xmlns="urn:jboss:module:1.5" name="org.wildfly.swarm.teiid" slot="main">
<dependencies>
<system export="true">
<paths>
<path name="org/wildfly/swarm/config"/>
<path name="org/wildfly/swarm/teiid/internal"/>
<path name="org/wildfly/swarm/teiid"/>
</paths>
</system>
<module export="true" name="org.wildfly.swarm.teiid" services="export" slot="api"/>
</dependencies>
</module>
- target/classes/modules/org/wildfly/swarm/teiid/api/module.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<module xmlns="urn:jboss:module:1.5" name="org.wildfly.swarm.teiid" slot="api">
<resources>
<artifact name="org.wildfly.swarm:teiid:2016.7-SNAPSHOT">
<filter>
<include-set>
<path name="org/wildfly/swarm/config"/>
<path name="org/wildfly/swarm/teiid/internal"/>
<path name="org/wildfly/swarm/teiid"/>
</include-set>
<exclude-set/>
</filter>
</artifact>
</resources>
<dependencies>
<module name="org.wildfly.swarm.container"/>
<module name="org.jboss.teiid" slot="main"/>
</dependencies>
</module>
- target/classes/modules/org/wildfly/swarm/teiid/runtime/module.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<module xmlns="urn:jboss:module:1.5" name="org.wildfly.swarm.teiid" slot="runtime">
<resources>
<artifact name="org.wildfly.swarm:teiid:2016.7-SNAPSHOT">
<filter>
<exclude-set>
<path name="org/wildfly/swarm/config"/>
<path name="org/wildfly/swarm/teiid/internal"/>
<path name="org/wildfly/swarm/teiid"/>
</exclude-set>
</filter>
</artifact>
</resources>
<dependencies>
<module name="org.wildfly.swarm.teiid" slot="main"/>
<module name="org.wildfly.swarm.bootstrap" optional="true"/>
<module name="org.wildfly.swarm.container" slot="runtime"/>
<module name="org.jboss.teiid" slot="main"/>
</dependencies>
</module>
2. create bootstrap conf
Set up bootstrap means create a wildfly-swarm-bootstrap.conf
file under classpath, which contain the bootstrap module name, there are 3 ways to do this:
- Pre-packaged
wildfly-swarm-bootstrap.conf
file undersrc/main/resources
- Use system proeprties
swarm.fraction.bootstrap
define the bootstrap module name, eg-Dswarm.fraction.bootstrap=org.wildfly.swarm.teiid
- Walk through src, if file path end with
Fraction.java
, then this java’s package as bootstrap module name, egorg.wildfly.swarm.teiid.TeiidFraction
referenced bootstrap module name isorg.wildfly.swarm.teiid
NOTE: Both step 2 and 3 will create a
wildfly-swarm-bootstrap.conf
under classpath, which comtain the bootstrap module name.
3. Generate Dependencies
Firstly, collect the dependencies in provided-dependencies.txt
.
The dependencies can be defined in provided-dependencies.txt
filem which under src/main/resources/
, which define the provided dependencies. Each line in provided-dependencies.txt
represent a dependency, a format like
An example of provided-dependencies.txt
:
org.wildfly.swarm:config-api
org.wildfly.swarm:config-api-runtime
Secondly, dump the collected dependencies to META-INF/wildfly-swarm-classpath.conf
.
An example of META-INF/wildfly-swarm-classpath.conf
:
1 package(org.wildfly.swarm.container) replace(org.wildfly.swarm.container:main)
2 package(org.wildfly.swarm.container) replace(org.wildfly.swarm.container:runtime)
3
4 maven(org.wildfly.swarm:config-api) remove
5 maven(org.wildfly.swarm:config-api-runtime) remove
6 maven(org.ow2.asm:asm-all) remove
7 maven(org.jboss.shrinkwrap:shrinkwrap-api) remove
8 maven(org.jboss.shrinkwrap:shrinkwrap-spi) remove
9 maven(org.jboss.shrinkwrap:shrinkwrap-impl-base) remove
10 maven(org.jboss.shrinkwrap.descriptors:shrinkwrap-descriptors-spi) remove
11 maven(org.jboss.shrinkwrap.descriptors:shrinkwrap-descriptors-api-base) remove
12 maven(org.jboss.shrinkwrap.descriptors:shrinkwrap-descriptors-api-jboss) remove
13 maven(org.jboss.shrinkwrap.descriptors:shrinkwrap-descriptors-api-javaee) remove
14 maven(org.jboss.shrinkwrap.descriptors:shrinkwrap-descriptors-impl-base) remove
15 maven(org.jboss.shrinkwrap.descriptors:shrinkwrap-descriptors-impl-jboss) remove
16 maven(org.jboss.shrinkwrap.descriptors:shrinkwrap-descriptors-impl-javaee) remove
17 maven(org.yaml:snakeyaml) remove
18 maven(org.wildfly:wildfly-naming) remove
19 maven(org.ow2.asm:asm-all) remove
20 maven(org.yaml:snakeyaml) remove
4. Filter Modules
The Sequence diagram as below
4- loadRewriteRules(): This step depend on module-rewrite.conf under base dir
5- walkProjectModules()
1) requiredModules - keep all module's name both from class path and generated
2) availableModules - keep all modules's dependency module's name both from class path and generated
3) Both module.xml contained under resources/modules and target/classes/modules will be analyzed, each module's name add to availableModules, each module's dependencies module as requiredModules
7- walkDependencyModules(): find all dependencies' modules definition, add each of them as availableModules
11- locateFillModules(): filter requiredModules which not exist in availableModules,
12- addFillModules()
1) find the wildfly-feature-pack.xml, process feature pack xml
2) addFillModule, generate modules to class path, analyze module xml, add module's name add to availableModules, it's dependencies module as requiredModules
3) addResources, if module define resources, like deployment, etc, generate to classpath
This steps including the following procedures:
- Load module rewrite rules
This step depend on module-rewrite.conf
under base dir, which defines module rewrite rules. An example of module-rewrite.conf
:
module: org.jboss.as.server
optional: org.jboss.as.domain-http-interface
- Walk Project Modules
Modules can be pre configured and packaged under resources/modules
, walk Project Modules will load each module as a availableModules
and each module’s dependencies module as requiredModules
.
- Walk Dependency Modules
Walk through all project dependencies, if a jar dependency has define the modules, then get all these modules as availableModules
.
NOTE:
org.wildfly.swarm:container
has defined lots of modules(more than 50), which supply the base evn of running wildfly self container, completed list refer to modules list.
- Index Potential Modules
Walk through all project dependencies, if a feature pack zip dependency has define, then index all zip file, if there are any modules defined, the add it as potentialModules
<dependency>
<groupId>org.wildfly.core</groupId>
<artifactId>wildfly-core-feature-pack</artifactId>
<type>zip</type>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-servlet-feature-pack</artifactId>
<type>zip</type>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.teiid</groupId>
<artifactId>wildfly-teiid-feature-pack</artifactId>
<type>zip</type>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
NOTE: so far, there are 3 kinds of modules:
availableModules
,requiredModules
,potentialModules
.
- locate Fill Modules
5. execute Jandexer
wildfly-swarm-plugin
The wildfly-swarm-plugin use a BuildTool
to a build swarm jar, the BuildTool
mainly has 2 aspects task:
Firstly, initialization.
- init projectArtifact - create a
projectAsset
base on project’s groupId, artifactId, version, etc. - init fractionList - the fractions predefined by
fraction-list
project, which contains all wildfly-swarm fractions - init properties - properties passed from mvn build
- set main class - main class name come from plugin config
- set bundleDependencies - bundleDependencies come from plugin config
- set executable - executable come from plugin config
- set executableScript - executableScript come from plugin config
- set fractionDetectMode - fractionDetectMode come from plugin config, default value is
when_missing
- init ArtifactResolvingHelper - a MavenArtifactResolvingHelper be created
- set logger - BuildTool.SimpleLogger be create
- set additionalFractions - additionalFractions come from plugin config, BuildTool’s fraction method be used to set additionalFractions
- set dependency - any dependency of project will be set to BuildTool
- set Resources - any resource of project will be set to BuildTool
- set additionalModules - additionalModules come from plugin config
Secondly, build the -swarm.jar
.
- analyze Dependencies - scan modules dependencies, scan bootstrap dependencies, analyze module dependencies, analyze provided dependencies
- add Wildfly Swarm Bootstrap Jar - move swarm bootstrap.jar to target archive.
- add WildFly Bootstrap Conf -
META-INF/wildfly-swarm-bootstrap.conf
- add Manifest - mainClass be used
- add WildFly Swarm Properties -
wildfly-swarm.properties
- add WildFly Swarm Application Conf -
META-INF/wildfly-swarm-application.conf
- add WildFly Swarm Dependencies Conf -
META-INF/wildfly-swarm-dependencies.conf
- add Additional Modules
- add Project Asset
- populate UberJar Maven Repository
A traditional config:
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
<version>2016.7-SNAPSHOT</version>
<configuration>
<mainClass>org.teiid.test.swarm.Main</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
A simplest -swarm.jar
In this section, a project with a simple Main class and no dependency, then we focus on how -swam.jar be build.
WildFly-Swarm container
A WildFly-Swarm container is the topest interface for Micro-Service WildFly Swarm, it use to start a simple JBoss MSC container, a tradition usag is
Swarm swarm = new Swarm();
swarm.start();
Fractions can be add to Container before container start, or Archives be deloyed after container start.
A WildFly-Swarm container represented by org.wildfly.swarm.container.Container
, it contains the following private fileds represents the fractions
, socketBindingGroups
, socketBindings
, server
, deployer
, etc.
Pre Container construction - bootstrap
java -jar X-swarm.jar
can start the lightweight container and fragment, how does this implemented? If look at the META-INF/MANIFEST.MF
uder the unberjar,
Manifest-Version: 1.0
Main-Class: org.wildfly.swarm.bootstrap.Main
WildFly-Swarm-Main-Class: org.teiid.test.swarm.Main
NOTE:
org.wildfly.swarm.bootstrap.Main
is the entrence of run uberjar, this Main be run before Container construction.WildFly-Swarm-Main-Class
come from wildfly-swarm-plugin’s configuration.
The bootstrap Main first set boot.module.loader
, then invoke the WildFly-Swarm-Main-Class.
The getMainClass()
code looks
String mainClassName = getMainClassName();
Module module = Module.getBootModuleLoader().loadModule(ModuleIdentifier.create("swarm.application"));
module.getClassLoader().loadClass(mainClassName);
NOTE: How to set JBoss modules’s BootModuleLoader? - system properties boot.module.loader can be used set BootModuleLoader, for example,
System.setProperty("boot.module.loader", BootModuleLoader.class.getName())
.
BootModuleLoader
Pre Container construction bootstrap mainly extended the jboss modules, made jboss modules can load zip file’s internal modules, this due to the implementation of org.wildfly.swarm.bootstrap.modules.BootModuleLoader
.
The boot module loader is the initial loader that is established by the module framework. It typically is based off of the environmental module path unless it is overridden by specifying a different class name for the boot.module.loader
system property.`
BootModuleLoader defines a series of Module Finders:
public class BootModuleLoader extends ModuleLoader {
public BootModuleLoader() throws IOException {
super(new ModuleFinder[]{
new BootstrapClasspathModuleFinder(),
new BootstrapModuleFinder(),
new ClasspathModuleFinder(),
new ContainerModuleFinder(),
new ApplicationModuleFinder(),
new FlattishApplicationModuleFinder(),
});
}
}
As UML diagram:
- BootstrapClasspathModuleFinder - Used only for loading dependencies of org.wildfly.bootstrap:main from its own jar. The classpath modules in bootstrap including:
javax.api
,javax.sql.api
,org.jboss.msc
, etc - BootstrapModuleFinder - Module-finder used only for loading the first set of jars when run in an fat-jar scenario.
- ClasspathModuleFinder
- BootstrapModuleFinder
- ApplicationModuleFinder
- FlattishApplicationModuleFinder
Container construction
As figure, Container construction mainly do the following:
- Check the ‘swarm.debug.bootstrap’ system property, if true enable bootstrap debug
- init ‘userComponentClasses’, ‘explicitlyInstalledFractions’, ‘stageConfig’, ‘xmlConfig’, ‘stageConfigUrl’
- init main method ‘args’
- JBoss logger be initialized, used to as logging system for container
- create ShrinkWrap Domain, a domain encapsulates a shared Configuration to be used by all Archives
- configure command-line base on passed arguments,’Container(boolean debugBootstrap, String… args)’, args are command-line arguments
- If stageFile not null, load stage configuration
Once Swarm be constructed, usually, it’s start method be invoked, refer below section for more details.
Swarm start
The main procedure of Swarm start including:
- Swarm
RuntimeServer
as a bean instance be registered in Weld SE Container, all extentions be inject via Weld SE Container - untimeServer statr invoke SelfContainedContainer’s start() method
- MSC container start and install services.
bootstrapOperations initilization
JBoss SelfContainedContainer start
A sample code to start MSC and install services via bootstrapOptions
import org.jboss.as.server.SelfContainedContainer;
import org.jboss.dmr.ModelNode;
import org.jboss.msc.service.ServiceActivator;
import org.jboss.msc.service.ServiceContainer;
SelfContainedContainer container = new SelfContainedContainer();
List<ModelNode> bootstrapOperations = new ArrayList<>();
SimpleContentProvider contentProvider = new SimpleContentProvider();
List<ServiceActivator> activators = new ArrayList<>();
ServiceContainer serviceContainer = container.start(bootstrapOperations, contentProvider, activators);