Petit focus sur 2 plugins Maven
- Olivier Lamy (https://olamy.blogspot.com/), qui est architecte open source et commiteur actif de moultes projets (je ne les citerai pas, il y en a trop… 😉 ) et qui travaille chez Talend,
- et Olivier Bazoud (https://blog.bazoud.com/) qui est architecte chez Ekino et également co-auteur du livre Spring Batch In Action aux éditions Manning.
Application Assembler Maven Plugin
Description
- *Nix,
- Windows NT
- Java Service Wrapper
Cas d’utilisation
- appassembler:assemble qui permet de créer une arborescence de fichiers comprenant des scripts de lancement de l’application ainsi que de toutes les dépendances nécessaires à son exécution.
- appassembler:create-repository qui permet de créer le répertoire contenant toutes les librairies nécessaires au bon fonctionnement de l’application.
- appassembler:generate-daemons qui permet de créer une arborescence de fichiers comprenant des scripts et des librairies à utiliser pour wrapper l’application dans un service via Java Service Wrapper.
Exemple
package fr.soat.maven.sample;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FooClass {
private static final Logger LOGGER = LoggerFactory.getLogger(FooClass.class);
public static void main(String[] args) {
LOGGER.info("this is FooClass sample");
}
}
Cet exemple a pour objectif de montrer, dans un premier temps, ce que génère le goal assemble puis, dans un second temps, le goal generate-daemons.
Pour ce faire, le pom.xml suivant sera utilisé :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.soat.maven.sample</groupId>
<artifactId>sample-assembler-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<projectBaseUri>${project.baseUri}</projectBaseUri>
<java.version>1.6</java.version>
<slf4j.version>1.6.4</slf4j.version>
<logback.version>1.0.0</logback.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
<daemons>
<daemon>
<id>mainService</id>
<mainClass>fr.soat.maven.sample.FooClass</mainClass>
<commandLineArguments>
<commandLineArgument>start</commandLineArgument>
</commandLineArguments>
<platforms>
<platform>jsw</platform>
</platforms>
<generatorConfigurations>
<generatorConfiguration>
<generator>jsw</generator>
<includes>
<include>linux-x86-32</include>
<include>linux-x86-64</include>
</includes>
</generatorConfiguration>
</generatorConfigurations>
</daemon>
</daemons>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<goals>
<goal>assemble</goal>
</goals>
</execution>
</executions>
<configuration>
<programs>
<program>
<mainClass>fr.soat.maven.sample.FooClass</mainClass>
<name>main</name>
</program>
</programs>
<binFileExtensions>
<unix>.sh</unix>
</binFileExtensions>
</configuration>
</plugin>
</plugins>
</build>
</project>
mvn package
On obtient :
Où le main.sh est le suivant :
#!/bin/sh
# ----------------------------------------------------------------------------
# Copyright 2001-2006 The Apache Software Foundation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ----------------------------------------------------------------------------
#
# Copyright (c) 2001-2006 The Apache Software Foundation. All rights
# reserved.
BASEDIR=`dirname $0`/..
BASEDIR=`(cd "$BASEDIR"; pwd)`
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
case "`uname`" in
CYGWIN*) cygwin=true ;;
Darwin*) darwin=true
if [ -z "$JAVA_VERSION" ] ; then
JAVA_VERSION="CurrentJDK"
else
echo "Using Java version: $JAVA_VERSION"
fi
if [ -z "$JAVA_HOME" ] ; then
JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Home
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ]
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ]
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# If a specific java binary isn't specified search for the standard 'java' binary
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD=`which java`
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly."
echo " We cannot execute $JAVACMD"
exit 1
fi
if [ -z "$REPO" ]
then
REPO="$BASEDIR"/repo
fi
CLASSPATH=$CLASSPATH_PREFIX:"$BASEDIR"/etc:"$REPO"/org/slf4j/slf4j-api/1.6.4/slf4j-api-1.6.4.jar:"$REPO"/ch/qos/logback/logback-classic/1.0.0/logback-classic-1.0.0.jar:"$REPO"/ch/qos/logback/logback-core/1.0.0/logback-core-1.0.0.jar:"$REPO"/fr/soat/maven/sample/sample-assembler-plugin/1.0-SNAPSHOT/sample-assembler-plugin-1.0-SNAPSHOT.jar
EXTRA_JVM_ARGUMENTS=""
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$CLASSPATH" ]
CLASSPATH=`cygpath --path --windows "$CLASSPATH"
[ -n "$JAVA_HOME" ]
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"
[ -n "$HOME" ]
HOME=`cygpath --path --windows "$HOME"`
[ -n "$BASEDIR" ]
BASEDIR=`cygpath --path --windows "$BASEDIR"`
[ -n "$REPO" ]
REPO=`cygpath --path --windows "$REPO"`
fi
exec "$JAVACMD" $JAVA_OPTS \
$EXTRA_JVM_ARGUMENTS \
-classpath "$CLASSPATH" \
-Dapp.name="main" \
-Dapp.pid="$$" \
-Dapp.repo="$REPO" \
-Dbasedir="$BASEDIR" \
fr.soat.maven.sample.FooClass \
"$@"
Après un rapide :
chmod +x target/appassembler/bin/main.sh
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.2</version>
<configuration>
<daemons>
<daemon>
<id>mainService</id>
<mainClass>fr.soat.maven.sample.FooClass</mainClass>
<commandLineArguments>
<commandLineArgument>start</commandLineArgument>
</commandLineArguments>
<platforms>
<platform>jsw</platform>
</platforms>
<generatorConfigurations>
<generatorConfiguration>
<generator>jsw</generator>
<includes>
<include>linux-x86-32</include>
<include>linux-x86-64</include>
</includes>
</generatorConfiguration>
</generatorConfigurations>
</daemon>
</daemons>
</configuration>
</plugin>
Ainsi, après l’exécution de la commande :
mvn appassembler:generate-daemons
on obtient :
chmod +x target/generated-resources/appassembler/jsw/mainService/bin/mainService
chmod +x target/generated-resources/appassembler/jsw/mainService/bin/wrapper-linux-x86-64
./target/generated-resources/appassembler/jsw/mainService/bin/mainService start
Qu’à cela ne tienne, si il manque le répertoire logs, il suffit de le créer…
wrapper.java.mainclass=org.tanukisoftware.wrapper.WrapperSimpleApp
set.default.REPO_DIR=repo
set.default.APP_BASE=.
# Java Classpath (include wrapper.jar) Add class path elements as
# needed starting from 1
wrapper.java.classpath.1=lib/wrapper.jar
wrapper.java.classpath.2=%REPO_DIR%/fr/soat/maven/sample/sample-assembler-plugin/1.0-SNAPSHOT/sample-assembler-plugin-1.0-SNAPSHOT.jar
wrapper.java.classpath.3=%REPO_DIR%/org/slf4j/slf4j-api/1.6.4/slf4j-api-1.6.4.jar
wrapper.java.classpath.4=%REPO_DIR%/ch/qos/logback/logback-classic/1.0.0/logback-classic-1.0.0.jar
wrapper.java.classpath.5=%REPO_DIR%/ch/qos/logback/logback-core/1.0.0/logback-core-1.0.0.jar
Il semble donc qu’il manque le répertoire repo où les librairies sont recherchées…
Qu’a cela ne tienne, la commande suivante :
mvn appassembler:appassembler:create-repository
Conclusion
Tomcat 7 Maven Plugin
Description
Cas d’utilisation
- tomcat7:deploy
- tomcat7:deploy-only
- tomcat7:exec-war
- tomcat7:exec-war-only
- tomcat7:run
- tomcat7:run-war
- tomcat7:run-war-only
- tomcat7:shutdown
Exemple
Maven Tomcat 7 Plugin
package fr.soat.maven.tomcat.sample;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Writer;
public class FooServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Writer out = resp.getWriter();
out.append("GET FooServlet successfully called...");
out.flush();
out.close();
}
}
pour le web.xml :
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://java.sun.com/xml/ns/javaee" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>FooServlet</servlet-name>
<servlet-class>fr.soat.maven.tomcat.sample.FooServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FooServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>fr.soat.maven.tomcat.sample</groupId>
<artifactId>sample-tomcat-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<projectBaseUri>${project.baseUri}</projectBaseUri>
<java.version>1.6</java.version>
<servlet-api.version>3.0-alpha-1</servlet-api.version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0-SNAPSHOT</version>
<executions>
<execution>
<id>tomcat-war-exec</id>
<goals>
<goal>exec-war</goal>
</goals>
<phase>package</phase>
<configuration>
<warRunDependencies>
<warRunDependency>
<dependency>
<groupId>fr.soat.maven.tomcat.sample</groupId>
<artifactId>sample-tomcat-plugin</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
</warRunDependency>
</warRunDependencies>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
On constate que le goal exec-war est associé à la phase package.
De ce fait, en exécutant la commande suivante :
mvn package
on obtient :
Ainsi, avec la commande suivante :
cd target
java -jar sample-tomcat-plugin-1.0-SNAPSHOT-war-exec.jar
il devient alors possible via notre navigateur préféré (à l’url suivante : https://localhost:8080/sample-tomcat-plugin/) d’obtenir la page suivante :
Maven Tomcat 7 Archetype
Ainsi, la commande :
mvn archetype:generate \
-DarchetypeGroupId=org.apache.tomcat.maven \
-DarchetypeArtifactId=tomcat-maven-archetype \
-DarchetypeVersion=2.0-SNAPSHOT \
-DarchetypeRepository=https://repository.apache.org/content/repositories/snapshots/
donne le résultat suivant :
- le module basic-api contient les interfaces pour le webservice REST
- le module basic-api-impl contient l’implémentation des webservices REST
- le module basic-webapp contient l’application web
- le module basic-webapp-exec permet de générer un jar exécutable embarquant l’application web ainsi que le nécessaire de tomcat pour le démarrer en standalone
- le module basic-webapp-it permet de lancer des tests Selenium sur l’application web démarrée au sein d’un Tomcat7
mvn install -Pchrome
Conclusion
Conclusion
Pour aller plus loin…
- Site officiel de l’archetype Maven Tomcat7 : https://tomcat.apache.org/maven-plugin-2.0-beta-1/archetype.html
- Site officiel du plugin Maven Tomcat7 : https://tomcat.apache.org/maven-plugin-2.0-SNAPSHOT/tomcat7-maven-plugin/
- Site officiel du plugin Maven AppAssembler : https://mojo.codehaus.org/appassembler/appassembler-maven-plugin/
- Blog d’Olivier Lamy : https://olamy.blogspot.com/