Posso aggiungere i jar a maven 2 build classpath senza installarli?

Maven2 mi sta facendo impazzire durante la sperimentazione / fase di simulazione rapida e sporca dello sviluppo.

Ho un file pom.xml che definisce le dipendenze per il framework di app web che voglio utilizzare e posso generare rapidamente progetti di avviamento da quel file. Tuttavia, a volte voglio collegarmi a una libreria di terze parti che non ha già un file pom.xml definito, quindi piuttosto che creare pom.xml file pom.xml per la lib di terze parti e installarlo, e aggiungere la dipendenza a mio pom.xml , vorrei solo dire a Maven: “Oltre alle mie dipendenze definite, includi anche tutti i jar che sono in /lib .”

Sembra che questo dovrebbe essere semplice, ma se lo è, mi manca qualcosa.

Ogni suggerimento su come farlo è molto apprezzato. In breve, se c’è un modo semplice per indirizzare Maven in una directory /lib e creare facilmente un pom.xml con tutti i jar racchiusi in una singola dipendenza che potrei quindi nominare / installare e colbind in un colpo solo. anche sufficiente

Problemi di approcci popolari

La maggior parte delle risposte che troverete su Internet suggeriscono di installare la dipendenza nel repository locale o specificare un ambito “sistema” nel pom e distribuire la dipendenza con l’origine del progetto. Ma entrambe queste soluzioni sono in realtà difettose.

Perché non si dovrebbe applicare l’approccio “Installa all’archivio locale”

Quando installi una dipendenza nel tuo repository locale, rimane lì. Il tuo artefatto di distribuzione andrà bene fino a quando avrà accesso a questo repository. Il problema è che nella maggior parte dei casi questo repository risiede sul tuo computer locale, quindi non ci sarà modo di risolvere questa dipendenza da nessun altro computer. Evitare chiaramente che il tuo artefatto dipenda da una macchina specifica non è un modo per gestire le cose. Altrimenti questa dipendenza dovrà essere installata localmente su ogni macchina che lavora con quel progetto che non è migliore.

Perché non si dovrebbe applicare l’approccio “Scopo del sistema”

I barattoli da cui si dipende con l’approccio “System Scope” non vengono installati su alcun repository o collegati ai pacchetti di destinazione. Ecco perché il tuo pacchetto di distribuzione non avrà un modo per risolvere tale dipendenza quando usato. Questo credo sia stato il motivo per cui l’uso dell’ambito del sistema è diventato deprecato. Ad ogni modo non vuoi fare affidamento su una funzione deprecata.

La soluzione di repository statico in-project

Dopo pom nel tuo pom :

  repo  true ignore   false  file://${project.basedir}/repo  

per ogni artefatto con un id di gruppo di forma xyz Maven includerà la seguente posizione all’interno della directory del progetto nella sua ricerca di artefatti:

 repo/ | - x/ | | - y/ | | | - z/ | | | | - ${artifactId}/ | | | | | - ${version}/ | | | | | | - ${artifactId}-${version}.jar 

Per approfondire questo argomento puoi leggere questo post sul blog .

Usa Maven per installare sul repository di progetto

Invece di creare questa struttura a mano consiglio di usare un plugin Maven per installare i tuoi vasi come artefatti. Quindi, per installare un artefatto in un repository all’interno del progetto, eseguire la cartella Repo:

 mvn install:install-file -DlocalRepositoryPath=repo -DcreateChecksum=true -Dpackaging=jar -Dfile=[your-jar] -DgroupId=[...] -DartifactId=[...] -Dversion=[...] 

Se scegli questo approccio, sarai in grado di semplificare la dichiarazione del repository in pom a:

  repo file://${project.basedir}/repo  

Una sceneggiatura di aiuto

