Heads up! These docs are for Portofino 3, which is a legacy product. Check out Portofino 4!

Posted by Paolo Predonzani
on April 9, 2009


Introduction

In this tutorial we'll see two things.
First we'll do a very simple customization of Portofino: changing the logo and css stylesheet.
Second we'll use Maven to create a new mywebapp.war which bundles, in a single .war, the standard Portofino distribution, the customizations and the portofino-custom.properties configuration.

In this way, the mywebapp.war that contains the customized application will be self-contained, professional and easy to deploy.

The problem

If I had to create and distribute an application based on Portofino I would:


  • Download the standard Portofino distribution
  • Unpack the war file
  • Add a portofino-custom.properties configuration file
  • Customize or add any other resources, e.g., css files, images, jars or class files
  • Repackage the war file as mywebapp.war
  • Distribute to my clients (who will deploy myapp.war to their app servers)

In a simplistic approach, I would do these steps manually. However this brings the following problems:


  • If many files need to be changed/added, the technique becomes error prone.
  • If a new version of Portofino comes out, I have to repeat all the steps manually again.
  • I have to document the customizations that I've applied, or I'm going to forget them.
  • If I distribute the source code rather than the .war package, I have to teach my users how to repeat the process.

For a one-off exercise this might be fine, but if I want to develop and maintain a serious application based on Portofino I would need a better process.

Maven overlays

All the manual steps mentioned above can be automated using Maven overlays. The process becomes repeatable, less error-prone, and overall simpler.

Maven is a build/dependency/project management tool. For an overview, see the Maven in 5 minutes guide.

Overlays are a specific, advanced use of Maven. Fundamentally they allow you to build a target war (mywebapp.war) as a "merge" between an original war (the Portofino standard distribution) and other code/files that you develop. To visualize how this "merge" works, see Manipulating WAR Overlays.

Installing Maven

From a shell/command line, check if Maven is already installed on your system:

$ mvn -version
Maven version: 2.0.10

Any version of Maven since 2.0.6 is suitable for our purposes.

To download and install Maven, follow the instructions here: http://maven.apache.org/download.html.

Installing Portofino in the local repository

This is a preliminary step that you need to do once on your system. Repeat it only when a new version of Portofino becomes available.

Download Portofino. Expand the archive and check that the file "portofino-war-3.1.0.war" is present. Then type the following command:

mvn install:install-file -DgroupId=com.manydesigns \
    -DartifactId=portofino-war -Dversion=3.1.0 -Dpackaging=war \
    -Dfile=/path/to/portofino-war-3.1.0.war

Notice that you must change "/path/to/portofino-war-3.1.0.war" to the location where you've actually downloaded Portofino.

Creating the maven overlay project

To kick-start the new maven project we'll use an archetype, a kind of template for various types of project. We choose the "maven-archetype-webapp", which is an archetype suitable for any war-based applications.

Before you start, you need to decide the groupId and artifactId for the customized application, roughly equivalent to an identifier of your organization and an identified of your webapp. We'll use:

  • groupId: com.mycompany.app
  • artifactId: mywebapp

Now we can run:

mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=mywebapp \
    -DarchetypeArtifactId=maven-archetype-webapp

Maven will run and log several messages. Make sure the last few lines look like this:

[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Mon Apr 06 14:56:39 CEST 2009
[INFO] Final Memory: 8M/14M

A new directory called "my-webapp" has been created. Let's have a look at it.

$ cd mywebapp
$ find .
.
./pom.xml
./src
./src/main
./src/main/resources
./src/main/webapp
./src/main/webapp/index.jsp
./src/main/webapp/WEB-INF
./src/main/webapp/WEB-INF/web.xml

As you can see, a standard directory structure has been created (for more information on this, see the Introduction to the standard directory layout).
Now edit the pom.xml file and add the section in bold:

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion> 
  <groupId>com.mycompany.app</groupId> 
  <artifactId>mywebapp</artifactId> 
  <packaging>war</packaging> 
  <version>1.0-SNAPSHOT</version> 
  <name>mywebapp Maven Webapp</name> 
  <url>http://maven.apache.org</url> 
  <dependencies>
    <dependency> 
      <groupId>com.manydesigns</groupId>
      <artifactId>portofino-war</artifactId>
      <version>3.1.0</version>
      <type>war</type>
      <scope>compile</scope> 
    </dependency>
    <dependency> 
      <groupId>junit</groupId> 
      <artifactId>junit</artifactId> 
      <version>3.8.1</version> 
      <scope>test</scope> 
    </dependency> 
  </dependencies> 
  <build> 
    <finalName>mywebapp</finalName> 
  </build> 
</project>

Now we're ready to run our first build. Type:

mvn package

And make sure you get the BUILD SUCCESSFUL message.
Have a look at a folder called "target", which has just been created. It should contain a file called "mywebapp.war" as well as an expanded version of it in the "mywebapp" directory.
Well, that is the overlaid war target. It still doesn't do what we want, but we're getting closer.

Cleaning up some files we don't need

Before proceeding, make sure you delete two files that were automatically created by the archetype:

  • src/main/webapp/index.jsp
  • src/main/webapp/WEB-INF/web.xml

Unless you really want to customize Portofino's index.jsp and web.xml files, those two files must not be left around.


Adding the portofino-custom.properties

The portofino-custom.properties can be easily bundled inside mywebapp.war. Create the file:

src/main/resources/portofino-custom.properties

And copy the following content:

database.jdbc.driverClass=oracle.jdbc.driver.OracleDriver
database.jdbc.connectionURL=jdbc:oracle:thin:@127.0.0.1:1521:XE
database.jdbc.username=myusername
database.jdbc.password=mypassword

model.application.name=MyWebApp
model.stylesheet=/mywebapp.css 

Of course customize the database connection details. If you do not want to hardwire this information in the configuration file, you may use the following content instead:

database.configurationType=jndi
database.jndi.name=jdbc/portofinodb

model.application.name=MyWebApp
model.stylesheet=/mywebapp.css

...which refers to a JNDI data source called jdbc/portofinodb that you'll have to set up on the deployment server.

Adding a custom logo

Create or choose a logo image and save it as 

src/main/webapp/mylogo.png

Adding a custom stylesheet

Our custom stylesheet will be just sufficient to display the custom logo. Create this file:

src/main/webapp/mywebapp.css

And copy the following content:

@import url("default.css");

div#logo a {
    display: block;
    position: absolute;
    top: 14px; /* distance from top margin */
    left: 20px; /* distance from left margin */
    text-decoration: none;
    color: black;
    font-weight: bold;
    font-size: 2em;
    background: url('mylogo.png') no-repeat 0px 0px;
    padding-top: 60px; /* the logo's height */
    height: 0px;
    width: 200px; /* the logo's width */
    overflow: hidden;
}

Notice the structure. The @import statement at the first line ensures that the standard Portofino css is still used, while the lines that follow override only the part that takes case of the title/logo display.

The size and position of the logo on the screen will depend on the values shown in bold. Make sure you customize them to your needs.

Building the .war file

Let's check we have all the files in place.

$ find .
.
./pom.xml
./src
./src/main
./src/main/resources
./src/main/resources/portofino-custom.properties
./src/main/webapp
./src/main/webapp/mylogo.png
./src/main/webapp/mywebapp.css
./src/main/webapp/WEB-INF

Now run:

mvn package

Maven will run for a few seconds. At the end you should have a file in:

target/mywebapp.war

That's the final .war, containing all the customizations/configurations, that you can deploy or distribute.

Where to go next

No discussion of war overlays is complete without talking about profiles and filtering: this is the subject of the Using Maven profiles and resource filtering tutorial.
Maven can be employed in many useful situations. For a real life application see our tutorial Integrating Portofino with Alfresco.

The technique we've seen lays the basis for more serious customizations where you can extend the functionality of Portofino. This will be the subject of other tutorials. For now you can have a preview from the reference manual: