eap

Creating a Self-Signed Certificate on JBoss EAP 8.1

There are times when we want our JBoss EAP instances to be accessed via a secure connection (HTTPS) instead of plain, insecure HTTP. The fastest way to achieve this in a development or testing environment is to generate and apply a self-signed certificate.

First, let’s create the self-signed certificate. Be sure to replace your-hostname and your-ipaddress with the actual details of your JBoss EAP server:

$ keytool -genkeypair -alias server \ 
	-keyalg RSA -keysize 4096 -sigalg SHA256withRSA \ 
	-validity 3650 -storetype PKCS12 -keystore keystore.p12 \ 
	-storepass password -keypass password \ 
	-dname "CN=jboss,OU=RH,O=Edwin,C=ID" -ext SAN=dns:your-hostname,ip:your-ipaddress

This command generates a keystore.p12 file. Move this file into your JBOSS_HOME/standalone/configuration/ directory.

Next, we need to reference this new keystore in our standalone.xml. Locate the section within the elytron subsystem and update the applicationKS definition to point to your new keystore.p12 file:

<tls>
	<key-stores>
		<key-store name="applicationKS">
			<credential-reference clear-text="password"/>
			<implementation type="PKCS12"/>
			<file path="keystore.p12" relative-to="jboss.server.config.dir"/>
		</key-store>
	</key-stores>
	
	<key-managers>
		<key-manager name="applicationKM" key-store="applicationKS">
			<credential-reference clear-text="password"/>
		</key-manager>
	</key-managers>
	
	<server-ssl-contexts>
		<server-ssl-context name="applicationSSC" key-manager="applicationKM"/>
	</server-ssl-contexts>
</tls>

Start your JBoss EAP and see whether JBoss EAP is leveraging our certificate or not by using a curl command,

