Relationship between .iml file and pom.xml file - maven

Each time I create a Maven project, there is a .iml file along with a pom.xml file.
What exactly is their relationship?

The pom.xml is used by maven to resolve your project's dependencies, which plugins to execute and a lot of other things. From the maven website:
A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details used by Maven to build the project.
The .iml file on the other hand is part of IntelliJ's own project structure. The short version is that it declares the libraries (e.g. jars) that are visible only to the module, and not the rest of the project or other projects. It's an xml file containing a library entry for each artifact declared in your pom.xml, along with its scope (e.g. TEST or COMPILE). For example:
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="COMPILE" name="Maven: com.google.guava:guava:18.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
</component>
</module>
I assume IntelliJ keeps its own file format so it can read the project faster, regardless of which build system the project is using (e.g. maven vs. gradle).

IntelliJ idea doesn't understand the maven project model (POM.xml) itself. When creating or importing maven project in idea. It also creating its own project structure, maven dependencies , module details etc etc.. basically required project metadata in the format it can understand and use it internally for it actions. These metadata stored in .iml file and .idea project directory.
Main advantage of keeping it's own structure would provide capacity to run faster and manage project efficiently. I hope this give some explanation on the relationship between these two files.
Sample pom.xml
<?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>test</groupId>
<artifactId>test</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>2.5.2</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jmock</groupId>
<artifactId>jmock</artifactId>
<version>${jmock.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.jmock</groupId>
<artifactId>jmock-junit4</artifactId>
<version>${jmock.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junitperf</groupId>
<artifactId>junitperf</artifactId>
<version>1.8</version>
</dependency>
</dependencies>
<properties>
<jmock.version>2.5.1</jmock.version>
<junit.version>4.6</junit.version>
<log4j.version>1.2.14</log4j.version>
<org.slf4j.version>1.5.2</org.slf4j.version>
</properties>
</project>
Relavent IDEA .iml file
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: log4j:log4j:1.2.14" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-log4j12:1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.5.2" level="project" />
<orderEntry type="library" name="Maven: org.easymock:easymock:2.5.2" level="project" />
<orderEntry type="library" name="Maven: org.jmock:jmock:2.5.1" level="project" />
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-core:1.1" level="project" />
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-library:1.1" level="project" />
<orderEntry type="library" name="Maven: org.jmock:jmock-junit4:2.5.1" level="project" />
<orderEntry type="library" name="Maven: junit:junit-dep:4.4" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.6" level="project" />
<orderEntry type="library" name="Maven: junitperf:junitperf:1.8" level="project" />
</component>
</module>

The .iml file is generated using the pom.xml.
When you open a project in IntelliJ for the first time, IntelliJ downloads all the required dependencies using the pom.xml as reference. There is a one-way sync between the pom.xml and the .iml file.
When you try to run the project, the .iml file and .idea directory are created. These files and directories allow IntelliJ to run faster.

Related

Cannot get rid of nuget warning NU5128 about missing dependency group

[Env: nuget.exe 5.9.1.11, VS Pro 2019 16.9.6, W10 x64 1909]
I am having trouble configuring the dependencies section of my .nuspec file so nuget generates a package which correctly contains the Dependency for .NET Framework 4.7.2. I consistently get the warning
WARNING: NU5128: Some target frameworks declared in the dependencies group of the nuspec and the
lib/ref folder do not have exact matches in the other location. Consult the list of actions below:
- Add a dependency group for .NETFramework4.7.2 to the nuspec
when I run the nuget pack command. In the .nupkg archive, there are lib\net472\MyLib.dll and lib\net472\MyLib.xml files generated by nuget. (I am running nuget in the VS project directory which contains a .csproj file and my .nuspec file.) Here are the different configurations of the dependencies section that I have tried (my library does have a dependency on the MathNet.Numerics NuGet package):
<dependencies>
<group targetFramework=".NETFramework4.7.2" />
</dependencies>
&
<dependencies>
<group targetFramework=".NETFramework4.7.2" />
<group>
<dependency id="MathNet.Numerics" version="4.15.0" />
</group>
</dependencies>
&
<dependencies>
<group>
<dependency id="MathNet.Numerics" version="4.15.0" />
</group>
<group targetFramework=".NETFramework4.7.2" />
</dependencies>
&
<dependencies>
<group>
<dependency id="MathNet.Numerics" version="4.15.0" />
</group>
<group targetFramework="net472" />
</dependencies>
&
<dependencies>
<group targetFramework="net472" />
<group>
<dependency id="MathNet.Numerics" version="4.15.0" />
</group>
</dependencies>
&
<dependencies>
<group targetFramework="net472" />
</dependencies>
&
<dependencies>
<group targetFramework="net472">
<dependency id="MathNet.Numerics" version="4.15.0" />
</group>
</dependencies>
&
<dependencies>
<group targetFramework=".NETFramework4.7.2">
<dependency id="MathNet.Numerics" version="4.15.0" />
</group>
</dependencies>
& no <dependencies></dependencies> section as well.

Wildfly 14 - explicit dependencies

I have two EAR (ear01-0.0.1-SNAPSHOT.ear, ear02-0.0.1-SNAPSHOT.ear) applications and both of them are useing a common library (common-0.0.1-SNAPSHOT.jar). I decided to move out that common part and add it as module to a Wildfly 14 but even with a deployment descritor I get exception during the EAR deployment:
java.lang.NoClassDefFoundError: Failed to link ki/wildfly_deps/ejbs01/EchoBean01
I used this CLI to add the new module:
module add --name=ki.wildfly_deps.common --resources=common-0.0.1-SNAPSHOT.jar
and the JAR now is in
$JBOSS_HOME/modules/ki/wildfly_deps/common/main
1. QUESTION
This JAR shouldn't be in folder
$JBOSS_HOME/modules/system/layers/base/ki/wildfly_deps/common/main
beside the other modules?
After adding the module, the module.xml look like this:
<?xml version='1.0' encoding='UTF-8'?>
<module xmlns="urn:jboss:module:1.1" name="ki.wildfly_deps.common">
<resources>
<resource-root path="common-0.0.1-SNAPSHOT.jar"/>
</resources>
</module>
The jboss-deployment-structure.xml from each EAR declares a dependency on the above common library:
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<deployment>
<dependencies>
<module name="ki.wildfly_deps.common" />
</dependencies>
</deployment>
2. QUESTION
Should I specify the package what must be imported from the common module?
<jboss-deployment-structure
xmlns="urn:jboss:deployment-structure:1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<deployment>
<dependencies>
<module name="ki.wildfly_deps.common" //>
<imports>
<include path="META-INF**" />
<include path="ki.wildfly_deps.common**" />
</imports>
</module>
</dependencies>
</deployment>

Spring Boot uber jar packaging classes to root instead of BOOT-INF/classes

Hi Spring Boot Experts -
I am trying to create a spring boot uber jar that needs to be deployed to a apache storm cluster. But, the catch is that Storm is expecting all the class files in the root of the jar while the packaged app files are under "BOOT-INF/classes" when packaged using the "spring-boot-maven-plugin".
Is there a way I can have my app classes packaged directly under the root instead of "BOOT-INF/classes"?
I tried using the "maven-assembly-plugin" with the "spring-boot-maven-plugin" as shown below which creates the Uber jar with all the class files from the dependency jars packaged at the root of the uber jar, but the app classes are still at BOOT-INF/classes.
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.apache.storm</groupId>
<artifactId>storm-core</artifactId>
</exclude>
</excludes>
<requiresUnpack>
<dependency>
<groupId>com.myorg</groupId>
<artifactId>my-app-artifact</artifactId> <!-- This does not help! :( -->
</dependency>
</requiresUnpack>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
So, for my future self or for anyone who is trying to find an answer for a similar question. Here are the different things that I realized during my research for this -
Storm wants an executable java jar file
Spring Boot provides a custom jar packaging. While it confirms with java jar packaging, Spring Boot loads the classes from the BOOT-INF/classes
So, to make a Spring Boot jar work on the storm cluster while behaving as Spring Boot - we would need to create a copy of all the classes from BOOT-INF/classes to the root of the jar file.
Is this possible? and the answer is yes.
Using the approach describe here, I was able to create a Spring Boot jar with the BOOT-INF/classes copied to the root of the Spring Boot jar. This approach requires ant build.xml, ivy settings and an ivy.xml as shown below. (disclaimer: config tested only till packaging on not on the storm cluster)
Since we are able to create a Spring Boot Jar hacked with classes at the root -
Should we do it? NO.
Here are the reasons -
Spring strongly advises not taking this approach to not end up with unwanted class overwrite and class versioning issues for classes with same names across jar files and with different versions.
Spring Boot Jar packaging is not a format intended for using as a dependency jar. Read the first line here. Hence for dependency use cases, you need to stick with your plain old java modules. Spring Boot is for more of standalone executables or for deployment on containers like tomcat.
Good luck!
build.xml
<project
xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:spring-boot="antlib:org.springframework.boot.ant"
name="spring-boot-sample-ant"
default="build">
<description>
Sample ANT build script for a Spring Boot executable JAR project. Uses ivy for
dependency management and spring-boot-antlib for additional tasks. Run with
'$ ant -lib ivy-2.2.jar spring-boot-antlib.jar' (substitute the location of your
actual jars). Run with '$ java -jar target/*.jar'.
</description>
<property name="spring-boot.version" value="1.4.2.RELEASE" />
<property name="lib.dir" location="${basedir}/target/lib" />
<property name="start-class" value="com.my.main.class" />
<target name="resolve" description="--> retrieve dependencies with ivy">
<ivy:retrieve pattern="${lib.dir}/[conf]/[artifact]-[type]-[revision].[ext]" />
</target>
<target name="classpaths" depends="resolve">
<path id="compile.classpath">
<fileset dir="${lib.dir}/compile" includes="*.jar" />
</path>
</target>
<target name="init" depends="classpaths">
<mkdir dir="target/classes" />
</target>
<target name="compile" depends="init" description="compile">
<javac srcdir="src/main/java" destdir="target/classes" classpathref="compile.classpath" />
</target>
<target name="clean" description="cleans all created files/dirs">
<delete dir="target" />
</target>
<target name="build" depends="compile">
<spring-boot:exejar destfile="target/${ant.project.name}-${spring-boot.version}.jar" classes="target/classes">
<spring-boot:lib>
<fileset dir="${lib.dir}/runtime" />
</spring-boot:lib>
</spring-boot:exejar>
</target>
<target name="unjar_dependencies" depends="compile">
<unzip dest="target/classes">
<fileset dir="${lib.dir}/compile">
<include name="my-app-common-0.1-SNAPSHOT.jar" />
</fileset>
</unzip>
</target>
<!-- Manual equivalent of the build target -->
<target name="manual" depends="compile, unjar_dependencies">
<jar destfile="target/manual/${ant.project.name}-${spring-boot.version}.jar" compress="false">
<mappedresources>
<fileset dir="target/classes" />
<globmapper from="*" to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources> <!-- **** this mapped resources block does what I was looking for **** -->
<fileset dir="target/classes" />
<globmapper from="*" to="/*"/>
</mappedresources>
<mappedresources>
<fileset dir="src/main/resources" erroronmissingdir="false"/>
<globmapper from="*" to="BOOT-INF/classes/*"/>
</mappedresources>
<mappedresources>
<fileset dir="${lib.dir}/runtime" />
<globmapper from="*" to="BOOT-INF/lib/*"/>
</mappedresources>
<zipfileset src="${lib.dir}/loader/spring-boot-loader-jar-${spring-boot.version}.jar" />
<manifest>
<attribute name="Main-Class" value="org.springframework.boot.loader.JarLauncher" />
<attribute name="Start-Class" value="${start-class}" />
</manifest>
</jar>
</target>
</project>
ivysettings.xml
<ivysettings>
<settings defaultResolver="chain" />
<resolvers>
<chain name="chain" returnFirst="true">
<!-- NOTE: You should declare only repositories that you need here -->
<filesystem name="local" local="true" m2compatible="true">
<artifact pattern="${user.home}/.m2/repository/[organisation]/[module]/[revision]/[module]-[revision].[ext]" />
<ivy pattern="${user.home}/.m2/repository/[organisation]/[module]/[revision]/[module]-[revision].pom" />
</filesystem>
<ibiblio name="ibiblio" m2compatible="true" />
<ibiblio name="spring-milestones" m2compatible="true" root="http://repo.spring.io/release" />
<ibiblio name="spring-milestones" m2compatible="true" root="http://repo.spring.io/milestone" />
<ibiblio name="spring-snapshots" m2compatible="true" root="http://repo.spring.io/snapshot" />
</chain>
</resolvers>
</ivysettings>
ivy.xml
<ivy-module version="2.0">
<info organisation="org.springframework.boot" module="spring-boot-sample-ant" />
<configurations>
<conf name="compile" description="everything needed to compile this module" />
<conf name="runtime" extends="compile" description="everything needed to run this module" />
<conf name="loader" description="Spring Boot loader used when manually building an executable archive" />
</configurations>
<dependencies>
<dependency org="org.springframework.boot" name="spring-boot-starter" rev="${spring-boot.version}" conf="compile">
<exclude org="ch.qos.logback" name="logback-classic"/>
</dependency>
<dependency org="org.springframework.boot" name="spring-boot-loader" rev="${spring-boot.version}" conf="loader->default" />
<dependency org="org.apache.storm" name="storm-core" rev="1.0.2">
<exclude org="org.apache.logging.log4j" name="log4j-slf4j-impl"/>
<exclude org="org.apache.logging.log4j" name="log4j-core"/>
</dependency>
<dependency org="com.mycompany" name="app-common" rev="0.1-SNAPSHOT"/>
<dependency org="org.apache.storm" name="storm-kafka" rev="1.0.2"/>
<dependency org="org.apache.kafka" name="kafka_2.10" rev="0.10.1.0"/>
<dependency org="org.apache.kafka" name="kafka_2.10" rev="0.10.1.0"/>
<dependency org="org.apache.httpcomponents" name="httpcomponents-client" rev="4.5.2"/>
<dependency org="org.eclipse.paho" name="org.eclipse.paho.client.mqttv3" rev="1.1.0"/>
<dependency org="com.amazonaws" name="aws-java-sdk-s3" rev="1.11.53"/>
<dependency org="com.jcraft" name="jsch" rev="0.1.54"/>
<dependency org="io.netty" name="netty-handler" rev="3.7.0.Final"/>
</dependencies>
</ivy-module>
Is there a way I can have my app classes packaged directly under the root instead of "BOOT-INF/classes"?
Yes, you just need to use Spring Boot 1.3. Back to maven... in your pom.xml if you declare your parent like this:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
</parent>
then your classes (and other files) will be placed at the root level. This is the "old way" for spring boot.
In version 1.4 they changed the spring boot jar structure to use the BOOT-INF directory. So, if you use <version>1.4.1.RELEASE</version> for example, then your classes will be under BOOT-INF/classes. An undesirable side effect is that your configuration files (e.g., application.properties, application-myprofile.properties, etc.) will also be under BOOT-INF/classes, even though they are not Java classes.

Logback not working with JBoss EAP 6.1

I have a maven web application in which I am using logback and JBoss EAP 6.1 as server. The problem is that when I deploy it on server, my logback.xml is ignored and logback's default configuration is used which prints on console instead of my log file. Logging works fine if I deploy my application on tomcat.
I have put logback.xml in src/main/resources.
Found similar question at - Logging Configuration in Logback + SL4J + JBoss EAP 6.0
and
Logback and Jboss 7 - don't work together?
but no use...
Forgot to share the solution earlier..here it is -
We need to add following lines in jboss-deployment-structure.xml
<exclusions>
<module name="org.apache.commons.logging" />
<module name="org.slf4j" />
<module name="org.slf4j.ext" />
<module name="org.slf4j.impl" />
<module name="org.apache.log4j" />
</exclusions>
So the entire file looks like -
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<!-- Exclusions allow you to prevent the server from automatically adding
some dependencies -->
<exclusions>
<module name="org.apache.commons.logging" />
<module name="org.slf4j" />
<module name="org.slf4j.ext" />
<module name="org.slf4j.impl" />
<module name="org.apache.log4j" />
</exclusions>
</deployment>
</jboss-deployment-structure>
If you have a maven project, you can put this file at -
<project>/webapp/META-INF/jboss-deployment-structure.xml
Now logging will work fine.
First, thanks to #popeye
Climbing on to what #popeye has well defined, here are my 2 cents
Location of 'jboss-deployment-structure.xml' : src/main/webapp/WEB-INF/jboss-deployment-structure.xml
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<!-- Hey Server please don't add these dependencies. I don't need them.
I have mine in my application dependencies -->
<exclusions>
<module name="org.apache.commons.logging" />
<module name="org.slf4j" />
<module name="org.slf4j.ext" />
<module name="org.slf4j.impl" />
<module name="org.apache.log4j" />
</exclusions>
<dependencies>
<module name="com.oracle" />
<module name="org.jboss.ironjacamar.jdbcadapters" slot="main" />
</dependencies>
</deployment>
</jboss-deployment-structure>
Now, logback.xml is in action. yo!
why is this needed - <module name="com.oracle" /> ?
This is the name of module of driver you mentioned in JBOSS standalone.xml
<subsystem xmlns="urn:jboss:domain:datasources:1.1">
<datasources>
<datasource><!-- your configurations --></datasource>
<drivers>
<driver name="ojdbc6-11.2.0.4" module="com.oracle">
<xa-datasource-class>oracle.jdbc.OracleDriver</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
Note that this is for JBOSS server to Database communication.
[Even if you have ojdbc6-11.2.0.4.jar in your project/lib you need this configuration ]
How did you come up with this name 'com.oracle'? Is that a standard ?
No . This is the struture of folder I created on server
Look at this SO post here - Xmlparserv2 error while application deployed in jboss, Installing Oracle ojdbc module in JBoss for Java web application 'How to create a Oracle module in JBOSS'
Also note not to confuse this one with the dependency that you might add in your project pom.xml.
ie: this one
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.4</version>
<scope>provided</scope> <!-- to exclude from WEB-INF/lib -->
</dependency>
The above project dependency is needed for you to write the Java code, get it compiled,
and also during runtime, for your code to communicate to the driver.
why is this needed - <module name="org.jboss.ironjacamar.jdbcadapters" slot="main" /> ?
Otherwise you might get an error to get a jndi datasource set on JBoss in your Spring application.
So that's a dependency. Don't forget to add the jar as well in your pom.xml
<dependency>
<groupId>org.jboss.ironjacamar</groupId>
<artifactId>ironjacamar-jdbc</artifactId>
</dependency>

Resolving transitive dependences in Ivy from the Maven repository

I'm using ant-ivy to resolve dependencies from the maven repository. And i'm using the same ant-ivy to publish new artifacts into that repository, so i'm generating .pom file in ant too.
The generated .pom file is very simple and looks like this(PROJECT_A):
<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>COMPANY</groupId>
<artifactId>PROJECT_A</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.7</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
So it just has some dependencies in compile scope and some in test scope. Now my ivy.xml file for that project(and the source of that .pom above) looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven">
<info organisation="COMPANY" module="PROJECT_A" revision="1.0" />
<configurations defaultconf="default,sources" defaultconfmapping="sources->sources;%->default">
<conf name="test" visibility="private"/>
<conf name="default" description="list of dependencies"/>
<conf name="sources" description="source files for all dependencies" />
</configurations>
<publications>
<artifact type="jar" conf="default" />
<artifact type="sources" ext="jar" m:classifier="sources" conf="sources" />
<artifact type="pom" ext="pom" conf="default" />
</publications>
<dependencies>
<!-- General -->
<dependency org="commons-collections" name="commons-collections" rev="3.2.1" transitive="false"/>
<dependency org="commons-configuration" name="commons-configuration" rev="1.7" transitive="false"/>
<dependency org="commons-lang" name="commons-lang" rev="2.6" transitive="false"/>
<dependency org="log4j" name="log4j" rev="1.2.16" transitive="false"/>
<!-- dependencies for junit testing -->
<dependency org="junit" name="junit" rev="latest.release" conf="test" />
<dependency org="org.mockito" name="mockito-all" rev="latest.release" conf="test" /> <!-- it's useful by itself, plus it has hamcrest in it which junit needs -->
</dependencies>
</ivy-module>
Again, very simple - 3 configurations, the default has all the dependencies, test is for testing dependencies and sources to publish sources.
And it all works quite well, apart of one thing - i'm declaring my dependencies as not transitive in the PROJECT_A, then when i'm pushing the pom to the repository those dependencies are listed there in the scope compile. Therefore the other project(PROJECT_B) which will have PROJECT_A as a dependency, will have all the transitive dependencies of the PROJECT_A as well, and i don't want that at all i just want those which are explicitly declared in the ivy.xml of PROJECT_A.
I've tried playing with the scopes and mappings, but it seems i really don't understand what i'm doing there as it doesn't make any sense. I would like to modify that scheme somehow so that when i include the PROJECT_A as a dependency, it'll only include the actual dependencies of the PROJECT_A declared in the ivy.xml, so transitive flag will be taken into account.
One more thing, i'm creating that .pom file like that:
<ivy:makepom ivyfile="generated-ivy.xml" pomfile="${ant.project.name}.pom" templatefile="${template.pom}" artifactPackaging="jar">
<mapping conf="default" scope="compile" />
<mapping conf="test" scope="test" />
</ivy:makepom>
Mark the dependency as <optional> to make it non-transitive.
Dirty hack, but that's maven.

Resources