Recommended solution for splitting up Maven projects? - maven-2

What is the best way to split up a large enterprise project in Maven?
It's easy enough to understand how to partition things vertically like this...
You have a DAO project
The DAO project is a dependency of
the Service project
The Service project is a dependency
of the web project.
Does anybody have input on best practices in partitioning/splitting up really large projects in Maven.m

Some things that have helped me
Use multi-module projects for projects that are related and only projects that are related. An EJB that exists only in a single EAR is a candidate for this. A bo layer that is used by an EJB and a client app is not.
One Artifact per pom, one deployable per multi-module project Do Not Waste Time trying to get around this.
Create dependency poms that include common sets of dependencies. That way you can include your DAO, your jdbc driver and your ORM tools with a single dependency. It also makes upgrading dozens of projects to the newest version of your ORM or DAO that much easier.
Create builder projects that exist only to run assembly and create deployment sets. This will keep multiple parts of your project in sync. Assembling large complex enterprise apps is often complicated enough that you need a mix of maven, shell scripts and/or ant:run tasks plus dozens of profiles. Putting the mess in a project far away from your code will contain the mess before it spreads.
Create tester projects for continuous integration use. Define your web and app servers in those poms as well as the test deployment info. Use of parent projects and common properties files will make testing deployment changes easier.
Define distributionManagement in a parent pom only if it is possible to make all sub-projects a child (or grand-child) of it.
Try not to depend on large files (EAR, WAR) being stuffed into your repository on every build. Removing the need for a 175mb WAR to be pushed to nexus on each snapshot improved our build times.
Try to define things as few times as possible. A DRY build is a happy build. Having 30 poms with source-version 1.5 or 30 poms using junit 3.8.2 is going to make upgrading to java 6 or junit 4.4 that much harder.
Hope this helps.

I've been happily using the Multi-module Enterprise Project layout from Maven by Example. Read it through for inspiration and work it into what works for you..

Here's a few pointers:
Declare dependency versions in a common parent or use declare the versions in a specific project's dependencyManagement and reference it with import scope.
Avoid unversioned plugins. Declare plugin versions in a pluginManagement section.
Declare common plugin configurations in a parent pom, particularly reporting configurations.
Don't declare repositories in your POMs.
Use a repository manager like Nexus
Use properties to allow child projects to inherit configuration, but override key values (e.g. in the url for distributionManagement)
Set up a continuous integration server. Projects in development should have SNAPSHOT versions and be deployed to the repository regularly.

It's all adjustment. Maven don't have all nor latest. mine here saved me you may look and just feel what's right for you.
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.appspot.classifiedsmarket</groupId>
<artifactId>classifiedsmarket</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>classifiedsmarket Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>httpunit</groupId>
<artifactId>httpunit</artifactId>
<version>1.6.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>struts</groupId>
<artifactId>struts</artifactId>
<version>1.2.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>informa</groupId>
<artifactId>informa</artifactId>
<version>0.6.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.jasypt</groupId>
<artifactId>jasypt</artifactId>
<version>1.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>1.9</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>dwr</groupId>
<artifactId>dwr</artifactId>
<version>1.1.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<finalName>classifiedsmarket</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>RELEASE</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>RELEASE</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>RELEASE</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<netbeans.hint.deploy.server>Tomcat55</netbeans.hint.deploy.server>
</properties>
</project>

Related

Issue while integrating selenium with cucumber with maven

I am facing the below error in the base class (Java Step Defination Class)
The type org.openqa.selenium.remote.RemoteWebdriver cannot be resolved
I have tried with the solution provide to a similar question, However, none of them is working
Tried adding selenium remote driver class in the pom.xml
Tried clean the maven project and updating the project
Tried with new versions of cucumber, selenium java and other
Upon running the project I am facing the below issue or upon updating with new versions i am facing class not found error
Adding 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>SeleniumCucumber</groupId>
<artifactId>WebAutomation101</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>6.6.0</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.141.59</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>6.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
</project>
What is the root cause of this problem, is there a way to fix it ?
I am able to resolve the issue after deleting the existing .m2 files from the system

Why does Maven use already non-existent classes and dependencies from history in build

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?

How to implement variable dependency versions in Maven3 using _profiles_?

We need to build project with different versions of deps (in this example, Postgres 8 and Postgres 9). Also, our developers have different versions of DBs on their computers.
I'm tried to do something like this:
<profile>
<id>postgres9</id>
<properties>
<postgres.driver.version>
9.0-801
</postgres.driver.version>
</properties>
</profile>
<profile>
<id>postgres8</id>
<properties>
<postgres.driver.version>
8.3-603
</postgres.driver.version>
</properties>
</profile>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.driver.version}</version>
</dependency>
<properties>
<postgres.driver.version>8.3-603</postgres.driver.version>
</properties>
mvn clean test -Ppostgres9
But it didn't work. Profile variable is not overriding pom variable at all. Also, I cannot achieve that even with the ~/.m2/settings.xml.
Does anyone know how to do this? Thanks.
We've been trying to do similar things in our projects for quite a while. The only way that consistently works is to pass -Dpostgres.driver.version=8.3-603. For some reason, variables are not interpolated before dependencies are computed.
Oddly enough, it seems to work on some of my projects under Maven 3.0.2. I'm trying to investigate deeper now.
I had the same problem.
Moving the version (with the property) from dependency to dependencyManagement in the parent pom solved it for me:
old:
pom.xml:
<dependencies>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.driver.version}</version>
</dependency>
</dependencies>
new:
pom.xml
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
parent pom:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.driver.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

JSF 1.1 to 1.2 migration

