What does it mean that artifact scope is not transitive? - maven

In this document (https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html) under dependency scope "test", it says test scope is not transitive. What does it mean?
Does it mean if we include an artifact with scope as test in some pom, then its dependent artifacts will not be automatically downloaded/included in classpath?
Or does it mean if we include an artifact in some pom, then its dependent artifacts with scope as test will not be downloaded/included in classpath?
Or something else.
As far as I know first one is not true and second one is right. Can someone please tell me what exactly does it mean?

To be clear, this is the passage of the documentation:
test
This scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases. This scope is not transitive.
Those two sentences handle the cases that can rise during dependency resolution: declaring a dependency in the POM, and considering transitive dependencies of dependencies declared in the POM.
The first part means that having in your POM a dependency with scope test will result in that dependency being only available in the test classpath. Put another way, it applies when you have explicitly declared a dependency in the POM:
<dependency>
<!-- GAV coordinates -->
<scope>test</scope>
</dependency>
Trying to use it in main Java classes (under src/main/java) will result in a compilation error, and using it in test Java classes (under src/test/java) will work fine.
The second part applies to the dependencies of dependencies that are declared in the POM. It means that test scoped dependencies of the dependencies declared in the POM will be omitted. For example, suppose you are having a compile-time dependency on a library called A, and A itself has a test-scoped dependency on B; then B will be ignored in the dependency resolution, and will not end up on your classpath. The logic is that, A needs B to run its tests, but as a consumer of A, you don't need B to be able to use it. Those test-scoped dependencies will always be omitted, whatever the scope of the declared dependency you have (whether it is compile, runtime, or even test), which is why the test scope is called not transitive.
Put another way, it all depends what is meant by "some pom". When you're declaring a test scoped dependency in your POM, it will be available on the test classpath. All of its compile and runtime transitive dependencies will be available on the test classpath as well, because the compile and runtime scope are transitive and will be inherited with a scope of test. When the POM is not your own, the test scoped dependencies will be always omitted (therefore its dependencies will be omitted as well).

Related

What is the final dependency scope when different scopes are specified for one JAR?

I am studying some JARs in the Maven Repository and discovered this:
Hibernate Validator Engine 5.4.0.FINAL lists jboss-logging as a compile dependency, and jboss-logging-processor as a provided dependency
jboss-logging-processor lists jboss-logging as a provided dependency
In general, when a JAR is mentioned multiple times along the way under different scopes, what is the final, actual scope? Is there an order of precedence of sorts?
It depends on the context rather than inheritance.
However, if some implications are present:
something is marked as compile it is implicitly a runtime dependency.
something is marked as runtime it is implicitly a test dependency.
provided will be used in both runtime and test though it is not loaded during run or test time.
system will be used in both runtime and test

What is <scope> under <dependency> in pom.xml for?

Looking at documentation http://maven.apache.org/surefire/maven-surefire-plugin/examples/testng.html, we can see <scope> tag under <dependency>
What is that and how can we use it for running test?
The <scope> element can take 6 values: compile, provided, runtime, test, system and import.
This scope is used to limit the transitivity of a dependency, and also to affect the classpath used for various build tasks.
compile
This is the default scope, used if none is specified. Compile dependencies are available in all classpaths of a project. Furthermore, those dependencies are propagated to dependent projects.
provided
This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
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.
test
This scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases.
system
This scope is similar to provided except that you have to provide the JAR which contains it explicitly. The artifact is always available and is not looked up in a repository.
import (only available in Maven 2.0.9 or later)
This scope is only used on a dependency of type pom in the section. It indicates that the specified POM should be replaced with the dependencies in that POM's section. Since they are replaced, dependencies with a scope of import do not actually participate in limiting the transitivity of a dependency.
To answer the second part of your question:
How can we use it for running test?
Note that the test scope allows to use dependencies only for the test phase.
Read the documentation for full details.
Six Dependency scopes:
compile: default scope, classpath is available for both src/main and src/test
test: classpath is available for src/test
provided: like complie but provided by JDK or a container at runtime
runtime: not required for compilation only require at runtime
system: provided locally provide classpath
import: can only import other POMs into the <dependencyManagement/>, only available in Maven 2.0.9 or later. It is not always practical to change parent, many projects already specify a parent project to manage their organization standards. dependencyManagement allows us to add parent project without making parent, it's like multiple inheritance.
Scope tag is always use to limit the transitive dependencies and availability of the jar at class path level.If we don't provide any scope then the default scope will work i.e. Compile .
Compile means that you need the JAR for compiling and running the app. For a web application, as an example, the JAR will be placed in the WEB-INF/lib directory. Provided means that you need the JAR for compiling, but at run time there is already a JAR provided by the environment so you don't need it packaged with your app. For a web app, this means that the JAR file will not be placed into the WEB-INF/lib directory. For a web app, if the app server already provides the JAR (or its functionality), then use "provided" otherwise use "compile".
.pom dependency scope can contain:
compile - available at Compile-time and Run-time
provided - available at Compile-time. (this dependency should be provided by outer container like OS...)
runtime - available at Run-time
test - test compilation and run time
system - is similar to provided but exposes <systemPath>path/some.jar</systemPath> to point on .jar
import - is available from Maven v2.0.9 for <type>pom</type> and it should be replaced by effective dependency from this file <dependencyManagement/>

