verify maven managed dependencies - java

maven allows you to define in pom file:
(A) dependencies -> the actual direct dependencies of the project
(B) dependencyManagement/dependencies -> managed dependencies that affect dependencies of category (A) with undefined version and transitive dependencies.
If I put wrong/unknown artifact on category A - maven will surely fail.
If I put wrong/unknown artifact on category B - maven will fail only if it affects category A (for instance, A defines dep on foo:bar and B defines dep on foo:bar:<unknown-version>.
I wonder if there is any existing plugin that will allow me to verify all managed deps (category B) - make sure they actually exist.
I have 1 global pom project with deps management that serves multiple projects and I want to verify any change to the deps in the CI before uploading new version to remote repository

In maven dependency plugin there is goal dependency:analyze-dep-mgt. You may use it to check dependencies in dependencyManagement section of your pom.xml.
If you need deeper control or more functionality, options would be to create your own plugin or have a dummy project which would use all your managed dependencies (although I should say this is a cumbersome solution).

Related

How to let kotlin library support java project friendly

I create an kotlin library and published into maven central.
However, if this library is used by pure java project, user must add the dependency “kotlin-stdlib” explicitly.
It looks like that the “koitlin-stdlib” is automatically excluded from grade/maven dependency tree because it is treated as provided dependency.
How to resolve this problem?
In gradle you can add
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
}
The generated pom.xml should contain this dependency.
See:
https://mvnrepository.com/artifact/io.github.ragin-lundf/bdd-cucumber-gherkin-lib/1.48.0
-> under runtime dependencies
https://github.com/Ragin-LundF/bbd-cucumber-gherkin-lib/blob/main/build.gradle
-> as an example how to generate the pom for publishing to maven central in gradle
I find the reason.
implemetation(kotlin("reflect"))
is not OK,
api(kotlin("reflect"))
must be used.

Why are jackson library dependencies missing when used in sub project using gradle?

I have a gradle project P which has module A and B. Module A has this jackson dependencies:
...
dependencies {
...
compile 'com.fasterxml.jackson.core:jackson-core:2.12.0-rc1'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.12.0-rc1'
compile 'com.fasterxml.jackson.core:jackson-databind:2.12.0-rc1'
compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.12.0-rc1'
...
}
...
and module B uses module A, and has no need for including this dependencies because jackson usage is encapsulated in module A. But when code executed from module B reaches a statement that invokes code from Module A using it, I get exception:
java.lang.NoClassDefFoundError: com/fasterxml/jackson/dataformat/xml/XmlMapper
If I add the same dependencies to Module's B gradle.build file, the code works.
The question is, why would I include them if Module A does not use the library?
Shouldn't dependencies in Module A be compiled, packaged, so that when Module A is used elsewhere, its code works (using its included dependencies such as jackson library as in this example)
Disclaimer: I don't know Gradle, but this sounds like a problem common to Maven and Gradle.
The fact that you can build the module, but not run the module, means that somewhere you are not bringing the transitive dependencies into the Spring Boot fat jar. Jackson doesn't do anything weird with metadata files, classloaders, etc. It plays well with others in a fat jar.
Given that you haven't shared much of your build files, the easiest way to figure out if something has excluded the Jackson XML module is to just run jar -xvf target/app.jar and inspect the output to see if it's in there.
If it's not, look for a Gradle equivalent of the Maven dependency plugin's dependency-tree target that will show you the whole transitive dependency tree. If it's being excluded you'll definitely see it missing from a dependency dump.

See Maven Dependencies in Repository Scan (jQAssistant)

I ran a jQAssistant scan on my Maven repository. Now I can see some information, but unfortunately, if I try
MATCH (a:Maven:Artifact) --> (b:Maven:Artifact) RETURN a
I see no results although there should be DEPENDS_ON connections between Artifacts. Is there some extra switch for the scan to also find these arcs?
If you're scanning a Maven repository there are no direct dependencies between artifacts, this is only the case if you're scanning a Maven reactor (i.e. using the Maven plugin).
In case of a repository you have the following structure:
(:Repository)-[:CONTAINS_POM]->(:Pom)
(:Pom)-[:DESCRIBES]->(:Artifact)
(:Pom)-[:DECLARES_DEPENDENCY]->(:Artifact)
The following query returns all Poms, the artifacts which each of them describes and the dependencies that are declared:
MATCH
(:Repository)-[:CONTAINS_POM]->(pom:Pom),
(pom)-[DESCRIBES]->(artifact:Artifact),
(pom)-[:DECLARES_DEPENDENCY]->(dependency:Artifact)
RETURN
pom.fqn, collect(artifact.name), collect(dependency.fqn)

What happens to a dependency defined in a root project in a subproject in gradle?

