Dovresti fornire librerie dipendenti nel bar del cliente?

Stiamo fornendo un contenitore client per altre app interne per connettersi all’API REST della nostra app. La nostra API dipende da alcune librerie Jakarta standard. È una buona pratica includere questi file JAR nel nostro file jar del client? O semplicemente documentate le dipendenze e tocca ai clienti assicurarsi di avere quei vasi sul loro percorso di class?

Non dovresti raggruppare i vasi di terze parti nel tuo barattolo come un jar uber, ma sarebbe bello includere una copia di tutti i jar richiesti nella tua distribuzione in una directory lib o cosa mai.

La ragione principale di ciò è che i tuoi clienti potrebbero utilizzare qualche forma di sistema di gestione delle dipendenze (maven / edera, ecc.) E fornire pacchetti e classi che non appartengono effettivamente al tuo progetto invalideranno questi schemi.

C’è un’alternativa e cioè usare qualcosa come il plug- in Maven per riposizionare le proprie dipendenze nel proprio spazio dei nomi del pacchetto. Questo ovviamente ha il lato negativo che aumenterai le dimensioni del codice della tua libreria, ma sul lato positivo puoi quasi garantire le versioni delle tue dipendenze senza alcun effetto sulle altre librerie che i tuoi clienti potrebbero usare.

EDIT: in risposta a Marcus Leon commento:

Possibili soluzioni senza raggruppamento / riposizionamento:

  • Documentazione, assicurati di documentare le tue dipendenze e eventuali conflitti noti con le versioni precedenti – nessuno in realtà la legge
  • Distribuisci la tua libreria tramite un sistema gestito da dipendenze … come un repository di eden o maven, questi ti permettono di documentare in un insieme molto specifico di limiti (compresi quelli superiori) quali sono le tue dipendenze – può essere comunque sovrascritto solo i tuoi clienti sapranno che lo stanno facendo
  • Aggiungi informazioni OSGi nel MANIFEST.MF – utile solo se i tuoi clienti usano effettivamente OSGi
  • Se le tue dipendenze sono state compilate usando Maven o le informazioni sulla versione sono presenti in file manifest, potresti scrivere una sorta di routine di controllo che analizza il classpath per questi e controlla le versioni – un po ‘estremo

Alla fine è estremamente difficile accertarsi di avere le dipendenze che si desidera, poiché java è un linguaggio in ritardo, è ansible che le dipendenze (anche se raggruppate) vengano ignorate da qualcuno che include una versione diversa prima del proprio sul classpath.

Nota: recentemente ho passato una bruttissima giornata cercando di scoprire perché una delle nostre app non è riuscita a trovare una nuova versione di log4j. la causa: qualcuno che cercava di essere d’aiuto l’aveva messo in un jar casuale completamente indipendente.

Dovresti includere tutti i vasi da cui dipendi. Se si consente a un cliente di fornire giare standard, ci si basa su di essi per fornire la versione corretta. È molto più indolore per entrambi, se includi le versioni con cui sai che la tua app funziona.

I professionisti di raggruppare in un singolo barattolo sono ovviamente:

  • semplicità per il cliente

Gli aspetti negativi del raggruppamento sono:

  • incapacità di aggiornare le versioni delle librerie dipendenti
  • hide le librerie necessarie può effettivamente portare a potenziali conflitti nel client con quelle librerie extra
  • complessità per te nel processo di compilazione (ma modi per farlo abbastanza facilmente in Ant / Maven)
  • alcune librerie con manifest non possono essere solo unjared e rejared – devi effettivamente unire le informazioni manifest. Tuttavia, c’è un supporto Ant e Maven per questo.

Un’altra opzione è quella di usare un singolo jar principale (il tuo codice) con l’attributo manifest del percorso di class impostato per succhiare negli altri jar. Personalmente non mi piace perché è davvero facile perdere queste dipendenze semi-nascoste.

Alla fine, se stai parlando solo di uno o due vasi, li lascerei separati. Se stai parlando di 10 o 15, potresti prendere in considerazione l’idea di raggruppare.

Dovresti includere questi vasi se stai distribuendo l’app come applicazione autonoma. Se stai distribuendo il sorgente per qualcuno da compilare e fornisci un file Maven Pom, non devi necessariamente farlo.

Stai esprimendo nervosismo su dipendenze di versioni di librerie molto specifiche (e posso capire che, dato quanto strettamente accoppiato, diciamo, Hibernate è tra i suoi diversi moduli – solo alcune versioni di Hibernate-annotazioni funzionano con un core di ibernazione, che a sua volta deve essere usato con uno specifico validatore di ibernazione).

Se sai che un pacchetto deve funzionare come parte di una piattaforma molto più grande (ad esempio, come plugin per un framework che può caricare i propri jar), è davvero necessario il più potente caricamento di class multi-versione di OSGI (noto anche come JSR -291): tecnologia OSGI

Con un framework abilitato per OSGI, come Spring, Eclipse, Jonas o Glassfish, è ansible specificare in un file XML le dipendenze specifiche della versione e se si dipende dal bundle libfoo-1.1.4, mentre un altro plugin dipende da libfoo-2.0 a, il gestore delle dipendenze OSGI assicurerà che ogni carico della versione corretta.