Tuesday, February 13, 2007

Generating a Site and Documentation in Maven

(this post is an excerpt from the upcoming book Java Power Tools... no reproductions without permission)

A perfectly designed project is meaningless without good documentation to back it up. No matter how well designed, without a path to lead new developers up to your stride you may as well write spaghetti code. Without documentation to explain to users how one goes about using your project it will never gain popularity beyond a small group of people (often the developers themselves... and perhaps their moms). Maven acknowledges this need and builds documentation generation as a cornerstone of a comprehensive software development management process.

Site project setup

Although any individual project can have its own site, oftentimes it is easier to manage a seperate site project. Our examples will assume a seperate site project, however, note that all of this information can just as easily apply to a project that contains code as well.

The simplest way to bootstrap any Maven development is by running an archetype.
mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-site \
-DarchetypeVersion=1.0 \
-DgroupId=com.mycompany \
-DartifactId=my-site

This will generate a sample Maven site project, which may be built by executing the site build lifecycle.
my-site
|-- pom.xml
`-- src
|-- site.xml
|-- site_fr.xml
`-- site
|-- apt
| |-- format.apt
| `-- index.apt
|-- fml
| `-- faq.fml
|-- xdoc
| `-- xdoc.xml
`-- fr
|-- apt
| |-- format.apt
| `-- index.apt
|-- fml
| `-- faq.fml
`-- xdoc
`-- xdoc.xml

The items to note in the above structure are the site.xml file and the directories under src/site: apt, fml and xdoc; each representing a document notation type. Finally, the site_fr.xml and src/site/fr sub directory contain a French language version of the documents, rounding out Maven's commitment to built-in internationalization. You must merely add the French language verion to the site plugin's configuration in the POM.
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<locales>en,fr</locales>
</configuration>
</plugin>
</plugins>
</build>
</project>

The Site Outline

The site.xml file is responsible for the structure of the site as a whole, defining the site's banners, the links (upper right-hand corner by default) and the left-hand side (LHS) menu. Note that links in the menu defined below have similar names to the documents above, yet end with .html. This is because each of the document markups are converted to HTML by the site plugin, more specifically, by Doxia.
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="Maven">
<bannerLeft>
<name>Maven</name>
<src>http://maven.apache.org/images/apache-maven-project.png</src>
<href>http://maven.apache.org/</href>
</bannerLeft>
<bannerRight>
<src>http://maven.apache.org/images/maven-small.gif</src>
</bannerRight>
<body>
<links>
<item name="Apache" href="http://www.apache.org/" />
<item name="Maven 1.0" href="http://maven.apache.org/"/>
<item name="Maven 2" href="http://maven.apache.org/maven2/"/>
</links>

<menu name="Maven 2.0">
<item name="APT Format" href="format.html"/>
<item name="FAQ" href="faq.html"/>
<item name="Xdoc Example" href="xdoc.html"/>
</menu>
</body>
</project>

