Maven Learning Questions - maven

In eclipse I've installed m2e plugin. I am trying to understand how do you know the names of properties for dependencies to add to pom file?
Say for instance how do you know which artifact id to use?
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
why here say aspectjrt in artifact id?
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
and here same as group id ??
is there any pattern?
say my project is missing
org.hibernate.Query;
org.hibernate.Session;
org.hibernate.SessionFactory;
and in maven dependencies folder I have hibernate-core-3.6.0.Final.jar which effectively contains everything except those 3.
Do you write these .pom yourself?
I am betting that for student project I will have to stick with manually adding hundreds of libraries... otherwise I will fail trying to learn it :-)

You know what groupId:artifactId:version (we call these coordinates) to use by which artifact you want. Most often, you find out which artifact you want by reading it in the project's documentation, especially for projects with a large number of artifacts, some of which might contain optional addons.
aspectjrt is short for AspectJ RunTime.
GroupId and artifactId are defined by the creators of the library in question. There's no universal pattern because there's no one central coordinator. There are some conventions that have evolved, though. Generally, the groupId is at least partly the reversed domain name, like the first part of a Java package name is: org.hibernate, org.apache, org.springframework... The artifactId distinctly identifies the role of that particular artifact in the group it belongs to, like spring-core, spring-tx, spring-jms, etc. You can get an idea of what groupId's and artifactId's look like by searching Maven Central for some of the libraries you know.
If you're missing org.hibernate.SessionFactory, then you don't have hibernate-core-3.6.0.Final on your classpath. If you have that on your classpath, then you're not missing the SessionFactory class. Those three classes you mentioned are most definitely in that artifact, as you can see from searching for the class in Central. If you still doubt, do a jar -tf hibernate-core-3.6.0.Final.jar and check out the contents yourself. I promise it has those classes.

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.

How to write AOP #Around for a package from specific dependency

I have multiple packages with same name like org.abc.com.client.* in different external libraries/dependencies which have same groupId name but unique artifactId name.
Therefore, it looks like:
<dependency>
<groupId>same_name</groupId>
<artifactId>unique</artifactId>
<version>same_or_different</version>
</dependency>
and unique artifactId has same package name. I don't need AOP for a class.
I want write #Around for a package specific to particular artifactId.
#Around("call(* package(org.abc.com.client)_of_specific_artifactId1(..))")
public void doSomething(){}
#Around("call(* package(org.abc.com.client)_of_specific_artifactId2(..))")
public void logSomething(){}
The artifact ID is a piece of build-time information and should be utterly irrelevant during runtime. BTW, artifact IDs can change, dependencies be re-packaged into uber JARs via Maven Shade or Maven Assembly plugins etc. What you want to do is simply bad design. You should refactor your libraries or find another way to differentiate them from each other.
FWIW, you can solve your problem also during build time by applying native AspectJ aspects to selected artifacts using binary weaving, creating new woven artifacts which can replace the original ones. The AspectJ Maven plugin does that for you, if configured correctly. For Gradle have a look at Freefair.
Update: About 7 years ago, I answered another question involving binary weaving of input JARs. It is a more complex multi-module scenario and if you read the whole answer, you are also going to find a link to a GitHub repository with a complete MCVE. Just replace the the Maven plugin org.codehaus.mojo:aspectj-maven-plugin:1.7 by dev.aspectj:aspectj-maven-plugin:1.13, because the MojoHaus version only supports up to Java 8 and misses some features compared the Aspectj.dev version.

How to have a private maven dependency that is automatically included in a war?

I have the following situation:
project-A
project-B, depends on project-A
project-C, depends on project-B
war-project, depends on project-C
Then because of transitive dependencies, project-C has access to project-A. I don't like this as it allows me to use stuff directly from project-A that project-B was intended to encapsulate (let's stay project-B is a DAO project, and project-A is Hibernate ... I don't want to be able to use Hibernate stuff in project-C).
However, the final war artifact must contain everything needed to run the application, meaning A, B and C. How do I achieve this in a clean manner?
I'm basically looking for a new kind of scope that can be used in project-B's pom:
<dependency>
<artifact>project-A</artifact>
<scope>not-transitive-but-include-in-war</scope>
<!-- this dependency is needed internally only, but should not be exported as it is not needed to use this project -->
</dependency>
<dependency>
<artifact>some-other-dependency</artifact>
<!-- regular transitive dependency, that for example is used in the API -->
</dependency>
I tried using exclusions in project-C (a half-assed solution, as it still requires knowledge of project-A), and also didn't work as project-A did not get included in the war
I also tried using provided / optional scopes. Didn't work, they don't get included in the war.
I don't want to add dependencies only to the war project. This requires me to have knowledge of project-A again.
Why do I want this?
Because it allows me to make sure that certain projects don't accidently start using dependencies they should not be using. Now it is way too easy to break layering because all dependencies are transitive (ie, I can use Hibernate at the Web level or one of the dozens of util projects like apache-commons, google-collections in every dependent project while we for example want to use only JDK stuff in certain projects).

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.

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