Spring boot war file with unnecessary jars - spring

I am making war packaging of my spring boot. made spring boot starter tomcat as provided, removed spring boot maven plugin.
But I still see tomcat jdbc and tomcat juli, to name a few (even junit, but it could be from other custom dependencies, so discounting this for this question). I am using logback, but I see log4j over slf4j from starter web.
Can I ask, how to skip unwanted jars and keep my package nice and tidy

Maven has the concept of "scope" for dependencies. You probably know the scope test which is used for unit test dependencies which should not go into the final product. Use this scope for junit.
What you need is the scope provided for the Tomcat dependencies. This tells Maven: "Don't include it; when the code is run, someone else will make sure this dependency is on the classpath".
The dependency log4j-over-slf4j is necessary when one of your dependencies still uses log4j to log. log4j-over-slf4j contains the code to redirect those calls to logback.
Now you will face the case where you can't change the scope because it's in a POM of someone else.
The correct solution here is to define the dependency with the correct scope (and version) in a dependencyManagement element in your POM. This definition will be used when any POM asks for this group+artifactId. So even when some deep dependency of Spring Boot pulls that in, your WAR will be build with the version and scope from the dependencyManagement element.
See also:
Dependency Scopes
Dependency Management

Related

Need to know the difference between spring-boot-starter-parent and spring-boot-parent

Can some one explain me the difference between spring-boot-parent and spring-boot-starter-parent, As i have seen in one of the GIT HUB code link attached below where they have written separate modules for spring-boot-starter-parent and spring-boot-parent.
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/
If any one knows the difference between these two dependencies pls let me know, Also in most of the projects we generally use spring-boot-starter-parent as parent but not spring-boot-parent when both of them shares the same parent spring-boot-dependencies.
https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/
As described at https://www.baeldung.com/spring-boot-starter-parent
Spring-boot-starter-parent
The spring-boot-starter-parent project is a special starter project –
that provides default configurations for our application and a
complete dependency tree to quickly build our Spring Boot project.
It also provides default configuration for Maven plugins such as
maven-failsafe-plugin, maven-jar-plugin, maven-surefire-plugin,
maven-war-plugin.
Beyond that, it also inherits dependency management from
spring-boot-dependencies which is the parent to the
spring-boot-starter-parent.
spring-boot-parent
Sometimes we have a custom Maven parent. Or, we may prefer to declare
all our Maven configurations manually.
In that case, we may opt to not use the spring-boot-starter-parent
project. But, we can still benefit from its dependency tree by adding
a dependency spring-boot-dependencies in our project in import scope.
Spring Boot Starter Parent helps us with managing dependency versions, the java version used by project and the default configuration for plug-ins, as we don't have to specify a lot of things manually.
It helps us with the following :
Configuration
Dependency management
Default plugin configuration (default configurations for maven-failsafe-plugin, maven-jar-plugin and maven-surefire-plugin etc)
According to spring-boot doc :
Starters are a set of convenient dependency descriptors that you can
include in your application. You get a one-stop shop for all the
Spring and related technologies that you need without having to hunt
through sample code and copy-paste loads of dependency descriptors
The spring-boot-starter is the Core starter and provides functionalities including auto-configuration support, logging and YAML.It defines spring-boot-dependencies as the parent pom .
In the github url that you provided , they have kept a separate module to specify the parent spring-boot-dependencies in the pom.It might be because they needed to use the spring-boot-dependencies , dependency tree alone without the auto-configuration and plugin configuration , and publish it as separate jar for some use-case.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${revision}</version>
<relativePath>../spring-boot-dependencies</relativePath>
</parent>
https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent/2.1.6.RELEASE
I believe you meant the difference between spring-boot-starter-parent and spring-boot-starter.
spring-boot-starter-parent - has spring-boot-dependencies as the parent and hence provides various spring-boot dependencies and helps in dependency management. In addition to this spring-boot-starter-parent on it's own helps in plugin management as well.
So if you use only spring-boot-dependencies you can benefit from the dependency management provided by it but instead if you use the spring-boot-starter-parent, you get dependency management + plugin management.
spring-boot-starter - It is a dependency provided by spring-boot-dependencies which provides dependencies for autoconfigure, logging and also spring-core. In order to pull any dependency from the starter or from spring-boot-dependencies, you need to explicitly add it as a dependency in your main pom.

Spring boot: submodule dependency

