What is correct Maven scope of findbugs annotations? - maven

I want to use a library that has the following dependency:
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>annotations</artifactId>
<version>2.0.3</version>
</dependency>
I read that FindBugs is for static analysis of Java code, so I though it isn't necessary to include in application. Is it safe to exclude the jar with <scope>provided</scope> or with an <exclusion>...</exclusion>?
One reason to exclude it is that there is a company policy against (L)GPL licence.

Yes, you can safely exclude this library. It contains only annotations which do not need to be present at runtime. Take care to have them available for the FindBugs analysis, though.
Note that you should also list jsr305.jar, like this:
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>annotations</artifactId>
<version>3.0.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
<scope>provided</scope>
</dependency>
Both JARs are required to make these annotations work.
Check the most recent findbugs version in Maven Central.
FindBugs is provided under the LGPL, so there should not be any problems for your company. Also, you are merely using FindBugs; you are not developing something derived from FindBugs.

In theory, it should be entirely safe (as defined in the OP's clarifying comment) to exclude the Findbugs transitive dependency. If used correctly, Findbugs should only be used when building the library, not using it. It's likely that someone forgot to add <scope>test</scope> to the Findbugs dependency.
So - go ahead and try the exclusion. Run the application. Do you get classpath errors, application functionality related to the library that doesn't work, or see messages in the logs that seem to be due to not having Findbugs available? If the answer is yes I personally would rethink using this particular library in my application, and would try to find an alternative.
Also, congratulations on doing the classpath check up front! As a general practice, it is a great idea to do what you have done every time you include a library in your application: add the library, then check what other transitive dependencies it brings, and do any necessary classpath clean-up at the start. When I do this I find it makes my debugging sessions much shorter.

Related

how does runtime instance deal with provided scope dependency?

i am interested in understanding maven scopes during build life cycle.
i understood that working with a dependency, like this one :
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
the javax.servlet-api jar will not be included in the final executable jar,
because the server is supposed to already possess the dependency.
ok, but how does it work ?
where is physically the util jar ? (javax.servlet-api.jar)
last question :
when we build a jar, how can we be sure the dependency can be tagged as provided scope,
so that the server already has it, for the run ?
It is actually up to you to make that sure. Maven does not know about it.
So if you know that your server provides certain dependencies (e.g. because you read the server manual), then you can mark them as provided.

Removing a JAR from deployment

I am working on a Spring Project on a JBoss server. I am facing a situation where I think removing a jar from the deployment may solve all the issues. But I want to keep the JAR in compile time so that I can use it in the classes.
I want to know how I can remove a jar from deployment only but keep it during the run time.
Probably, this is not the question to be asked on SO, as a matter of fact, SO is all about Coders and its main intention is to help us in solving a problem.
So, anyone ? How I can do this ?
If you are using Maven, the you need to mark the dependency as provided.
For example
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>provided</scope>
</dependency>
If you are using Gradle the corresponding element would be providedCompile. The code would look like:
providedCompile 'log4j:log4j:1.2.17'
For an Eclipse based build, check out this SO post

Can Maven's provided scoping, be transitive?

I have an Ancestor dependency has dependent scoped as provided, I need to propagate that scoping to anything that depends on my project.
For example, say I have SomeProjectA which depends on SomeLibraryB. I need to scope SomeLibraryB has provided.
Currently to compile anything that depends on SomeProjectA, has to also set SomeLibraryB has provided. I would rather propagate that scoping, then have any project that depend on mine deal with my project's dependents..
I dont think that is possible. Each project should declare provided dependencies on its own. Propagating that scope would be wrong since you would make an assumption about the deployment that you cant make since you are not responsible for the deployment. The user of your library does that..
Simple hack
This can be achieved by a simple hack.
You can exclude SomeLibraryB and SomeLibraryC inside your direct dependency tag.
Below is the dependency tag for your SomeProjectA.
<dependency>
<groupId>org.direct.dependency</groupId>
<artifactId>SomeProjectA</artifactId>
<exclusions>
<exclusion>
<groupId>org.some</groupId>
<artifactId>SomeLibraryB</artifactId>
</exclusion>
<exclusion>
<groupId>org.some</groupId>
<artifactId>SomeLibraryC</artifactId>
</exclusion>
</exclusions>
</dependency>
But if you have this configuration, your tests and compilation other validations will starts to fail. Therefore, you can put direct dependencies to those libraries with <scope>test</scope>.
<dependency>
<groupId>org.some</groupId>
<artifactId>SomeLibraryB</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.some</groupId>
<artifactId>SomeLibraryC</artifactId>
<scope>test</scope>
</dependency>
As you can see from the Maven documentation, the provided scope doesn't influence compilation, but runtime. In general you should only need to specify the provided scope in the dependencies for a packaging project, such as a project of type war. For this reason it doesn't usually matter much that it isn't transitive.
In other words, if you add a dependency to a jar project without explicitly specifying its scope, that dependency will be made available during compilation and so will that dependency's dependencies. If you then explicitly declare that dependency to have provided scope, this does not change.

In Maven, how can I exclude all transitive dependencies from a particular dependency?

I want to exclude all transitive dependencies from one dependency. In some places I've seen it suggested to use a wildcard for that
<dependency>
<groupId>myParentPackage</groupId>
<artifactId>myParentProject</artifactId>
<version>1.00.000</version>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
When I do that I get a warning:
'dependencies.dependency.exclusions.exclusion.groupId' for myParentPackage:myParentProject:jar with value '*' does not match a valid id pattern. # line 146, column 30
The declaration itself is successful though: The transitive dependencies really are ignored in my build.
I've also found a old feature request that does request exactly this feature
So now I don't know if this is a deprecated feature that I shouldn't use, if the warning's wrong, or of the feature hasn't been completely implemented yet (I'm using Maven 3.0.4) ...Does anybody know more about this?
This is a supported feature in Maven 3.2.1 - see 'Transitive dependency excludes' section in the release notes.
I hate getting Maven warnings myself. I've seen the wildcard approach but have avoided it. Run a mvn dependency:tree goal, discover the top-level dependencies belonging to the artefact in question and exclude each one individually (hopefully the list isn't so vast). This is by far the safest way to approach this problem.
As to my knowing, this feature does not yet exist. In the feature request you sent, you can see it's status is still "Unresolved".

dependencyManagement and scope

I usually put a <dependencyManagement> section in parent-project/pom.xml. This <dependencyManagement> section contains declaration and version for all dependencies of my children modules like this (i.e. without the <scope> element):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</dependencyManagement>
In all children modules (i.e. moduleX/pom.xml), I have:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Obviously, in this example I'm repeating the <scope>test</scope> multiple times for the same dependency (once in every child module needing junit).
My question is:
What are the best practices regarding <scope> declaration?
Is it better to put it in the <dependencyManagement>?
Or is it better to put it in the <dependencies> section of the child module (like in this post)? And why?
Is there any definitive answer to this question?
A little late to the party, but I'll add my two cents.
I recently ran into a very difficult to debug issue.
I have a parent pom for managing dependencies across multiple projects. I had it set with all the dependencies common amongst them and included groupId, artifactId, version and the most common scope.
My thinking would be that I would not have to include scope in the actual dependency section in each project if it fell in line with that most common scope.
The problem occurred when some of those dependencies showed up as transitive dependencies. For example, if:
A depends on B at compile scope.
B depends on C at compile scope.
C is set to provided in dependencyManagement of parent.
Then A's transitive dependency on C is determined to be provided. I'm not really sure if that makes sense or not, but it certainly is confusing.
Anyway, save yourself the hassle, and leave scope out of your dependencyManagement.
dependencyManagement is just here to define dependencies version for all project submodules, the only pertinent scope in this section is import for BOMs.
Scope must be defined in dependencies section.
(For a given dependency it determines the usage context. It allows to include the dependency only when it is required for execution. For example an ear will not be packaged with Java-ee dependencies (scope provided) as it will find them on the target server.)
[edit]
The first statement has an exception, the scope provided in dependencyManagement section will override defined scope in dependencies sections. see DependencyManagement to force scope
As with other answers, best practice is to exclude scope from dependencyManagement and explicitly specify it when defining the dependency. It is a rare case that you would want a different version of the same dependency in different scopes, e.g., one version when compiling your app and a different when running it -- the only case I can think of is you want to explicitly run your tests against a different version of a library in case users use that version instead of the one you specify.
If you define scope in dependencyManagement, it restricts the use of that version to ONLY the defined scope -- so any other scopes will pick up a random version of the dependency. I ran into this yesterday when we had defined junit 4.12 in dependencyManagement with test scope, but our common test framework module used junit with compile scope, so it picked up version 4.8.2 instead.
There is no gain in adding a single dependency to the dependency management, for any scope. All you have is the duplication. If you want to have the version configurable, add a property and use it in your dependency:
<properties>
<junit.version>4.10</junit.version>
...
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
</dependencies>
However, there are cases where the dependency management shines - when you are using boms in order to orchestrate the versions for a larger collections of artifacts, like using a certain version of a Java EE implementation:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.jboss.bom</groupId>
<artifactId>jboss-javaee-6.0-with-tools</artifactId>
<version>${javaee6.with.tools.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
....
super late to the party, but the latest maven has very clear documentation on the transitive dependency scope and dependencyManagement details, including one example.
https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#dependency-scope
from the documentation we can see:
when transitive scopes are different, there are precedence rules governing which one will be applied. At the first glance the rules table is complicated, but it makes common sense for most cases.
the documentation specifically has an example of dependency scope and dependencyManagement combined case. ultimately it follows the rules specified in 1.
As a conclusion, it's recommended to include scope in the most 'common' ways. If there are transitive, conflicting or cornered cases, we need to carefully check the precedence rules.

Resources