Dal momento che eseguire il comando di installazione per ogni lib è un po ‘fastidioso e decisamente sobject a errori, ho creato uno script di utilità che installa automaticamente tutti i jar da una cartella di lib in un repository di progetto, risolvendo automaticamente tutti i metadati (groupId, artefatto e così via). dai nomi dei file. Lo script stampa anche le dipendenze xml affinché tu possa copiare e incollare nel tuo pom .

Includere le dipendenze nel pacchetto di destinazione

Quando avrai creato il tuo repository nel progetto avrai risolto il problema di distribuire le dipendenze del progetto con la sua fonte, ma da quel momento l’artefatto del tuo progetto dipenderà da giare non pubblicati, quindi quando installi in un repository avrà dipendenze irrisolvibili.

Per superare questo problema suggerisco di includere queste dipendenze nel pacchetto di destinazione. Questo puoi fare sia con il plug-in Assembly che con il plug-in OneJar . La documentazione ufficiale su OneJar è facile da comprendere.

Solo per buttare via il codice

imposta scope == system e crea un groupId, artefatto e versione

  org.swinglabs swingx 0.9.2 system ${project.basedir}/lib/swingx-0.9.3.jar  

Nota: le dipendenze del sistema non vengono copiate nel file jar / war risultante
(vedi Come includere le dipendenze di sistema in war create usando Maven )

Puoi creare un repository locale sul tuo progetto

Ad esempio se hai una cartella libs nella struttura del progetto

  • Nella cartella libs dovresti creare una struttura di directory come: /groupId/artifactId/version/artifactId-version.jar

  • Nel tuo pom.xml dovresti registrare il repository

      ProjectRepo ProjectRepo file://${project.basedir}/libs  
  • e aggiungi la dipendenza come al solito

      groupId artifactId version  

Questo è tutto.

Per informazioni dettagliate: Come aggiungere librerie esterne in Maven

Nota: quando si utilizza l’ambito del sistema ( come indicato in questa pagina ), Maven richiede percorsi assoluti.

Se i tuoi vasi sono sotto la radice del tuo progetto, vorrai anteporre i tuoi valori systemPath a $ {basedir}.

Dovresti davvero avere un quadro in atto tramite un repository e identificare le tue dipendenze in anticipo. Usare l’ambito del sistema è un errore comune che le persone usano, perché “non si preoccupano della gestione delle dipendenze”. Il guaio è che facendo questo ti ritroverai con una build pervertita di esperti che non mostrerà esperti in condizioni normali. Faresti meglio a seguire un approccio come questo .

Questo è quello che ho fatto, funziona anche sul problema del pacchetto e funziona con il codice estratto.

Ho creato una nuova cartella nel progetto nel mio caso ho usato il repo , ma sentitevi liberi di usare src/repo

Nel mio POM ho avuto una dipendenza che non è in nessun repository pubblico di Maven

  com.dovetail zoslog4j 1.0.1 runtime  

Ho quindi creato le seguenti directory repo/com/dovetail/zoslog4j/1.0.1 e repo/com/dovetail/zoslog4j/1.0.1 copiato il file JAR in quella cartella.

Ho creato il seguente file POM per rappresentare il file scaricato (questo passaggio è facoltativo, ma rimuove un AVVISO) e aiuta il prossimo a capire dove ho avuto il file per cominciare.

   4.0.0 com.dovetail zoslog4j jar 1.0.1 z/OS Log4J Appenders http://dovetail.com/downloads/misc/index.html Apache Log4j Appender for z/OS Logstreams, files, etc.  

Due file opzionali che creo sono i checksum SHA1 per POM e JAR per rimuovere gli avvisi di checksum mancanti.

 shasum -b < repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.jar \ > repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.jar.sha1 shasum -b < repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.pom \ > repo/com/dovetail/zoslog4j/1.0.1/zoslog4j-1.0.1.pom.sha1 

Infine aggiungo il seguente frammento al mio pom.xml che mi consente di fare riferimento al repository locale

   project file:///${basedir}/repo   

