Sending json from js to controller with ajax post - java

I'm having trouble sending a json object from javascript to java controller,
Ajax:
var xmlHttp = getXmlHttpRequestObject();
if(xmlHttp) {
var jsonObj = JSON.stringify({"title": "Hello","id": 5 });
xmlHttp.open("POST","myController",true);
xmlHttp.onreadystatechange = handleServletPost;
xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xmlHttp.send(jsonObj);
}
function handleServletPost() {
if (xmlHttp.readyState == 4) {
if(xmlHttp.status == 200) {
alert(window.succes);
}
}
}
What I tried in Java:
public void process(
final HttpServletRequest request, final HttpServletResponse response,
final ServletContext servletContext, final TemplateEngine templateEngine)
throws Exception {
String jsonObj = request.getParameter("jsonObj");
}
They all are null.
I tried reading related posts and multiple ways of sending the data but same result. I don't know how to use Jquery for ajax, so I'm looking for a js solution mainly.
Can someone tell me what I'm missing? As I spent about three hours trying to figure it out

To get your JSON sent with a POST request, you have to read the body of the request in a doPost method. Here's one way to do it :
protected void doPost(HttpServletRequest hreq, HttpServletResponse hres)
throws ServletException, IOException {
StringWriter sw = new StringWriter();
IOUtils.copy(hreq.getInputStream(), sw, "UTF-8");
String json = sw.toString();
And then you'll have to parse the JSON. This may be done for example using Google gson.
Supposing you have a class Thing with public parameters id and title, this would be
Gson gson = new GsonBuilder().create();
Thing thing = gson.fromJson(json, Thing.class);
int id = thing.id;
String title = thing.title;
Of course there are other solutions than gson to parse JSON but you have to parse it.

I think you are confusing URL parameters with request body. To get json string from request you need read it from request.getReader().

I have figured it out.
The Json should be sent like this:
xmlHttp.send("jsonObj="+jsonObj);
instead of
xmlHttp.send(jsonObj);
In order to receive it as parameter.

Related

How To Receive JSON Data In Cross Origin Resource Sharing (CORS) with Spring REST

I am trying to send / Receive JSON data from / to my Controller Class in my Project.
The Controller Class Of My Project Is as Follows :
#RequestMapping(value = "/dummy/",method = RequestMethod.POST,headers="Accept=application/json")
public Response getDummyJSON() {
/* Method 2: Getting the Dummy JSON Data From file and sending it as an JSON Object */
JSONParser parser = new JSONParser();
JSONObject jsonObject = null;
try {
Object obj = parser.parse(new FileReader("d:\\JsonStruc.json"));
jsonObject = (JSONObject) obj;
} catch (Exception e) {
System.out.println("Error Parsing: - ");
}
return Response.status(200).entity(jsonObject).build();
}
#RequestMapping(value = "/insert/dummy/",method= RequestMethod.POST,headers="Accept=application/json")
public Response setDummyJSON(#RequestBody JSONObject inputjsonObj){
/*Step 1: Display The JSON data sent by AngularJS */
System.out.println("Data Received:"+ inputjsonObj.toString());
JSONParser jsonparser = new JSONParser();
ContainerFactory containerFactory = new ContainerFactory(){
public List creatArrayContainer() {
return new LinkedList();
}
public Map createObjectContainer() {
return new LinkedHashMap();
}
};
Map obj = (Map)inputjsonObj;
Iterator iter = obj.entrySet().iterator();
while(iter.hasNext()){
Map.Entry entry = (Map.Entry)iter.next();
System.out.println(entry.getKey() + "=>" + entry.getValue());
}
/* Step 2: send the next dummy JSON file */
JSONParser parser = new JSONParser();
JSONObject jsonObject1 = null;
try {
Object obj1 = parser.parse(new FileReader("d:\\JsonStruc1.json"));
jsonObject1 = (JSONObject) obj1;
} catch (Exception e) {
System.out.println("Error Parsing: - ");
}
return Response.status(200).entity(jsonObject1).build();
}
The CORS class of my Project is as follows :
public class CorsFilter extends OncePerRequestFilter{
private Properties prop = new Properties();
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
System.out.println("Inside Cross Origin Resource Sharing Filter Class");
System.out.println(request.getContentType());
System.out.println(request.getContentLength());
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD, PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
filterChain.doFilter(request, response);
}
}
There is no Problem regarding sending Dummy JSON data through the URL (/service/question/dummy/) But
when I am trying to get The JSON data (/service/question/insert/dummy/) and send the next JSON object
through the method setDummyJSON(....) then I am having trouble. The AngularJS (Client) side is showing the following exception message :
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at /FetchQuestions/service/question/insert/dummy/. This can be fixed by moving the resource to the same domain or enabling CORS.
On invoking the URL (/service/question/insert/dummy/) from localhost with a JSON String as Content Body the following error message is thrown :
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method ().
What am I doing Wrong ? Any Help will be appreciated. Thanks.
There is Nothing Wrong with the above code.
For Some Reason Whenever the Content-Type was set to application/json in AngularJS(Client Side) by using the following command :
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json';
The Server Side received a Content-Type of null. Any other Content-Type like application/x-www-form-urlencoded or text/plain Works but the Problem occurs only with application/json (even though AngularJS was sending JSON data to Server Side).
Thus a little change in the Controller class Fixed the Problem.
#RequestMapping(value = "/insert/dummy/",method= RequestMethod.POST")
public Response setDummyJSON(#RequestBody String inputjsonObj){
/* Step1: Receive The Data in Text/Plain Format
Step2: Conver The String To JSON Object. Do Necessary Processing.
Step3: Return Dummy JSON Object through the Response. */
return Response.status(200).entity(jsonObject1).build();
}

