You are on page 1of 168

WildFly

Swarm User's Guide

Table of Contents
Introduction 0
License 1
Getting Started 2
Introducing WildFly Swarm 2.1
Concepts and Terminology 2.1.1
System Requirements 2.2
Developing your first application 2.3
Maven pom.xml 2.3.1
Adding application code 2.3.2
Running the application 2.3.3
Using WildFly Swarm 3
Build System 3.1
Maven 3.1.1
Advanced 3.1.1.1
Gradle 3.1.2
Application Bootstrap 3.1.3
Container 3.1.3.1
Deployments using ShrinkWrap 3.1.3.2
Packaging Types 3.1.3.3
WAR 3.1.3.3.1
JAR 3.1.3.3.2
Configuration 3.1.4
System Properties 3.1.4.1
Command line arguments 3.1.4.2
Using the Java API 3.1.4.3
Project Stages 3.1.4.4
Using XML 3.1.4.5
Testing your application 3.1.5
Using Arquillian 3.1.5.1
Features (Fractions) 4

2
WildFly Swarm User's Guide

Logging 4.1
Logging 4.1.1
Logstash 4.1.2
FluentD 4.1.3
Data Access 4.2
JPA 4.2.1
Datasources 4.2.2
Flyway 4.2.3
NoSQL 4.2.4
REST/HTTP 4.3
JAX-RS 4.3.1
Swagger 4.3.2
Dependency Injection 4.4
Messaging 4.5
Web 4.6
JSF 4.6.1
Security 4.7
Security Realms 4.7.1
Single Sign On 4.7.2
Keycloak Server 4.7.3
Stability Patterns 4.8
Circuit Breaker 4.8.1
Reactive 4.9
Integration with Vert.x 4.9.1
Service Discovery 4.10
Multicast discovery 4.10.1
Integration with Consul 4.10.2
Javascript API 4.10.3
Transactions 4.11
JTA/JTS 4.11.1
STM 4.11.2
Spring 4.12
Management 4.13
Remote Access 4.13.1

3
WildFly Swarm User's Guide

Jolokia 4.13.2
Monitoring 4.14
Health Checks 4.14.1
Distributed Tracing 4.14.2
Clustering 4.15
JGroups 4.15.1
Infinispan 4.15.2
Tools 5
Forge Add-on 5.1
SwarmTool 5.2
Pre-built Servers 6
MicroProfile 6.1
Keycloak Server 6.2
Swagger UI 6.3
Management Console 6.4
Additional Reading 7
Getting Involved 8
Contributing to WildFly Swarm 8.1
Implementation Details 8.2
Fraction Authoring 8.3

4
WildFly Swarm User's Guide

WildFly Swarm User’s Guide

WildFly Swarm User’s Guide for 2017.11.0-SNAPSHOT

http://wildfly-swarm.io/

Introduction 5
WildFly Swarm User's Guide

License
WildFly Swarm itself is licensed under the Apache Licence, version 2.0.

This documentation is licensed under the Creative Commons - Attribution-ShareAlike,


version 4.0.

Apache License Version 2.0


Version 2.0, January 2004

http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by the copyright owner
that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all other entities that control,
are controlled by, or are under common control with that entity. For the purposes of this
definition, "control" means (i) the power, direct or indirect, to cause the direction or
management of such entity, whether by contract or otherwise, or (ii) ownership of fifty
percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such
entity.

"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted
by this License.

"Source" form shall mean the preferred form for making modifications, including but not
limited to software source code, documentation source, and configuration files.

"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included in or
attached to the work (an example is provided in the Appendix below).

License 6
WildFly Swarm User's Guide

"Derivative Works" shall mean any work, whether in Source or Object form, that is
based on (or derived from) the Work and for which the editorial revisions, annotations,
elaborations, or other modifications represent, as a whole, an original work of
authorship. For the purposes of this License, Derivative Works shall not include works
that remain separable from, or merely link (or bind by name) to the interfaces of, the
Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including the original version of the
Work and any modifications or additions to that Work or Derivative Works thereof, that is
intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by
an individual or Legal Entity authorized to submit on behalf of the copyright owner. For
the purposes of this definition, "submitted" means any form of electronic, verbal, or
written communication sent to the Licensor or its representatives, including but not
limited to communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for the
purpose of discussing and improving the Work, but excluding communication that is
conspicuously marked or otherwise designated in writing by the copyright owner as "Not
a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom
a Contribution has been received by Licensor and subsequently incorporated within the
Work.

2. Grant of Copyright License. Subject to the terms and conditions of this License, each
Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of this License, each
Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where such
license applies only to those patent claims licensable by such Contributor that are
necessarily infringed by their Contribution(s) alone or by combination of their
Contribution(s) with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a cross-claim or counterclaim in a
lawsuit) alleging that the Work or a Contribution incorporated within the Work
constitutes direct or contributory patent infringement, then any patent licenses granted
to You under this License for that Work shall terminate as of the date such litigation is
filed.

License 7
WildFly Swarm User's Guide

4. Redistribution. You may reproduce and distribute copies of the Work or Derivative
Works thereof in any medium, with or without modifications, and in Source or Object
form, provided that You meet the following conditions:

i. You must give any other recipients of the Work or Derivative Works a copy of this
License; and

ii. You must cause any modified files to carry prominent notices stating that You
changed the files; and

iii. You must retain, in the Source form of any Derivative Works that You distribute, all
copyright, patent, trademark, and attribution notices from the Source form of the
Work, excluding those notices that do not pertain to any part of the Derivative
Works; and

iv. If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the attribution
notices contained within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one of the following places:
within a NOTICE text file distributed as part of the Derivative Works; within the
Source form or documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and wherever such third-party
notices normally appear. The contents of the NOTICE file are for informational
purposes only and do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside or as an addendum to
the NOTICE text from the Work, provided that such additional attribution notices
cannot be construed as modifying the License.

You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution


intentionally submitted for inclusion in the Work by You to the Licensor shall be under
the terms and conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of any
separate license agreement you may have executed with Licensor regarding such
Contributions.

6. Trademarks. This License does not grant permission to use the trade names,
trademarks, service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and reproducing the

License 8
WildFly Swarm User's Guide

content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing,


Licensor provides the Work (and each Contributor provides its Contributions) on an "AS
IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
or implied, including, without limitation, any warranties or conditions of TITLE, NON-
INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
You are solely responsible for determining the appropriateness of using or redistributing
the Work and assume any risks associated with Your exercise of permissions under this
License.

8. Limitation of Liability. In no event and under no legal theory, whether in tort (including
negligence), contract, or otherwise, unless required by applicable law (such as
deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental, or
consequential damages of any character arising as a result of this License or out of the
use or inability to use the Work (including but not limited to damages for loss of
goodwill, work stoppage, computer failure or malfunction, or any and all other
commercial damages or losses), even if such Contributor has been advised of the
possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative


Works thereof, You may choose to offer, and charge a fee for, acceptance of support,
warranty, indemnity, or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only on Your own behalf
and on Your sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability incurred
by, or claims asserted against, such Contributor by reason of your accepting any such
warranty or additional liability.

END OF TERMS AND CONDITIONS

Creative Commons Attribution-ShareAlike 4.0


International Public License
By exercising the Licensed Rights (defined below), You accept and agree to be bound by the
terms and conditions of this Creative Commons Attribution-ShareAlike 4.0 International
Public License ("Public License"). To the extent this Public License may be interpreted as a
contract, You are granted the Licensed Rights in consideration of Your acceptance of these

License 9
WildFly Swarm User's Guide

terms and conditions, and the Licensor grants You such rights in consideration of benefits
the Licensor receives from making the Licensed Material available under these terms and
conditions.

Section 1 — Definitions.
1. Adapted Material means material subject to Copyright and Similar Rights that is derived
from or based upon the Licensed Material and in which the Licensed Material is
translated, altered, arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the Licensor. For purposes
of this Public License, where the Licensed Material is a musical work, performance, or
sound recording, Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.

2. Adapter’s License means the license You apply to Your Copyright and Similar Rights in
Your contributions to Adapted Material in accordance with the terms and conditions of
this Public License.

3. BY-SA Compatible License means a license listed at


creativecommons.org/compatiblelicenses, approved by Creative Commons as
essentially the equivalent of this Public License.

4. Copyright and Similar Rights means copyright and/or similar rights closely related to
copyright including, without limitation, performance, broadcast, sound recording, and
Sui Generis Database Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-
(2) are not Copyright and Similar Rights.

5. Effective Technological Measures means those measures that, in the absence of proper
authority, may not be circumvented under laws fulfilling obligations under Article 11 of
the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international
agreements.

6. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or
limitation to Copyright and Similar Rights that applies to Your use of the Licensed
Material.

7. License Elements means the license attributes listed in the name of a Creative
Commons Public License. The License Elements of this Public License are Attribution
and ShareAlike.

8. Licensed Material means the artistic or literary work, database, or other material to
which the Licensor applied this Public License.

License 10
WildFly Swarm User's Guide

9. Licensed Rights means the rights granted to You subject to the terms and conditions of
this Public License, which are limited to all Copyright and Similar Rights that apply to
Your use of the Licensed Material and that the Licensor has authority to license.

10. Licensor means the individual(s) or entity(ies) granting rights under this Public License.

11. Share means to provide material to the public by any means or process that requires
permission under the Licensed Rights, such as reproduction, public display, public
performance, distribution, dissemination, communication, or importation, and to make
material available to the public including in ways that members of the public may access
the material from a place and at a time individually chosen by them.

12. Sui Generis Database Rights means rights other than copyright resulting from Directive
96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.

13. You means the individual or entity exercising the Licensed Rights under this Public
License. Your has a corresponding meaning.

Section 2 — Scope.
1. License grant.

i. Subject to the terms and conditions of this Public License, the Licensor hereby
grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable
license to exercise the Licensed Rights in the Licensed Material to:

i. reproduce and Share the Licensed Material, in whole or in part; and

ii. produce, reproduce, and Share Adapted Material.

ii. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and
Limitations apply to Your use, this Public License does not apply, and You do not
need to comply with its terms and conditions.

iii. Term. The term of this Public License is specified in Section 6(a).

iv. Media and formats; technical modifications allowed. The Licensor authorizes You to
exercise the Licensed Rights in all media and formats whether now known or
hereafter created, and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or authority to forbid You from
making technical modifications necessary to exercise the Licensed Rights,

License 11
WildFly Swarm User's Guide

including technical modifications necessary to circumvent Effective Technological


Measures. For purposes of this Public License, simply making modifications
authorized by this Section 2(a) (4) never produces Adapted Material.

v. Downstream recipients.

i. Offer from the Licensor — Licensed Material. Every recipient of the Licensed


Material automatically receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this Public License.

ii. Additional offer from the Licensor — Adapted Material. Every recipient of


Adapted Material from You automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material under the conditions of
the Adapter’s License You apply.

iii. No downstream restrictions. You may not offer or impose any additional or
different terms or conditions on, or apply any Effective Technological Measures
to, the Licensed Material if doing so restricts exercise of the Licensed Rights
by any recipient of the Licensed Material.

vi. No endorsement. Nothing in this Public License constitutes or may be construed as


permission to assert or imply that You are, or that Your use of the Licensed Material
is, connected with, or sponsored, endorsed, or granted official status by, the
Licensor or others designated to receive attribution as provided in Section 3(a)(1)
(A)(i).

2. Other rights.

i. Moral rights, such as the right of integrity, are not licensed under this Public
License, nor are publicity, privacy, and/or other similar personality rights; however,
to the extent possible, the Licensor waives and/or agrees not to assert any such
rights held by the Licensor to the limited extent necessary to allow You to exercise
the Licensed Rights, but not otherwise.

ii. Patent and trademark rights are not licensed under this Public License.

iii. To the extent possible, the Licensor waives any right to collect royalties from You
for the exercise of the Licensed Rights, whether directly or through a collecting
society under any voluntary or waivable statutory or compulsory licensing scheme.
In all other cases the Licensor expressly reserves any right to collect such royalties.

Section 3 — License Conditions.


Your exercise of the Licensed Rights is expressly made subject to the following conditions.

License 12
WildFly Swarm User's Guide

1. Attribution.

i. If You Share the Licensed Material (including in modified form), You must:

i. retain the following if it is supplied by the Licensor with the Licensed Material:

i. identification of the creator(s) of the Licensed Material and any others


designated to receive attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if designated);

ii. a copyright notice;

iii. a notice that refers to this Public License;

iv. a notice that refers to the disclaimer of warranties;

v. a URI or hyperlink to the Licensed Material to the extent reasonably


practicable;

ii. indicate if You modified the Licensed Material and retain an indication of any
previous modifications; and

iii. indicate the Licensed Material is licensed under this Public License, and
include the text of, or the URI or hyperlink to, this Public License.

ii. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based
on the medium, means, and context in which You Share the Licensed Material. For
example, it may be reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required information.

iii. If requested by the Licensor, You must remove any of the information required by
Section 3(a)(1)(A) to the extent reasonably practicable.

2. ShareAlike. In addition to the conditions in Section 3(a), if You Share Adapted Material
You produce, the following conditions also apply.

i. The Adapter’s License You apply must be a Creative Commons license with the
same License Elements, this version or later, or a BY-SA Compatible License.

ii. You must include the text of, or the URI or hyperlink to, the Adapter’s License You
apply. You may satisfy this condition in any reasonable manner based on the
medium, means, and context in which You Share Adapted Material.

iii. You may not offer or impose any additional or different terms or conditions on, or
apply any Effective Technological Measures to, Adapted Material that restrict
exercise of the rights granted under the Adapter’s License You apply.

License 13
WildFly Swarm User's Guide

Section 4 — Sui Generis Database Rights.


Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of
the Licensed Material:

1. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse,
reproduce, and Share all or a substantial portion of the contents of the database;

2. if You include all or a substantial portion of the database contents in a database in


which You have Sui Generis Database Rights, then the database in which You have Sui
Generis Database Rights (but not its individual contents) is Adapted Material, including
for purposes of Section 3(b); and

3. You must comply with the conditions in Section 3(a) if You Share all or a substantial
portion of the contents of the database.

For the avoidance of doubt, this Section 4 supplements and does not replace Your
obligations under this Public License where the Licensed Rights include other Copyright and
Similar Rights.

Section 5 — Disclaimer of Warranties and Limitation of


Liability.
1. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.

2. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE TO


YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.

License 14
WildFly Swarm User's Guide

3. The disclaimer of warranties and limitation of liability provided above shall be


interpreted in a manner that, to the extent possible, most closely approximates an
absolute disclaimer and waiver of all liability.

Section 6 — Term and Termination.


1. This Public License applies for the term of the Copyright and Similar Rights licensed
here. However, if You fail to comply with this Public License, then Your rights under this
Public License terminate automatically.

2. Where Your right to use the Licensed Material has terminated under Section 6(a), it
reinstates:

i. automatically as of the date the violation is cured, provided it is cured within 30


days of Your discovery of the violation; or

ii. upon express reinstatement by the Licensor.

For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor
may have to seek remedies for Your violations of this Public License.

3. For the avoidance of doubt, the Licensor may also offer the Licensed Material under
separate terms or conditions or stop distributing the Licensed Material at any time;
however, doing so will not terminate this Public License.

4. Sections 1, 5, 6, 7, and 8 survive termination of this Public License.

Section 7 — Other Terms and Conditions.


1. The Licensor shall not be bound by any additional or different terms or conditions
communicated by You unless expressly agreed.

2. Any arrangements, understandings, or agreements regarding the Licensed Material not


stated herein are separate from and independent of the terms and conditions of this
Public License.

Section 8 — Interpretation.
1. For the avoidance of doubt, this Public License does not, and shall not be interpreted to,
reduce, limit, restrict, or impose conditions on any use of the Licensed Material that
could lawfully be made without permission under this Public License.

License 15
WildFly Swarm User's Guide

2. To the extent possible, if any provision of this Public License is deemed unenforceable,
it shall be automatically reformed to the minimum extent necessary to make it
enforceable. If the provision cannot be reformed, it shall be severed from this Public
License without affecting the enforceability of the remaining terms and conditions.

3. No term or condition of this Public License will be waived and no failure to comply
consented to unless expressly agreed to by the Licensor.

4. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or


waiver of, any privileges and immunities that apply to the Licensor or You, including
from the legal processes of any jurisdiction or authority.

Creative Commons is not a party to its public licenses. Notwithstanding, Creative


Commons may elect to apply one of its public licenses to material it publishes and in
those instances will be considered the "Licensor." Except for the limited purpose of
indicating that material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the use of the
trademark "Creative Commons" or any other trademark or logo of Creative
Commons without its prior written consent including, without limitation, in connection
with any unauthorized modifications to any of its public licenses or any other
arrangements, understandings, or agreements concerning use of licensed material.
For the avoidance of doubt, this paragraph does not form part of the public licenses.
Creative Commons may be contacted at creativecommons.org.

License 16
WildFly Swarm User's Guide

Basics of WildFly Swarm


WildFly Swarm is a project that has taken the WildFly Java Application Server 10.1.0.Final
and deconstructed it into fine-grained parts. WildFly Swarm then allows the selective
reconstitution of those parts back together with your application to allow building self-
contained executable "uberjars".

The point of these machinations is to support microservices while providing just-enough-


appserver to support whatever subset of traditional JavaEE APIs your application requires.

Additionally, WildFly Swarm brings other state-of-the-art components to your application,


integrating them seamlessly. This includes authentication/authorization from Keycloak,
client-side load-balancing via NetflixOSS Ribbon/Hystrix, and log aggregation using
Logstash.

Monolithic Application Server


When using a traditional monolithic application server, you first install the entire server, and
then deploy your application on top of it. In the case of microservices, you might end up with
an app-server that supports significantly more functionality than your application requires.
This can lead to an excess use of resources.

WildFly Swarm Uberjar


In the WildFly Swarm "uberjar" scenario, just enough application server is wrapped around
your application. Any un-needed parts are simply excluded. This results in a much smaller
usage of resources. Additionally, a single artifact is produced which can be shuffled along a
continuous deployment pipeline.

Introducing WildFly Swarm 17


WildFly Swarm User's Guide

Introducing WildFly Swarm 18


WildFly Swarm User's Guide

Common Concepts and terminology

Terminology
Fraction
A well-defined collection of capabilities to add. In some cases, a fraction maps directly to
a subsystem from WildFly, but in other cases (e.g. Jolokia) a fraction may involve
different functionality.

Uberjar
A self-contained, executable Java archive. In the case of WildFly Swarm uberjars, it is a
single .jar file containing your application, the portions of WildFly required to support
it, an internal Maven repository of dependencies, plus a shim to bootstrap it all.

Hollow Uberjar
A self-contained, executable Java archive that contains no application code. Somewhat
contradictory term. It is a container capable of deploying a particular type of application.

