Le plugin fournit des capacités de déploiement d'applications Web à un conteneur Web Tomcat intégré dans une version Gradle donnée. Il étend le plugin de guerre. Pour le moment, les versions Tomcat 6.0.x, 7.0.x, 8.0.x, 8.5.x et 9.0.x sont prises en charge.
Le cas d'utilisation typique de ce plugin est de prendre en charge le déploiement pendant le développement. Le plugin permet un développement rapide d'applications Web en raison des temps de démarrage rapides du conteneur. Gradle commence le conteneur intégré dans le même JVM. Actuellement, le conteneur ne peut pas être fourchu comme un processus distinct. Ce plugin ne peut pas non plus déployer un fichier de guerre dans un conteneur distant. Si vous recherchez cette capacité, veuillez jeter un œil au plugin de cargaison à la place.
Pour utiliser les fonctionnalités du plugin, vous devrez ajouter son artefact binaire au chemin de classe de votre script de build et appliquer le plugin.
Le pot de plugin doit être défini dans le chemin de classe de votre script de construction. Il est directement disponible sur le portail du plugin Gradle. L'extrait de code suivant montre un exemple sur la façon de le récupérer:
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath ' com.bmuschko:gradle-tomcat-plugin:2.7.0 '
}
}Le fichier JAR est livré avec deux plugins:
| Identifiant de plugin | Dépend de | Taper | Description |
|---|---|---|---|
| com.bmuschko.tomcat-base | - | Tomcatbaseplugin | Fournit des types de tâches personnalisés Tomcat, pré-configures ClassPath. |
| com.bmuschko.tomcat | com.bmuschko.tomcat-base | Tomcatplugine | Fournit des tâches pour démarrer et arrêter un conteneur Tomcat intégré et expose une extension nommée tomcat . |
Le plugin com.bmuschko.tomcat vous aide à démarrer rapidement. Si vous allez bien si les tâches préconfigurées, c'est l'option préférable. La plupart des utilisateurs de plugins iront avec cette option. Pour utiliser le plugin Tomcat, incluez l'extrait de code suivant dans votre script de construction:
apply plugin: 'com.bmuschko.tomcat'
Si vous avez besoin d'un contrôle total sur vos tâches ou si vous ne souhaitez pas accompagner les tâches préconfigurées, vous voudrez utiliser le plugin com.bmuschko.tomcat-base . Cela pourrait être le cas si vous souhaitez configurer le conteneur uniquement pour les tests fonctionnels. L'inconvénient est que chaque tâche doit être configurée individuellement dans votre script de construction. Pour utiliser le plugin de base Tomcat, incluez l'extrait de code suivant dans votre script de construction:
apply plugin: 'com.bmuschko.tomcat-base'
De plus, les bibliothèques d'exécution TomCat doivent être ajoutées à la configuration tomcat . À l'heure actuelle, les versions Tomcat 6.0.x, 7.0.x, 8.0.x, 8.5.x et 9.0.x sont prises en charge par le plugin. Assurez-vous de ne pas mélanger les bibliothèques Tomcat de différentes versions.
Tomcat 6.0.x:
repositories {
mavenCentral()
}
dependencies {
def tomcatVersion = ' 6.0.51 '
tomcat " org.apache.tomcat:catalina: ${ tomcatVersion } " ,
" org.apache.tomcat:coyote: ${ tomcatVersion } " ,
" org.apache.tomcat:jasper: ${ tomcatVersion } "
}Tomcat 7.0.x:
repositories {
mavenCentral()
}
dependencies {
def tomcatVersion = ' 7.0.76 '
tomcat " org.apache.tomcat.embed:tomcat-embed-core: ${ tomcatVersion } " ,
" org.apache.tomcat.embed:tomcat-embed-logging-juli: ${ tomcatVersion } " ,
" org.apache.tomcat.embed:tomcat-embed-jasper: ${ tomcatVersion } "
}Tomcat 8.0.x:
repositories {
mavenCentral()
}
dependencies {
def tomcatVersion = ' 8.0.42 '
tomcat " org.apache.tomcat.embed:tomcat-embed-core: ${ tomcatVersion } " ,
" org.apache.tomcat.embed:tomcat-embed-logging-juli: ${ tomcatVersion } " ,
" org.apache.tomcat.embed:tomcat-embed-jasper: ${ tomcatVersion } "
}Tomcat 8.5.x:
Veuillez noter que la dépendance tomcat-embed-logging-juli n'est requise que pour activer la journalisation des conteneurs via Log4j 1.x (qui n'est plus pris en charge par la communauté log4j). Log4j 2.x peut être utilisé pour la journalisation des conteneurs sans déclarer de bibliothèques supplémentaires.
repositories {
mavenCentral()
}
dependencies {
def tomcatVersion = ' 8.5.16 '
tomcat " org.apache.tomcat.embed:tomcat-embed-core: ${ tomcatVersion } " ,
" org.apache.tomcat.embed:tomcat-embed-logging-juli:8.5.2 " ,
" org.apache.tomcat.embed:tomcat-embed-jasper: ${ tomcatVersion } "
}
tomcat {
httpProtocol = ' org.apache.coyote.http11.Http11Nio2Protocol '
ajpProtocol = ' org.apache.coyote.ajp.AjpNio2Protocol '
}Tomcat 9.0.x:
Veuillez noter que la dépendance tomcat-embed-logging-juli n'est requise que pour activer la journalisation des conteneurs via Log4j 1.x (qui n'est plus pris en charge par la communauté log4j). Log4j 2.x peut être utilisé pour la journalisation des conteneurs sans déclarer de bibliothèques supplémentaires.
repositories {
mavenCentral()
}
dependencies {
def tomcatVersion = ' 9.0.1 '
tomcat " org.apache.tomcat.embed:tomcat-embed-core: ${ tomcatVersion } " ,
" org.apache.tomcat.embed:tomcat-embed-logging-juli:9.0.0.M6 " ,
" org.apache.tomcat.embed:tomcat-embed-jasper: ${ tomcatVersion } "
}
tomcat {
httpProtocol = ' org.apache.coyote.http11.Http11Nio2Protocol '
ajpProtocol = ' org.apache.coyote.ajp.AjpNio2Protocol '
} Le plugin com.bmuschko.tomcat prédéfinit les tâches suivantes hors de la boîte:
| Nom de tâche | Dépend de | Taper | Description |
|---|---|---|---|
| tomcatrun | - | Tomcatrun | Démarre une instance Tomcat et déplace l'application Web explosée. |
| tomcatrunwar | - | Tomcatrunwar | Démarre une instance Tomcat et déploie la guerre. |
| tomcatstop | - | Tomcatstop | Arrête l'instance Tomcat. |
| tomcatjasper | - | Tomcatjasper | Exécute le compilateur JSP et transforme les pages JSP en source Java à l'aide de Jasper. |
Le plugin Tomcat utilise la même disposition que le plugin de guerre.
Le plugin Tomcat expose les propriétés suivantes via l'extension nommée tomcat :
httpPort : Le port TCP sur lequel Tomcat doit écouter les demandes HTTP (par défaut en 8080 ).httpsPort : le port TCP sur lequel Tomcat doit écouter les demandes HTTPS (par défaut à 8443 ).ajpPort : le port TCP sur lequel Tomcat doit écouter les demandes AJP (par défaut à 8009 ).stopPort : le port TCP sur lequel Tomcat doit écouter les demandes d'administration (par défaut en 8081 ).stopKey : la clé à passer à Tomcat lorsque vous demandez de s'arrêter (par défaut, null ).contextPath : le chemin de contexte de l'URL sous lequel l'application Web sera enregistrée (par défaut, nom de la guerre).enableSSL : détermine si le connecteur HTTPS doit être créé (par défaut est false ).daemon : Spécifie si le serveur Tomcat doit s'exécuter en arrière-plan. Lorsque cela est vrai, cette tâche se termine dès le début du serveur. Lorsqu'il est faux, cette tâche bloque jusqu'à ce que le serveur Tomcat soit arrêté (par défaut est false ).keystoreFile : le fichier de clés à utiliser pour SSL, s'il est activé (par défaut, un stage de clés sera généré).httpProtocol : le nom de classe du gestionnaire de protocole HTTP à utiliser (par défaut sur org.apache.coyote.http11.Http11Protocol ).httpsProtocol : le nom de classe du gestionnaire de protocole HTTPS à utiliser (par défaut, org.apache.coyote.http11.Http11Protocol ).ajpProtocol : le nom de classe du gestionnaire de protocole AJP à utiliser (par défaut sur org.apache.coyote.ajp.AjpProtocol ).users : Liste des utilisateurs avec username , password et roles . Utilisé pour configurer TomCat avec l'authentification de base avec ces utilisateurs. L'exemple de code suivant montre comment modifier les ports par défaut HTTP / HTTPS. Pour activer SSL, nous définissons la propriété enableSSL sur true . L'application Web sera accessible dans le cadre de l' sample-app chemin de contexte.
tomcat {
httpPort = 8090
httpsPort = 8091
enableSSL = true
contextPath = ' sample-app '
users {
user {
username = ' user1 '
password = ' 123456 '
roles = [ ' developers ' , ' admin ' ]
}
user {
username = ' user2 '
password = ' abcdef '
roles = [ ' manager ' ]
}
}
}De plus, vous pouvez définir les propriétés de tâche optionnelles suivantes:
contextPath : le chemin de contexte de l'URL dans lequel votre application Web sera enregistrée (par défaut, nom du nom de guerre).webDefaultXml : le web par défaut.xml. S'il n'est pas défini, une instance d' org.apache.catalina.servlets.DefaultServlet et org.apache.jasper.servlet.JspServlet sera configurée.additionalRuntimeResources : définit des pots d'exécution ou des répertoires supplémentaires qui ne sont pas fournis par l'application Web.URIEncoding : Spécifie le codage des caractères utilisé pour décoder les octets URI par le connecteur HTTP (par défaut vers UTF-8 ).daemon : Spécifie si le serveur Tomcat doit s'exécuter en arrière-plan. Lorsque cela est vrai, cette tâche se termine dès le début du serveur. Lorsqu'il est faux, cette tâche bloque jusqu'à ce que le serveur Tomcat soit arrêté (par défaut est false ).configFile : le chemin du fichier XML de contexte Tomcat (par défaut vers src/main/webapp/META-INF/context.xml pour tomcatRun , par défaut META-INF/context.xml dans la guerre pour tomcatRunWar ).outputFile : le fichier pour écrire des messages de journal Tomcat. Si le fichier existe déjà de nouveaux messages seront ajoutés.reloadable : Force la numérisation du contexte si vous n'utilisez pas de fichier de contexte (par défaut est true ).keystorePass : le mot de passe de la clé à utiliser pour SSL, s'il est activé.truststoreFile : le fichier TrustStore à utiliser pour SSL, si activé.truststorePass : le mot de passe TrustStore à utiliser pour SSL, si activé.clientAuth : le paramètre ClientAuth à utiliser, les valeurs peuvent être: true , false ou want (par défaut est false ). Remarque: keystoreFile et truststoreFile nécessitent chacun une instance d'un fichier File EG file("/path/my.file")
Dans l'exemple de code suivant, nous déclarons un fichier de contexte personnalisé pour la tâche tomcatRun .
tomcatRun . configFile = file( ' context.xml ' ) Pour configurer la tâche du compilateur Jasper, vous pouvez choisir de définir les propriétés suivantes dans la fermeture jasper de l'extension tomcat :
validateXml : détermine si web.xml doit être validé (par défaut, null ).validateTld : détermine si web.xml doit être validé (par défaut, null ).uriroot : le répertoire de racine d'application Web (par défaut à src/main/webapp ).webXmlFragment : le fichier de fragments web xml généré à référencer par votre fichier web.xml .addWebXmlMappings : Ajoutez automatiquement le fragment XML Web généré au fichier web.xml . ATTENTION: Cela modifiera le fichier web.xml dans le projet, pas le répertoire de construction.outputDir : Le répertoire de sortie dans lequel les JSP compilés se termineront (par défaut à build/jasper ).classdebuginfo : si le fichier de classe est compilé avec des informations de débogage (par défaut est true ).compiler : quelle fourmi compilateur doit utiliser pour compiler les pages JSP. Voir la documentation ANT pour plus d'informations. Si la valeur n'est pas définie, le compilateur JAVA ECLIPSE JDT par défaut sera utilisé au lieu d'utiliser Ant. Aucune valeur par défaut.compilerSourceVM : quelle version jdk est les fichiers source compatibles (par défaut est 1.6 ).compilerTargetVM : quelle version jdk est les fichiers générés compatibles avec (par défaut à 1.6 ).poolingEnabled : Détermine si le regroupement du gestionnaire de balises est activé. Il s'agit d'une option de compilation. Il ne modifiera pas le comportement des JSP qui ont déjà été compilés (par défaut, c'est true ).errorOnUseBeanInvalidClassAttribute : Si Jasper émet une erreur lorsque la valeur de l'attribut de classe dans une action UseBean n'est pas une classe de bean valide (par défaut est true ).genStringAsCharArray : Si les chaînes de texte devraient être générées sous forme de tableaux de char, pour améliorer les performances dans certains cas (par défaut, false ).ieClassId : la valeur de classe-ID à envoyer à Internet Explorer lors de l'utilisation de balises <jsp:plugin> (par défaut à clsid:8AD9C840-044E-11D1-B3E9-00805F499D93 ).javaEncoding : Encodage de fichiers Java à utiliser pour générer des fichiers source Java (par défaut vers UTF8 ).trimSpaces : Les espaces blancs dans le texte du modèle entre les actions ou les directives sont coupés (par défaut à TrimSpaces.TRUE ).xpoweredBy : détermine si l'en-tête de réponse X-propulsé par X est ajouté par servlet généré (par défaut est false ).tomcat {
jasper {
validateXml = true
webXmlFragment = file( " $w ebAppDir /WEB-INF/generated_web.xml " )
outputDir = file( " $w ebAppDir /WEB-INF/src " )
}
}J'obtiens une exception de compilation lors de l'appel d'un JSP. Y a-t-il quelque chose qui me manque?
L'exception que vous pourriez voir est probablement similaire à celle-ci: org.apache.jasper.JasperException: Unable to compile class for JSP . Tomcat 7.x et 8.x vous oblige à avoir Eclipse ECJ 3.6.x dans votre ClassPath. Cependant, cette version de la dépendance n'existe pas dans Maven Central. Vous devrez télécharger cette dépendance et la mettre dans votre propre référentiel ou définir un référentiel sur votre disque local où vous pouvez le déposer. Voici un exemple:
repositories {
flatDir name : ' localRepository ' , dirs : ' lib '
} Pourquoi ai-je un java.lang.ClassCastException sur javax.servlet.Servlet ?
Tomcat est très sensible à avoir plusieurs versions des dépendances javax.servlet:servlet-api et javax.servlet:jsp-api dans son chemin de classe. Par défaut, ils sont déjà retirés en tant que dépendances transitives des bibliothèques Tomcat intégrées. L'exception que vous pourriez voir ressemble à celle-ci:
java.lang.ClassCastException: org.springframework.web.servlet.DispatcherServlet cannot be cast to javax.servlet.Servlet
at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1062)
at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1010)
at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4935)
at org.apache.catalina.core.StandardContext$3.call(StandardContext.java:5262)
at org.apache.catalina.core.StandardContext$3.call(StandardContext.java:5257)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Pour résoudre ce problème, assurez-vous de définir vos dépendances JSP et des modules de servlet avec la portée providedCompile comme celle-ci:
providedCompile ' javax.servlet:servlet-api:2.5 ' ,
' javax.servlet:jsp-api:2.0 'Comment puis-je déboguer à distance que mon Tomcat a commencé par le plugin?
Si vous souhaitez pouvoir déboguer à distance votre application, vous devez définir les options JVM suivantes dans votre variable d'environnement GRADLE_OPTS avant de démarrer le conteneur. Le numéro de port que vous choisissez dépend de vous.
-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
Tomcat écoutera ensuite sur le port spécifié pour les connexions de débogage à distance entrantes. Lorsque vous démarrez le conteneur, vous devriez voir le message suivant:
Listening for transport dt_socket at address: 5005
Vérifiez votre documentation IDE sur la façon de configurer la connexion au port de débogage distant.
Mon conteneur Tomcat doit utiliser une source de données JNDI. Comment configurer mon projet?
Tout d'abord, vous devez vous assurer de déclarer la dépendance au pool de connexion à l'aide de la configuration tomcat .
Tomcat 6.0.x:
def tomcatVersion = ' 6.0.35 '
tomcat " org.apache.tomcat:dbcp: ${ tomcatVersion } "Voir coordonnées sur Maven Central pour plus de détails.
Versions ultérieures:
def tomcatVersion = ' 9.0.8 '
tomcat " org.apache.tomcat:tomcat-dbcp: ${ tomcatVersion } "Voir coordonnées sur Maven Central pour plus de détails.
Si vous décidez d'aller avec les paramètres par défaut, placez votre context.xml dans le répertoire src/main/webapp/META-INF . Pour définir un emplacement personnalisé, vous pouvez utiliser la configFile de la propriété Convention. Voici un exemple sur la façon de le définir pour les tâches tomcatRun et tomcatRunWar .
[tomcatRun, tomcatRunWar] * . configFile = file( ' context.xml ' )Veuillez vous référer à la documentation Tomcat pour une liste des attributs de contexte. L'exemple suivant montre comment configurer une source de données MySQL JNDI.
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< Context >
< Resource name = " jdbc/mydatabase "
auth = " Container "
type = " javax.sql.DataSource "
username = " superuser "
password = " secretpasswd "
driverClassName = " com.mysql.jdbc.Driver "
url = " jdbc:mysql://localhost:3306/mydb "
validationQuery = " select 1 "
maxActive = " 10 "
maxIdle = " 4 " />
</ Context >Comment utiliser le déploiement de code chaud avec le plugin?
Le plugin fournit une prise en charge prête à l'emploi pour échanger le code d'octets via la propriété reloadable . Par défaut, cette option est avérée afin que vous n'ayez pas besoin de modifications de configuration supplémentaires. Tout ce que vous avez à faire est d'avoir une instance de course du conteneur initié par tomcatRun . Allumez votre éditeur préféré, modifiez un fichier source de production, enregistrez-le et recompilez vos sources dans un autre terminal via gradle compileJava . Après quelques secondes, le contexte est rechargé et vous devriez voir le comportement reflété dans la fenêtre de terminal exécutant le conteneur:
Reloading Context with name [/myapp] has started
Reloading Context with name [/myapp] is completed
Alternativement, vous pouvez utiliser d'autres technologies de swap de code d'octets commerciales. La configuration est généralement spécifique au produit. Veuillez vous référer à la documentation du produit sur la façon de le configurer pour votre projet. La section suivante décrit comment configurer Gradle et le plugin avec Jrebel. Tout d'abord, téléchargez Jrebel, installez-le sur votre machine et configurez la licence. Pour dire à Jrebel quel répertoire scrutant un code d'octet modifié, vous devez créer un fichier rebel.xml. Dans votre module Web, placez le fichier sous build/classes/main afin qu'il puisse être chargé par le plugin Tomcat. Pour créer la configuration du fichier, le plugin Gradle Jrebel est utile. Il n'est pas nécessaire d'utiliser le plugin. Vous pouvez également décider de créer la configuration à la main. Gardez à l'esprit que gradle clean supprimera le fichier. Pour la configuration de Jrebel dans un scénario de projet multi-modules, veuillez vous référer à la documentation. L'extrait de code suivant montre un exemple de fichier rebel.xml .
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< application xmlns : xsi = " http://www.w3.org/2001/XMLSchema-instance " xmlns = " http://www.zeroturnaround.com "
xsi : schemaLocation = " http://www.zeroturnaround.com http://www.zeroturnaround.com/alderaan/rebel-2_0.xsd " >
< classpath >
< dir name = " /Users/ben/dev/projects/mywebproject/build/classes/main " >
</ dir >
</ classpath >
< web >
< link target = " / " >
< dir name = " /Users/ben/dev/projects/mywebproject/src/main/webapp " >
</ dir >
</ link >
</ web >
</ application > Modifiez votre script de démarrage Gradle et ajoutez-y la ligne suivante pour dire à Gradle d'utiliser l'agent Jrebel. Veuillez vous assurer de définir la variable d'environnement REBEL_HOME qui pointe vers votre répertoire d'installation Jrebel.
JAVA_OPTS="-javaagent:$REBEL_HOME/jrebel.jar $JAVA_OPTS"
Au démarrage de votre module Web à l'aide de gradle tomcatRun vous devriez voir des informations sur la licence Jrebel utilisée et les répertoires analysés pour les modifications. Pour notre exemple de fichier rebel.xml , cela ressemblerait à ceci:
JRebel: Directory '/Users/ben/dev/projects/mywebproject/build/classes/main' will be monitored for changes.
JRebel: Directory '/Users/ben/dev/projects/mywebproject/src/main/webapp' will be monitored for changes.
Si un fichier a été recompilé, Jrebel l'indique en l'écrivant dans la console comme ceci:
JRebel: Reloading class 'de.muschko.web.controller.TestController'.
Besoin de réaliser des tests d'intégration en contact avec la partie dans le cadre de ma construction. Que faut-il faire?
Habituellement, les tests d'unité et d'intégration sont maintenus séparés par convention. Une convention pourrait être de nommer les fichiers source de test différemment, par exemple, les tests d'intégration se terminent toujours avec le suffixe IntegrationTest , les fichiers de test unitaires se terminent par Test . En faisant cela, vous pouvez les exécuter séparément. Pour exécuter les tests d'intégration, vous voudrez exécuter la tâche Tomcat en tant que thread de démon et l'arrêter une fois vos tests terminés. L'exemple suivant montre comment configurer une tâche Gradle qui fournit cette fonctionnalité. Bien sûr, ce n'est qu'une façon de le faire. L'exemple suivant nécessite Gradle> = 1,7:
apply plugin : ' com.bmuschko.tomcat-base '
ext {
tomcatStopPort = 8081
tomcatStopKey = ' stopKey '
}
task integrationTomcatRun( type : com.bmuschko.gradle.tomcat.tasks.TomcatRun ) {
stopPort = tomcatStopPort
stopKey = tomcatStopKey
daemon = true
}
task integrationTomcatStop( type : com.bmuschko.gradle.tomcat.tasks.TomcatStop ) {
stopPort = tomcatStopPort
stopKey = tomcatStopKey
}
task integrationTest( type : Test ) {
include ' **/*IntegrationTest.* '
dependsOn integrationTomcatRun
finalizedBy integrationTomcatStop
}
test {
exclude ' **/*IntegrationTest.* '
}Comment ajouter des fichiers JAR ou des répertoires qui ne font pas partie de mon code source d'application Web?
Chaque tâche de type AbstractTomcatRun expose une propriété nommée additionalRuntimeResources qui est utilisée pour mélange avec le chemin de classe d'exécution de l'application Web.
[tomcatRun, tomcatRunWar] . each { task ->
task . additionalRuntimeResources << file( ' /Users/bmuschko/config/props ' )
task . additionalRuntimeResources << file( ' /Users/bmuschko/ext/jars/my.jar ' )
}