Spring boot Sanitizing json with #RequestBody - spring-boot

I am using spring boot 2.0.2.
My controller is
#RequestMapping(
value = "/process",
method = RequestMethod.POST)
public Response<String> abcd(#RequestBody Map<String, Object> payload) {
System.out.println(payload);
Response<String> s = new Response<>();
s.setData("aaaa");
return s;
}
So basically input is json. Now I want to sanitize my json via some library(not part of question).
My question is how can I do this? I mean where should I write this code?
I want a centralized solution like using AOP (aspect-oriented programming)?
How do i write my AOP?
What i just want is that I should get input as json, and return sanitized json and request body works as it is.

If you want to do this with AOP you could write an after advice for the code doing the json serialization and do the sanitize you want there. I think Spring boot use ObjectMapper to do the serialization. You can try to add your advice to the method writeValueAsString in the ObjectMapper class.
You can find a short intro on how to use AOP with Spring boot on https://www.baeldung.com/spring-aop.

Related

Given an assignment to return specific data using Springboot reactive but the JSON is really complicated

I am new to Springboot reactive
I was asked to call the following endpoint and return todays weather data only:
https://api.weather.gov/gridpoints/MLB/33,70/forecast
I believe I need to use something like this...
WebClient.create().get()
.uri("https://api.weather.gov/gridpoints/MLB/33,70/forecast")
.retrieve()
.bodyToMono(WeatherClass.class)
.block();
Do I need to map out an entire java object to match the JSON at the endpoint? is there an easy way to perhaps just grab the a certain piece of the JSON?
How would I handle something like the #context annotation in the JSON.
The WebClient in spring boot automatically uses Jackson's ObjectMapper to unmarshall json to a java object when the content type of the response is application/json. So there is no need to pull in any additional libraries or have to write any specific unmarshalling code, unless you want to use an alternate json-to-java library.
When using Jackson, you don't need to map every field in the json to your java object. You can annotate your java class with #JsonIgnoreProperties to inform jackson to ignore any properties that may appear in the json but do not have a matching field in your java object.
An example WeatherClass in which you want only the #context and forecastGenerator unmarshalled would look something like this
#JsonIgnoreProperties
public class WeatherClass {
private final List<Object> context;
private final WeatherProperties weatherProperties;
public WeatherClass(#JsonProperty("#context") List<Object> context,
#JsonProperty("properties") WeatherProperties weatherProperties) {
this.context = context;
this.weatherProperties = weatherProperties;
}
private class WeatherProperties {
private final String forecastGenerator;
private WeatherProperties(#JsonProperty("forecastGenerator") String forecastGenerator) {
this.forecastGenerator = forecastGenerator;
}
}
}
Note
#context seems to be an array that can contain multiple types (both objects and strings in your example). I've used Object to work around this but obviously isn't the most graceful solution but should be adequate to demonstrate how Jackson works
Alternatively, you can unmarshall the response to a JsonNode, which you can then use to traverse the structure of the json without converting it to a java object. For example
String forecastGenerator = WebClient.create().get()
.uri("https://api.weather.gov/gridpoints/MLB/33,70/forecast")
.retrieve()
.bodyToMono(JsonNode.class)
.block().get("properties").get("forecastGenerator").toString()
There are many other annotations provided by Jackson that can used to define how the unmarshaller functions. Too many to cover here. See Jackson Deserialisation Annotations

Kotlin Spring Boot form-urlencoded POST requests with a Map

I've just started playing around with Kotlin and Spring Boot and decided to write a simple endpoint that takes a form-urlencoded POST request. I didn't feel like writing an actual data class for the body, so I tried to just use a Map for the body, hoping I could just access key/value pairs. I first tried:
#RestController
class MyController {
#RequestMapping(value = "/endpoint", method = arrayOf(RequestMethod.POST),
consumes = arrayOf("application/x-www-form-urlencoded"))
fun myEndpoint(#RequestBody body: Map<String,String>): String {
// Do stuff
}
}
But that resulted in a 415 error about unsupported media type...which I read was due to the use of #RequestBody and form-urlencoded POSTs. I subsequently tried using the #ModelAttribute instead but then received
Failed to instantiate [java.util.Map]: Specified class is an interface
Hardly surprising as I was completely hacking. I also tried without any annotations for the body, but then none of the form parameters were injected. I know I could add a data class to solve this, but I'd like to know if this can be done generically using a Map as I've done a similar thing in Java before.
Thanks.
You need to annotate your body param with #RequestParam
#RequestMapping(value = "/endpoint", method = [(RequestMethod.POST)],
consumes = [MediaType.APPLICATION_FORM_URLENCODED_VALUE])
fun myEndpoint(#RequestParam body: Map<String,String>): String {
return //...
}
(Also note that I removed the arrayOf calls in favour of array literals, which are available for annotations as of Kotlin 1.2)

Spring automatically wrap rest controller response in ResponseEntity

Here is what I'm trying to achieve :
I have many spring rest reactive controller returning various Object such as Mono, Flux
I would like to wrap all these response in a ResponseEntity and so always return something like :
Mono<ResponseEntity<MyObjects>>
Any suggestion ?
Just use #ResponseBody Annotation on your controllers
When you use the #ResponseBody annotation on a method, Spring converts the return value and writes it to the http response automatically. Each method in the Controller class must be annotated with #ResponseBody.
See the example

