2011-08-22 11 views
40

Ho un'applicazione Web che si basa su alcune risorse e parametri da configurare dopo l'installazione, come una connessione JDBC.Come fornire una configurazione del contesto per un'applicazione Web in Tomcat?

Quello che mi è venuto in mente è fornire un META-INF/context.xml che viene copiato in [engine-name]/[server-name]/[app-name].xml da Tomcat quando distribuisco l'applicazione. In questo modo tutto ciò che sto fornendo è un file di guerra che può essere copiato nella cartella appBase (webapps). La documentazione di Tomcat says se esiste un file di questo tipo non verrà sovrascritta, il che è davvero eccezionale, poiché le modifiche apportate dopo la distribuzione non andranno perse.

Ma c'è un sottile problema qui: Poiché distribuiamo l'applicazione copiando nella directory webapps, Tomcat prima disinstallerà l'applicazione esistente e il file di configurazione. In questo modo il file di configurazione verrà perso/sovrascritto, il che non è desiderabile. Tomcat won't modifica questo comportamento per quanto ne so.

La domanda è: C'è un modo per ovviare a questo problema installando l'applicazione in modo che Tomcat non rimuova il file di configurazione esistente. Oppure, c'è un modo migliore di confezionare l'applicazione?

Si noti che non si desidera impostare autoDeploy su false e non è possibile utilizzare l'intervento umano per l'installazione (che esclude l'utilizzo dell'applicazione Web Tomcat Manager).

Se ottengo il file di configurazione dal file .war e lo copio separatamente come [engine-name]/[server-name]/[app-name].xml, Tomcat lo associa ancora alla mia applicazione e lo rimuovo una volta che copio un nuovo file .war.

Un altro presupposto è: non conosciamo in anticipo i valori per la configurazione. Forniremo solo una configurazione di esempio (un segnaposto, se lo si desidera) mentre la configurazione effettiva verrà eseguita in un momento successivo (non necessariamente nel tempo di installazione).

Grazie

+0

non puoi rimuovere il tuo file context.xml dalla guerra e metterlo direttamente dove Tomcat ha bisogno? Non sarebbe più disinstallato e reinstallato. Sul molo, è così che funziona la distribuzione a caldo – Snicolas

+0

Ho provato che, se il file corrisponde al modello [engine]/[host]/[app] .xml, è considerato come parte dell'applicazione, anche se non era nel file .war (o_O). – n0rm1e

+0

Non è possibile fornire script di compilazione per tutti i diversi ambienti in modo da non dover modificare nulla dopo la distribuzione? – home

risposta

8

sono riuscito a risolvere il problema in qualche modo.

1- Installare una directory WAR esplosa da qualche parte all'esterno di AppBase di Tomcat, supponiamo che sia in /usr/local/MyApp. [È possibile utilizzare un file WAR per questo passaggio invece di WAR, se l'applicazione viene eseguita da una guerra inesplosa.]

2- Copiare il file di configurazione del contesto nella directory [tomcat.conf]/[engine]/[hostname], chiamiamolo MyApp.xml. Questo file punterà alla posizione dell'applicazione:

<?xml version="1.0" encoding="UTF-8"?> 
<!-- Context configuration file for my web application --> 
<Context docBase="/usr/local/MyApp" privileged="true" antiResourceLocking="false" antiJARLocking="false"> 
     <Resource name="jdbc/myapp-ds" auth="Container" type="javax.sql.DataSource" 
       maxActive="100" maxIdle="30" maxWait="10000" username="XXX" password="XXX" 
       driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/mydb" /> 
</Context> 

3- Ora siete liberi di andare e modificare il file di configurazione.

4- Aggiornamento dell'applicazione copiando nuova versione della propria applicazione in/usr/local/MyApp

Note:

a) Questa soluzione si applica a un file .war non espanso pure, ma dal momento che usa Spring's Log4JConfigListener che non verrebbe eseguito da un file .war inesploso. Tomcat non esplode. I file .war vengono messi all'esterno della cartella appBase (webapps).

b) Questo approccio non impedisce di avere context.xml in /usr/local/MyApp/META-INF/context.xml poiché non verrà utilizzato da Tomcat in questa configurazione. Puoi usarlo nel tuo ambiente di sviluppo, dove devi scaricare il tuo file .war nella cartella appBase (webapps).

Questo è quello che ho ottenuto finora, ancora alla ricerca di soluzioni migliori.

+0

Puoi anche guarda in Overlay Deployer che è supportato sia da Tomcat che da Jetty: http://www.eclipse.org/jetty/documentation/current/overlay-deployer.html – n0rm1e

+0

link overlay-deployer non funziona più, ma qui sembra essere: https://github.com/eclipse/jetty.project/tree/jetty-9.4.x/jetty-overlay-deployer –

1

non so come modificare il comportamento di Tomcat, ma riuscivo a pensare a 2 diverse soluzioni:

  1. diversa (parametrizzato) costruire script per ogni ambiente, in modo che si definisce un parametro chiamato env per gli script di compilazione e in base al valore che imposta l'ambiente specifico context.xml nella GUERRA durante la compilazione.
  2. Creare uno script install per ciascun ambiente che prima redeploys il file WAR (lo inserisce nella directory webapps) e quindi apporta modifiche all'installazione di Tomcat in base all'ambiente, ad es. diverso nome host per JDBC DataSource in context.xml.

Uso intensamente quest'ultimo approccio poiché funziona in ambienti aziendali. Le politiche di separazione delle funzioni spesso proibiscono alla squadra di sviluppatori di conoscere ad es. password del database di produzione. L'opzione # 2 risolve questo problema perché solo le operazioni IT hanno accesso agli script di installazione specifici dell'ambiente dopo che sono stati creati.

