Recenlty I have big problem with Polish Characters in JSON response from the server. I have simple Ajax request for this:
jQuery.ajax( "/GetSimpleRuleList",
{
type:"GET",
responseType:"application/json;charset=utf-8",
contentType:"application/json;charset=utf-8",
cache:false
} ).done( function ( data )
{
console.log( data );
//nevermind here
} );
And appropriate Controller at server end:
#RequestMapping(value = "/GetSimpleRuleList", method = RequestMethod.GET)
public
#ResponseBody
String getRuleList( ServletResponse response )
{
//magically getting my list here
response.setCharacterEncoding( "UTF-8" );
return //Using JACKSON ObjectWriter here
}
Now I'm 100% sure that encoidng on server side and database from where I take data from is OK, no problem with that.
But when It comes to reading response from server it is:
???
instead of Polish char like:
ąćź
Moreover it only fails when receiving response from server, while sending a request with data is encoded correctly.
In my web.xml I have filter for character encoding.
Any help with this? I'm out of ideas.
Now I'm 100% sure that encoidng on server side and database from where I take data from is OK
try adding the Content-Type header if it's not already present int your response:
response.setHeader("Content-Type", "application/json;charset=UTF-8")
Get sure to use UTF-8 charset when reading from database. Jackson's encoding defaults to UTF-8, so your data might not be encoded using UTF-8?!?
what encoding do you use when reading from database? maybe ISO-8859-2?
Try changing your response type to org.springframework.http.ResponseEntity
public ResponseEntity<String> getRuleList(){
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("Content-Type", "application/json; charset=utf-8");
responseHeaders.setCacheControl("no-cache, max-age=0");
String allyourjson = "yourjsongoeshere";
return new ResponseEntity<String>(allyourjson, responseHeaders, HttpStatus.OK);
}
You can use spring annotation RequestMapping above controller class for receveing application/json;utf-8 in all responses
#Controller
#RequestMapping(produces = {"application/json; charset=UTF-8","*/*;charset=UTF-8"})
public class MyController{
...
#RequestMapping(value = "/GetSimpleRuleList", method = RequestMethod.GET)
public
#ResponseBody
String getRuleList( ServletResponse response )
{
//magically getting my list here
response.setCharacterEncoding( "UTF-8" );
return //Using JACKSON ObjectWriter here
}
...
}
Related
I am new to web programming in general, especially in Java, so I just learned what a header and body is.
I'm writing RESTful services using Spring MVC. I am able to create simple services with the #RequestMapping in my controllers. I need help understanding how to get HTTP header information from a request that comes to my method in my REST service controller. I would like to parse out the header and get some attributes from it.
Could you explain how I go about getting that information?
When you annotate a parameter with #RequestHeader, the parameter retrieves the header information. So you can just do something like this:
#RequestHeader("Accept")
to get the Accept header.
So from the documentation:
#RequestMapping("/displayHeaderInfo.do")
public void displayHeaderInfo(#RequestHeader("Accept-Encoding") String encoding,
#RequestHeader("Keep-Alive") long keepAlive) {
}
The Accept-Encoding and Keep-Alive header values are provided in the encoding and keepAlive parameters respectively.
And no worries. We are all noobs with something.
You can use the #RequestHeader annotation with HttpHeaders method parameter to gain access to all request headers:
#RequestMapping(value = "/restURL")
public String serveRest(#RequestBody String body, #RequestHeader HttpHeaders headers) {
// Use headers to get the information about all the request headers
long contentLength = headers.getContentLength();
// ...
StreamSource source = new StreamSource(new StringReader(body));
YourObject obj = (YourObject) jaxb2Mashaller.unmarshal(source);
// ...
}
My solution in Header parameters with example is user="test" is:
#RequestMapping(value = "/restURL")
public String serveRest(#RequestBody String body, #RequestHeader HttpHeaders headers){
System.out.println(headers.get("user"));
}
You can use HttpEntity to read both Body and Headers.
#RequestMapping(value = "/restURL")
public String serveRest(HttpEntity<String> httpEntity){
MultiValueMap<String, String> headers =
httpEntity.getHeaders();
Iterator<Map.Entry<String, List<String>>> s =
headers.entrySet().iterator();
while(s.hasNext()) {
Map.Entry<String, List<String>> obj = s.next();
String key = obj.getKey();
List<String> value = obj.getValue();
}
String body = httpEntity.getBody();
}
Using REST with RESTEasy and Swagger, is there any way to stream data back to the caller with a GET endpoint? I've seen a couple of examples where the entire stream can be returned, but I haven't seen any examples where the data can actually be streamed back. I also did have a look at this example(followed from this link-Return File From Resteasy Server) however, this example looks like it is returning a stream and expecting the caller to utilize the stream? Is this a correct assumption?:
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
#Path("/stream/test")
public Response getTestStream() {
String myName = "name";
InputStream stream = new ByteArrayInputStream(myName.getBytes(StandardCharsets.UTF_8));
return Response.ok().entity(stream).build();
}
But this does not seem to work for me. I get an exception: javax.ws.rs.NotAcceptableException: RESTEASY003635: No match for accept header.
Any help would be greatly appreciated!
You can return Object of inputstream object in Response.
For e.g.
#GetMapping(value = "/stream/test")
#ResponseBody
public ResponseEntity<?> getTestStream() {
String myName = "name";
InputStream stream = new ByteArrayInputStream(myName.getBytes(StandardCharsets.UTF_8));
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
return ResponseEntity
.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(new InputStreamResource(stream));
}
I am trying to create a RESTful service and encounter a type conflict within the application. Right now, I deal with this problem by using two different URLs, but this leads to other problems and doesn't feel right.
// Controller to get a JSON
#RequestMapping(value = "/stuff/{stuffId}",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public stuffDto getStuff(#PathVariable String stuffId) {
return //JSON DTO//
}
// Controller to get an HTML Form
#RequestMapping(value = "/stuff/{stuffId}/form", // <- nasty '/form' here
method = RequestMethod.GET)
public String getStuffForm(#PathVariable String stuffId, ModelMap model) {
// Prepares the model
return "JSP_Form";
}
And on the JavaScript side:
function loadStuffForm(url) {
$.ajax({
type : 'GET',
url : url,
success : function(response) {
showStuffForm(response);
}
});
}
How can I merge both controllers so it will return the right type of data based on what the client accepts? By default it would return a JSON. I want to add 'text/html' somewhere in the ajax query to get the Form instead. Any idea?
You can use Content Negotiation to communicate to the server and tell it what kind of a response you're expecting form it. In your particular scenario, you as a client using an Accept header tell the server to serve a text/html or application/json. In order to implement this, use two different produces with that same URL:
// Controller to get a JSON
#ResponseBody
#RequestMapping(value = "/stuff/{stuffId}", method = GET, produces = "application/json")
public stuffDto getStuff( ... ) { ... }
// Controller to get an HTML Form
#RequestMapping(value = "/stuff/{stuffId}", method = GET, produces = "text/html")
public String getStuffForm( ... ) { ... }
In your requests to /stuff/{id} endpoint, if you send Accept: text/html in headers, the HTML form would return. Likewise, you would get the JSON response by sending Accept: application/json header.
I'm not a JQuery expert but you can check this answer out on how to send an Accept header in $.ajax requests.
I am trying to send a JSON string as a request to my application. This is my code:
#RequestMapping(
value = "/mylink/upload",
method = RequestMethod.POST,
consumes ="application/json",
produces = "application/json")
public
#ResponseBody
List<Upload> upload(
#RequestParam(value = "hdfsLocation") String hdfsLocation
) throws Exception {
return S3HdfsTransfer.uploadFromHDFS(hdfsLocation);
}
I am trying to send a request with Postman. The method I use is POST, the header contains: Accept "application/json",Content-Type "application/json", the request body is the following:
{
"hdfsLocation" : "hdfs://145.160.10.10:8020"
}
This is the response I get. If I put the parameter in the URL, it works.
{
"httpStatus": 500,
"appErrorId": 0,
"message": "Required String parameter 'hdfsLocation' is not present",
"trackingId": "8c6d45fd-2da5-47ea-a213-3d4ea5764681"
}
Any idea what I am doing wrong?
Thanks,
Serban
Looks like you have confused #RequestBody with #RequestParam. Do either of following :
Pass the request param as a request param(not as a body). Like, (encoded)
http://example.com?hdfsLocation=http%3A%2F%2Fexample.com%3FhdfsLocation%3Dhdfs%3A%2F%2F145.160.10.10%3A8020
Replace the #RequestParam with #RequestBody. If you are sending a body, don't send it along with request param. Those are two different things.
I guess you over looked :)
Shouldn't it be #RequestBody instead of #RequestParam?
Also, even after using #RequestBody, the whole of the JSON string:
{
"hdfsLocation" : "hdfs://145.160.10.10:8020"
}
will be the value of String hdfsLocation and not just the hdfs url. Hence, you'll have to JSON parse that JSON by yourself to get just the hdfs url.
In My controller i have a method below which is working well
#RequestMapping(value="/searchresults",method = RequestMethod.GET)
public SearchResponse searchResults(
#PathVariable("domain") String domain,
#RequestParam(value="rowCount" , defaultValue="0", required=false) Integer rowCount,
HttpServletRequest req){}
but the same thing is not working when adding headers,
#RequestMapping(value="/searchresults", method = RequestMethod.GET,headers = "application/json;charset=UTF-8")
public SearchResponse searchResults(
#PathVariable("domain") String domain,
#RequestParam(value="rowCount" , defaultValue="0", required=false) Integer rowCount,
HttpServletRequest req){}
Exception :
Representation: null org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException: No matching handler method found for servle
t request: path '/search/searchresults.json', method 'GET',
I tried as follows,
#RequestMapping(value="/searchresults", method = RequestMethod.GET,headers = {"content-type=application/json,charset=UTF-8"})
but it throws,
java.lang.IllegalArgumentException: "charset=UTF-8" does not contain '/'
How to resolve it
You forgot to add the headers names :|
application/json is the Content-Type, while UTF-8 is the Charset.
Take a look at the complete list of HTTP headers.
The correct mapping will then be :
#RequestMapping(value="/searchresults", method = RequestMethod.GET,
headers = {"content-type=application/json,charset=UTF-8"})
That said, it's worth knowing that the ContentType should be specified only for POST and PUT requests.
You need to specify the header name also, which is content-type. Change this:
headers ="application/json;charset=UTF-8"
to
headers = {"content-type=application/json,charset=UTF-8"}
Change headers to produces
#RequestMapping(value="/searchresults", method = RequestMethod.GET,produces = "application/json;charset=UTF-8")
public SearchResponse searchResults(
#PathVariable("domain") String domain,
#RequestParam(value="rowCount" , defaultValue="0", required=false) Integer rowCount,
HttpServletRequest req){}
Ideally you should use #RestController if you are using Spring 4
Use ; instead of ,
#RequestMapping(value="/searchresults", method = RequestMethod.GET,headers = {"content-type=application/json;charset=UTF-8"})
There is a workaround for those who use WebLogic, while maybe other app servers an do the similar, here is what worked for me in weblogic.xml
<wls:charset-params>
<wls:input-charset>
<wls:resource-path>/restful</wls:resource-path>
<wls:java-charset-name>UTF-8</wls:java-charset-name>
</wls:input-charset>
</wls:charset-params>
My Request Mapping annotation looks like this:
#RequestMapping(method = RequestMethod.POST, value = "/echo", produces = "text/plain;charset=UTF-8", headers = "Accept=*/*")
adding
headers = {"content-type=application/json,charset=UTF-8"}
didn't help and I am puzzled why, but I got away somehow. HTH
I found this useful (being stuck with Spring 3.0.x):
#ResponseBody
public ResponseEntity<String> getResponse() {
String body = ...
MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
headers.set("Content-Type", "application/json;charset=UTF-8");
return new ResponseEntity<String>(body, headers, HttpStatus.OK);
}