I have multi-module spring boot application. I have organized it in such way that it contains web module which has #SpringBootApplication class and several other modules which are being imported by web module (e.g. batch-jobs module).
web module contains all dependencies from spring boot:
compile('org.springframework.boot:spring-boot-starter-batch')
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-integration')
...
providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
testCompile('org.springframework.boot:spring-boot-starter-test')
etc...
I wonder whether I should include all spring-boot-starter dependencies into this modules or it's better to have pure spring dependencies like here:
dependencies {
compile 'org.springframework:spring-core'
compile 'org.springframework:spring-context'
compile 'org.springframework.integration:spring-integration-java-dsl'
compile 'org.springframework.batch:spring-batch-core'
...
testCompile 'org.springframework:spring-test'
testCompile 'org.springframework.integration:spring-integration-test'
}
Those dependencies are taken anyway from upper dependency-management configuration. Which approach is better? Can you please advise here?
I think this post will be flagged as opinion-based but anyway:
My thoughts on this topic are (or were if I look at spring boot) to explicitly name the dependencies you actively use in your code (and the specific modules). But with spring boot you cannot really match the dependency in your modules against the starters in the 'project'. Of course you may know that a starter-web will provide mvc from looking in the dependencies outside your project but I think that it will be hard for others to get into the definitions if the project
grows and maintain them.
Pure speculative: What if a starter gets an update and drops a dependency in favour of another? Just to give an example: LibX provided by vendorA is now switched to vendorB. You will still have a JSON dependency to vendorA in your module config but also vendorB gets in your classpath. If they have the same fully qualified name...(bam)
You could extract several starters like persistence related ones to the persistence module and web to web and so on.

Maven: How to include a dependency with a specific build profile?

I have a project where I use Spring Boot 1.1.2.RELEASE which uses Spring 4.1.5, and Spring HATEOAS 0.10.0.RELEASE which uses Spring 4.0.9. This causes some dependency problems like the infamous java.lang.ClassNotFoundException: org.springframework.beans.factory.SmartInitializingSingleton.
I dug into the POM of spring-hateoas and found that there are different profiles defined, one of them being spring41 which depends on Spring 4.1.5. Is it possible to select this profile in my <dependency> section, or do I have to exclude the Spring dependencies?
Automatically selecting a profile for a build isn't easy. You can enable it by default in your personal settings.xml but that breaks the build for everyone who doesn't have the same file.
You can't enable a profile in the POM of the project.
With Maven 3.3, you can add the profile to ${maven.projectBasedir}/.mvn/maven.config. Since this file is part of the project, it's easy to share. You can use the Maven Enforcer plugin to make sure everyone uses a Maven version with actually uses the file.
If you can't use 3.3, then your best bet is to exclude the dependencies. If you have a parent POM, then you can use a dependencyManagement element to do it for all POMs in the reactor build.

What is the difference between spring-context and spring-core dependencies?

Hello I am new to the Spring and maven world, and I want to know what is the difference between this 2 dependencies?
Its a simple question.. I am having trouble with my pom.xml file, so I want to know everything :).
Thanks in advance.
These are actually 2 of many Spring Framework modules. You can easily find what packages these artifacts contain, using this site:
http://mvnrepository.com/artifact/org.springframework/spring-core/3.1.1.RELEASE
This can give you information about classes contained within a particular artifact and probably about the its purpose.
For Spring Framework, spring-core contains mainly core utilities and common stuff (like enums) and because it's really critical for Spring, probably all other Spring modules depend on it (directly or transitively).
In turn spring-context provides Application Context, that is Spring's Dependency Injection Container and it is probably always defined in POMs of artifacts that use Spring Framework somehow. In fact, spring-context depends on spring-core so by defining spring-context as your dependency, you have spring-core in your classpath as well.

Why Spring 3 needs explicit cglib dependency declaration when using Maven?

I'm using Spring 3 and Maven. I've defined all spring modules in my pom.xml.
When I use <aop:scoped-proxy />, I get an error saying that CGLIB is missing.
Well... I add CGLIB as a dependency in my pom and it all runs...
I'm a little confused... Maven is a dependency manager... Why it does not download CGLIB when I use the spring-aop module?
It's not the only case... Why do some projects need explicit dependency declaration instead of using Maven transitive dependency mechanism?
It's because cglib is marked as an optional dependency.
Essentially you don't need cglib for every usage of the spring-aop library, so maven doesn't download it automatically. You need to specify it manually, unfortunately.
I'm a little confused... Maven is a dependency manager... Why it does not download the cglib when I use the spring-aop module ?
Because not everybody uses CGLIB (an AOP proxy in Spring can be a JDK dynamic proxy or a CGLIB proxy) so CGLIB is marked as an optional dependency in the pom of spring-aop and you have to add it explicitly if you want to use it. This is exactly what optional dependencies are for.
Another similar example is Hibernate that lets you choose between cglib and javassist in hibernate-core in the same way. Hibernate also lets you choose between various connection pools (if you decide to use one of them) or cache providers (only ehcache, the default, is not declared as optional).
My guess would be that cglib is not enabled in Spring by default. And therefore it's not included in the pom unless you explicitly enable it.
As far as I know, Maven cannot go into your Spring configuration files and determine if it needs additional optionally enabled libraries. Although, that certainly sounds like it would be a cool Spring-Maven plugin if it were possible to modify the pom on the fly via plugin. Not sure if it is, but it would be cool.
Good news - this is a problem of the past:
As of Spring 3.2, it is no longer necessary to add CGLIB to your
project classpath, as CGLIB classes are repackaged under
org.springframework and included directly in the spring-core JAR. This
means that CGLIB-based proxy support just works in the same way that
JDK dynamic proxies always have.
Read more here.

Resources