Trying to use bing translator API with Robospice in Android

I need to implement robospice for doing the networking part in my Translator app. I previously used async task class and it was working fine, but now i want to improve my application with implementing robospice. I'am trying to execute the following code but it doesn't't throw any exception it just never executes....
#Override
public TranslatedText loadDataFromNetwork() throws Exception {
String jsonString = getJsonString();
String headerValue = getHeaderValue(jsonString);
String text = pair.getWordPairs().getWordFrom();
String languageFrom = pair.getLanguagePairs().getLanguageFrom().getCode();
String languageTo = pair.getLanguagePairs().getLangougateTo().getCode();
String uri = String
.format("http://api.microsofttranslator.com/v2/Http.svc/Translate?text=%s&from=%s&to=%s&contentType=text/html",
URLEncoder.encode(text, "UTF-8"),
URLEncoder.encode(languageFrom, "UTF-8"),
URLEncoder.encode(languageTo, "UTF-8"));
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", headerValue);
// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();
// Add the Simple XML message converter
getRestTemplate().getMessageConverters().add(new SimpleXmlHttpMessageConverter());
//set the headerValue in the Entity
org.springframework.http.HttpEntity<?> request = new org.springframework.http.HttpEntity<Object>(headerValue);
// Make the HTTP GET request, marshaling the response from XML to an
// EventList
Log.v("request","Making request!");
//This line never finish execuitng, doesen't throw exception or anything in logCat
ResponseEntity<Object> responseEntity = getRestTemplate().exchange(uri, HttpMethod.GET, request, null);
Log.v("request", responseEntity.getBody().toString());
Log.d("Load Data From Network", request.getBody().toString());
return null;
}
The last thing it shows in log cat is Request First!! And nothing after that. It never even gets to The Request Listener onRequestFailure.
Can any 1 tell me what i do wrong ?
This is what look weird to me in your code:
ResponseEntity<Object> and null as 4th parameter of the exchange method are not correct. You need to provide a type which represents the response you get from the server.
The object returned by loadDataFromNetwork() is what you will get in the onRequestSuccess() method. Returning null is not a good idea, in my opinion.
I fixed the problem. So if you need to handle stream you will have to provide the following code
ResponseEntity<byte[]> responseEntity = getRestTemplate().exchange(uri, HttpMethod.GET, request, byte[]);