Default Deployment
The primary application artifact created by your Maven or Gradle build. This may be a
.war in many cases or a .jar , depending on the <packaging> in your pom.xml

Concepts and Terminology 19


WildFly Swarm User's Guide

System Requirements
At a bare minimum you need at least the following:

JDK 8

Maven 3.3.x

Java 8
WildFly leverages the Java 8 API’s, in particular lambdas and the collection enhancements.
Therefore the JDK 8 is required to build and run WildFly Swarm applications:

Download JDK 8

Maven 3.3.x
The Maven Plugin, that performs most of the work when packaging WildFly Swarm
applications requires at maven 3.3.x:

Download Apache Maven

If running WildFly Swarm from within the IDE, especially mvn wildfly-swarm:run ,
you will need to verify that the IDE uses this Maven version. Typically IDEs will be
running a Maven version less than 3.2.x which will cause issues

System Requirements 20
WildFly Swarm User's Guide

Developing your first application


Before we begin make sure to read section on System Requirements

In this example we build a simple restful HTTP endpoint using WildFly Swarm. The project
uses maven and follows a typical maven project layout:

|-pom.xml
|-src
|-main
|-java

As a first step, we look at the Maven POM

Generating a custom project


The most simple way to get going is to use the web based Project Generator. It allows you
to generate zip file with a full maven build structure, including example application code:

Head over to the Project Generator

Chose a JAX-RS fraction to begin with

Click Generate and save the resulting zip file on your machine

Unpack the zip and you’ve code everything we use in this simple example

Developing your first application 21


WildFly Swarm User's Guide

Maven POM
The most simple pom.xml to be used with WildFly Swarm looks like the following. As you
can see, it contains three notable elements:

A dependency management section

A declaration of the wildfly-swarm-plugin

A a reference to the Java EE 7 API’s

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


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instan
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"

<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>restful-endpoint</artifactId>
<name>Wildfly Swarm Example</name>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>

<properties>
<version.wildfly.swarm>2017.11.0-SNAPSHOT</version.wildfly.swarm>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>bom</artifactId>
<version>${version.wildfly.swarm}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<finalName>restful-endpoint</finalName>
<plugins>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
<version>${version.wildfly.swarm}</version>

Maven pom.xml 22
WildFly Swarm User's Guide

<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencies>
<!-- Java EE 7 dependency -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!-- Wildfly Swarm Fractions -->
</dependencies>
</project>

In the next step, we are going to write some code

Maven pom.xml 23
WildFly Swarm User's Guide

Adding application code


Our example should serve HTTP requests, hence we add a JAX-RS endpoint
implementation and a corresponding application context to define the context root: All of this
goes into src/main/java .

package com.example.rest;

import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;

@Path("/hello")
public class HelloWorldEndpoint {

@GET
@Produces("text/plain")
public Response doGet() {
return Response.ok("Hello from WildFly Swarm!").build();
}
}

And the application context looks like this:

package com.example.rest;

import javax.ws.rs.core.Application;
import javax.ws.rs.ApplicationPath;

@ApplicationPath("/rest")
public class RestApplication extends Application {
}

In the next step, we are going to package the application and run it.

Adding application code 24


WildFly Swarm User's Guide

Running the application


To run your application you can …​

either use the maven plugin to run your application

or package it as an uberJar and run it

Package and run using the maven plugin

Running the application 25


WildFly Swarm User's Guide

mvn wildfly-swarm:run

[INFO] ------------------------------------------------------------------------
[INFO] Building Wildfly Swarm Example 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[....]
[INFO] --- maven-war-plugin:2.2:war (default-war) @ restful-endpoint ---
[INFO] Packaging webapp
[INFO] Assembling webapp [restful-endpoint] in [/Users/hbraun/Downloads/restful-endpoint/target/restf
[INFO] Processing war project
[INFO] Webapp assembled in [28 msecs]
[INFO] Building war: /Users/hbraun/Downloads/restful-endpoint/target/restful-endpoint.war
[INFO]
[INFO] --- wildfly-swarm-plugin:2017.11.0-SNAPSHOT:package (default) @ restful-endpoint ---
[INFO] Scanning for needed WildFly Swarm fractions with mode: when_missing
[INFO] Detected fractions: jaxrs:2017.11.0-SNAPSHOT
[INFO] Adding fractions: container:2017.11.0-SNAPSHOT, ee:2017.11.0-SNAPSHOT, io:2017.11.

[....]

13:47:54,556 INFO [org.jboss.msc] (main) JBoss MSC version 1.2.6.Final


13:47:54,767 INFO [org.jboss.as] (MSC service thread 1-6) WFLYSRV0049: WildFly Core 2.0.
13:47:55,360 INFO [org.wildfly.extension.io] (ServerService Thread Pool -- 11) WFLYIO001: Worker
13:47:55,363 INFO [org.jboss.as.security] (ServerService Thread Pool -- 13) WFLYSEC0002: Activating
13:47:55,371 INFO [org.jboss.as.security] (MSC service thread 1-3) WFLYSEC0001: Current PicketBox ve
13:47:55,390 INFO [org.jboss.as.naming] (ServerService Thread Pool -- 15) WFLYNAM0001: Activating Na
13:47:55,392 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 12) WFLYUT0003: Und
13:47:55,392 INFO [org.wildfly.extension.undertow] (MSC service thread 1-1) WFLYUT0003: Undertow
13:47:55,423 INFO [org.jboss.as.naming] (MSC service thread 1-4) WFLYNAM0003: Starting Naming Servic
13:47:55,466 INFO [org.xnio] (MSC service thread 1-7) XNIO version 3.3.4.Final
13:47:55,476 INFO [org.xnio.nio] (MSC service thread 1-7) XNIO NIO Implementation Version
13:47:55,516 INFO [org.wildfly.extension.undertow] (MSC service thread 1-2) WFLYUT0012: Started serv
13:47:55,669 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly Core 2.0.
13:47:55,732 INFO [org.wildfly.extension.undertow] (MSC service thread 1-5) WFLYUT0006: Undertow HTT
13:47:56,517 INFO [org.wildfly.swarm.runtime.deployer] (main) deploying restful-endpoint.war
13:47:56,536 INFO [org.jboss.as.server.deployment] (MSC service thread 1-4) WFLYSRV0027: Starting de
13:47:57,262 INFO [org.wildfly.extension.undertow] (MSC service thread 1-2) WFLYUT0018: Host default
13:47:57,705 INFO [org.jboss.resteasy.resteasy_jaxrs.i18n] (ServerService Thread Pool --
13:47:57,741 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 3) WFLYUT0021: Regi
13:47:57,776 INFO [org.jboss.as.server] (main) WFLYSRV0010: Deployed "restful-endpoint.war"

Package and run with plain java


The uberJar is packaged by the maven plugin, when your execute the mvn package
command:

Running the application 26


WildFly Swarm User's Guide

mvn package

[INFO] ------------------------------------------------------------------------
[INFO] Building Wildfly Swarm Example 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[....]
[INFO] --- maven-war-plugin:2.2:war (default-war) @ restful-endpoint ---
[INFO] Packaging webapp
[INFO] Assembling webapp [restful-endpoint] in [/Users/hbraun/Downloads/restful-endpoint/target/restf
[INFO] Processing war project
[INFO] Webapp assembled in [26 msecs]
[INFO] Building war: /Users/hbraun/Downloads/restful-endpoint/target/restful-endpoint.war
[INFO]
[INFO] --- wildfly-swarm-plugin:2017.11.0-SNAPSHOT:package (default) @ restful-endpoint ---
[INFO] Scanning for needed WildFly Swarm fractions with mode: when_missing
[INFO] Detected fractions: jaxrs:2017.11.0-SNAPSHOT
[INFO] Adding fractions: container:2017.11.0-SNAPSHOT, ee:2017.11.0-SNAPSHOT, io:2017.11.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 7.779 s
[INFO] Finished at: 2016-07-07T13:38:26+02:00
[INFO] Final Memory: 54M/1161M
[INFO] ------------------------------------------------------------------------

The resulting uberJar carries the -swarm.jar suffix and can be found in the ./target
directory:

ll target/
-rw-r--r-- 1 hbraun staff 41943061 Jul 7 13:38 restful-endpoint-swarm.jar
-rw-r--r-- 1 hbraun staff 3591 Jul 7 13:38 restful-endpoint.war

Any -swarm.jar can simply be run using plain java:

Running the application 27


WildFly Swarm User's Guide

java -jar target/restful-endpoint-swarm.jar

13:45:29,211 INFO [org.jboss.msc] (main) JBoss MSC version 1.2.6.Final


13:45:29,433 INFO [org.jboss.as] (MSC service thread 1-7) WFLYSRV0049: WildFly Core 2.0.
13:45:30,074 INFO [org.wildfly.extension.io] (ServerService Thread Pool -- 10) WFLYIO001: Worker
13:45:30,085 INFO [org.jboss.as.naming] (ServerService Thread Pool -- 12) WFLYNAM0001: Activating Na
13:45:30,100 INFO [org.jboss.as.security] (ServerService Thread Pool -- 14) WFLYSEC0002: Activating
13:45:30,101 INFO [org.jboss.as.security] (MSC service thread 1-4) WFLYSEC0001: Current PicketBox ve
13:45:30,103 INFO [org.jboss.as.naming] (MSC service thread 1-3) WFLYNAM0003: Starting Naming Servic
13:45:30,149 INFO [org.wildfly.extension.undertow] (MSC service thread 1-7) WFLYUT0003: Undertow
13:45:30,149 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 15) WFLYUT0003: Und
13:45:30,198 INFO [org.xnio] (MSC service thread 1-6) XNIO version 3.3.4.Final
13:45:30,206 INFO [org.xnio.nio] (MSC service thread 1-6) XNIO NIO Implementation Version
13:45:30,262 INFO [org.wildfly.extension.undertow] (MSC service thread 1-3) WFLYUT0012: Started serv
13:45:30,399 INFO [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: WildFly Core 2.0.
13:45:30,456 INFO [org.wildfly.swarm.runtime.deployer] (main) deploying restful-endpoint.war
13:45:30,474 INFO [org.wildfly.extension.undertow] (MSC service thread 1-2) WFLYUT0006: Undertow HTT
13:45:30,485 INFO [org.jboss.as.server.deployment] (MSC service thread 1-1) WFLYSRV0027: Starting de
13:45:30,765 INFO [org.wildfly.extension.undertow] (MSC service thread 1-7) WFLYUT0018: Host default
13:45:31,152 INFO [org.jboss.resteasy.resteasy_jaxrs.i18n] (ServerService Thread Pool --
13:45:31,184 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 8) WFLYUT0021: Regi
13:45:31,211 INFO [org.jboss.as.server] (main) WFLYSRV0010: Deployed "restful-endpoint.war"

Testing the endpoint


To test it simply send an HTTP request:

curl http://localhost:8080/rest/hello

Hello from WildFly Swarm!

Congratulations!
You’ve just build your first application using WildFly Swarm.

Running the application 28


WildFly Swarm User's Guide

Maven Plugin
To assist in building WildFly Swarm projects, a Maven plugin is available. This plugin creates
the -swarm.jar uberjar which contains your application along with the necessary parts of
WildFly to support it.

Configuration
To use the plugin, you must add it to your pom.xml :

<build>
<plugins>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

Packaging your application


Default uberjar
To produce the myapp-swarm.jar , simply perform a typical mvn package command after
setting the package goal on the plugin:

mvn package

Hollow uberjar

Maven 29
WildFly Swarm User's Guide

To produce a hollow uberjar, the same mvn package method is used, but either set the
property -Dswarm.hollow=true or configure the plugin with <hollow>true</hollow> from
within your pom.xml .

A hollow uberjar will have the suffix of -hollow-swarm.jar and will not include the actual
application deployment. This may be useful if you are targetting layered Linux containers,
where you wish to place the runtime on a lower layer, and the more frequently changing
deployment on a higher layer.

If using the hollow functionality, the command-line arguments to the uberjar should point to
one or more deployments that should be used.

java -jar myruntime-hollowjar.jar myapp.war

An example of the hollow jar functionality may be seen in the MicroProfile standalone server.

Running your application


To execute your application, you may use the wildfly-swarm:run goal:

mvn wildfly-swarm:run

This will execute your application within the WildFly Swarm runtime directly from the Maven
command-line, and wait for it to exit.

Both of these goals will perform the same type of fraction detection as the package task if
no WildFly Swarm dependencies are found.

Fraction detection
If the plugin doesn’t detect any WildFly Swarm dependencies in your pom.xml , it will attempt
to auto-detect needed fractions by scanning the application. This is mostly useful for WAR-
based applications that you are migrating to WildFly Swarm - you only need to add the
plugin to your configuration, and not any other WildFly Swarm dependencies. You can
control fraction detection by setting <fractionDetectMode> . See the configuration options
below for more details.

Plugin Configuration Options

Maven 30
WildFly Swarm User's Guide

The plugin accepts the following options:

Name Property Description

If true, dependencies will be


included in the -swarm.jar.
bundleDependencies swarm.bundleDependencies Otherwise, they will be true
resolved from $M2_REPO or
the network at runtime.

A port to use for debugging.


If set, the swarm process
debug none will suspend on start and
open a debugger on this
port.

A properties-style list of
environment variables to
environment none
use when running the
application

A .properties file of
environment variables to
environmentFile swarm.environmentFile
use when running the
application

The mode for fraction


detection. Options are: *
when_missing : runs only
when no WildFly Swarm
dependencies are found *
force : always run, and
fractionDetectMode swarm.fractionDetectMode when_missing
merge any detected
fractions with the existing
dependencies, with existing
dependencies taking
precedence * never :
disable fraction detection

A list of extra fractions to


include when auto-detection
is used, useful for fractions
that can’t be detected or
user-provided fractions.
Each fraction can be of the
form group:name:version ,
name:version , or name . If
fractions none
no group is provided,
org.wildfly.swarm is
assumed. If no version is
provided, the version is

Maven 31
WildFly Swarm User's Guide

looked up from the WildFly


Swarm BOM for the version
of the plugin you are using.

Boolean specifying if the


resulting executable jar
hollow swarm.hollow should be hollow and not false
include the default
deployment.

A list of <jvmArgument>
elements specifying
jvmArguments swarm.jvmArguments
additional JVM arguments
(such as -Xmx32m )

A class to execute as the


mainClass swarm.mainClass org.wildfly.swar
main

Paths to a directory
modules none containing additional ./modules
module definitions

Application configurations to
processes none start (see multistart section
above)

(see properties section


properties none
below)

(see properties section


propertiesFile swarm.propertiesFile
below)

A file path to use to store


stderr output instead of
stderrFile swarm.stderr
sending it stderr of the
launching process

A file path to use to store


stdout output instead of
stdoutFile swarm.stdout
sending it stdout of the
launching process

If true, the -swarm.jar from


${project.build.directory}
will be used. This jar will not
be automatically created, so
useUberJar swarm.useUberJar false

Maven 32
WildFly Swarm User's Guide

the package goal will need


to have already been
executed.

Properties
Many properties may be used to configure execution and affect the packaging or running of
your application.

If you add a <properties> or <propertiesFile> section to the <configuration> of the


plugin, the properties will be used when running your application via mvn wildfly-swarm:run .
Additionally, those same properties will be added to your myapp-swarm.jar to affect
subsequent executions of the uberjar. Any properties loaded from <propertiesFile> will
override same-named properties from <properties> .

Any properties added to the uberjar can of course be overridden at runtime using the
traditional -Dname=value mechanism of java .

Only properties specified outside of <properties> or <propertiesFile> that start with


jboss. , wildfly. , swarm. , or maven. , or override a property specified in <properties>

or <propertiesFile> are added to the uberjar at package time.

Please see Configuration Properties for a non-exhaustive list of useful properties.

Maven 33
WildFly Swarm User's Guide

Maven Plugin: Advanced


Starting applications
If you want to start the application without maven waiting for it to exit, use the wildfly-
swarm:start goal

Starting multiple applications at once


You can start multiple swarm applications at once using the wildfly-swarm:multistart goal
(this is useful for integration testing a set of applications). Each application is specified as a
<process> containing an optional <groupId> , an <artifactId> , and an optional

<executionId> (useful if you need to launch multiple copies of the same application). Each

<process> can also include any configuration that is valid for the wildfly-swarm:start goal.

Example

Maven 34
WildFly Swarm User's Guide

<build>
<plugins>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
<executions>
<execution>
<id>multistart</id>
<phase>pre-integration-test</phase>
<goals>
<goal>multistart</goal>
</goals>
<configuration>
<processes>
<process>
<artifactId>my-frontend-app</artifactId>
</process>
<process>
<artifactId>my-auth-app</artifactId>
<properties>
<swarm.http.port>8081</swarm.http.port>
</properties>
<mainClass>com.example.auth.Main</mainClass>
</process>
<process>
<artifactId>my-indexing-app</artifactId>
<properties>
<swarm.http.port>8082</swarm.http.port>
</properties>
<environment>
<ENV>test</ENV>
</environment>
</process>
</processes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

Stopping applications
If you have started any applications with either wildfly-swarm:start or wildfly-
swarm:multistart , they can be stopped by executing the wildfly-swarm:stop goal.

Maven 35
WildFly Swarm User's Guide

Gradle Plugin
To assist in building WildFly Swarm projects, a Gradle plugin is available. This plugin creates
the -swarm.jar uberjar which contains your application along with the necessary parts of
WildFly to support it.

Gradle doesn’t get the same attention by the core developers as Maven. If you want
to be on the safe side, use Maven. If you are interested in contributing to the Gradle
build system, please let us know!

Packaging your application


To use the plugin, you must add it to your build.gradle :

buildscript {
repositories {
mavenLocal()
mavenCentral()
}

dependencies {
classpath "org.wildfly.swarm:wildfly-swarm-gradle-plugin:1.0.0.Alpha9-SNAPSHOT"
}
}

apply plugin: 'wildfly-swarm'

To produce the myapp-swarm.jar , simply perform a gradle wildfly-swarm-package command


after adding the plugin.

Using the WildFly Swarm BOM


WildFly Swarm provides a BOM that specifies the versions for all of the provided fractions.
To import it into your gradle build, you’ll need to use the dependency-management-plugin:

Gradle 36
WildFly Swarm User's Guide

buildscript {
repositories {
mavenLocal()
mavenCentral()
}

dependencies {
classpath "io.spring.gradle:dependency-management-plugin:1.0.3.RELEASE"
classpath "org.wildfly.swarm:wildfly-swarm-gradle-plugin:2017.11.0-SNAPSHOT"
}
}

apply plugin: "io.spring.dependency-management"


apply plugin: 'wildfly-swarm'
apply plugin: 'java'

repositories {
mavenLocal()
mavenCentral()
}

dependencyManagement {
imports {
mavenBom "org.wildfly.swarm:bom:2017.11.0-SNAPSHOT"
}
}

dependencies {
compile "org.wildfly.swarm:jaxrs"
}

Configuration
You can optionally provide configuration to the plugin.

Configuration Options
The plugin accepts the following options:

Gradle 37
WildFly Swarm User's Guide

Name Description Default

If true, dependencies
will be included in the -
swarm.jar. Otherwise,
bundleDependencies true
they will be resolved
from $M2_REPO or the
network.

A class to execute as
the main. If not set, the
plugin will check for
mainClassName mainClassName from org.wildfly.swarm.bootstrap.Main
the application
plugin before using the
default.

Paths to a directory
modules containing additional ./modules
module definitions

(see properties section


properties
below)

(see properties section


propertiesFile
below)

A Jar-Task which
should be wrapped
instead of the JAR-
archiveTask
Task (Java-Plugin) or
WAR-Task (WAR-
Plugin)

Properties
Many properties may be used to configure execution and affect the packaging or running of
your application.

If you set a properties map or the propertiesFile field in the swarm block in your build
script, the properties will be added to your myapp-swarm.jar to affect subsequent executions
of the uberjar. Any properties loaded from propertiesFile will override same-named
properties from properties .

Any properties added to the uberjar can of course be overridden at runtime using the
traditional -Dname=value mechanism of java .

Gradle 38
WildFly Swarm User's Guide

Only properties specified outside of properties or propertiesFile that start with jboss. ,
wildfly. , or swarm. , or override a property specified in properties or propertiesFile

are added to the uberjar at package time.

Please see Configuration Properties for a non-exhaustive list of useful properties.

Example

swarm {
properties {
swarm.http.port = 8181
my.app.property = 'biscuits'
}

bundleDependencies = false
moduleDirs = [new File(buildDir, 'resources/main/modules')]
propertiesFile = new File(buildDir, "resources/main/some.properties")
}

Gradle 39
WildFly Swarm User's Guide

Container ( Swarm )
At the root of every WildFly Swarm application is the container.

The container provides an API for instantiating an embedded WildFly Swarm container,
starting and stopping it, and deploying.

The container can either be instantiated inside your own main(…​) , or if you don’t provide a
main(…​) , then WildFly Swarm will handle the construction of the container and subsequent

deployment of your project artifact.

User-Provided main(…​)
If you provide a main(…​) and configure it in using the Maven Plugin or Gradle Plugin, it
should simply be a regular Java main(…​) method.

Because of some initialization timing issues, you should construct the Swarm prior to
working with any deployments using the ShrinkWrap API.

It’s also recommended that the Swarm is constructed prior to any other code in the main(…​
) . This is to prevent any issues of JBoss Logging not being able to initialize the logging

subsystem if another framework or class has used JUL, or another logger, first.

public class MyMain {


public static void main(String...args) {

// Instantiate the container


Swarm swarm = new Swarm();

// Create one or more deployments


JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class);
...

// Add resource to deployment


deployment.addClass(MyResource.class);

swarm.start();
swarm.deploy(deployment);
}
}