Il plug-in di installazione di Maven ha l’uso della riga di comando per installare un jar nel repository locale, POM è facoltativo ma dovrai specificare GroupId, ArtifactId, Version e Packaging (tutte le cose POM).

Questo è il modo in cui aggiungiamo o installiamo un jar locale

   org.example iamajar 1.0 system ${project.basedir}/lib/iamajar.jar  

ho dato alcuni groupId e artefatto di default perché sono obbligatori 🙂

L’uso di system è una pessima idea per ragioni spiegate da altri, l’installazione manuale del file nel repository locale rende la build non riproducibile e l’utilizzo del file://${project.basedir}/repo non è una buona idea perché (1) potrebbe non essere un URL di file ben formato (ad esempio se il progetto è estratto in una directory con caratteri insoliti), (2) il risultato è inutilizzabile se il POM di questo progetto è usato come dipendenza del progetto di qualcun altro.

Supponendo che tu non voglia caricare l’artefatto in un repository pubblico, il suggerimento di Simeon su un modulo helper fa il lavoro. Ma ora c’è un modo più semplice …

La raccomandazione

Utilizza il plugin non-maven-jar-maven . Fa esattamente quello che stavi chiedendo, con nessuno degli inconvenienti degli altri approcci.

Ho trovato un altro modo per farlo, vedi qui da un post Heroku

Per riassumere (mi dispiace per alcuni copia e incolla)

  • Creare una directory di repo nella cartella principale:
 ProgettoUtente
 + - pom.xml
 + - src
 + - repo
  • Esegui questa operazione per installare il jar nella directory repo locale
 mvn deploy: deploy-file -Durl = file: /// percorso / a / tuoproject / repo / -Dfile = mylib-1.0.jar -DgroupId = com.example -DartifactId = mylib -Dpackaging = jar -Dversion = 1.0
  • Aggiungi questo tuo pom.xml :
    project.local project file:${project.basedir}/repo    com.example mylib 1.0  

Dopo aver discusso molto a lungo con CloudBees sulla confezione corretta di questo tipo di JAR, hanno fatto una proposta interessante per una soluzione:

Creazione di un falso progetto Maven che allega un JAR preesistente come un artefatto principale, eseguendo l’installazione POM appartenuta: installazione del file di installazione. Ecco un esempio di tale kinf di POM:

     org.apache.maven.plugins maven-install-plugin 2.3.1   image-util-id install  install-file   ${basedir}/file-you-want-to-include.jar ${project.groupId} ${project.artifactId} ${project.version} jar       

Ma per implementarlo, la struttura del progetto esistente dovrebbe essere cambiata. Innanzitutto, dovresti avere in mente che per ogni tipo di JAR di questo tipo dovrebbe essere creato un falso progetto Maven (modulo) falso. E dovrebbe essere creato un progetto Maven padre che includa tutti i sottomoduli che sono: tutti i wrapper JAR e il progetto principale esistente. La struttura potrebbe essere:

progetto root (questo contiene il file POM padre include tutti i sottomoduli con l’elemento XML del modulo ) (confezione POM)

JAR 1 wrapper Progetto figlio Maven (confezione POM)

JAR 2 wrapper Progetto figlio Maven (confezione POM)

principale progetto figlio Maven esistente (confezione WAR, JAR, EAR ….)

Quando genitore è in esecuzione tramite mvn: install o mvn: l’imballaggio è forzato e i sottomoduli verranno eseguiti. Ciò potrebbe essere preoccupante come un negativo qui, poiché la struttura del progetto dovrebbe essere cambiata, ma alla fine offre una soluzione non statica

Il problema con systemPath è che i vasi delle dipendenze non vengono distribuiti lungo le risorse come dipendenze transitive. Prova cosa ho postato qui: è meglio Mavenize i tuoi file jar di progetto o metterli in WEB-INF / lib?

Quindi dichiarare le dipendenze come al solito.

E per favore leggi la nota del footer.

