Reputation: 3592
I have been developing rest api service using spring boot. This is my rest controller
@RequestMapping(value = "owner/login", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
@ResponseBody
public ResponseEntity<String> login(@RequestBody Owner owner) throws TimeoutException, SocketTimeoutException, SocketException {
controller.login(owner);
return ResponseEntity.ok("\"error\": 0");
}
This is controller
public JsonObject login(Owner loginOwner){
Map<String,String> params = new HashMap<String,String>();
params.put("email", loginOwner.getEmail());
params.put("password", loginOwner.getPassword());
if(GMoikaStringUtils.isEmpty(loginOwner.getEmail()) || !GMoikaStringUtils.isValidEmail(loginOwner.getEmail())){
throw new InvalidUserInputException("Wrong email format", CLASS_NAME, "login", params, "owners/owner/login POST");
}
else{
someLogic...
}
}
The question is, using this structure i should to create map with params inside each method.How to avoid creation of map inside each method and put all params into this map? I need "MAP" to show params in logs in case if exception is occured. Maybe spring boot can do it , but i can't find my case in official docs. Thanks in advance
Upvotes: 3
Views: 2448
Reputation: 44665
If you only want to do this after an InvalidUserInputException
is thrown, you could write an exception handler:
@ExceptionHandler(InvalidUserInputException.class)
@ResponseBody
public ValidationError getError(InvalidUserInputException ex) {
// ...
}
Since InvalidUserInputException
is a custom exception, you could add a field of type Object
in which you can pass your request body, for example:
throw new InvalidUserInputException("Wrong email format", loginOwner);
Now you can use the toString()
method of the Owner
object to log it. If you want to get it in a JSON style, you can use Apache commons and their ToStringBuilder
:
@Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.JSON_STYLE)
.append("email", email)
.append("password", password)
.toString();
}
Alternatively, if you don't want to rely on using the toString()
method and just want to return the plain request body, you can also add HttpServletRequest
as a parameter to an exception handler.
Before you do that, you have to wrap it though, because the request body can only be read once, and to overcome that problem you should "cache" the request body once it's read. To do this, you can use Spring their ContentCachingRequestWrapper
.
To wrap it, you should write your own Filter
. You can do this by extending from Spring their OncePerRequestFilter
like this:
ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
wrapper.getContentAsByteArray();
@Component
public class RequestWrapperFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(new ContentCachingRequestWrapper(httpServletRequest), httpServletResponse);
}
}
Now you can get the request body in the exception handler by calling the getContentAsByteArray()
method. To get the request body as a String you can use IOUtils
from Apache Commons:
ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
logger.warn("Input validation failed, request body: {}", IOUtils.toString(wrapper.getContentAsByteArray(), wrapper.getCharacterEncoding()));
This will log the entire request body as a string. Be careful with logging sensitive information though.
Upvotes: 2
Reputation: 1070
You can use any Logger, like Log4j and log in else statement:
Steps to follow:
1. Download latest log4j distribution.
2. Add log4j’s jar library into your program’s classpath.
3. Create log4j’s configuration.
4. Initialize log4j with the configuration.
5. Create a logger.
6. Put logging statements into your code.
Logger logger = Logger.getLogger(MyClass.class);
public JsonObject login(Owner loginOwner){
Map<String,String> params = new HashMap<String,String>();
params.put("email", loginOwner.getEmail());
params.put("password", loginOwner.getPassword());
if(GMoikaStringUtils.isEmpty(loginOwner.getEmail()) || !GMoikaStringUtils.isValidEmail(loginOwner.getEmail())){
throw new InvalidUserInputException("Wrong email format", CLASS_NAME, "login", params, "owners/owner/login POST");
}
else{
logger.info("Log this event");
}
}
Refer here: http://www.codejava.net/coding/how-to-configure-log4j-as-logging-mechanism-in-java
Upvotes: 1