2010-08-27 12 views
9

Dieses Beispiel ist ein bisschen künstlich; Ich habe es vereinfacht, um überflüssige Details zu entfernen und mich auf das Problem zu konzentrieren, das ich habe. Ich habe einen Validator, der wie folgt aussieht:Autowiring eines Dienstes in einen Validator

@Component 
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> { 

    @Autowired 
    UsernameService usernameService; 

    @Override 
    public void initialize(UniqueUsername uniqueUsername) { 
    } 

    @Override 
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) { 
     return !usernameService.exists(s); 
    } 
} 

ich den Validator nennen wie dies von meinem Controller:

@RequestMapping 
public void checkUsername(Model model, User user) { 
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory(); 
    Validator validator = factory.getValidator(); 

    Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(user, "username"); 
    model.addAttribute("error", constraintViolations.size() > 0); 
} 

Allerdings halte ich eine NullPointerException Ausnahme bekommen. Ich fügte einen Haltepunkt in meinem Prüfer hinzu und sah, dass usernameServicenull war. Warum wird es nicht autowired? Anfangs dachte ich, dass es daran lag, dass ich den Validator nicht mit @Component annotiert hatte, aber ich habe immer noch das gleiche Problem, selbst nachdem ich es notiert habe. Die UsernameService Klasse wurde bereits mit @Service annotiert und ich kann überprüfen, dass der Konstruktor aufgerufen wird.

Ich bin neu bei Spring, also bin ich mir nicht einmal sicher, ob es in Ordnung ist, einen Service in einen Validator einzubinden. Was mache ich falsch?

Antwort

11

Im Frühjahr, müssen Sie ValidatorFactory (oder Validator selbst) über LocalValidatorFactoryBean statt Validation.buildDefaultValidatorFactory() zu erhalten, wie in the reference beschrieben.

@Autowired 
Validator validator; 

@RequestMapping 
public void checkUsername(Model model, User user) { 
    Set<ConstraintViolation<User>> constraintViolations = validator.validateProperty(user, "username"); 
    model.addAttribute("error", constraintViolations.size() > 0); 
} 

-

<bean id="validator" 
    class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> 

EDIT: Aber vielleicht der bessere Weg, es zu tun ist, Spring MVC automatische Validierung mit @Valid Annotation zu verwenden:

@RequestMapping 
public void checkUsername(Model model, @Valid User user, BindingResult result) { 
    if (result.hasErrors()) { 
     ... 
    } 
} 

Dies erfordert auch <mvc:annotation-driven/> in die Konfig.

+0

Vielen Dank! Genau das habe ich gesucht. Ich ging die Referenzdokumentation durch, aber ich suchte nach Dingen wie "Autowinding Services in Constraints". Danke noch einmal! –

+0

Ich mag die Bearbeitung mit der @Valid. Ich wünschte, ich könnte mehr als einmal upvote :) –

+0

Vielen Dank, Ihre Antwort hat mir geholfen, Zeit zu sparen! –

0

Anstatt einen neuen Validator zu erstellen, müssen Sie ihn auto- oder in den Controller injizieren. Die NPE des Dienstes, der nicht als Validator eingegeben wird, wird nicht im Frühling erstellt/verwaltet.

+0

Wenn ich den Validator direkt autowire, brauche ich den 'ConstraintValidatorContext', um' isValid' aufzurufen. Wie bekomme ich das? Es scheint mir auch ein wenig klüger. Gibt es einen besseren Weg, um das zu tun, was ich versuche? –