Gradle 40
WildFly Swarm User's Guide

If you only need to do some configuration of the container without needing to manipulate the
deployment archive, you can call deploy() with no arguments to have it deploy the default
archive. For example, here we configure an h2 datasource, then deploy the default archive:

public class MyMain {


public static void main(String...args) {
new Swarm()
.fraction(new DatasourcesFraction()
.jdbcDriver("h2", (d) -> {
d.driverClassName("org.h2.Driver");
d.xaDatasourceClass("org.h2.jdbcx.JdbcDataSource");
d.driverModuleName("com.h2database.h2");
})
.dataSource("ExampleDS", (ds) -> {
ds.driverName("h2");
ds.connectionUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
ds.userName("foo");
ds.password("bar");
}))
.start()
.deploy();
}
}

No User-Provided main(…​)
If you choose not to provide a main, org.wildfly.swarm.Swarm#main(…​) will be used by
default. It boots the default container (based upon your dependencies) and deploys your
project artifact.

The org.wildfly.swarm.Swarm class is also suitable for executing directly from your IDE if
you have no requirement of providing a customized main(…​) .

Supporting with Command-Line arguments


When no user-provided main(..) is available, the default Swarm main supports a handful
of command-line arguments to the -swarm.jar

In the event a user-provided main(…​) exists, it can still optionally provide support for the
above-mentioned command-line arguments. A constructor of Swarm takes the String…​args
provided to the main(…​) and will process all relevant arguments.

Gradle 41
WildFly Swarm User's Guide

public class MyMain {


public static void main(String...args) {
Swarm swarm = new Swarm(args);
...
}
}

In this case, be aware that if the -swarm.jar is invoked with --help , a call to
System.exit(0) will occur, abruptly terminating the application.

Gradle 42
WildFly Swarm User's Guide

Deployments using ShrinkWrap


ShrinkWrap is an open-source project sponsored by Red Hat. It provides an API and SPI for
easily creating, importing, exporting and manipulating archives. ShrinkWrap works in-
memory, but can also be used to create archives on disk.

ShrinkWrap Basics
The primary entry-point into ShrinkWrap is the ShrinkWrap class and its create(class)
method. You can create simple Java or Web archives ( .jar and .war , respectively) by
passing JavaArchive.class or WebArchive.class to the create(…​) method.

WildFly Swarm additionally makes other types of archives available, depending on which
fractions you include in your application. While they all ultimately produce a Java archive,
they provide additional logic to make building certain types of archives easier.

The types of archives that WildFly Swarm makes available includes, but is not limited to:

Type Description
An enhanced version of .jar which
JARArchive provides easy methods for adding
dependencies.

An enhanced version of a .war which


WARArchive provides easy methods for serving static
content or adding dependencies.

Web archive which can automatically


JAXRSArchive create the necessary default
Application / @ApplicationPath bindings.

Secured
Archive type which injects keycloak.json
and sets up security constraints

RibbonArchive
Archive which can register Ribbon-based
services or clients

Using Several Types of Archives

Gradle 43
WildFly Swarm User's Guide

Each ShrinkWrap archive type is effectively a view onto the underlying archive. Using the
archive’s own .as(class) method, the view can be changed several times while
constructing it.

// First create and use generic JAX-RS archive


JAXRSArchive deployment = ShrinkWrap.create( JAXRSArchive.class );
deployment.addResource( MyResource.class );

// Next, view it as a Secured archive, which activated Keycloak


deployment.as( Secured.class )

// Then, view it as a RibbonArchive, and set its service name for discovery
deployment.as( RibbonArchive.class ).setApplicationName( "my-service" );

Gradle 44
WildFly Swarm User's Guide

WAR Packaging
If you have an existing WAR-based application, you can construct a self-contained myapp-
swarm.jar from it with ease. By using the plugin of your choice (Maven or Gradle), the

resulting uberjar will contain your application along with enough of the application-server to
support it.

Maven
For a Maven project, you already have a pom.xml with

<packaging>war</packaging>

Simply add configuration for the wildfly-swarm-plugin :

<build>
<plugins>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
</plugin>
</plugins>
</build>

When you perform a typical Maven build using mvn package , your target directory will
include a myapp-swarm.jar version of your application.

If you don’t specify any WildFly Swarm fractions as dependencies, the maven plugin will
auto-detect the fractions your application needs. See the Maven chapter for more details.

This artifact can then be executed using:

java -jar ./target/myapp-swarm.jar

Gradle 45
WildFly Swarm User's Guide

JAR Packaging
If you desire to move away from traditionally-packaged .war applications, more options are
available to you with WildFly Swarm. Though a fluent API, you can fully configure the
facilities brought to your application and control what gets deployed.

Writing your own main(…​)


When your application is packaged as a .jar , you can also (but are not required) to
provide your own main(…​) method. In your main(…​) you can configure the container as
much or as little as you require. You can also .deploy(…​) one or more deployments.

The main(…​) method should exactly match the typical requirements of a main method in
Java, and is executable from your IDE.

