Direct dependency and transitive dependency in test scope through maven - 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.

Related

Meaning of SCOPE tag in Maven Dependency

When we use scope tag while providing dependencies in POM file of Maven, we can give several valid values (compile, run, provided etc..). I understand that tag is applicable for only transitive dependencies (i.: list of JARs required by direct dependencies that we give in POM).
When we give the scope as provided, will the dependency not be downloaded from Maven central repository ? Can someone please confirm.
Thanks!
Dependencies with scope provided are meant to be provided by the container in which the application runs (e.g. provided by jboss).
This means that they are downloaded by Maven, put on the compile and test classpath, but not included into the final WAR or EAR you are building.

What does it mean that artifact scope is not transitive?

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).

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/>

Correct way to declare multiple scope for Maven dependency?

I have a dependency that I want to use in test scope (so that it is in the classpath when I am running unit tests), and in runtime scope (so that I can contain that in WAR/EAR/other packaging for deployment, but not affecting transitive dependency lookup for dependent artifacts).
A real life example is SLF4J's implementation JARs (e.g. Logback). I want it to exist in the classpath when I am running tests, and I want it to be included in my WAR/EAR, but I don't want project depending on my project to include that in transitive dependency lookup.
I tried to use <scope>test,runtime</scope> but Maven 3 produces a warning:
[WARNING] 'dependencies.dependency.scope' for org.slf4j:jcl-over-slf4j:jar
must be one of [provided, compile, runtime, test, system] but is 'test,runtime'.
What is the right way for declaring the dependency scope in such a case?
The runtime scope also makes the artifact available on the test classpath. Just use runtime. (See the Maven documentation.)
To avoid having the dependency resolved transitively, also make it optional with <optional>true</optional>:
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback</artifactId>
<version>0.5</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
You can only define one scope value per <scope/> tag.
I'm afraid what you'd like to do cannot be achieved by merely using a scope. If you define a scope of test, it will only be available during tests; if you define a scope of provided, that would mean that you would expect that dependency for your project to be resolved and used during both compilation and tests, but it will not be included in your WAR file. Either way, it's not what you would want.
Therefore, I would recommend you have a look at the maven-assembly-plugin, with which you can achieve it, but it will still require some playing around.
Not sure if this would still help someone who is still looking for a simple way to do this - https://howtodoinjava.com/maven/maven-dependency-scopes/ this link helped me add the correct scope. Here is the summary of mapping of scopes and the phases where we need the dependencies.
compile - build, test and run
provided - build and test
runtime - test and run
test - compile and test
So, when I needed the dependency during test and runtime, I gave the scope as "runtime" and it worked as expected.
Declaring a dependency with a scope of runtime ensures that the library is not available during compile time.
Declaring the dependency as optional causes a break in the dependency resolution process; projects depending on your libraries will need to explicitly include the dependencies themselves.
So the correct way to declare this would be:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.13</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

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