Json Get/Send Data Strategies

Now I'm learning how to use Gson library to set and get data from webservice in Json format, but its best practices and strategies are a bit dark for me so I will be very delightful if somebody would explain more about it.
I've created an Entity class to get response entity from server:
public class Response
{
#SerializedName("Type")
public String Type;
#SerializedName("result")
public String result;
}
and in AsyncTask class I've used:
Response _Response = new Response();
try
{
String _url = Global.Url_Request ;
Map<String, String> Params = new HashMap<String, String>();
Params.put("PhoneNumber", this.User_PhoneNumber);
String json = new GsonBuilder().create().toJson(Params, Map.class);
HttpClient httpclient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(_url);
httpPost.setEntity(new StringEntity(json));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
HttpResponse getResponse = httpclient.execute(httpPost);
HttpEntity returnEntity = getResponse.getEntity();
is = returnEntity.getContent();
Gson gson = new Gson();
Reader reader = new InputStreamReader(is);
_Response = gson.fromJson(reader, Response.class);
}
catch (Exception e)
{
_Response.Type= "Error";
_Response.result= "Data Is Wrong";
}
return _Response;
It works fine with creating an Entity Object for every different http POST call, but my questions are:
What is the best practice for handling webservices with different response objects?
How can I handle this situation: if data sent ok then return specific Jsonarray; if not, return a Response object to detect something is wrong. Should I use Custom typeAdapter?(sample code would be great)
If webservice returns an empty response gson.fromJson would throw an **IllegalStateException: Expected a string but was BEGIN_OBJECT** how can i prevent this?
Thanks in advance
1. What is the best practice for handling webservices with different response objects?
I think that this depends on the kind of control you have. If you code also the webservice, you could create a big container object that has may fields. Each of these fields is one of the possible responses you can pass between client and server. If you have not control on what the server can reply, and it can differ a lot, JsonParser is your best friend. You can use it to snoop inside JSON and decide the right strategy to handle the response.
Let's do an example for case one. I declare these classes:
public static class GenericResponse{
public ServerException exception;
public StandardResponse1 responseType1;
public StandardResponse2 responseType2;
#Override
public String toString() {
return "GenericResponse [exception=" + exception + ", responseType1=" + responseType1 + ", responseType2=" + responseType2 + "]";
}
}
public static class ServerException{
public int error;
public String message;
}
public static class StandardResponse1{
public List<Integer> list;
public Date now;
}
With this kind of classes, I can parse:
{"responseType1":{"list":[1,2],"now":"Nov 25, 2013 9:26:51 PM"}}
or
{"exception":{"error":-1,"message":"Don\u0027t do this at home"}}
For example, if I get from server the second type of response, this code:
GenericResponse out = g.fromJson(fromServerStream, GenericResponse.class);
System.out.println(out);
will return me:
GenericResponse [exception=stackoverflow.questions.Q20187804$ServerException#1e9d085, responseType1=null, responseType2=null]
All you have to do is to check your fields to see what actually the server replied.
Case two. You cannot control the JSON, so the server can reply
[13,17]
or
{"error":-1,"message":"Don\u0027t do this at home"}
In this case you cannot pass directly the class type to Gson as before, but you have to check things. I would solve this problem with a JsonParser.
Gson g = new Gson();
JsonParser jp = new JsonParser();
JsonElement o = jp.parse(s);
if (o.isJsonArray()){
List<Integer> list = (List) g.fromJson(o, listType1);
System.out.print(list);
}
else{
ServerException e = g.fromJson(s, ServerException.class);
System.out.print(e);
}
Using JsonObject/JsonArray and so on, is what happens inside a TypeAdapter. In the adapter you start with the JsonElement that is already parsed. There are many good example of it on SO, this for example.
How can I handle this situation: if data sent ok then return specific Jsonarray; if not, return a Response object to detect something is wrong. Should I use Custom typeAdapter?(sample code would be great)
Do you mean you want to parse this kind of response? Examples of point 1 show this.
If webservice returns an empty response gson.fromJson would throw an **IllegalStateException: Expected a string but was BEGIN_OBJECT how can i prevent this?**
JsonParser/TypeAdapter is again the solution. You can check if JsonElement is null or if is a primitive type (String, Integer, Boolean) and deal it.

Fetching JSON object from Servlet Java

I want to create an application that will fetch a JSON object from a servlet to deserialize it, and then use its variables to do other things.
My servlet has the following code in the doPost:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ObjectOutputStream os;
os = new ObjectOutputStream(response.getOutputStream());
String s = new String("A String");
Gson gson = new Gson();
String gsonObject= gson.toJson(s);
os.writeObject(gsonObject);
os.close();
}
Now, while the servlet is running, I can access it via a browser, if I post same code in the doGet method, that would download a servlet file, which is not what I want.
What should I use in my second application that would connect to the servlet, fetch the object, so that I can manipulate it later?
Thanks in advance.
You need few changes in your servlet :
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String s = new String("A String");
String json = new Gson().toJson(s);
this.response.setContentType("application/json");
this.response.setCharacterEncoding("UTF-8");
Writer writer = null;
try {
writer = this.response.getWriter();
writer.write(json);
} finally {
try {
writer.close();
}
catch (IOException ex) {
}
}
}
If its downloading the servlet file instead of showing it in the browser , most probably you have not set the content type in the response. If you are writing a JSON string as the servlet response , you have to use
response.setContentType("text/html");
response.getWriter().write(json);
Please note the order , its "text/html" and not "html/text"
IfI understood the question correctly then you can use, java.net.HttpURLConnection and java.net.URL objects to create a connection to this servlet and read the JSON streamed by the above JSON servlet in your second servlet.