$ curl -Ikv https://localhost:8443
* Host localhost:8443 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
*   Trying [::1]:8443...
* connect to ::1 port 8443 from ::1 port 40968 failed: Connection refused
*   Trying 127.0.0.1:8443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 / x25519 / RSASSA-PSS
* ALPN: server accepted h2
* Server certificate:
*  subject: C=ID; O=Edwin; OU=RH; CN=jboss
*  start date: Jul 27 12:42:48 2026 GMT
*  expire date: Jul 24 12:42:48 2036 GMT
*  issuer: C=ID; O=Edwin; OU=RH; CN=jboss
*  SSL certificate verify result: self-signed certificate (18), continuing anyway.
*   Certificate level 0: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
* Connected to localhost (127.0.0.1) port 8443
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://localhost:8443/
* [HTTP/2] [1] [:method: HEAD]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: localhost:8443]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.15.0]
* [HTTP/2] [1] [accept: */*]
> HEAD / HTTP/2
> Host: localhost:8443
> User-Agent: curl/8.15.0
> Accept: */*
>
* Request completely sent off
< HTTP/2 200
HTTP/2 200
< last-modified: Tue, 29 Jul 2025 01:49:24 GMT
last-modified: Tue, 29 Jul 2025 01:49:24 GMT
< content-length: 1720
content-length: 1720
< content-type: text/html
content-type: text/html
< accept-ranges: bytes
accept-ranges: bytes
< date: Mon, 27 Jul 2026 12:50:15 GMT
date: Mon, 27 Jul 2026 12:50:15 GMT
<

JBoss EAP 8.1 Daily and Size-Based Rolling File Logging

I recently had a requirement to configure JBoss logging to rotate both on a daily basis and by file size. The goal was to generate an output structure that looks like this

server.log.2026-06-24.3
server.log.2026-06-24.2
server.log.2026-06-24.1
server.log

To achieve this, I use the in my JBoss configuration. Here is the XML snippet:

        <subsystem xmlns="urn:jboss:domain:logging:8.0">

			<periodic-size-rotating-file-handler name="DAILY_SIZE_FILE" autoflush="true">
				<formatter>
					<named-formatter name="PATTERN"/>
				</formatter>
				<file relative-to="jboss.server.log.dir" path="server.log"/>
				<suffix value=".yyyy-MM-dd"/>
				<rotate-size value="200m"/>
				<max-backup-index value="30"/>
				<append value="true"/>
			</periodic-size-rotating-file-handler>
			
            <root-logger>
                <level name="INFO"/>
                <handlers>
                    <handler name="DAILY_SIZE_FILE"/>
                </handlers>
            </root-logger>

        </subsystem>

The configuration above perfectly combines both strategies. It performs a daily log rotation, but it will also trigger the creation of a newly indexed log file whenever the current file size exceeds 200MB within that same day.

Creating a Query Timeout on JBoss EAP 8

Sometimes we want to limit the time needed for each queries, this is necessary to prevent our system from being slow and unresponsive due to slow queries.

For this sample, we are going to run a query on PostgreSQL that can simulate slowness

select pg_sleep(10);

And lets start with a pom file,

<?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-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.edw</groupId>
    <artifactId>simulate-jboss-connection-timeout</artifactId>
    <version>1.0</version>
    <packaging>war</packaging>

    <properties>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>


    <dependencies>
        <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-web-api</artifactId>
            <version>10.0.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>3.4.0</version>
                <configuration>
                    <warName>${project.name}</warName>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

And some Java files,

package com.edw.helper;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class DatabaseHelper {
    private DataSource ds = null;

    public DatabaseHelper() {
        try {
            Context initCxt = new InitialContext();
            ds = (DataSource) initCxt.lookup("java:/pgsql-ds");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
}

package com.edw.controller;

import com.edw.helper.DatabaseHelper;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

@WebServlet(name = "IndexController", urlPatterns = "/")
public class IndexController extends HttpServlet {

    private static final long serialVersionUID = 1L;

    private DatabaseHelper dbHelper = new DatabaseHelper();

    @Override
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response)
            throws ServletException, IOException {

        // create a 10 second query
        String sql = "select pg_sleep(10)";

        try (Connection conn = dbHelper.getConnection();
             PreparedStatement preparedStmt = conn.prepareStatement(sql)) {

            // do some query
            ResultSet resultSet = preparedStmt.executeQuery();

        } catch (Exception e) {
            e.printStackTrace(); // we should see some timeout exception here
        }

        response.setContentType("application/json");

        PrintWriter out = response.getWriter();
        out.println("{\"hello\":\"world\"}");
    }

}

Above code is using a Connection Pool called “java:/pgsql-ds” and would simulate a slowness when being executed,

$ time curl -kv http://127.0.0.1:8080/simulate-jboss-connection-timeout/
*   Trying 127.0.0.1:8080...
* Connected to 127.0.0.1 (127.0.0.1) port 8080
> GET /simulate-jboss-connection-timeout/ HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Type: application/json;charset=ISO-8859-1
< Content-Length: 19
< Date: Mon, 16 Jun 2025 08:04:50 GMT
<
{"hello":"world"}
* Connection #0 to host 127.0.0.1 left intact
real    0m 10.17s
user    0m 0.01s
sys     0m 0.01s

Lets try giving a timeout to that Connection Pool,

And try to do another curl test

$ time curl -kv http://127.0.0.1:8080/simulate-jboss-connection-timeout/
*   Trying 127.0.0.1:8080...
* Connected to 127.0.0.1 (127.0.0.1) port 8080
> GET /simulate-jboss-connection-timeout/ HTTP/1.1
> Host: 127.0.0.1:8080
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Type: application/json;charset=ISO-8859-1
< Content-Length: 19
< Date: Mon, 16 Jun 2025 08:05:26 GMT
<
{"hello":"world"}
* Connection #0 to host 127.0.0.1 left intact
real    0m 5.22s
user    0m 0.00s
sys     0m 0.01s

And we can see that theres an exception logged at our JBoss console,

15:11:42,531 ERROR [stderr] (default task-1) org.postgresql.util.PSQLException: ERROR: canceling statement due to user request
15:11:42,532 ERROR [stderr] (default task-1) 	at deployment.simulate-jboss-connection-timeout.war//com.edw.controller.IndexController.doGet(IndexController.java:43)

Complete code can be viewed on below Github repository

https://github.com/edwin/simulate-jboss-connection-timeout

Deploying a Binary WAR File to Openshift 4 Using s2i

We can leverage s2i to deploy an existing war file into Openshift 4. How to do it is pretty much simple and straight forward, basically just running some oc command and you can have your war file deployed on Openshift.

But before we go far, we need to have a sample application to be deployed and for this sample, i have a hello world apps which is created by using Java Servlet.

https://github.com/edwin/jboss-eap-hello-world

We can clone this application, and build it using a simple maven command.

$ mvn clean package

Next step is create an empty folder where we would run our oc command,

$ mkdir -p jboss-eap/deployments

and we can put our ROOT.war file inside deployment folder,

$ tree .
.
+---- deployments
    +---- ROOT.war

Next is creating a new BuildConfig,

$ oc new-build --name=custom-eap-application \
	--binary=true --image-stream=jboss-eap74-openjdk11-openshift:latest

and start building it by using a start-build command, we can also repeat this step again if there is a new changes to our war file

$ oc start-build custom-eap-application --from-dir . --follow

and finally we can deploy our application directly by using new-app command,

$ oc new-app --name=custom-eap-application \ 
	--image-stream=edwin-ns/custom-eap-application:latest

So deployment can be done easily by using just 3 simple steps.

Dockerfile for Deploying Applications in JBoss EAP 7.4, and on top of Openshift 4

Openshift have a different permission right because by default, any containers deployed in Openshift will gets a random user ID. Therefore it needs a specific approach when creating a containerized apps, especially in regards to folder access rights. A simple chmod or chown commands wont be sufficient enough for this purpose.

Long story short, we can use below Dockerfile to be use to deploy an existing war file into JBoss EAP base image and push the result into Openshift 4.

FROM registry.redhat.io/jboss-eap-7/eap74-openjdk11-openshift-rhel8

ENV DISABLE_EMBEDDED_JMS_BROKER=true

COPY target/*.war $JBOSS_HOME/standalone/deployments/

USER root
RUN chgrp -R 0 $JBOSS_HOME/standalone/deployments/ && \
	chmod -R g=u $JBOSS_HOME/standalone/deployments/
USER 185

EXPOSE 8080

Run below command to build the image, can use either Podman or Docker command for it.

$ podman build -t custom-app-name .