How to correctly declare Server Runtime or provided Wildfly dependency on Gradle

Asked

Viewed 892 times

3

I have a Java web project being developed to run in Wildfly, using the Eclipse IDE. This application uses JPA, JTA, JSF and CDI at first, but will use other Java EE resources in the future. The dependency control of this project is done by Gradle, but as you can see on build.gradle below, I do not declare any of the dependencies already present in Wildfly:

apply plugin: 'war'
apply plugin: 'eclipse-wtp'

sourceCompatibility = 1.8
version = '1.0'
jar {
    manifest {
        attributes 'Implementation-Title': 'Arch Project', 'Implementation-Version': version
    }
}

repositories {
    mavenCentral()
}

So to add Java EE dependencies I add a library of the kind Server Runtime in my project, in other words, I right-click on my project -> Configure Build Path -> Add Libraries, select Server Runtmime and finally, I select the server Wildfly I set up in my Eclipse.

The above setting leaves my project with 3 libraries

  • JRE System Library
  • Gradle Dependencies (empty)
  • Wildfly 8.2 Runtime


Problem

This way, I can run my application in Wildfly (right click on the project -> Run As -> Run on Server, however, if I try to build my .War using Gradle via command Gradle War, it obviously gives error, accusing that the Wildfly classes are not in the classpath.


Solutions

  1. Declare JPA, JTA, JSF and CDI dependencies with scope provided in the build.gradle:

    • Pro: I’ve seen something similar in Maven projects and makes it clear to other developers which dependencies are used.
    • Against: To avoid bugs I will have to try the versions of the Apis used by Wildfly, and with each new dependency, I will have to open the Wildfly documentation and search for the correct version of the jar, to add the same version as dependency provided in my Gradle.
  2. Somewhat similar to Eclipse, add the dependency of a server runtime to my build.Gradle.

    • Pro: If it works correctly, I’ll make sure I’m using the same libraries that will be searched when the application is running on the server, avoiding surprises from different versions or even the famous ones ClassNotFoundException for having developed with more modern Apis than those on Wildfly.
    • Against: I don’t even know if this is possible, and if it is, I believe that every user who downloads the project on their machine, will have to manually configure the Wildfly path so that Gradle can find.

I would like to know which solution is more appropriate, and if it is the second, how this configuration would be carried out.

Thanks in advance.

1 answer

2


While both solutions appear to be acceptable, the second includes an external (implicit) dependency on the IDE. Thus, the first solution seems to me the most appropriate.

On the Apis versions used by Wildfly, I wouldn’t worry too much about that. In fact, for Java EE services you usually only need to depend on the interfaces / Apis.

In many projects a simple dependency to javaee-api is enough:

configurations {
    provided
}

sourceSets {
    main.compileClasspath += configurations.provided
    test.compileClasspath += configurations.provided
    test.runtimeClasspath += configurations.provided
}

dependencies {
    provided 'javax:javaee-api:7.0'
} 

To avoid problems with version differences between some Apis present simultaneously in the JVM (Java SE) and on your application server (Java EE), it is also interesting to configure the Java EE Endorsed Api. For more information on how to do this at Radle see that post.

For individual Java EE Apis, see that listing.


Of course, eventually you may want to use non-standard Apis, e.g., specific annotations from Hibernate. In this case you will also need to include dependencies provided for libraries. These are the most difficult cases to administer (according to the conclusion you arrived at in the question) because there may be compatibility break if the settings of graddle do not reflect the exact reality of the application server. The ideal is to reduce the amount of dependencies of this type. Those dependencies that are strictly necessary should be highlighted; it is also interesting to create mechanisms to help you update versions (e.g., properties for versions that are well highlighted in style maven).

  • Hello Anthony! Thank you for your reply.

  • I didn’t know this dependence on javaee-api, She really solves a lot of the problems I would have. The second option seemed to me the most fragile even, anyway would need parameterization pro Wildfly in the user’s classpath. I’m new to Gradle and haven’t used it yet sourceSets and configurations. Could you give me a brief explanation of what they do in this particular configuration? In any case, I will accept your reply and thank you again for the excellent explanation.

  • It emulates the configuration provided Maven. Basically this creates a separate dependency tree (called provided) and adds to Classpath (in this case, compile and Runtime, both for testing and for the main application. This may not be exactly your case).

  • Perfect. I believe I will need it, because unit testing will be the next step. Also, I’ll read about the endorsed API, I’ve seen it in some places but I didn’t know what it was about (and it was so important). Thank you Anthony.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.