+0

Questo è lo scenario che voglio evitare: 1- Installiamo l'applicazione e la configuriamo correttamente. 2- Il nostro team di infrastruttura sposta le VM in giro e modifica correttamente la configurazione. Tutti felici 3- Aggiorniamo l'applicazione e distribuiamo un nuovo file .war. 4- BANG! Le modifiche nel passaggio 2 sono perse. – n0rm1e

+0

Il secondo approccio funziona se è possibile forzare l'applicazione a essere nuovamente configurata ogni volta che viene aggiornata. Potremmo farlo se non trovo un modo migliore per rilasciare l'applicazione. – n0rm1e

1

@ n0rm1e: non so se tomcat fornisce qualsiasi tipo di soluzione per il tuo problema. Ma una possibile soluzione può essere: - creare uno script ant con i seguenti passi:

i) Verificare l'esistenza di.file xml nella directory [nome-motore]/[nome-server]. Se esiste, fare un backup di questo/rinominarlo.

ii) copia il tuo file di guerra su webapps di tomcat. Riavvia il server tomcat.

iii) copia dei file di configurazione di backup-ed a [motore-name]/[nome-server] Directory

+0

Anche se non mi piace questo approccio, ma abbiamo finito per farlo (in RPM pre-installazione e script post-installazione), perché le persone non potevano girare la testa intorno alle applicazioni andando da qualche altra parte della cartella webapps: D – n0rm1e

38

La soluzione è semplice: non inserire la configurazione nel contesto.xml.

Ecco una soluzione che usiamo (che funziona bene per un certo numero di diversi clienti esterni):

Abbiamo una sola guerra che sarà utilizzato in più ambienti, webapp.war. Abbiamo tre ambienti, sviluppo, integrazione e produzione. Integrazione e produzione sono sul sito del cliente. Non conosciamo password e percorsi di file per l'integrazione del client e i siti di produzione.

Utilizziamo una combinazione di due elementi: ricerca JNDI per i file di database e file di proprietà esterni.

Nel context.xml quello disponibile in guerra, abbiamo un ResourceLink

<ResourceLink name="jdbc/webapp" 
    global="uk.co.farwell.webapp.datasource.MySqlDataSource" /> 

Questo dà un riferimento a una fonte di dati definito globalmente, che è definito nella server.xml per Tomcat.

<Resource auth="Container" 
      driverClassName="com.mysql.jdbc.Driver" 
      name="uk.co.farwell.webapp.datasource.MySqlDataSource" 
      password="xxx" url="xxx" username="fff" /> 

Così i dettagli del database possono essere cambiati modificando il server.xml senza cambiare la webapp.war.Fondamentalmente, questo deve essere fatto solo una volta per ogni server, non per ridistribuire.

Nella nostra configurazione primavera, per definire il dataSource abbiamo:

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/webapp" /> 

Per altre proprietà, abbiamo un file application.properties globale che viene consegnato insieme al webapp.war, ma non fa parte del la guerra. A questo fa riferimento un -D sulla riga di comando per avviare Tomcat. -Duk.co.farwell.webapp.applicationDir="/usr/xxx/fff". Prendiamo la definizione e leggiamo il file delle proprietà. Le cose del database potrebbero essere fatte anche in questo modo, ma perderemmo il pool fatto da Tomcat.

Un'altra cosa: non dobbiamo ricostruire se i server vengono spostati, o se le macchine vengono cambiate per qualche motivo. Questa è una questione per il cliente e per le persone della sua infrastruttura.

+0

Questo è un buon approccio. Forse non dovremmo preoccuparci di come le origini dati JNDI sono configurate in produzione. – n0rm1e

+2

Mi sono appena rotto e ho aggiunto tutto nel file context.xml globale. Tomcat rende la mia vita dolorosa a volte. – HaxElit

+12

Funziona alla grande nella maggior parte dei casi. Ma se hai bisogno di distribuire la stessa app in più contesti, ognuno con un database diverso, non funzionerà. – Lachlan

4

Facendo riferimento a Apache Tomcat 5.5 Documentation:

Nella $ CATALINA_HOME/conf/file di context.xml: l'elemento di contesto informazioni verrà caricata da tutti i webapps

Si potrebbe facilmente provare questo approccio , potrebbe funzionare, ma non sono sicuro che questa sia una buona soluzione, specialmente se stai eseguendo più webapp su Tomcat.

3

Questo è come si possa riuscire a esternare contesto webapp dal file .war

  1. Luogo file .WAR da qualche gatto fuori
  2. Creare un file $ APP_NAME.xml in $ TOMCAT_HOME/conf/[Motore ]/[Host]/directory.
  3. Ora il file "$ APP_NAME.xml" appena creato deve disporre di definizione del contesto e parametri + Qualsiasi variabile di ambiente che si desidera specificare per quel contesto.

Ad es. Ho una webapp chiamata VirtualWebApp.

creerò di file come VirtualWebApp.xml con definizione del contesto di seguito:

<Context docBase="/home/appBase/VirtualWebApp" path="/VirtualWebApp" reloadable="true"> 
    <Environment name="webservice.host" type="java.lang.String" value="1.2.3.4" /> 
    <Environment name="webservice.port" type="java.lang.String" value="4040" /> 
</Context> 

Per accedere a queste variabili di ambiente si deve scrivere il codice qui sotto (solo ricerca):

InitialContext initialContext = new javax.naming.InitialContext(); 

host = (String)initialContext.lookup("java:comp/env/webservice.host"); 
port = (String)initialContext.lookup("java:comp/env/webservice.port"); 
+0

Assicurati di aggiungere lo spazio dei nomi iniziale "java: comp/env /" per cercare le voci. – srv

Problemi correlati