Maven is more or less the de facto system for managing dependencies and builds in Java applications these days. Whether this is good or bad is up to yourself to decide, but Maven is here to stay and by using it properly, you can actually do some pretty nice stuff with it.
In this blog post, I’m going to talk a little bit about how to configure your Maven-based Vaadin projects to get the most out of them. I’m going to show you how to use overlays to support multiple deployment configurations and give you a few options for compiling the widgetset.
This blog post isn’t a crash course in Maven. I assume you know the basics of Maven, such as declaring dependencies and adding and configuring build plugins. I also assume you already know how to use the Vaadin Maven plugin. If not, there is a little information about it in the Book of Vaadin.
For code examples, please see my GitHub. There you will find both template projects and Maven archetypes that are able to generate projects with this type of setup. Keep in mind, though, that I maintain these archetypes for my own personal use and I may make changes to them at any time. Also note that not all project configurations presented in this blog post have archetypes.
Applications with server-side code only
For many Vaadin applications, all you need is just a single WAR-file that contains both your UI and your backend logic. However, there is one very good reason why you would want to configure this as a multi-module Maven project and that is overlays.
If you’re not familiar with Maven overlays, I suggest you take a look at the Maven WAR Plugin documentation. In short, it makes it possible to build different WAR files of the same application very easily.
For example, in many projects, the application requires one configuration to run on the development machine, another to run in the test environment and maybe a third to run in the production environment. The Maven project setup could look like this:
Let’s have a closer look at what the different Maven projects contain.
Parent
This is the root POM file that is required by all multi-module Maven projects. I normally add common configurations (such as source code encoding, Java version used by the compiler, etc.) and dependencies (such as the Vaadin jars, any Java EE APIs, testing libraries, etc.) to it.
Webapp
This is a WAR module and contains the main application. It is configured for development mode, which means it should be directly deployable from within your IDE. Any widgetset compilation can also be handled by this module, although in some cases you might want to move it to a completely different module. I will return to this shortly.
Webapp-production
This is another WAR module, but it does not contain any source code. It only contains the files that should be added to - or replaced in - the Webapp module when deployed in the production environment. For example, you could have a different web.xml file or a different logging configuration file optimized for production.
It also imports the Webapp module as a dependency. Thanks to overlays, Maven will merge the contents of the Webapp module with the contents of this module, with any files in this module taking precedence over the files with the same name in the Webapp module.
Finally, if you’re using SCSS themes and aren’t compiling them in the Webapp module, or if you’re using different widgetset compilation configurations during development and production, you need to configure this module to take care of the necessary compilation as well. In this case, you might have to tweak the resources plugin so that the necessary files are copied from the Webapp module into this module.
Webapp-test
This is another overlay WAR module optimized for deployment in a test environment. If you don’t have a separate test environment, you can just leave this module out. Likewise, if you have a need for more deployment configurations, you can just add more overlay projects.
Adding client-side code to the mix
The previous example did not contain any application-specific client side code. If your application needs it, all you need to do is add another JAR module that contains your client-side code:
However, you might need to add some additional configuration to the client module depending on where you compile your widgetset. Let’s have a look at a few different alternatives:
Compiling everything in the client module
One alternative is to build the widgetset directly in your client module, package it inside the JAR and let the Vaadin servlet load it from the classpath.
Pros: It is easy to configure.
Cons: You cannot easily have different widgetset compilation configurations for development and production, and your client module needs to depend on all other modules that contain client-side code as well (like add-ons, for example).
Compiling everything in the webapp module
This is basically the alternative presented in the beginning of this article. However, if you also want to include your own client side module, you need to do some additional configuration.
First, you need to add the Maven Source Plugin to your build lifecycle so that a source jar is also built for the client module, in addition to the binary jar. Next, you need to add the source jar as a dependency with provided
scope to your webapp module.
Pros: Makes it possible for multiple webapp modules to have their own widgetset compilation configurations, and there is no need to separately maintain dependencies to other client-side modules since the webapp is already aware of all of them.
Cons: Requires slightly more configuration.
Use separate modules for compiled widgetsets
A third alternative is to create separate Maven modules for the compiled widgetsets and then include these in the webapp modules. This basically requires the same amount of configuration as the first alternative.
Pros: You can have pre-compiled versions of your widgetset for different environments. If you have your own application framework, you could make the pre-compiled widgetsets part of the framework and reuse them in other applications (provided that they don’t use any additional client side components).
Cons: The compilation module needs to be aware of all modules that contain client-side code, and you get more Maven configuration files to maintain.
Summary
I have now presented the way I like to set up my Maven-based Vaadin projects. I use overlays to support multiple deployment configurations, sometimes for different environments, other times even for different customers. I also presented different ways of handling the widgetset compilation, if the application relies on client side code not found in the Vaadin core widgetset.
As with most of the problems in software engineering, there is always more than one solution. If you have a neat way of setting up your Vaadin projects with Maven, or think there are any issues with my setup, please let me know by either adding a comment below or contacting me directly.
Finally, I can mention that Vaadin is planning to release new Maven archetypes that will be based around this type of project configuration. We will return to this in the not too distant future.