Spring MVC get Jackson JSON as parameter - json

Hello In frist time I want apologize if my english isn't so good
I want send Multipart request to the server by Apache HttpClient. This request consist from several types of parts. One of these part is JSON. JSON is created by Jackson.
HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
HttpPost httppost = new HttpPost("http://xxx.xxx.xxx.xx:8080/synchronize");
HttpResponse response =null;
CProject project = new CProject();
project.setId(10L);
project.setName("name");
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(project);
MultipartEntity multipart = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE);
multipart.addPart("project", new StringBody(json,"application/json",Charset.forName("UTF-8")) );
httppost.setEntity(multipart);
response = httpclient.execute(httppost);
Structure of CProject is very simple
public class CProject implements Serializable{
private Integer id;
private String name;
}
And I wand catch this request on server as parameter with anotations #RequestParam or #ModelAttribute but no with #RequestBody because this catch full request - and I need send multiply parameters(Multipart Entity).
Code on server
#RequestMapping (value = "/synchronize", method = RequestMethod.POST)
public #ResponseBody
List<Object> getRequest (#RequestParam CProject project, HttpServletResponse response)
{
return null;
}
Problem is that variable project is created but its atributes are null.
I try several tutorials on net what works with #RequestBody and send request on server and set full header as "application/json". And my application works if I change header of full request as JSON and send them on server, and catch this as #RequestBody on server this work. But I need send json as parameter.
Thanks for any ideas.

Related

Can pass my own object with RestTemplate PUT

I want to build a small RESTful Service, send a PUT request with an Object of a class I created (MyObject), and getting a response with only status.
My controler:
#RestController
public class MyControler {
#RequestMapping(path = "/blabla/{id}", method = RequestMethod.PUT)
#ResponseBody
public ResponseEntity<String> putMethod (#PathVariable("id") Long id,
#RequestBody MyObject t) {
/*todo*/
return new ResponseEntity<String>(HttpStatus.OK);
}
My Test App
#SpringBootApplication
public class App {
public String httpPut(String urlStr) {
MyObject myObject = new MyObject(p,p,....);
URI url = null;
HttpEntity<MyObject> requestEntity;
RestTemplate rest = new RestTemplate();
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
HttpHeaders headers = new HttpHeaders();
List<MediaType> list = new ArrayList<MediaType>();
list.add(MediaType.APPLICATION_JSON);
headers.setAccept(list);
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Content-Type", "application/json");
requestEntity = new HttpEntity<Transaction>(t, headers);
ResponseEntity<String> response =
rest.exchange(url, HttpMethod.PUT, requestEntity, MyObject.class);
return response.getStatusCode().getValue();
}
Im getting an HttpClientErrorException: 400 Bad Request
Where is my mistake? What I want is for Spring to automaticly serialize the MyObject. MyObject class is implementing serializable.
What do I miss?
}
Maybe you're doing to much?
Did you try to put the object as json via postman or something similar? If so what is the response?
Nevertheless i created a minimal example for consuming a service via Springs RestTemplate.
This is all needed code for getting a custom object AND putting a custom object via RestTemplate
public void doTransfer(){
String url = "http://localhost:8090/greetings";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<Greeting> greeting = restTemplate.getForEntity(url, Greeting.class);
LOGGER.info(greeting.getBody().getValue());
Greeting myGreeting = new Greeting();
myGreeting.setValue("Hey ho!");
HttpEntity<Greeting> entity = new HttpEntity<Greeting>(myGreeting);
restTemplate.exchange(url, HttpMethod.PUT, entity, Greeting.class);
}
I've provided a sample project with a sender (maybe not a good name .. it is the project with the greetings endpoint) and a receiver (the project which consumes the greetings endpoint) on Github
Try to do this:
ResponseEntity<MyObject> responseSerialized =
rest.exchange(url, HttpMethod.PUT, requestEntity, MyObject.class);

How to send JSON data in request to rest web service

I have created a rest webservice which has a below code in one method:
#POST
#Path("/validUser")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public JSONObject validUserLogin(#QueryParam(value="userDetails") String userDetails){
JSONObject json = null;
try{
System.out.println("Service running from validUserLogin :"+userDetails);
json = new JSONObject(userDetails);
System.err.println("UserName : "+json.getString("userName")+" password : "+json.getString("password"));
json.put("httpStatus","OK");
return json;
}
catch(JSONException jsonException) {
return json;
}
}
I am using Apache API in the client code.And below client code is calling this service, by posting some user related data to this service:
public static String getUserAvailability(String userName){
JSONObject json=new JSONObject();
try{
HttpContext context = new BasicHttpContext();
HttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109);
URI uri=new URIBuilder(BASE_URI+PATH_VALID_USER).build();
HttpPost request = new HttpPost(uri);
request.setHeader("Content-Type", "application/json");
json.put("userName", userName);
StringEntity stringEntity = new StringEntity(json.toString());
request.setEntity(stringEntity);
HttpResponse response = client.execute(request,context);
System.err.println("content type : \n"+EntityUtils.toString(response.getEntity()));
}catch(Exception exception){
System.err.println("Client Exception: \n"+exception.getStackTrace());
}
return "OK";
}
The problem is, I am able to call the service, but the parameter I passed in the request to service results in null.
Am I posting the data in a wrong way in the request. Also I want to return some JSON data in the response, but I am not able to get this.
With the help of Zack , some how i was able to resolve the problem,
I used jackson-core jar and changed the service code as below.
#POST
#Path("/validUser")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public JSONObject validUserLogin(String userDetails){
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readValue(userDetails, JsonNode.class);
System.out.println("Service running from validUserLogin :"+userDetails);
System.out.println(node.get("userName").getTextValue());
//node.("httpStatus","OK");
return Response.ok(true).build();
}