Se si desidera una soluzione rapida e sporca, è ansible fare quanto segue (anche se non lo consiglio per nulla, tranne i progetti di test, Maven si lamenterà di quanto non sia corretto).

Aggiungi una voce di dipendenza per ogni file jar di cui hai bisogno, preferibilmente con uno script perl o qualcosa di simile e copia / incolla quello nel tuo file pom.

 #! /usr/bin/perl foreach my $n (@ARGV) { [email protected]*/@@; print " local.dummy $n 0.0.1 system \${project.basedir}/lib/$n  "; 

Una soluzione batch rapida e sporca (basata sulla risposta di Alex):

libs.bat

 @ECHO OFF FOR %%I IN (*.jar) DO ( echo ^ echo ^local.dummy^ echo ^%%I^ echo ^0.0.1^ echo ^system^ echo ^${project.basedir}/lib/%%I^ echo ^ ) 

Esegui in questo modo: libs.bat > libs.txt . Quindi apri libs.txt e copia il suo contenuto come dipendenze.

Nel mio caso, avevo solo bisogno delle librerie per compilare il mio codice, e questa soluzione era la migliore per quello scopo.

Una strana soluzione che ho trovato:

usando Eclipse

  • creare un progetto java semplice (non-maven)
  • aggiungi una class principale
  • aggiungi tutti i vasi al classpath
  • export Runnable JAR (è importante, perché non c’è altro modo per farlo)
  • selezionare Estrai le librerie richieste nel JAR generato
  • decidere i problemi di licenza
  • tadammm … installa il barattolo generato sul tuo m2repo
  • aggiungi questa singola dipendenza agli altri tuoi progetti.

evviva, Balint

Anche se non si adatta perfettamente al tuo problema, lo lascerò qui. I miei requisiti erano:

  1. I vasi che non possono essere trovati in un repository online di Maven dovrebbero essere nella SVN.
  2. Se uno sviluppatore aggiunge un’altra libreria, gli altri sviluppatori non dovrebbero preoccuparsi di installarli manualmente.
  3. L’IDE (NetBeans nel mio caso) dovrebbe essere in grado di trovare i sorgenti e javadoc per fornire completamento automatico e aiuto.

Parliamo prima di (3): avere i vasi in una cartella e in qualche modo unirli nel jar finale non funzionerà qui, poiché l’IDE non lo capirà. Ciò significa che tutte le librerie devono essere installate correttamente. Tuttavia, non voglio che tutti lo installino usando “mvn install-file”.

Nel mio progetto avevo bisogno di metawidget. Eccoci qui:

  1. Crea un nuovo progetto di maven (chiamalo “shared-libs” o qualcosa di simile).
  2. Scarica metawidget ed estrai lo zip in src / main / lib.
  3. La cartella doc / api contiene i javadocs. Crea un file zip del contenuto (doc / api / api.zip).
  4. Modifica il pom come questo
  5. Costruisci il progetto e la libreria verrà installata.
  6. Aggiungi la libreria come dipendenza al tuo progetto o (se hai aggiunto la dipendenza nel progetto shared-libs) aggiungi shared-libs come dipendenza per ottenere tutte le librerie in una volta.

Ogni volta che si ha una nuova libreria, basta aggiungere una nuova esecuzione e dire a tutti di ribuild il progetto (è ansible migliorare questo processo con le gerarchie del progetto).