Parse local JSON file with RestTemplate

I would like to parse a local JSON file and marshal it into models using RestTemplate, but can't tell if this is possible.
I'm trying to pre-populate a database on an Android app that is using RestTemplate for syncing with the server. Rather than parsing the local JSON on my own, I thought, why not use RestTemplate? It's made exactly for parsing JSON into models.
But...I can't tell from the docs if there is any way to do this. There is the MappingJacksonHttpMessageConverter class which appears to convert the server's http response into a model...but is there any way to hack that to work with a local file? I tried, but kept getting deeper and deeper down the rabbit hole with no luck.
Figured this out. Instead of using RestTemplate, you can just use Jackson directly. There is no reason RestTemplate needs to be involved in this. It's very simple.
try {
ObjectMapper mapper = new ObjectMapper();
InputStream jsonFileStream = context.getAssets().open("categories.json");
Category[] categories = (Category[]) mapper.readValue(jsonFileStream, Category[].class);
Log.d(tag, "Found " + String.valueOf(categories.length) + " categories!!");
} catch (Exception e){
Log.e(tag, "Exception", e);
}
Yes, I think it is possible(with MappingJacksonHttpMessageConverter).
MappingJacksonHttpMessageConverter has method read() which takes two parameters: Class and HttpInputMessage
MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
YourClazz obj = (YourClazz) converter.read(YourClazz.class, new MyHttpInputMessage(myJsonString));
With this method you can read single object from single json message, but YourClazz can be some collection.
Next, You have to create you own HttpInputMessage implementation, in this example it expected json as string but You probably can pass stream to your json file.
public class MyHttpInputMessage implements HttpInputMessage {
private String jsonString;
public MyHttpInputMessage(String jsonString) {
this.jsonString = jsonString;
}
public HttpHeaders getHeaders() {
// no headers needed
return null;
}
public InputStream getBody() throws IOException {
InputStream is = new ByteArrayInputStream(
jsonString.getBytes("UTF-8"));
return is;
}
}
PS. You can publish your app with database

Categories