How to send JSON in Spring?

I tried to find how I can write in Spring to POST JSON from REST client. For example, I wrote:
#RequestMapping(value = "/{userId}/add", method = RequestMethod.POST, headers = {"content-type=application/json"})
#ResponseBody
public Map<String, String> saveUser(#RequestBody User user, BindingResult result) {
Map<String, String> jsonResponse = new HashMap<String, String>();
if (result.hasErrors()) {
jsonResponse.put("Message", "Can't add the user");
jsonResponse.put("Code", "401");
return jsonResponse;
}
userService.addUser(user);
jsonResponse.put("Message", "Success add User");
jsonResponse.put("Code", "200");
return jsonResponse;
}
End tested it from Firefox REST client. But I saw 404 error. What am I doing wrong? Thanx for help.
First, if the URI of your request ended with "/user/2/add", it won't map to your method, which is mapped as "/{userId}/add". This will cause the HTTP 404 error you receive. Instead, your URI should end with "/2/add", if the "userId" is 2.
Second, annotating the User parameter with #RequestBody is not enough for the complex User type. You will need to convert your JSON request body into a User object. You can accomplish this with the MappingJacksonHttpMessageConverter. By declaring a bean of this type, you can use Jackson's annotations to control how the JSON is parsed into the User properties.

The request sent by the client was syntactically incorrect ().+Spring , RESTClient

I am working with Spring MVC using JSON objects. while I am tring to send JSON Object from RESTClient, I am getting
HTTP Status 400 - The request sent by the client was syntactically incorrect ().
This is my controller
ObjectMapper mapper=new ObjectMapper();
#RequestMapping(value = "/addTask", method = RequestMethod.GET)
public ModelAndView addTask(#RequestParam("json") String json) throws JsonParseException, JsonMappingException, IOException
{
System.out.println("Json object from REST : "+json);
Task task=(Task) mapper.readValue(json, Task);
service.addService(task);
return new ModelAndView("Result");
}
My request URL : http://localhost:8080/Prime/addTask
My Json Object :
{"taskName":"nothing","taskId":1234,"taskDesc":"nothing doing"}
Also i tried specifying "Content-Type: application/json" in RESTClient but still am getting the same error
I ran into a similar situation using a JSON string in the request body recently, and using a very similar Spring setup as yours. In my case I wasn't specifying a String parameter and deserialising it myself though, I was letting Spring do that:
#RequestMapping(value = "/myService/{id}", method = RequestMethod.POST)
#ResponseBody
public void myService(#PathVariable(value = "id") Long id, #RequestBody MyJsonValueObject request) {
..
}
I was getting an HTTP error 400 "The request sent by the client was syntactically incorrect" response. Until I realised that there wasn't a default constructor on the #RequestBody MyJsonValueObject so there were problems deserialising it. That problem presented in this way though.
So if you are using POST and objects, and getting errors like this, make sure you have a default constructor! Add some JUnit to be sure you can deserialise that object.
Note: I'm not saying this is the only reason you get this error. The original case used just String (which does have a default constructor !) so it's a little different. But in both cases it appears the request URI appears to have been mapped to the right method, and something has gone wrong trying to extract parameters from the HTTP request.
Try this
Change
#RequestParam("json") String json
To
#RequestBody Task task
If you are not interested in POST method you can try this
change your Controller method from
#RequestMapping(value = "/addTask", method = RequestMethod.GET)
public ModelAndView addTask(#RequestParam("json") String json)
to
#RequestMapping(value = "/addTask/{taskName}/{taskId}/{taskDesc}", method = RequestMethod.GET)
public ModelAndView addTask(#RequestParam("taskName") String taskName,
#RequestParam("taskId") String taskId,#RequestParam("taskDesc") String taskDesc)
and change your URL to
http://localhost:8080/Prime/addTask/mytask/233/testDesc
My problem was due to the incorrect mapping of the #RequestBody object.
My Request Body looks like this
{data: ["1","2","3"]}
I had the following code in my controller
#RequestMapping(value = "/mentee", method = RequestMethod.POST)
public #ResponseBody boolean updateData(#RequestBody List<Integer> objDTO, HttpSession session) {
...
}
This give me HTTP 400 because Spring doesn't know how to bind my Json data to a List.
I changed the RequestBody object to the following
#RequestMapping(value = "/mentee", method = RequestMethod.POST)
public #ResponseBody boolean updateData(#RequestBody ObjectiveDto objDTO, HttpSession session) {
...
}
and defined ObjectiveDto as followed
#ToString
public class ObjectiveDto {
#Getter #Setter
private List<Integer> data;
}
This resolved the HTTP 400 error.

Access HttpServletRequest object from Jackson custom deserializer

I am trying to send an object via an ajax POST using JSON payload; this object has references to other objects stored in a database, handled by Hibernate; I need to access this database to resolve other objects references and store them in the new object obtained deserializing JSON payload of request.
Now, I have to access HttpServletRequest attribute in order to get a saved hibernate session to use to access to database. Is it possible?
The controller that handle the request is the following:
#RequestMapping(value = "/newproduct", method = RequestMethod.POST)
public #ResponseBody
Integer newProduct(HttpServletRequest request, #RequestBody Product product)
{
//Controller code here
}
The deserializer where I have to be able to get request attribute "hibernate_session" is a custom deserializer, registered to Jackson and is the following:
public class ProductDeserializer extends JsonDeserializer<Product>
{
#Override
public Product deserialize(JsonParser jpar, DeserializationContext arg1)
throws IOException, JsonProcessingException
{
Product newProduct = new Product();
// I want to get request attribute or open a new hibernate session here
return newProduct;
}
}
If necessary I'll post more code if needed.
Thanks
You may try following approach
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
.getRequestAttributes()).getRequest();