Eclipse Maven runtime dependencies and profiles - eclipse

Im trying to understand maven profiles and have run into the following issue.
This is my simplified example, I have two maven projects, project A and Project B.
project A has a compile time maven dependency on project B.
project B includes a runtime dependency (lets say to project C) when the maven profile "TEST" is active.
so the problem is the class path generated when I run project A. it doesn't have project C in it, even though the TEST profile is active for project A.
this is using eclipse Helios service release 1, Maven Integration for Eclipse plugin vrs 0.10.2.20100623-1649
any ideas?

I'm not sure that profiles are the best way to handle with TEST.
The use of profile to change dependecies will change the POM of the generated project.
If you install Project B with TEST activated, the runtime dependency will be added. (Whatever project A profile).
Optional dependencies are not added by transitivity. You need to add the dependency in project A.

I just tested this in Eclipse using m2eclipse 0.12.x. The second project pom.xml look like this:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>test2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<profiles>
<profile>
<id>TEST</id>
<dependencies>
<dependency>
<groupId>org.test</groupId>
<artifactId>test1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</profile>
</profiles>
</project>
Then I set profile TEST as an active on Maven panel in the project properties dialog and made sure dependency resolution from Workspace is enabled there.
After that you can run any classes from test2 project's src/main/java and generated classpath looks like this:
C:\Dev\Java1.6\bin\javaw.exe -Dfile.encoding=Cp1252
-classpath C:\Dev\Workspace\test2\target\classes;C:\Dev\Workspace\test1\target\classes org.test2.Test2
Note, that dependencies with runtime scope only works for "Java Application" launch configuration type in Eclipse, but not for "JUnit" launch configuration, which uses different classpath resolver provided by m2eclipse's JDT integration.

It seems dependencies that are within profiles of dependent projects (transitive) dont give there runtime dependencies to the person who depends on them, This seems strange.
A work around was to add the profiles (containing the dependencies) to a parent then the children inherit the dependencies.
i.e. introduce a parent to A, I could have put them directly in A as YMomb kindly suggested. but its the inheritance aspect of this issue I needed to resolve as I have lots of projects As.

Related

Missing Maven dependencies in Eclipse multi-module project

I’m using STS 2.9.1 (build on Eclipse 3.7.2) with m2e plugin bundled with STS (v1.0.200.20111228-1245).
I have a problem regarding missing dependencies in Eclipse project that contains several modules, or maybe I don’t fully understand how it should work.
It’s a maven project.
In my Project > Properties > Java Build Path > Libraries I have “Maven Dependencies” library, but it's empty (and that’s the problem).
The main POM doesn’t have any dependencies, but it has several modules declared in it.
Adding a dependency to module’s POM doesn’t add it to the “Maven Dependencies” library (what was my expectation) and leads to Eclipse showing errors in source files.
Adding a dependency to the main POM adds it to the “MD” lib, but of course I don’t want to add all of my modules’ dependencies to the main POM just to have it in “MD” lib and adding every single dependency to the Build Path doesn’t seem right nor practical.
I’ve tried:
Project > Clean,
Maven > Update dependencies,
Maven > Update project configuration,
Unchecking the checkbox: Project > Properties > Maven > Resolve dependencies from Workspace projects.
None of the above seems to do the trick.
Example:
Simplified project structure:
simple.project
...
sample-module
...
pom.xml
pom.xml
simple.project/pom.xml:
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>test</groupId>
<artifactId>simple.project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>sample-module</module>
</modules>
<dependencies>
<dependency><!-- This dependency is present in "MD" lib. -->
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
simple.project/sample-module/pom.xml:
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>simple.project</artifactId>
<groupId>test</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>test</groupId>
<artifactId>sample-module</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency><!-- I've expected this dependency also to appear in "MD" lib. -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
It is not supposed to work. A project only imports a dependency from another one if it depends on that project (using dependency) or if it inherits from it (using parent). The module element only represents an aggregation.
The question is from time ago, but I solved this creating a Maven Project and adding Maven Modules: right click on project and "New > Project... > Maven > Maven Module".
After that, no more errors were shown in code.
First thing that I see is that you're defining dependencies in a pom parent. There I would expect to see a <dependencyManagement> (see here the doc) structure. In this way the submodules will inherit properly those common dependencies.
Aside from that lets start for the most simple test. Try to compile your project from the maven utility in the command line. If it works then you have a problem in your Eclipse configuration, otherwise the problem is in the way you have defined your project.
If your project compiles properly from the command line, lets see what else can be happening.
The fact that the Maven Dependencies Library is empty means that the Eclipse Maven plugin is not resolving properly your poms. I had quite bad experiences with the embedded STS maven plugin. Try to downgrade it to the m2e 0.10 version. You only need to open the STS DashBoard / Find Updates / Install m2e 0.10
I hope some of these tips can help you.

