Env: Maven 2.2.1
I have two java projects under svn (projectA, projectB). My maven structure is as follows..
For projectA
pom.xml (contains ProjectA parent pom definitions)
module moduleA
module moduleB
For projectB
pom.xml (contains ProjectB parent pom definitions)
module moduleC
module moduleD
projectA/pom.xml and projectB/pom.xml contain common definitions like junit, selenium, compiler, eclipse plug-ins which are common to both projects. (e.g. given below)
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency
How should I create / organize a organization specific project pom which includes such common definitions, so that individual projects don't have to re-create / maintain one. Can someone provide some snippets or projects which have already done this before?
EDIT1:
company/pom.xml
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>company</artifactId>
<packaging>pom</packaging>
<name>parent</name>
<version>1.0.0</version>
<build>
<defaultGoal>install</defaultGoal>
</build>
<dependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
projectA/pom.xml
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.mycompany</groupId>
<artifactId>company</artifactId>
<version>1.0.0</version>
</parent>
<groupId>com.mycompany</groupId>
<artifactId>projectA</artifactId>
<packaging>pom</packaging>
<name>projectA</name>
<version>1.0.0</version>
<modules>
<module>moduleA</module>
<build>
<defaultGoal>install</defaultGoal>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
projectA/moduleA/pom.xml
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.mycompany</groupId>
<artifactId>projectA</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.mycompany</groupId>
<artifactId>moduleA</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>moduleA</name>
<build>
<finalName>moduleA</finalName>
<defaultGoal>install</defaultGoal>
</build>
<dependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</dependency>
</dependencies>
Throws the following error:
Project ID: com.mycompany:moduleA
POM Location: c:\temp\maven\projectA\moduleA\pom.xml
Validation Messages:
[0] 'dependencies.dependency.version' is missing for commons-lang:comm
ons-lang:jar
[1] 'dependencies.dependency.version' is missing for javax.servlet:ser
vlet-api:jar
I would seriously reconsider adding dependencies into a "super" POM, this unnecessarily couples the projects (but may hint that if the projects aren't disparate then they should be merged anyway).
I think the last comment by #lexicore is poignant too, to expand on the OOP analogy it also feels like "mixing levels of abstraction".
Alex Gitelman provides the correct answer, you need to use dependencyManagement as shown here Dependency Scope
Maven3 is supposed to be supporting POM fragments see How to use Maven 3 mixins? which I've long been waiting for.
We have an organisation Über POM but this just contains:
<organization>
<name>...</name>
<url>...</url>
</organization>
<developers>
<developer>
<id>...<id>
<name>...</name>
<email>...</email>
<roles>
<role>...</role>
</roles>
</developer>
<distributionManagement>
...
</distributionManagement>
<repositories>
<!-- your proxy repo here -->
</repositories>
These are things that change very rarely (if we change our repository/distribution-management then all projects must change, if a developer leaves or joins we can update the project POMs at any time convenient).
Dependencies belong specifically to the module under consideration, just because two independent project happen to share dependencies now doesn't mean they always will. I completely understand the annoyance of having to copy 'n' paste reams of XML for each project (compiler plugin, reporting plugins, junit etc), but differing levels of activity in each project will surely mean they diverge at some point.
WRT cascade builds in Continuous Integration, if project A demands a change in the super dependencies POM, then all you other projects will be forced to rebuild - maybe fine if you've only 2 projects but even then did you checkout and build both before committing the change?
If it's only dependencies that you need to reuse, create another project with packaging pom and specify dependencies there. Let's call it OrgDependencies Then include it as dependency in your projectA and projectB. It will transitively pull all dependencies from OrgDependencies project.
In your example, in projectA, instead of
<parent>
<groupId>com.mycompany</groupId>
<artifactId>company</artifactId>
<version>1.0.0</version>
</parent>
Try putting
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>company</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
And remove dependencies to commons-lang etc from modules.
Update.
While my previous solution with transitive dependencies should work, actually what you need
is <dependencyManagement> section in your company wide pom.xml
That's where you define versions.
Note: Anything in dependencyManagement section is not really a dependency but just a descriptor that allows to specify version and exclude transitive dependencies (if necessary) in case normal dependencies section specifies that dependency. So you can put as many items in dependencyManagement as you want, it will not make all descendants dependent on them.
I tested it and it works:
<?xml version="1.0" encoding="UTF-8"?>
<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>
<groupId>com.mycompany</groupId>
<artifactId>company</artifactId>
<packaging>pom</packaging>
<name>parent</name>
<version>1.0.0</version>
<build>
<defaultGoal>install</defaultGoal>
</build>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
In OS projects I am normally using 3+ levels of POMs:
"Company-wide POM" contains dev-wide definitions like distribution management, individual plugin versions etc. Very stable, normally has one-number version. Example: Sonatype OSS Parent.
"Project POM" contains project-wide definitions: Java compiler version, dependency management etc. Parent is company-wide POM. Example :JAXB2 Basics Project. Version is updated with each release.
"Module POMs" on different levels. List individual dependencies (versions of dependencies are inherited from the project POM), add "special" build steps. Example: JAXB Basics.
I saw a similar pattern an other OS projects (like Apache's) as well.
A few more comments:
You may also have the "department POM" or "product POM" depending on the company size and product organization.
Think of POM inheritance pretty much as of OOP inheritance. What would you put into which abstract class so that class hierarchy is stable but dynamic? For instance, it would not make sense to define versions of dependencies in the company-wide POM since versions change too often. On the contrary, defining distribution management in earch of the projects would hurt the DRY principle.
Related
I've noticed that fabric8.io for Kubernetes client has two dependencies ending with project and BOM.
The only difference I've noticed is that it first has a distributed version. Also according to apache guides, bom usually used as a parent for projects.
Are there any other uses/differences? Which dependency should I use with Spring Boot?
A BOM project can be either used as a parent for your Maven module or imported as a BOM dependency which allows you to import dependencies from that BOM. A really good article on this matter can be found here.
Why is a BOM important? Since you've added a Spring tag to your question, let's say you want to use a certain Spring version and component_1 works fine with component_2 as long as they have the same version. As a library developer, you would have a versioned BOM which contains component_1 and component_2 and in your project, you would need to import the BOM with the version you need and the components you need without the version, as it will be inherited from your imported BOM/parent. This is exactly what Spring does.
In case the link above won't work in the future, here is the basic workflow with BOMs.
// BOM project
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>baeldung</groupId>
<artifactId>Baeldung-BOM</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>BaelDung-BOM</name>
<description>parent pom</description>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>b</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>c</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
// importing the BOM in your project
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>baeldung</groupId>
<artifactId>Test</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Test</name>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>baeldung</groupId>
<artifactId>Baeldung-BOM</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<dependency>
<groupId>test</groupId>
<artifactId>b</artifactId>
<!-- version and scope omitted, inherited from the BOM, 1.0 and compile (you can override them here, but that defeats the purpose) -->
</dependency>
</dependencies>
</project>
Note that importing a BOM does NOT add all of its dependencies specified in the dependencyManagement section, unless you add them in the dependencies section of your project. It's like a product catalog, it shows you what the BOM is offering you.
Here is the Spring Boot 2.3.0 dependencies pom.xml, with dependencyManagement section to see how a real world BOM looks like (or just parent, if you want).
If you ever wanted to use Spring 6, Hibernate 5 and JUnit 5 & Assertion lib friends, assuming that all of them provide a BOM, you could include those 3 BOMs and every time you need to upgrade Spring version for your project, all you'd need is an update to the imported Spring BOM's version.
I am developing a spring boot project which has few modules. I have on entry point module which has main class, the other module dependencis i have added in entry point module pom.xml. When i give command mvn clean install it throws an error saying `
Failed to execute goal on project api: Could not resolve dependencies
for project com.nikesh:api:jar:1.0.0: The following artifacts could
not be resolved: com.nikesh:lib:jar:1.0.0, com.nikesh:repo:jar:1.0.0,
com.nikesh:entity:jar:1.0.0, com.nikesh:dto:jar:1.0.0,
com.nikesh:service:jar:1.0.0, com.nikesh:common:jar:1.0.0: Failure to
find com.nikesh:lib:jar:1.0.0 in https://repo.maven.apache.org/maven2
was cached in the local repository, resolution will not be reattempted
until the update interval of central has elapsed or updates are forced
-`
This is my pom.xml
<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>
<groupId>com.nikesh</groupId>
<artifactId>api</artifactId>
<version>1.0.0</version>
<description>api module</description>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
<start-class>com.nikesh.api.MultiModuleApp</start-class>
</properties>
<dependencies>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>lib</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>repo</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>entity</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>dto</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>service</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.nikesh</groupId>
<artifactId>common</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Please help me out resolving this issue.
You need to make sure that all sub modules are built in proper order before the main module build.
Guide to Working with Multiple Modules
The Reactor
The mechanism in Maven that handles multi-module projects is referred to as the reactor. This part of the Maven core does the following:
Collects all the available modules to build
Sorts the projects into the correct build order
Builds the selected projects in order
Because modules within a multi-module build can depend on each other, it is important that The reactor sorts all the projects in a way that guarantees any project is built before it is required.
The following relationships are honoured when sorting projects:
a project dependency on another module in the build
a plugin declaration where the plugin is another modules in the build
a plugin dependency on another module in the build
a build extension declaration on another module in the build
the order declared in the element (if no other rule
applies)
Note that only "instantiated" references are used - dependencyManagement and pluginManagement elements will not cause a change to the reactor sort order
for more info. You can refer this link for a sample multi module maven project.
The setup is the following:
I am using Maven and I would like to use as a parent POM some artifact that has a number of dependencies in the dependencyManagement section. But I would also like to have a dependencyManagement section in my POM as well, because my artifact will be the parent pom of some other submodules.
Example:
<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.mycompany</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0</version>
</parent>
<groupId>com.mycompany</groupId>
<artifactId>my-artifact</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>sub-module-01</module>
<module>sub-module-02</module>
</modules>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>1.2.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
Let's say that both these parent poms define a version for some dependency (let's say the version for jackson), but each has a different version.
When I define that dependency in one of my submodules, which version will be resolved?
I am not sure how to search for this situation on google.
Typically, Maven resolves using the closest version declaration.
My best guess would be that the one from the import in the dependency management section would be preferred, since it is closer to the location where the dependency is used:
dependency -> imported dependency in parent pom = 2 hops
dependency -> parent pom -> dependencyManagement in parent pom = 3 hops
But really, just try it ;)
Let us according to the different case:
Firstly, The simplest case is NO pom dependency import tag in any pom's dependencyManagement section, everything is clear and the dependency declaration will make a really affect with the closest dependency and properties such as exclude will inherit from parent pom and the exclusion with be merged .
Secondly, if the there is a direct declaration in any of each pom's DM section, this declaration will be used for this jar . if not, the closest import dependency declaration if exists will be used to the jar/pom's version. Here the closest mean is the distance to the pom and super pom or ,super super pom. But Not The transitivity distance!
I think it will be the version from import. Because the import
DependencyManagement Just do a replace of dependencies. so Parent dependency will be overwritten by the import dependency. I do not verify this. Just a guess.
I Just do an experiment to check this situation.
Firstly. I define a dependency of netty-handler.
In my maven repository netty-handler version contain:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>4.1.8.Final</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>4.1.9.Final</version>
</dependency>
I create one test_parent pom project with this content in pom.xml
<groupId>dm-test</groupId>
<artifactId>parent-test-pom</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<!-- define a dependency in super parent pom with version 4.1.8.Final -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>4.1.8.Final</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
and then create a pom project for import:
<groupId>dm-test</groupId>
<artifactId>import-pom</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<!-- define a dependency in super parent pom with version 4.1.9.Final -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
<version>4.1.9.Final</version>
</dependency>
</dependencies>
</dependencyManagement>
Finally, I create a war project with the parent_pom and import_pom, like this:
<groupId>dm-test</groupId>
<artifactId>test-project</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<parent>
<groupId>dm-test</groupId>
<artifactId>parent-test-pom</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>dm-test</groupId>
<artifactId>import-pom</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-handler</artifactId>
</dependency>
</dependencies>
finally, We can see the dependency jar version is 4.1.8.Final
So, My guess is wrong. sorry about that.
I am working with Maven and creating my own modules.
I have the 01CentralDomain project
with the simple com.manuel.jordan.domain package with three #Entities
one of them is for example Product
Part of its pom.xml is:
<modelVersion>4.0.0</modelVersion>
<groupId>com.manuel.jordan.centraldomain</groupId>
<artifactId>central-domain</artifactId>
<packaging>jar</packaging>
<name>01CentralDomain</name>
<version>1.0.1</version>
<url>https://github.com/manueljordan/</url>
I have the other 02CentralDomain project
again with the same simple com.manuel.jordan.domain package with two new #Entities
one of them is for example User
Consider this how an extension of the first project
Part of its pom.xml is:
<modelVersion>4.0.0</modelVersion>
<groupId>com.manuel.jordan.centraldomain</groupId>
<artifactId>central-domain</artifactId>
<packaging>jar</packaging>
<name>02CentralDomain</name>
<version>1.0.2</version>
<url>https://github.com/manueljordan/</url>
...
<dependencies>
<dependency>
<groupId>com.manuel.jordan.centraldomain</groupId>
<artifactId>central-domain</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
Therefore practically my second project has access to the first project, it about to be able to reference the three entities, like Product, we can assume my domain package now has a total of 5 entities, 3 from the first + 2 for the second.
Now I have a third project (02CentralExecution)
Part of its pom.xml is:
<modelVersion>4.0.0</modelVersion>
<groupId>com.manuel.jordan.centralexecution</groupId>
<artifactId>central-execution</artifactId>
<packaging>jar</packaging>
<name>02CentralExecution</name>
<version>1.0.2</version>
<url>https://github.com/manueljordan/</url>
...
<dependencies>
<dependency>
<groupId>com.manuel.jordan.centraldomain</groupId>
<artifactId>central-domain</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
Theoretically the third project has access to the second project source code and therefore for the first project source code too.
It does not work, the third project only can access the second project source code.
I can use the User class but not the Product class.
Even if I declare both
<dependencies>
<dependency>
<groupId>com.manuel.jordan.centraldomain</groupId>
<artifactId>central-domain</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>com.manuel.jordan.centraldomain</groupId>
<artifactId>central-domain</artifactId>
<version>1.0.2</version>
</dependency>
</dependencies>
It does not work.
How I can get working this?
You should use different artifactId's. Maven considers (roughly) groupId:artifactId as the "primary key" for your module, and if you depend on two different versions of module XXX:YYY then it will just include the "most appropiate one", which is usually the one with the higher version.
Furthermore, it turns out that two different modules is what you actually want, as you do not really have two versions of the same module, but a module X that depends on a different one Y, and a third module Z that depends on both X and Y (direct dependency on X, and indirect dependency on Y through X).
So if you have:
01CentralDomain pom.xml:
<modelVersion>4.0.0</modelVersion>
<groupId>com.manuel.jordan.centraldomain</groupId>
<artifactId>central-domain-01</artifactId><!-- note renamed artifactId -->
<packaging>jar</packaging>
<name>01CentralDomain</name>
<version>1.0.1</version>
<url>https://github.com/manueljordan/</url>
02CentralDomain pom.xml:
<modelVersion>4.0.0</modelVersion>
<groupId>com.manuel.jordan.centraldomain</groupId>
<artifactId>central-domain-02</artifactId><!-- note renamed artifactId -->
<packaging>jar</packaging>
<name>02CentralExecution</name>
<version>1.0.1</version><!-- Not a higher version, but a different module!!! -->
<url>https://github.com/manueljordan/</url>
...
<dependencies>
<dependency>
<groupId>com.manuel.jordan.centraldomain</groupId>
<artifactId>central-domain-01</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
02CentralExecution pom.xml:
<modelVersion>4.0.0</modelVersion>
<groupId>com.manuel.jordan.centralexecution</groupId>
<artifactId>central-execution</artifactId>
<packaging>jar</packaging>
<name>02CentralExecution</name>
<version>1.0.1</version><!-- Version 1.0.2 makes no sense now, just use 1.0.1 -->
<url>https://github.com/manueljordan/</url>
...
<dependencies>
<dependency>
<groupId>com.manuel.jordan.centraldomain</groupId>
<artifactId>central-domain-02</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
Then everything should "just work"
I read some useful posts here on SO about previous maven questions, I'm currently very interested in learning maven(cause I like it and because my boss requires me to). I'm currently reading [this][1] book and I'm working my way trough examples. Its a straightforward book but its has some errors inside(trivial ones), yet for a newbie like me can be hard to spot, once spotted it can be easily fixed. Is there any other book better to understand maven from top to bottom?
Second part of the question is relating an example in this book, maybe a simple explanations would resolve my doubts.
Here is the thing, I made a simple-weather project in java which retrieves the weather conditions from yahoo weather server, given the particular zip code it returns weather information.
Then I made an 'simple-webapp'(with maven as well as the one above I forgot to mention that), which is basicaly a web project which has some default servlet already there with maven and it does nothing.
And I have some parent-project I wanna merge those two projects into one, so I made a pom.xml which has 2 modules , 1 to retrieve info(java project) and other to display it on the web (web app).
I made everything work at the end, but here is the odd thing .. if I make webapp display any string "name" lets say then build it independently, it does exactly print that string. But when I put the webapp in the "parent-project" and change this string to "name1" and build it as sa partent-project sub module.. nothing changes ..
So I go back to the point, because simple-webapp is dependent on simple-weather I can't build it anymore on its own, so now if I wanna make some changes to the webapp.. modify the webapp outside the "parent-project" build it there then paste it back to the parent-project and then the changes will apply, why is that, why can't I directly change the servlet content/or add another one in the webapp as the part of the "parent-project"?
Thank you.. I know its a long and boring question, but I'm just trying to learn things and there is no better place to ask than here :D
EDIT - HERE ARE POM FILES FOR EACH PROJECT :
1. simple-parent pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.sonatype.mavenbook.multi</groupId>
<artifactId>simple-parent</artifactId>
<packaging>pom</packaging>
<version>1.0</version>
<name>Multi Chapter Simple Parent Project</name>
<modules>
<module>simple-weather</module>
<module>simple-webapp</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
2. simple-weather pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonatype.mavenbook.multi</groupId>
<artifactId>simple-parent</artifactId>
<version>1.0</version>
</parent>
<artifactId>simple-weather</artifactId>
<packaging>jar</packaging>
<name>Multi Chapter Simple Weather API</name>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
3. simple-webapp pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.sonatype.mavenbook.multi</groupId>
<artifactId>simple-parent</artifactId>
<version>1.0</version>
</parent>
<artifactId>simple-webapp</artifactId>
<packaging>war</packaging>
<name>simple-webapp Maven Webapp</name>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.sonatype.mavenbook.multi</groupId>
<artifactId>simple-weather</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<build>
<finalName>simple-webapp</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I am not sure to completely understand your question. However, let's explain some principles in Maven.
So you have such a structure:
parent
+ simple-weather
+ simple-webapp
On a Maven point of view, we have 3 projects here:
parent, which is a pom project (i.e. its packaging attribute is set to pom)
simple-weather, which is a jar project and has parent as parent.
simple-webapp, which is a war project, has parent as parent and simple-weather as dependency.
The parent projects uses two concepts in Maven:
The inheritance, which say that all of his children (simple-weather and simple-webapp) will inherit all of his properties (this concept is almost the same thing as the extends in Java).
The aggregation, which is defined by the definition of <modules>. Aggregation means that every command that will be run on the project will also be run on each module.
What happen if I build (using mvn clean install) on the parent directory?
Maven will "compile" the parent project and then install the pom.xml in the local repository.
Maven will compile the simple-weather project, but as it has a parent, Maven will look the parent pom.xml file into the local repository. Once the JAR is created, it is installed in the local repository.
Maven will finally compile the simple-webapp project. Maven will do the same thing for the parent pom.xml, but also for the simple-weather project.
The situtation explained in the 3rd point is important: If you want to build the simple-webapp project, Maven will always try to find all of his dependencies - including simple-weather - from the local (or distant) repository.
That's why if you build only the simple-webapp without building and installing simple-weather, Maven will not find the latter project, or will find an older version.
So to summarize, when you work on multi-modules project with Maven, try to always run the build and install commands from the root (or parent) directory.
I hope that this explanation is clear enough and help you to understand what happen in your case. Do not hesitate to ask more information...