spring dependencies - java

I just found one daunting thing. There are two versions of spring dependency coordinates.
Project has dependencies on spring mvc and spring flow. There are two parallel sets of dependencies.
Spring MVC has dependencies of the following scheme: org.springframework:spring-asm.
Spring Flow has dependencies of the following scheme: org.springfrmaework:org.springframework.asm.
Why are there two different sets of the same dependency? How can it be overcome?
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>org.springframework.webflow</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>

It's basically a question of the artifacts you are using:
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>org.springframework.webflow</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
Is an artifact from the SpringSource Enterprise Bundle Repository and those artifacts are OSGi compliant. I quote:
Welcome to the SpringSource Bundle Repository. Here you'll find
OSGi-ready versions of hundreds of open source enterprise libraries
that are commonly used when developing Spring applications.
On the other hand, you have:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
Is a standard artifact from the maven repository.
org.springframework.asm
Is a patched version of the asm artifact for use with OSGi.
The best solution to fix this is only using the SEBR repository artifacts.
I recommend this because one time I had a problem with the jars from the maven central repo (they were corrupt) so I try to use the SEBR for any spring dependency. But I quote from the documentation:
If OSGi does not matter to you, either place works, though there are
some pros and cons between them. In general, pick one place or the
other for your project; do not mix them. This is particularly
important since EBR artifacts necessarily use a different naming
convention than Maven Central artifacts.

Related

How to make specific maven dependency versions mandatory

I am working on creating a common library for my team which can be used by different micro-services of our team. Common library will be service-starter which includes : specific spring boot, spring version and other compatible versions and dependencies. Is it possible to guardrail using maven such that our whole team must be on specific MUST versions of some maven dependencies like spring boot version should be common across team (We will also have other maven dependencies which can be overridden in respective micro-service pom if needed.)
You cannot stop your team from defining their own version in their project. However, you can add a <dependencyManagement>tag in your project which will define the versions you wish them to use so they won't have to decide.
But, again, nothing to stop them to override these.
You can create a parent pom that you want and put in <dependencyManagement> the dependencies that you want to be used by applications that use this parent pom.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
so if another application uses as parent pom the one you have declared above and uses as dependency
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
</dependency>
</dependencies>
(It does not contain any specific version), it would retrieve by default the version which was delcared in parent pom of 1.0
But the child pom application would always be free to declare their own version if they want, and use that instead, effectively overriding what was declared in parent pom
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
More about Dependency management in Maven

WildFly App Dev: how to reflect the runtime classpath at development time?

I am working on a Project that is deployed as .war WebApp on a single WildFly 16 instance.
Using IntelliJ Idea UE with Maven as development environment, I ask myself how to reflect the classpath that the deployed app will see at runtime in the development classpath at development time.
I have read about implicit dependencies in the Developer Guide.
So I conclude that the classpath of my deployment will contain the elements from the "Dependencies that are always added" column plus those that are added on trigger conditions (in my case these are Weld, Web, Hibernate, Resteasy, EJB3).
How can I figure out what Maven artifacts I have to import so that my development classpath equals the runtime classpath of my WebApp?
I would like to solve dependency conflicts at development time, not at runtime.
You can use the WildFly 16 Bill of Materials (BOM) for that. I'm sure you are well aware of Maven's import feature for artifacts of type POM. Just in case you are not, add these lines to your Maven pom.xml:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.wildfly.bom</groupId>
<artifactId>wildfly-javaee8</artifactId>
<version>16.0.0.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
It enables you to reference most of WildFly's artifacts (or at least the relevant ones) as well as the Java EE 8 specification artifacts. Here's an example:
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jboss.spec.javax.servlet</groupId>
<artifactId>jboss-servlet-api_4.0_spec</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<!-- And so on... -->
You still need to list all the dependencies you require though. If you have additional dependencies (not provided by WildFly), you should package them in your WAR or EAR. This way you shouldn't get any conflicts.
Oh, and one more thing, because you mentioned several dependencies, which are WildFly specific (e.g. Weld and Hibernate): Try sticking to Java EE APIs, where possible. It enables you to port your application to other application servers faster, if needed.

Maven: Resolve dependencies using container dependencies first

