Spring Boot #ControllerAdvice #ExceptionHandler content type via an annotation - spring

I know e.g. status can be set via an annotation:
#ExceptionHandler(MyException.class)
#ResponseStatus(HttpStatus.BAD_REQUEST)
public String handleMyException(MyException myException) {
return myException.getMessage();
}
I know I can make a ResponseEntity with the appropriate content type like this:
#ExceptionHandler(MyException.class)
public ResponseEntity<String> handleMyException(MyException myException) {
return ResponseEntity
.badRequest()
.header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
.body(myException.getMessage());
}
Is it possible to set the content type via annotation only, i.e. something like this:
#ExceptionHandler(MyException.class)
#ContentType(MediaType.TEX_PLAIN_VALUE)
public String handleMyException(MyException myException) {
return myException.getMessage();
}
I couldn't find an annotation that would do that.

According to spring documentation (same for boot as well), you can set only #ResponseStatus annotation with ExceptionHandler.
https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ExceptionHandler.html

Related

How do I set the HttpStatus code when using #ResponseBody?

In a SpringBoot Controller class, my APIs usually return a ResponseEntity with a body and a status code. But I can apparently dispense with the ResponseEntity by annotating my controller method with #ResponseBody, like this:
#Controller
public class DemoController
{
#Autowired
StudentService studentService;
#GetMapping("/student")
#ResponseBody
Student getStudent(#RequestParam id) {
return studentService.getStudent(id);
}
}
If my service throws an exception, I can return a custom HTTP status by throwing a ResponseStatusException, but it's not clear how to specify the HTTP status for a valid response. How would I specify this? Or how does it decide what to use?

AutoConfigure RestController Spring Boot

I have tried to find documentation on how to manually configure a RestController (i.e in a Configuation class). That means without using the RestController annotation. Considering all the other annotations, like mapping, pathvariables etc. is at all possible?
A controller is essentially a component with a request mapping. See RequestMappingHandlerMapping.
#Override
protected boolean isHandler(Class<?> beanType) {
return (AnnotatedElementUtils.hasAnnotation(beanType, Controller.class) ||
AnnotatedElementUtils.hasAnnotation(beanType, RequestMapping.class));
}
If you want to instantiate a "rest controller" through configuration, you can probably do so via the following:
#Configuration
public class MyConfiguration {
#Bean
public MyController() {
return new MyController();
}
}
#ResponseBody
public class MyController {
#RequestMapping("/test")
public String someEndpoint() {
return "some payload";
}
}
But I don't think you'll be able to configure the request mappings (path variables, etc) in the configuration though; at least I haven't seen an example nor figured out how.

Authenticate Operation Before Each Action In Spring Boot Effectively

I have a code block like below. For each method, I call action authentication. Is it possible to do with annotation or other thing effectively?
#GetMapping
public ResponseEntity getAction(#PrincipalUser user, Long actionId)
{
repository.checkUserForAction(user.getId(), actionId);
implement actions...
return service call;
}
#PostMapping
public ResponseEntity addAction(#PrincipalUser user)
{
repository.checkUserForAction(user.getId());
implement actions...
return service call;
}
#DeleteMapping
public ResponseEntity addAction(#PrincipalUser user, Long actionId)
{
repository.checkUserForAction(user.getId(), actionId);
implement actions...
return service call;
}
Actually, in here my other problem is that I call repository method each time and I know this is not an effective way.
You could use Spring Security and #PreAuthorize annotation.
Example:
#PreAuthorize("#authorizationService.check(#actionId)")
#DeleteMapping
public ResponseEntity performAction(Long actionId) {
implement actions...
}
And encapsulate authorization logic inside authorizationService, moreover authorizationService must be a bean and #EnableGlobalMethodSecurity(prePostEnabled = true) must be set.

Spring 4 RestController - How to return jaxb object with ResponseEntity

I am using Spring #RESTController for my REST webservice. instead of returning the object of ModelAndView I am trying to return the object of ResponseEntity object in my rest method. for the Strgin type of response it is working ut when I am building ResponseEntity with a Jaxbobject it is giving me HTTP error 406
#RestController
#RequestMapping(value="/service")
public class MyController {
public #ResponseBody ResponseEntity<String> getDashBoardData() throws JAXBException {
// Some Operation
return new ResponseEntity<String>(myStringXML, responseHeaders, HttpStatus.OK);
}
}
Below is not working
#RestController
#RequestMapping(value="/service")
public class MyController {
public #ResponseBody ResponseEntity<MyJaxbClass> getDashBoardData() throws JAXBException {
// Some Operation
return new ResponseEntity<MyJaxbClass>(MyJaxbClassObject, HttpStatus.OK);
}
}
The #RestController annotation already implies the #ResponseBody annotation for all request handling methods, that is one of its purposes (it saves you from putting all those annotations there). So you can/should remove it.
Processing the return value of the method is done by a 'HandlerMethodReturnValueHandlerand the specific one which should handle this delegates to aHttpMessageConverter. It selects a specificHttpMessageConverterbased on the requested/supported response types for the current request and the support response types from theHandlerMethodReturnValueHandler`.
In general when using #EnableWebMvc or <mvc:annotation-driven /> everything should be setup automatically. The automatic setup does some detection on which libs are available (jaxb, json etc).
Based on the response code (406) you either have manually configured something wrong on the server side or the client doesn't support xml as a response type.

Can not get param from json request when using spring aop

I am using spring AOP to check permission
#Component
#Aspect
public class PermissionManager {
#Around(value = "#annotation(requiredPermission) && args(id,..)", argNames = "id,requiredPermission")
public Object checkCanViewFile(ProceedingJoinPoint pjp, String id, RequiredPermission permission) throws Throwable {
...
}
}
Controller
#RequiredPermission(RequiredPermission.OperationType.editProject)
#RequestMapping("/searchFile")
public #ResponseBody
WebFile search(String id, String word) throws TokenExpiredException, FetchException {
...
}
It works on spring mvc test but can not working on real environment. the value of 'id' is null, I doubt spring AOP get this method before jackson objectmapper, is it right? How can fix it?

Resources