2015-11-26 8 views
22

Ho bisogno di hot-deploy e -undeploy risorse in un ServletContainer Jersey.Dinamicamente (un) distribuzione di risorse in Jersey

Sembra non esserci modo di "annullare la registrazione" delle risorse su un ResourceConfig, quindi il percorso che sto seguendo è quello di sostituire tutte le risorse con un nuovo set.

Anche se the documentation dice registerResources on ResourceConfig sostituisce tutte le risorse, sfogliare il codice sorgente sembra contraddire questo.

La soluzione che ho trovato era di ricaricare ServletContainer con un ResourceConfig completamente nuovo.

Set<Class<?>> classes = ... 
ResourceConfig config = new ResourceConfig(classes); 
container.reload(config); 

Questo funziona fino a quando non distribuisco una risorsa che risulta in ModelValidationException. Dopodiché non riesco a riportare ServletContainer in uno stato corretto.

Se prendo uno sguardo al codice sorgente:

public void reload(final ResourceConfig configuration) { 
    try { 
     containerListener.onShutdown(this); 

     webComponent = new WebComponent(webComponent.webConfig, configuration); 
     containerListener = webComponent.appHandler; 
     containerListener.onReload(this); 
     containerListener.onStartup(this); 
    } catch (final ServletException ex) { 
     LOGGER.log(Level.SEVERE, "Reload failed", ex); 
    } 
} 

Il ModelValidationException è gettato dal costruttore WebComponent. Successivamente, qualsiasi chiamata a ricaricare genera un'eccezione dal metodo onShutdown, causato da checkState nel metodo preDestroy di ServiceLocatorImpl.

posso evitare l'eccezione ignorando gli errori di convalida

ResourceConfig config = new ResourceConfig(classes); 
config.property(ServerProperties.RESOURCE_VALIDATION_IGNORE_ERRORS, 
    Boolean.TRUE); 
container.reload(config); 

Non c'è modo ora però per scoprire se ci sono stati errori, ma per esplorare la registrazione, che è altrettanto male, davvero.

Per heenenee's comment Ho provato la sottoclasse di ServletContainer, ma qualcosa di simile dà problemi in quanto il ResourceConfig non può essere inserito in due WebComponents.

Ho cercato di creare il WebComponent prima di spegnersi, per ottenere una rapida uscita, ma questo viene a mancare la ricarica effettiva se non ci sono errori nelle risorse (perché il ResourceConfig non può essere modificato dopo che il webcomponent è stata creata)

@Override 
public void reload(ResourceConfig configuration) { 
    try { 
     new WebComponent(new WebServletConfig(this), configuration); 
    } catch (ServletException e) { 
     LOGGER.log(Level.SEVERE, "Reload failed", e); 
     List<ResourceModelIssue> resources = Collections.emptyList(); 
     throw new ModelValidationException(e.getMessage(), resources); 
    } 
    super.reload(configuration); 
} 

C'è un altro modo per hot-undeploy delle risorse? C'è un modo per resettare ServletContainer dopo un errore di ricarica?

+0

Si potrebbe provare a creare una sottoclasse 'ServletContainer', override' reload (ResourceConfig) '' per la cattura RuntimeException' e registrare un errore, quindi specificare la sottoclasse in web.xml. – heenenee

risposta

1

Non penso che questo possa essere ottenuto senza l'uso di un contenitore servlet che supporta le distribuzioni a caldo. Nella mia esperienza, un buon modo per farlo è usare un contenitore che supporti OSGi. Puoi dare un'occhiata a Eclipse Virgo o Apache Karaf.

Ad esempio, in un ambiente OSGi, è possibile creare moduli (denominati pacchetti) che possono essere rilasciati in una cartella scansionata per abilitare le funzionalità in fase di runtime o rimosse da una cartella per disabilitare alcune funzionalità. Questo è simile a come funzionano i plugin in Eclipse IDE, dove un nuovo plug-in di installazione/disinstallazione non richiede necessariamente un riavvio.

+0

Sono d'accordo. Questo è esattamente il caso d'uso per un'applicazione Web modulare. Hai solo bisogno di pubblicare nel contenitore OSGi i servizi JAX-RS annotati con @Path che soddisfano l'interfaccia predefinita. L'implementazione di Servlet (anche un pacchetto) troverà i tuoi servizi e pubblicherà tramite HTTP. Il contenitore OSGi è responsabile del cablaggio del servizio e del servlet insieme in fase di runtime. – Leo

0

Jersey non è tecnicamente un contenitore servlet, è un framework REST/JaxB in esecuzione su un contenitore servlet.

La maggior parte dei container servlet incorporabili, Tomcat, Jetty, Grizzly consente di ridistribuire applicazioni e servlet in fase di runtime. Ma la ridistribuzione non è in genere una funzionalità che si utilizza quando si incorpora il contenitore nel codice.

La ridistribuzione a caldo è molto utile in produzione, consentendo di distribuire continuamente nuove versioni. Su Tomcat è possibile avere una versione nuova e vecchia di un'applicazione distribuita sullo stesso server e tomcat garantisce che le nuove sessioni vengano avviate sulla versione più recente dell'applicazione, ma le versioni precedenti continueranno a utilizzare la versione dell'applicazione con cui sono state avviate. Quando un'applicazione non è utilizzata, viene automaticamente annullata.

Problemi correlati