2013-06-24 10 views
6

Sono in procinto di convertire un'applicazione Web Java già esistente in un'applicazione web RESTful utilizzando Spring MVC e Groovy. Una delle caratteristiche principali che volevo ottenere era l'HOT DEPLOYMENT. Ho scelto groovy perché non volevo apportare modifiche alla logica aziendale già implementata (gestori) e anche se dovessi apportare modifiche al codice groovy dopo la distribuzione, avrei potuto facilmente farlo senza riavviare il server (ad es. runtime). Questo può essere fatto perché Spring supporta il ricaricamento dinamico di script groovy (bean). Ricarica le classi di linguaggi dinamici se vengono modificati.Applicazione Spring/REST con HOT Deployment: lo script Groovy non viene caricato dinamicamente da applicationContext.xml all'avvio di tomcat in runtime

Sto utilizzando le annotazioni Spring per associare gli URL delle richieste ai metodi del controller e l'applicazione viene distribuita in tomcat 6.0.35.

Questo è il file web.xml

//web.xml 

     <?xml version = "1.0" encoding = "UTF-8"?> 
     <web-app xmlns="http://java.sun.com/xml/ns/javaee" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> 

     <!-- Spring Dispatcher --> 
     <servlet> 
       <servlet-name>rest</servlet-name> 
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
       <load-on-startup>1</load-on-startup> 
     </servlet> 
     <servlet-mapping> 
       <servlet-name>rest</servlet-name> 
       <url-pattern>/service/*</url-pattern> 
     </servlet-mapping> 
     <!-- Loads application context files in addition to ${contextConfigLocation} --> 
     <listener> 
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
     </listener>  

      <!-- Set session timeout to 30 minutes --> 
     <session-config> 
      <session-timeout>30</session-timeout> 
     </session-config> 
    </web-app> 

Questo file Groovy è il controller a cui associa la DispatcherServlet la richiesta.

// UserController.groovy 

@Controller 
class UserController 
{ 
    // This is the method to which the HTTP request is submitted to based on the mapping of the 
    // action field of the form ie. /service/user/login/auth.json 
    @RequestMapping(value="/user/login/auth.{extension:[a-zA-Z]+}", method=RequestMethod.POST) 
    @ResponseBody 
    public String authenticate(
    @PathVariable String extension, 
    @RequestParam(value="username", required=true) String username, 
    @RequestParam(value="password", required=true) String password) 
    { 
     // UserResource makes the backend calls, authenticates a user and returns the result. 
     def user = new UserResource() 
     def result = user.login(name:username, userPassword:password) 

     // Output the result of the query. Method makeView makes a JSON response of the result 
     // and sends to the client(browser) 
     def builder = makeView(extension) 
     { 
      it.login(action:result.action, message:result.message) 
     } 
    } 
    } 

Il file di configurazione è la seguente primavera in cui ho usato il "lang: groovy" tag che supporta i linguaggi dinamici. Ho anche menzionato il tempo di aggiornamento di 5 secondi, in modo che le modifiche apportate a quei file groovy in fase di esecuzione possano essere visualizzate ogni 1 secondo e le classi vengano ricaricate.

//applicationContext.xml 

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:lang="http://www.springframework.org/schema/lang" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:c="http://www.springframework.org/schema/c" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context-3.1.xsd 
     http://www.springframework.org/schema/util 
     http://www.springframework.org/schema/util/spring-util-3.1.xsd 
     http://www.springframework.org/schema/lang 
     http://www.springframework.org/schema/lang/spring-lang-3.1.xsd"> 

    <context:annotation-config/> 
    <context:component-scan base-package="app.controller,app.resource" /> 

    <lang:groovy id="user" script-source="classpath:controller/UserController.groovy" refresh-check-delay="1000"></lang:groovy> 

    <!-- To enable @RequestMapping process on type level and method level --> 
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" /> 
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> 

    <!-- Resolves view names to template resources within the directory --> 
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
     <property name="prefix" value="/"/> 
     <property name="suffix" value=".html"/> 
    </bean> 

</beans> 

Ho configurato il mio Buildpath e compilatore Groovy di conseguenza, in modo che tutti gli script groove direttamente vengono copiati nella cartella di destinazione invece di ottenere compilati in file di classe.

il problema principale
Quando schiero questo progetto in un server Tomcat, carica tutti i bean Spring necessari tra cui la scriptProcessor. Ora, quando vado al mio browser, caricare il modulo, e cercare di inviare il modulo di autenticazione, ottengo il seguente errore in Tomcat registro:

15:20:09 WARN - No mapping found for HTTP request with URI [/service/user/login/auth.json] in DispatcherServlet with name 'rest' 

ho anche fatto i cambiamenti nel $ TOMCAT_DIR/conf/contesto .xml antibloccaggio risorse e vasetti

<Context antiResourceLocking="true" antiJARLocking="true" reloadable="true" privileged="true"> 
. 
. 
.</Context> 

Tuttavia, se devo configurare il mio progetto per compilare questi script Groovy in classi bytecode, commentare la "lang: groovy" tag in applicationContext.xml, e quindi riavviare il server, gli script groovy vengono compilati in file di classe e la richiesta viene gestita perfettamente. L'autenticazione ha luogo

Inoltre, se configuro i bean dinamici nel mio applicationContet.xml utilizzando le seguenti due righe anziché il tag, i miei bean DO vengono creati dinamicamente in fase di runtime e gli URL vengono mappati ai rispettivi metodi del controller a causa delle annotazioni .

<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor" /> 

<bean id ="User" class="org.springframework.scripting.groovy.GroovyScriptFactory"> 
    <constructor-arg value="classpath:controller/UserController.groovy" /> 
</bean> 

Ma non so come creare la funzionalità di aggiornamento del bean con questo stile. Quindi immagino ci sia un problema con il modo in cui il tag elabora gli script groovy.

Apprezzerei molto l'aiuto su questo. Ho cercato su Internet e ho letto un numero infinito di tutorial, e ho seguito la procedura esatta menzionata lì. Ma non posso scoprire che cosa sta andando storto.

Per favore aiutami a risolvere questo problema.

Grazie.

risposta

0

Provare a creare il controller con Java/Groovy che viene compilato e lasciare che venga iniettato lo "script" Groovy come dipendenza per eseguire il lavoro effettivo. Mi sembra di ricordare di averlo fatto prima e potrebbero essere le annotazioni o il modo in cui Spring carica i controller che rendono lo 'script' non funzionante per te.

Problemi correlati