public class Main {

public static void main(String...args) {


..
}

Within the main method, you can work with the org.wildfly.swarm.Swarm API to configure
fractions into the system and deploy components.

The primary methods on Swarm are:

Name Description
fraction(…​) Add an explicitly-configured fraction

start(…​) Start the configured container

deploy(…​) Deploy a ShrinkWrap archive

Default Configuration

Gradle 46
WildFly Swarm User's Guide

When you add dependencies to your project, they automatically activate the related fraction.
For instance, simply having the logging dependency adds the logging fraction to the
container and initializes it.

You only need to call .fraction(new LoggingFraction()) if you want to change the
configuration to be different from the default. Any fraction that has been brought in through
the dependency mechanism but has not been explicitly configured will be added with its
default configuration.

Deployments
Once a container is created, one or more deployments may be created using ShrinkWrap
and deployed into the container. Please see the chapter on ShrinkWrap for general details
on how to create deployments.

Gradle 47
WildFly Swarm User's Guide

System Properties
Below is a non-exhaustive set of useful properties, which may be available depending on
which fractions your application uses.

For a full set of supported options, please consult the documentation for each
fraction and the javadocs on class SwarmProperties.java

General
Name Description Default
swarm.bind.address Interface to bind servers 0.0.0.0

Sets a global port


swarm.port.offset 0
adjustment

Timeout, in seconds, to
swarm.deployment.timeout wait for a deployment to 300
occur

Causes a deployed artifact


to be dumped to disk
swarm.export.deployment false
when swarm starts, for
debugging

If provided, the swarm


process will pause for
debugging on the given
port. This option is only
available when running an
swarm.debug.port Arquillian test or mvn none
wildfly-swarm:run , not
when executing java -
jar . The latter requires
normal Java debug agent
parameters

Undertow

Gradle 48
WildFly Swarm User's Guide

Name Description Default


swarm.http.port Sets the port for the HTTP server 8080

Sets the port for the HTTPS


swarm.https.port 8443
server

If true,
generates a
swarm.https.certificate.generate
Enables HTTPS and generates a self-signed
self-signed certificate certificate for
development
purposes

The host used in the self-signed


swarm.https.certificate.generate.host certificate if localhost
swarm.https.certificate.generate
is true

Sets the context path for the


swarm.context.path /
deployed application

Databases
For the H2, MySQL and Postgres database fractions, the follow properties are supported to
configure the datasource.

Name Description Default

swarm.ds.name
Name of the datasource ExampleDS
(e.g. ExampleDS )

Username to access the


swarm.ds.username driver specific
database

Password to access the


swarm.ds.password driver specific
database

swarm.ds.connection.url JDBC connection URL driver specific

Gradle 49
WildFly Swarm User's Guide

Supporting with Command-Line arguments


When no user-provided main(..) is available (see Container), the default Swarm main
supports a handful of command-line arguments to the -swarm.jar :

Argument Description Default

-D<name> or -D<name>= Define a Java system


none
<value> property.

Location of a Java
-P<file-or-url> .properties file to use as none
system properties.

Bind the public listeners to


-b <addr> 0.0.0.0 (all)
an address.

Specify an XML
configuration file (such as
-c <file-or-url> none
standalone.xml or a
fragment of such).

project-defaults.yml
-s <file-or-url> Specify a project- from the application
defaults.yml
classpath, if available.

Name of profile to activate


from a project-
-S <active-profile> none
[profile].yml file (see -
s ).

Display relevant help,


--help or -h
including any known n/a
project-defaults.yml
keys (see -s ).

Display the version of


--version or -v WildFly Swarm being n/a
used.

Gradle 50
WildFly Swarm User's Guide

Configuration using the Java API


The Java API is most straight forward way to configure fractions in WildFly Swarm. A typical
example looks like this:

new DatasourcesFraction()
.jdbcDriver("h2", (d) -> {
d.driverClassName("org.h2.Driver");
d.xaDatasourceClass("org.h2.jdbcx.JdbcDataSource");
d.driverModuleName("com.h2database.h2");
})
.dataSource("ExampleDS", (ds) -> {
ds.driverName("h2");
ds.connectionUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
ds.userName("sa");
ds.password("sa");
});

The complete Javadocs for the config API are available here

In this example we configure the datasource fraction with an additional datasource and a
corresponding JDBC driver.

All of the fractions that represent WildFly subsystems can be configured this way. The
configuration model is an equivalent to the WildFly XML schema. In fact it is actually
generated from it.

Gradle 51
WildFly Swarm User's Guide

Configuration overlays using stage properties


In some cases it may be desirable to extract some of the configuration properties and switch
them depending on the target environment. Project stages are a way to move environment
specific configuration properties into an external file.

project-defaults.yml
Default configuration is represented in an external YAML file:

logger:
level: DEBUG
swarm:
port:
offset: 10
---
project:
stage: development
logger:
level: DEBUG
swarm:
port:
offset: 50
---
project:
stage: production
logger:
level: INFO
swarm:
port:
offset: 100

Project Stage Definitions


To have separate configuration for different environments we could then have:

project-development.yml

logger:
level: DEBUG
swarm:
port:
offset: 50

project-production.yml

Gradle 52
WildFly Swarm User's Guide

logger:
level: INFO
swarm:
port:
offset: 100

Container Bootstrap

ClassLoader cl = Main.class.getClassLoader();
URL stageConfig = cl.getResource("project-defaults.yml");

Swarm swarm = new Swarm(false)


.withConfig(stageConfig);
[...]

Auto detection picks up project-defaults.yml from src/main/resources

Command-line switches / System Properties


Two notable command-line switches are available to easily re-configure Swarm in different
environments:

System Property Example Purpose


Enables a specific stage
(fallback to System
-Dswarm.project.stage=
swarm.project.stage environment variable
<stage name>
SWARM_PROJECT_STAGE or
default if neither exists)

- Allows to reference a
swarm.project.stage.file Dswarm.project.stage.file= different project-
<URL> defaults.yml file

Referencing Stage Configuration Values


The stage configuration properties are internally resolved to simple properties:

YAML Internal
swarm: port: offset: swarm.port.offset

logger: level: logger.level

Gradle 53
WildFly Swarm User's Guide

Internally there are three ways to get hold of stage configuration values.

1. Reference them as expressions (standalone.xml)

2. Retrieve them through StageConfig

3. Inject them in CDI contexts

Using Expressions

The fist case is useful when you work with standalone.xml and still need to extract
environment specific properties. In this cases you can make use of regular WildFly
expressions in XML:

<subsystem xmlns="urn:jboss:domain:logging:3.0">
<console-handler name="CONSOLE">
<level name="${logger.level:INFO}"/>
<formatter>
<named-formatter name="COLOR-PATTERN"/>
</formatter>
</console-handler>
<root-logger>
<level name="${logger.level:INFO}"/>
<handlers>
<handler name="CONSOLE"/>
</handlers>
</root-logger>
[...]
</subsystem>

Here the stage configuration logger.level is referenced using the expression syntax
${logger.level:INFO} (INFO is the fallback value).

Using StageConfig

StageConfig is the java type representing the former YAML file. It allows you to access

named properties following the standard java properties name syntax (i.e. logger.level )

It is available in two places:

1. Injectable into Customizers, ArchivePreparers, etc

2. From Swarm

The first case is intended to be used by Fraction authors if they need to hook into the stage
configuration for the default configuration of a fraction itself.

The later case is intended for users to combine stage and fraction configuration in a custom
Main() :

Gradle 54
WildFly Swarm User's Guide

Swarm swarm = new Swarm(false)


.withStageConfig(stageConfig);

swarm.fraction(
new DatasourcesFraction()
.jdbcDriver("h2", (d) -> {
d.driverClassName("org.h2.Driver");
d.xaDatasourceClass("org.h2.jdbcx.JdbcDataSource");
d.driverModuleName("com.h2database.h2");
})
.dataSource("ExampleDS", (ds) -> {

ds.driverName("h2");

ds.connectionUrl(
// referencing stage configuration values
swarm
.stageConfig()
.resolve("database.connection.url")
.getValue()
);
ds.userName("sa");
ds.password("sa");
})
);

In this example the datasource#connectionUrl() is resolved from a stage configuration


value. The stage configuration is exposed through the container.

Gradle 55
WildFly Swarm User's Guide

Configuration using XML


If you prefer an external, XML based configuration, i.e. because you migrate from WildFLy to
WildFly Swarm, the you can leverage an existing standalone.xml file as well.

To make use of such a file, you’d need to bootstrap the Container with a reference to an
XML configuration:

ClassLoader cl = Main.class.getClassLoader();
URL xmlConfig = cl.getResource("standalone.xml");

Swarm swarm = new Swarm(false)


.withXmlConfig(xmlConfig);

[...]

In this case, you would still need to declare explicit maven dependencies on Swarm
fractions, but the Container would just use those subsystem configurations for which a
corresponding fraction can be found, i.e.:

<subsystem xmlns="urn:jboss:domain:datasources:4.0">
<datasources>
<drivers>
<driver name="h2" module="com.h2database.h2">
<driver-class>org.h2.Driver</driver-class>
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE</connection-url
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
</datasources>
</subsystem>

Gradle 56
WildFly Swarm User's Guide

Testing with Arquillian


Arquillian is a test-harness from JBoss that facilitates launching applications and executing
test code both from outside and within the running application.

Under traditional usage, Arquillian first launches the application server, then deploys an
archive created within your unit test to it. When used with WildFly Swarm, there is obviously
no separate launch the application server phase.

Instead, your test-case creates your application, and the Arquillian adapter wraps it with the
WildFly Swarm bits and executes the resulting uberjar.

Once it is running, test code may run outside of the uberjar or within it, reporting the test
results back to the testing framework.

Configuring
To use the WildFly Swarm Arquillian adapter, you need to add the following into your
pom.xml :

Gradle 57
WildFly Swarm User's Guide

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.arquillian</groupId>
<artifactId>arquillian-bom</artifactId>
<version>1.1.10.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- Brought in via WildFly Swarm `bom` -->
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>arquillian</artifactId>
<scope>test</scope>
</dependency>
<!-- Brought in via Arquillian BOM, see dependencyManagement section above -->
<dependency>
<groupId>org.jboss.arquillian.junit</groupId>
<artifactId>arquillian-junit-container</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

Writing a Test
To integrate Arquillian into your test, you need to use the JUnit @RunWith annotation and the
Arquillian.class test-runner:

@RunWith(Arquillian.class)
public class MyTest {
...
}

This integrates the Arquillian lifecycle with the test-case.

Next, you need to specify the deployment that should be wrapped up in the WildFly Swarm
mechanism. This is accomplished by using the @Deployment Arquillian annotation on a
public static method that returns a ShrinkWrap archive.

@Deployment
public static Archive createDeployment() {
...
}

Gradle 58
WildFly Swarm User's Guide

The contents of this method is similar to whatever you would do within your main(…​)
method.

For instance:

@Deployment
public static Archive createDeployment() {
JAXRSArchive deployment = ShrinkWrap.create( JAXRSArchive.class );
deployment.addResource( MyResource.class );
return deployment;
}

By default, all methods annotated with @Test will run inside the application. Depending on
the functionality you include, you can use annotations such as @Inject (if you’re using CDI)
to inject components into your test-case class.

If you wish to test your application from outside (for instance, with a web client), you can use
the @RunAsClient annotation on your method.

Example with CDI

@RunWith(Arquillian.class)
public class MyTest {

@Inject
private MyComponent component;

@Test
public void testMyComponent() {
// Runs within the application, CDI injects MyComponent

// assert something about this.component


}

@Deployment
public static Archive createDeployment() {
JARArchive archive = ShrinkWrap.create( JARArchive.class );

// ... set up archive ...

return archive;
}
}

Example with custom Container configuration

Gradle 59
WildFly Swarm User's Guide

If the swarm container has to be configured (e.g. to configure the DataSource fraction) then
this can be done by implementing the ContainerFactory interface.

@RunWith(Arquillian.class)
public class MyTest {
@Deployment(testable = false)
public static Archive createDeployment() {
JARArchive deployment = ShrinkWrap.create(JARArchive.class);
// ... set up archive ...
return deployment;
}

@CreateSwarm
public static Swarm newContainer() throws Exception {
Swarm swarm = new Swarm();
// ... configure Swarm ...
return swarm;
}

@Test
@RunAsClient
public void testNothing() {

}
}

Default Deployment
In a world of microservices, this tends to not be the case, and the entire "application"
represents one small microservice component.

The @DefaultDeployment annotation has been provided to automatically create the


deployment of the entire application.

@RunWith(Arquillian.class)
@DefaultDeployment
public class InContainerTest {

Using the @DefaultDeployment annotation provided by WildFly Swarm’s Arquillian integration


means you should not use the usual Arquillian @Deployment annotation on a static method
returning an Archive.

The @DefaultDeployment annotation looks at the package of the test, and it uses heuristics
to include all of your other application classes residing in that package or deeper within the
Java packaging hierarchy.

@DefaultDeployment defaults to create a ShrinkWrap WAR archive.

Gradle 60
WildFly Swarm User's Guide

Passing additional options to the -swarm.jar


The Arquillian container for WildFly Swarm supports the following system properties in
addition to those listed in the plugin chapter:

Name Description Default


':' separated list of paths to
swarm.build.modules module directories to "modules"
include

',' separated list of repo


swarm.build.repos urls to include when
resolving dependencies

If true, the test -swarm.jar


swarm.export.uberjar will be exported to disk to false
aid debugging

Gradle 61
WildFly Swarm User's Guide

Logging
Logging is supported by WildFly Swarm using the typical JBoss-Logging systems. By
default, logging occurs to the console. Advanced configuration can adjust the amount of
information logged and where the log ends up (files or console or other locations).

Including Logging Capabilities


Several of the higher-order fractions include logging by default. If you need to include it
explicitly, though, you may use the following Maven coordinates.

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>logging</artifactId>
</dependency>

Configuration
Including the above dependency will automatically configure reasonable INFO-level logging
to the console. You can control the logging level with the swarm.logging sysprop: -
Dswarm.logging=DEBUG .

If you wish to perform more advanced configuration, please see the JavaDocs for the
Logging API.

Logging to a file
In order to log to a file, you’d need to specifiy a file handler and link it to the root logger. A full
example for the configuration of a log file handler looks like this:

Logging 62
WildFly Swarm User's Guide

String logFile = System.getProperty("user.dir") + File.separator + "swarm.log";

Swarm container = new Swarm();


container.fraction(
new LoggingFraction()
.fileHandler("FILE", f -> {

Map<String, String> fileProps = new HashMap<>();


fileProps.put("path", logFile);
f.file(fileProps);
f.level(Level.INFO);
f.formatter("%d{HH:mm:ss,SSS} %-5p [%c] (%t) %s%e%n");

})
.rootLogger(Level.INFO, "FILE")
);

container.start();

[...]

Logging 63
WildFly Swarm User's Guide

Logstash
The Logstash project from Elastic provides for a centralized server to accumulate logs from
a multitude of applications. WildFly Swarm makes it easy to have each of your applications
or services dump their logs into it.

Configure
Dependency
To add Logstash integration to your WildFly Swarm application, you need to add a
dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>logstash</artifactId>
</dependency>

Configuration
While the above dependency adds the capability of logging to Logstash, until the Logstash
server’s hostname and port is set, the integration remains inactive.

To configure where the Logstash server is running, the following two properties need to be
set, either through plugin configuration or on the command-line using -D…​

Name Description

swarm.logstash.hostname The hostname of the Logstash server

swarm.logstash.port The port of the Logstash server

Logstash 64
WildFly Swarm User's Guide

FluentD
The FluentD project from http://www.fluentd.org/ provides for an open source data collector
for a unified logging layer. The fluentd fraction installs a custom log handler that’s capable of
logging to a fluentd daemon, which filter, buffer and route logging information according to
your needs. == Configure

Dependency
To add FluentD integration to your WildFly Swarm application, you need to add a
dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>fluentd</artifactId>
</dependency>

Configuration
To configure where the FluentD daemon is running, the following two properties need to be
set, either through plugin configuration or on the command-line using -D…​ Usually we
would expect the daemon to run co-located with the Swarm process (i.e. same docker
image).

Name Default value Description

The hostname of the


swarm.fluentd.hostname localhost
FluentD daemon

The port of the FluentD


swarm.fluentd.port 24224
daemon

FluentD 65
WildFly Swarm User's Guide

JPA
Java Persistence API (JPA) is a standard JavaEE API for developing applications that need
access to relational databases.

Configuration
To use JPA in your application, you need to add the JPA dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jpa</artifactId>
</dependency>

and then specify the dependency for whichever JDBC Driver you need for your particular
database.

Examples include:

H2 JDBC Driver

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>

MySQL JDBC Driver

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

Postgres JDBC Driver

JPA 66
WildFly Swarm User's Guide

<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>

Usage
The jpa fraction makes the JPA APIs available to your application through a transitive
dependency. There is no need to add them yourself.

Usage in a WAR Application


By default, inclusion of the jpa fraction will cause the creation of the default ExampleDS
datasource for usage by your persistence.xml . The datasource is bound as the default
datasource, so there is no need to reference it by name from your persistence.xml .

Usage in a JAR application


If you have a .jar -based application with a main(…​) , you can configure multiple
datasources for usage with JPA.

Please see the Datasources chapter for details on configuring datasources.

Configuration
If the default datasource for JPA is used, it may be configured using system properties.

Property Description
swarm.ds.connection.url JDBC connection URL

swarm.ds.username
Username for authenticating the
connection

swarm.ds.password
Password for authenticating the
connection

swarm.ds.name Simple name of the datasource, such as


ExampleDS

JPA 67
WildFly Swarm User's Guide

JPA 68
WildFly Swarm User's Guide

Datasource
Datasources provide managed connections to relational databases. While they may be used
directly, typically they are consumed through other frameworks, such as a JPA.

Configuration
To use Datasources in your application, you need to add the following dependency:

Default using H2-based Datasource

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>datasources</artifactId>
</dependency>

Usage
Using the Java API, you may create one or more datasources, along with registering
relevant JDBC drivers:

swarm.fraction(new DatasourcesFraction()
.jdbcDriver("h2", (d) -> {
d.driverClassName("org.h2.Driver");
d.xaDatasourceClass("org.h2.jdbcx.JdbcDataSource");
d.driverModuleName("com.h2database.h2");
})
.dataSource("MyDS", (ds) -> {
ds.driverName("h2");
ds.connectionUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE"
ds.userName("sa");
ds.password("sa");
})
);

If the JPA fraction is used, by default it will create a default ExampleDS .

Datasources 69
WildFly Swarm User's Guide

Datasources 70
WildFly Swarm User's Guide

Flyway
Flyway is an open-source database migration tool. It strongly favors simplicity and
convention over configuration.

Read more about how Flyway works in here: https://flywaydb.org/getstarted/how

Configuration
To enable Flyway, the following dependency is required:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>flyway</artifactId>
</dependency>

SQL Scripts should be placed under src/main/resources/db/migration and distributed inside


the UberJar.

Customizing the Flyway Configuration


The Flyway fraction will by default use the primary datasource, however you may use a
specific JDBC configuration in a main() method. For example:

Flyway 71
WildFly Swarm User's Guide

public class Main {

public static void main(String...args) {

// Set the configuration for the Flyway migration


FlywayFraction fraction = new FlywayFraction()
.jdbcUrl("jdbc:oracle:oci8:@")
.jdbcUser("admin")
.jdbcPassword("password");

// Instantiate Swarm and add our fraction


Swarm swarm = new Swarm();
swarm.fraction( fraction );

// Start the container


swarm.start();
}

Flyway 72
WildFly Swarm User's Guide

wildfly-nosql native API integration


The goal of wildfly-nosql, is to provide integration with NoSQL database native drivers.
Database connection profiles are defined with a logical name, that the application code
refers to (via @Inject or @Resource). Application deployments specify the version of the
NoSQL driver libraries to be used ("bring your own driver" style), as long as the driver library
version is API compatible with the supported version.

Connection pooling
Connections to NoSQL database servers are managed by the underlying native NoSQL
drivers. Connection pooling is provided directly by the native NoSQL drivers.

Define NoSQL connection profiles


Connections to NoSQL database servers are managed by the underlying native NoSQL
drivers. Connection pooling is provided directly by the native NoSQL drivers.

CDI Injection
Each NoSQL connection profile uniquely names the profile id, which can be used to @Inject
@Named("id") the NoSQL connection into your application code.

@Inject @Named("MyMongoDB") MongoDatabase database;


@Inject @Named("MyCassandra") Cluster cluster;
@Inject @Named("MyOrientDBPool") OPartitionedDatabasePool pool;
@Inject @Named("MyNeo4j") Driver database;

Custom module name


Each NoSQL connection profile (optionally) specifies the module name that contains the
native NoSQL driver classes, which is important for working with other software that may
presume different NoSQL driver module names. If the module is not specified, a default
name is used. This improves integration with other NoSQL tools that expect certain module
names.

JNDI resource lookup

NoSQL 73
WildFly Swarm User's Guide

Each NoSQL connection profile uniquely names the JNDI lookup jndi-name, which can be
easily used by application code.

@Resource(lookup = "java:jboss/cassandra/MyDB") Cluster cluster;


@Resource(lookup = "java:jboss/mongodb/MyDB") MongoDatabase database;
@Resource(lookup = "java:jboss/neo4j/MyDB") Driver database;
@Resource(lookup = "java:jboss/orientdb/MyDB") OPartitionedDatabasePool pool;

Specify the NoSQL driver artifacts


You get to bring your own NoSQL driver. In fact, you must bring your own NoSQL driver. All
that’s required though is just adding Maven dependencies to your project ( check the below
Java driver version table to see which NoSQL driver versions are known to work).

Example pom.xml dependencies for each NoSQL fraction:

MongoDB driver dependencies example

<dependencies>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${version.mongodb.driver}</version>
</dependency>
</dependencies>

Cassandra driver dependencies example

<dependencies>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>cassandra</artifactId>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>${version.cassandra.driver}</version>
</dependency>
</dependencies>

NoSQL 74
WildFly Swarm User's Guide

Neo4j driver dependencies example

<dependencies>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>${version.neo4j.driver}</version>
</dependency>
</dependencies>

OrientDB driver dependencies example

NoSQL 75
WildFly Swarm User's Guide

<dependencies>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>orientdb</artifactId>
</dependency>

<dependency>
<groupId>com.orientechnologies</groupId>
<artifactId>orientdb-core</artifactId>
</dependency>

<dependency>
<groupId>com.orientechnologies</groupId>
<artifactId>orientdb-graphdb</artifactId>
</dependency>

<dependency>
<groupId>com.orientechnologies</groupId>
<artifactId>orientdb-object</artifactId>
</dependency>

<dependency>
<groupId>com.orientechnologies</groupId>
<artifactId>orientdb-client</artifactId>
</dependency>

<dependency>
<groupId>com.tinkerpop.blueprints</groupId>
<artifactId>blueprints-core</artifactId>
</dependency>

<dependency>
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
</dependency>

Creating the connection profiles


MongoDB Java driver versions

NoSQL 76
WildFly Swarm User's Guide

Table 1. MongoDB Java driver (org.mongodb:mongo-java-driver).


Version WildFly WildFly Swarm

3.0.3 NO YES

3.2.2 YES YES

3.3.0 NO YES

3.4.2 NO YES

Example of connecting to MongoDB via MongoDBFraction

project-defaults.yml

NoSQL 77
WildFly Swarm User's Guide

swarm:
mongodb:
mongos:
mongodbtestprofile:
database: mongotestdb
jndi-name: java:jboss/mongodb/test
id: mongodbtestprofile
module: org.mongodb.driver.custom
security-domain: mongoRealm
hosts:
mongotesthost:
outbound-socket-binding-ref: mongotesthost

security:
security-domains:
mongoRealm:
cache-type:
classic-authentication:
login-modules:
ConfiguredIdentity:
code: ConfiguredIdentity
flag: required
ConfiguredIdentity:
module-options:
principal: DBUSERID
password: DBPASSWORD
username: DBUSERID
network:
socket-binding-groups:
standard-sockets:
outbound-socket-bindings:
mongotesthost:
remote-host: localhost
remote-port: 27017

HelloWorldEndpoint.java

NoSQL 78
WildFly Swarm User's Guide

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

import com.mongodb.client.MongoDatabase;

@ApplicationScoped
@Path("/hello")
public class HelloWorldEndpoint {

@Inject @Named("mongodbtestprofile")
MongoDatabase database;

@GET
@Produces("text/plain")
public Response doGet() {
return Response.ok("Hello from WildFly Swarm! database = " + database).build();
}
}

pom.xml

<!-- pom.xml -->


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instan
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.x
<modelVersion>4.0.0</modelVersion>
<groupId>org.wildflynosql</groupId>
<artifactId>demo</artifactId>
<name>WildFly Swarm Example</name>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>

<properties>
<version.wildfly.swarm>2017.6.0-SNAPSHOT</version.wildfly.swarm>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.mongodb.driver>3.2.2</version.mongodb.driver>
<version.org.glassfish.javax.json>1.0.3</version.org.glassfish.javax.json>
</properties>

<dependencyManagement>
<dependencies>

NoSQL 79
WildFly Swarm User's Guide

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>bom-all</artifactId>
<version>${version.wildfly.swarm}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<finalName>demo</finalName>
<plugins>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
<version>${version.wildfly.swarm}</version>
<configuration>
<mainClass>org.wildflynosql.demo.rest.Main</mainClass>
</configuration>

<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencies>
<!-- Java EE 7 dependency -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!-- WildFly Swarm Fractions -->
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jaxrs-jsonp</artifactId>
</dependency>

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jsonp</artifactId>
</dependency>

<dependency>
<groupId>org.glassfish</groupId>

NoSQL 80
WildFly Swarm User's Guide

<artifactId>javax.json</artifactId>
<version>${version.org.glassfish.javax.json}</version>
</dependency>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>${version.mongodb.driver}</version>
</dependency>

</dependencies>
</project>

beans.xml to enable CDI

<!-- empty beans.xml -->


<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

Cassandra Java driver versions


Table 2. Cassandra Java driver (com.datastax.cassandra:cassandra-driver-core).
Version WildFly WildFly Swarm
3.0.0 YES YES

Example of connecting to Cassandra via


CassandraFraction

project-defaults.yml

NoSQL 81
WildFly Swarm User's Guide

swarm:
cassandradriver:
cassandras:
cassandratestprofile:
database:
jndi-name: java:jboss/cassandradriver/test
id: cassandratestprofile
module: org.cassandra.custom
security-domain: cassandraRealm
hosts:
casstesthost:
outbound-socket-binding-ref: casstesthost
security:
security-domains:
cassandraRealm:
cache-type:
classic-authentication:
login-modules:
ConfiguredIdentity:
code: ConfiguredIdentity
flag: required
ConfiguredIdentity:
module-options:
principal: DBUSERID
password: DBPASSWORD
username: DBUSERID
network:
socket-binding-groups:
standard-sockets:
outbound-socket-bindings:
casstesthost:
remote-host: localhost
remote-port: 9042

HelloWorldEndpoint.java

NoSQL 82
WildFly Swarm User's Guide

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

import com.datastax.driver.core.Cluster;

@ApplicationScoped
@Path("/hello")
public class HelloWorldEndpoint {

@Inject @Named("cassandratestprofile")
Cluster cluster;

@GET
@Produces("text/plain")
public Response doGet() {
return Response.ok("Hello from WildFly Swarm! cluster = " + cluster).build();
}
}

pom.xml

<!-- pom.xml -->


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instan
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.x
<modelVersion>4.0.0</modelVersion>
<groupId>org.wildflynosql</groupId>
<artifactId>demo</artifactId>
<name>WildFly Swarm Example</name>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>

<properties>
<version.wildfly.swarm>2017.6.0-SNAPSHOT</version.wildfly.swarm>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.cassandra.driver>3.0.0</version.cassandra.driver>
<version.org.glassfish.javax.json>1.0.3</version.org.glassfish.javax.json>
</properties>

<dependencyManagement>
<dependencies>
<dependency>

NoSQL 83
WildFly Swarm User's Guide

<groupId>org.wildfly.swarm</groupId>
<artifactId>bom-all</artifactId>
<version>${version.wildfly.swarm}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<finalName>demo</finalName>
<plugins>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
<version>${version.wildfly.swarm}</version>
<configuration>
<mainClass>org.wildflynosql.demo.rest.Main</mainClass>
</configuration>

<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencies>
<!-- Java EE 7 dependency -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!-- WildFly Swarm Fractions -->
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jaxrs-jsonp</artifactId>
</dependency>

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jsonp</artifactId>
</dependency>

<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>

NoSQL 84
WildFly Swarm User's Guide

<version>${version.org.glassfish.javax.json}</version>
</dependency>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>cassandra</artifactId>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>${version.cassandra.driver}</version>
</dependency>

</dependencies>
</project>

beans.xml to enable CDI

<!-- empty beans.xml -->


<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

OrientDB Java driver versions


Table 3. OrientDB Java driver (com.orientechnologies:orientdb-core,
com.orientechnologies:orientdb-graphdb, com.orientechnologies:orientdb-object,
com.orientechnologies:orientdb-client).
Version WildFly WildFly Swarm
2.2.9 YES YES

Example of connecting to OrientDB via OrientDBFraction


The orientdb subsystem may define multiple OrientDB connection profiles, that are used to
obtain com.orientechnologies.orient.core.db.OPartitionedDatabasePool class instances that
represent each defined profile. The OPartitionedDatabasePool class is thread safe and can
be shared by multiple deployed applications.

NoSQL 85
WildFly Swarm User's Guide

The OrientDB client API, is heavily dependent on keeping one OrientDB database
open per Java thread. When your application is done with the database, you must
close the OrientDB database to disassociate it from the Java thread, or the open
database will still be open by that Java thread, when the Java thread is returned to
the Java thread pool. A max of one OrientDB database can be open per Java thread,
so if you open a different database, the current one will be automatically closed first.

project-defaults.yml

swarm:
orientdb:
orients:
orienttesttprofile:
database: test
jndi-name: java:jboss/orientdb/test
id: orienttesttprofile
module: org.orientdb.custom
security-domain: orientRealm
hosts:
orienttesthost:
outbound-socket-binding-ref: orienttesthost
security:
security-domains:
orientRealm:
cache-type:
classic-authentication:
login-modules:
ConfiguredIdentity:
code: ConfiguredIdentity
flag: required
ConfiguredIdentity:
module-options:
principal: DBUSERID
password: DBPASSWORD
username: DBUSERID
network:
socket-binding-groups:
standard-sockets:
outbound-socket-bindings:
orienttesthost:
remote-host: localhost
remote-port: 2424

HelloWorldEndpoint.java

NoSQL 86
WildFly Swarm User's Guide

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

import com.orientechnologies.orient.core.db.OPartitionedDatabasePool;

@ApplicationScoped
@Path("/hello")
public class HelloWorldEndpoint {

@Inject @Named("orienttesttprofile")
OPartitionedDatabasePool databasePool;

@GET
@Produces("text/plain")
public Response doGet() {
return Response.ok("Hello from WildFly Swarm! databasePool= " + databasePool).build();
}
}

pom.xml

<!-- pom.xml -->


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instan
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.x
<modelVersion>4.0.0</modelVersion>
<groupId>org.wildflynosql</groupId>
<artifactId>demo</artifactId>
<name>WildFly Swarm Example</name>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>

<properties>
<version.wildfly.swarm>2017.6.0-SNAPSHOT</version.wildfly.swarm>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.cassandra.driver>3.0.0</version.cassandra.driver>
<version.org.glassfish.javax.json>1.0.3</version.org.glassfish.javax.json>
</properties>

<dependencyManagement>
<dependencies>

NoSQL 87
WildFly Swarm User's Guide

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>bom-all</artifactId>
<version>${version.wildfly.swarm}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<finalName>demo</finalName>
<plugins>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
<version>${version.wildfly.swarm}</version>
<configuration>
<mainClass>org.wildflynosql.demo.rest.Main</mainClass>
</configuration>

<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencies>
<!-- Java EE 7 dependency -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!-- WildFly Swarm Fractions -->
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jaxrs-jsonp</artifactId>
</dependency>

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jsonp</artifactId>
</dependency>

<dependency>
<groupId>org.glassfish</groupId>

NoSQL 88
WildFly Swarm User's Guide

<artifactId>javax.json</artifactId>
<version>${version.org.glassfish.javax.json}</version>
</dependency>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>orientdb</artifactId>
</dependency>
<dependency>
<groupId>com.orientechnologies</groupId>
<artifactId>orientdb-core</artifactId>
</dependency>

<dependency>
<groupId>com.orientechnologies</groupId>
<artifactId>orientdb-graphdb</artifactId>
</dependency>

<dependency>
<groupId>com.orientechnologies</groupId>
<artifactId>orientdb-object</artifactId>
</dependency>

<dependency>
<groupId>com.orientechnologies</groupId>
<artifactId>orientdb-client</artifactId>
</dependency>

<dependency>
<groupId>com.tinkerpop.blueprints</groupId>
<artifactId>blueprints-core</artifactId>
</dependency>

<dependency>
<groupId>com.googlecode.concurrentlinkedhashmap</groupId>
<artifactId>concurrentlinkedhashmap-lru</artifactId>
</dependency>
</dependencies>
</project>

beans.xml to enable CDI

<!-- empty beans.xml -->


<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

NoSQL 89
WildFly Swarm User's Guide

Neo4j Java driver versions


Table 4. Neo4j Java driver (org.neo4j.driver:neo4j-java-driver).
Version WildFly WildFly Swarm
1.2.1 YES YES

Example of connecting to Neo4j via Neo4jFraction

project-defaults.yml

swarm:
neo4jdriver:
neo4js:
neo4jtestprofile:
jndi-name: java:jboss/neo4jdriver/test
id: neo4jtestprofile
module: org.neo4j.driver.custom
security-domain: neo4jRealm
transaction: 1pc
hosts:
neo4jtesthost:
outbound-socket-binding-ref: neo4jtesthost
security:
security-domains:
neo4jRealm:
cache-type:
classic-authentication:
login-modules:
ConfiguredIdentity:
code: ConfiguredIdentity
flag: required
ConfiguredIdentity:
module-options:
principal: DBUSERID
password: DBPASSWORD
username: DBUSERID
network:
socket-binding-groups:
standard-sockets:
outbound-socket-bindings:
neo4jtesthost:
remote-host: localhost
remote-port: 7687

HelloWorldEndpoint.java

NoSQL 90
WildFly Swarm User's Guide

// HelloWorldEndpoint.java

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;

import org.neo4j.driver.v1.Driver;

@ApplicationScoped
@Path("/hello")
public class HelloWorldEndpoint {

@Inject @Named("neo4jtestprofile")
Driver database;

@GET
@Produces("text/plain")
public Response doGet() {
return Response.ok("Hello from WildFly Swarm! database = " + database).build();
}
}

pom.xml

<!-- pom.xml -->


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instan
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.x
<modelVersion>4.0.0</modelVersion>
<groupId>org.wildflynosql</groupId>
<artifactId>demo</artifactId>
<name>WildFly Swarm Example</name>
<version>1.0.0-SNAPSHOT</version>
<packaging>war</packaging>

<properties>
<version.wildfly.swarm>2017.6.0-SNAPSHOT</version.wildfly.swarm>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<failOnMissingWebXml>false</failOnMissingWebXml>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<version.neo4j.driver>1.2.1</version.neo4j.driver>
<version.org.glassfish.javax.json>1.0.3</version.org.glassfish.javax.json>
</properties>

NoSQL 91
WildFly Swarm User's Guide

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>bom-all</artifactId>
<version>${version.wildfly.swarm}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<finalName>demo</finalName>
<plugins>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-plugin</artifactId>
<version>${version.wildfly.swarm}</version>
<configuration>
<mainClass>org.wildflynosql.demo.rest.Main</mainClass>
</configuration>

<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

<dependencies>
<!-- Java EE 7 dependency -->
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!-- WildFly Swarm Fractions -->
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jaxrs-jsonp</artifactId>
</dependency>

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jsonp</artifactId>
</dependency>

NoSQL 92
WildFly Swarm User's Guide

<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>${version.org.glassfish.javax.json}</version>
</dependency>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>${version.neo4j.driver}</version>
</dependency>
</dependencies>
</project>

<!-- empty beans.xml -->


<beans xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

Logging categories
org.wildfly.nosql - Enable NoSQL subsystem logging.

org.wildfly.swarm.neo4j - Enable Neo4j fraction logging.

org.wildfly.swarm.orientdb - Enable OrientDB fraction logging.

org.wildfly.swarm.cassandra - Enable Cassandra fraction logging.

org.wildfly.swarm.mongodb - Enable MongoDB fraction logging.

Common issues
1. Incorrectly spelled profile name causes CDI injection or JNDI lookup, to fail. Correct to
use correct spelling of NoSQL profile name.

2. Missing beans.xml leads to deployment failure

NoSQL 93
WildFly Swarm User's Guide

JAX-RS
JAX-RS is a standard JavaEE API for defining web services. It can be used to replace
Servlet -based applications where resources are well-defined, such as in RESTful

architectures.

WildFly Swarm supports JAX-RS with both .war and .jar deployments.

Configuration
To bring JAX-RS functionality to your application, you need the following dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jaxrs</artifactId>
</dependency>

Usage
The jaxrs fraction brings the JAX-RS APIs to your application through a transitive
dependency. It also provides a JAXRSArchive archive type for easily creating JAX-RS-based
deployments if you provide your own main(…​) method.

JAXRSArchive deployment = ShrinkWrap.create( JAXRSArchive.class );


deployment.addResource( SomeResource.class );

Use of the jaxrs fraction dependency provides a default Application with the
@ApplicationPath annotation if you do not provide one when creating the deployment. If you

do provide an Application it will take precedence.

Using JAX-RS with CDI


By default, JAX-RS does not provide CDI support. To bring CDI support to your application,
an additional dependency is required:

JAX-RS 94
WildFly Swarm User's Guide

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>cdi</artifactId>
</dependency>

With this fraction in place, you can inject dependencies into your JAX-RS endpoints using
@Inject , benefit from CDI interceptors and more.

Using JAX-RS with multipart forms


To use JAX-RS with multipart forms (to support file uploads, for instance), another
dependency is required:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jaxrs-multipart</artifact>
</dependency>

JAX-RS 95
WildFly Swarm User's Guide

Swagger

Introduction
Swagger is a formal specification for a language-agnostic interface to REST APIs. This
interface lets both humans and computers understand an API’s capabilities such that a
consumer of the API can interact with the service. In simple terms, swagger is a JSON
representation of a RESTful API, typically made available over HTTP at /swagger.json .

A simple swagger.json will look something like this.

{
"swagger":"2.0",
"info":{},
"basePath":"/",
"tags":[{"name":"time"}],
"paths":{
"/time/now":{
"get":{
"tags":["time"],
"summary":"Get the current time",
"description":"Returns the time as a string",
"operationId":"get",
"produces":["application/json"],
"parameters":[],
"responses":{
"200":{
"description":"successful operation",
"schema":{"type":"string"}
}
}
}
}
}
}

WildFly Swarm provides a swagger fraction that enables JAX-RS API developers to easily
publish a /swagger.json describing the API.

To learn more about Swagger’s capabilities, see the Swagger website.

Configuration

Swagger 96
WildFly Swarm User's Guide

To enable Swagger in your application, you need to add a dependency to your pom.xml .

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>swagger</artifactId>
</dependency>

Usage
The swagger fraction pulls in required dependencies, and when your application is
deployed, the underlying Swagger system is automatically configured and initialized.

By default, swagger can be used with zero-configuration. This means you can simply
include the swagger fraction in the POM file for your application, and WildFly Swarm will
figure out reasonable defaults. However, if you would like to customize the configuration, this
is possible using ShrinkWrap and SwaggerArchive . Configure this in the main() method for
your application.

public static void main(String[] args) throws Exception {

Swarm swarm = new Swarm();

JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class, "swagger-app.war"


deployment.addClass(TimeResource.class);

// Enable the swagger bits


SwaggerArchive archive = deployment.as(SwaggerArchive.class);
// Tell swagger where our resources are
archive.setResourcePackages("org.wildfly.swarm.examples");
archive.setTitle("My Awesome Application");

deployment.addAllDependencies();
swarm
.fraction(LoggingFraction.createDefaultLoggingFraction())
.start()
.deploy(deployment);
}
}

The packages are recursively scanned, so if you have a package hierarchy, you just need to
set the top level package name. See the SwaggerArchive interface for additional
configuration options.

Swagger 97
WildFly Swarm User's Guide

Usage with WAR packaging ( META-


INF/swarm.swagger.conf )

If you don’t use JAR packaging, like in the example above (no custom Main()), then you
would need to configure swagger through META-INF/swarm.swagger.conf . It allows you to
specify resource packages to be scanned and other atributes, similar to SwaggerArchive in
the previous example.

packages:com.example.rest (1)
root:rest (2)
title:WildFly Swarm Demo (3)

1. resource packages for the swagger annotation scanner (comma delimited, String[])

2. the content root, which typically is configured in the jaxrs.Application

3. arbitraty othe things to pimp up the UI appearance

Swagger UI
The folks over at http://swagger.io have also created an HTML5/JavaScript application for
querying and interacting with swagger-enabled REST APIs. WildFly Swarm provides a
simple way to deploy this application using the Swagger-UI server. See the Servers
documentation for more information.

Swagger 98
WildFly Swarm User's Guide

CDI
The fraction supports CDI (Content & Dependency Injection) which is a handy method for
weaving components together. The primary part of CDI is the @Inject annotation.

Configuration
To use CDI in your application, you need to add the following dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>cdi</artifactId>
</dependency>

Dependency Injection 99
WildFly Swarm User's Guide

Messaging
The Messaging fraction brings support for JMS to your application. Currently, the messaging
capability does not span across multiple independent WildFly Swarm-based services, but is
only available within a single service.

The WildFly Swarm messaging broker is based upon ActiveMQ.

Configuration
To enable messaging for your application, you need to include the following dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>messaging</artifactId>
</dependency>

Additionally, you must configure some destinations for the messaging broker to be useful.
This is done through your main(…​) function.

swarm.fraction(new MessagingFraction()
.defaultServer( (server)->{
server.topic("my-topic")
server.queue("my-queue");
} );
);
);

Remote Message Broker


While the above configures a message broker internal to your application, that is many times
sub-optimal when working with microservices. A better approach may be to run your
message broker as a separate, more persistent process, and simply connect all of your
microservices to it.

WildFly Swarm supports two separate methods for achieving that.

Java API

Messaging 100
WildFly Swarm User's Guide

You can use the same Java API as above to create a remote connection to an outboard
message broker, configuring the host, port, and JNDI name for the pooled connection
factory.

swarm.fraction( new MessagingFraction()


.defaultServer( (server)->{
server.remoteConnection( "remote-mq", (connection)->{
connection.host( "mq.mycorp.com" );
connection.port( 61616 );
connection.jndiName( "java:/jms/remote-mq" );
} );
} );
);

Configuration Properties
Additionally, if you only need a single remote connection, it can be completely configured
using Java system properties, or configuration values from project-defaults.yml .

If any of the following properties are set, a remote connection will be created. Any un-set
properties will use their defaults, as long as at least the swarm.messaging.remote flag is set to
true. If any of the other values are configured explicitly, there is no need to also set
swarm.messaging.remote .

Messaging 101
WildFly Swarm User's Guide

Key Default Value Description

Flag ( true or false ) to


swarm.messaging.remote none signal installation of
remote connection

Base name of the remote


swarm.messaging.remote.name remote-mq
connection. Used to build
JNDI name if not
otherwise specified

swarm.messaging.remote.host localhost
Hostname of the remote
message broker

Port of the remote


swarm.messaging.remote.port 61616
message broker

JNDI name of the remote


pooled connection
factory A combination of
swarm.messaging.remote.jndi-
java:/jms/remote-mq
the two methods above
name may be used, where the
configuration properties
override the values set
through the Java API.

Messaging 102
WildFly Swarm User's Guide

JSF
JavaServer Faces (JSF) is a standard JavaEE API for developing component based user
interfaces in web applications. It utilizes Facelets as the default templating system, though
JSP is still supported.

WildFly Swarm supports JSF with both .war and .jar deployments.

Configuration
To use JSF in your application, you need to add the following dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jsf</artifactId>
</dependency>

Usage
The jsf fraction makes the JSF APIs available to your application through a transitive
dependency. There is no need to add them yourself.

Usage in JAR Application


As the web resources JSF needs are not automatically added to the generated archive, we
need to explicitly add them though our custom main(…​) .

JSF 103
WildFly Swarm User's Guide

Swarm swarm = new Swarm();

WARArchive deployment = ShrinkWrap.create( WARArchive.class );

<!-- Add Beans and other Java classes -->


deployment.addClass(Message.class);

<!-- Add Web resources -->


deployment.addAsWebResource(
new ClassLoaderAsset("index.html", Main.class.getClassLoader()), "index.html");
deployment.addAsWebResource(
new ClassLoaderAsset("index.xhtml", Main.class.getClassLoader()), "index.xhtml");

deployment.addAsWebInfResource(
new ClassLoaderAsset("WEB-INF/web.xml", Main.class.getClassLoader()), "web.xml");
deployment.addAsWebInfResource(
new ClassLoaderAsset("WEB-INF/template.xhtml", Main.class.getClassLoader()), "template.xhtml"

JSF 104
WildFly Swarm User's Guide

Security Realms
Security realms are provided through the management fraction. Security realms can be used
used to secure the management endpoints, but also the monitoring endpoints are even
application level code.

Configuration
To use the management fraction in your application, you need to add the following
dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>management</artifactId>
</dependency>

You may use the InMemoryAuthentication and InMemoryAuthorization plugins for simple
compile-time definition of security-realms. Each of these can be specified programattically or
through user-defined loading of .properties files similar to the default mgmt-
users.properties and mgmt-groups.properties that WildFly normally uses.

new ManagementFraction()
.securityRealm("ManagementRealm", (realm) -> {
realm.inMemoryAuthentication( (authn)->{
authn.add( "admin", "password", true );
});
realm.inMemoryAuthorization( (authz)->{
authz.add( "bob", "admin" );
});
})

If you wish to perform more advanced configuration, please see the JavaDocs for the
Management API.

Security Realms 105


WildFly Swarm User's Guide

Single Sign On using Keycloak


Keycloak is an authentication and authorization server created by JBoss. It runs separate
from any particular application. It acts as the primary authentication/authorization database
of record and can also provide social-login capabilities.

WildFly Swarm provides easy integration with Keycloak.

Currently, WildFly Swarm supports version 2.5.5.Final.

Adding Keycloak support


To bring Keycloak integration to your application, you need the following dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>keycloak</artifactId>
</dependency>

Once this is added, you can use the Secured archive type to secure your application. The
easiest way to integrate is by providing a keycloak.json file in your application classpath
and use .as(Secured.class) .

JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class);


deployment.as(Secured.class);

By default, this only adds support, but not a requirement, on Keycloak. Anonymous users
can still access the entire application. If they are authenticated, the SecurityContext will be
populated with the user’s information.

Protecting your application


You can also protect various aspects of your application after using .as(Secured.class) by
chaining calls to .protect(path)

deployment.as(Secured.class)
.protect( "/some-resource" )
.withMethod( "GET" )
.withRoles( "admin" );

Single Sign On 106


WildFly Swarm User's Guide

If your appliction doesn’t have main(), you can do it with project-defaults.yml.

swarm:
keycloak:
security:
constraints:
- url-pattern: /some-resource
methods: [GET]
roles: [admin]

Configuration
Property Description
External keycloak.json path. If this
swarm.keycloak.json.path property specified, keycloak.json on
classpath will be ignored.

Single Sign On 107


WildFly Swarm User's Guide

Keycloak Server
Generally intended to be used as a standalone service, the Keycloak Server is a fraction like
any other in the WildFly Swarm ecosystem.

Adding Keycloak Server support


To bring a Keycloak Server to your application, you need the following dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>keycloak-server</artifactId>
</dependency>

There is currently no configuration required beyond this. The Keycloak Server will launch
with your application, and be available at the /auth/admin context path.

Standalone Keycloak Server


Please see the chapter on Keycloak Server.

Keycloak Server 108


WildFly Swarm User's Guide

NetflixOSS

Introduction
Netflix, the online movie streaming company, has invested heavily in microservices. To
support their architectures, they have created many projects that have been integrated into
WildFly Swarm.

Ribbon
Ribbon provides a method for registering services by name, and allowing clients to invoke
those services. One of the primary facilities of Ribbon is client-side load-balancing. With
Ribbon, each client discovers possibly many instances of a given service, and uses a
strategy (such as round-robin) to balance requests to the service across the many providers.

Additionally, Ribbon provides a method for wrapping an HTTP/REST invocation in an easy-


to-use Java interface.

Ribbon makes heavy use of both RxJava and Netty.

Hystrix
Part of the Netflix strategy for using microservices involves being able to satisfy (for some
value of "satisfy") requests even if remote services are unavailable. Sometimes called a
circuit-breaker, this pattern allows for providing locally-derived fallback responses when the
bonafide service fails to respond.

The Hystrix components work with Ribbon to provide this circuit-breaker functionality.

For instance, in the case of Netflix’s own consumer product, the "recommendations" for a
given movie or television show may be provided by a specific service. If that service is
unavailable, the UI can still provide some default list of recommendations. Everybody loves
The Big Lebowksi, so it could be returned by the Hystrix component if the intelligent
recommendation service is unavailable.

RxJava
RxJava provides a framework for working with asynchronous & reactive components. If one
service needs to invoke an additional 3 services, RxJava provides the way to fire off the
three additional requests and perform work as each completes (or once all have completed).

Circuit Breaker 109


WildFly Swarm User's Guide

Netty
Netty is an asynchronous I/O framework maintained by Trustin Lee of Twitter (formerly of
Red Hat). Ribbon uses Netty underneath the covers to perform its network actions. The
primary way that Netty is exposed to users of Ribbon is through the ByteBuf interface,
which provides interaction with bytes sent or received from an I/O stream.

Configuration
To use the Netflix OSS stack within your WildFly Swarm application, you need to add the
following dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>ribbon</artifactId>
</dependency>

The necessary components for RxJava, Hystrix and Netty will be transitively made available
to your code.

Usage
In order for your service to participate in the service discovery (as a service to be
discovered, a client performing discovery, or both), your deployment should be converted to
a TopologyArchive at some point.

In the event your deployment has a service you wish to advertise, you subsequently need to
advertise(name) on the resulting TopologyArchive .

A service advertising itself


There are a couple of ways to advertise a service’s name. By default the advertise()
method on TopologyArchive will advertise the simplified name of the archive without the
extension.

Circuit Breaker 110


WildFly Swarm User's Guide

JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class, "recommendations.war");

