2

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?

3 Answers 3

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the response. I've been reading up on WAR Overlays, it looks like they don't preserve dependencies and I'd have to either duplicate dependencies across core/children OR use the Appfuse WARPATH plugin (overlays + dependencies). Both methods also integrate really poorly into eclipse (from what I've seen so far). That might just be me stuffing things up though.
If you declare a dependency on the common war's POM, Maven will download all of the common war's dependencies. You might have to use the <packagingExcludes> parameter of the war goal to keep the common POM out of the other war. It's hacky but I've used the technique for another purpose and it works.
The current state of Maven overlays and Eclipse integration may have improved since these other comments, but with the help of the m2e-wtp project, I was able to come up with a very workable Maven overlay based solution to this problem that also works well in Eclipse. (You may need to split your war module's classes into a separate jar module, but that's not a big deal.)
1

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.

2 Comments

I'm poking around with Gradle now, at first glance it seems pretty promising but I'm still sorting out the nuts and bolts. My only fear is that it seems like a very young project. How have you found the stability/community support?
gradle has been around for several years now. I used it on several projects (still using it) where I built Java/Groovy and Scala projects with breeze. Gradle forum and Gradle mailing list are very active and helpful, so is SO.
0

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/

7 Comments

Would love to hear your thoughts about this (and other) solutions a year later... Trying to make this same decision for our team right now.
I should probably do a blog post or something about this (its a broad topic) but applying the KISS principle has worked thus far. Backend being split into a 'core' dependency of multiple projects has worked wonders despite being a large upfront investment in development. Maven handles all of the dependency legwork here. For the frontend 'core' JS we make releases of a single ZIP with all of our common JS,CSS utilities/widgets, this gets dropped into projects in the same way you would drop any other JS 'library'. Maven can handle release packaging here with the maven-assembly-plugin
Thanks, Josh! BTW, are SVN externals still a part of your solution? Also, do you use Eclipse, and if so, how well does this solution work with your dev environment? Right now, I can come up with several solutions that I think would work well from Maven's perspective, but am still struggling to find what will work best in Eclipse.
We use eclipse, it works well enough for us but my main gripe is the default JS editor sucks. SVN externals originally were used because the core javascript project (which was still early in development) didn't have any real means to test the developed widgets. Hence they were imported via an external and changes fed back via developing the child projects. This is still in place now BUT the core project is now mature enough to stand on its own. The svn externals are more just legacy cruft and will probably get removed, we treated them as a development crutch, not a permanent solution.
I should also mention that eclipse + subversion plugin will happily split commits up amongst svn externals. This is powerful but also terrifying.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.