What is the proper way to use provided Wildfly dependencies with Java & Maven?

751 views
Skip to first unread message

Christoffer A. Nilsen

unread,
May 23, 2024, 11:33:23 AM5/23/24
to WildFly
I'm trying to figure out the proper way of defining Maven dependencies for an Java application for Wildfly. I have tried to describe a few scenarios below. And would be very grateful if I could get feedback if this looks to be a good way of doing it.

Let's assume I use Wildfly 31.0.0.Final, we depend on  the BOM in dependencyManagement in the root pom.xml:
<dependency>
   <groupId>org.wildfly.bom</groupId>
   <artifactId>wildfly-ee</artifactId>
   <version>${version.wildfly}</version>
   <scope>import</scope>
   <type>pom</type>
</dependency>

Let's assume I need the jakarta.inject:jakarta.inject-api that is already specified in the BOM:
<dependency>
   <!-- From Wildfly BOM -->
   <groupId>jakarta.inject</groupId>
   <artifactId>jakarta.inject-api</artifactId>
   <scope>provided</scope>
</dependency>

Let's assume I need org.apache.httpcomponents:httpmime that contains org.apache.httpcomponents:httpclient, where the same version is already provided by the Wildfly, I exclude it:
<dependency>
   <!-- Not part of Wildfly BOM -->
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpmime</artifactId>
   <version>${version.
httpmime}</version>
   <exclusions>
       <exclusion>
           <!-- From Wildfly BOM -->
          <groupId>org.apache.httpcomponents</groupId>
          <artifactId>httpclient</artifactId>
       </exclusion>
   </exclusions>
</dependency>

Let's assume I need org.keycloak:keycloak-admin-client that contains multiple resteasy dependencies with different versions than provided by Wildfly. I still exclude them and hope what is provided by Wildfly is compatible:
<dependency>
    <!-- Not provided by Wildfly BOM -->
   <groupId>org.keycloak</groupId>
   <artifactId>keycloak-admin-client</artifactId>
   <version>${version.keycloak}</version>
   <exclusions>
       <exclusion>
                     <!-- From Wildfly BOM -->
          <groupId>org.jboss.resteasy</groupId>
          <artifactId>resteasy-client</artifactId>
        </exclusion>
        <exclusion>
                    <!-- From Wildfly BOM -->
            <groupId>org.jboss.resteasy</groupId>
          <artifactId>resteasy-multipart-provider</artifactId>
        </exclusion>
        <exclusion>
                     <!-- From Wildfly BOM -->
             <groupId>org.jboss.resteasy</groupId>
             <artifactId>resteasy-jackson2-provider</artifactId>
        </exclusion>
        <exclusion>
                     <!-- From Wildfly BOM -->
             <groupId>org.jboss.resteasy</groupId>
             <artifactId>resteasy-jaxb-provider</artifactId>
        </exclusion>
     </exclusions>
</dependency>

Let's assume I want to use org.apache.httpcomponents:httpclient:4.5.14. Using Maven with <scope>provided</scopeis not enough, I also need to add it as a global module in the standalone:
<global-modules>
    <module name="org.apache.httpcomponents"/>
</global-modules>

Let's assume I want to use JAXB that uses uses jdk.xml.dom at runtime, that is a part of JDK17, I would have to add another global module in the standalone:
<global-modules>
   <module name="jdk.xml.dom"/>
</global-modules>

Let's assume I want to use nashorn that uses jdk.dynalink at runtime, that is a part of JDK17, I would have to add another global module in the standalone:
<global-modules>
   <module name="jdk.dynalink"/>
</global-modules>

Is this really the correct/proper way of keeping track of / defining dependencies for an Wildfly Java & Maven application?

Eduardo Martins

unread,
May 23, 2024, 12:38:31 PM5/23/24
to Christoffer A. Nilsen, WildFly
Hi, please see inline comments.

On 23 May 2024, at 16:33, 'Christoffer A. Nilsen' via WildFly <wil...@googlegroups.com> wrote:

I'm trying to figure out the proper way of defining Maven dependencies for an Java application for Wildfly. I have tried to describe a few scenarios below. And would be very grateful if I could get feedback if this looks to be a good way of doing it.

