{"id":268,"date":"2026-10-13T05:51:23","date_gmt":"2026-10-13T05:51:23","guid":{"rendered":"http:\/\/www.scmgalaxy.com\/tutorials\/2010\/07\/07\/clover-and-maven-working-with-distributed-applications\/"},"modified":"2026-10-13T05:51:23","modified_gmt":"2026-10-13T05:51:23","slug":"clover-and-maven-working-with-distributed-applications","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/clover-and-maven-working-with-distributed-applications\/","title":{"rendered":"Maven Clover for Distributed Java Applications: Instrument, Collect, and Aggregate Coverage"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><em>Originally published on 2010-07-07; fully revised and updated.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide explains how to use <strong>Maven Clover<\/strong> in a <strong>distributed test setup<\/strong>, where instrumented code runs on multiple servers instead of only on the build machine. It is useful for Java teams running integration or system tests remotely and needing a single, consolidated code coverage report.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This revision preserves the original workflow and legacy <code>clover2<\/code> Maven goals from the source post: configure Clover, build with instrumentation, deploy to test nodes, run tests, and generate coverage reports.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.devopsschool.com\/blog\/wp-content\/uploads\/2010\/07\/clover-and-maven-working-wi.png\" alt=\"clover-and-maven-working-with-distributed-applications\" width=\"600\" height=\"400\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Why distributed coverage needs extra steps<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In a local-only build, instrumentation, execution, and report generation all happen on one machine. In distributed testing, Clover data is split across remote servers, so you must move the right files at the right time.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Build machine creates Clover-instrumented artifacts and a Clover registry database file.<\/li><li>Test servers execute instrumented code and write runtime coverage recording files.<\/li><li>Coverage recording files must be copied back before generating the final report.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">End-to-end Clover workflow for distributed applications<\/h2>\n\n\n\n<pre class=\"mermaid\">\nflowchart TD\n    A[Configure Clover in Maven] --> B[Build instrumented artifacts]\n    B --> C[Deploy artifacts to test servers]\n    C --> D[Copy Clover registry DB to each test node]\n    D --> E[Run remote tests]\n    E --> F[Collect coverage recording files]\n    F --> G[Copy recordings to build machine]\n    G --> H[Generate aggregate Clover report]\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">1) Configure Clover in Maven<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Add the Clover plugin to your <code>pom.xml<\/code>. For multi-module projects, define it in the parent POM so all modules inherit a consistent setup.<\/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\">project<\/span>&gt;<\/span>\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>com.atlassian.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-clover2-plugin<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/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>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">project<\/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<p class=\"wp-block-paragraph\">The original workflow uses command-line goals for setup, aggregation, and report generation, so many teams keep plugin configuration minimal and drive execution from CI jobs.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2) Build all components with Clover enabled<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run the build with Clover instrumentation enabled:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" 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\">-U<\/span> <span class=\"hljs-selector-tag\">clover2<\/span><span class=\"hljs-selector-pseudo\">:setup<\/span> <span class=\"hljs-selector-tag\">package<\/span> <span class=\"hljs-selector-tag\">clover2<\/span><span class=\"hljs-selector-pseudo\">:aggregate<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><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 logs should show Clover loading, creating a database, and instrumenting source files.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-text\">&#91;INFO] Loaded <span class=\"hljs-keyword\">from<\/span>: ...\/clover<span class=\"hljs-number\">-2.6<\/span><span class=\"hljs-number\">.3<\/span>.jar\n&#91;INFO] Clover: Commercial License registered to ...\n&#91;INFO] Creating <span class=\"hljs-keyword\">new<\/span> database at <span class=\"hljs-string\">'...\/target\/clover\/clover.db'<\/span>.\n&#91;INFO] Processing files at <span class=\"hljs-number\">1.5<\/span> source level.\n&#91;INFO] Clover all over. Instrumented ... files (... package).<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">3) Deploy instrumented build and Clover registry to test servers<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Deploy the instrumented build as you normally deploy test artifacts. In addition, copy the Clover registry database (created during build, often referenced by Clover <code>initstring<\/code>) to each test server where instrumented code will run.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Deploy instrumented binaries to all test nodes.<\/li><li>Copy the Clover registry DB to the path expected at runtime.<\/li><li>Ensure the runtime user can read and write in that folder.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">The source article also documents Java policy permissions used in older secured JVM setups:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-text\">grant codeBase <span class=\"hljs-string\">\"file:\/path\/to\/clover.jar\"<\/span> {\n  permission java.util.PropertyPermission <span class=\"hljs-string\">\"*\"<\/span>, <span class=\"hljs-string\">\"read\"<\/span>;\n  permission java.io.FilePermission <span class=\"hljs-string\">\"&lt;&gt;\"<\/span>, <span class=\"hljs-string\">\"read, write\"<\/span>;\n  permission java.lang.RuntimePermission <span class=\"hljs-string\">\"shutdownHooks\"<\/span>;\n};<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Legacy server paths mentioned in the original process:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript language-bash\">%JAVA_HOME%<span class=\"hljs-regexp\">\/jre\/<\/span>lib\/security\n%JAVA_HOME%<span class=\"hljs-regexp\">\/jre\/<\/span>lib\/ext<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\">4) Run tests remotely and collect coverage recordings<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Run automated or manual tests as usual. While instrumented code executes, Clover writes coverage recording files near the registry DB. The original naming pattern is described as:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css language-text\"><span class=\"hljs-selector-tag\">xxx<\/span><span class=\"hljs-selector-class\">.dbHHHHHHH_TTTTTTTTTT<\/span>\n<span class=\"hljs-selector-tag\">clover<\/span><span class=\"hljs-selector-class\">.dbHHHHHHH_TTTTTTTTTT<\/span><span class=\"hljs-selector-class\">.1<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><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\">After test execution, copy all recording files from each remote node back to the build machine (to the expected initstring location) before report generation.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php language-bash\"><span class=\"hljs-comment\"># Example collection commands (adapt hostnames and paths)<\/span>\nscp test-node<span class=\"hljs-number\">-1<\/span>:\/opt\/app\/clover<span class=\"hljs-comment\">\/*.db* \/ci\/workspace\/coverage\/\nscp test-node-2:\/opt\/app\/clover\/*.db* \/ci\/workspace\/coverage\/\nscp test-node-3:\/opt\/app\/clover\/*.db* \/ci\/workspace\/coverage\/<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><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\">5) Generate and review the Clover report<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Once coverage recording files are centralized on the build machine, generate the report:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" 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\">clover2<\/span><span class=\"hljs-selector-pseudo\">:clover<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><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\">Review the generated coverage output and verify that all remote test runs contributed data. Missing node files typically lead to lower-than-expected coverage.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Maven goals used in this workflow<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Goal or phase<\/th><th>Purpose in pipeline<\/th><th>When to run<\/th><\/tr><\/thead><tbody><tr><td>clover2:setup<\/td><td>Prepare Clover instrumentation and registry data<\/td><td>Before compile\/package<\/td><\/tr><tr><td>package<\/td><td>Build instrumented artifacts<\/td><td>Build stage<\/td><\/tr><tr><td>clover2:aggregate<\/td><td>Aggregate Clover results across modules<\/td><td>After module builds<\/td><\/tr><tr><td>clover2:clover<\/td><td>Generate final coverage report<\/td><td>After collecting remote recordings<\/td><\/tr><\/tbody><\/table><\/figure>\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>Keep Clover configuration centralized in the parent POM for multi-module builds.<\/li><li>Use the same expected registry location between build and runtime environments.<\/li><li>Validate write permissions on the folder that stores Clover DB and recording files.<\/li><li>Collect recordings from <strong>every<\/strong> test node before generating reports.<\/li><li>Treat the policy and <code>jre\/lib\/ext<\/code> guidance as legacy and verify against your current JDK\/security model.<\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Learn a practical Clover + Maven workflow for distributed test environments. This walkthrough covers instrumentation, remote execution, coverage file collection, and final report generation.<\/p>\n","protected":false},"author":1,"featured_media":4444,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[29],"tags":[91,1045,4309,610,254,3357,4307,1122,4310,919,161,4308,593,1668,104],"class_list":["post-268","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-maven","tag-build","tag-clover","tag-clover-and-maven-working-with-distributed-applications","tag-code-coverage","tag-configure","tag-deploy","tag-distributed-applications","tag-guide","tag-how-clover-and-maven-works-with-distributed-applications","tag-instructions","tag-maven","tag-maven-clover-plugin","tag-process","tag-run","tag-tutorials"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/268","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=268"}],"version-history":[{"count":2,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/268\/revisions"}],"predecessor-version":[{"id":79096,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/268\/revisions\/79096"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media\/4444"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=268"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=268"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=268"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}