I'm wanting to return/throw an object depending on some logic inside the controller.
For example lets say something required a user to login I'd want to return an appropriate message
throw a new ReturnLoginMessage("Must login", "xx@xx.com", 111)
I can't just throw ReturnLoginMessage as it'd just return the following:
"exception": "com.userapi.returntypes.ReturnLoginMessage"
Which is not useful at all! I'd want the JSON representation of that returnloginmessage object.
{
"message": "Must login",
"email": "xx@xx.com",
"code": "111"
}
Is this possible given the following controller? What this controller does is check to see if the user already exists, if it does, they must login (which is why I'm returning the returnloginmessage object.
@RequestMapping(value="login/email", method=RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_VALUE })
UserCredential login(@RequestBody UserFacebookLoginContext body) throws IOException, InvalidKeySpecException,
NoSuchAlgorithmException, ConfirmLogin, ClassNotFoundException, ConfirmResponse, InvalidRequestException, ConfirmLoginEmail {
... Logic that checks to see if user exists....
if (user does exist)
throw new ReturnLoginMessage("Must login", "xx@xx.com", 111); // THis returns "exception": "com.userapi.returntypes.ReturnLoginMessage"
else if(other condition)
throw new OtherMessage("...", "...");
else
return UserCredential;
Is there away I can return a JSON representation of the ReturnLoginMessage ? Given the following Java object?
public class ReturnLoginMessage extends Exception {
private int code;
private String message;
private String email;
private Date timestamp;
public ReturnLoginMessage(int code, String message) {
this.code = code;
this.email = email;
this.timestamp = new Date();
}
public ReturnLoginMessage(String message, int code, String email) {
super(message);
this.code = code;
this.email = email;
this.timestamp = new Date();
}
... Getters .... Setters ...
}
You could achieve this by declaring a new ExceptionHandler
method for ReturnLoginMessage.class
. See this answer.
Other approach would be to extend the return value of the login
to something more generic. For example:
Declare it return Object
instead of UserCredentials
and simply return ReturnLoginMessage instead of throwing it.
Declare it return Map<String,Object>
and construct the proper key/value pairs for both scenarios. See this answer
I acheived almost same thing(perhaps) by this way
first
add a ExceptionHandler at your REST Controller and return your exception as a JSON (put a @ResponseBody).
@Controller
@RequestMapping("/rest")
public class RestfulTodoController {
@ExceptionHandler(ReturnLoginMessage.class)
@ResponseBody
public ReturnLoginMessage handleException(final ReturnLoginMessage e) {
return e;
}
// and your login handler method
}
check whether response is Json and also returning type is ReturnLoginMessage at advice that extends AbstractMappingJacksonResponseBodyAdvice, if response is ReturnLoginMessage then modify response as you like
@ControllerAdvice
public class MyResponseBodyAdvice extends AbstractMappingJacksonResponseBodyAdvice {
@Override
public boolean supports(final MethodParameter returnType,
final Class<? extends HttpMessageConverter<?>> converterType) {
return super.supports(returnType, converterType)
&& null != returnType.getMethodAnnotation(ResponseBody.class);
}
@Override
protected void beforeBodyWriteInternal(final MappingJacksonValue bodyContainer, final MediaType contentType,
final MethodParameter returnType, final ServerHttpRequest request, final ServerHttpResponse response) {
if (bodyContainer.getValue() instanceof ReturnLoginMessage) {
//set some object as you like
bodyContainer.setValue();
}
}
}
}
finally
register above your advice as a Bean
@Configuration
public class WebAppConfiguration {
@Bean
public MyResponseBodyAdvice myResponseBodyAdvice() {
return new MyResponseBodyAdvice();
}
}
Use Fasterxml Jackson library best JSON parser for Java
Fasterxml Jackson convert Java Collection directly into JSON.
Maven Dependency
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${faster-xml-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${faster-xml-version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${faster-xml-version}</version>
</dependency>
Controller Code
@RequestMapping(value="login/email", method=RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_VALUE })
@ResponseBody
Map<String, Object> login(@RequestBody UserFacebookLoginContext body) throws IOException, InvalidKeySpecException,
NoSuchAlgorithmException, ConfirmLogin,
ClassNotFoundException, ConfirmResponse, InvalidRequestException,
ConfirmLoginEmail {
... Logic that checks to see if user exists....
if (user does exist)
return Utility.getSuccessResponse("message","Must
login","email","xx@xx.com","code",111);
else if(other condition)
return Utility.getSuccessResponse("", "");
else
return Utility.getSuccessResponse("userCredential", UserCredential);
Utility Class
public class Utility {
public static Map<String, Object> getSuccessResponse(Object... responseContent) {
if (responseContent.length % 2 != 0) {
throw new IllegalArgumentException();
}
Map<String, Object> responseObject = new HashMap<String, Object>();
Map<String, Object> responseList = new HashMap<String, Object>();
for (int i = 0; i < responseContent.length; i = i + 2) {
responseList.put(responseContent[i].toString(), responseContent[i + 1]);
}
responseObject.put("result", responseList);
return responseObject;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.