Multi-flavor webapp


#1

This might be a noob question, please excuse if it is…

I have a webapp which has 2 “flavors” (cloud, onprem).
Both use some common java source and some common webapp files.

So I have a directory tree looking like:

theWebapp
---- common
-------- src
------------ main
---------------- java
---------------- resources
---------------- webapp
------------ test
---- cloud
-------- src
------------ main
---------------- java
---------------- resources
---------------- webapp
------------ test
-------- build.gradle
---- onprem
-------- src
------------ main
---------------- java
---------------- resources
---------------- webapp
------------ test
-------- build.gradle
---- build.gradle
---- settings.gradle

common is never supposed to be compiled or deployed alone.
common source can’t be compiled without flavor source.
common is included in both cloud and onprem flavors.

Also when directly building theWebapp, I’d like it to build the cloud project as the default.

The root settings.gradle has:
include "common", "cloud"

The root build.gradle has:

buildscript {
	repositories {
		jcenter()
	}
	dependencies {
		classpath 'org.akhikhl.gretty:gretty:+'
	}
}

subprojects {
	apply plugin: 'war'
	apply plugin: 'org.akhikhl.gretty'

	repositories {
		jcenter()
	}

	dependencies {
		compile group: 'commons-io', name: 'commons-io', version: '1.4'
		compile group: 'log4j', name: 'log4j', version: '1.2.15', ext: 'jar'
	}
}

Both flavors build.gradle have:

dependencies {
	compile project(':common')
}

The 2 problems are:

  • compilation fails as common project requires some source it does not have without the flavor
  • cloud webapp files don’t include commom webapp files

Thanks for any help.

Seb


(Stefan Oehme) #2

Note that this is badly supported by IDEs and most of the time unneeded. I think you’d generally be better off if you rewrite your common code so that it can be compiled by itself and so that the flavor projects can plug into it.

If you really want to compile the flavors and common code together, you wouldn’t do that with separate projects, but instead use one source set per flavor. But I’m pretty sure you’d have to tune a lot of things to make gretty and the war plugin work with that. So I encourage you to follow my first suggestion of decoupling your projects better.


#3

Hi Stefan,

Thanks for your answer.
I’ll try to do this concerning compilation.

But concerning the webapp?


(Stefan Oehme) #4

Could you be more specific, please?


#5

The common project contains all common webapp files.
When I build the webapp of cloud project, it doesn’t include the common files…
I can’t see why.


(Stefan Oehme) #6

Because your common project buids a ‘war’. Wars are not magically included into each other. What you probably want is a web library (a jar file containing the common resources). This is supported by Servlet 3.x. You put them into META-INF/resources and they are visible in downstream webapps as if you had included them in their resource directory.


#7

and would something like this work?


(Stefan Oehme) #8

Why don’t you just give it a try and see how it goes? :slight_smile: I’d generally go with the more modern approach though. This is exactly what Servlet 3.x was designed for, so you don’t have to explode wars anymore.


#9

Thanks for you help.
Indeed exploding common war before generating flavor war works.
I’ll give a try to the modern way.


#10

Tried several things but failed.
Could you give me a hint on how to acheive this?


#11

Finally, works!
For those who are interested in an answer.

2 ways to acheive this properly:

Using gretty
The flavor project (lets say cloud) build.gradle just needs the following settings:

gretty {
	overlay ':common'
}

The following command will start a webserver with merged webapp files:
gradle :cloud:appRun

To build a merged war:
gradle :cloud:assemble

Using servlet3.0 resource jar
Move all the common webapp files from
theWebapp/common/src/main/webapp/*
to
theWebapp/common/src/main/resources/META-INF/resources/
Then just call classic:
gradle :cloud:war


(Stefan Oehme) #12

And make the common project a normal jar project. :slight_smile: