Reputation: 69
I have a web application, built with Maven, consisting of a Java (Spring) backend and Javascript (ExtJS/OpenLayers) frontend. This web app has slowly become the base for a number of derivative or child web applications. By that I mean we have a single webapp whose functionality has been extended for a few domain specific problems which has resulted in a set of webapps all relying on common functionality.
Up until now we've been 'managing' the problem by having a SVN repo with the core code that the derivative webapps branch from and allows us to occasionally merge changes between the branches. This method has all sorts of problems but there were historical reasons for why it was chosen, luckily we are now in a position to rectify this.
A better solution seems to be turning the common core code into a library (not hard) and having the derivative children link to it. Unfortunately a large chunk of the common functionality exists in the javascript (ExtJS widgets and the like) so simply generating a JAR library won't suffice. We need a way to have the 'core javascript' files make their way into the child webapps, although it's not possible to truly treat them like java classes our codebase does the best job it can by leveraging the Ext JS class system.
My question is whether there are any solutions out there to help manage this problem? Has anyone had any luck doing something similar with Maven? Is this such a rare case that I might have to resort to creating my own maven plugins or should I be searching for a new build tool?
Upvotes: 2
Views: 808
Reputation: 69
So after evaluating a few different tools + ideas I've found that the best fit for our project(s) is a combination of Maven and SVN externals. We address the frontend/backend dependencies separately:
Backend - Core: Build the core as a typical JAR package (nothing special here)
Frontend - Core: Have the core frontend included in the same repository as the core backend. It will be in a webapp directory that isn't packaged by the core JAR build, instead it will be packaged separately into a ZIP file using the maven assembly plugin:
pom.xml
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<descriptors>
<descriptor>src/assembly/webapp.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
webapp.xml
<assembly>
<id>webapp</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}/src/main/webapp/core/</directory>
<outputDirectory/>
<includes>
<include>**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Backend - Child : Typical maven dependency on core
Frontend - Child : Either references the core frontend using an SVN external or by using a pre built package dropped somewhere into the webapp. Using the external allows Eclipse to transparently develop the core + child frontends, using the pre built package is much 'easier' to manage but harder to migrate changes.
Overall the system is relatively easy to manage, the only non intuitive parts come with releases which complicate the svn externals. But with 'proper' release branching + tagging it's nothing that can't be dealt with.
I've also written a blog post comparing and contrasting all the options we considered - https://cgsrv1.arrc.csiro.au/blog/2012/06/15/managing-an-extensible-javajavascript-application/
Upvotes: 0
Reputation: 22509
While there is a maven javascript plugin, I would recommend to use something a lot more friendly for your build than maven.
One option you can look at is to use gradle with its great js plugin:
// Pull the plugin from a Maven Repo
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.eriwen:gradle-js-plugin:0.4'
}
}
// Invoke the plugin
apply plugin: 'js'
You can get the examples from the docs. Remember, this is Groovy, hence you can add "versions" as simple properties e.g. "file-${file-version}.js", where a "file-version" could be defined in a separate "versions" file which can be imported:
apply from: 'housekeeping/versions.gradle'
Here is an example on how to "Combine, Minify and Copy your JS's to your .war file using Gradle"
Again Groovy is what it sounds like => it is Groovy. In my opinion is the best language for your Java build.
There is also a gradle CSS plugin in case you need one.
On a separate note, if you have such an option I would move to git, as managing many related projects is way easier in git than in SVN, as different repos, or git submodules.
Upvotes: 1
Reputation: 14951
The overlays feature of the maven-war-plugin may help.
The common js files (and perhaps even the classes if it makes sense) may be moved into a separate war file. If it will not be deployed on its own you could configure the war plugin to not fail on a missing web.xml
file with the <failOnMissingWebXml>
element. Then, you add the overlay configuration to each of the derivative wars.
Upvotes: 1