Spring / Angular 7 POST method requestparameter is null - java

I would like to send datas (in json form) from frontend to backend using POST, but requestparameter is null.
Angular:
this.http.post('api/example', { mydata: JSON.stringify(data) },
{ "headers": { header: "text/html;charset=UTF-8" } }).subscribe(Response => console.log(Response);
});
JSON.stringify(data) looks like this:
[
["num1","num2","num3","num4","num5", "num6"],
["test6","test2","test1","test5","test4", "test3"]
]
This is just an example, the data will be dynamic, so sometimes I will have more or less columns and rows.
Spring backend:
#RequestMapping(value = "/api/example", method = RequestMethod.POST)
public #ResponseBody void postExample(HttpServletRequest request, HttpServletResponse response)
throws IOException {
HttpSession session = request.getSession();
response.setContentType("text/html");
response.setCharacterEncoding("UTF-8");
request.setCharacterEncoding("UTF-8");
String mydata = request.getParameter("mydata");
System.out.println(mydata);
...
}
mydata is null, when I print out. I don't know why.
What I tried:
change "text/html" to "application/json" and "application/*" and "text/plain" (and wanted to convert the text to json at backend, but still null parameter)
I would like to use "getParameter" instead of using #RequestBody annotation.
How can I get the json data from frontend and use it in backend?
Edit:
Originally I didn't want to use #RequestBody, but if I want to use it, how can I use it for getting these json arrays?

for using #RequestBody you'll need a Java data structure matching your JSON,
e.g. a nested array
#PostMapping(path="/api/example")
public void postExample(#RequestBody ArrayList<ArrayList<String>> body) {
//....
}
Test case (from question above)
[
["num1","num2","num3","num4","num5", "num6"],
["test6","test2","test1","test5","test4", "test3"]
]

You need to use .getReader(), instead of the .getParameter() method, since you need to retrieve the body of the request not some parameter.

Related

Receiving a MultiPart file and JSON data using Spring and AngularJS