Maven: Jar in Referenced Libraries despite not showing in effective POM

Before importing my Maven project, I build it using the following: mvn clean install
I then create the necessary Eclipse files as follows: mvn -Dwtpversion=2.0 eclipse:eclipse
I notice that my Referenced Libraries in Eclipse contains this jar: validation-api-1.0.0.GA.jar
However, when I view the effective POM in Eclipse no such jar appears. Therefore, I am wondering how this jar gets added to my Eclipse classpath?
I require this jar for #Valid annotation I am using and I need Maven to be aware of it. If I build my classpath files using Maven then how come Maven is not aware of it?
Thanks
Check the Dependency hierarchy-tab in your pom (in Eclipse), maybe the jar is a dependency of some other jar you use.
In this case, the reference was in the project's Java Build Path, and was probably added when the project was created because of the -Dwtpversion=2.0 -parameter.
Maven also adds to your class path the sub-dependencies of your main dependencies (which are those specifically declared by you in the pom.xml). Do a
mvn dependency:tree -Dverbose
To see what other dependencies are pulled in with a specific pom-declared dependency.
Also, if you only wanna see the subdependencies of a certain dependency, called x.y.z you can do:
mvn dependency:tree -Dverbose -Dincludes=x.y.z
(where x.y is the groupId and z is the artefactId)
One of your project dependencies probably has a dependency for this jar file. Check the graphical dependency graph or just search for that, find out your project dependency that is dependent on this and exclude this dependency, if possible, by using maven's 'exclude' tags.
You can use maven dependency exclusions, as below:
<project>
...
<dependencies>
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<exclusions>
<exclusion> <!-- declare the exclusion here -->
<groupId>sample.ProjectB</groupId>
<artifactId>Project-B</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>
Source: Maven - Dependency Exclusions
I have encountered the same problem. And after some research I realized that transitive dependencies of your parent pom may not show up in Effective POM, but would be present in Reference libraries.
The whole confusion raised because when I ran the following command
mvn dependency:tree -Dincludes=X (where X is the group-id of the jar I was looking for)
It did no mention of parent pom, instead it referred to dependency in parent pom which brings X to the table. (Which make sense because we inherit from parent pom).

Eclipse Maven Dependency

I have just added dependencies to an eclipse project so that my jar can see other jars. How can I be sure that the dependencies work, and that what I've done is correct? I view a pom.xml file that has been created so what are the target folder and classes,test-classes subfolders used for? Thanks
If you have the m2eclipse plugin installed you can open your pom in Eclipse and click on the Dependency Hierarchy tab to view your resolved dependencies. You should manage all dependencies through Maven with the setup you are describing.
If you want to check command line you may want to look at using Effective Pom.
If you use m2e, it adds Maven Dependencies pseudo library to your project.
You may expand it and see if the dependent jar file is in there.
If it is, Eclipse ( or more precisely m2e ) has resolved the dependency correctly and it's available for you project build.
If you added your dependencies correctly your application should build and execute correctly, or am I missing something? Dependencies should be added to a POM section that looks like this example:
<dependencies>
<dependency>
<groupId>annogen</groupId>
<artifactId>annogen</artifactId>
<version>0.1.0</version>
</dependency>
<!-- other dependencies here -->
</dependencies>
Maven and the m2e/m2eclipse plugin rely on source files to be conventionally placed in src/main/java for application code and src/test/java for test code. Application code is compiled to target/classes and test code is compiled to target/test-classes. If you plan to use Maven and/or m2e/m2eclipse, do read about it. Maven: The Complete Reference is a good starting point.

Eclipse Project with Dependency Management by Maven

