Can someone explain Maven 2 (or 3) dependency resolution to me? - eclipse

I used Maven before in quite a few projects but they we already configured by someone else. I quickly understood the main concepts (groups, artifacts and versions for jars, local and remote repositories) so I assumed that if I'm asked I'll be able to set up a new project from scratch easily.
That turned out not to be the case when I deal with multiple modules which depend on one another. I poked around maven docs but they are either way too concise or way too technical (sometimes I get a feeling that Maven people wrote it for themselves and not for Maven users). So I'm asking for community help.
Here's a typical scenario:
Three repositories:
My local repo at <User>/.m2
My company repo at http://maven.mycompany.com/repository
Maven Central at http://repo1.maven.org/maven2/
I'm building a normal Java EE project consisting of one EJB jar with a corresponding client jar, a web module and a JPA module (I like keeping my entities and all db-connectivity separated from business logic). That gives me 5 project in my IDE:
myapp-ear
myapp-ejb
myapp-ejb-client
myapp-jpa
myapp-web
myapp-jpa is used by myapp-ejb and myapp-web. myapp-ejb-client contains business interfaces for my EJBs.
How should I set all that up? I suspect that I need some kind of parent project but I'm not sure how should I organize inter-project dependency resolution. For example: currently when I specify
<dependency>
<groupId>com.mycompany.myapp</groupId>
<artifactId>myapp-jpa</artifactId>
<version>0.1-SNAPSHOT</version>
</dependency>
in myapp-ejb's pom.xml maven tries to search for it in my repository and tells me that the .jar can't be found. Even if I build and install all app components into my local repository one by one Maven always fails to build the ear file itself :(
I'd love to get it working under Eclipse or NetBeans.

I think you're on the right path. You need a parent project to pull it all together. In the parent project (and here is the important part) you need your dependencies laid out NOT in the dependency section of your parent pom, rather, you need them in your dependencyManagement section. Then, in your child pom's you can declare dependencies that are in the parent.
The only other gotcha (that I can think of) is that when you check the project using a version control system in Eclipse you need to remember to check the parent project out "as Maven project" otherwise the m2Eclipse plugin tends to freak out and not resolve things properly.
I hope this helps.

Related

Eclipse doesn't see classes from Maven modules in workspace

We have some Maven modules shared between several teams, with the mandate to share the source code even though our projects use different dependencies and resources. To accomplish this, we have our modules set up as recommended in Using Maven When You Can't Use the Conventions under "Producing Multiple Unique JARs from a Single Source Directory." Specifically, we have a shared parent module containing the src directory but whose pom declares <packaging>pom</packaging> and only builds the two submodules. Each submodule inherits from this parent and refers to the shared src directory using this:
<build>
<sourceDirectory>../src/main/java</sourceDirectory>
</build>
The two submodules have different artifact ids, allowing dependent modules and projects to specify which version and dependency set they need. It also upholds the Maven principle of "one module, one output."
This all works great in Maven-land: compilation, installation, deployments, etc. What doesn't work well is Eclipse integration. Some things work fine: building the modules, deploying to our Maven repo, pulling in dependencies to build our project. But things such as code completion and jumping to class/method definitions do not work at all. It's as though Eclipse doesn't recognize the source at all.
If we just check out a module from SVN, Eclipse doesn't know about the classes but instead uses jars from the repo. If we then import the modules as Maven modules, they show up in package explorer and the project build path. However, all references to those classes and methods are now flagged as errors by Eclipse. And we still do not have code completion or navigation.
So my questions are these: How can we get Eclipse to recognize the code and do its normal code navigation while still satisfying our varying project requirements? Am I missing some simple Eclipse configuration? Do we need to rework our Maven module structure, and if so, how?
Some additional context: The different dependencies for the projects are rather large, including different major versions for things such as Weblogic and Spring. The Weblogic versions will converge some time next year, but the other dependencies will be slower (and some resource files will likely always remain distinct). So for the near- to mid-future, we have to account for different dependencies between the projects.
We are using profiles to allow our Jenkins server to build both submodules while allowing individual developers to build only the submodule their project needs. Using profiles to manage the dependencies is problematic because we lose transitivity of dependencies.
Update (12/8/15)
I was eventually able to make Eclipse recognize the source directory by using "Link Source..." on the "Configure Build Path..." dialog. Adding a source folder would not let me reference the module's parent directory, but Link Source let me assign an arbitrary directory to use. It's not ideal, but it seems to be working.
I was eventually able to make Eclipse recognize the source directory by using "Link Source..." on the "Configure Build Path..." dialog. Adding a source folder would not let me reference the module's parent directory, which derailed me for a while. However,Link Source let me assign an arbitrary directory to use.
It's not ideal, but it seems to be working. We can now jump to definitions with F3, and errors are now highlighted correctly. It's good enough that I don't feel bad recommending it to the other team. I wish Eclipse would automatically allow a parent source directory to be referenced, but at least the manual intervention worked right.

what exactly maven dependency tag does?

I have started reading and trying maven since yesterday. But its making me go crazy.
I am java developer but never came across ant or maven before.
I want to know what exactly happens with the dependency tag in POM.xml file?
Lets say, I am using camel framework and want to use camel core jars.
If one of my class file contains following line:
CamelContext context = new DefaultCamelContext();
so what exactly I need to do after that?
Do I need to include the jars myself in the class path or dependency tag will download the jar files over internet for me?
If the case is former, what dependency tag will do? & where should I place my jar files? I mean is there any specific location on my hard drive? and
if the case is lateral then during compile time I get error "cannot be resolved to a type"
And the imports are to be specified or not?
I know the question might sound silly but I am not able to find its answer.
I have tried googling alot, it didn't help me still.
Any help would be greatful, even help on maven topics which I might come across in near future would be appreciated.
Thanks in advance.
Solved. Please check https://stackoverflow.com/a/20094312/1121208 for help
dependency tag will download the jar specified in the dependency tag for you if available. Otherwise will raise a pom.xml error - could not found dependency..
Imports have nothing to do with maven. They will appear when you will you another class in your class/java file. So if you import in build path the jar by yourserf or if you put it there with maven, you will have the import.
Are you using eclipse or any other ide ?
First of all, Maven is a build tool. It doesn't run your app. It builds it. So, at runtime, the classpath needs to be set like for any oter application yo would have built with something else.
When you build an app, you depend on external libraries. The dependencies mechanism of Maven simply lets you declare wwhich libraries your ap needs. When you build your app, Maven downloads these libraries from a central repository (or sevaral ones), and stores them in a local repository on your hard drive. These jars are automatically added to the build classpath by Maven. At runtime though, depending on the kind of ap you're building, you'll have to copy or embed those jars in order to create a runnable application.
The rules of Java don't change just you build them with Maven. Meven uses the stadard Java compiler (javac). And of course, if you want to use a class by its simple name, you'll have to add an import statement for this class.
I think that, before using Maven, you should try to compile and run a simple application depending on an external library without using any IDE. You would then understand better all the steps that are required to build and run an app, the concept of build and runtime classpath, etc.
Finally got what I needed to know
Sharing it for others who may stuck up in same situation
Does dependency tag download the jar specified?
maven dependency tag actually downloads the jar files you specify in the dependency tag. It downloads and save it under .m2/repositories(local repository) folder on your hard drive (along with some information like last updated, etc)
Local repository is shared among all your projects
from where it downloads?
It downloads the jar from the central repositories. There central repositories contain almost all the open source jar files one needs in a project. It downloads based on information you provide in groupid, artifactid, etc.
http://repo1.maven.org/maven/
http://mvnrepository.com/
can be checked for correct groupid, etc
Once these jar files are downloaded, they are automatically added to the classpath and are available in your project for use.
If the jar files you are searching for, are not available in the central repository, maven may throw error, in that case you can download it manually and let maven know about it.
Without maven you need to put jars into lib folder.
With maven you specify as declaration inside <dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
and when you do mvn package, maven will download required jars on your PC.
With Eclipse and m2e (maven eclipse integration) you can do that all not leaving Eclipse,
and even get sources for used libraries automatically.
Read http://maven.apache.org/ It worth it.

Maven integration with IDEs

I thought I understood Maven as I've worked on a few projects using it, but I seem to be having trouble creating my own project with it, so can someone correct me wherever I may be wrong?
Assuming I create a new Maven project (we'll say I did it through Eclipse or IntelliJ):
If I add a dependency to my POM file, assuming I add a public repository where that dependency can be found, shouldn't the IDE download the specified JAR and make it so that it is recognized when I use it in my code? Currently, my projects do not recognize any classes that should be found in JARs via my POM dependencies.
Assuming #1 does work, how can I determine via maven which transient dependencies I have? For example, I'm using classes from Pentaho Data Integration, and some of the plugins for it reference things like org.mozilla.javascript.*. Could maven automatically tell me that without me having to run the code, see it fail, and manually fix the dependency? There will be hundreds of those instances here, so manual fixing really isn't viable.
Here are my IntelliJ two cents:
1 - Adding a dependency in pom.xml of your project
Should indeed download the depended jar(s). You may need to approve "Import Changes" dialog if it pops in, or enable auto import.
2 - Seeing transitive dependencies
It can be achieved via Maven Dependencies Diagram - unfortunately only in IntelliJ Ultimate edition. You can use Maven Dependencies Plugin to see the dependencies tree in your favorite CLI.
Question 1: Adding a dependency
In Eclipse, depending on how you created the project, you should be able to add dependencies that are automatically recognized using the maven context menu.
Note that you should have created the project using the eclipse maven plugin so that it has maven nature.
To add dependencies/plugins from a remote repository, you can search in the resulting UI for a dependency if you know the artifactId or groupId. The plugin will pull up the deps whether the repo url is specified in the pom.xml or not.
After adding a dependency to the POM, the IDE will start downloading it and all transient dependencies as soon as you save the file.
If something goes wrong, you can try to "Update Project" from the context menu.
Question 2: Determining transitive dependencies
Transient dependencies are visible in the "Dependency Hierarchy" tab of the POM editor.
I usually default to the command line because it allows much more flexibility and functionality when tracking the dependency graph.
I am sorry but I have not worked with IntelliJ

is there a way to generate a pom.xml with dependencies from an eclipse project?

I have inherited a big project with several subprojects.
all of them use several jar files, all of them located under each project's lib directory. I want to take all the projects and migrate them to maven, but dependencies are a problem (too many of them), some of them are commonly used libraries (apache projects, xerces, jms, etc) and others are not.
is there a way to autogenerate maven dependencies for those jars that can be found on public maven repositories. for example, see that my project use the spice-jndikit-1.2.jar file and automatically get the appropiate depedency with group, artifact and (if possible) version?
thank you
I wrote a groovy script to generate a starting set of Apache ivy files.
https://github.com/myspotontheweb/ant2ivy
In my case, I wanted to "Maven-ize" my ANT builds without switching completely away from ANT.
It is feasible to extend this code to generate a Maven POM, if people were interested in this feature.
You can convert a project to Maven using the m2e plugin, but this erases your jar references, and should not be used.
I doubt that such a thing exists since typical jars (unless themselves built with Maven) don't have the necessary information to correlate the groupId, artifactId and version back to a repository to get the proper path.
You might be able to write something that parses the file name for the name and version, but you still have the package-based path to figure out.
If you're building using Ant, you might also consider using Apache Ivy, and its file-system based resolution (very fast and easy to configure), to get you started, and slowly role over to the Maven repos for the artifacts, this way you're not spending a lot of time up-front finding Maven dependencies.

Eclipse + Subversion (subclipse) + Maven (m2eclipse) multi-module project

I have some related legacy projects that are a mess and I would like to mavenize them as a multi-module project shared on subversion (first multi-module project, we've always had them separate). There are a few key parts 1) webservice, 2) various swing clients, 3) model (w/ persistence from hibernate), 4) core JSE tasks.
I've been messing around for a few days trying to correctly set it up using Eclipse (Helios), Maven (2.2.1), m2eclipse (0.10.0) and Subversion (1.6) for our team. I keep stumping myself or having random errors that force me to backtrack. I'm hoping someone can help me out with some best practices.
Here are some of the questions:
m2eclipse requires a "flat" eclipse project structure. Does that mean I should create a subversion repository for each module? If I do one repository and try to check in from the parent project I'm having a difficult time setting the svn:ignore property on the nested project target (and other) directories.
If I do a module per repository, I seem to be able to check them in ok. The question then is what is the best way to check out via subclipse? Is there a best order? Parent or child project(s) first? Do I need to checkout the parent project and modify the checkout path of the children project to be nested in the file directory that will allow me to then "clean install" from the parent project?
Or, should I abandon subclipse and m2eclipse and checkout and run my maven goals from the command line.
Or, should I just be using the SCM integration with Maven. Or, maybe just not even try to get a multi-module project setup.
What do others do? Does anyone have some documentation (I missed) or some links (Google didn't recommend)?
Thanks in advance for your feedback.
m2eclipse requires a "flat" eclipse project structure.
Hmm, m2eclipse supports nested projects AFAIK (or at least importing a nested project structure). I don't use Eclipse wizards to create my projects though so maybe I'm not aware of something.
Does that mean I should create a subversion repository for each module?
No, no, absolutely not and I wouldn't do that (this will be hard to maintain). However, depending on your projects release cycles, you might have to think about the layout of your repository (single vs multiple trunk/tags/branches), especially if you plan to use the maven release plugin. If some pieces have independent release cycles, then I'd go for several trunk/tags/branches. If you always release them all together (as a single product), then a single trunk/tags/branches should do it. I wrote several answers on the topic that may be of interest:
Migrating to maven from an unusual svn directory structure?
Maven parent pom vs modules pom
How to handle maven versions in a multi module project?
If I do one repository and try to check in from the parent project I'm having a difficult time setting the svn:ignore property on the nested project target (and other) directories.
What is the particular problem?
If I do a module per repository, I seem to be able to check them in ok. The question then is what is the best way to check out via subclipse? Is there a best order? Parent or child project(s) first? Do I need to checkout the parent project and modify the checkout path of the children project to be nested in the file directory that will allow me to then "clean install" from the parent project?
Whatever choice you'll make (multiple repositories or not, multiple trunk/tags/branches or not), it should be possible to checkout the whole project structure in one time (using svn:externals if required). At least, you should try to make it possible (and it is, see the links posted above).
But I repeat, I do not recommend using multiple repositories (unless you want independent revision numbers) and nothing forces you to do that.
Or, should I abandon subclipse and m2eclipse and checkout and run my maven goals from the command line.
I use Eclipse, m2eclipse, subclipse successfully, all well integrated (at least for the build and "check in" part). But I do the initial import and the initial checkout on the command line and then imported
Or, should I just being using the SCM integration with Maven.
I don't use it, I don't have the need for it.
Or, maybe just not even try to get a multi-module project setup.
There is no reason to forbid the use of a multi-modules project setup, multi-modules builds are one of the key part of Maven.
What do others do? Does anyone have some documentation (I missed) or some links (Google didn't recommend)?
Have a look at the links I posted :)
It is a bit tricky at first. The way I've typically seen it setup is like so:
In subversion:
- Parent Project
-- Module A
--- pom.xml (module A)
-- Module B
--- pom.xml (module B)
-- Module c
--- pom.xml (module C)
-- pom.xml (parent project)
Some things to note (you already know):
You have to have the child projects
listed as modules in your parent
project
You have to list the parent project
in your child pom's (as the parent
group, artifact, version)
When you check out the project from
svn, you need to do 'check out as
maven project' instead of the
standard 'check out' (this one can be
a gotcha)
I hope this helps.