Integrating Maven & Non-maven projects - maven-2

I'm currently working on two projects simultaneously:
My main project (built with maven)
A spike of an open source project, which my main project depends on (not build with maven)
How do I set up maven to use the OSS project as a dependency with the least amount of friction, given that I'm often developing the two in tandem?

I can think of several solutions:
Mavenize the existing OSS project. This is of course the "ideal" option but often not feasible (even if you introduce the new build system in parallel of the existing one). The project has likely an existing project structure that differs from Maven's standard layout. Changing the existing layout and build script may not be desired by developers, adapting a Maven build to use a non standard layout can be painful. In both case, you're screwed.
Wrap the existing Ant build with Maven. This can be nice if you want to include the build of the OSS project in the lifecycle of your project and have both of them built in one step. You can check this answer on SO for details on how to do this.
Use Apache Ivy or Maven Ant Task in the existing build to produce and install a Maven artifact in your local repository. Use this artifact as a regular dependency in your Maven project (except that you'll have to declare its transitive dependencies manually). This is maybe the quicker and less intrusive approach if building both project separately is not a problem.
It looks like you choose option 3. I think it's a good choice for a quick win.

The solution I've used is the maven-ant tasks (http://maven.apache.org/ant-tasks/).
I added an install task onto the build.xml file, which installs the compiled .jar into the local repo.
While adding a full-fledged pom to the project would defintely be the best approach, this is a major chunk of work, and inflicts maven on the project (where the other users would prefer not to use it).

I think you probably need to bite the bullet and set up a POM for your OSS project tree. This is the painful part (as you would need to hunt down the details of specifying resources paths for various plugins involved depending on the OSS app type (i.e. web, etc.)). Good news is that this is a one time effort.
Once that is done, your main project can refer to the (wrapped) OSS project as a dependency. Here a (standard maven) multi-project structure would apply.

If OSS project has dependencies - create a POM with those dependencies (your project will use them as transitive dependencies) and install that artifact and pom in local repository. If OSS project hasn't any other dependencies is even simpler - the POM is generated automatically during installing.
For both cases use maven-install-plugin.
mvn install:install-file -Dfile=your-artifact-1.0.jar \
[-DpomFile=your-pom.xml] \
[-Dsources=src.jar] \
[-Djavadoc=apidocs.jar] \
[-DgroupId=org.some.group] \
[-DartifactId=your-artifact] \
[-Dversion=1.0] \
[-Dpackaging=jar] \
[-Dclassifier=sources] \
[-DgeneratePom=true] \
[-DcreateChecksum=true]

Related

Can I install several files into one artifact with Maven2 instal:install-file command

I'm developping application with JOGL2 and my favorite IDE Eclipse, also I want to use Maven2 for this purpose. Unfortunately, JOGL2 has no artifact yet. Also, I plan to deploy it as a runnable jar file.
So I want to install JOGL artifact locally : so i'll use the install:install-file command.
But I want to group several jars to make several artifacts, that is :
gluegen-rt.jar and jogl.all.jar as a single artifact named jogl.core
gluegen-rt-natives-linux-i586.jar and jogl.all-natives-linux-i586.jar as a single jar named jogl-natives-linux-i586
and so on
Is it possible ? (The official documentation does not mention the possibility or unpossibility to do so).
Thanks in advance
Install all files as usual like file:jar:version. Than create pom with pom packaging and use gluegen-rt.jar and jogl.all.jar as dependencies in it (they must be already installed). After that use new pom as dependency in your project.
maven doesn't have support for that. You would have to unpack these JAR files and repackage them together.
maven does have support for merging JAR with dependencies (http://stackoverflow.com/questions/574594) - and it's done the way I mentioned above. But you are asking about merging two arbitrary JARs, which is not possible in maven.

How do you perform a reactor build in Maven3 without a root project?

How does one perform an ad-hoc reactor build over multiple maven projects without a root project?
This used to be possible in maven2 by invoking the mvn command with the '-r' option which would search recursively from the working directory for projects and organize them in the reactor to build in the correct order even if the projects did not share a common parent pom.xml. Optionally one could specifically include or exclude certain projects using maven.reactor.includes and maven.reactor.excludes option.
I realize that the legacy reactor mode was removed from maven3 but I can't figure out how to achieve this functionality using the 'make-like' reactor mode.
The "Maven 2"-style reactor feature has been removed following this discussion on the mailing list. The relevant JIRA issue is MNG-4260.
As mentioned in the comments above, it's best to create a top-level pom with a <modules> section that lists the directories containing projects. (If you don't always build all of your projects at the same time, you can put separate modules sections in profiles).

Setting up a standard directory layout using Maven

I'm new to Maven and have skimmed over the documentation as I am following the Hibernate tutorial at http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#tutorial-firstapp-mvn.
I have installed Maven and successfully setup a web-app but this does not contain all of the standard directories mentioned in the tutorial. Am I going mad?
When building my Maven project I am using the maven-archetype-webapp. This gives me the arh-webapp\src\main\resources and arh-webapp\src\main\webapp directories but I'm missing quite a few directories mentioned on the link http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html.
Surely I don't have to manually add these? If not then the Hibernate documentation does not mention what archetype to use in order to achieve the directory structure used in their tutorial. Please can someone enlighten me.
What archetype do I need to use in order to have the above directory plus the src/main/java directory? If there is no such archetype then can easily append these using Maven? and how?
Surely you'll have to manually add these.
Just create those directories that according to the Maven convention are missing. Remember, a Maven Archetype is just a starting point to save you time configuring your workspace. After encountering many problems in some Archetypes myself I've been accustomed to just use a basic-web-app-archetype and then customize it myself, as a beginner with Maven you'll be better off doing that, and will learn a lot.
Regards.
Not all the directories mentioned are required for your standard web application. In fact, the reason behind the presence of the src/main/java, src/main/resources and the src/main/webapp directories is due to the archetype that you've used.
IMHO, the book titled "Better Builds with Maven" will serve you better; the Sonatype books on Maven might also help. The complete Maven documentation is also available as a PDF file, for future reference.
But just in case, you need some clarity on the terms used, here's some:
Archetype: A pattern for projects. Simple web applications (with no dependencies on other frameworks/libraries) have their own archetypes, so do applications using Spring, Hibernate, Seam, etc. Some archetypes will result in creation of different directories, as they are coded that way. You might be able to change the directory structures in most cases, although I cannot vouch for every archetype. For instance, it is quite possible to place your sources in 'src' instead of 'src/main/java', although this requires additional configuration in the POM.
Lifecycles, Phases and Goals: A Maven build lifecycle is a series of phases, with each phase executing a set of goals. Maven can be commanded to execute a build phase, which results in execution of all phases until and including the specified phase.
Maven plugins: Maven plugins contain one or more goals. Goals need not be bound to phases, but usually you would bind them to particular phases. Plugins are the basis for everything operational in Maven; you're using plugins even though you are just compiling the application (the Maven compiler plugin is a core plugin that is present in the Maven distribution).
I hope the above helps, but I would suggest that the reference books be followed.

A layout for maven project with a patched dependency

Suppose, I have an opensource project that depends on some library, that must be patched in order to fix some issues. How do I do that? My ideas are:
Have that library sources set up as a module, keep them in my vcs. Pros: simple. Cons: some third party sources in my repo, might slow down build process, hard to find a patched place (though can be fixed in README)
Have a module, like in 1, but keep patched source files only, compile them with orignal library jar in classpath and somehow replace *.class files in library jar on build. Pros: builds faster, easy to find patched places. Cons: hard to configure, that jar hackery is non-obvious (library jar in repository and in my project assembly would be different)
Keep patched *.class files in main/resources, and replace on packaging like in 2). Pros: almost none. Cons: binaries in vcs, hard to recompile a patched class as patch compilation is not automated.
One nice solution is to create a distinct project with patched library sources, and deploy it on local/enterprise repository with -patched qualifier. But that would not fit for an opensourced project that is meant to be easily buildable by anyone who checks out its sources. Or should I just say "and also, before you build my project, please check out that stuff and run mvn install".
One nice solution is to create a distinct project with patched library sources, and deploy it on local/enterprise repository with -patched qualifier. But that would not fit for an opensourced project that is meant to be easily buildable by anyone who checks out its sources. Or should I just say "and also, before you build my project, please check out that stuff and run mvn install".
This is what I would do (and actually what I do) for both a corporate and an opensource project. Get the sources, put them under version control in a distinct project, patch them, rebuild the patched library (and include this information in the version, something like X.Y.Z-patched), deploy it to a repository (you could use SVN for this, a la Google Code1), declare the repository in your POM and update the dependency to point on your patched version.
With this approach, you can say to your users: check out my code and run mvn install and they will just get the patched version without any extra action. This is IMHO the cleanest way (not error prone, no class path order mess, no increase of the build time, etc).
1 Lots of people are deploying their code to their hosted subversion repository (how-to in this post).
One nice solution is to create a distinct project with patched library sources, and deploy it on local/enterprise repository with -patched qualifier. But that would not fit for an opensourced project that is meant to be easily buildable by anyone who checks out its sources. Or should I just say "and also, before you build my project, please check out that stuff and run mvn install".
I'd agree with this and Pascal's answer. Some additional notes:
you may use dependency:unpack on the original artifact and then combine that with your compiled classes if you don't want to rebuild the whole dependant project
in either case, your pom.xml will need to correctly represent the dependencies of that library
you can still integrate this as part of your project's build to avoid the 'deploy to a repository' step
make sure you honour the constraints of the project's license when doing all this!