deployment.as(TopologyArchive.class)
.advertise();

swarm.deploy( deployment );

If you haven’t named the archive, or wish to advertise it with a distinct service-name, there is
a version of advertise(…​) which can take the service name as an argument.

JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class);

deployment.as(TopologyArchive.class)
.advertise( "recommendations" );

swarm.deploy( deployment );

Secured Ribbon
If your application is using Keycloak to secure your services, and you are using Ribbon to
invoke those services, you’ll want to use the secured variant of Ribbon. This requires a
slightly different dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>ribbon-secured</artifactId>
</dependency>

In addition to your normal usage of .as(RibbonArchive) and .as(Secured) , instead of using


the Netflix-provided Ribbon class, you should use the WildFly Swarm-provided
SecuredRibbon class to construct your clients.

RecommendationService recommendations = SecuredRibbon.from(RecommendationService.class);

By using the SecuredRibbon factory, any Keycloak security token will propagate across
invocations of the services using an HTTP Authorization header and a bearer token.

Ribbon Webapp can be used on the client side to secure calls to ribbon services as well.
Just include the keycloak.js Javascript that is provided with the Keycloak server in your
HTML file and call the ribbon constructor function with a keycloak object.

Circuit Breaker 111


WildFly Swarm User's Guide

<script src="/ribbon/ribbon.js"></script>
<script src="http://keycloak-server:9191/auth/js/keycloak.js"></script>
<script>
var keycloak = new Keycloak( '/keycloak.json' );
var Ribbon = ribbon( {keycloak: keycloak} );
</script>

