Jackson JSON mapping of Strings - spring-mvc

I used POJO's as #RequestBody parameters and they worked fine. But now I try something like this public void func(#RequestBody String s) and cant pass the value to String s. When I used POJO's I writes {"attribute" : "value"} in request and the question is what I should write in POSTMAN to pass the value?

If you want to send only string value then it is better idea to use #RequestParam and in postman client you can send key value parameter.
public String method(#RequestParam("key") String value){
}

Related

Array in Api's Query String

Using WebClient do send an array to an ApiController via query string I get the error 400.
The api method looks like
public IHttpActionResult List([FromUri] Model model)
In the Model class I have
public int[] Ids { get; set; }
In the client side the code looks like:
webClient.QueryString.Add("ids", "1");
webClient.QueryString.Add("ids", "2");
...
await webClient.DownloadStringTaskAsync(url);
If I send just one "ids" parameter the code works fine, but not with two or more.
I found that the client creates the url like "url?ids=1,2" instead "url?ids=1&ids=2".
Is there some configuration I missed?
WebClient will automatically turn multiple values with the same key into a comma separated string. You can change this behavior, see: How to build WebClient querystring with duplicate keys?
I would recommend using HttpClient instead of WebClient though.

Spring controller return string as pure json

I am returning a string object from spring controller like
#RequestMapping(value = "/persons.html", method = RequestMethod.GET)
public #ResponseBody String listPersonHtml(Model model) {
return "{\"abc\":\"test\"}";
}
I am getting response on ui like "{\"abc\":\"test\"}",i want this response as
{"abc":"test"}
i.e pure json object.
what type of configuration I need?
On UI side,if I set Accept */* then I face this issue,if I set Accept text/html or Accept text/plain then no issue is there,but I can't change accept header.
I found the way.Its all about spring message-converters.I added MappingJackson2HttpMessageConverter in this list and this converter tries to convert string to json and produces this result.
Just add org.springframework.http.converter.StringHttpMessageConverter before MappingJackson2HttpMessageConverter so that StringHttpMessageConverter can come into action and string can be returned as it is.
Old question, but I just had to solve the same issue and most of the answers I found resulted misleading, so here's mine:
It all starts with the Controller, and Spring trying to answer a mapped request in the format that the invoking client is expecting. The client can inform this using different HTTP features, and there is where the different HttpMessageConverter implementations are involved. Spring pick's the format to answer based on different strategies, applied by the ContentNegotiationManager.
By prioritizing StringHttpMessageConverter over MappingJackson2XmlHttpMessageConverter you are only telling Spring to answer in "text/plain" format over "application/json", and it will work until a client specifies that is expecting a json response (this is mostly done by setting the Accept header in the request, although there are other ways to do it). The important thing is that if a client sets that header to "application/json", Spring will use MappingJackson2XmlHttpMessageConverter that will translate the Java String to a Json String, ending up with something like "{\"abc\":\"test\"}" instead of {"abc":"test"}
So, the real issue that every developer faces in this case is that MappingJackson2XmlHttpMessageConverter translates a Java String to a Json String, and in some cases, you might not need that, because the string contains valid json that needs to be returned without modifications. There are some configuration classes for this MessageConverter but I did'n went that road, because I need to return Strings like "raw" Json only in some specific endpoints (performance is the key driver). Here's an expample that resumes my "approach":
#RestController
#RequestMapping(value = "test", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public class TestController {
#RequestMapping(method = RequestMethod.GET, value = "endpoint")
public JsonObject getSomeJson() {
return new JsonObject("{\"abc\":\"test\"}");
}
private static class JsonObject {
private String rawJsonValue;
JsonObject(String rawJsonValue) {
this.rawJsonValue = rawJsonValue;
}
#JsonValue #JsonRawValue
public String getRawJsonValue() {
return rawJsonValue;
}
}
}
#JsonValue and #JsonRawValue are Jackson annotations that tell MappingJackson2XmlHttpMessageConverter to treat the getRawJsonValue method result as the Json representation of JsonObject, without making any modification. The response of the endpoint will be {"abc":"test"}

Spring MVC - #RequestParam causing MissingServletRequestParameterException with x-www-form-urlencoded

The follwing Spring MVC code throws MissingServletRequestParameterException,
#Controller
#RequestMapping("/users")
public class XXXXResource extends AbstractResource {
.....
#RequestMapping(method = RequestMethod.PUT
, produces = {"application/json", "application/xml"}
, consumes = {"application/x-www-form-urlencoded"}
)
public
#ResponseBody
Representation createXXXX(#NotNull #RequestParam("paramA") String paramA,
#NotNull #RequestParam("paramB") String paramB,
#NotNull #RequestParam("paramC") String paramC,
#NotNull #RequestParam("paramD") String paramD ) throws Exception {
...
}
}
There are no stack traces in the logs, only the Request from Postman returns with HTTP 400 Error.
if you want to Content-type:application/x-www-form-urlencoded means that the body of the HTTP request sent to the server should be one giant string -- name/value pairs are separated by the ampersand (&) and will be urlencoded as his name implies.
name=name1&value=value2
this means that you should not user #RequestParam because the arguments are passed in the body of the http request.
So if you want to use this content-type from their doc:
You convert the request body to the method argument by using an
HttpMessageConverter. HttpMessageConverter is responsible for
converting from the HTTP request message to an object and converting
from an object to the HTTP response body. The
RequestMappingHandlerAdapter supports the #RequestBody annotation with
the following default HttpMessageConverters:
ByteArrayHttpMessageConverter converts byte arrays.
StringHttpMessageConverter converts strings.
FormHttpMessageConverter converts form data to/from a MultiValueMap.
SourceHttpMessageConverter converts to/from a
javax.xml.transform.Source.
You should use #RequestBody with FormHttpMessageConverter, which will get this giant string and will convert it to MultiValueMap<String,String>. Here is a sample.
#RequestMapping(method = RequestMethod.PUT
, consumes = {"application/x-www-form-urlencoded"}
,value = "/choice"
)
public
#ResponseBody
String createXXXX(#RequestBody MultiValueMap params) throws Exception {
System.out.println("params are " + params);
return "hello";
}

HttpServletRequest - Get Literal Path

I have a method marked with Spring's #RequestMapping that includes an HttpServletRequest method parameter.
If I print out the results of a call to "request.getServletPath()" when the path is, say, "/things/{thingId}", I will get "/things/2489sdfjk43298f," where the {thingId} path parameter has been replaced with the actual value.
I want to print out the literal request path "/things/{thingId}"; I.e. with the curly-braced, un-replaced path parameter "{thingId}."
Is this possible in any way?
Edit: After looking at Sotirios's second comment below, I realize I may be looking at the problem backward. Here's what I'm actually trying to do...
I am trying to making a single endpoint under "/**" that gets the path from the HttpServletRequest, which I use to look up a value in an enum. This enum has several fields, one of which is obviously the aforementioned path, but another is the path of a target JSP file. I then put this path into a ModelAndView object and return it to display the page.
This was going just fine until I hit the first endpoint with a path parameter, because I obviously can't place the value "/things/2489sdfjk43298f" into the enum, because that will only match for that one specific thing with that one specific ID.
So perhaps the actual question would be: How would I do that look-up when parts of the path will change due to path parameters? Is there some sort of wildcard-containing String format I can use?
I guess this is turning into more of a enum-lookup/String-matching question. My bad.
Edit 2: Shortened example of the enum thing I'm talking about:
public enum JspEndpointType {
HOME("/home", "jsp/home");
private static final Map<String, String> pathMap;
private String requestPath;
private String jspPath;
static {
pathMap = new HashMap<>();
for (JspEndpointType jspEndpointType : JspEndpointType.values()) {
pathMap.put(jspEndpointType.getRequestPath(), jspEndpointType.getJspPath());
}
}
private JspEndpointValue(String requestPath, String jspPath) {
this.requestPath = requestPath;
this.jspPath = jspPath;
}
public String getRequestPath() {
return requestPath;
}
public String getJspPath() {
return jspPath;
}
public static String getByRequestPath(String requestPath) {
return pathMap.get(requestPath);
}
}
Shortened example of my endpoint:
#RequestMapping(value = "/**", method = RequestMethod.GET)
public ModelAndView showPage(HttpServletRequest request) {
return new ModelAndView(JspEndpointType.getByRequestPath(request.getServletPath()));
}
So things essentially boil down to trying to add to the enum a value like this:
THINGS("/things/{thingId}", "jsp/things/whatever")
..and then being able to pass in the path "/things/2489sdfjk43298f" and get back "/jsp/things/whatever."
Edit 3: I found this StackoverFlow question which directed me to Spring's UriComponentsBuilder, specifically the "fromPath" method. However, that seems to be the reverse of what I'm trying to do...
You may look for the #RequestMapping annotation on your own, using reflection.

how to process variable numbers of parameters for jersey post requests

I've got a Jersey REST server that responds to post requests like so:
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String postHtml() {
I don't know ahead of time the names of all the parameters that might be sent to me. With a GET request I handle this like:
#Context
private UriInfo context;
#GET
#Produces(MediaType.TEXT_HTML)
public String getHtml() {
MultivaluedMap<String, String> queryParameters = context.getQueryParameters();
how can I do a similar thing with a POST request. I simply want to get all the parameters supplied in the post and I'll work with them in my code.
Turns out you can do:
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String postHtml(MultivaluedMap<String, String> inFormParams) {
If all your parameters are String type, which mine are. It would be good to know what to do if you have non-String parameters.

Resources