In our Maven project, we are trying the following directory structure (with about 80 projects total, only a few are shown so that you get the idea):
myappli (pom)
-- module1 (pom)
--|-- utils (pom)
--|-- ejb (pom)
--|--|-- myappli-module1-a-ejb (jar)
--|--|-- myappli-module1-b-ejb (jar)
--|-- war (pom)
--|-- applet (pom)
...
-- module6 (pom)
--|-- utils (pom)
--|-- ejb (pom)
--|--|-- myappli-module6-c-ejb (jar)
--|-- war (pom)
--|-- applet (pom)
Note: This is a flat structure for Maven, as all non-leaf projects have a packaging value of "pom". (cf BetterBuildsWithMaven book).
We define the dependency versions in "dependencyManagement", in the "myappli" pom. This works fine.
Our problem is with the reuse of the dependencies themselves.
For example, the ejb dependencies are common to all ejb projects (by design).
We don't want to cut'n-paste, and maintain all that with each change!
We were thinking to use some "import notion" for the ejb dependencies, and define our ejb dependencies once at the application level. Our unsuccessful attempts were:
The Maven "parent pom" notion would be fine, but it is already used by the modules, so it is not available for our requirement.
No import facility found in Maven (except for dependencyManagement)
XML entity definition is not recognized. We tried a pom like the following, and got the error
"Reason: Parse error reading POM. Reason: could not resolve entity named 'ejbDependencies'":
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project [
<!ENTITY ejbDependencies SYSTEM "./ejbDependencies.txt">
]>
<project ...
...
&ejbDependencies;
...
Edited : I am trying the solution suggested by Robert, but something is wrong.
When I compile my ejb project, it doesn't find the dependencies themselves. I get an error when compiling (mvn compile), saying the javax.ejb package is missing.
Note: I did run "mvn install" on the dependencies project before.
This is my configuration :
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.company</groupId>
<artifactId>myproj-maven</artifactId>
<version>3.1-SNAPSHOT</version>
</parent>
<groupId>com.company</groupId>
<artifactId>myproj-maven-ejb</artifactId>
<version>${myproj-version}</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>javax.ejb</groupId>
<artifactId>ejb</artifactId>
</dependency>
<dependency>
<groupId>ojdbc</groupId>
<artifactId>ojdbc</artifactId>
</dependency>
</dependencies>
</project>
---------------------------------
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.company</groupId>
<artifactId>myproj-identite-ejb</artifactId>
<version>3.1-SNAPSHOT</version>
</parent>
<groupId>com.company</groupId>
<artifactId>myproj-identite-metier</artifactId>
<name>SNR IDENTITE METIER</name>
<version>2.0.1</version>
<packaging>ejb</packaging>
<dependencies>
<dependency>
<groupId>com.company</groupId>
<artifactId>myproj-maven-ejb</artifactId>
<version>${myproj-version}</version>
<type>pom</type>
</dependency>
</dependencies>
</project>
I don't know if it changes something, but we have a hierarchy that relates the two poms.
We have a strict Maven structure, where each directory declares all subdirectories as maven modules, and each subdirectory declares the parent as a maven parent.
And the common parent directory is part of this structure.
+---maven
| \---ejb
+---identite
| +---ejb
| | \---SNR_IDENTITE_METIER
Edited:
The answer given by reef seem correct. It is impossible to do with Maven, because our dependency are provided, and therefore not transitive :-(
We really have many problems with setup up Maven. So many little things just don't work. Today I found out that the site target cannot handle properties, that we are using for version numbers!
You can use pom dependencies to import dependencies into arbitrary projects.
A pom project can look similar to:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>persistence-deps</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>${hibernateVersion}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>${hibernateAnnotationsVersion}</version>
</dependency>
</dependencies>
</project>
And is imported as:
<dependency>
<groupId>com.example</groupId>
<artifactId>persistence-deps</artifactId>
<version>1.0</version>
<type>pom</type>
</dependency>
See Maven, the definitive guide - Grouping Dependencies for details.
Do your imported dependencies have a provided scope?
Indeed this scope is not transitive (see Maven Dependency Scopes).
This could be the reason of the non-replacement.
Related
I am using maven 3.2.1. for my project.
Maven builds artifacts and puts classes and dependencies into them which do not exist. For example, I used omnifaces as dependency in pom-file. I removed omnifaces from pom-file weeks ago but maven still builds it into the artifact. Another issue is, that maven builds an old and the new structure of the project. I removed a package and put all the classes into another package but maven still builds the old package next to the new one. That causes a ClassCastException at some points.
I'd like to know if anyone knows about that problem. Is there a way to configure maven to use only the current dependecies and project structure to build artifacts?
<?xml version="1.0" encoding="UTF-8"?>
http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
<parent>
<groupId>myProject</groupId>
<artifactId>webApplication</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>webApplication-war</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>myProject</groupId>
<artifactId>model-jar</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>myProject</groupId>
<artifactId>ordering-ejb</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>javax.faces-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>5.0</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0.2</version>
<scope>provided</scope>
</dependency>
</dependencies>
<name>${project.artifactId}-1.0-SNAPSHOT</name>
<!--<url>http://localhost</url> -->
<!--<build>-->
<!--<finalName>${project.artifactId}-1.0-SNAPSHOT</finalName>-->
<!--<pluginManagement>-->
<!--<plugins>-->
<!--<plugin>-->
<!--<groupId>org.apache.maven.plugins</groupId>-->
<!--<artifactId>maven-war-plugin</artifactId>-->
<!--<version>2.4</version>-->
<!--<configuration>-->
<!--<packagingExcludes>WEB-INF/lib/model-1.0-SNAPSHOT.jar</packagingExcludes>-->
<!--<webappDirectory>src/main/webapp</webappDirectory>-->
<!--<webXml>src/main/webapp/WEB-INF/web.xml</webXml>-->
<!--<outputDirectory>${env.M3_REPO}/ordentity/webApplication/1.0-SNAPSHOT</outputDirectory>-->
<!--</configuration>-->
<!--</plugin>-->
<!--</plugins>-->
<!--</pluginManagement>-->
<!--<plugins>-->
<!--<plugin>-->
<!--<groupId>org.apache.maven.plugins</groupId>-->
<!--<artifactId>maven-dependency-plugin</artifactId>-->
<!--<version>2.8</version>-->
<!--<executions>-->
<!--<execution>-->
<!--<phase>install</phase>-->
<!--<goals>-->
<!--<goal>copy</goal>-->
<!--</goals>-->
<!--<configuration>-->
<!--<overWriteIfNewer>true</overWriteIfNewer>-->
<!--<artifactItems>-->
<!--<artifactItem>-->
<!--<groupId>${project.groupId}</groupId>-->
<!--<artifactId>${project.artifactId}</artifactId>-->
<!--<version>${project.version}</version>-->
<!--<type>${project.packaging}</type>-->
<!--</artifactItem>-->
<!--</artifactItems>-->
<!--<outputDirectory>${env.JBOSS_HOME}/standalone/deployments</outputDirectory>-->
<!--</configuration>-->
<!--</execution>-->
<!--</executions>-->
<!--</plugin>-->
<!--</plugins>-->
<!--</build>-->
Maven puts classes and directories into that war file which do not exist in project structure. I had a package called bean, but deleted it weeks ago. It still appears in the war file. I am really disapointed...
SOLVED: I found a helpful thread (link below) where a comment gave me the solution.
I found a classes directory in my project under:
webApplication/war/src/main/webapp/WEB-INF
It contained all the old classes which were build into the artifact as well. Therefore maven also built all the dependencies into the artifact. After I deleted the classes directory all the ugly sideeffects disappeared.
Why might Maven ignore updated classes during install?
I've imported maven multimodule project and some transitive dependencies are not resolved. This same project builds in Jenkins/Eclipse/Console.
I've tried two import each project separately, and also to import only parent pom - both are not working.
I have following structure: Project A and Project B have common parent and both are defined as modules in this parent. Project A contains as dependency jackon-jar, Project B does not have it. Project A contains jackson-jar in default scope - jar is visible during compilation and tests are running. Now Project B imports Project A and also uses jackson-jar - and here is the problem - jackson-jar in not visible in Project B :( When I specify it explicitly in Project B all works fine, but it should come automatically as transitive dependency from Project A ......
Is this common problem? Is there workaround?
Here are POM examples:
Parent:
<project ....>
<modelVersion>4.0.0</modelVersion>
<version>1.0-SNAPSHOT</version>
<groupId>miklas.test</groupId>
<artifactId>my-parent</artifactId>
<packaging>pom</packaging>
<modules>
<module>my-project-a</module>
<module>my-project-b</module>
<module>my-project-c</module>
</modules>
</project>
Project-A
<project ....>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>miklas.test</groupId>
<artifactId>my-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>my-project-a</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jackson-provider</artifactId>
<version>2.3.4.Final</version>
</dependency>
</dependencies>
</project>
Project-B
<project >
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>miklas.test</groupId>
<artifactId>my-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>my-project-b</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>miklas.test</groupId>
<artifactId>my-project-a</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Below is also the screenshot from my real project - this would be Project B from simplified example above. On the left side we can see, that resteasy-jackoson-provider has 4 dependent jars, and on the right side there are only two. Both views are showing the same project:
Now the same screenshot from Project A
This appears to be a bug in IntelliJ 12. See http://youtrack.jetbrains.com/issue/IDEA-98425 and please vote for the issue if it's important to you.
Workaround mentioned at http://youtrack.jetbrains.com/issue/IDEA-98425 that worked for me and others is to go to "settings - Maven - Multiproject build fail policy". Set it to "Fail At End".
I have maven multiple-module project.
A: parent.
B: child1.
C: child2.
B will be packaged to get jar file and then c will use this jar file to compile the code.
In B, if I run mvn package, it will create b.jar (stays in B/target/jars not in B/target -for another purpose).
In C, I need to use that b.jar to compile the code.
Now, from A, when I run: mvn package. First, I am successful to create b.jar file for B.
But when it come to C's compilation phase, it looks like C doesn't recognize b.jar in the classpath (the compilation gets errors because C's code can not import the class file from B).
My question is: How can I solve this problem?
---------- Below are the pom files
A: pom.xml
<groupId>AAA</groupId>
<artifactId>A</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>C</module>
<module>B</module>
</modules>
B: pom.xml
<groupId>AAA</groupId>
<artifactId>B</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<parent>
<artifactId>A</artifactId>
<groupId>AAA</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
C: pom.xml
<parent>
<artifactId>A</artifactId>
<groupId>AAA</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<groupId>AAA</groupId>
<artifactId>C</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>AAA</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
....
Try ${project.version}
e.g.
<dependency>
<groupId>AAA</groupId>
<artifactId>B</artifactId>
<version>${project.version}</version>
</dependency>
Looks like it should work to me. But you might try mvn install instead of mvn package.
My question is how I can solve this problem?
Dependency resolution is done through the local repository so the canonical way to "solve" the problem is to run install from A so that modules will get installed in the local repository.
Now, regarding the following comment
But if I go with install then c war file will also be installed. That one is not accepted in my current project".
Sure, I'm not on your project, I don't know all constraints and rules. But if you decide to use Maven, this is a totally ridiculous policy (seriously, WTF?) and using a system scoped dependency is certainly not a good solution (more troubles later guaranteed). If this policy is real, better not use Maven in that case.
i have a solution: using the dependency with the scope=system
in C pom.xml
<dependency>
<groupId>AAA</groupId>
<artifactId>B</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>system</scope>
<systemPath>${basedir}\..\B\target\jars\b.jar</systemPath>
</dependency>
and in A pom.xml, put module B on the top like this
<modules>
<module>B</module>
<module>C</module>
</modules>
Doing mvn install only places the artifact into the local .m2 repository of the machine you're running the command on. How can that not be acceptable? I agree with Pascal. If you building A, there should be no reason that a the war is placed there.
On the other hand, if you're using Maven 2.2.x, take a look at the maven reactor plugin? This should help the crazy unacceptable cannot install C.war into your local .m2 repository policy for the current project.
If you have moduleA on your machine say at D:\moduleA and inside moduleA you have created another module say moduleB at D:\moduleA\moduleB , for you to use moduleB inside moduleA you create a dependency in the pom.xml file of moduleA like so:
<project xmlns="http://maven.apache.org/POM/4.0.0" ...>
...
<groupId>net.passioncloud</groupId>
<artifactId>moduleA</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>net.passioncloud</groupId>
<artifactId>moduleB</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependencies>
...
To compile the project so you can use it, from the module folder (moduleB) do:
.\mvnw clean install
Here are what I did to solve it:
From intelij , create new module from existing source.
Change the version of dependency B in A.pom same as version of B in B.pom
I have a multi module project consisting of several jar modules and a war module. When I do mvn package, the war is created but one dependency (javax.mail) is not included in the lib folder of the war.
The dependency is set to compile is the main pom. The war is not dependent from the mail.jar but a module.jar is.
When I do mvn dependency:tree, the three looks fine to me. Running in debug does not show me anything wrong either.
Anyone has an idea?
BB
Peter
Edit: in the master POM I have
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.1</version>
<scope>compile</scope>
</dependency>
as a managed dependency. The module jar has the dependency as follows:
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</dependency>
The war module has no dependency to javax.mail.
Edit2:
I do override the war plugin in the master pom like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<warName>${war.name}</warName>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
<manifestEntries>
<Implementation-Build>${buildNumber}</Implementation-Build>
</manifestEntries>
</archive>
</configuration>
</plugin>
Does your pom or master pom override the maven-war-plugin? It's possible to explicitly exclude artifacts from being put in the war:
http://maven.apache.org/plugins/maven-war-plugin/war-mojo.html#packagingExcludes
Also,
http://maven.apache.org/plugins/maven-war-plugin/war-mojo.html#warSourceExcludes
...I can't remember exactly the difference between the two excludes, and it doesn't really matter if you're not overriding the war plugin anyway.
If the javax.mail dependency is a dependency of one of your module, it should be included. However, if it is defined as an optional dependency, it will break the transitive dependency mechanism.
In others words, if in your module, you have that definition:
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.1</version>
<optional>true</optional>
</dependency>
If this is the case, simply remove this <optional>true</optional> statement.
We have a solution with numerous wars. Wars are similar in the sense they all use hibernate and spring. This means that we have a number of same jars inside each war. This is becoming a problem, because the size of the ear is starting to grow out of proportion.
I would like to use Maven to calculate dependencies and to place all jars common to multiple wars to the root of the EAR.
I tried organizing my project using j2ee archetype (maven-archetype-j2ee-simple), but all wars are still packaged with dependencies inside the WEB-INF/lib.
Is there a way to make Maven calculate common dependencies and place them to EAR, just as he is able to calculate all transitional dependencies when constructing a war or a jar?
As you've mentioned in a comment, it's maven's task to calculate every dependency. When you're creating an artifact, with every common dependency, then you'll also have to guess, which dependencies belong there.
It could also be possible, that you have to deploy one war, with it's dependencies on another machine without an ear, an when you set every war dependency to provided, then you're stuck again.
The only right way, to get skinny wars is from the examples:
http://maven.apache.org/plugins/maven-war-plugin/examples/skinny-wars.html
But, and now comes the interesting part, there is one big! shortcut (which completly takes away the mentioned pain), to tell maven, which dependencies your WARs have.
Go inside your EAR-Module an declare a second dependency on the WAR with type pom for every WAR dependency.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.foo</groupId>
<artifactId>skinny</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>ear</artifactId>
<packaging>ear</packaging>
<dependencies>
<dependency>
<groupId>com.foo</groupId>
<artifactId>war</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>war</type>
</dependency>
<dependency>
<groupId>com.foo</groupId>
<artifactId>war</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.8</version>
<configuration>
<skinnyWars>true</skinnyWars>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<modules>
<webModule>
<groupId>com.foo</groupId>
<artifactId>war</artifactId>
</webModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>
Now, every WAR will be packaged independently with it's own dependencies and the EAR will be packaged with skinny WARs and every dependency inside the lib folder
Update:
Keep in mind, that the ear/lib folder can't be used for every dependency jar in a strict Container like JBoss EAP 6. JSF Component libraries like tomahawk, primefaces, etc. have to reside in WEB-INF/lib folder.
A handy way to achieve this with the above described solution is to make an exclusion for the component library in the EARs pom.xml like this:
...
<dependencies>
<dependency>
<groupId>com.foo</groupId>
<artifactId>war</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>war</type>
</dependency>
<dependency>
<groupId>com.foo</groupId>
<artifactId>war</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
<exclusions>
<exclusion>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<exclusion>
</exclusions>
</dependency>
</dependencies>
...
Now every dependency of the WAR will be placed in ear/lib except the component library which will be placed in WEB-INF/lib inside the WAR
Create a new artifact named commons-jars and package it as pom. It should depend on all the common jars you are using - Spring, Hibernate, Log4j, etc.
Then, in each on your wars add it as dependency with scope "provided" (and don't forget to set the type as pom). You will be able to see it in your classpath but they won't be packaged into the war. This way you can also have war specific dependencies packaged into it, which the solution from skinny wars does not provide.
You can set the dependancies scope to "provided". This means they will be provided by some other module and will not be included in the final jar or war.
Perhaps the assembly plugin can help you when packaging up the final EAR and place common jars there.
http://maven.apache.org/plugins/maven-war-plugin/examples/skinny-wars.html