IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Spring Java Discussion :

[@Controller][Validator] Injecter un service depuis un validator


Sujet :

Spring Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 51
    Par défaut [@Controller][Validator] Injecter un service depuis un validator
    Bonsoir à tous,

    Je suis entrain de galérer sur l'injection d'un service depuis une classe validator :
    Voici ma classe service :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    @Service("PersonService")
    public class PersonServiceImpl implements PersonService {
     
    	@Autowired
    	private PersonDao dao;
     
    	public void setDao(PersonDao dao) {
    		this.dao = dao;
    	}
     
    	...
    Voici mon contrôleur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    @Controller
    @SessionAttributes("person")
    public class PersonController {
     
    	@Autowired
    	private PersonService service;
     
    	public void setService(PersonService service) {
    		this.service = service;
    	}
     
    @RequestMapping(value = "/form.html", method = RequestMethod.POST)
    	public String submit(@ModelAttribute("person")Person person, BindingResult result, SessionStatus status) { 
     
    		new PersonValidator().validate(person, result);
    		if (result.hasErrors()) {
    			return "form";
    		} else {
    			service.saveOrUpdate(person);
    			status.setComplete(); 
    			return "redirect:list.html";
    		}
    	}
    Je voudrais tester si la personne existe déjà dans la base de données avant de la rajouter :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
     
    public class PersonValidator implements Validator {
     
    	@Autowired
    	private PersonService service;
     
    	public void setService(PersonService service) {
    		this.service = service;
    	}
     
    	public boolean supports(Class clazz) {
    		return false;
    	}
     
    	public void validate(Object object, Errors errors) {
    		 Person p = (Person) object;
    		 System.out.println("dans le validate : "+p.getNom());
    		 	if(service.userExists(p.getNom())){
    				errors.rejectValue("nom","errors.required", null,"Username already taken.");
    			}
    	}
    J'ai un java.lang.NullPointerException sur la variable service quand j'invoque la méthode service.userExists(p.getNom()) de la couche
    Pourtant l'objet p n'est pas a null, j'ai vérifié il est bien remplit par l'interface.
    Ce qui est bizarre est que si je désactive cette ligne, la méthode service.saveOrUpdate(person); du contrôleur s'exécute parfaitement => le contrôleur arrive bien a injecter le service et pas le validator !


    Voici la stack error :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    GRAVE: "Servlet.service()" pour la servlet spring a g�n�r� une exception
    java.lang.NullPointerException
    	at spring.tutorial.web.PersonValidator.validate(PersonValidator.java:36)
    	at spring.tutorial.web.PersonController.submit(PersonController.java:88)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    	at java.lang.reflect.Method.invoke(Unknown Source)
    	at org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:160)
    	at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:245)
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:874)
    	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:808)
    	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:476)
    	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:441)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    	at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:75)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
    	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:845)
    	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
    	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    	at java.lang.Thread.run(Unknown Source)
    j'ai rajouté cette ligne dans le spring-config.xml

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    <bean id="configurationLoader"		class="org.springmodules.validation.bean.conf.loader.annotation.AnnotationBeanValidationConfigurationLoader" />
    	<bean id="validator"
    		class="org.springmodules.validation.bean.BeanValidator"
    		p:configurationLoader-ref="configurationLoader" />

    Auriez-vous une idée pourquoi je n'arrive pas à injecter le service dans ma classe Validator ?

    Merci par avance de votre aide.

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 51
    Par défaut Problème Résolut !
    Bon,
    Je me répond à moi même pour ceux qui sont intéressés par la solution que j'ai trouvé :

    J'ai utilisé le constructeur de ma classe PersonValidator pour passer une référence vers le PersonService :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    @Controller
    @SessionAttributes("person")
    public class PersonController {
     
    	@Autowired
    	private PersonService service;
     
    	public void setService(PersonService service) {
    		this.service = service;
    	}
     
     
    @RequestMapping(value = "/form.html", method = RequestMethod.POST)
    	public String submit(@ModelAttribute("person")Person person, BindingResult result, SessionStatus status) { 
     
    //Passer une référence du service dans le constructeur
    		new PersonValidator(service).validate(person, result);
    		...
    	}
    Et dans la classe Validator :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public class PersonValidator implements Validator {
     
    	public PersonService service;
     
    	public PersonValidator(PersonService service) {
    	    this.service = service;
    	}
     
            public void validate(Object object, Errors errors) {
    		 Person p = (Person) object;
     
                             //Maintenant l'invocation de la fonction userExists marche
    		 	if(service.userExists(p.getNom())){

    Avez-vous une meilleure solution ?

    Merci.

  3. #3
    Membre Expert
    Homme Profil pro
    Inscrit en
    Septembre 2006
    Messages
    2 963
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Septembre 2006
    Messages : 2 963
    Par défaut
    Citation Envoyé par hkefi Voir le message

    Avez-vous une meilleure solution ?

    Merci.
    le fait que le Validator ait besoin de connaître le service est - à mon sens - un problème de design de votre architecture…

    le rôle d'un Validator devrait être limité à la validation d'un object en lui-même sans tenir compte de contraintes contextuelles…

    service "création d'un nouvel individu" =
    1. validation de son contenu propre via le Validator,
    2. si 1 OK alors vérification de sa pertinence (par exemple unicité) via le DAO

    si vous aviez bien séparé les responsabilités, le problème de l'injection du service dans le validator ne se serait donc même pas posé car elle n'a pas lieu d'être…

    ce que vous faites c'est :
    "le service qui demande au validator qui demande au service de demander au dao de vérifier l'unicité…"

  4. #4
    Rédacteur
    Avatar de Hikage
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 177
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 177
    Par défaut
    Le soucis est ici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @RequestMapping(value = "/form.html", method = RequestMethod.POST)
    	public String submit(@ModelAttribute("person")Person person, BindingResult result, SessionStatus status) { 
    		
    		new PersonValidator().validate(person, result);
    		if (result.hasErrors()) {
    			return "form";
    		} else {
    			service.saveOrUpdate(person);
    			status.setComplete(); 
    			return "redirect:list.html";
    		}
    	}
    Le fait de faire un new PersoValidator(), ce n'est pas Spring qui va l'instancier, et donc Spring ne fait pas le wiring.
    Donc ton service est 'null'.

    Ta solution corrige cela evidemment.
    L'autre moyen est de te faire injecter le validator dans le controlleur, dans ce cas la, l'injection du service sera réalisée dans le validator aussi
    Hikage
    SCJP / SCWCD & SCWSJD Certified / Spring Framework Certified
    [Personal Web] [CV]

    F.A.Q Spring Framework - Participez !

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 51
    Par défaut injecter le validator dans le controlleur
    Merci pour vos réponses,
    Pour répondre à JeitEmgie, j'ai bien séparé les couches et je pouvais pas faire la vérification de l'unicité après la validation du contenu propre par ce que je pourrais plus retourner une erreur ! a moins que tu as une solution à me proposer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    @RequestMapping(value = "/form.html", method = RequestMethod.POST)
    	public String submit(@ModelAttribute("person")Person person, BindingResult result, SessionStatus status) { 
     
    		new PersonValidator().validate(person, result);
     
    // a ce niveau je peux vérifier l'unicité mais je ne peux plus remplir result.hasErrors()
    		if (result.hasErrors()) {
    			return "form";
    		} else {
     
    			service.saveOrUpdate(person);
    			status.setComplete(); 
    			return "redirect:list.html";
    		}
    	}
    mais je voudrais rebondir sur la remarque de Hikage :

    L'autre moyen est de te faire injecter le validator dans le controlleur, dans ce cas la, l'injection du service sera réalisée dans le validator aussi
    Justement, comment injecter le validator dans le controlleur ?
    Les exemples que j'ai trouvé appellent tous le validateur en passant par un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    new PersonValidator().validate(person, result);
    Merci

  6. #6
    Rédacteur
    Avatar de Hikage
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    1 177
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2004
    Messages : 1 177
    Par défaut
    As tu essayé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	@Autowired
    	private PersonValidator validator;
    Hikage
    SCJP / SCWCD & SCWSJD Certified / Spring Framework Certified
    [Personal Web] [CV]

    F.A.Q Spring Framework - Participez !

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    51
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 51
    Par défaut Ca marche pas
    Je viens de faire comme tu m'as dit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    @Controller
    @SessionAttributes("person")
    public class PersonController {
     
    	@Autowired
    	private PersonService service;
     
    	public void setService(PersonService service) {
    		this.service = service;
    	}
     
    	@Autowired
    	public PersonValidator validator;
     
    	public void setValidator(PersonValidator validator) {
    	    this.validator = validator;
    	}
     
    @RequestMapping(value = "/form.html", method = RequestMethod.POST)
    	public String submit(@ModelAttribute("person")Person person, BindingResult result, SessionStatus status) { 
    	    validator.validate(person, result);
    		if (result.hasErrors()) {
    			return "form";
    		} else {
    			service.saveOrUpdate(person);
    			status.setComplete(); 
    			return "redirect:list.html";
    		}
    	}
    Et dans la classe Valildator :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public class PersonValidator implements Validator {
     
        	@Autowired
    	public PersonService service;
     
    	public void setService(PersonService service) {
    		this.service = service;
    	}
    J'ai une grosse stack : No unique bean of type PersonValidator is defined:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    2009-01-05 14:26:06,809 ERROR [org.springframework.web.context.ContextLoader] - <Context initialization failed>
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'personController': Autowiring of fields failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: public spring.tutorial.web.validator.PersonValidator spring.tutorial.web.PersonController.validator; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [spring.tutorial.web.validator.PersonValidator] is defined: Unsatisfied dependency of type [class spring.tutorial.web.validator.PersonValidator]: expected at least 1 matching bean
    	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:231)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:978)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:485)
    	at java.security.AccessController.doPrivileged(Native Method)
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:455)
    	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:251)
    	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:169)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:248)
    	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:170)
    	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:413)
    	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:735)
    	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:369)
    	at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:251)
    	at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:190)
    	at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45)
    	at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
    	at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
    	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
    	at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
    	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
    	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
    	at org.apache.catalina.core.StandardService.start(StandardService.java:516)
    	at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
    	at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    	at java.lang.reflect.Method.invoke(Method.java:585)
    	at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
    	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
    Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: public spring.tutorial.web.validator.PersonValidator spring.tutorial.web.PersonController.validator; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [spring.tutorial.web.validator.PersonValidator] is defined: Unsatisfied dependency of type [class spring.tutorial.web.validator.PersonValidator]: expected at least 1 matching bean
    	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredElement.inject(AutowiredAnnotationBeanPostProcessor.java:375)
    	at org.springframework.beans.factory.annotation.InjectionMetadata.injectFields(InjectionMetadata.java:61)
    	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessAfterInstantiation(AutowiredAnnotationBeanPostProcessor.java:228)
    	... 30 more
    Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [spring.tutorial.web.validator.PersonValidator] is defined: Unsatisfied dependency of type [class spring.tutorial.web.validator.PersonValidator]: expected at least 1 matching bean
    	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveDependency(AbstractAutowireCapableBeanFactory.java:417)
    	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredElement.inject(AutowiredAnnotationBeanPostProcessor.java:361)
    	... 32 more
    Merci

Discussions similaires

  1. Réponses: 1
    Dernier message: 15/09/2011, 17h21
  2. controle de saisie d'une adresse email valide
    Par nassing dans le forum jQuery
    Réponses: 1
    Dernier message: 26/05/2011, 14h52
  3. [AC-2007] Valider une liste multiple depuis un bouton du Ruban
    Par curt dans le forum IHM
    Réponses: 1
    Dernier message: 05/06/2009, 23h38
  4. URL web service est il valide?
    Par Mr_Welby dans le forum Services Web
    Réponses: 1
    Dernier message: 05/09/2007, 18h08
  5. [validation]Erreur format texte depuis BDD
    Par Death83 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 18/02/2006, 19h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo