2008-11-20 6 views
40

J'ai un script groovy qui a besoin d'une bibliothèque dans un pot. Comment puis-je l'ajouter au classpath? Je veux que le script soit exécutable, donc j'utilise #!/usr/bin/env groovy en haut de mon script.Comment inclure des jars dans un script groovy?

+2

On dirait que cela a déjà été demandé: http://stackoverflow.com/questions/254385/how-do-i-auto-load-a-database-jar-in-groovy-without-using-the-cp- switch – timdisney

Répondre

30

Si vous avez vraiment vous pouvez également charger un fichier JAR à l'exécution avec:

this.getClass().classLoader.rootLoader.addURL(new File("file.jar").toURL()) 
+0

Heh, définitivement raté la section "Ajouter des choses au classpath" la première fois que j'ai lu ça. – timdisney

+0

Je n'arrivais pas à faire fonctionner ce classloader ... quelqu'un d'autre pouvait-il l'utiliser? – Zombies

+4

Il y a des limitations non couvertes dans la documentation lors de l'exécution avec un shebang (#!). Je les ai expliqué plus loin [bas] (http://stackoverflow.com/a/8945888/54396). @Zombies, la technique du chargeur de classe ne fonctionne que lorsque vous n'avez pas besoin d'importer des classes de ce fichier .jar. Les importations sont résolues avant l'exécution du script et l'importation du .jar – Patrick

4

Le même comme vous le feriez en Java.

Ceci est un exemple d'exécution d'un script de surveillance d'état MySQL. mysql.jar contient le connecteur MySQL que j'appelle du script status.groovy.

mysql.jar -cp groovy status.groovy CT1

20

Vous pouvez ajouter les pots à $ HOME/.groovy/lib

+0

fonctionne pour moi (en utilisant Groovy 2.1.2 avec Windows 7) – pinei

+0

C'est génial sauf si vous exécutez autant de processus Groovy que vous avez épuisé vos fichiers ouverts limite. –

10

Vous pouvez également essayer Groovy Grape. Il vous permet d'utiliser des annotations pour modifier le chemin de classe. C'est expérimental en ce moment, mais plutôt cool. Voir docs.groovy-lang.org/.../grape

44

Démarrer un script groovy avec #!/usr/bin/env groovy a une limitation très importante - Aucun argument supplémentaire ne peut être ajouté. Aucun classpath ne peut être configuré, pas d'exécution groovy avec define ou en debug. Ce n'est pas un problème groovy, mais une limitation dans la façon dont le tralala (#!) fonctionne - tous les arguments supplémentaires sont traités comme seul argument si #!/usr/bin/env groovy -d est révélateur /usr/bin/env pour exécuter la commande groovy -d Rathen puis groovy avec un argument de d.

Il existe une solution de contournement pour ce problème, qui consiste à amorcer groovy avec bash dans le script groovy.

#!/bin/bash                                         
//usr/bin/env groovy -cp extra.jar:spring.jar:etc.jar -d -Dlog4j.configuration=file:/etc/myapp/log4j.xml "$0" [email protected]; exit $? 

import org.springframework.class.from.jar 
//other groovy code 
println 'Hello' 

Toute la magie se produit dans les deux premières lignes. La première ligne nous indique qu'il s'agit d'un script bash. bash commence à courir et voit la première ligne. Dans bash# est pour les commentaires et // est réduit à / qui est le répertoire racine. Donc, bash va exécuter /usr/bin/env groovy -cp extra.jar:spring.jar:etc.jar -d -Dlog4j.configuration=file:/etc/myapp/log4j.xml "$0" [email protected] qui commence groovy avec tous nos arguments souhaités. Le "$0" est le chemin d'accès à notre script, et [email protected] sont les arguments. Maintenant, groovy s'exécute et il ignore les deux premières lignes et voit notre script groovy et puis revient à bash. bash puis quitte (exit $?1) avec le code d'état de groovy.

+0

Cela peut-il être fait avec un fichier de commandes Windows? – djangofan

+2

Astuce sympa - bien que cela ne semble pas fonctionner dans un shell Windows Cygwin, car la double barre oblique dans // usr/bin/env n'est pas réduite. – Henry

+0

Vraiment sympa astuce –

19

Ma façon préférée de faire cela est avec Groovy Grapes. Ceux-ci accèdent au référentiel central Maven, téléchargent le fichier jar référencé, puis le placent sur le classpath. Ensuite, vous pouvez utiliser la bibliothèque comme n'importe quelle autre bibliothèque. La syntaxe est très simple:

@Grab(group='com.google.collections', module='google-collections', version='1.0') 

Vous pouvez lire plus de détails here. Un avantage majeur ici est que vous n'avez pas besoin de distribuer vos dépendances lorsque vous distribuez votre script. Le seul inconvénient de cette méthode est que le Jar doit être dans le dépôt Maven.

+0

Lien brisé pour ici – Leo

3

En ajoutant à @Patrick sa réponse, qui m'a beaucoup aidé, j'ai récemment découvert une autre astuce.

Si vous ajoutez beaucoup de fichiers jars au classpath sur une seule ligne, les choses peuvent devenir illisibles.Mais vous pouvez faire ce qui suit!

#!/bin/bash 
//bin/true && OPTS="-cp blah.jar -Dmyopt=value" 
//bin/true && OPTS="$OPTS -Dmoreopts=value2" 
//usr/bin/env groovy $OPTS "$0" [email protected]; exit $? 

println "inside my groovy script" 

Laissez votre imagination sur la façon dont une ligne de commande complexe, vous pouvez décomposer cette façon en morceaux maniables

Maarten

3

Ci-dessous est une combinaison de Patrick's solution, Maarteen Boekhold's solution, et le commentaire de foozbar qui fonctionne avec Linux et Cygwin:

#!/bin/bash 
// 2>/dev/null; SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" 
// 2>/dev/null; OPTS="-cp $SCRIPT_DIR/lib/extra.jar:$SCRIPT_DIR/lib/spring.jar" 
// 2>/dev/null; OPTS="$OPTS -d" 
// 2>/dev/null; OPTS="$OPTS -Dlog4j.configuration=file:/etc/myapp/log4j.xml" 
// 2>/dev/null; exec groovy $OPTS "$0" "[email protected]"; exit $? 

import org.springframework.class.from.jar 
//other groovy code 
println 'Hello' 

Comment ça marche:Est un commentaire groovy valide, donc toutes les commandes bash sont ignorées par Groovy.

  • // renvoie une erreur, mais la sortie d'erreur est redirigée vers /dev/null et n'est donc pas affichée.
  • bash exécute des commandes après un point-virgule même si la commande précédente a échoué.
  • exec remplace le programme actuel dans le processus en cours sans forcer un nouveau processus. Ainsi, exécute groovy dans le processus de script original (ps montre le processus que le script plutôt que l'exécutable groovy)
  • La déclaration exit $? suivante exec groovy empêche bash d'essayer d'interpréter le reste du script comme un script bash, et conserve également le code de retour du script groovy. L'astuce de bash ci-dessus est plus pratique dans certains cas que the RootLoader trick parce que vous pouvez utiliser des instructions d'importation régulières dans le script. L'utilisation de l'astuce RootLoader vous oblige à charger toutes les classes en utilisant la réflexion. C'est très bien dans certaines situations (comme lorsque vous devez charger un pilote JDBC), mais gênant dans d'autres. Si vous savez que votre script ne sera jamais exécuté sur Cygwin, l'utilisation de la solution de Patrick ou de Maarteen entraînera probablement des performances légèrement meilleures, car elles évitent le surcoût lié à la génération et au rejet d'une erreur.

  • 1

    Si vous voulez utiliser tout de suite avant que les déclarations import il est possible comme ça :):

    // printEmployees.groovy 
    this.class.classLoader.rootLoader.addURL(
        new URL("file:///C:/app/Dustin/product/11.1.0/db_1/jdbc/lib/ojdbc6.jar")) 
    import groovy.sql.Sql 
    sql = Sql.newInstance("jdbc:oracle:thin:@localhost:1521:orcl", "hr", "hr", 
             "oracle.jdbc.pool.OracleDataSource") 
    sql.eachRow("SELECT employee_id, last_name, first_name FROM employees") 
    { 
        println "The employee's name is ${it.first_name} ${it.last_name}." 
    } 
    

    Pris de cette javaworld.com article.

    Questions connexes