2012-10-01 19 views
9

Mam problem z automatyzacją komponentu bean wewnątrz niestandardowego sprawdzania poprawności. Instancja sprawdzania poprawności ograniczenia nie jest podana za pomocą Spring LocalValidatorFactoryBean. Dostawca JSR-303 jest weryfikatorem hibernacji 4.2.0.Final.Spring 3.1 Autowiring nie działa w niestandardowym kontrolerze więzów

Wiosna konfiguracja fragment:

<!-- JSR 303 validation --> 
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" /> 
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/> 

klienta Ograniczenie Validator:

import javax.validation.ConstraintValidator; 
import javax.validation.ConstraintValidatorContext; 

import org.springframework.beans.factory.annotation.Autowired; 

import com.model.Subject; 
import com.services.SomeTypeService; 

public class ReadOnlyValidator implements ConstraintValidator<ReadOnly, String> { 

@Autowired 
private SomeTypeService someTypeService; 

@Override 
public void initialize(ReadOnly constraintAnnotation) { } 

@Override 
public boolean isValid(String type, ConstraintValidatorContext context) { 
    try { 
     if (null != type) { 
         return !someTypeService.isReadonly(type); 
        } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 

    return false; 
} 
} 

Adnotacja:

import static java.lang.annotation.ElementType.*; 
import static java.lang.annotation.RetentionPolicy.*; 

import java.lang.annotation.Documented; 
import java.lang.annotation.Retention; 
import java.lang.annotation.Target; 

import javax.validation.Constraint; 
import javax.validation.Payload; 

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) 
@Retention(RUNTIME) 
@Constraint(validatedBy = ReadOnlyValidator.class) 
@Documented 
public @interface ReadOnly { 
String message() default "{constraints.subjecttype.readonly}"; 
public abstract Class<?>[] groups() default {}; 
public abstract Class<? extends Payload>[] payload() default {}; 
} 

SomeService:

@Validated 
public interface SomeService { 
    ... 
    public void updateType(@ReadOnly String type) throws SomeException; 
    ... 
} 

SomeServiceImpl:

@Service 
public class SomeServiceImpl implements SomeService { 
    ... 
    public void updateType(String type) throws SomeException { 
    // do something 
    } 
    ... 
} 

SomeTypeService jest kolejnym @Service adnotacją fasoli, które nie zależą od SomeService ...

Problemem jest to, że otrzymuję NPE jako autowiring nie działa; ktoś inny zarządza niestandardowymi instancjami sprawdzania poprawności, a nie wiosną ...

Z góry dziękuję za wszelkie porady.

+0

Pytanie Claudiu - Czy masz dwa różne konteksty aplikacji - jeden zadeklarowany przez ContextLoaderListener i jeden przez DispatcherServlet, ponieważ masz @validated na poziomie metod obsługi, prawdopodobnie musisz zadeklarować LocalValidatorFactoryBean również w kontekście aplikacji sieci web root? –

+0

Cóż, znalazłem kilka anomalii związanych z liczbą instancji LocalValidatorFactoryBean. Deklaracja, którą podałem w opisie "pytanie", znajduje się w service-content.xml => jest to jedna instancja. Inna instancja jest tworzona automatycznie podczas używania polecenia => Masz rację, jeśli masz główną aplikację WWW. –

+0

Po sprawdzeniu, że utworzono tylko jedną instancję LocalValidatorFactoryBean, przejdę do sprawdzenia, ile instancji ReadOnlyValidator zostało utworzonych. Korzystanie z jmap -histo: live | grep "ReadOnlyValidator", zauważyłem, że tworzone jest tylko jedno wystąpienie, ale tylko wtedy, gdy metoda usługi updateType jest wywoływana po raz pierwszy, a nie po zainicjowaniu LocalValidatorFactBean.Myślę, że silnik sprawdzania poprawności hibernacji tworzy po prostu własną instancję sprawdzania poprawności. W jaki sposób "zmusić" LocalValidatorFactoryBean do zarządzania instancją ReadOnlyValidator, aby można było użyć okablowania komponentu bean? –

Odpowiedz

9

Wystąpił problem. To samo "weryfikator" fasola odniesienia musi być stosowany przez MethodValidationPostProcessor i MVC: adnotacji napędzane deklarację:

service-context.xml

<!-- JSR 303 validation --> 
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/> 
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"> 
    <property name="validator" ref="validator"/> 
</bean> 
    ... 

dyspozytor-servlet.xml

... 
<mvc:annotation-driven validator="validator" /> 
... 
+0

Claudiu, oznacza to, że musimy zarejestrować każdy nowy walidator za pomocą metody MethodValidationPostProcessor. Czy wiesz, jak to wdrożyć za pomocą Java Config. Doświadczam tego samego problemu. Jedyną różnicą jest to, że jestem autowiring interfejs i że używam Java Config, a nie xml. – Tito

+0

Musiałem "wstrzyknąć" walidator do MethodValidationPostProcessor. –

+0

if bean LocalValidatorFactoryBean i MethodValidationPostProcessor zdefiniowane w dispatcher-servlet.xml @Validated nie będą działać. – Bodil

4

Tito, sprawdź, czy możesz użyć czegoś podobnego do konfiguracji Java:

@Configuration 
public class SampleConfig { 
    ... 

    @Bean 
    public Validator validator() { 
    return new LocalValidatorFactoryBean().getValidator(); 
    } 

    @Bean 
    public MethodValidationPostProcessor mvpp() { 
    MethodValidationPostProcessor mvpp = new MethodValidationPostProcessor(); 
    mvpp.setValidator(validator()); 

    return mvpp; 
    } 

    ... 
} 

Aby ponownie wykorzystać komponent bean weryfikatora w innym komponencie bean konfiguracji, można użyć adnotacji @Import.

Powiązane problemy