Let's assume I use Wildfly 31.0.0.Final, we depend on  the BOM in dependencyManagement in the root pom.xml:
<dependency>
   <groupId>org.wildfly.bom</groupId>
   <artifactId>wildfly-ee</artifactId>
   <version>${version.wildfly}</version>
   <scope>import</scope>
   <type>pom</type>
</dependency>


Correct, a short note tho is that you should say “we import the WildFly’s BOM dependencyManagement”. Importing a BOM does not adds any dependency, Maven simply replaces this BOM import with the BOM dependencyManagement content. 

Let's assume I need the jakarta.inject:jakarta.inject-api that is already specified in the BOM:
<dependency>
   <!-- From Wildfly BOM -->
   <groupId>jakarta.inject</groupId>
   <artifactId>jakarta.inject-api</artifactId>
   <scope>provided</scope>
</dependency>


Correct, any artifact in WildFly should have ‘provided’ scope, preventing it is added to the deployment.. 

Let's assume I need org.apache.httpcomponents:httpmime that contains org.apache.httpcomponents:httpclient, where the same version is already provided by the Wildfly, I exclude it:
<dependency>
   <!-- Not part of Wildfly BOM -->
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpmime</artifactId>
   <version>${version.
httpmime}</version>
   <exclusions>
       <exclusion>
           <!-- From Wildfly BOM -->
          <groupId>org.apache.httpcomponents</groupId>
          <artifactId>httpclient</artifactId>
       </exclusion>
   </exclusions>
</dependency>


Incorrect, you are just excluding httpclient, not using WildFly BOM’s one. Please note that the usage of Wildfly BOM’s one is done automatically by Maven, which only uses one version per artifact... the first one it found in Dependency Management or, if no version found in Dependency Management, the first one it found in Dependencies.

Your need to exclude here is to not add it (and its transitives) to the deployment’s WAR (assuming it’s a web app), since this is not a ‘provided’ scoped dependency.  
Assuming that your app components (EJB, Servlets, REST endpoints, etc) don’t bring those as implicit dependencies to the deployment, and those above are existing modules in WildFly, then yes that’s a way that works... But a better solution - since global modules means such modules will be visible to everything - is to add a jboss-deployment-structure.xml to your deployment, stating the explicit module dependencies your app needs. For more details please refer to https://docs.wildfly.org/32/Developer_Guide.html#jboss-deployment-structure-file

—E

Christoffer A. Nilsen

unread,
May 24, 2024, 3:50:46 AM5/24/24
to WildFly
@Eduardo, thank you very much for your reply.

I said "import" because the scope of the BOM was import. I could have explained that better.
One thing I forgot to explain in my original post was how all of the configurations was thought to be in the <dependencyManagement> in the root pom.xml. So whatever sub-module wanting to use for example org.apache.httpcomponents:httpmime would also have to add org.apache.httpcomponents:httpclient:provided as a dependency to their module.

I will look more into jboss-deployment-structure.xml, I'm really not a fan of configuration added to META-INF/WEB-INF(beans.xml is bad enough). But if it is simply a better way of doing it than adding global-modules to the standalone, I might swap over.

My go to way of cleaning up dependencies so far has been to:
  1. Build the EAR artifact
  2. Look into the lib folder of the EAR artifact
  3. Check if there is any dependency (.jar) there which is also provided by Wildfly.
  4. Do mvn dependency:tree to find where this dependency is located.
  5. Either change the dependency from compile to provided, or if a child-dependency, exclude it, and add it with scope=provided  in the same POM.
Does this sound reasonable? The hardest part of this routine is when the dependency needs to be added to jboss-deployment-structure.xml or global-modules, because it is private such as org.apache.httpcomponents.

I'm not sure I fully understand what you mean by: "Please note that the usage of Wildfly BOM’s one is done automatically by Maven, which only uses one version per artifact... the first one it found in Dependency Management or, if no version found in Dependency Management, the first one it found in Dependencies." I will setup a test project building an EAR and testing a few different scenarios.
Reply all
Reply to author
Forward
0 new messages