Download from http://www.wildfly.org
Untar to /opt
and create a symlink to /opt/wildfly
.
# separate user for running WildFly sudo adduser --system wildfly sudo addgroup --system wildfly sudo usermod -g wildfly wildfly # set primary group of user wildfly to group wildfly # set owner of symlink & all WildFly files to wildfly sudo chown --no-dereference wildfly:wildfly /opt/wildfly sudo chown -HR wildfly:wildfly /opt/wildfly
Create a management user
sudo -u wildfly /opt/wildfly/bin/add-user.sh
Start WildFly (optionally with command line parameters)
sudo -u wildfly /opt/wildfly/bin/standalone.sh
Visit the managment console: https://localhost:9990
/opt/wildfly/bin/standalone.conf
:
Configure JVM arguments (e.g. -Xss
, -Xmx
) for standalone/server deployment. Note that when starting WildFly from Eclipse you need to configure these parameters in Eclipse!
It's also a good idea to explicitly set UTF-8 as default:
JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8" JAVA_OPTS="$JAVA_OPTS -Dsun.jnu.encoding=UTF-8"
Create the file /etc/systemd/system/wildfly.service
and adapt the IP to the IP the service is publicly accessible with:
[Unit] Description=WildFly After=network.target [Service] Type=simple User=wildfly Group=wildfly ExecStart=/opt/wildfly/bin/standalone.sh -b 127.0.0.1 -bmanagement 127.0.0.1 [Install] WantedBy=multi-user.target
With WantedBy=multi-user.target
we specify that we want to start WildFly after boot. For autostart to work we also have to enable the service:
sudo systemctl enable wildfly
Manually use / manage the service with:
sudo systemctl start wildfly sudo systemctl stop wildfly systemctl status wildfly journalctl -f -u wildfly # view log and follow it live
In case your deployments have a long setup time you must extend the default limit of 300 seconds.
Add these system properties to your /opt/wildfly/standalone/configuration/standalone.xml
. The system-properties are a child element of server and must come after the extensions section. The timeout value is in seconds:
<server..> <extensions> ... </extensions> <system-properties> <property name="jboss.as.management.blocking.timeout" value="900"/> </system-properties> ...
Also add the timeout to the deployment-scanner:
<profile> <subsystem xmlns="urn:jboss:domain:deployment-scanner:2.0"> <deployment-scanner path="deployments" relative-to="jboss.server.base.dir" scan-interval="5000" deployment-timeout="900" runtime-failure-causes-rollback= "${jboss.deployment.scanner.rollback.on.failure:false}"/> </subsystem> ... </profile>
And to allow long transactions (if your logs contain tasks cancelled by the TransactionReaper) configure the default-timeout of the transaction subsystem:
<profile> <subsystem xmlns="urn:jboss:domain:transactions:5.0"> <core-environment node-identifier="${jboss.tx.node.id:1}"> <process-id> <uuid/> </process-id> </core-environment> <recovery-environment socket-binding="txn-recovery-environment" status-socket-binding="txn-status-manager"/> <coordinator-environment default-timeout="900" statistics-enabled="${wildfly.transactions.statistics-enabled:${wildfly.statistics-enabled:false}}"/> <object-store path="tx-object-store" relative-to="jboss.server.data.dir"/> </subsystem> ... </profile>
Go to the undertow subsystem configuration in /opt/wildfly/standalone/configuration/standalone.xml
.
Then add the gzip filter to the filter section and a filter-ref to host section under server, e.g.:
<subsystem xmlns="urn:jboss:domain:undertow:6.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other"> <buffer-cache name="default"/> <server name="default-server"> <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true"/> <https-listener name="https" socket-binding="https" security-realm="ApplicationRealm" enable-http2="true"/> <host name="default-host" alias="localhost"> <location name="/" handler="welcome-content"/> <http-invoker security-realm="ApplicationRealm"/> <filter-ref name="gzipfilter" predicate="regex[pattern='text/html|text/css|application/javascript|application/json',value=%{o,Content-Type}] and max-content-size[value=1024]"/> </host> </server> <servlet-container name="default"> <jsp-config/> <websockets/> </servlet-container> <handlers> <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/> </handlers> <filters> <gzip name="gzipfilter"/> </filters> </subsystem>
Source: http://mcaikovski.blogspot.com/2018/01/how-to-activate-gzip-compression-of.html
This will then work e.g. for welcome-content, which is static. For e.g. REST services look into http://docs.jboss.org/resteasy/docs/3.5.1.Final/userguide/html/gzip.html
Changing the default ports is easy. Look out for socket-binding in /opt/wildfly/standalone/configuration/standalone.xml
:
<socket-binding name="http" port="${jboss.http.port:80}"/> <socket-binding name="https" port="${jboss.https.port:443}"/>
Note that serving on ports below 1024 requires root privileges. This means when manually starting WildFly you can start it with sudo
, but for a systemd service we need a different approach:
The safe way is to use setcap
to allow java
to bind ports but don't give it any more privileges. This must be done after every update of java!
sudo setcap cap_net_bind_service=+epi $JAVA_HOME/bin/java sudo setcap cap_net_bind_service=+epi $JAVA_HOME/jre/bin/java
It is not recommended to simply use User=root
in wildfly.service
.
In /opt/wildfly/standalone/configuration/standalone.xml
add the following configuration to automatically redirect e.g. from port 80 to https on port 443.
In subsystem (undertow) > filters add a redirect including your full domain name. The %U
retains the rest of the URL.
<rewrite name="http-to-https" redirect="true" target="https://example.com:443%U"/>
..or if you do not need to retain the domain name you can replace it with the host ip (%h
)
<rewrite name="http-to-https" redirect="true" target="https://%h:443%U"/>
In subsystem (undertow) > server > host add a reference to the filter. Adapt the predicate to your needs, the example only activates the filter when port 80 is accessed.
<filter-ref name="http-to-https" predicate="equals(%p,80)"/>
See the undertow documentation for more variables.
When using HTTPS you should most probably also provide a valid TLS (aka SSL) certificate. Otherwise browsers tend to block access to your page or at least give a big warning that the page is not secure.
explore: there seems to be a new way to configure Letsencrypt directly via the WildFly CLI since WildFly 14: https://developer.jboss.org/people/fjuma/blog/2018/08/31/obtaining-certificates-from-lets-encrypt-using-the-wildfly-cli
The certificate must be present in a Java Keystore file. Copy com.example.jks
to /opt/wildfly/standalone/configuration
.
Then add the security-realm under management > security realms in /opt/wildfly/standalone/configuration/standalone.xml
:
<security-realm name="SslRealm"> <server-identities> <ssl> <keystore path="com.example.jks" relative-to="jboss.server.config.dir" keystore-password="YOUR_PASSWORD"/> </ssl> </server-identities> </security-realm>
And add this in subsystem (undertow) > server:
<https-listener name="default-ssl" socket-binding="https" security-realm="SslRealm" enable-http2="true"/>
See SSL/TSL Certificates for more details.
Sources: http://reallifejava.com/configuring-ssl-in-wildfly-8, https://stackoverflow.com/questions/32008182/wildfly-9-http-to-https
By default port 9990
is used for deployment via the wildfly maven plugin and to access the web-based management interface.
For deployments to servers except localhost
and to enter the management interface a 'Management User' in the 'ManagementRealm' is required:
sudo -u wildfly /opt/wildfly/bin/add-user.sh
This script creates an entry for each user in /opt/wildfly/standalone/configuration/mgmt-users.properties
.
Using Maven to deploy to WildFly/Jboss: deploy_to_jboss
Check the official quickstart tutorials and the BOMs
To access a database, e.g. PostgreSQL, the driver dependency must not be included into the deployment itself but a data source must be configured within WildFly. Simply including the database dependency into your deployment opens a memory leak since they corresponding classes can not be removed by WildFly during un/redeploys of your project.
An easy way configure the data source is to use the WildFly Managment web frontend (http://your-server:9990) to upload the driver .jar and create a data source:
Then configure the data source:
The data source configuration can also be found in /opt/wildfly/standalone/configuration/standalone.xml
.
More info in the official docs.
Put the following configuration of the maven-war-plugin into the build/plugins section of your pom.xml:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <archive> <manifestEntries> <!-- "The Dependencies manifest header is used to specify dependencies that a jar file has." (https://docs.jboss.org/author/display/MODULES/Manifest+module+information) Note that sql drivers must NOT be put in the war file (this is a source of memory leaks), so they are deployed directly to Wildfly, and they needed to be listed as application dependency here. --> <Dependencies>deployment.postgresql-9.4.1208.jar</Dependencies> </manifestEntries> </archive> </configuration> </plugin>
@ApplicationScoped public class DB { @Resource(mappedName = "java:/PostgresDS") private DataSource ds; boolean connectToDb(String userId) { try (Connection conn = ds.getConnection(); Statement statement = conn.createStatement(); ResultSet rs = statement.executeQuery("SELECT id FROM um_user WHERE id=" + userId)) { //... } catch (SQLException e) { //... } } }
In jboss-cli you add new loggers and configure existing loggers using these commands
# create logger /subsystem=logging/logger=at.ac.ait:add(level=DEBUG) # set loglevel /subsystem=logging/logger=at.ac.ait:write-attribute(name=level,value=ALL) # note that the "FINEST" level of java.util.logging maps only to level ALL (and not to TRACE)
To remove a logger:
/subsystem=logging/logger=at.ac.ait:remove
To specify an Alternative Implementation for a Bean and have it override the default implementation use:
import javax.annotation.Priority; import javax.ejb.Stateless; import javax.enterprise.inject.Alternative; @Alternative @Priority(1) @Stateless public class BetterMyBean implements MyBean { ... }
CDI brings its own EventBus implementation. See https://docs.oracle.com/javaee/6/tutorial/doc/gkhic.html
1. Define Dummy Event
public class DummyEvent{}
2. Define Listener
import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; @ApplicationScoped public class DummyEventListener{ public void myObserverMethod(@Observes DummyEvent e) { doSomethingWith(e);} }
3. Fire Event
import javax.inject.Inject; import javax.enterprise.event.Event; import javax.enterprise.context.ApplicationScoped; @ApplicationScoped public class Something { @Inject private Event<DummyEvent> dummyEvent; public void someMethod() { dummyEvent.fire(new DummyEvent()); } }
Events seem to be processed syncronously. Asyncronous event processing can easily be enabled by defining an EventListener like this:
import javax.ejb.Asynchronous; import javax.ejb.ConcurrencyManagement; import javax.ejb.ConcurrencyManagementType; import javax.ejb.Singleton; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; @ApplicationScoped @Singleton @ConcurrencyManagement(ConcurrencyManagementType.BEAN) public class AsynchronousEventListener { @Asynchronous public void onEvent(@Observes DummyEvent e) { System.out.println("Got event and starting reeeeeally expensive computation ;) " ); try { Thread.sleep(10000); System.out.println(" DONE!" ); } catch (InterruptedException e) {} } }
The behaviour of executor services can be configured in (e.g.) /opt/wildfly/standalone/configuration/standalone.xml
.
The queue-length
must be set explicitly:
<managed-executor-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-threshold="60000" core-threads="2" max-threads="2" queue-length="1000" keepalive-time="5000"/>
Otherwise you will run into problems when submitting many tasks at once:
Caused by: javax.ejb.EJBException: java.util.concurrent.RejectedExecutionException: Task org.glassfish.enterprise.concurrent.internal.ManagedFutureTask@6e36d5b6 rejected from org.glassfish.enterprise.concurrent.internal.ManagedThreadPoolExecutor@6409b656[Running, pool size = 25, active threads = 25, queued tasks = 0, completed tasks = 12]