Properties
The following properties control ribbon options:

Name Description Default


Can be used to override
the default /ribbon
swarm.ribbon.context.path /ribbon
context for Ribbon
Webapp

Circuit Breaker 112


WildFly Swarm User's Guide

Vert.x
This fraction adds support for the Vert.x API in Java EE applications by enabling the Vert.x
JCA adapter.

Configuration

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>vertx</artifactId>
</dependency>

Usage
There is no need to configure the VertxFraction if you intend to use the default behavior
(JCA adapter deployed and VertxConnectionFactory registered).

Using the Java API you can inhibit the JCA adapter deployment (if you intend to use just the
Vert.x APIs for example).

swarm.fraction(new VertxFraction()
.inhibitAdapterDeployment()
);

You can also modify the VertxConnectionFactory parameters using the same API

swarm.fraction(new VertxFraction()
.jndiName("java:/eis/MyVertxConnectionFactory")
.clusterHost("myhost")
.clusterPort(1000)
);

Overview
The general purpose of a JCA resource adapter is to provide connectivity to an Enterprise
Information System (EIS) from a Java EE application server. Specifically, the Vert.x JCA
adapter provides both outbound and inbound connectivity with a Vert.x instance.

Integration with Vert.x 113


WildFly Swarm User's Guide

Outbound Connectivity
An application component (e.g Servlet, EJB), can send messages to a Vert.x instance.

Usage:

@Resource(mappedName="java:/eis/VertxConnectionFactory")
VertxConnectionFactory connFactory;

public void sendMessage() throws Exception {


try (VertxConnection conn = connFactory.getVertxConnection()) {
conn.vertxEventBus().send("tacos", "Hello from JCA");
}
}

As with any JCA resource, always call the close() method (or use the try-with-
resources strategy above) when your work is complete to allow the connection to be
returned to the pool. This will not close the underlying Vert.x instance. Please see
the JCA specification for more details.

Inbound Connectivity
Since the JCA 1.5 specification, inbound connectivity is provided via a listener interface
which can be implemented by a Java EE Message Driven Bean (MDB). As opposed to the
default JMS listener type, the Vert.x JCA listener interface allows an MDB to receive
messages from a Vert.x address.

The endpoint of the MDB should implement


io.vertx.resourceadapter.inflow.VertxListener.

Integration with Vert.x 114


WildFly Swarm User's Guide

package io.vertx.resourceadapter.examples.mdb;

import io.vertx.resourceadapter.inflow.VertxListener;
import io.vertx.core.eventbus.Message;

import java.util.logging.Logger;

import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;

import org.jboss.ejb3.annotation.ResourceAdapter;

@MessageDriven(name = "VertxMonitor",
messageListenerInterface = VertxListener.class,
activationConfig = {
@ActivationConfigProperty(propertyName = "address", propertyValue = "tacos"
})
@ResourceAdapter("vertx-ra")
public class VertxMonitor implements VertxListener {

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

/**
* Default constructor.
*/
public VertxMonitor() {
logger.info("VertxMonitor started.");
}

@Override
public <T> void onMessage(Message<T> message) {
logger.info("Got a message from Vert.x at address: " + message.address());

T body = message.body();

if (body != null) {
logger.info("Body of the message: " + body.toString());
}
}
}

Integration with Vert.x 115


WildFly Swarm User's Guide

Topology
When building systems of many microservices, being able to locate, discovery and interact
with them in an ever-changing deployment environment can become a challenge. There are
many solutions to managing a topology of services, each with this own trade-offs.

In a pure WildFly scenario, in an environment where multicast is available, many users rely
upon JGroups to handle discovery and reliable communications between nodes. In other
scenarios, either due to the lack of multicast, heterogenuity of services, or scaling concerns,
different service-discovery mechanisms are used. These may include services such as
Apache Zookeeper or Hashicorp’s Consul.

WildFly Swarm attempts to abstract away the many ways of handling service registration
and discovery through its topology fraction. The topology fraction only provides the
abstractions and APIs. It must work in concert with other specific implementations to actually
provide information about the layout of your concrete services.

At the moment, two topology implementations are available:

JGroups

Consul

Additionally, regardless of the topology implementation selected, WildFly Swarm provides a


topology-webapp which helps bring the topology abstraction to your Javascript-centric

applications running in the browser.

General Usage
Advertising Services

Via Deployment Archive


When using topology in your application, your various archives can be turned into a
TopologyArchive and subsequently advertise() themselves under a variety of names. By

default, a no-arg version of advertise() will advertise the deployed service using the base
name of the archive.

Service Discovery 116


WildFly Swarm User's Guide

JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class, "events.war");

// advertise this deployment as `events`


deployment.as(TopologyArchive.class).advertise();

Additionally, archives can advertise different names, especially in the case where you do not
provide a name when creating the archive.

JAXRSArchive deployment = ShrinkWrap.create(JAXRSArchive.class);

// advertise this deployment as `events`


deployment.as(TopologyArchive.class).advertise("events");

Annotations
If you wish to be more declarative in advertising services, the
org.wildfly.swarm.topology.Advertise annotation may be applied to arbitrary classes.

Usually you would apply the annotation to a JAX-RS resource, a servlet, or some other
reasonable component that exposes a discoverable service. The annotation may be
repeated in the event you wish to advertise a single service under multiple names.

@Advertise("cheesemonger")
@Advertise("cheese-seller")
public class MyResource {
...
}

Runtime API
If you only want some services to register when they are actually alive, or dynamically
registered based upon runtime knowledge, the Topology interface provides a method,
advertise(…​) which can be used within your deployment to advertise a service during any

arbitrary point of execution. It returns an AdvertisementHandle which may be used to


unadvertise the service.

AdvertisementHandle handle = Topology.lookup().advertise("cheesemonger");


...
handle.unadvertise();

General

Service Discovery 117


WildFly Swarm User's Guide

With alladvertisement forms, the service will be registered with the current server’s IP
address, and the appropriate ports for HTTP and HTTPS, if either or both are enabled.

Additionally, if the HTTP port is registered, the service will also be advertised with the tag of
http , and likewise HTTPS services will be tagged as https .

Accessing Topology Information inside a WildFly Swarm


Application
The Topology is made available through JNDI, and provides a simple method for
performing the retrieval of it from within your running application.

Topology topology = Topology.lookup();

Once retrieved, your application and add or remove a TopologyListener in order to be


informed about changes in the topology as services start and stop.

Additionally, the Topology class provides an asMap() method which returns the full current
topology in a Map where the keys are the service names, and the values are a list of
Topology.Entry items, providing access to the host and port.

Service Discovery 118


WildFly Swarm User's Guide

Topology using JGroups


By including the topology-jgroups dependency in your application, and optionally
configuring the jgroups fraction, all of your WildFly Swarm instances can discover one
another without having to run any additional servers. The JGroups topology management
infrastructure is server-less and is peer-to-peer in mosts cases.

Configuration

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>topology-jgroups</artifactId>
</dependency>

Multicast discovery 119


WildFly Swarm User's Guide

Topology using Hashicorp Consul


By including the topology-consul dependency in your application, your WildFly Swarm
instances can register themselves within your Consul catalog. Additionally, they can look up
any other services that are registered, even if they are not WildFly Swarm applications.

Using Consul requires having a Consul server and agent strategy already in place. Further
documentation about Consul can be found at https://www.consul.io/.

Configuration

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>topology-consul</artifactId>
</dependency>

Fault tolerance
In order to build a true fault tolerant system, every application host must have a consul agent
running in client mode. This approach avoids hard coded consul host configuration.

For example, if you don’t use this strategy, your application will need to manage the list of
consul server addresses available and update this list when they become unavailable. This
is consul agent work, you don’t need to do this.

So, instead of every application having its own configuration, you must configure one consul
agent per host application. Thereafter, you configure your app to register itself through the
agent. Start both consul client and you application and everything will work properly.

Furthermore, you won’t have a large number of consul servers because they are resource
intensive. Moreover, the maximum number of servers should be 3-5 per datacenter.
However, you can have any number of clients you need, since they are stateless and they
just need a minimum of resources in order to run properly.

Example
Following what was stated above, suppose you have this structure:

3 hosts running consul agent in server mode;

4 Application hosts each one running:

Integration with Consul 120


WildFly Swarm User's Guide

Consul agent in client mode

a REST API

With this approach, every instance of your application will register itself to consul
agent(client mode) daemon running in localhost(127.0.0.1), like the following picture:

The benefits of this perspective are:

1. Because every host has its own agent, it will be easier to identify in consul what
applications are online or offline because they will be grouped by host;

2. If the consul client(agent) gets offline, only one instance of your application will be
offline as well.

3. Your application will need to know only one consul agent address, therefore, it is pretty
straightforward: localhost;

4. Your application won’t need to manage the consul servers available list, this is agent
job;

5. If you don’t intend to use any implementation of Java Consul clients keeping your
application clean, you can just register your application by configuring the consul
client(agent) config file inside checks section.

Integration with Consul 121


WildFly Swarm User's Guide

Accessing Topology Information outside of a


WildFly Swarm Application
The chief use of accessing topology information outside of a WildFly Swarm application is in
the case of a JavaScript-centric browser-based application. In the event your various
services are publicly routable and directly exposed to a single-page application, being able
to discover them from the user’s browser is useful.

The topology-webapp fraction can be added to a service, and it exposes a URL where
external clients can retrieve a topology.js script which will provide topology access within
the browser. The topology.js script also takes advantage of a Server-Sent-Events (SSE)
endpoint that is also published, in order to push changes of the topology in real-time to the
browser.

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>topology-webapp</artifactId>
</dependency>

By including the above dependency, the topology.js script, along with the SSE endpoint
will automatically be mounted under the context-path of /topology in your application.

JavaScript API
The JavaScript API provided by topology-webapp allows clients to open a persistent
connection to the provided servlet. The known service topology is fed to clients as JSON
data, and updated automatically via Server Sent Events as services come up and go down.
Clients can register listeners to respond to these change events. When you include the
topology.js script in your client application, a topology function is added to the global

scope. This function returns a promise which is resolved when initial topology is obtained
and the API is ready to use. Example usage:

topology().then(function(Topology) {
// listen for changes to the service topology
// and update our component on change
Topology.onTopologyChange(function(topology) {
someReactComponent.setState({data: topology});
});
});

The JSON received from this request will look similar to this.

Javascript API 122


WildFly Swarm User's Guide