I have a Eclipse project where Maven manages the dependencies. I have also few jar files that are not Maven enable and I locate them at src/main/webapp/WEB-INF/lib. I have no issue to build/run the project in Eclipse. I have no issue also to run "mvn:package" after I built the project in Eclipse. However, after I invoke "mvn:clean", if I run "mvn:package", I will get compilation error as it can't find dependency jar files under src/main/webapp/WEB-INF/lib. What I need to do is to rebuild the Eclipse project then "mvn:package". Therefore, I can't invoke "mvn:package" outside Eclipse IDE.
How to resolve this?
Thanks.
You have to put the not "Maven enabled artifacts" to an appropriate Maven Repository (Nexus, Artifactory what ever) and than change your project to use the dependencies appropriately. Furthermore either you do Maven or not but nothing in between. Maven is a build tool and not only for dependency management. After those changes working with Eclipse will work fine (if you use M2Eclipse). If you correctly use Maven you can do both things via Eclipse or call mvn package on command line.
If you can not set up a recommended environment (maven repository) you can add the dependencies as System dependencies to your pom.xml.
<project>
...
<dependencies>
<dependency>
<groupId>foo</groupId>
<artifactId>bar</artifactId>
<version>1.2.3</version>
<scope>system</scope>
<systemPath>${basedir}/src/main/webapp/WEB-INF/lib/foobar.jar</systemPath>
</dependency>
</dependencies>
...
</project>

Maven and Eclipse code organization

I'm new to Maven, and after having read the docs on the maven site and Sonatype's online Maven book, I'm still not clear on how to best organize things.
I have two apps, A and B which share code from mylib. Different developers work on apps A and app B, they are released independently. Before we started with maven, in Eclipse, I'd have a workspace with apps A and B and mylib. The classpath for app A contained mylib. If I made a change in mylib, pressing run within Eclipse, contained my latest changes.
In Maven, I can create a parent pom.xml, which references app A and mylib. But this makes mylib a subdirectory of app A. How can I keep one instance of mylib and not link the building of apps A and B?
We use SVN for our SCM
Thanks
You have multiple options, however, potentially the simplest approach would be to separate out mylib into its own Maven project with its own life-cycle. The benefit of this approach is that you can support having multiple versions of mylib and your apps A and B can reference different versions of mylib as needed. If mylib and appA are open in Eclipse (and mylib references the version of mylib you have open), you can build the application in the same manner as you did prior to using Maven.
This approach does not mandate any dependencies between the directory structures of the applications, so you could go with something similar to the following:
/myapps/mylib
/myapps/appA
/myapps/appB
The downside to this approach is that maven will not automatically build both appA and mylib (or appB and mylib) as they are treated as separate applications. However, this may not be much of an issue if your applications are using pre-defined and built versions of mylib (that have been uploaded to your local maven repository using "mvn install").
Here is an example of the POMs for these projects:
mylib:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>myLib</artifactId>
<versioning>0.0.1</versioning>
<packaging>jar</packaging>
<name>mylib</name>
...
</project>
appA:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>appA</artifactId>
<packaging>jar</packaging>
<name>appA</name>
...
<dependencies>
<groupId>com.text</groupId>
<artifactId>mylib</artifactId</artifactId>
<version>0.0.1</version>
</dependencies>
...
</project>
appB:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.test</groupId>
<artifactId>appB</artifactId>
<packaging>jar</packaging>
<name>appB</name>
...
<dependencies>
<groupId>com.text</groupId>
<artifactId>mylib</artifactId</artifactId>
<version>0.0.1</version>
</dependencies>
...
</project>
If you still want the convenience of a parent POM (one mvn package comment), then you could create a master pom in the /myapps folder similar to the following:
<project>
<groupId>com.test</groupId>
<version>0.0.1</version>
<artifactId>myapps</artifactId>
<packaging>pom</packaging>
<name>myapps</name>
<modules>
<module>shared</modules>
<module>appA</modules>
<module>appB</modules>
</modules>
</project>
This POM will automatically build myapp, appA and appB. If desired you could also create an appA and appB specific POM (pom-appA.xml). This is not the cleanest approach from a Maven perspective, but it will function. The only issue you would run into is if the version of mylib is not the version on which appA or appB is dependent. In that case your appA or appB code would be compiling against the version in your maven repository (if that version exists).
There are many other options you can use as well and I have seen plenty of discussions on Blogs and Wikis as to which is the best for various scenarios. However, it usually comes down to what works best for you and your organization. As long as it works and you are not going off building a custom, non-portable maven solution, then you are probably doing ok.
Hopefully this gives you some thoughts that you can use.