I have a plugin project which is added to other container projects as a dependency.
Now, this plugin project uses many frequent dependencies like spring-security, commons-lang, etc.
Usually, the container projects contain their own versions of such frequent dependencies. So, when we add our plugin dependency there are conflicts and the dependencies are resolved based on regular maven dependency resolver and depending on scopes and optional tags provided in the plugin project dependencies.
Is there a way where all the dependencies are resolved using the version in parent dependencies first and iff they are not available then use the version specified in plugin dependency.
Note: optional and scope runtime have a problem that these dependencies are provided by the container and thus beats the aim to provide a hassle-free single dependency to add plugin dependency.
In your plugins pom define the version of a dependency as range of the versions you know the plugin to be able to use. If a container-dependency overlaps this will be used. If no overlapping version, of the dependency both container and plugin need, can be found, an error will be produced, since the negotiation failed.
Use no special scope for the dependencies, since you want them to be included if necessary into the container,
See:
https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html
And:
https://books.sonatype.com/mvnref-book/reference/pom-relationships-sect-project-dependencies.html#pom-relationships-sect-version-ranges
Assuming that your container and plugin projects use the same parent pom you could utilize the <dependencyManagement> section in the parent to define the common artifacts. This allows you to omit the version in the plugins <dependencies> section.
parent:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
plugin/module:
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
</dependency>
</dependencies>
See https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html for further details.
you can exclude it when you build a plugin project and add a dependency to maven.
This is an example. Dependency and main project have conflicted due to logging library. Below is to exclude log4j in dependency project.
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zk.version}</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
P/S: Added from my comments:
I have also developed a system which has a similar architecture with yours. I separate this system into 3 main parts: 1. Commons which contains common code and required maven dependencies, 2. The main project, 3. plugin project. You can refer this.

Can I easily replace spring-boot-starter by spring-boot to avoid use of spring-boot-starter-parent?

I want to use spring-boot-starter, but that means I have to use the "spring-boot-starter-parent" pom and cannot use the company wide used root pom.
Spring-boot-starter is a huge advantage when it comes to manage dependecy and plugin that go together. But that contradict the advantage of our company wide used root pom.
Are there further advantages of using spring-boot-starter?
Is there an easy way to only use spring-boot without spring-boot-starter?
If you do not want to use the spring-boot-starter-parent, you can still keep the benefit of the dependency management (but not the plugin management) by using a scope=import dependency, as follows:
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
And here you can find an appropriate section in Spring Documentation with more details.
Add needed version of spring-boot-starter-parent as the parent to your company's root pom.xml file.
This way it is spring-boot that manages all the dependencies for all of your projects.
Your Company's parent-pom can have its own <dependencyManagement> to override and manage any internal or third-party dependencies.
The plugin management is cleaner this way. You can define your own stages on project and parent level.

download compatible dependency in maven

Supppose I use spring 4.0 in my pom file and I want to use junit. In that case how can I declare the junit dependency to download the which compatible with the given spring version with out specify any specific junit version. This can be any dependency where I take junit as a example.
In Maven there are two possible matching things. First the dependency management of the artefact itself. spring-core:4.2.0 defines that it depends on commons-codec:1:10. So there is nothing to do for you when you want to also use commons-codec since its already in your classpath. It did not define JUnit so it did not depend on it and should be compatible with all versions.
The second thing is aBOM pom. This is used to package a lot of dependencies together and let the user select the once he needs but the bom defines the versions for you already (and so they should be compatible). Especially spring has some of this bom poms in the repo.
For example spring-framework-bom which packaged everything related to spring which you could use in your app but you will define which parts you need and do not bothering yourself with the version numbers of the sub dependencies.
For example I want to use spring 4.2 and need webmvc the jdbc stuff and something for spring tests. So will define this:
<dependencymanagement>
<dependencies>
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-framework-bom</artifactid>
<type>pom</type>
<version>4.2.0.RELEASE</version>
<scope>import</scope>
</dependency>
<dependencies>
</dependencymanagement>
<dependencies>
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-webmvc</artifactid>
</dependency>
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-jdbc</artifactid>
</dependency>
<dependency>
<groupid>org.springframework</groupid>
<artifactid>spring-test</artifactid>
<scope>test</scope>
</dependency>
</dependencies>
This question doesn't really make sense. If spring 4.0 depends on JUnit (you don't say which spring module you're referring to), JUnit (or any other dependency) will automatically be included in your dependencies, since it will be inherited from the spring 4.0 dependency you have already declared, and the version will match whatever version the Spring module declares in its POM.
However, it seems likely that your particular Spring 4.0 dependency does not depend on JUnit, so in which case you may just pick which ever version is suitable for your requirements.
You can view the dependencies which are currently included in your project (explicit and inherited) by running the following command:
mvn dependency:list
This will trace down the dependency tree and show you all the dependencies which are currently included in your project.

Categories

Resources