{
"time": [{"endpoint": "http://192.168.0.5:9000","tags":["http"]}, {"endpoint": "http://192.168.0.
"events": [{"endpoint": "http://192.168.0.6:9000","tags":["http"]}, {"endpoint": "http://192.168.
}

That is, the client will receive a JSON object that has service names as keys, and a list of
available servers as values. To call these services, however, clients do not need to know the
host names and ports. Topology Webapp manages these for you. You simply need to know
the service names. The JavaScript API makes 3 asynchronous functions available.

getJSON Makes an asynchronous HTTP GET request to a known service.

postJSON Makes an asynchronous HTTP POST request to a known service.

ajax Makes an AJAX request to a known service. This function allows for

customizable AJAX settings.

Each of these functions returns a promise. Here is some example usage.

// Call the time service


// activate a browser alert on response
Topology.getJSON("time").then(alert);

// Post to the events service a new event


// Activate a browser alert on response
Topology.postJSON("events", {name: 'my-event-name'}).then(alert);

// Call a remote event service and provide a custom header


// alert on response
Topology.ajax( "events", '/', {
method: 'POST',
data: {
name: 'event-name',
value: 'event-value'
},
headers: {
Pragma: 'no-cache'
}
})
.then(alert);

You will note that the services are often available on hosts different from the host that served
the webpage and the topology.js script. Web browsers all apply the same-origin policy, so
by default, calling the services will not be possible. The services should send cross-origin
resource sharing HTTP headers to allow cross-origin access.

Javascript API 123


WildFly Swarm User's Guide

Javascript API 124


WildFly Swarm User's Guide

Transactions
The Transactions fraction brings support for JTA and JTS to your application. This is based
on the Narayana transaction manager and more information on configuring transactions can
be found at http://narayana.io/documentation/index.html

Configuration
To enable transactions for your application, you need to include the following dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>transactions</artifactId>
</dependency>

By default Narayana uses two TCP ports for recovery and status information in a distributed
environment. These are 4712 and 4713, respectively. However, you can change these
values in your main(…​) function.

swarm.subsystem(new TransactionsFraction(4712, 4713));

Note, if you change either or both of these values then you must ensure that all WildFly
Swarm instances participating in the same transaction have these same values.

JTA/JTS 125
WildFly Swarm User's Guide

Software Transactional Memory (STM)


As well as Java EE compliant transactions (JTA and JTS), WildFly Swarm provides
advanced transaction support through the Narayana transaction project. One of these
examples is Software Transactional Memory (STM). Much more detail can be found here
(http://narayana.io/docs/project/index.html) but a summary is given below for completeness.

In order to illustrate the Narayana STM implementation let’s look at one of the WildFly
Swarm examples (https://github.com/wildfly-swarm/wildfly-swarm-
examples/tree/master/arjuna/stm-shrinkwrap). This example will use all of the default
settings for STM so it’s worth knowing that there are a lot of other things you can change
when building your applications. We’ll start by creating a fairly simple STM integer object
which has three methods, increment, decrement and value which do pretty much what their
names imply.

@Transactional
public interface Sample {
public void increment ();
public void decrement ();

public int value ();


}

The @Transactional annotation defines that implementations of the interface are to be


managed within a transactional container. All public methods will be assumed to modify the
state of the object, i.e., require write locks. All state variables will be saved and restored.
Now we look at an implementation of this interface.

STM 126
WildFly Swarm User's Guide

@Transactional
public class SampleLockable implements Sample {
public SampleLockable (int init) {
_isState = init;
}

@ReadLock
public int value () {
return _isState;
}

@WriteLock
public void increment () {
_isState++;
}

@WriteLock
public void decrement () {
_isState--;
}

@State
private int _isState;
}

In the implementation we use some additional annotations to override the default values. For
instance @ReadLock tells the system that the value method isn’t going to change the state
of the instance so only a read lock will be obtained.

When creating instances of SampleLockable, we need to pass them to an STM container in


order for it to manage the interactions with the objects. In the example (below) we create
transactions (AtomicAction instances) before operating on the STM objects but that’s not
strictly necessary.

STM 127
WildFly Swarm User's Guide

Container<Sample> theContainer = new Container<Sample>("Demo", Container.TYPE.PERSISTENT, Container.M

Sample obj1 = theContainer.create(new SampleLockable(10));


String str = "Object name: "+theContainer.getIdentifier(obj1)+"\n";

for (int i = 0; i < 10; i++) {


AtomicAction A = new AtomicAction();

A.begin();

obj1.increment();

str += "Transaction value hello" + obj1.value() + "\n";

A.commit();
}

return str;

STM 128
WildFly Swarm User's Guide

Spring
The Spring Framework is a popular choice for developers that don’t want to use Java EE.

WildFly Swarm supports Spring deployments.

Configuration
To bring Spring functionality to your application, you need the following dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>spring</artifactId>
</dependency>

If you also require JSON handling, such as returning JSON response documents from a
REST interface, you will need the following dependency instead:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>spring-rest</artifactId>
</dependency>

Usage
The spring and spring-rest fractions provide some special handling for Spring
applications when used with WildFly Swarm, but they do not provide any Spring Framework
dependencies transitively.

Whatever Spring Framework dependencies your application currently requires are still
necessary within your projects' pom.xml .

Spring 129
WildFly Swarm User's Guide

Management
The management fraction supports enabling the WildFly management interface and
specifying security realms.

Configuration
To use the management fraction in your application, you need to add the following
dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>management</artifactId>
</dependency>

By default, the HTTP-upgrade-based management interface is exposed. You will probably


desire to provide a security-realm at least for the ManagementRealm to secure the
management interface.

You may use the InMemoryAuthentication and InMemoryAuthorization plugins for simple
compile-time definition of security-realms. Each of these can be specified programattically or
through user-defined loading of .properties files similar to the default mgmt-
users.properties and mgmt-groups.properties that WildFly normally uses.

ManagementFraction.createDefaultFraction()
.httpInterfaceManagementInterface((iface) -> {
iface.securityRealm("ManagementRealm");
})
.securityRealm("ManagementRealm", (realm) -> {
realm.inMemoryAuthentication( (authn)->{
authn.add( "bob", "tacos!", true );
});
realm.inMemoryAuthorization( (authz)->{
authz.add( "bob", "admin" );
});
})

If you wish to perform more advanced configuration, please see the JavaDocs for the
Management API.

Remote Access 130


WildFly Swarm User's Guide

Properties
The following properties control options for the management interface:

Name Description Default

The HTTP port


swarm.management.http.port management will listen 9990
on

The HTTPS port


swarm.management.https.port management will listen 9993
on

Remote Access 131


WildFly Swarm User's Guide

Jolokia
Jolokia is a small utility which provides a JSON-based JMX connector over HTTP. WildFly
Swarm supports a simple method for adding Jolokia to your application.

Adding Jolokia
To bring Jolokia to your application, you need to add a dependency on the Jolokia fraction:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jolokia</artifactId>
</dependency>

This is sufficient to bind an unsecured Jolokia to the context root of /jolokia .

If you would like to configure where Jolokia is mounted, you can override the defaults within
your main(…​) method:

Swarm swarm = new Swarm();


swarm.fraction(
new JolokiaFraction("/jmx")
);

The above would make Jolokia available at the path of /jmx .

Adding the Jolokia fraction to your application will bring in the Undertow fraction implicitly if
you have not already included it.

Securing
If you need to secure your Jolokia endpoint (which is highly recommended), the
JolokiaFraction class supports passing in a pre-existing jolokia-access.xml as a file or

URL, or building it programmatically.

swarm.fraction(
new JolokiaFraction()
.jolokiaAccess( "/path/to/jolokia-access.xml" )
);

Jolokia 132
WildFly Swarm User's Guide

Or

swarm.fraction(
new JolokiaFraction()
.jolokiaAccess( (access)->{
access.host( "localhost" );
access.strictChecking();
} )
);

Please see the JavaDocs for JolokiaAccess and related classes.

Jolokia 133
WildFly Swarm User's Guide

Monitor

Configuration
To use the monitor fraction in your application, you need to add the following dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>monitor</artifactId>
</dependency>

Node Status
The monitoring fraction provides access to the runtime status on each node. The runtime
information is exposed through a HTTP interface and gives access following information:

WebContext Description Content-Type


Node specific identifiers
and overall runtime status
/node application/json
(i.e. reload and suspend
states)

{
"name" : "macbook-pro-2",
"server-state" : "running",
"suspend-state" : "RUNNING",
"running-mode" : "NORMAL",
"uuid" : "a8100296-573d-4b40-9648-e82bdb0041d9",
"wfs-version" : "fixme"
}

/heap The JVM heap usage application/json

Health Checks 134


WildFly Swarm User's Guide

{
"heap-memory-usage" : {
"init" : 268435456,
"used" : 56067784,
"committed" : 356515840,
"max" : 3817865216
},
"non-heap-memory-usage" : {
"init" : 2555904,
"used" : 52717328,
"committed" : 57622528,
"max" : -1
}
}

/threads The JVM thread usage application/json

{
"thread-count" : 33,
"peak-thread-count" : 47,
"total-started-thread-count" : 49,
"current-thread-cpu-time" : 66855000,
"current-thread-user-time" : 64003000
}

A list of available health


/health application/json
endpoints

Health Check API


Health checks are implemented using regular JAX-RS API and exposing certain GET
methods through the @Health annotation. Health check responses are expressed using the
HealthStatus and CompositeHealthStatus API’s. Any health status response type will

automatically converted to an application/json response content type and the HTTP status
derived from the HealthStatus.<UP|DOWN> states:

Health Checks 135


WildFly Swarm User's Guide

package org.wildfly.swarm.examples.jaxrs.health;

import java.io.File;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

import org.wildfly.swarm.monitor.Health;
import org.wildfly.swarm.monitor.HealthStatus;

@Path("/app")
public class HealthCheckResource {

@GET
@Path("/diskSpace")
@Health
public HealthStatus checkDiskspace() {
File path = new File(".");
long freeBytes = path.getFreeSpace();
long threshold = 1024 * 1024 * 100; // 100mb
return freeBytes>threshold ? HealthStatus.up() : HealthStatus.down().withAttribute(
}

@GET
@Path("/other")
@Health(inheritSecurity = false)
public HealthStatus checkSomethingElse() {
return HealthStatus.up();
}

Accessing the above endpoint will return a json encoded response like this:

curl --digest -u "<user>:<pass>" http://localhost:8080/health/app/diskSpace

{
"freebytes": "1234567890"
}

Health Check HTTP Endpoints


Health checks (i.e. to integrate with external service registries) can be added by
implementing JAX-RS endpoints and declaring them as a health endpoints through the use
of the '@Health' annotation. Any GET method annotated with @Health will be accessible
through /health/<subresource>

Health Checks 136


WildFly Swarm User's Guide

For instance if you provide an HTTP endpoint for /app/diskSpace , then it will be listed under
/health and accessible through /health/app/diskSpace

curl http://localhost:8080/health

{
"links": [
"/health/app/diskSpace"
]
}

Secure access to @Health endpoints


In order to secure access to the HTTP endpoints you’ll need to include the 'management'
fraction and configure a security realm. See Security Realms for further information.

Usually the security for the endpoints behind '/health' will be inherited. (i.e. the security realm
settings you configured) But you can override this policy with
@Health(inheritSecurity=false) .

If security is inherited, then the JAX-RS endpoint annotated with @Health will not be directly
accessible directly anymore (yields HTTP 403). If you don’t inherit the security, it’s up to your
responsibility to secure the endpoint (or leave it unprotected) .

The combinations of using the @Health annotations with regard to the possible HTTP
requests are outlined in the table below:

Health Checks 137


WildFly Swarm User's Guide

Request path @Health Annotation Outcome

Any HTTP will require


authentication, if the
'ManagementRealm' is
configured. If you don’t
configure a security realm
/health irrelevant
this endpoint will not
require authentication to
access it. The @Health
secure attribute is not
relevant in this case.

Any direct HTTP request


/foo/bar/health inheritSecurity=true to this endpoint will
receive a 403 response.

Any direct HTTP request


to this endpoint will be
passed through. Security
/foo/bar/health inheritSecurity=false
for this endpoint is an
obligation of the
developer.

Health Checks 138


WildFly Swarm User's Guide

Distributed Tracing using Zipkin


The zipking fraction adds the instrumentation to JAX-RS resources to report tracing
information to a Zipkin interoperable backend (i.e. Hawkular, or the Zipkin backend itself).

Configure
Dependency
To add zipkin instrumentation to your WildFly Swarm application, you need to add a
dependency:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>zipkin-jaxrs</artifactId>
</dependency>

Configuration
To configure where the zipkin backend can be found, you need to specify the reportUrl for
the backend to store the tracing data, i.e. 'http://localhost:9411/api/v1/spans'

swarm.fraction(
new ZipkinFraction(<SERVICE_NAME>)
.reportAsync("http://localhost:9411/api/v1/spans")
.sampleRate(0.1f) // keep 10%
);

Distributed Tracing 139


WildFly Swarm User's Guide

JGroups
Traditional WildFly includes a subsystem for clustering, so that many instances can work
together to distribute load. Typically, in a WildFly cluster, each node is homogeneous,
serving the same applications.

WildFly Swarm uses the same subsystem but to a different end. With a cluster of WildFly
Swarm services, each service may be unique and distinct. Clustering, in tandem with the
Topology fraction, serves to assist in discovery of other services.

Configuration
To enable clustering, the following dependency is required:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>jgroups</artifactId>
</dependency>

JGroups 140
WildFly Swarm User's Guide

JGroups
The WildFly clustering functionality is built upon JGroups, a reliable group communications
stack. By default, it uses IP multicast to locate other members of the cluster. In environments
where multicast is not supported, other components may be used.

When using clustering with multicast, JGroups must know which interface to use for
multicast packets. By default, your WildFly Swarm application binds to 0.0.0.0
which means all available interfaces. This is ambiguous to JGroups. Therefore,
when clustering you must explicitly bind to some non-ambiguous interface. You can
do this by setting the swarm.bind.address property through the Maven or Gradle
plugins, or via the command-line using -Dswarm.bind.address=w.x.y.z .

Other properties that affect clustering:

Name Description Default


The id of this node in a
swarm.node.id <a uuid>
cluster

The multicast address


swarm.default.multicast.address that will be used by 230.0.0.4
JGroups

JGroups 141
WildFly Swarm User's Guide

Infinispan
The Infinispan subsystem provides high-performance, clustered, transactional caching. For
example, in a clustered web application, client session identifiers and/or data may need to
be replicated across all nodes in the cluster. The failure of a session-oriented HTTP request
requires that client session data is available on the new failover node.

Including Infinispan Capabilities


To use the Infinispan fraction, just add it to your pom.xml .

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>infinispan</artifactId>
</dependency>

By default, the Infinispan fraction is configured with four cache containers.

Container Cache Cache


Cache Types
Name Names Modes

Default server default replicated SYNC


Container

Web web dist distributed ASYNC


Container

EJB ejb dist distributed ASYNC


Container

local-query , local,
Hibernate default,
hibernate entity , invalidation,
Container SYNC , ASYNC
timestamps replicated

Customizing the Infinispan Configuration


To customize the configuration of your Infinispan fraction, you may use the configuration API
in a main() method. For example:

Infinispan 142
WildFly Swarm User's Guide

public class Main {

public static void main(String...args) {

// Configure a cache container using the wildfly


// swarm configuration API
CacheContainer webCache = new CacheContainer("web")
.defaultCache("dist")
.jgroupsTransport(new JGroupsTransport().lockTimeout(60000L))
.distributedCache("dist", distCache -> distCache
.mode("ASYNC")
.l1Lifespan(0L)
.owners(2)
.lockingComponent(new LockingComponent().isolation("REPEATABLE_READ"))
.transactionComponent(new TransactionComponent().mode("BATCH"))
.fileStore(new FileStore()));

// Create a new fraction, and add the cache container.


// Using the default ctor to create a new InfinispanFraction
// will provide no default caches.
InfinispanFraction fraction = new InfinispanFraction();
fraction.cacheContainer( webCache );

// Instantiate Swarm and add our fraction


Swarm swarm = new Swarm();
swarm.fraction( fraction );

// Start the container


swarm.start();
}

Infinispan is a fairly complex caching system with plenty of knobs and buttons for
programmers and administrators to twiddle. For more information on Infinispan and how its
runtime configuration may be customized, please also see the WildFly documentation and
the official Infinispan Documentation.

Infinispan 143
WildFly Swarm User's Guide

JBoss Forge Add-on


JBoss Forge is a software development tool that extends your IDE, providing wizards and
extensions (add-ons) for different technologies and solutions. Try JBoss Forge by
downloading it at http://forge.jboss.org.

The Wildfly Swarm team provides an add-on that eases the user experience on Swarm.

Installation
From Forge CLI:

addon-install-from-git --url https://github.com/forge/wildfly-swarm-addon.git

From Eclipse/JBoss Developer Studio:


Press Ctrl (Or Command if you are on OSX) + 4 and select the Install an Addon from
GIT option.

Enter https://github.com/forge/wildfly-swarm-addon.git as the url and press "Finish"

From IntelliJ IDEA:


Press Ctrl (Or Command if you are on OSX) + Alt + 4 and select the Install an Addon
from GIT option.

Enter https://github.com/forge/wildfly-swarm-addon.git as the url and press "Finish"

From Netbeans:
Go to the Quick Search field in the upper right corner and type Install an Addon from
GIT .

Enter https://github.com/forge/wildfly-swarm-addon.git as the url and press "Finish"

Features
Wildfly-Swarm Setup command

Forge Add-on 144


WildFly Swarm User's Guide

Using the Forge shell, navigate to a Java EE project, or create one using the project-
new --named demo --stack JAVA_EE_7 command and type the following command if you’re

in shell.

wildfly-swarm-setup

It should read Wildfly-Swarm: Setup if you’re in a GUI environment:

This will make the wildfly-swarm-maven plugin to be installed in your project and the
Wildfly Swarm BOM added to the <dependencyManagement> section.

You may also find some options that will be added to the Wildfly Swarm maven plugin
like the context path, the HTTP port and the HTTP Port offset

Wildfly-Swarm Add Fraction


You can install Wildfly Swarm Fractions by using the command Wildfly-Swarm: Add
Fraction :

[demo]$ wildfly-swarm-add-fraction --fractions


arquillian camel-jms datasources javafx jdr
batch-jberet camel-jmx ejb jaxrs jgroups
bean-validation camel-jpa ejb-remote jaxrs-cdi jmx
camel-cdi camel-mail h2 jaxrs-jaxb jolokia
camel-core camel-other hibernate-search jaxrs-jsonp jpa
camel-cxf camel-undertow hibernate-validator jaxrs-multipart jsf
camel-ejb cdi hystrix jaxrs-validator keycloak
camel-jaxb cdi-ext infinispan jca keycloak-server

Installed fractions are not listed when you press <TAB> to auto-complete

WildFly-Swarm Create Test Class


You can create a Java Test Class and adds Arquillian WildFly Swarm dependency. This
test uses the @DefaultDeployment deployment approach and in case of specifying the
flag asClient it sets this test as testable false and also enriches your test with current
URL.

Forge Add-on 145


WildFly Swarm User's Guide

[demo]$ wildfly-swarm-new-test --target-package org.example.rest --named HelloWorldEndpointTest


***SUCCESS*** Test Class org.example.rest.HelloWorldEndpointTest was created
[demo]$ cd src/test/java/org/example/rest/HelloWorldEndpointTest.java
[HelloWorldEndpointTest.java]$ cat -c .
package org.example.rest;

import org.junit.runner.RunWith;
import org.jboss.arquillian.junit.Arquillian;
import org.wildfly.swarm.arquillian.DefaultDeployment;
import org.junit.Test;

@RunWith(Arquillian.class)
@DefaultDeployment
public class HelloWorldEndpointTest {

@Test
public void should_start_service() {
}
}

Forge Add-on 146


WildFly Swarm User's Guide

Swarmtool
Swarmtool is a standalone jar that is used to wrap an existing JAR or WAR file in a -
swarm.jar without requiring any other tooling.

Usage
To use swarmtool, you’ll first need to download the standalone jar for the WildFly Swarm
version you are using. You can get it from Maven Central with the following (or the
equivalent command on your system):

curl https://repo1.maven.org/maven2/org/wildfly/swarm/swarmtool/2017.11.0-SN

This jar file is executable on systems that provide /bin/sh , so you if you are on one of
those systems, you can rename it to something nicer (like swarmtool ), and execute it with:

swarmtool path-to-war

If that isn’t an option for you, you can always execute it with java -jar :

java -jar swarmtool-2017.11.0-SNAPSHOT-standalone.jar path-to-war

Command-line Options
Name Description

Set a property to be used at runtime by


-Dkey=value
the -swarm.jar. Overrides values from --
properties-file . See the Properties
section below.

If specified, causes the -swarm.jar to be


--executable generated as a executable on systems
where /bin/bash is available.

SwarmTool 147
WildFly Swarm User's Guide

A list of extra fractions to include when


auto-detection is used, useful for fractions
that can’t be detected or user-provided
fractions. Each fraction can be of the form
-f , --fractions=x,y,z
group:name:version , name:version , or
name . If no group is provided,
org.wildfly.swarm is assumed. If no
version is provided, the version is looked
up from the WildFly Swarm BOM for the
version of swarmtool you are using.

-h , --help Print usage message and exit.

-v , --version Print version and exit.

A list of paths to dirs containing any


--modules=dir1,dir2 required JBoss Modules module
specifications

The name of the final jar sans the -


-n , --name=name
swarm.jar suffix (default: <source name>)

If specified, dependencies will be included


--no-bundle-deps
in the -swarm.jar. Otherwise, they will be
resolved from $M2_REPO or the network at
runtime.

If specified, no attempt is made to detect


--no-fraction-detect the fractions the WAR needs. See
Fraction Detection section below.

Directory where the final jar will be written


-o , --output-dir=path
(default: .)

Sets properties to be used at runtime by


--properties-file the -swarm.jar. See the Properties section
below.

A list of additional maven repositories to


--repos=url1,url2 use in addition to Maven Central and the
JBoss Public Repository.

Fraction Detection

SwarmTool 148
WildFly Swarm User's Guide

Swarmtool will attempt to auto-detect needed fractions by scanning the WAR file. You can
augment the list of fractions it will include with the --fractions option, and you can disable
fraction detection completely with --no-fraction-detect . Note that in that case, you will
have to specify all needed fractions with --fractions . Any fractions specified via --
fractions will override any corresponding fractions that are discovered.

Properties
Many properties may be used to configure execution and affect the packaging or running of
your application.

You can use the --properties-file or -D options to specify system properties that will be
stored within the -swarm.jar and applied when running your application.

Any properties added to the uberjar can of course be overridden at runtime using the
traditional -Dname=value mechanism of java .

Please see Configuration Properties for a non-exhaustive list of useful properties.

SwarmTool 149
WildFly Swarm User's Guide

Pre-built Servers
The WildFly Swarm project has pre-built some standalone servers. The source for these
reside in the standalone-servers portion of the repository.

MicroProfile

Keycloak

Swagger UI

Management Console

Pre-built Servers 150


WildFly Swarm User's Guide

MicroProfile
MicroProfile is a new effort that is underway which attempts to refine the enterprise Java
specifications for use in microservices.

The currently included bits are:

JAX-RS

JSON-P

CDI

WildFly Swarm MicroProfile


WildFly Swarm provides a hollow MicroProfile standalone server which can be used to
deploy any compliant .war application.

Download
You can download the server here.

Usage

java -jar microprofile-2017.11.0-SNAPSHOT-hollowswarm.jar myapp.war

MicroProfile 151
WildFly Swarm User's Guide

Keycloak Server
The WildFly Swarm project has built a standalone uberjar for running Keycloak Server.

It’s Maven coordinates are:

<dependency>
<groupId>org.wildfly.swarm.servers</groupId>
<artifactId>keycloak</artifactId>
<classifier>swarm</classifier>
</dependency>

Download
Download or otherwise obtain the -swarm.jar and simply execute it as any other service
created with WildFly Swarm.

Usage
java -jar keycloak-2017.11.0-SNAPSHOT-swarm.jar

Keycloak Server 152


WildFly Swarm User's Guide

Swagger UI Server
Swagger UI is a dependency-free collection of HTML, Javascript, and CSS assets that
dynamically generate documentation and sandbox from a Swagger-compliant API. WildFly
Swarm provides an easily deployable and customizable version of this application.

It’s maven coordinates are:

<dependency>
<groupId>org.wildfly.swarm.servers</groupId>
<artifactId>swagger-ui</artifactId>
<classifier>swarm</classifier>
</dependency>

Download the -swarm.jar and execute it with the java command.

$ java -jar swarm-ui-2017.11.0-SNAPSHOT-swarm.jar

You can customize any of the HTML, CSS, JavaScript or image assets provided by the
server by specifying these on the command line. The command line will accept a path to a
jar or war file on disk, a path to a directory on disk containing your web resources, or

maven coordinates to a jar file.

The jar file provided (or the directory on disk) will be overlaid on to the resources provided
by swagger-ui . For example, to customize the main page, provide an index.html file at the
root of the jar or war file, or in the top level of the directory provided.

$ jar tvf my-custom-project.jar


0 Mon Feb 01 11:42:08 EST 2016 META-INF/
68 Mon Feb 01 11:42:08 EST 2016 META-INF/MANIFEST.MF
312 Mon Feb 01 11:41:58 EST 2016 index.html

$ java -jar swarm-ui-2017.11.0-SNAPSHOT-swarm.jar ./my-custom-resources.jar

This will cause the index.html file provided in my-custom-resources.jar to be served


instead of the default provided by swagger-ui .

Swagger UI 153
WildFly Swarm User's Guide

Management Console
The management console is a standalone Web application that allows you to connect to a
management interface of a running WildFly or WildFly Swarm instance.

Configuration
To enable the Management console in your application, you need to add the following
dependency to your Swarm application:

<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>management-console</artifactId>
</dependency>

There is a bug in WildFly 10.0.0.Final that prevents Swarm to register a


management-console bound to the management interface of the same running
instance (without prompting for the target server when accessed). This is already
fixed and should be available in the next WildFly release.

Usage
Using the Java API, you can change the management console context root (default is
/console )

swarm.fraction(new ManagementConsoleFraction()
.contextRoot("/general-console")
);

Management Console 154


WildFly Swarm User's Guide

Additional Reading

Reading on microservices concepts


We cannot fully cover the wide range of microservice concepts and related topics in this user
guide. It’s therefore recommended that you read up about related ideas yourself relate this
information to a situation that concerns you, like a recent software project or upcoming
architectural discussions with your peers.

The following is a list of resources that we can recommend to get you started.

Online articles
Eberhard Wolff, "Microservices Primer"

Martin Fowler, "Microservices in a Nutshell"

Microservice Books
Sam Newman. "Building Microservices"

Eric Evans, "Domain Driven Design"

WildFly Swarm
Homepage

Blog

OpenShift
OpenShift Origin

Additional Reading 155


WildFly Swarm User's Guide

Getting Involved
WildFly Swarm is an open-source project sponsored by Red Hat, Inc.

Source Code
WildFly Swarm’s source-code is completely open and hosted on GitHub under the WildFly
Swarm organization:

https://github.com/wildfly-swarm

Documentation
This documentation is also maintained on GitHub and published using GitBooks.io.

https://github.com/wildfly-swarm/wildfly-swarm-users-guide

Bugs & Feature Requests


The project uses JIRA to track bugs and feature requests:

https://issues.jboss.org/browse/SWARM

Chat
You can find us in #wildfly-swarm on Freenode.

Contributing to WildFly Swarm 156


WildFly Swarm User's Guide

Implementation Details
This chapter mostly serves as a road-map for users who are curious about the actual inner
workings of WildFly Swarm.

Uberjar Layout
The layout of the generated myapp-swarm.jar looks roughly like:
wildfly-swarm.properties

File containing the version of WildFly Swarm used in the construction.


META-INF/wildfly-swarm.properties

File containing all user-specified (or default) properties to be used when executing the
uberjar. For example:

#Generated by WildFly Swarm


#Tue Aug 25 11:38:12 BRT 2015
swarm.port.offset=3
swarm.logstash.hostname=localhost
swarm.context.path=/
swarm.bind.address=127.0.0.1
java.net.preferIPv4Stack=true
swarm.node.id=booker-pricing
swarm.app.artifact=booker-pricing-1.0.0.Alpha01-SNAPSHOT.jar
swarm.logstash.port=8000

META-INF/wildfly-swarm-bootstrap.conf

Lists all WildFly Swarm module dependencies in Maven GAV format. For example:

org.wildfly.swarm:logging-modules:2017.11.0-SNAPSHOT
org.wildfly.swarm:security-modules:2017.11.0-SNAPSHOT
org.wildfly.swarm:hystrix:2017.11.0-SNAPSHOT
org.wildfly.swarm:rxnetty:2017.11.0-SNAPSHOT
org.wildfly.swarm:rxjava:2017.11.0-SNAPSHOT
org.wildfly.swarm:ee-modules:2017.11.0-SNAPSHOT
org.wildfly.swarm:logstash-modules:2017.11.0-SNAPSHOT
org.wildfly.swarm:ribbon-secured-modules:2017.11.0-SNAPSHOT

META-INF/wildfly-swarm-application.conf

Lists all application dependencies as JBoss-Module names or Maven GAVs. For


example:

Implementation Details 157


WildFly Swarm User's Guide

module:org.wildfly.swarm.keycloak
module:org.wildfly.swarm.netflix.ribbon.secured
module:org.wildfly.swarm.security
module:org.wildfly.swarm.logstash
module:org.wildfly.swarm.netflix.ribbon
gav:org.wildfly.swarm:undertow:2017.11.0-SNAPSHOT
gav:org.wildfly.swarm:io:2017.11.0-SNAPSHOT
gav:io.netty:netty-transport:4.0.27.Final
gav:io.netty:netty-buffer:4.0.26.Final
gav:org.wildfly.swarm:clustering:2017.11.0-SNAPSHOT
gav:javax.json:javax.json-api:1.0
gav:io.reactivex:rxnetty:0.4.9

META-INF/MANIFEST.MF

Standard Java archive manifest which specifies the WildFly Swarm bootstrap Main-
Class along with tracking the user-provided main class. For example:

Main-Class: org.wildfly.swarm.bootstrap.Main
Wildfly-Swarm-Main-Class: org.mycorp.myapp.Main

_bootstrap/

Directory containing the .jar or .war of the application.


m2repo/

Maven-style repository of all jars


modules/

JBoss-Modules tree of module.xml files which reference jars by Maven GAV

Bootstrap
When the myapp-swarm.jar is executed through java -jar , the
org.wildfly.swarm.bootstrap.Main class is always executed initially. It initializes the JBoss-

Modules module system and sets up the modules listed in META-INF/wildfly-swarm-


bootstrap.conf

It then loads the user-provided main-class from the artifact in the _bootstrap/ directory and
executes it.

ClassLoaders
Conceptually there are 3 classloader spaces in a WildFly Swarm uberjar.

Implementation Details 158


WildFly Swarm User's Guide

The first is the system classloader, which is used initially when bootstrapping the core
Main .

Second, the user-provided main-class is executed in a relatively vanilla classloader to


perform the Container and fraction configuration.

Thirdly, the Container configuration is passed to the back-end classloader which then
converts the simple POJO configuration objects into the appropriate control structures used
to initialize the WildFly container.

When a user-provided main-class is executed directly from an IDE, the first two conceptual
classloaders are actually both satisfied by the system ClassLoader .

Implementation Details 159


WildFly Swarm User's Guide

Fraction Authoring

Introduction
The composable pieces of WildFly Swarm are called fractions. Each fraction starts with a
single Maven-addressable artifact which may transitively bring in others.

The pom.xml
It is useful to set at least a pair of properties, specifying the version of the WildFly Swarm
SPI and fraction-plugin being used:

<properties>
<version.swarm>2017.7.0</version.swarm.spi>
<version.swarm.fraction-plugin>57</version.swarm.fraction-plugin>
</properties>

You can include all of the primary bits of WildFly Swarm using the bom-all artifact in a
<dependencyManagement> import. Additionally, you’ll need two more dependencies added in

order to write CDI components to configure the server.

Fraction Authoring 160


WildFly Swarm User's Guide

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>bom-all</artifactId>
<version>${version.swarm}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

Additionally, the wildfly-swarm-fraction-plugin should be configured within the parent


pom.xml so that it fires for every sub-module:

<build>
<plugins>
<plugin>
<groupId>org.wildfly.swarm</groupId>
<artifactId>wildfly-swarm-fraction-plugin</artifactId>
<version>${version.swarm.fraction-plugin}</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>process</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

What’s in a Fraction

Fraction Authoring 161


WildFly Swarm User's Guide

A "fraction" can include all or none of the following components. Ultimately a fraction
contributes configuration or capabilities to a runtime system.

Package Layout
For a given fraction, a unique package root is required. In the usual case of the core code, it
matches the pattern of org.wildfly.swarm.CAPABILITY , such as org.wildfly.swarm.undertow
or org.wildfly.swarm.naming .

Within the root the following additional sub-packages may be found:

deployment

detect

internal

runtime

The org.wildfly.swarm.CAPABILITY.detect package holds classes that are used for


determining if the fraction applies to a given deployment.

The org.wildfly.swarm.CAPABILITY.runtime and org.wildfly.swarm.CAPABILITY.internal


package holds classes that are considered "back-end" components, loaded via our internal
CDI implementation in order to configure and setup the server.

The org.wildfly.swarm.CAPABILITY.deployment package holds other classes that should not


be considered either part of the front-end API of the fraction exposed to users, nor a part of
the back-end components to configure the server. Instead, the .deployment package is a
sidecar to hold additional classes that may be added to deployment archives.

The module.conf
Alongside your pom.xm you need at least an empty module.conf file to signal the plugin
that your build is actually a fraction.

This file is used to enumerate the JBoss-Modules dependencies your fraction may have, and
helps produce the resulting module.xml files for your fraction.

In this file, one per line, you may list the module dependencies you may have. If your fraction
relies on runtime linking to other fractions, they should typically be listed in this file.

org.jboss.logging
org.wildfly.swarm.undertow

Fraction Authoring 162


WildFly Swarm User's Guide

Maven Artifact Dependencies


You cannot specify maven artifact style dependencies in the module.conf file. If you have
such dependencies, you need to create a JBoss-Modules module.xml descriptor in your
fraction’s src/main/resources/modules directory. For example, the org.wildfly.swarm:fluentd
fraction includes the following src/main/resources/modules/org/fluentd/main/module.xml to
declare dependencies on:

org.fluentd:fluent-logger:${fluentd.version}

org.msgpack:msgpack:0.6.8

com.googlecode.json-simple:json-simple:1.1.1

org.javassist:javassist:3.18.1-GA

org.slf4j:slf4j-api:1.7.7.jbossorg-1

org.jboss.logmanager:jboss-logmanager-ext:${version.jboss-logmanager-ext}

<?xml version="1.0" ?>


<module xmlns="urn:jboss:module:1.3" name="org.fluentd">

<resources>
<artifact name="org.fluentd:fluent-logger:${fluentd.version}"/>
<artifact name="org.msgpack:msgpack:0.6.8"/>
<artifact name="com.googlecode.json-simple:json-simple:1.1.1"/>
<artifact name="org.javassist:javassist:3.18.1-GA"/>
<artifact name="org.slf4j:slf4j-api:1.7.7.jbossorg-1"/>
<artifact name="org.jboss.logmanager:jboss-logmanager-ext:${version.jboss-logmanager-ext}"
</resources>

<dependencies>
<module name="org.jboss.logmanager"/>
<module name="javax.json.api"/>
<module name="javax.xml.stream.api"/>
</dependencies>
</module>

For more information on the syntax of the JBoss-Modules module.xml descriptor, see
https://jboss-modules.github.io/jboss-modules/manual/.

Generated modules
The wildfly-swarm-fraction-plugin generates a number of module.xml descriptors depending
on what features it has found in the faction. You may override any one of these descriptors
by providing the corresponding module.xml in your src/main/resources/modules directory.

Fraction Authoring 163


WildFly Swarm User's Guide

api: this is a module definition that depends on all modules specified in module.conf +
swarm container and cdi modules, the fraction artifact, excluding the <fraction-root-
package>/{runtime,deployment} packages if they exist. It is used to configure fractions,
container, etc, when running in Uber jar mode when JBoss-Modules is fully active

deployment: is a module definition that depends on all modules specified in


module.conf, the fraction:main module, excluding the <fraction-root-
package>/{runtime,META-INF} paths, the fraction artifact excluding the <fraction-root-
package>/{runtime,internal,META-INF} packages. This module is automatically added
as a module dependency to any deployments. It’s a convenient way to had code into
the user deployment for handling integrations with the container.

main: This is a module definition similar to API, but active when running from IDE or
wildfly-swarm:run

runtime: this is a module definition that depends on the fraction artifact with the root
excluded, the main module, swarm and cdi modules, and all modules in module.conf.
This module is used to load the fraction and any of its runtime code. These modules are
what JBoss Modules loads for use by the WF self contained server to make extensions,
subsystems, etc available for the deployment.

The *Fraction.java
If the fraction includes configuration capabilities, or otherwise alters the runtime system
through deployments or adjustments to the server, it may include an implementation of
org.wildfly.swarm.spi.api.Fraction .

Any opaque POJO configuration details that are required may be added in the
implementation, and will be made available to the back-end runtime portion during server
boot-up to control configuration.

In the event that no particular configuration values are required, no Fraction


implementation is required. If provided, it should reside in the absolute root of the fraction
java package, such as org.wildfly.swarm.undertow.UndertowFraction .

Fraction Authoring 164


WildFly Swarm User's Guide

package com.mycorp.cheese;

import java.util.Set;
import java.util.HashSet;
import org.wildfly.swarm.spi.api.Fraction;

public class CheeseFraction implements Fraction {


// arbitrary configuration parameters are allowed

public void cheese(String type) {


this.cheeses.add( type );
}

public void cheeses(Set<String> types) {


this.cheeses.addAll( types );
}

public Set<String> cheeses() {


return this.cheeses;
}

private Set<String> cheeses = new HashSet<>();


}

Runtime CDI Components


Within the runtime sub-package of the fraction, a variety of CDI-enabled components may
be used. Within these classes, you can use typical CDI mechanisms such as @Inject ,
@Produces , and Instance<> in order to accomplish whatever is required for your fraction.

Typically these components would, at the minimum, inject their own fraction. They should
each be marked as @Singleton .

@Singleton
public class MyComponents implements Whatever {

@Inject
private MyFraction myFraction;

DeploymentProcessor

If your fraction needs an opportunity to alter or otherwise prepare all deployed archives, you
may implement the org.wildfly.swarm.spi.api.DeploymentProcessor interface.

Fraction Authoring 165


WildFly Swarm User's Guide

@DeploymentScoped
public class MyArchivePreparer implements DeploymentProcessor {

private final Archive archive;

@Inject
private MyFraction myFraction;

@Inject
public MyArchivePreparer(Archive archive) {
this.archive = archive;
}

@Override
public void process() throws Exception {
WARArchive war = archive.as(WARArchive.class);
...
}
}

Useful Annotations

There are a few additional annotations that you may include on your fraction class:

@WildFlyExtension(module = "org.keycloak.keycloak-adapter-subsystem"), if the


fraction is installed, then the named WildFly Extension will also be installed. This is
equivalent to the <extension> element in the WildFly standalone.xml.

@WildFlySubsystem("keycloak"), if the fraction is installed, then the named WildFly


Subsystem will also be included. This is equivalent to the <subsystem> element in the
WildFly standalone.xml.

@DeploymentModule(name = "org.keycloak.keycloak-core") adds the indicated module


dependency to the deployment archives that are appropriate to a fraction.

Injecting IndexView

If your fraction needs an opportunity to process the Jandex metadata of all deployed
archives, you can inject org.jboss.jandex.IndexView into your DeploymentProcessor
instance, e.g.

Fraction Authoring 166


WildFly Swarm User's Guide

@DeploymentScoped
public class ServiceClientProcessor implements DeploymentProcessor {
private final Archive<?> archive;
private final IndexView index;

@Inject
public ServiceClientProcessor(Archive archive, IndexView index) {
this.archive = archive;
this.index = index;
}
}

Customizer

Most of the heavy-lifting of configuration may occur within implementations of


org.wildfly.swarm.spi.api.Customizer .

If your fraction is always present with other fractions, cross-fraction manipulation may be
achieved.

Two different executions of Customizers occur. All customizers annotated with @Pre are
fired, followed by all annotated with @Post .

@Post
@Singleton
public class MyCustomizer implements Customizer {

@Inject
private MyFraction myFraction;

@Inject
private UndertowFraction undertowFraction;

public void customize() {


if ( undertowHasSSL() ) {
doSomethingSpecialWithMyFraction()
}
}
}

Archive producers

In some cases, a fraction implicitly produces a deployment archive by its simple presence in
the dependency graph. For example, including org.wildfly.swarm:jolokia ensures that the
Jolokia web-app is deployed. This is accomplished by having a CDI component that
@Produces a ShrinkWrap Archive . No particular interface is required to be implemented.

Fraction Authoring 167


WildFly Swarm User's Guide

@Singleton
public MyArchiveProducers {

@Inject
private MyFraction myFraction;

@Produces
Archive myManagementConsole() {
WARArchive archive = ... // produces the Archive any way you like
archive.setContextRoot( myFraction.getContextRoot() );
return archive;
}
}

The @ConfigurationValue annotation


Any of your components can also @Inject configuration values that are sourced from either
project-defaults.yml based upon the currently active stage, or system properties if no

project stage is available.

@Inject @ConfigurationValue('my.db.url')
private String dbUrl;

@Inject @ConfigurationValue('my.age')
private int age;

Transitive dependencies
If your fraction depends upon the presence of a Servlet container being configured, you
should add a dependency on the necessary fractions into your pom.xml

<dependencies>
<dependency>
<groupId>org.wildfly.swarm</groupId>
<artifactId>undertow</artifactId>
</dependency>
</dependencies>

By doing this, a user must only include your fraction, and the Undertow fraction will be
dragged along implicitly into their application.

Fraction Authoring 168

You might also like