I have a gradle project with several subprojects. I have defined several dependencies with version numbers in the root project but not all subprojects use all of these dependencies.
root
- build.gradle
- compile 'math:math:1.0.0'
- settings.gradle
- include 'messages'
- include 'message-handler'
\ messages
- build.gradle
- //no math
\ message-handler
- build.gradle
- compile 'math:math'
Will my artifact of the messages project contain a dependency on the math library?
In other words, if I make a separate project that depends on the messages artifact from a nexus repository, would my dependency tree show the math library for this new project?
Yes - your messages project artifact will contain a dependency on the math library.
According to Gradle Documentation:
For most multi-project builds, there is some configuration which is
common to all projects. In our sample, we will define this common
configuration in the root project, using a technique called
configuration injection. Here, the root project is like a container
and the subprojects method iterates over the elements of this
container - the projects in this instance - and injects the specified
configuration
In other words, every configuration which is included in the root project will hold for all the sub-projects.

maven - separate modules for interfaces and implementation with Spring

We are working on Mavenizing our java project and we would like to setup a clean separation between interfaces and implementations for each module.
In order to do so, we want to split each module into two sub-modules one for interfaces and data objects used by them and another for implementations.
For example:
+commons
+commons-api
+commons-impl
The POMs of the modules will be configured such that no module depends on the impl sub-modules. This way no code from one module will be able to "see" implementation details of another module.
What we are having trouble with, is where to put our spring XMLs.
In our project we automatically import spring XML files using wildcard import like
<import resource="classpath*:**/*-beans.xml"/>
This way the location of Spring XMLs doesn't really matter at runtime, as all the modules get loaded into the same class loader and, the strict one way dependency rules in the POMs don't apply.
However, during development we want the IDE - we use Intellij IDEA - to recognize implementation classes referenced from the spring XMLs.
We also want IDEA to recognize beans defined in other modules.
If we put the spring XMLs in API sub-modules - they won't "see" the implementation classes in the impl sub-modules.
If we put them in the impl sub-modules, their beans won't be "seen" from other modules.
It is probably possible to configure the IDEA project to recognize spring XMLs from modules on which there is no dependency, but we prefer for our POMs to hold all the project structure information and not rely on IDEA project files.
We considered creating a third sub-module just to hold Spring XMLs (and perhaps hibernate xmls as well). For example:
+commons
+commons-api
+commons-impl
+commons-config
The external modules will depend on both commons-api and commons-config and commons-config will depend on both commons-api and commons-impl, with the dependency on commons-impl marked as "provided" (to prevent transitive resolution).
This however seems like a complex and awkward solution and we feel that there must be a better - simpler way to achieve interface/impl separation with Maven and Spring.
What you need is a runtime dependency scope:
runtime - This scope indicates that the dependency is not required for compilation, but is for execution. It is in the runtime and test classpaths, but not the compile classpath.
(https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html)
Define a runtime dependency from one impl module to another impl module where you use the impl classes in the *-beans.xml config. Intellij will correctly recognize this in spring configuration files, but won't auto complete them in code (but it will do that in test code).
Also if anyone used the classes in the code, compilation through maven would fail, because the runtime dependency is not on a compile class path.
You can achieve decoupling of api and impl like this:
+ commons (pom)
+ pom.xml <--- serves as a parent aggregator (see below)
+ commons-api (jar) <--- contains models, interfaces and abstract classes only
+ commons-impl (jar) <--- depends on commons-api
+ commons-config (jar) <--- depends on commons-impl only (no need to depend on commons-api as it is brought in transitively)
+ external-project (war or jar) <--- has commons-config as a dependency
Parent aggregator pom (specify build order):
<modules>
<module>commons-api</module>
<module>commons-impl</module>
<module>commons-config</module>
</modules>
The config module can be omitted if it only contains spring application context configuration. The app configuration xml should be in the classpath and folder structure of the module that contains the artifact that you are deploying. So if you are building a war artifact, the app context should be in there.
The only configuration that should be in your commons module would be in a test package of your impl module.
In short you want Idea to override maven dependency graph but avoid keeping this configuration in idea project files?
One option is to group implementation dependencies in a maven profile. This profile would not be enabled by default but you should be able to mark it as active under idea.
Two ideas come to mind:
You will have one (or more) modules where all the modules (api+impl) are dependencies, you could place your spring configuration files there.
Place the spring configuration files in the api modules and declare a dependency on the impl module with scope provided this way the implementations will be known, while there is no dependency of the api for the deployment.
commons-impl at runtime scope in external modules
commons (pom dependencyManagement) =>
+commons-api (compile)
+commons-impl (compile)
+commons-config (compile)
commons-impl (pom dependencies) =>
+commons-api (compile)
+commons-config (compile)
external modules (pom dependencies) =>
+commons-impl (runtime)
+commons-api (compile)
+commons-config (compile)
keep modules number as little as possible;
This speeds up project build time and simplifies its layout.
keep modules structure as plain as possible: single root + all sub modules in the same folder, e. g.:
pom.xml
commons-api/
commons-runtime/
module-a-api/
module-a-runtime/
...
This simplifies navigation across the project, when modules number is really high (>50)
provide runtime-scoped dependencies to the runtime modules only when they are required;
This keeps your architecture clear. Use mocks instead of explicit dependency to another runtime module.
keep your api spring contexts in api modules, define your public beans as abstract bean + interface;
keep your implementation contexts in runtime modules, override api beans with your implementations via spring profiles (use <beans profile="default").
Result: simple, transparent layout and design; full ide support; no explicit dependencies on runtime module internals.

Categories

Resources