Here's my controller below:
#RequestMapping(value="/upload", method=RequestMethod.PUT)
public ResponseEntity<String> handleFileUpload(
#RequestParam("file") MultipartFile file,
#RequestParam("data") String campaignJson,
Principal principal) throws JsonParseException, JsonMappingException, IOException {
I want to be able to receive a MultipartFile as well as a JSON string containing data associated to the file (title, description, etc).
I can get MultipartFile uploading to work on it's own, and I can receive a JSON string and parse it on its own, but when I have them together in 1 controller, it fails. Whenever I print out the String campaignJson it says [object Object] instead of the data that I'm sending (when I print out the data being sent in angular, it's in correct JSON format.)
I've tried #RequestBody, #RequestParam, #RequestPart, but to no avail.
My question is: How do I receive both a MultipartFile and data in the form of JSON in one Spring controller?
This worked for me :
#RequestMapping(value = "/{id}/upload", method = RequestMethod.PUT)
public DocumentResource uploadPut(#PathVariable("id") Long id,
MultipartHttpServletRequest request,
HttpServletResponse response) {
String next = request.getFileNames().next();
MultipartFile file = request.getFile(next);
.....
}
Edit :
Using the MultipartHttpServletRequest should not limit you in any way to use other #PathVariables or #RequestParams, so passing title and description should be possible.
I used it to upload multiple images with AngularJS and FileUploader
( angular-file-upload v1.1.5 )
like this
var uploader = new FileUploader({
url: config.apiUrl('/machine/' + $scope.id + '/images/'),
method: "post",
queueLimit: maxFiles
});

Simple restful JSON POST with java as server and jquery as client

Before I ask my question I have to say that I have read more than 20 questions and articles about this problem and none of them could solve it.
My problem is I have a restful server in java like this:
#RequestMapping (value = "/downloadByCode", method = RequestMethod.POST)
#ResponseBody
public void downloadByCode(#RequestBody final String stringRequest, final HttpServletResponse response)
{
try
{
final ObjectMapper objectMapper = new ObjectMapper();
final JsonNode jsonRequest = objectMapper.readValue(stringRequest, JsonNode.class);
// ...
// some processings here to create the result
// ....
final ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(result);
// Flush the result
outputStream.flush();
}
catch (final Exception exception)
{
LOG.debug("Exception Thrown [downloadByCode]", exception);
}
}
And I have tried different ways to send a json to this server with jquery (but all of them create errors):
$.ajax({
url:"/downloadByCode",
type:"POST",
data: JSON.stringify({"name":"value"}) });
415 "errors message" : "Content type 'application/x-www-form
urlencoded;charset=UTF-8' not supported", "type" :
"HttpMediaTypeNotSupportedError"
So I tried to fix it by adding contentType:
$.ajax({
url:"/downloadByCode",
contentType:"application/json",
type:"POST",
data: JSON.stringify({"name":"value"}) });
400 "errors message" : "Could not instantiate JAXBContext for class
[class java.lang.String]: null; nested exception is
javax.xml.bind.JAXBException\n - with linked
exception:\n[java.lang.NullPointerException", "type"
:"HttpMessageConversionError"
I tried to send json object directly instead of JSON.stringify and it gives the same 400 error.
I tried to add different consumes to the #requestMapping but still no luck.
I tried to define my own class instead of JsonNode but it does not change anything.
Any ideas?
Please try to create new class :
public class InputData{
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
Then
public void downloadByCode(#RequestBody InputData stringRequest, final HttpServletResponse response)
And
$.ajax({
url:"/downloadByCode",
contentType:"application/json",
type:"POST",
data: JSON.stringify({"name":"value"}) });
try #RequestBody final Map<String, String> stringRequest
also you will need consumes = "application/json" on the #RequestMapping because you have that in your AJAX call
You will get 400 if spring doesn't like the format in which you send your ajax - I've had so much trouble with this in the past and it seems better to just ignore header types and content types unless necessary
You might try sending your response back as a ResponseEntity instead of using the HttpServletResponse directly. My hunch is that second argument, the HttpServletRequest argument, is what is causing the problem. I've never used that. I've always send my response back using the spring mvc api.
With Jersey api you can try just:
#POST
public void downloadByCode(String stringRequest)
and I think you'll find the body of your post in stringRequest.
You can take request body as string with usage of org.springframework.http.HttpEntity<String> as request type, here is example with your code as base:
#RequestMapping (value = "/downloadByCode", method = RequestMethod.POST)
#ResponseBody
public void downloadByCode(final HttpEntity<String> request, final HttpServletResponse response)
{
try
{
final ObjectMapper objectMapper = new ObjectMapper();
final JsonNode jsonRequest = objectMapper.readValue(request.getBody(), JsonNode.class);
// ...
// some processings here to create the result
// ....
final ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(result);
// Flush the result
outputStream.flush();
}
catch (final Exception exception)
{
LOG.debug("Exception Thrown [downloadByCode]", exception);
}
}
But maybe it will be better to use also String as return type, if you are planning to return result as string value, like this:
#RequestMapping (value = "/downloadByCode", method = RequestMethod.POST)
#ResponseBody
public String downloadByCode(HttpEntity<String> request) {
String requestBody = request.getBody();
String result;
// ...
// some processings here to create the result text
// ....
return result;
}
I made simple application using Spring Boot with usage of proposed solutions using HttpEntity and also additional example of usage POJO, to run application you need to have Maven and JDK >= 1.7.
#clonning repository with sample
git clone git#github.com:mind-blowing/samples.git
#change current folder to sample application root
cd samples/spring-boot/rest-handler-for-plain-text
#running application using maven spring-boot plugin
mvn spring-boot:run
After application will be started you can open http://localhost:8080 and you will see html page with simple usage of JQuery to send POST requests, text of request and response will visible on html page, in controller I added two handlers, first with usage of HttpEntity and second with usage of POJO.
Controller: SampleRestController.java
HTML page: index.html
Project: https://github.com/mind-blowing/samples/tree/master/spring-boot/rest-handler-for-plain-text
First of all If you are using maven you should add dependency for jackson
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.1</version>
</dependency>
or you can download the jar and put it in our project class path (you can use other mapper as well)
then you should create a model or DTO class where you can map your json
public class Data{
private String name;
pubilc Data(){}
//getter and setter
}
THEN you controller
#RequestMapping (value = "/downloadByCode", method = RequestMethod.POST)
#ResponseBody
public Data downloadByCode(#RequestBody final Data data, final HttpServletResponse response)
{
//your code
return data;
}
AJAX CALL
$.ajax({
url:"/downloadByCode",
contentType:"application/json",
type:"POST",
data: JSON.stringify({"name":"value"}) });
(Optional)You can override behavior by telling object mapper not to fail on missing properties by defining the bean as follows:
#Bean
public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false));
return converter;
}
http://websystique.com/springmvc/spring-mvc-requestbody-responsebody-example/
Looking at your errors, it's clear that you have configured 'Jaxb2RootElementHttpMessageConverter' or similar XML converter in your spring configuration. And since you have registerned an XML converter, the #RequestBody and #ResponseBody work based on the registered message converters.
So, to solve your problem, go with a JSON message converter such as 'MappingJacksonHttpMessageConverter'. Once you register a JSON message converter, create a bean class to hold your json data and use it with RequestBody as below:
// It has to meet the json structure you are mapping it with
public class YourInputData {
//properties with getters and setters
}
Update 1:
Since you have defined multiple message converters, Spring tries to use the first one available by default. In order to use specific message converter(in this case Jackson converter), you should specify 'Accept' header from client like below:
$.ajax({
headers: {
"Accept" : "application/json; charset=utf-8",
"Content-Type": "application/json; charset=utf-8"
}
data: "data",
success : function(response) {
...
} })
The final answer is a combination of a number of answers/comments in this question that I am going to summarize them here:
1- You have to make sure you have an appropriate json converter in your spring config such as MappingJacksonHttpMessageConverter (credits to #java Anto)
2- You have to create a POJO class with same structure as your json object (see #Vinh Vo answer)
3- Your POJO class cannot be an inline class unless it is a static class. It means it should have its own java file or it should be static. (credits to #NTyler)
4- Your POJO class can miss parts of your json object if you set it appropriately in your object mapper (see #Aman Tuladhar answer)
5- Your ajax call requires contentType:"application/json", and you should send your data with JSON.stringify
Here is the Final code that is working perfectly:
public static class InputData
{
private String name
public String getName()
{
return name;
}
public void setName(final String name
{
this.name = name;
}
}
#RequestMapping(value = "/downloadByCode", method = RequestMethod.POST)
#ResponseBody
public void downloadByCode(#RequestBody final InputData request, final HttpServletResponse response)
{
try
{
String codes = request.getName();
// ...
// some processings here to create the result
// ....
final ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(result);
// Flush the result
outputStream.flush();
}
catch (final Exception exception)
{
LOG.debug("Exception Thrown [downloadByCode]", exception);
}
}
And it is the jquery Ajax request:
$.ajax({
url:"/downloadByCode",
contentType:"application/json",
type:"POST",
data: JSON.stringify({"name":"value"}) });
Delete the #ResponseBody on your downloadByCode method
Change your method downloadByCode() return type to String and then return the String
Response body will automatically convert the returned String to JSON and then use the data appropriately
I am not that well versed with java but as much as I know your java code must be something like this.
public class downloadByCode{
#GET
#Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
public Response downloadByCode(#QueryParam("paramater1") final String parameter 1, #Context HttpServletRequest httpRequest) {
If this not helps you can keep you code somewhere and share it.

Java Spring MVC - Send JSON request body error

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.

How to ignore JSON processing for a request in Spring MVC?

I have a request handler for which I would like to skip json processing and retrieve the request body as a string. Eg -
#RequestMapping(value = "/webhook", method = RequestMethod.POST)
public void webHook(#RequestBody String body) {
}
However, the above method definition doesnt work as Spring forcibly tries to parse the posted string as json and thus throws an exception.
How do i tell spring to skip json processing for this request?
use like this it'll work.
#RequestMapping(value = "/webhook", method = RequestMethod.POST)
public void webHook(HttpServletRequest request) {
String body = IOUtils.toString( request.getInputStream());
// do stuff
}
Not using #RequestBody is key here. When spring sees #RequestBody it tries to map the entire body as object.

Springs MVC JSON Response and convert it to JS Object

I am having a question that how can I send JSON Object from Springs MVC so that I can convert it into a JavaScript Object on my HTML Page.
In a traditional way I do it: Below is a snippet from Java Servlet which sets a request attribute and forward it to the JSP Page.
JSONObject jsonObj = new JSONObject();
jsonObj.put("name","test");
jsonObj.put("age",24);
request.setAttribute("jsonObj",jsonObj);
request.getRequestDispatcher("test.jsp").forward(request,response);
In JSP I retrieve as :
<script type="text/javascript">
var jsonObj =<%=request.getAttribute("jsonObj"); %>;
alert("name = "+jsonObj.name+" ; age = "+jsonObj.age); // This will output name and age from the JSON Object
</script>
So what I need to ask how can I do the same in Springs MVC. How can I send the JSONObject from Dispatcher Servlet, and convert it to JS object in my JSP page ?
An easy way to do this using the ObjectMapper. It will create an JSON String from your Object. And that you can send to your view/jsp.
I put an small example of a controller I do this (just snipped).
#Controller
public class UsersSettingsController {
#Autowired
UserSettingsDefaultService userSettingsService;
#RequestMapping(value="/userSettings/dynamic/userSettings", method=RequestMethod.GET)
public ModelAndView get() throws Exception {
ModelAndView mav = new ModelAndView();
ObjectMapper mapper = new ObjectMapper();
User user = (User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserSettings userSet = userSettingsService.getUserSettingsByUser(user);
mav.addObject("userSettingsJSON", mapper.writeValueAsString(userSet));
mav.setViewName("userSettings/dynamic/filter");
return mav;
}
}
Or course can you create your JSON Object in your Contoller step by step like you did in your example. Then you don't need the Mapper, just sending the String to your View.
In the JSP you load the json String like this into a JS var:
var jsonString = '${userSettingsJSON}';
To get elements from JSON String or parse, see: http://www.json.org/js.html.
I'm an KnockOut Framework Fan would do it with it.
I think you should use ajax(for example jquery),the following is spring mvc
#RequestMapping(value = "/admin/new/list", method = RequestMethod.GET)
#ResponseBody
public List<News> list()
{
return newsDao.findAll();
}
and in the jsp page,you may use ajax util (for example jquery)
$.ajax({
type: "GET",
url: '<c:url value="/admin/new/list"/>',
cache:false,
dataType :'json',
success: function(data){
alert(data);
}
});
the data is json object
I don't know whether the above is what you need
A much easier way to do this is to include the Jackson dependencies in maven and use #ResponseBody to return a JSON representation of the object, without having to manually write the manipulation.
Have a look at the example below, you shouldn't have to write any tranlation to JSON code.
http://www.mkyong.com/spring-mvc/spring-3-mvc-and-json-example/
As per your requirement, I suggest you to use AJAX call with JSON as data type.
For example :
$.ajax({
url: "getFormatIdDescMap?compId="+compId,
global: false,
type: "POST",
dataType:"json",
contanttype:'text/json',
async:false,
error:function(){
alert("Error during retrieving the foramt ID List");
},
success: function(data){
//REMOVE ALL THE OLD VALUES OF FORMAT DROP DOWN
removeDropDownVals('formatList');
var optn;
for(var index=0;index<data.formatKeys.length;index++){
optn = document.createElement("option");
document.getElementById("formatList").options.add(optn);
optn.text =data.formatDescs[index];
optn.value=data.formatKeys[index];
}
}
});
});
In the code above, I am preparing a new list of Formats based on company ID. You can iterate over the response.
It will give response text as per your requirements. But here note that .. if you are getting json Array in the response, it will contain that data in square bracket like..[1,2,3] and If you are getting response in JSON Object then it will be displayed in curly braces like {"data",[1,2,3]}.

Categories

Resources