I'm currently using JSF 1.1 on Apache Tomcat 6.0.13, with maven 2.
I'm planing to migrate from JSF 1.1 to 1.2. Could someone point me at:
- what JSF implementation is best to use
- is this implementation available at maven central repository
- what part of code will I need to adjust (I'm using custom tags in my project, but besides that it's all plain JSF)
etc.
Any info would be helpful... Thanx!
[edit 1]:
Hm, it haven't worked for me. Dependencies cannot be downloaded from the repository you've specified. Maybe it's because this is link for maven 1 repository. I'm using following pom settings instead:
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>1.2</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${basedir}/src/main/webapp/WEB-INF/lib/jsf-api.jar</systemPath>
</dependency>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>1.2</version>
<type>jar</type>
<scope>system</scope>
<systemPath>${basedir}/src/main/webapp/WEB-INF/lib/jsf-impl.jar</systemPath>
</dependency>
I hope this approach is the correct one. If someone has a more maven-friendly solution, please advise. Thanx!
[edit 2]:
After I've changed my JSF jar from 1.1. to 1.2, following error occurred during application startup:
java.lang.IllegalStateException: Application was not properly initialized at startup, could not find Factory:
javax.faces.context.FacesContextFactory
To fix this error, additional listener need to be added in web.xml:
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
Have a look at the following release notes that has a migration guide from 1.1 to 1.2
http://java.sun.com/javaee/javaserverfaces/docs/ReleaseNotes.html
The maven2 artifacts for JSF 1.2 have found their way in the standard maven2 repository located at http://http://repo1.maven.org/maven2
JSF Implementation
http://repo2.maven.org/maven2/javax/faces/jsf-impl/1.2-b19/
JSF API
http://repo1.maven.org/maven2/javax/faces/jsf-api/1.2-b19/
As such, you shouldn't require any special repository setup in your pom.xml or settings.xml
The dependencies can be defined like this in the pom (1.2-b19 is the latest version at the time of writing) :
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>1.2-b19</version>
</dependency>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>1.2-b19</version>
</dependency>
Included below is a full pom.xml that should contain the basic dependencies for starting a JSF 1.2 project
<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>com.ecs.sample.jsf</groupId>
<artifactId>SampleJsfPom</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<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>
</build>
<dependencies>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>1.2-b19</version>
</dependency>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>1.2-b19</version>
</dependency>
<dependency>
<groupId>com.sun.facelets</groupId>
<artifactId>jsf-facelets</artifactId>
<version>1.1.11</version>
</dependency>
<dependency>
<groupId>commons-digester</groupId>
<artifactId>commons-digester</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

Add jar (dependency with scope system) in an Ear build

I work with Maven and I want to do a build with packaging ear, i want to add a dependency with scope system and also with specifing the systemPath of the jar like follow:
<dependency>
<groupId>group1</groupId>
<artifactId>group1</artifactId>
<version>1</version>
<scope>system</scope>
<systemPath>D:\Buildear\Jars\file.jar</systemPath>
</dependency>
But I don't found the jar in my generater ear!!!
Help please.
I work with Maven and I want to do a build with packaging ear, I want to add a dependency with scope system (...). But I don't found the jar in my generater ear!!!
Yes, that's just what you get when (ab)using a system scoped dependency which is supposed to be always available by definition. I wrote many times about this, for example in this previous answer that I'm quoting below:
I already wrote many, many,
really many times about this
here on SO and in 99% of the cases,
system scoped dependencies should be
avoided. And I'll repeat what the
Dependency Scopes mini guide says
one more time:
system: This dependency is required in some phase of your
project's lifecycle, but is
system-specific. Use of this scope
is discouraged: This is considered an
"advanced" kind of feature and should
only be used when you truly understand
all the ramifications of its use,
which can be extremely hard if not
actually impossible to quantify.
This scope by definition renders your
build non-portable. It may be
necessary in certain edge cases. The
system scope includes the
<systemPath> element which points to
the physical location of this
dependency on the local machine. It is
thus used to refer to some artifact
expected to be present on the given
local machine an not in a repository;
and whose path may vary
machine-to-machine. The systemPath
element can refer to environment
variables in its path: ${JAVA_HOME}
for instance.
So, instead of using the system
scope, either:
Add your libraries to your local repository via install:install-file.
This is a quick and dirty way to get
things working, it might be an option
if you're alone but it makes your
build non portable.
Install and run an "enterprise repository" like Nexus, Archiva, or
Artifactory and add your libraries via
deploy:deploy-file. This is the
ideal scenario.
Setup a file based repository as described in this previous answer
and put your libraries in there. This
is the best compromise if you
don't have a corporate repository but
need to work as a team and don't want
to sacrifice portability.
Please, stop using the system scope.
<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>
<artifactId>aaa</artifactId>
<groupId>aaa</groupId>
<version>1.0</version>
</parent>
<groupId>aaa</groupId>
<artifactId>aaa</artifactId>
<version></version>
<packaging>ear</packaging>
<name>aaa - Ear</name>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>aaa-ejb</artifactId>
<version>${project.version}</version>
<type>ejb</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>aaa-webapp</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jboss-common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jboss</groupId>
<artifactId>jbosssx</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>${aaa.name}-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<generateApplicationXml>false</generateApplicationXml>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<modules>
<ejbModule>
<groupId>${project.groupId}</groupId>
<artifactId>aaa-ejb</artifactId>
</ejbModule>
<jarModule>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<excluded>true</excluded>
</jarModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<aaa.name>aaa-batch</aaa.name>
</properties>
This creates an ear and copies the libraries into the lib folder in the ear.