This is the first of a series of posts, where I will attempt to consolidate a set of practices for creating, building and deploying Magnolia projects.
Why, you ask ?
Over time, Magnolia has grown into a fairly complex, but beautifully flexible product. There are a number of features, techniques and tricks that can make one’s life much easier. Unfortunately, I still see a lot of folks building or deploying their projects in ways that make me cringe. Not that they’re doing awful things, no, but it seems it’s high time to gather a few tricks here that will hopefully make a few folks go “aaaaahhhh”, and perhaps even a few others cursing me for not telling them about all this earlier.
I’ll introduce a few points which will hopefully make everyone’s life a little simpler, developers and sys admins alike. Here’s a little roadmap of the key points, covered by different blog posts:
- Automate your builds: don’t build Magnolia, build your project. You’re reading this post.
- Automate your configurations: you don’t need to manually configure Magnolia when installing it.
- Streamline your deployments: you don’t need to modify files on the filesystem to configure Magnolia, or produce different artifacts for different instances of the same project.
We’ll use the following tools:
- Maven 2.2.1. The stuff mentioned here probably works with Maven 3, but I’ve never tried. Leave a comment if you do !
- IntelliJ IDEA. Am I opinionated when I claim this is the best Java IDE around ? Perhaps. Again, if you’re an Eclipse, Netbeans, or any other IDE user, please leave comments if you know equivalent “procedures” for your IDE of choice.
You might be better off feeling familiar with:
- Maven and its dependency mechanism. Similar concepts apply if you use other dependency management and build tools, such as Ant+Ivy or Gradle. I’ve been looking into writing this article with Gradle instead, but it seems it doesn’t support war overlays just yet, so I abandoned the idea. Comments, yada yada yada, you know the deal.
- A *nix shell. I’ll use a few commands here and there, and some might be OSX-specific. Hopefully, you’ll know your way around the terminal your OS provides.
Often times, I see people trying to build Magnolia itself, as the first step to build their own project. That’s quite a hurdle, I’m trying to demonstrate below that it’s not necessary. Once your project is setup, of course, you might want to make modifications to Magnolia, but you’ll find out that in most case you should be able to do everything you need within the confines of your own project.
Creating a basic, empty project
For simplicity’s sake 1, I will use Maven and its archetype mechanism in the following example. Open a terminal,
cd to somewhere you feel comfortable and type the following command:
mvn archetype:generate -DarchetypeCatalog=https://nexus.magnolia-cms.com/content/groups/public/
If this is the first time you use archetypes, this might take a while. You’ll get to choose which archetype to use in a list of archetypes. If the list hasn’t changed since writing this post, 6 should be your choice. (magnolia-project-archetype)
After entering some details about your project, this archetype will create an empty, ready-to-use, Maven structure with a top-level “project” and a webapp as a Maven sub-module. This might seem overkill for a simple project, but it will ease the transition if you want to add modules later on.
For the sake of the example, here are the values I used:
'groupId': com.acme 'artifactId': acme-project 'version': 1.0-SNAPSHOT 'package': com.acme 'magnolia-version': 4.4.4 'project-name': My ACME Project
A first build (Ô, the emotion)
Let’s enter the project we just created, and build it.
cd acme-project/ mvn clean install
Again, if this is your first time, this might take a little while, possibly longer. Go grab a coffee.
Now that we have a first successful build, let’s switch to our IDE of choice. 2
open -a "IntelliJ IDEA 10" pom.xml
If you’re not on OSX, just create a new project, based on the top-level
New Project >
Import project from external model >
Maven > Select root directory of the project >
Running the project
Well, hopefully you know the drill in your IDE. With IntelliJ, I do:
Run > Edit Configurations > + (Tomcat > Local), then add the
acme-project-webapp:war exploded artifact to the
Deployment section, make sure it deploys to the root context (
/)… or anywhere else, as long as you remember it, anyway.
Now hit that Start button already ! Tomcat should start Magnolia, and my IntelliJ is configured to then open my browser to http://localhost:8080 once it’s up and running. Should that not be the case for you, well, do it manually.
Go through the install screen, and once the installation is completed, login as
Ok, so what now ? We have a basic Magnolia project running, but … what’s next ? Well, let’s just make it a little more useful, by giving it a set of useable templates and some layout.
Adding a module… or two
So, let’s add Magnolia’s Standard Templating Kit to our webapp3. Open
acme-project-webapp/pom.xml, and in the
<dependencies> section, paste the following:
<dependency> <groupId>info.magnolia</groupId> <artifactId>magnolia-module-standard-templating-kit</artifactId> <version>1.4.4</version> </dependency>
Note: In IntelliJ, a notification bar shows up when you modify a pom file, prompting you to “Import Changes” or “Enable Auto-Import”. Enabling auto-import works quite well, but can be resource intensive when heavily modifying pom files. For this example, you can go ahead and enable it. If you don’t, just remember to click “Import Changes” at least once before starting up the server.
At this stage, you’ll need to restart your server for the new module to be picked up, but to save you the trouble of deciphering an error message, do not start just yet. The Standard Templating Kit has a non-optional dependency to the DMS module, which we’ll need to add to our pom as well 4. So, adding the DMS module:
<dependency> <groupId>info.magnolia</groupId> <artifactId>magnolia-module-dms</artifactId> <version>1.5.2</version> </dependency>
And while we’re at it, we probably want some sort of design for our project, right ? Well, why don’t we go and use a different theme than the default theme shipped with the STK bundle ? There’s a different theme available on the Magnolia Forge, let’s use that !
<dependency> <groupId>info.magnolia.themes.blue</groupId> <artifactId>magnolia-theme-blue</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency>
Once our beloved IDE has picked up and digested all those changes, it’s time to restart our server. By the magics of Maven, not 3, but a dozen-or-so modules will need to be installed.
An aside for Maven enthusiasts
If you’ve looked at the pom files produced by the archetype above, you’ll have noticed two things:
- We depend on the
magnolia-empty-webapp, twice. This is to compensate for MWAR-33. The one dependency to the
warartifact is to overlay our project on top of it: we don’t need to have a
web.xml, nor any of the other files that come with the basic Magnolia webapp. The dependency to the
pomartifact is to ensure Maven can resolve dependencies properly. Finally, we need to exclude
WEB-INF/lib/*.jarfrom the dependent war files, which is why there is a little bit of configuration for the
maven-war-pluginin our webapp pom.
- Our top-level pom has yet another “special” dependency: it depends on
magnolia-project(which is the top-level pom for
magnolia-empty-webapp, …) in
scope:import. This has a special meaning in Maven: essentially, all dependencies in the referred artifact’s
<dependencyManagement>section are “imported” into our project. This is the equivalent of copy-pasting that entire section into our project, … without the copy-and-paste mess. This would be extremely advantageous, if you want to depend on, say,
magnolia-enterprise-webappin scope import: you would not need to know which version of STK was shipped with that specific release of Magnolia, nor of any other module. The day you want to move to Magnolia 4.4.5, 4.5 or 5.0, you’d only need to change that one version number, and get all upgraded dependencies. And this wouldn’t even prevent you from selecting specific versions of some modules if you’d want to. (for instance if a bug fix of the DMS module came out but you didn’t want to update all other modules). Unfortunately, up to 4.4.4, there’s a caveat, which is why we still have both the
A first page and a bang
If you’ve been getting impatient (I don’t blame you!), you have tried to create a first page in this project, and your eyes started to bleed when you saw the infamous red-and-yellow “FreeMarker template error” – well, you’ve stumbled upon MGNLSTK-788 !
Call me a tease, but we’ll look into solving that in next installment of this series of posts.
In this first post, we’ve looked at how we can relatively simply create a Magnolia-based project, building with Maven. Granted, the project doesn’t do much yet, but it’s reached a few goals already:
- We are building our own project with Magnolia. At no point in time did anyone come and manually “drop a jar” in the webapp, or modify a configuration file in the deployed webapp. We intend to keep it that way over the course of this series of post.
- The build is reproducible. At any point from now, you should be able to commit your files to your scm, have builds produced by your team mates, your CI server, and do releases of your project.
- The arguable simplicity of using the tools I know best. Really looking forward for some Gradle examples. ↩
Just for the record, I don’t ever type this; I have an alias in my
~/.profileand I just type
idea pom.xml, which I find quite practical. IntelliJ also has a built-in command (
Create Command-line Launcher) which generates a script to do the same. ↩
This is where some Maven experience and knowledge might start to get interesting. If you’re used to Maven, you’ll probably want to add this dependency to the top-level pom’s
<dependencyManagement>section, and refer to it without version number in the webapp pom. ↩
If you wonder why it doesn’t come in transitively, it’s because of a fairly annoying “feature” of our builds: when we build a “bundle”, we use the maven-assembly-plugin to incorporate all dependencies of a project by filtering on their scope, only including those in the
compilescope. In the case of the STK, we chose to mark the DMS dependency in scope:provided, because we did not want the DMS to end up in the bundle, considering that it is already shipped with the default Magnolia CE bundle. For another, perhaps more understandable example, we do the same thing with magnolia-core: we don’t want nor need to ship magnolia-core in the STK bundle. However, we do bundle STK with a couple of other less common modules: inplace-templating, resources, … Not bundling the DMS module helps folks installing manually: one can just unzip the bundle in
WEB-INF/liband not search for duplicate jars. Feedback and ideas more than welcome, of course! ↩