{"id":270,"date":"2026-10-13T06:11:42","date_gmt":"2026-10-13T06:11:42","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2010\/07\/12\/maven2-step-by-step\/"},"modified":"2026-10-13T06:11:42","modified_gmt":"2026-10-13T06:11:42","slug":"maven2-step-by-step","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/maven2-step-by-step\/","title":{"rendered":"Maven2 Web Application Setup: Legacy Step-by-Step Guide with Build, Jetty, and Site Reporting"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><em>Originally published on 2010-07-12; fully revised and updated.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide is for engineers maintaining or modernizing legacy Maven2-style Java web projects. You will learn how to bootstrap a project, switch to WAR packaging, run the core Maven lifecycle, use an in-place Jetty development loop, and generate project documentation and quality reports from <code>pom.xml<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2010\/07\/maven2-step-by-step.png\"><img decoding=\"async\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2010\/07\/maven2-step-by-step.png\" alt=\"maven2-step-by-step\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Create a Maven web application skeleton<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The original workflow starts from the Maven archetype flow described in the <a href=\"http:\/\/maven.apache.org\/guides\/getting-started\/index.html\">Maven Getting Started Guide<\/a>:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs language-bash\">mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-app<\/code><\/span><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Then add web and resource directories for a typical JSP\/Servlet style project:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs language-bash\">mkdir -p my-app\/src\/main\/webapps\/WEB-INF\nmkdir -p my-app\/src\/main\/resources\nmkdir -p my-app\/src\/test\/resources<\/code><\/span><\/pre>\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Path<\/th><th>Used in original post<\/th><th>Purpose<\/th><\/tr><\/thead><tbody><tr><td>src\/main\/webapps\/WEB-INF<\/td><td>Yes<\/td><td>Web app context and deployment descriptors<\/td><\/tr><tr><td>src\/main\/resources<\/td><td>Yes<\/td><td>Application resource files on classpath<\/td><\/tr><tr><td>src\/test\/resources<\/td><td>Yes<\/td><td>Test-only resource files<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">To produce a web archive instead of a JAR, change packaging from <code>jar<\/code> to <code>war<\/code>. The original post also configured the compiler for Java 1.5:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">packaging<\/span>&gt;<\/span>war<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">packaging<\/span>&gt;<\/span>\n\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">build<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">plugins<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">plugin<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.apache.maven.plugins<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>maven-compiler-plugin<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">configuration<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">source<\/span>&gt;<\/span>1.5<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">source<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">target<\/span>&gt;<\/span>1.5<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">target<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">configuration<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">plugin<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">plugins<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">build<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Core Maven goals you will use daily<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Command<\/th><th>What it does<\/th><th>Typical use<\/th><\/tr><\/thead><tbody><tr><td>mvn clean<\/td><td>Removes generated build output<\/td><td>Reset workspace before a fresh build<\/td><\/tr><tr><td>mvn compile<\/td><td>Compiles main Java sources<\/td><td>Quick compile check<\/td><\/tr><tr><td>mvn test-compile<\/td><td>Compiles test sources<\/td><td>Validate test code compiles<\/td><\/tr><tr><td>mvn test<\/td><td>Runs unit tests<\/td><td>Local validation before packaging<\/td><\/tr><tr><td>mvn package<\/td><td>Builds artifact (JAR\/WAR)<\/td><td>Create deployable output<\/td><\/tr><tr><td>mvn install<\/td><td>Installs artifact into local Maven repository<\/td><td>Make artifact available to local dependent builds<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\"><span class=\"hljs-comment\"># Common local build sequence<\/span>\nmvn clean test package<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">Run an in-place development loop with Jetty<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The original article uses the <a href=\"http:\/\/mojo.codehaus.org\/jetty-maven-plugin\/usage.html\">Maven2 Jetty Plugin<\/a> to run the app directly from source and shorten edit-build-run feedback cycles.<\/p>\n\n\n\n<pre class=\"mermaid\">\nflowchart LR\n    A[Create project] --> B[Add web directories]\n    B --> C[Set packaging to war]\n    C --> D[Run clean test package]\n    D --> E[Start Jetty]\n    E --> F[Open app in browser]\n    F --> G[Edit code]\n    G --> D\n    D --> H[Generate site reports]\n<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Legacy Jetty configuration snippet from the original workflow:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">plugin<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.mortbay.jetty<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>maven-jetty6-plugin<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">configuration<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">scanIntervalSeconds<\/span>&gt;<\/span>10<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">scanIntervalSeconds<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">configuration<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependencies<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.apache.geronimo.specs<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>geronimo-j2ee_1.4_spec<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">version<\/span>&gt;<\/span>1.0<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">version<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">scope<\/span>&gt;<\/span>provided<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">scope<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependencies<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">plugin<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css language-bash\"><span class=\"hljs-selector-tag\">mvn<\/span> <span class=\"hljs-selector-tag\">jetty6<\/span><span class=\"hljs-selector-pseudo\">:run<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Expected local URL in this setup: <code>http:\/\/localhost:8080\/my-app<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Generate IDE metadata from pom.xml<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The post highlights Maven-driven IDE metadata generation so source paths and dependencies come from the same POM definition.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css language-bash\"><span class=\"hljs-selector-tag\">mvn<\/span> <span class=\"hljs-selector-tag\">eclipse<\/span><span class=\"hljs-selector-pseudo\">:eclipse<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">It also notes setting <code>M2_REPO<\/code> in Eclipse to point to the local repository path (typically <code>~\/.m2\/repository<\/code>).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Build project documentation and reports with Maven Site<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Maven can generate a project site and reports from POM metadata and source docs. The original article references <a href=\"http:\/\/www.docbook.org\/\">DocBook<\/a>, <a href=\"http:\/\/maven.apache.org\/guides\/mini\/guide-apt-format.html\">APT (Almost Plain Text)<\/a>, and FML for FAQ content.<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs language-bash\">mkdir -p my-app\/src\/site\/apt\nmkdir -p my-app\/src\/site\/fml\nmkdir -p my-app\/src\/site\/resources\/images\ntouch my-app\/src\/site\/site.xml<\/code><\/span><\/pre>\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs language-bash\">mvn site<\/code><\/span><\/pre>\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Plugin<\/th><th>Role in reporting\/site<\/th><th>Standalone command<\/th><\/tr><\/thead><tbody><tr><td>maven-project-info-reports-plugin<\/td><td>Project metadata reports (dependencies, SCM, issue tracking, etc.)<\/td><td>Usually run via mvn site<\/td><\/tr><tr><td>maven-javadoc-plugin<\/td><td>API documentation generation<\/td><td>mvn javadoc:javadoc<\/td><\/tr><tr><td>maven-jxr-plugin<\/td><td>Cross-referenced source browsing<\/td><td>mvn jxr:jxr<\/td><\/tr><tr><td>maven-checkstyle-plugin<\/td><td>Code style reporting<\/td><td>mvn checkstyle:checkstyle<\/td><\/tr><tr><td>cobertura-maven-plugin<\/td><td>Test coverage reports<\/td><td>mvn cobertura:cobertura<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The original Cobertura notes mention that a <code>cobertura.ser<\/code> file may be left in the project root and can be removed with <code>mvn clean<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Original reference links<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"http:\/\/www.javaworld.com\/javaworld\/jw-05-2006\/jw-0529-maven.html\">The Maven 2 POM demystified<\/a><\/li><li><a href=\"http:\/\/www.javaworld.com\/javaworld\/jw-02-2006\/jw-0227-maven.html\">Get the most out of Maven2 site generation<\/a><\/li><li><a href=\"http:\/\/maven.apache.org\/maven-v4_0_0.xsd\">The Maven2 Schema<\/a><\/li><li><a href=\"http:\/\/www.mergere.com\/m2book_download.jsp\">Better Builds with Maven<\/a><\/li><li><a href=\"http:\/\/www.amazon.com\/gp\/product\/0596007507\">Maven : A Developer&#8217;s Notebook<\/a><\/li><li><a href=\"http:\/\/checkstyle.sourceforge.net\/\">Checkstyle<\/a><\/li><li><a href=\"http:\/\/cobertura.sourceforge.net\/\">Cobertura<\/a><\/li><li><a href=\"http:\/\/maven-plugins.sourceforge.net\/maven-cobertura-plugin\/\">Cobertura Maven plugin<\/a><\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Best practices and common pitfalls<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li>Treat this as a <strong>legacy Maven2 baseline<\/strong>; validate plugin goals and coordinates in your current Maven environment.<\/li><li>Keep build logic centralized in <code>pom.xml<\/code> so IDE, CI, packaging, and documentation use the same source of truth.<\/li><li>Run <code>mvn clean test<\/code> frequently to catch classpath and test breakage early.<\/li><li>If you rely on <code>mvn site<\/code>, keep reporting plugins intentionally curated to avoid noisy or stale reports.<\/li><li>Document your project conventions (directory layout, Java level, plugin set) in-repo so onboarding does not depend on tribal knowledge.<\/li><li>For deployment transport (Wagon and related flows), add explicit environment-specific documentation because the original post does not provide implementation detail.<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>A practical Maven2-era walkthrough for creating a Java web app, running core build goals, and generating docs and reports from pom.xml. This revision keeps the original workflow but adds structure, comparisons, and implementation-ready snippets.<\/p>\n","protected":false},"author":1,"featured_media":4451,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[29],"tags":[4325,161,4321,4323,4317,4319,4320,4322,359,4318,4324],"class_list":["post-270","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-maven","tag-about-maven2","tag-maven","tag-maven-2-introduction","tag-maven-2-tutorial","tag-maven2","tag-maven2-documentation","tag-maven2-getting-started-guide","tag-maven2-guide","tag-overview","tag-step-by-step","tag-what-is-maven-2"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/270","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=270"}],"version-history":[{"count":3,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/270\/revisions"}],"predecessor-version":[{"id":79098,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/270\/revisions\/79098"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/4451"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=270"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=270"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=270"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}