The site phase can easily generate sites of different languages. All one need do is create a site descriptor file similar to the file above, yet suffix the file name with the language code of your choice. The archetype created a French language version for you, site_fr.xml. At this point Maven will look for a matching language directory under src/site and generate that documentation for an audience of that particular language (usually by a webbrowser's language settings). If no matching language is found the site.xml's language is the default (presumed to be English).

Doxia

The heart of the Maven site plugin is the Doxia project, which is a self-contained sub-project of Maven (Doxia). Doxia is responsible for converting your chosen document markup to the html that can be deployed to a website. Doxia also has the ability to convert a document from any supported markup to any other supported markup. It does this with and . A Doxia parser implements the org.apache.maven.doxia.parser.Parser Plexus role and is responsible for converting the implemented markup into a given sink. A Doxia sink implements the org.apache.maven.doxia.sink.Sink Plexus role and is any supported output, for example XHTML or PDF. This is important to know if you ever decided to write your own modules for Doxia to support.

APT

APT, or Almost Plain Text, can be considered the default documentation method for Maven projects. It is a simple wiki-like syntax that is easily converted to a Doxia sink. If you built the site generated by maven-archetype-site, navigate to target/site/format.html and you will be treated to a comprehensive guide for using APT. There is no need to reproduce it here.
Snippets
A useful feature of Doxia are snippets. Snippets are macros that are given a file and an id.
%{snippet|id=myID|file=some.file}

The macro will search the file for the comment START SNIPPET: myID and ending comment END SNIPPET: myID. For example, add the following to your POM:
<project>
...
<!-- START SNIPPET: props -->
<properties>
<my.prop>value</my.prop>
</properties>
<!-- END SNIPPET: props -->
</project>

And the following to your index.apt file.
%{snippet|id=props|file=pom.xml}

Run the site phase, and be amazed! Rather than "file", the snippet can also take a "url".

Hint: rather than running the site phase, try running the site:run goal. It will launch your documents under a web container accessible from port 8080 that will show your changes in real time.

FML

FML is FAQ Markup Language, and is specialized in creation the ubiquitous Frequently Asked Questions (FAQ) document. An example is as follows:
<faqs id="faqs1">
<part id="part1">
<faq id="faq1">
<question>What is a good question?</question>
<answer>
<p>Any valid XHTML can be placed in the <code>answer</code> element</p>
</answer>
</faq>
</part>
</faqs>

The FML document can have any number of parts, and each part may have any number of FAQs - each having one question and one answer. When the document is generated, it will place all questions at the top of the page as links, which anchor to the answer later in the page.


XDoc

XDoc is an XML markup for writing documents, and has been around since the early days of Maven 1 and Ant. It is similar to HTML, but document-centric with extra elements for sections and more constraints. All XDoc documents must be under the xdoc directory, with a .xml extension. Its support is mostly for historical reasons, and it is recommended to write new documentation in APT format.

Look and Feel

Changing Skins

Changing skins in Maven is easy. Just alter your POM, and viola! Your entire site's look and feel has been altered. Better yet, it is all consistent. To switch the my-site project to use the Stylus theme, alter the site.xml file ( the POM).
<project>
...
<skin>
<groupId>org.apache.maven</groupId>
<artifactId>maven-classic-skin</artifactId>
<version>1.0</version>
</skin>
</project>

The list of default skins available from Maven Central Repository are here http://repo1.maven.org/maven2/org/apache/maven/skins/. At the time of this article's writing, the list is:

  • maven-classic-skin

  • maven-default-skin

  • maven-stylus-skin


As you probably guessed, maven-default-skin is the default.

Creating your own skin

First, create a project with the following layout:
my-skin
|-- pom.xml
`-- src
`-- main
`-- resources
|-- css
| `-- maven-theme.css
`-- images

and a simple pom.xml.
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>my-skin</artifactId>
<version>1.0-SNAPSHOT</version>
</project>

The important file in a custom skin is the maven-theme.css. Also note the src/main/resource/images directory that allows you to add images into your CSS, accessible as "/images/my-image.ext". Most control of the css is via the basics like body or a, but there are a few important CSS ids generated by default

  • breadcrumbs - a sequence of data at the top of the page

  • leftColumn - represents the left column of the page

  • navcolumn - wraps the navigation elements in the left column

  • banner - contains the left and right banners defined in the site.xml

  • bodyColumn - wraps the contentBox of the page

  • contentBox - contains the main content of the page

  • footer - contains the data generated as a page footer

Velocity Manipulation

Skin manipulation is nice to change the look of your site, but in order to change the way the site is generated requires creating your own Velocity (.vm) file. Apache Velocity is a templating engine that has been around for years, has proven its metal in projects such as Apache Turbine, and is a simple method for allowing users to overwrite the default templates.

Rather than starting from scratch, it is far simpler to download the default default-site.vm file and manipulate it. The default renderer is available under the doxia-site-rendered project source code, available for download under the doxia project. Doxia is available from the subversion repository http://svn.apache.org/repos/asf/maven/doxia/trunk/
(if not found there, check the doxia website at http://maven.apache.org/doxia). From there, the doxia-site renderer project's resource contains the template, at doxia-site-renderer/src/main/resources/org/apache/maven/doxia/siterenderer/resources/default-site.vm. Copy this file to your project at src/site/my-site.vm, and point your my-site project's pom.xml to utilize it.
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<configuration>
<templateFile>src/site/my-site.vm</templateFile>
</configuration>
</plugin>
</plugins>
</build>
</project>

If you look at the my-site.vm, you will notice the XHTML and CSS generated by it. This gives you the power to alter the structure of your generated Maven site, as well as allow your custom skins more control than merely the default (perhaps by adding more spans, or more types of CSS classes).

Or, better yet, you can add the template to your skin, to src/main/resources/META-INF/maven/site.vm. This way, when a project uses your skin, they automatically use your template.

Distribution

The final step in site generation is publishing it to a location where a public webserver may access it. There is a special element in the distributionManagement element called site, which gives the location and method of distribution. In your my-site POM, you will notice the element has been added for you. Now you merely need to set it like any other Maven distribution. The example uses secure copy protocol (scp).
<project>
...
<distributionManagement>
<site>
<id>website</id>
<url>scp://webhost.company.com/www/website</url>
</site>
</distributionManagement>
</project>

With a suitable distribution set up, you merely run the site-deploy phase (which has bound to it the site:site.deploy goal).
mvn site-deploy

That's it! Maven will generate the documentation using your chosen template and skin, and copy those files to the specified location.

5 comments:

Anonymous said...

great post, many thanks !

there is a small bug in "changing skins":
groupId should be "org.apache.maven.skins" and NOT "org.apache.maven"

thanks for this text, it helped me a lot !

Tomek
http://kaczanowscy.pl/tomek

Sami Badawi said...

Hi Eric,

I followed your instructions on customizing the default-site.vm file, and was able to generate a custom site.
The site looks fine, but the menu on the left hand side does not work, and I got this build error:

[INFO] Velocimacro : initialization starting.
[INFO] Velocimacro : adding VMs from VM library template : VM_global_library.vm
[ERROR] ResourceManager : unable to find resource 'VM_global_library.vm' in any resource loader.
[INFO] Velocimacro : error using VM library template VM_global_library.vm : org.apache.velocity.exception.ResourceNotFoundException: Unable to find resource 'VM_global_library.vm'
[INFO] Velocimacro : VM library template macro registration complete.

Any suggestions would be helpful.

Thanks,
-Sami
http://samibadawi.blogspot.com

Eric said...

That error message actually has nothing to do with your customizations... you'll get that error in any case. It's just an annoying artifact of Maven's (lack of comprehensive) error handling.

That said, I don't know why it wouldn't work. I'd suggest you check out my book instead.

Sami Badawi said...

I found the problem, default-site.vm
newest revision, 595592, had a bug, while revision 573556 worked.

Maven is very powerful, but the documentation leaves a lot to be desired.
I have been using your Maven book for a while. That was the reason that I could use Maven site generator to build my little one man open source project site: www.shapelogic.org.

Do you know know how run the site builder without also generating the whole Javadoc each time?

Thanks you so much,
-Sami
http://samibadawi.blogspot.com

Martin Harrigan said...

Thank you for the article! If developing your own skin, it is sometimes useful to check out, say, one of the default skins from http://svn.apache.org/repos/asf/maven/skins to see how they are put together.