Mam problemy podczas używania @ControllerAdvice i @Valid adnotacji razem w kontrolerze REST.Wiosna Reszta ErrorHandling @ControllerAdvice/@Valid
Mam kontroler reszta zadeklarowana następująco:
@Controller
public class RestExample {
...
/**
* <XmlRequestUser><username>user1</username><password>password</password><name>Name</name><surname>Surname</surname></XmlRequestUser>
* curl -d "@restAddRequest.xml" -H "Content-Type:text/xml" http://localhost:8080/SpringExamples/servlets/rest/add
*/
@RequestMapping(value="rest/add", method=RequestMethod.POST)
public @ResponseBody String add(@Valid @RequestBody XmlRequestUser xmlUser) {
User user = new User();
user.setUsername(xmlUser.getUsername());
user.setPassword(xmlUser.getPassword());
user.setName(xmlUser.getName());
user.setSurname(xmlUser.getSurname());
// add user to the database
StaticData.users.put(xmlUser.getUsername(), user);
LOG.info("added user " + xmlUser.getUsername());
return "added user " + user.getUsername();
}
}
I klasa ErrorHandler:
@ControllerAdvice
public class RestErrorHandler extends ResponseEntityExceptionHandler {
private static Logger LOG = Logger.getLogger(RestErrorHandler.class);
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<Object> handleException(final RuntimeException e, WebRequest request) {
LOG.error(e);
String bodyOfResponse = e.getMessage();
return handleExceptionInternal(e, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
}
}
Problemem jest to, że jeśli dodać "throw new RuntimeException" obrębie metoda RestExample.add następnie wyjątek jest poprawnie obsługiwany przez klasę RestErrorHandler.
Jednak gdy Curlingu nie ważny wniosek do sterownika RestErrorHandler nie złapać wyjątek rzucony przez walidator i otrzymać odpowiedź 400 BadRequest. (W przypadku nie ważny wniosek Znaczy żądanie xml gdzie Nazwa użytkownika nie jest określona)
Zauważ, że XmlRequestUser klasa wygenerowaną automatycznie przez wtyczkę maven-jaxb2-plugin + krasa-jaxb-tools (pom.xml):
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaDirectory>src/main/xsd</schemaDirectory>
<schemaIncludes>
<include>*.xsd</include>
</schemaIncludes>
<args>
<arg>-XJsr303Annotations</arg>
<arg>-XJsr303Annotations:targetNamespace=http://www.foo.com/bar</arg>
</args>
<plugins>
<plugin>
<groupId>com.github.krasa</groupId>
<artifactId>krasa-jaxb-tools</artifactId>
<version>${krasa-jaxb-tools.version}</version>
</plugin>
</plugins>
</configuration>
</plugin>
The wygenerowana klasa ma poprawnie pola @NotNull Adnotacja na polu Nazwa użytkownika i Hasło.
Moja context.xml jest bardzo proste, zawierające tylko skaner dla kontrolerów i umożliwiający MVC: adnotacji napędzane
<context:component-scan base-package="com.aa.rest" />
<mvc:annotation-driven />
Czy ktoś wie jak zrobić pracę @ControllerAdvice i @Valid adnotacji razem w Kontroler REST?
Z góry dziękuję. Antonio
Dzięki, właśnie tego szukałem. –
@matsev Zamiast rozszerzać ResponseEntityExceptionHandler i przesłonić metodę handleMethodArgumentNotValid, czy nie mógłby po prostu użyć obiektu @ExceptionHandler (MethodArgumentNotValidException.class)? – Stephane
@StephaneEybert Pewnie, czemu nie. Zdecydowałem się rozszerzyć 'ResponseEntityExceptionHandler', ponieważ zostało ono już rozszerzone w pierwotnym pytaniu. Powiązane: przy użyciu adnotacji '@ ControllerAdvice' (niezależnie od tego, czy rozszerzysz' ResponseEntityExceptionHandler' lub użyjesz adnotacji '@ ExceptionHandler') uzyskasz spójną obsługę błędów dla wszystkich kontrolerów. – matsev