Chapter 4. Capability Trimming in JBoss EAP for OpenShift

When building an image that includes JBoss EAP, you can control the JBoss EAP features and subsystems to include in the image.

The default JBoss EAP server included in S2I images includes the complete server and all features. You might want to trim the capabilities included in the provisioned server. For example, you might want to reduce the security exposure of the provisioned server, or you might want to reduce the memory footprint so it is more appropriate for a microservice container.

4.1. Provision a Custom JBoss EAP Server

To provision a custom server with trimmed capabilities, pass the GALLEON_PROVISION_LAYERS environment variable during the S2I build phase.

The value of the environment variable is a comma-separated list of the layers to provision to build the server.

For example, if you specify the environment variable as GALLEON_PROVISION_LAYERS=jaxrs-server,sso, a JBoss EAP server is provisioned with the following capabilities:

  • A servlet container
  • The ability to configure a datasource
  • The jaxrs, weld, and jpa subsystems
  • Red Hat SSO integration

4.2. Available JBoss EAP Layers

Red Hat makes available six layers to customize provisioning of the JBoss EAP server in OpenShift.

Three layers are base layers that provide core functionality. Three are decorator layers that enhance the base layers.

The following Jakarta EE specifications are not supported in any provisioning layer:

  • Jakarta Server Faces 2.3
  • Jakarta Enterprise Beans 3.2
  • Jakarta XML Web Services 2.3

4.2.1. Base Layers

Each base layer includes core functionality for a typical server user case.

datasources-web-server

This layer includes a servlet container and the ability to configure a datasource.

This layer does not include MicroProfile capabilities.

The following are the JBoss EAP subsystems included by default in the datasources-web-server:

  • core-management
  • datasources
  • deployment-scanner
  • ee
  • elytron
  • io
  • jca
  • jmx
  • logging
  • naming
  • request-controller
  • security-manager
  • transactions
  • undertow

The following Jakarta EE specifications are supported in this layer:

  • Jakarta JSON Processing 1.1
  • Jakarta JSON Binding 1.0
  • Jakarta Servlet 4.0
  • Jakarta Expression Language 3.0
  • Jakarta Server Pages 2.3
  • Jakarta Standard Tag Library 1.2
  • Jakarta Concurrency 1.1
  • Jakarta Annotations 1.3
  • Jakarta XML Binding 2.3
  • Jakarta Debugging Support for Other Languages 1.0
  • Jakarta Transactions 1.3
  • Jakarta Connectors 1.7

jaxrs-server

This layer enhances the datasources-web-server layer with the following JBoss EAP subsystems:

  • jaxrs
  • weld
  • jpa

This layer also adds Infinispan-based second-level entity caching locally in the container.

The following MicroProfile capability is included in this layer:

  • MicroProfile REST Client

The following Jakarta EE specifications are supported in this layer in addition to those supported in the datasources-web-server layer:

  • Jakarta Contexts and Dependency Injection 2.0
  • Jakarta Bean Validation 2.0
  • Jakarta Interceptors 1.2
  • Jakarta RESTful Web Services 2.1
  • Jakarta Persistence 2.2

cloud-server

This layer enhances the jaxrs-server layer with the following JBoss EAP subsystems:

  • resource-adapters
  • messaging-activemq (remote broker messaging, not embedded messaging)

This layer also adds the following observability features to the jaxrs-server layer:

  • MicroProfile Health
  • MicroProfile Metrics
  • MicroProfile Config
  • MicroProfile OpenTracing

The following Jakarta EE specification is supported in this layer in addition to those supported in the jaxrs-server layer:

  • Jakarta Security 1.0

4.2.2. Decorator Layers

Decorator layers are not used alone. You can configure one or more decorator layers with a base layer to deliver additional functionality.

sso

This decorator layer adds Red Hat Single Sign-On integration to the provisioned server.

observability

This decorator layer adds the following observability features to the provisioned server:

  • MicroProfile Health
  • MicroProfile Metrics
  • MicroProfile Config
  • MicroProfile OpenTracing
Note

This layer is built in to the cloud-server layer. You do not need to add this layer to the cloud-server layer.

web-clustering

This layer adds embedded Infinispan-based web session clustering to the provisioned server.

4.3. Provisioning User-developed Layers in JBoss EAP

In addition to provisioning layers available from Red Hat, you can provision custom layers you develop.

Procedure

  1. Build a custom layer using the Galleon Maven plugin.

    For more information, see Building Custom Layers for JBoss EAP.

  2. Deploy the custom layer to an accessible Maven repository.
  3. Create a custom provisioning file to reference the user-defined layer and supported JBoss EAP layers and store it in your application directory.

    For more information, see Custom Provisioning Files for JBoss EAP.

  4. Run the S2I process to provision a JBoss EAP server in OpenShift.

    For more information, see Building an Application Provisioned with User-developed Layers.

4.3.1. Building Custom Layers for JBoss EAP

Create your custom layer feature pack as a Maven project.

  1. Custom layers depend on at least a base layer. Select the base layer that provides the capabilities you need for your custom layer.
  2. Within the Maven project, create your layer content in the directory src/main/resources.

    For example, to create layers to provision support for PostgreSQL and a PostgreSQL datasource, in the directory src/main/resources create the layers/standalone subdirectories. The standalone subdirectory includes the following content.

    • postgresql-driver

      This directory contains a layer-spec.xml file with the following content.

      <?xml version="1.0" ?>
      <layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="postgresql-driver">
          <feature spec="subsystem.datasources">
              <feature spec="subsystem.datasources.jdbc-driver">
                  <param name="driver-name" value="postgresql"/>
                  <param name="jdbc-driver" value="postgresql"/>
                  <param name="driver-xa-datasource-class-name" value="org.postgresql.xa.PGXADataSource"/>
                  <param name="driver-module-name" value="org.postgresql.jdbc"/>
              </feature>
          </feature>
          <packages>
              <package name="org.postgresql.jdbc"/>
          </packages>
      </layer-spec>
    • postgresql-datasource

      This directory contains a layer-spec.xml file with the following content.

      <?xml version="1.0" ?>
      <layer-spec xmlns="urn:jboss:galleon:layer-spec:1.0" name="postgresql-datasource">
          <dependencies>
              <layer name="postgresql-driver"/>
          </dependencies>
          <feature spec="subsystem.datasources.data-source">
              <param name="use-ccm" value="true"/>
              <param name="data-source" value="PostgreSQLDS"/>
              <param name="enabled" value="true"/>
              <param name="use-java-context" value="true"/>
              <param name="jndi-name" value="java:jboss/datasources/${env.POSTGRESQL_DATASOURCE,env.OPENSHIFT_POSTGRESQL_DATASOURCE:PostgreSQLDS}"/>
              <param name="connection-url" value="jdbc:postgresql://${env.POSTGRESQL_SERVICE_HOST,\
      env.OPENSHIFT_POSTGRESQL_DB_HOST}:${env.POSTGRESQL_SERVICE_PORT,\
      env.OPENSHIFT_POSTGRESQL_DB_PORT}/${env.POSTGRESQL_DATABASE, env.OPENSHIFT_POSTGRESQL_DB_NAME}"/>
              <param name="driver-name" value="postgresql"/>
              <param name="user-name" value="${env.POSTGRESQL_USER, env.OPENSHIFT_POSTGRESQL_DB_USERNAME}"/>
              <param name="password" value="${env.POSTGRESQL_PASSWORD, env.OPENSHIFT_POSTGRESQL_DB_PASSWORD}"/>
              <param name="check-valid-connection-sql" value="SELECT 1"/>
              <param name="background-validation" value="true"/>
              <param name="background-validation-millis" value="60000"/>
              <param name="flush-strategy" value="IdleConnections"/>
              <param name="statistics-enabled" value="${wildfly.datasources.statistics-enabled:${wildfly.statistics-enabled:false}}" />
          </feature>
  3. In the pom.xml file used to build your custom feature pack, refer to the JBoss EAP dependencies.

    <dependency>
        <groupId>org.jboss.eap</groupId>
        <artifactId>wildfly-ee-galleon-pack</artifactId>1
        <version>7.3.0.GA-redhat-00004</version>
        <type>zip</type>
    </dependency>
    1
    When using the JBoss EAP expansion pack (JBoss EAP XP), the value of this element should be wildfly-galleon-pack.

    These dependencies are available in the Red Hat Maven repository: https://maven.repository.redhat.com/ga/

  4. Use the build-user-feature-pack goal in the Galleon Maven plugin to build custom layers.