Should all 3rd-party jar dependencies be introduced to Maven via 'import' scope?

So confused about import scoping in Maven. It seems to imply that all 3rd-party jar dependencies in a large, muti-module project would benefit from being dependency managed in the parent using the 'import' scope. Is that correct?
From maven's documentation about the import scope:
This scope is only used on a dependency of type pom in the section. It indicates that the specified POM should be replaced with the dependencies in that POM's section. Since they are replaced, dependencies with a scope of import do not actually participate in limiting the transitivity of a dependency.
Frankly, this is usually isn't a very useful scope, and in any event it is not relevant for 3rd party jar dependencies - only for 3rd party pom dependencies. Where you place dependencies is somewhat a matter of taste, but the practice I found worked best for me was to place all the dependencies in the "lowest common denominator" pom's <dependencyManagement> section, and then referencing them in the <dependencies> section of the specific subprojects as needed.

Direct dependency and transitive dependency in test scope through maven

Is a direct dependency available in test scope while using maven?
So, if user-management have a dependency on utility module in normal flow:
<dependency>
<groupId>GROUP ID</groupId>
<artifactId>utils</artifactId>
<version>${version.product}</version>
</dependency>
Then will it also be available in test scope while testing user-management?
Is transitive dependency available in test scope while using mavan?
like User-managment-> utility-> plan
Then I don't think it would be available as maven document Maven: The Complete Reference
3.4. Project Dependencies.
So how can I include transitive dependency in test scope?
While testing user-management I am using some domain objects and service classes of other modules also.
I am shocked with this and it would be great help if someone can help that how to run these test cases as a project level.
Thanks in advance!!!!!
During tests, the test output directory and main output directory are the first two things on the test classpath, respectively. Then come all of your direct and transitive dependencies of all scopes, following the rules for scopes and transitive dependencies in the link you mentioned and in the order you've declared them in the POM. Find details about each scope in "Dependency Scope" on the Maven site.

How can I efficiently declare provided scope dependencies in maven multi-module builds?

I have a maven multi-module pom which builds a war. I want to declare a provided scope dependecy on jsp-api in the parent pom. Maven docs suggest that dependencies declared as provided are not transitive, so:
Do I therefore need to go through all the sub-module poms and declare a provided dependency? There are ~40 modules in the project and it's not immediately clear which will need the dependency, so this seems like quite alot of effort to achieve not very much and I am lazy. How are you handling this situation in your projects?
--Edit--
So for others reference this was happening because the parent pom was defining all dependencies in a dependencyManagment section. I'd not come across this before but it helps with cutting down duplication of complex dependencies with excludes or other non-trivial attributes. It also overrides the inheritance mechanism. As I understand it then, a good rule of thumb is to only use it to solve a problem don't just chuck all your dependencies in there as the author of this pom had done. Perhaps a suitable maven expert could confirm this.
Even though provided scope dependencies are not transitive they may be inherited. That is to say, if you have module A with a provided scope dependency, and module B has a dependency on A, module B will not implicitly have the provided scope dependency. However, I believe that if module C has module A as a parent pom, it should inherit that dependency as normal.
You can verify this behavior yourself by running mvn help:effective-pom on one of the child poms, the effective-pom goal should give you a fully resolved view of the pom you run it on, taking into account inheritance, equivalent to what maven will actually use when it runs. If the <dependency> shows up there (as it seems to in my experiments) you should be fine specifying the dependency only in the parent pom.

Resources