views:

137

answers:

2

I'm currently developing multiple web applications using Spring. I'm using Maven for building and Git for version control. At the moment I'm trying to find a way to split development of some things used by all webapps, e.g. I have some helper classes that are the same for all projects. The problem is, I don't want to use only classes, but also resource files and some sort of parent POM while still being independent from a repository and able to benefit from Git.

Although I'm not enthusiastic to change the build system, I'm not a real fan of Maven. Especially the concept of inheritance and aggregation is what constrains me right now. Maybe Ivy is an option?

I'd want to give you a quick overview of my setup:

There's some sort of parent project including some classes, Spring configuration files and other resources like templates, images and style sheets. Let's call it base. This one is not a complete Spring webapp and won't be deployed. There are several other projects which inherit from base and should be packed into a WAR. Let's call them webapp1 and webapp2.

base, webapp1 and webapp2 have their own Git repositories:

\
 |
 |- base.git       (base's repository)
 |
 |- webapp1.git    (webapp1's repository)
 | \
 |   base          (base used as a Git submodule)
 |
 |- webapp2.git    (webapp2's repository)
   \
     base          (base used as a Git submodule)

I want to be able to change bases code from inside the the webapps using a Git submodule and also be able to build a fully functional WAR of each webapp using mvn package inside the webapp`s directory.

Maven's parent or module don't allow a dynamic approach like this. I didn't find a way to use module like that at all and using parent for my needs is complex and static: Every change to base would require a new version to be pushed to the repository so that the webapp`s can inherit from it.

Maybe I didn't completely understand Maven's inheritance, but I'm pretty lost right now.

Did anyone achieve something similar with success? What build system did you use and how?

A: 

Your use case seems to be a good use case for overlays (also have a look at the examples).

Overlays are used to share common resources accross multiple web applications. In general, all dependencies of a WAR project are collected in WEB-INF/lib except for WAR artifacts that are overlayed on the WAR source.

But base wouldn't be "under" the webapp module, it would very likely be a sibling module (maybe it can be "in" the webapp using some Git black magic but this goes beyond my Git skills and I fail at thinking of how this could be handled with Maven). No, really, I think the Maven way would be to use overlays. And if this is not what you want, better use something else than Maven IMO.

Pascal Thivent
This seems like a better approach than what I wrapped up with a Maven inheritance using `parent`. But it lacks, well, the inheritance. Combining both would result in a similar bloated configuration without dynamics and support for a smart Git workflow.Seems like Maven isn't playing that well with Git (and especially Git submodules). I'm already investigating alternatives and, like said before, I'm open for suggestions.
Koraktor
@Koraktor Maven is playing well with Maven, you have to follow its rules. What you want to do is not possible with Maven: you can't inherit from a project that has not a `pom` packaging (I don't see why you need inheritance between webappX and base BTW). You need something entirely configurable here i.e. Ant+Maven Ant tasks or Ant+Ivy (you don't want to compile "base" twice I guess, you need custom build logic). But honestly, I see more what you loose than what you win with your "smart Git workflow".
Pascal Thivent
A: 

I found a working solution by myself.

The basic solution of my problem is a small sub-element of the <parent> element called <relativePath>. It allows to search for the parent POM in the specified directory. Otherwise you would always need to deploy a new version before you could test it within your application.

<parent>
    <groupId>com.example</groupId>
    <artifactId>base</groupId>
    <version>1.0.0</groupId>
    <relativePath>base</relativePath>
</parent>

But that was only the starting point, allowing to work with a Git submodule. To get it really working, I needed to do the following:

  • Create a WAR with classes and resources from both, the webapp and base, i.e. all files inside

    base/src/main/java
    base/src/main/resources
    base/src/main/webapp
    src/main/java
    src/main/resources
    src/main/webapp
    

    While resources are pretty easy to cover, a bit of configuration for org.apache.maven.plugin:maven-war-plugin is needed to get the webapp resources into the WAR. Compiling of two different source folders requires a plugin, so I need to use org.codehaus.mojo:build-helper-maven-plugin to get the classes of base into the WAR.

  • Additionally, I used a lot of filtering for the resources, so there's almost no need for customization of the basic files to get a webapp up and running. For example I use ${project.artifactId} inside my main template file, so my HTML <head> will look something like this for a webapp called webapp1:

    <link href="stylesheets/base.css" rel="stylesheet" media="screen" type="text/css" />
    <link href="stylesheets/webapp1.css" rel="stylesheet" media="screen" type="text/css" />
    

It really took a lot of trial and error, but at last I got it working and I think this is the best way to achieve my target using Maven. This would've been a lot easier using a dynamic tool like Buildr, but sadly Buildr is slow on Windows (thanks to Ruby) and doesn't integrate very well into most IDEs.

Koraktor