Additional Resources

Base Layers

WildFly Galleon Maven Plugin Documentation

Example illustrating packaging of drivers and datasources as Galleon layers

4.3.2. Custom Provisioning Files for JBoss EAP

Custom provisioning files are XML files with the file name provisioning.xml that are stored in the galleon subdirectory.

The following code illustrates a custom provisioning file.

<?xml version="1.0" ?>
<installation xmlns="urn:jboss:galleon:provisioning:3.0">
    <feature-pack location="eap-s2i@maven(org.jboss.universe:s2i-universe)">1
        <default-configs inherit="false"/>2
        <packages inherit="false"/>3
    </feature-pack>
    <feature-pack location="com.example.demo:my-galleon-feature-pack:1.0
">4
        <default-configs inherit="false"/>
        <packages inherit="false"/>
    </feature-pack>
    <config model="standalone" name="standalone.xml">5
        <layers>
            <include name="cloud-server"/>
            <include name="my-custom-driver"/>
            <include name="my-custom-datasource"/>
        </layers>
    </config>
    <options>6
        <option name="optional-packages" value="passive+"/>
    </options>
</installation>
1
This element instructs the provisioning process to provision the current eap-s2i feature-pack. Note that a builder image includes only one feature pack.
2
This element instructs the provisioning process to exclude default configurations.
3
This element instructs the provisioning process to exclude default packages.
4
This element instructs the provisioning process to provision the com.example.demo:my-galleon-feature-pack:1.0 feature pack. The child elements instruct the process to exclude default configurations and default packages.
5
This element instructs the provisioning process to create a custom standalone configuration. The configuration includes the cloud-server base layer and the my-custom-driver and my-custom-datasource custom layers from the com.example.demo:my-galleon-feature-pack:1.0 feature pack.
6
This element instructs the provisioning process to optimize provisioning of JBoss EAP modules.

4.3.3. Building an Application Provisioned with User-developed Layers

When you build an application from a directory that includes a custom provisioning file, the S2I build process detects the provisioning file and provisions the JBoss EAP server as instructed.

Prerequisites

  • The user-developed layers must exist in an accessible Maven repository.
  • The application directory must contain a valid provisioning file that refers to the user-developed layers and the feature pack that contains them.

Procedure

  • Enter a standard S2I build command to build the application.

    For example, assume you create the following custom provisioning file in your application directory.

    <?xml version="1.0" ?>
    <installation xmlns="urn:jboss:galleon:provisioning:3.0">
        <feature-pack location="eap-s2i@maven(org.jboss.universe:s2i-universe)">
            <default-configs inherit="false"/>
            <packages inherit="false"/>
        </feature-pack>
        <feature-pack location="com.example.demo:my-galleon-feature-pack:1.0">
            <default-configs inherit="false"/>
            <packages inherit="false"/>
        </feature-pack>
        <config model="standalone" name="standalone.xml">
            <layers>
                <include name="cloud-server"/>
                <include name="my-custom-driver"/>
                <include name="my-custom-datasource"/>
            </layers>
        </config>
        <options>
            <option name="optional-packages" value="passive+"/>
        </options>
    </installation>

    The following command builds an application using the com.example.demo:my-galleon-feature-pack:1.0 feature pack, which includes the my-custom-driver and my-custom-datasource layers. The resulting application is named eap-my-custom-db. The connection to the database is configured using environment variables.

    oc build my-app \
    -e DEMO_DB=demo \
    -e DEMO_PASSWORD=demo \
    -e DEMO_HOST=127.0.0.1  \
    -e DEMO_PORT=5432 \
    -e DEMO_USER=demo \
    eap-my-custom-db

You can log in to the database on port 5432 with the user demo and the password demo.