Quello che sembra più semplice per me è configurare il tuo plugin per il compilatore di maven per includere i tuoi vasetti personalizzati. Questo esempio carica tutti i file jar in una directory lib.

   org.apache.maven.plugins maven-compiler-plugin   lib/*.jar    

Per installare il jar di terze parti che non si trova nel repository di Maven usa maven-install-plugin.

Di seguito sono riportati i passaggi:

  1. Scarica manualmente il file jar dalla sorgente (sito Web)
  2. Crea una cartella e inserisci il tuo file jar
  3. Esegui il comando seguente per installare il jar di terze parti nel tuo repository di Maven locale

mvn install: install-file -Dfile = -DgroupId = -DartifactId = -Dversion = -Dpackaging =

Di seguito, ad esempio, l’ho usato per simonsite log4j

mvn install: install-file -Dfile = / Users / athanka / git / MyProject / repo / log4j-rolling-appender.jar -DgroupId = uk.org.simonsite -DartifactId = log4j-rolling-appender -Dversion = 20150607-2059 – Dpackaging = jar

  1. Nel pom.xml includi la dipendenza come sotto

       uk.org.simonsite log4j-rolling-appender 20150607-2059  
  2. Eseguire il comando mvn clean install per creare la confezione

Di seguito è riportato il link di riferimento:

https://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html

Per coloro che non hanno trovato una buona risposta qui, questo è ciò che stiamo facendo per ottenere un jar con tutte le dipendenze necessarie in esso. Questa risposta ( https://stackoverflow.com/a/7623805/1084306 ) menziona l’uso del plug-in Maven Assembly, ma in realtà non fornisce un esempio nella risposta. E se non leggi fino alla fine della risposta (è piuttosto lungo), potresti non vederlo. Aggiungendo il sotto al tuo pom.xml genererai il target/${PROJECT_NAME}-${VERSION}-jar-with-dependencies.jar

   org.apache.maven.plugins maven-assembly-plugin 2.4.1    jar-with-dependencies     my.package.mainclass      make-assembly  package  single     

Questo non risponde come aggiungerli al tuo POM, e potrebbe non essere un gioco da ragazzi, ma aggiungere semplicemente la cartella lib al tuo lavoro classpath? So che è quello che faccio quando ho bisogno di un jar esterno che non voglio aggiungere ai miei repository Maven.

Spero che questo ti aiuti.

Ciò che funziona nel nostro progetto è ciò che ha scritto Archimede Trajano, ma abbiamo avuto nel nostro file .m2 / settings.xml qualcosa del genere:

   nexus * http://url_to_our_repository  

e il * dovrebbe essere cambiato in centrale. Quindi se la sua risposta non funziona per te, dovresti controllare il tuo settings.xml

Ho accennato ad alcuni codici Python in un commento alla risposta di @alex lehmann, quindi lo sto postando qui.

 def AddJars(jarList): s1 = '' for elem in jarList: s1+= """  local.dummy %s 0.0.1 system ${project.basedir}/manual_jars/%s \n"""%(elem, elem) return s1 

Volevo solo una soluzione rapida e sporca … Non potevo eseguire la sceneggiatura di Nikita Volkov: errore di syntax + richiede un formato rigoroso per i nomi dei jar.

Ho creato questo script Perl che funziona con qualsiasi formato per i nomi dei file jar e genera le dipendenze in un xml in modo che possa essere copiato direttamente in un pom.

Se vuoi usarlo, assicurati di capire cosa sta facendo lo script, potresti aver bisogno di cambiare la cartella lib e il valore per groupId o artifactId

 #!/usr/bin/perl use strict; use warnings; open(my $fh, '>', 'dependencies.xml') or die "Could not open file 'dependencies.xml' $!"; foreach my $file (glob("lib/*.jar")) { print "$file\n"; my $groupId = "my.mess"; my $artifactId = ""; my $version = "0.1-SNAPSHOT"; if ($file =~ /\/([^\/]*?)(-([0-9v\._]*))?\.jar$/) { $artifactId = $1; if (defined($3)) { $version = $3; } `mvn install:install-file -Dfile=$file -DgroupId=$groupId -DartifactId=$artifactId -Dversion=$version -Dpackaging=jar`; print $fh "\n\t$groupId\n\t$artifactId\n\t$version\n\n"; print " => $groupId:$artifactId:$version\n"; } else { print "##### BEUH...\n"; } } close $fh;