find dependencies in target/classes instead of local repository?

Summary: I'm looking for a way to instruct maven to search for dependencies in target/classes instead of jar in the local repository
Say I have 2 modules, A and B where A depends on B. Both are listed in a module S. Normally I need to run 'mvn install' in S. I'm looking for a way to run 'mvn compile' so that when A is compiled its classpath will contain ../B/target/classes instead of ~/.m2/repository/com/company/b/1.0/b-1.0.jar.
(my reason is so that i can have continous compilation without the need to go through packaing and installation, or, more exactly, use 'mvn scala:cc' on multiple modules)
I don't think that this is possible without horrible hacking, this is just not how maven works. Maven uses binary dependencies and needs a local repository to resolve them. So, the maven way to handle this is to launch a reactor build on all modules. Just in case, have a look at Maven Tips and Tricks: Advanced Reactor Options.
But, during development, can't you just import all your projects in your IDE and use "project references" (i.e. configure your projects to depend on source code instead of a JAR) like most Java developers are doing? This is the common approach to avoid having to install an artifact to "see" the modifications.
If this is not possible and if you really don't want to install artifacts into your local repository, then you'll have to move your code into a unique module.
i know this is annoying. which helped me here is definitely IDE support. eclipse and IntelliJ are clever to collect all dependencies once a maven-project import is done. even cross module dependencies are compiled live.