Spring #InitBinder on #RequestBody

I'm trying to use the #InitBind annotation to map only certain fields on the object in the request body.
I have a spring controller defined in this way:
#RequestMapping(value = "addAddress", method = RequestMethod.POST)
public Object addAddressToPerson(
HttpServletRequest request,
HttpServletResponse res,
#RequestParam(value = "name", required = false) String name,
#RequestParam(value = "surname", required = false) String surname,
#RequestBody personDTO personJson,BindingResult result) {
The client request will be a a json representing a personDTO, but I don't want that field except the address to be mapped in the object for security reasons.
The input will be something like:
{ "address":"123 Street","........}
The personDTO contains many fields, and since spring map all of them directly in a DTO, that can be a problem.
I've seen that a solution is to use a Binder to declase the allowed or Disallowed field, but if I check the personDTO inside the controller, other fields are populate (for example if pass "id":"1234").
Any Hints?
The binder code is the following:
#InitBinder("orderJson")
protected void orderJsonBinder(WebDataBinder binder){
binder.setAllowedFields(new String[]{"address"});
}
Am I missing something?
Best Regards,
Luca.
But you are not binding request parameters to a model attribute bean, you are just asking spring to use an appropriate MessageConverter to convert the request body. As you say it is Json, you will use a MappingJackson2HttpMessageConverter (or MappingJacksonHttpMessageConverter with Jackson 1.x). The Spring Reference Manual says for this converter :
[This is an] HttpMessageConverter implementation that can read and write JSON using Jackson's ObjectMapper. JSON mapping can be customized as needed through the use of Jackson's provided annotations. When further control is needed, a custom ObjectMapper can be injected through the ObjectMapper property for cases where custom JSON serializers/deserializers need to be provided for specific types. By default this converter supports (application/json).
#InitBinder can only configure binding of #ModelAttribute annotated parameters. It is useless here. If Jackson annotations are not enough, you will have to use a custom object mapper.
And I am surprised that you can use a BindingResult after a #RequestBody parameter, because the documentation says that it should follow a #ModelAttribute one.

How do I render a JSON view/response via AJAX using Spring MVC annotation-based controller for portlets?

I've spent the last six hours scouring Google and stackoverflow for an answer to this question. I'm originally a PHP developer, so bear with me - returning a JSON array from a PHP controller is trivial.
I'm using Spring MVC 3.0, and I simply want to return a JSON object back to some Javascript from my Spring MVC Controller. It seems that there is no easy way to currently do this using a portlet (https://jira.springsource.org/browse/SPR-7344). Solutions I have seen suggest creating another DispatcherServlet that serves up JSON responses, but I have yet to find a well-documented example of this. If anyone knows a good way to accomplish this (preferably with annotations), please do tell!
I ended up finding a workaround to return "JSON" from a Spring MVC portlet controller. Here's how I did it.
In my controller:
#ResourceMapping("ajaxTest")
public void ajaxHandler(ResourceRequest request, ResourceResponse response)
throws IOException {
OutputStream outStream = response.getPortletOutputStream();
StringBuffer buffer = new StringBuffer();
Map<String, String> testMap = new HashMap<String, String>();
testMap.put("foo", "bar");
String test = new JSONObject(testMap).toString();
buffer.append(test);
outStream.write(buffer.toString().getBytes());
}
In "view.jsp":
<portlet:resourceURL var="ajaxtest" id="ajaxTest"/>
<script type="text/javascript">
$.get('<%= ajaxtest %>', function(response) {
var json = eval('(' + response + ')');
});
</script>
Since the #ResourceMapping annotation currently doesn't support returning JSON, I just used org.json.JSONObject to convert my map to a JSON object, and then returned the toString() of this object. The value of #ResourceMapping should match the id of the resourceURL. The use of eval to convert the JSON string to Javascript poses a security risk, but I just included it because it's the simplest example. If you are worried about security, use a JSON parser.
http://blog.springsource.com/2010/01/25/ajax-simplifications-in-spring-3-0/ does not apply to portlets at this time. See: https://jira.springsource.org/browse/SPR-7344
I was able to make it work in Spring 3.0.5 with two simple modifications:
Implementing custom WebArgumentResolver to parse an object from JSON from ResourceRequest body
Returning MappingJacksonJsonView from my controller's method.
Available in Spring 3.1 only - you may want to use setExtractValueFromSingleKeyModel in your MappingJacksonJsonView
If anybody is in intereset, I can post java code
Elaborating on #alex answer:
#ResourceMapping(value = "showJson")
public ModelAndView showJson(ResourceRequest request) {
ModelAndView mav = new ModelAndView(new
MappingJacksonJsonView());
mav.addObject("key", myBeanToBeSerializedAsJson);
return mav;
}
Starting with Spring 3, a controller will automatically convert to json if using ajax get/post with application type of json (i.e. .getJSON and .postJSON in jQuery). This functionality is identical between the servlet and portlet variations of Spring MVC.
Here is a blog post explaining it.
http://blog.springsource.com/2010/01/25/ajax-simplifications-in-spring-3-0/

Resources