Is it possible to upload/download an entire directory and all of the sub-directories within it to/from a Nexus repository server?
In case you want to actually deploy a hierarchy of files, I hacked together a solution using GMaven (groovy embedded in maven).
Use the pom below, supply a few properties and hit mvn install.
The folder will be crawled and all files inside it will be deployed using an artifactId taken from the relative path. e.g.
Given the base folder
c:\a\b\c
the file
c:\a\b\c\def\ghi\jkl.mno
would have the artifactId def-ghi-jkl and the packaging mno, this can of course be changed to something else.
The repository info will be taken from the pom, so you need to supply a distributionManagement element in the pom.
Here it is (a lot of this code is taken from the deploy:deploy-file mojo):
<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</groupId>
<artifactId>folderdeployer</artifactId>
<packaging>jar</packaging>
<version>SNAPSHOT</version>
<properties>
<!-- This is where your artifacts are -->
<deploy.basefolder>c:\temp\stuff</deploy.basefolder>
<!-- This will be used as groupId -->
<deploy.groupId>my.groupid</deploy.groupId>
<!-- this will be used as version -->
<deploy.version>1.2.3</deploy.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
<executions>
<execution>
<id>deploy-files</id>
<phase>prepare-package</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
<![CDATA[
// read components from plexus container
def layout = session.lookup(
'org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout');
def repoFactory = session.lookup(
'org.apache.maven.artifact.repository.ArtifactRepositoryFactory');
def repository = repoFactory.createDeploymentArtifactRepository(
pom.distributionManagement.repository.id,
pom.distributionManagement.repository.url,
layout, true );
def localRepository = session.localRepository;
def helper =
session.lookup("org.apache.maven.project.MavenProjectHelper");
def afm = session.lookup(
'org.apache.maven.artifact.handler.manager.ArtifactHandlerManager');
def factory = new org.apache.maven.artifact.factory.DefaultArtifactFactory();
factory.class.getDeclaredField("artifactHandlerManager").accessible = true;
factory.artifactHandlerManager=afm;
def deployer = session.lookup(
'org.apache.maven.artifact.deployer.ArtifactDeployer');
// initialize properties
def baseFolder = new File(pom.properties['deploy.basefolder']);
def groupId = pom.properties['deploy.groupId'];
def version = pom.properties['deploy.version'];
// iterate over all files recursively
baseFolder.eachFileRecurse{
if(it.isDirectory())return;
// packaging = file.extension
def packaging = it.name.replaceAll( /.+\./ , '' );
// artifactId = file.relativePath.replace '/' , '-'
def artifactId = it.absolutePath
.replace(baseFolder.absolutePath, '')
.substring(1)
.replaceFirst( /\..*?$/ , '')
.replaceAll( /\W+/ , '-' );
def artifact =
factory.createBuildArtifact(
groupId, artifactId, version, packaging );
// create pom for artifact
def model = new org.apache.maven.model.Model();
model.setModelVersion( "4.0.0" );
model.setGroupId( groupId );
model.setArtifactId( artifactId );
model.setVersion( version );
model.setPackaging( packaging );
File pomFile = File.createTempFile( "mvndeploy", ".pom" );
pomFile.deleteOnExit();
fw = org.codehaus.plexus.util.WriterFactory.newXmlWriter( pomFile );
new org.apache.maven.model.io.xpp3.MavenXpp3Writer().write( fw, model );
org.apache.commons.io.IOUtils.closeQuietly( fw );
def metadata =
new org.apache.maven.project.artifact.ProjectArtifactMetadata(
artifact, pomFile );
artifact.addMetadata( metadata );
// deploy file
deployer.deploy(it, artifact, repository, localRepository );
}
]]>
</source>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
<id>your repo id here</id>
<url>scp://your.repo.url/here</url>
<layout>default</layout>
</repository>
</distributionManagement>
</project>
EDIT:
I elaborated on this on my blog
You can always zip the directory and ship it as a zip file.
the users of this folder can download it from Nexus and unzip using dependency:unpack.
Related
I have created the project using WSO2 Developer Studio. Under src/main/java I created the package com.training In that package the class UnzipFileMediator:
package com.training.mediators;
import org.apache.synapse.MessageContext;
import org.apache.synapse.mediators.AbstractMediator;
//Import another jar dependent jar
import com.test.Testing;
public class UnzipFileMediator extends AbstractMediator {
public boolean mediate(MessageContext context) {
// TODO Implement your mediation logic here
System.out.println("UnzipFile Mediation entered*****");
// Dependent JAR class
Testing t= new Testing();
t.sayHello();
return true;
}
}
In this project i have deployed another jar by using the following step
1. Right click on the project
2. Select configure build path
3. Select Java Build Path
4. Select Libraries
5.Click on Add External Jar. Then add the external jar called Hello
6. Hello Jar contain the class Testing
7. Above mentioned class import Dependent Testing class and create the `object and call the function as mentioned below.`
8.import com.test.Testing;
9. Its working fine here.
Now i am going to deploy it on WSO2ESB following are the step to creating the Jar file:
1. Right click on the project
2. Select Export
3. Select Runnable JAR File
4. Select the check box
Package Required libraries into generated JAR
6. JAR is created and available to deploy at WSO2ESB
I will deploy this jar into WSO2ESB below is the location:
1. <ESB_HOME>/repository/components/lib directory.
In the synapse configuration I call the class like this
<class name="samples.mediators.UnzipFileMediator"></class>
but when i try to call it.It generate the below error:
java.lang.NoClassDefFoundError: com/test/Testing
This is the dependent JAR file class as i mentioned above
Please guide me what i did wrong
You can simply put that dependent jar in lib directory. But make sure that two or more jars don't contain the same package (when it happens, class loading problems occur)
I would suggest that If you can make maven OSGi bundle this would be really easy. I will explain how to do it.
Step 1:
Create a maven-archetype-quickstart projet.You can generate this using this command.If you already installed Maven.
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Then create a package as you wish. As an example, it should be similar to this.
Step 2:
Then you need to modify you pom.xml similar to this.
<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/xsd/maven-4.0.0.xsd">
<version>1.0-SNAPSHOT</version>
<modelVersion>4.0.0</modelVersion>
<artifactId>com.training.mediators</artifactId>
<packaging>bundle</packaging>
<groupId>4.0.0</groupId>
<name>com.training.mediators</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.synapse</groupId>
<artifactId>synapse-core</artifactId>
<version>2.1.3-wso2v11</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>1.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Export-Package>
com.training.*
</Export-Package>
<Import-Package>
*,*;resolution:=optional
</Import-Package>
<Fragment-Host>synapse-core</Fragment-Host>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>wso2-maven2-repository</id>
<url>http://dist.wso2.org/maven2</url>
</repository>
<repository>
<id>apache-Incubating-repo</id>
<name>Maven Incubating Repository</name>
<url>http://people.apache.org/repo/m2-incubating-repository</url>
</repository>
<repository>
<id>apache-maven2-repo</id>
<name>Apache Maven2 Repository</name>
<url>http://repo1.maven.org/maven2/</url>
</repository>
<repository>
<id>wso2-nexus</id>
<name>WSO2 internal Repository</name>
<url>http://maven.wso2.org/nexus/content/groups/wso2-public/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>ignore</checksumPolicy>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>wso2-maven2-repository</id>
<url>http://dist.wso2.org/maven2</url>
</pluginRepository>
<pluginRepository>
<id>wso2-maven2-snapshot-repository</id>
<url>http://dist.wso2.org/snapshots/maven2</url>
</pluginRepository>
</pluginRepositories>
Here one important point is the export-package section you need to mention which sub packges are to export.
<Export-Package>
com.training.*
</Export-Package>
You don't need to import dependencies. Those things will be imported automatically.
Step 3:
Now it's time write your logic in your mediator class.
package com.training.mediators;
import org.apache.synapse.MessageContext;
import org.apache.synapse.mediators.AbstractMediator;
public class UnzipFileMediator extends AbstractMediator {
public boolean mediate(MessageContext context) {
// TODO Implement your mediation logic here
System.out.println("UnzipFile Mediation entered*****");
// Dependent JAR class
return true;
}
public String getType() {
return null;
}
public void setTraceState(int traceState) {
traceState = 0;
}
public int getTraceState() {
return 0;
}
}
Step 4:
type mvn clean package in the directory where your pom.xml file is located.
Then there will be generated a folder called target. In that folder, there should be *.jar file something similar to this: com.training.mediators-1.0-SNAPSHOT.jar.
Copy com.training.mediators-1.0-SNAPSHOT.jar to wso2esb-4.9.0/repository/components/dropins.
Restart ESB server.
Step 5:
Now you need to add an ESB configuration as you required. Here is sample
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
<sequence name="fault">
<makefault version="soap11">
<code value="tns:Receiver" xmlns:tns="http://www.w3.org/2003/05/soap-envelope"/>
<reason value="Mediation failed."/>
</makefault>
<send/>
</sequence>
<sequence name="main" onError="fault">
<in>
<class name="com.training.mediators.UnzipFileMediator"/>
<send>
<endpoint name="stockquote">
<address uri="http://localhost:9000/services/AdderService?wsdl"/>
</endpoint>
</send>
</in>
<out>
<send/>
</out>
</sequence>
I hope this will help :)
I am trying to test a simple custom plugin with custom lifecycle.
Here is my EchoMojo.java file:
package org.sonatype.mavenbook.plugins;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
/**
* Echos an object string to the output screen.
* #goal echo
* #execute lifecycle="custom-echo" phase="package"
*/
public class EchoMojo extends AbstractMojo
{
/**
* Any Object to print out.
* #parameter expression="${echo.message}" default-value="Hello World..."
*/
private Object message;
public void execute()
throws MojoExecutionException, MojoFailureException
{
getLog().info( message.toString() );
}
}
My pom.xml looks like this:
<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>org.sonatype.mavenbook.plugins</groupId>
<artifactId>echotest-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>1.0-SNAPSHOT</version>
<name>echotest-plugin Maven Mojo</name>
<url>http://maven.apache.org</url>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
I added this in my settings.xml:
<pluginGroups>
<pluginGroup>org.sonatype.mavenbook.plugins</pluginGroup>
</pluginGroups>
I created META-INF/maven/lifecycle.xml
<lifecycles>
<lifecycle>
<id>custom-echo</id>
<phases>
<phase>
<id>package</id>
<executions>
<execution>
<goals>
<goal>echo</goal>
</goals>
</execution>
</executions>
</phase>
</phases>
</lifecycle>
</lifecycles>
I have created META-INF/plexus/components.xml
<component-set>
<components>
<component>
<role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
<role-hint>custom-echo</role-hint>
<implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
<configuration>
<phases>
<package>org.sonatype.mavenbook.plugins:echotest-maven-plugin:echo</package>
</phases>
</configuration>
</component>
</components>
</component-set>
When i do mvn echotest:echo, I get "Build Sucessfull".
When i do mvn custom-echo, I get "[ERROR] Unknown lifecycle phase "custom-echo"."
All i wanted is to active my custom plugin when i execute "mvn custom-echo", where custom-echo is a custom lifecycle name
Can someone help me out please.
Im working on a large multi-module project which uses an internal framework as one of its dependencies. The framework version is set in the top level pom at the beginning of a project, and has to stay constant. If any submodule uses a different version, I want the build to fail.
Ive tried declaring the dependency as a single version:
<dependency>
<groupId>framework_snt</groupId>
<artifactId>SFP</artifactId>
<version>[6.1]</version>
<type>pom</type>
</dependency>
Ive tried using the enforcer plugin with banned dependencies:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.0.1</version>
<executions>
<execution>
<id>enforce-versions</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireJavaVersion>
<version>[1.6.0-21]</version>
</requireJavaVersion>
<requireMavenVersion>
<version>[3.0.3]</version>
</requireMavenVersion>
<bannedDependencies>
<excludes>
<exclude>framework_snt:SFP</exclude>
</excludes>
<includes>
<include>framework_snt:SFP:6.1.2</include>
</includes>
</bannedDependencies>
</rules>
</configuration>
</execution>
</executions>
</plugin>
Ive also tried adding the <DependencyConvergence/> tag as mentioned here, but none of these approaches work.
So given this top level pom fragment:
<project>
<groupId>glb</groupId>
<artifactId>GLB</artifactId>
<packaging>pom</packaging>
<name>Global</name>
<version>1.0</version>
........
<dependencies>
<dependency>
<groupId>framework_snt</groupId>
<artifactId>SFP</artifactId>
<version>[6.1.2]</version>
<type>pom</type>
</dependency>
</dependencies>
.....
</project>
And this (invalid) submmodule:
<project>
<groupId>glb</groupId>
<artifactId>CORE</artifactId>
<packaging>jar</packaging>
<name>Core</name>
<version>1.0</version>
<parent>
<groupId>glb</groupId>
<artifactId>GLB</artifactId>
<version>1.0</version>
</parent>
<dependencies>
<dependency>
<groupId>framework_snt</groupId>
<artifactId>SFP</artifactId>
<version>6.3</version>
<type>pom</type>
</dependency>
</dependencies>
</project>
how do I setup maven so the build will fail when using the child module above, but when I remove the tag <version>6.3</version> it succeeds (or I change the version to match the one from the top level pom?
Well after much search and trying stuff with various plugins and getting nowhere, I decided to write my own plugin to do conflict checking. Using the dependency:tree plugin source as a base I wrote the following:
/**
* Walks the dependency tree looking for anything marked as a conflict, and fails the build if one is found
* code ripped from the dependency:tree plugin
*
* #param rootNode
* the dependency tree root node to check
*
*/
private void checkForConflicts( DependencyNode rootNode ) throws MojoExecutionException
{
StringWriter writer = new StringWriter();
boolean conflicts=false;
// build the tree
DependencyNodeVisitor visitor = new SerializingDependencyNodeVisitor( writer, SerializingDependencyNodeVisitor.STANDARD_TOKENS);
visitor = new BuildingDependencyNodeVisitor( visitor );
rootNode.accept( visitor );
getLog().debug("Root: "+rootNode.toNodeString() );
DependencyNode node;
Artifact actual, conflict;
DependencyTreeInverseIterator iter = new DependencyTreeInverseIterator(rootNode);
while (iter.hasNext() )
{
node = (DependencyNode)iter.next();
if (node.getState() == DependencyNode.OMITTED_FOR_CONFLICT)
{
actual = node.getArtifact();
conflict = node.getRelatedArtifact();
getLog().debug("conflict node: " + node.toNodeString() );
getLog().debug("conflict with: "+conflict.toString() );
getLog().error(actual.getGroupId()+":"+actual.getArtifactId()+":"+actual.getType()+" Conflicting versions: "+actual.getVersion()+" and "+conflict.getVersion() );
conflicts=true;
}
}
if (conflicts)
throw new MojoExecutionException( "version conflict detected");
}
You can call this from your existing plugin using the following:
try
{
rootNode = dependencyTreeBuilder.buildDependencyTree( project, localRepository, artifactFactory, artifactMetadataSource, null, artifactCollector );
checkForConflicts( rootNode );
}
catch ( DependencyTreeBuilderException e)
{
throw new MojoExecutionException( "Cannot build project dependency tree", e);
}
Then in your plugin pom.xml, include dependencies from the existing dependency plugin source and your good to go.
This works for our project -- but if anyone knows a cleaner or better way, please let me know.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 8 years ago.
Improve this question
I am looking for source code for a complete application that uses the Webstart Maven Plugin.
Any ideas?
I tried the webstart plugin in a prrof of concept involving an embedded tomcat server. The plugin is bound to the package phase and takes a longtime to execute, I would recommend to invoke it manually from the command line. It generates a zip file in the target directory containing the jnlp file and all dependencies. This file can then be extraced and put on a webserver. The url in the pom should point to this path on the server. When started, the app runs a tomcat server on localhost port 8080 with a simple servlet that just returns the requested path as a string.
Let me know if this works for you.
Here is the pom of the project, the plugin configuration was mostly copied from the documentation here
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.jhorstmann</groupId>
<artifactId>EmbeddedTomcatWebstart</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>EmbeddedTomcatWebstart</name>
<url>http://localhost/jnlp/</url>
<organization>
<name>Organisation</name>
</organization>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<tomcat.version>7.0.6</tomcat.version>
</properties>
<repositories>
<repository>
<id>jboss</id>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
<repository>
<id>sonatype</id>
<url>http://oss.sonatype.org/content/repositories/releases/</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<archive>
<manifest>
<mainClass>net.jhorstmann.embeddedtomcat7.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo.webstart</groupId>
<artifactId>webstart-maven-plugin</artifactId>
<executions>
<execution>
<!-- bind to phase, I prefer to call it manualls -->
<phase>package</phase>
<goals>
<goal>jnlp-inline</goal> <!-- use jnlp, jnlp-inline or jnlp-single as appropriate -->
</goals>
</execution>
</executions>
<configuration>
<!--outputDirectory></outputDirectory--> <!-- not required?? -->
<!-- Set to true to exclude all transitive dependencies. Default is false. -->
<excludeTransitive>false</excludeTransitive>
<!-- The path where the libraries are stored within the jnlp structure. not required. by default the libraries are within the working directory -->
<libPath>lib</libPath>
<outputJarVersions>true</outputJarVersions>
<!-- [optional] transitive dependencies filter - if omitted, all transitive dependencies are included -->
<dependencies>
<!-- Note that only groupId and artifactId must be specified here. because of a limitation of the Include/ExcludesArtifactFilter -->
<!--
<includes>
<include>commons-logging:commons-logging</include>
<include>commons-cli:commons-cli</include>
</includes>
-->
<!--
<excludes>
<exclude></exclude>
<excludes>
-->
</dependencies>
<!--
<resourcesDirectory>${project.basedir}/src/main/jnlp/resources</resourcesDirectory>
-->
<!-- default value -->
<!-- JNLP generation -->
<jnlp>
<!-- default values -->
<!--inputTemplateResourcePath>${project.basedir}</inputTemplateResourcePath-->
<!--inputTemplate>src/main/jnlp/template.vm</inputTemplate--> <!-- relative to inputTemplateResourcePath -->
<outputFile>app.jnlp</outputFile> <!-- defaults to launch.jnlp -->
<!-- used to automatically identify the jar containing the main class. -->
<!-- this is perhaps going to change -->
<mainClass>net.jhorstmann.embeddedtomcat7.App</mainClass>
</jnlp>
<!-- SIGNING -->
<!-- defining this will automatically sign the jar and its dependencies, if necessary -->
<sign>
<keystore>${basedir}/keystore</keystore>
<keypass>password</keypass> <!-- we need to override passwords easily from the command line. ${keypass} -->
<storepass>password</storepass> <!-- ${storepass} -->
<!--storetype>fillme</storetype-->
<alias>EmbeddedTomcatWebstart</alias>
<!--validity>fillme</validity-->
<!-- only required for generating the keystore -->
<dnameCn>EmbeddedTomcatWebstart</dnameCn>
<dnameOu>Organisation Unit</dnameOu>
<dnameO>Organisation</dnameO>
<dnameL>Location</dnameL>
<dnameSt>State</dnameSt>
<dnameC>Country</dnameC>
<verify>true</verify> <!-- verify that the signing operation succeeded -->
<!-- KEYSTORE MANAGEMENT -->
<keystoreConfig>
<delete>true</delete> <!-- delete the keystore -->
<gen>true</gen> <!-- optional shortcut to generate the store. -->
</keystoreConfig>
</sign>
<!-- BUILDING PROCESS -->
<pack200>true</pack200>
<gzip>true</gzip> <!-- default force when pack200 false, true when pack200 selected ?? -->
<!-- causes a version attribute to be output in each jar resource element, optional, default is false -->
<outputJarVersions>false</outputJarVersions>
<!--install>false</install--> <!-- not yet supported -->
<verbose>true</verbose>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina</artifactId>
<version>${tomcat.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-coyote</artifactId>
<version>${tomcat.version}</version>
</dependency>
</dependencies>
</project>
Here is a custom template for the jnlp file placed at src/main/jnlp/template.vm, I can't remember why I needed that exactly:
<?xml version="1.0" encoding="utf-8"?>
<jnlp
spec="$jnlpspec"
codebase="$project.Url"
href="$outputFile">
<information>
<title>$project.Name</title>
<vendor>$project.Organization.Name</vendor>
<homepage href="$project.Url"/>
<description>$project.Description</description>
#if($offlineAllowed)
<offline-allowed/>
#end
</information>
#if($allPermissions)
<security>
<all-permissions/>
</security>
#end
<resources>
<j2se version="$j2seVersion"/>
$dependencies
</resources>
<application-desc main-class="$mainClass"/>
</jnlp>
This is the main class at src/main/java/net/jhorstmann/embeddedtomcat7/App.java
package net.jhorstmann.embeddedtomcat7;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Wrapper;
import org.apache.catalina.startup.Tomcat;
public class App {
public static void main(String[] args) throws LifecycleException, ServletException, IOException {
File tmpDir = new File(System.getProperty("java.io.tmpdir"));
File webappDir = new File(tmpDir, "embeddedtomcat7");
webappDir.mkdir();
final Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
tomcat.setBaseDir(tmpDir.getAbsolutePath());
tomcat.getConnector().setURIEncoding("UTF-8");
String contextPath = "/";
Context context = tomcat.addContext(contextPath, webappDir.getAbsolutePath());
Wrapper wrapper = tomcat.addServlet(contextPath, "Test", new TestServlet());
//Wrapper wrapper = tomcat.addServlet(contextPath, "Async", new AsyncServlet());
//wrapper.setAsyncSupported(true);
wrapper.addMapping("/*");
tomcat.start();
tomcat.getServer().await();
}
}
And finally a servlet at src/main/java/net/jhorstmann/embeddedtomcat7/TestServlet.java
package net.jhorstmann.embeddedtomcat7;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
PrintWriter writer = resp.getWriter();
writer.println("<h1>" + req.getPathInfo() + "</h1>");
writer.close();
}
}
A few notes on this plugin (it's documentation is horrible):
It won't use the template.vm file unless you specify it, like
<templateFilename>roll-gen-template.vm</templateFilename>
For creating a war:
If you want to use the JnlpDownloadServlet (the standard one java provides) to serve up the files instead of the above code (and have the plugin generate a working version.xml file for it to use, etc.), basically you need to create a new project of type war and target the jnlp-download-servlet goal (it doesn't seem to support creating a war with classes from the current pom project) then, instead of a single <jnlp> section, you'll have the <jnlpFiles> section instead, which can list multiple jar dependencies. You may need to modify your web.xml file as well.
http://www.mojohaus.org/webstart/webstart-maven-plugin/jnlp-mojos-overview.html has an example pom for
If you have additional comments feel free to edit this, it is a community wiki.
Does anybody know how to configure the maven findbugs plugin to output a summary of the bugs to the console (similar to the pmd plugin)?
At present findbugs:check just prints out how many bugs there are in total and I need to check the individual modules target/findbugs directory and each findbugs.xml file to fix the issues.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.0.1</version>
<configuration>
<xmlOutput>true</xmlOutput>
<xmlOutputDirectory>findbugsreports</xmlOutputDirectory>
<findbugsXmlOutput>true</findbugsXmlOutput>
<findbugsXmlOutputDirectory>target/site/findbugsreports</findbugsXmlOutputDirectory>
<debug>true</debug>
</configuration>
</plugin>
Ideally it would be good to get a summary report back on the command line. Any ideas?
I use this hack, based on maven-groovy-plugin:
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0-rc-5-SNAPSHOT</version>
<executions>
<execution>
<phase>prepare-package</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
def file = new File("${project.build.directory}/findbugsXml.xml")
if (!file.exists()) {
fail("Findbugs XML report is absent: " + file.getPath())
}
def xml = new XmlParser().parse(file)
def bugs = xml.BugInstance
def total = bugs.size()
if (total > 0) {
log.info("Total bugs: " + total)
for (i in 0..total-1) {
def bug = bugs[i]
log.info(
bug.LongMessage.text()
+ " " + bug.Class.'#classname'
+ " " + bug.Class.SourceLine.Message.text()
)
}
}
</source>
</configuration>
</execution>
</executions>
</plugin>
There isn't currently a means to do this using the standard plugin. You can create a plugin to read the findbugsChecks.xml and output the information you need though.
The code below will output the total bugs found and the bugs per package for any project with a findbugsChecks.xml in the output directory. You can configure the name of the file it reads by setting the findBugsChecks property on the configuration:
package name.seller.rich;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
* #goal stats
*/
public class FindbugsStatsMojo extends AbstractMojo {
/**
* Where to read the findbugs stats from
*
* #parameter expression="${findbugsChecks}"
* default-value="${project.build.directory}/findbugsCheck.xml"
*/
private File findbugsChecks;
/**
* Output the Findbus stats for the project to the console.
*/
public void execute() throws MojoExecutionException, MojoFailureException {
if (findbugsChecks != null && findbugsChecks.exists()) {
try {
Xpp3Dom dom = Xpp3DomBuilder.build(new FileReader(
findbugsChecks));
// get the summary and output it
Xpp3Dom summaryDom = dom.getChild("FindBugsSummary");
// output any information needed
getLog().info(
"Total bug count:"
+ summaryDom.getAttribute("total_bugs"));
Xpp3Dom[] packageDoms = summaryDom.getChildren("PackageStats");
getLog().info(packageDoms.length + " package(s)");
for (int i = 0; i < packageDoms.length; i++) {
String info = new StringBuilder().append("package ")
.append(packageDoms[i].getAttribute("package"))
.append(": types:").append(
packageDoms[i].getAttribute("total_types"))
.append(", bugs:").append(
packageDoms[i].getAttribute("total_bugs"))
.toString();
getLog().info(info);
}
} catch (FileNotFoundException e) {
throw new MojoExecutionException(
"Findbugs checks file missing", e);
} catch (XmlPullParserException e) {
throw new MojoExecutionException(
"Unable to parse Findbugs checks file", e);
} catch (IOException e) {
throw new MojoExecutionException(
"Unable to read Findbugs checks file", e);
}
}
}
}
To package this code, add it to the src/main/java folder of a Mavenproject with a POM like this:
<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>name.seller.rich</groupId>
<artifactId>maven-findbugs-stats-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>0.0.1</version>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
</project>
Then run mvn install to install the plugin.
To actually use it, you can run it as an additional goal on the command line, or bind it to your project to run as part of the standard lifecycle.
Here's the command to run from the commandline (assuming the project has previously been compiled:
mvn findbugs:check name.seller.rich:maven-findbugs-stats-plugin:0.0.1:stats
To bind the configurations to your project so it will be run on each build, use the following configuration:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>check</id>
<phase>package</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<xmlOutput>true</xmlOutput>
<xmlOutputDirectory>findbugsreports</xmlOutputDirectory>
<findbugsXmlOutput>true</findbugsXmlOutput>
<findbugsXmlOutputDirectory>${findbugsOutputDirectory}</findbugsXmlOutputDirectory>
<debug>true</debug>
<failOnError>false</failOnError>
</configuration>
</plugin>
<plugin>
<groupId>name.seller.rich</groupId>
<artifactId>maven-findbugs-stats-plugin</artifactId>
<executions>
<execution>
<id>stats</id>
<phase>package</phase>
<goals>
<goal>stats</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Following along from the concepts above I have raised this issue on the maven findbugs issue tracker. http://jira.codehaus.org/browse/MFINDBUGS-118. I have also coded and submitted a patch that shows total bugs for each project. It could easily be modified to get other details.
The code ignores projects specified as producing POM outputs and also ignores projects whose POMs specify true in their findbugs configuration. We are running a large multi-module maven build with the patch applied.
With the patch applied you run mvn findbugs:check and you get something like the following output (output obfuscated to protect the guilty :):
[INFO] Summary
[INFO] -------
[INFO] C:\PATH\Abstraction\PalDefinitions\target/findbugsXml.xml 4
[INFO] C:\PATH\System\target/findbugsXml.xml 19
[INFO] C:\PATH\ApplicationLayer\target/findbugsXml.xml 13
[INFO] C:\PATH\Support\ServiceStub\target/findbugsXml.xml 11
[INFO] C:\PATH\Support\MultiPlatform\target/findbugsXml.xml 10
[INFO] C:\PATH\Support\Serializer\target/findbugsXml.xml 19
[INFO] C:\PATH\Support\Brander\target/findbugsXml.xml 19
[INFO] C:\PATH\PlatformAbstraction\Pal1\target/findbugsXml.xml 8
[INFO] C:\PATH\PlatformAbstraction\Pal2\target/findbugsXml.xml 0
[INFO] C:\PATH\PlatformAbstraction\Pal3\target/findbugsXml.xml 0
[INFO] C:\PATH\PlatformAbstraction\Pal4\target/findbugsXml.xml 0
[INFO] C:\PATH\Framework\Common\target/findbugsXml.xml 12
[INFO] C:\PATH\Framework\legacyFramework\target/findbugsXml.xml 7
[INFO] C:\PATH\Framework\UIFramework\target/findbugsXml.xml 7
[INFO] C:\PATH\ExecutionLayer\Stub\target/findbugsXml.xml 0
[INFO] C:\PATH\ExecutionLayer\BB\BB\target/findbugsXml.xml 1
[INFO] TOTAL = 130
[INFO] -------
[INFO] Number of bugs 130 falls BELOW summaryThreshold 260. Check OK
You can do this with Violations Maven Plugin. It is configured with patterns to identify report files on the filesystem. It needs to run after findbugs, or any other static code analysis tool.
It will
Print the violations in the build log.
Optionally fail the build if number of violations found is higher then a configured number.