Test rest service having RequestParam using postman - java

I want to test my REST service in order to save a product having a certain category (manyToOne) with Postman:
This is the body of my request:
{
"categoryId": 36,
"product": {
"code": "code1",
"name": "product1",
"price": 20
}
}
And this is how the signature of my REST service method looks like:
#RequestMapping(value = "/addProduct", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<ProductBean> add(#RequestParam(value ="categoryId") Long id, #RequestParam(value = "product") ProductBean productBean)
I put in Postman my URL with the /addProduct at the end, then I choose POST. In the body tab, I choose raw and select the JSON (application json).
When I send the request I got HTTP 400.
How can test this without error in Postman?
Edit
I want to test it using postman to be sure that my REST is working before adding the front part. This is how I will send the data from the front
add: function (product, id, successCallBack, failureCallBack) {
$http({
method: 'POST',
url: "/addProduct",
params: {
product: product,
categoryId: id
},
headers: {'Content-Type': 'application/json'}
}).then(successCallBack, failureCallBack);
}

Your method signature is incorrect. #RequestParam is the parameter in the uri, not the body of the request. It should be:
public ResponseEntity<ProductBean> add(MyBean myBean)
where MyBean has to properties: id and product or
public ResponseEntity<ProductBean> add(#ModelAttribute(value ="categoryId") Long id, #ModelAttribute(value = "product") ProductBean productBean)
For more on mapping requests see Spring documentation
If you want to stick to your original mapping, then everything should be passed in the query string and nothing in the body.
The query string will look something like that:
/addProduction?categoryId=36&product={"code":"code1",...}

Related

AJAX POST method to Spring RestAPI not working

I'm trying to send a large form of data to my server side, using jQuery AJAX and sending it to a RESTful service made in the Spring Framework. And the form as arrays of unknown sizes, so am trying to get the auto serializing to work. But I can't even get it to work with a simple test example.
It seems to not be able to match my JSON file to the input class. So I must be doing something wrong. But I have not been able to see what I'm doing wrong based on the tutorials I have been trying to follow.
Here is my AJAX call
var test = JSON.stringify({
name : "hallo", lastname : "there"
});
console.log(test);
$.ajax({
type: "POST",
url: "/SpringTest_war_exploded/test",
contentType: "application/json",
data: test,
success: function (returnValue) {
console.log("success");
console.log(returnValue);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
console.log (XMLHttpRequest);
alert("Request: " + XMLHttpRequest.toString() + "\n\nStatus: " + textStatus + "\n\nError: " + errorThrown);
}
});
Here is my server-side method.
#PostMapping(value = "/test", consumes = "application/json")
#ResponseBody
public String testajax(#RequestBody TestAutoCreate test){
System.out.println("testajax");
System.out.println(test.getName());
return "hallo";
}
Here is the class I'm trying to match it with
public class TestAutoCreate {
private String name;
private String lastname;
public TestAutoCreate(String name, String lastname) {
this.name = name;
this.lastname = lastname;
}
// the getters and setters
...
}
And here is the error massage I get
The origin server is refusing to service the request because the payload is in a format not supported by this method on the target resource.
If I remove the #RequestBody TestAutoCreate test from the server side method, then the call works fine. It is only
The problem at here
#PostMapping(value = "/test", consumes = "application/json")
#ResponseBody
public String testajax(#RequestBody TestAutoCreate test){
System.out.println("testajax");
System.out.println(test.getName());
return "hallo";
}
It is RESTful controller, but return view. You must return RESTful response, what has content type is Content-Type: application/json .
See authority example: https://spring.io/guides/tutorials/rest/

Spring MVC test throwing 415 HttpMediaTypeNotSupportedException

this may or may not be a somewhat long post, but I'm going to be pasting every single piece of information relating to this issue and the method I am testing, from Controller class with method to the a.jax snippet. I have asked about 4-6 developers and no one can find out the reason why its giving me a 415 error instead of a 200, because it just seems like I am doing everything correct. I just need some fresh eyes and new perspectives, hopefully someone could help me solve this. I will be pasting the classes and the relevant pieces now, and then a couple comments after the snippets.
Controller class
#Controller
#RequestMapping(value = "/user")
public class Controller
{
#Autowired
private Service service;
public Controller() {
}
#RequestMapping(value = "/landing/{age}/{name}/{title}/{family}/{gender}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON)
public #ResponseBody String update(#RequestBody HouseModel model, #PathVariable int age, #PathVariable String name, #PathVariable String title, #PathVariable String family, #PathVariable String gender)
{
String result = service.update(model, age, name, title, family, gender);
// this will just return the string "Success" if update works or "Failed" if query is
wrong or not found
return result;
}
Service Class
#Service
public class Service
{
#Autowired
Dao dao;
public Service() {
}
public String update(HouseModel model, int age, String name, String title, String family)
{
return dao.update(HouseModel model, int age, String name, String title, String family);
}
}
Dao class
#Repository
public class Dao
{
public Dao () {
}
public String update(HouseModel model, int age, String name, String title, String family)
{
String result = "";
//some long query that updates the table and will populate result as "Success" or "Failed"
return result
}
}
Controller test class
#EnableWebMvc
#WebAppConfiguration
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:applicationContext-testing.xml",
"classpath:applicationContext-EIPW.xml"})
public class ControllerTest {
#Autowired
private Controller controller;
#Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
#Before
public void setup() throws Exception {
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void test_update() throws Exception {
String URI = "/user/landing/22/Test/Mr/Yes/Male";
String content = "{\n \"HouseId\": 5,\n \"DateOfPurchase\": \"2019-01-01\",\n \"Price\": 100,\n \"Floors\": 5,\n \"Style\": \"Victorian\",\n}";
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.put(URI).contentType(MediaType.APPLICATION_JSON).content(content).accept(MediaType.APPLICATION_JSON);
MvcResult mvcResult = mockMvc.perform(requestBuilder).andDo(MockMvcResultHandlers.print()).andReturn();
}
j.ajax
$j.ajax({
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
type: "PUT",
async: false,
data: JSON.stringify(
buildEdit(editRecords[i], ecRecord)
),
url:
"/user/landing/22/Test/Mr/Yes/Male",
dataType: "text"
printed error message
MockHttpServletRequest:
HTTP Method = PUT
Request URI = /user/landing/22/Test/Mr/Yes/Male
Parameters = {}
Headers = {Content-Type=[application/json], Accept=[application/json]}
Handler:
Type = controller.Controller
Async:
Was async started = false
Async result = null
Resolved Exception:
Type = org.springframework.web.HttpMediaTypeNotSupportedException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
MockHttpServletResponse:
Status = 415
Error message = null
Headers = {Accept=[application/octet-stream, */*, text/plain;charset=ISO-8859-1, */*, application/xml, text/xml, application/*+xml, application/x-www-form-urlencoded, multipart/form-data]}
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
Some Comments:
So I've had over 50 stack overflow tabs open relating to the same problem, and a lot of them had similar solutions that seemed so simple. Here are some, if not all of the things I did in attempts to try and solve this problem:
Switched around the content-type and accepts headers of requestBuilder to be MediaTypes of APPLICATION_JSON or APPLICATION_JSON_VALUE or ALL_VALUE, etc
Added produces or consumes = "application/json" or MediaType.APPLICATION_JSON/APPLICATION_JSON_VALUE/ALL_VALUE into the requestMapping().
Played around with a.jax to change content-type or accepts around
A couple of other things that I don't remember, but alas the 415 status is still here
I also do have setters and a default constructor in the HouseModel, and default constructors in every layer. I am 99.9% sure I have tried almost everything, if not everything, unless I am just missing something and am being stupid then yeah. I sent the request with the body as JSON raw an as:
{
"HouseId": 5,
"DateOfPurchase": "2019-01-01",
"Price": 100,
"Floors": 5,
"Style": "Victorian",
}
and it returned back success, I will attach its headers here:
[![Picture Link][1]][1]
[1]: https://i.stack.imgur.com/AqKnY.png
There is something interesting though, I did get one method to work but it required no arguments in its parameters, it was just a get method (dao calls database to store stuff in a list):
**Controller method**
#RequestMapping(value = "/levels", method = RequestMethod.POST, produces = "application/json")
public #ResponseBody String getLevels() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
// there is a long logic after this map to populate the map
Map<LevelObject, List<LevelObject>> map = new HashMap<LevelObject, List<LevelObject>>();
return mapper.writeValueAsString(map);
}
This is such a simple test and it worked perfectly fine, giving me a status 200 and my expected result.
**Test class method**
#Test
public void test_getLevels() throws Exception {
String URI = "/user/levels";
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post(URI).accept(MediaType.APPLICATION_JSON);
MvcResult mvcResult = mockMvc.perform(requestBuilder).andExpect(status().isOk()).andReturn();
}
**j.ajax for the getLevels method**
$j.ajax({
type: "POST",
url: "user/levels",
async: false,
dataType: "json",
Thank you so much!
Though I am not a front-end developer, I am sure that problem is in below line
data: JSON.stringify(
buildEdit(editRecords[i], ecRecord)
)
Reason - I tested your code locally. Code works fine from postman, if I select request body as raw and type as JSON
But if select request body as raw and type as "TXT". I am getting same error as you.
[![enter image description here][2]][2]
So, I am sure that your request body is not being built as JSON. rather it is being sent as some other format. Hence, the error.
[2]: https://i.stack.imgur.com/cqSCC.png
Also, you can try to change dataType: "text" to dataType: "json"
Please try the below,
$j.ajax({
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
type: "PUT",
async: false,
data:
buildEdit(editRecords[i], ecRecord),
url:
"/user/landing/22/Test/Mr/Yes/Male",
dataType: "json"
Remove converting the json to String
Change the dataType to json

spring mvc transport json to object

I am trying to post a json using ajax to my spring mvc controller I am using code like this in my js file:
$('#regist').click(function () {
$.ajax({
url: 'user/regist',
contentType: "application/json; charset=utf-8",
type: 'post',
dataType: 'json',
success: function (data) {
var json = JSON.stringify(data);
alert(json);
},
fail: function (errMsg) {
alert(errMsg);
},
data: JSON.stringify({
'IDCard': '1234567890'
})
})
});
the signature of my controller function is like this:
#RequestMapping(value = "/regist", method = RequestMethod.POST)
#ResponseBody
public ResultJson regist(HttpSession session, #RequestBody RegistFormJson json)
the RegistFormJson goes like this:
public class RegistFormJson {
private String IDCard;
public String getIDCard() {
return IDCard;
}
public void setiDCard(String IDCard) {
this.IDCard = IDCard;
}
}
now when I send my request, and what I get from my controller using
logger.info(json.getIDCard);
is null.When I change my bean propertity to idCard and change my other code as well ,I can get the result successfully. Who can tell me why ? And If I want to use IDCard in my code, how can I get the result .Thanks
Spring comes with Jackson API which uses Standard Java Code Convention to map JSON properties to Java models.
Since IDCard is not in lower camel case, Jackson API is not able to map the JSON property.
To overcome this you need to specify a #JsonProperty("IDCard") annotation on a Java attribute in order to use IDCard for your JSON property.
Likewise, you can set the PropertyNamingStrategy on the ObjectMapper to overcome this issue.

Deserializing json array in Spring MVC controller

I am sending a list of json object and trying to deserialize it in my Spring controller. But all the time I am getting error of 'Bad request' and results into a status code of 415. However, my json array is a valid one.
json is -
{
"users": [
{
"userName": "john",
"email": "john#gmail.com",
"user_id": "u223344"
},
{
"userName": "Smith",
"email": "smith#gmail.com",
"user_id": "u223345"
}
]
}
Ajax call is as follows -
$.ajax({
url: $("#addNewUser").attr("action"),
data: JSON.stringify({users : dataToSend}),
dataType: 'json',
type: "POST",
beforeSend: function(xhr) {
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("Content-Type", "application/json");
},
success: function(data){
alert('success= ' + data);
},
error:function(data,status,er) {
alert("error: "+ data.responseText +" status: "+status+" er:"+er);
}
});
Wrapper classes are as follows. User and UserWrapper class -
public class User {
private String email;
private String userName;
private String user_id;
//getters and setters
}
public class UserWrapper {
private List<User> userList;
//getter and setter
}
And finally the spring MVC controller is -
#RequestMapping(value="/user/add", method=RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public void createTeamMember(#RequestBody UserWrapper userWrapper) {
try{
for(User user : userWrapper.getUserList()){
System.out.println(user.getEmail());
}
}catch(Exception ex){
ex.printStackTrace();
}
}
I've added dependency for jackson-core and jackson-mapper in pom.xml. And I am using Spring 4.0.3. Any help is appreciated.
As #shazin is saying, you've most likely posted a wrong method to your question, or if not, simply make a change that he suggested.
You'll need another fix, and that is renaming the usersList property from UserWrapper to users so that it matches the JSON property being sent.
We these fixes, you should not have further problems, since your request is OK.
I think you need to change your #RequestBody POJO to UserWrapper
#RequestMapping(value="/task/add", method=RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public void createTeamMember(#RequestBody UserWrapper userWrapper) {
// Code to create members
}
I will not suspect server side binding error yet because you are getting 415 - Unsupported Media Type error. You are setting correct media type on controller and hence server side is looking good.
At client side, Please make sure you are using jquery 1.5+ to make sure beforeSend() method is getting invoked.
Easier way to content type will be,
$.ajax({
url:api,
....
contentType: "application/json"
});
Please inspect network request from browser and make sure content type is set in header.
If you receive 400-Bad Request, then you can start looking deserializing issues.

Problems sending multiple objects through POST and SPRING-MVC

I'm developing REST services which have to receive multiple info. In this case, two objects and an attribute.
This is the javascript where I'm testing the POST request
var user = {
username: "admin",
password: "admin"
};
var userToSubscribe = {
username: "newuser",
password: "newpassword",
email: "user#1and1.es"
};
var openid = "myopenid";
$.ajax({
url: '/myportal/rest/subscribeUser.json',
type: 'POST',
dataType: 'json',
contentType: 'application/json',
mimeType: 'application/json',
data: JSON.stringify({ user: user, userToSubscribe: userToSubscribe, openid: openid})
});
The POST request:
JSON
openid
"myopenid"
user
Object { username="admin", password="admin"}
userToSubscribe
Object { username="newuser", password="newpassword", email="user#1and1.es"}
Source
{"user":{"username":"admin","password":"admin"},"userToSubscribe":{"username":"newuser","password":"newpassword","email":"user#1and1.es"},"openid":"myopenid"}
And the controller which handles the POST:
#RequestMapping(method=RequestMethod.POST, value="/subscribeUser.json")
public #ResponseBody Message subscribeUser(#RequestBody("user") User user, #RequestBody("userToSubscribe") User userToSubscribe, #RequestParam String openid){
...
}
And the error is
POST subscribeUser.json 400 Incorrect request localhost:8080 990 B [::1]:8080
What am i doing wrong?
Thank you
The request body will contain the entire JSON content. So when you want to map the JSON, you use only one RequestBody annotated-parameter. You will have to do something like this:
public #ResponseBody Message subscribeUser(#RequestBody String str)
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(str);
And then use the convertValue method of the mapper to get your different objects from the string.
JsonNode node = mapper.readTree(str);
User theUser = mapper.convertValue(node.get("user"), User.class);
Similarly for the other objects
You cannot use #ModelAttributes in a RESTful method that accepts JSON. I believe the proper method is to use #RequestBody, as done here. You will most likely need to wrap the objects in some wrapper class, but I could be wrong there as I have never personally tried to pass multiple JSON objects in one request before.
That said, I think it would be a good idea if you rethought your REST api, removing the JSON arguments and instead passing them in as part of the URI path, if possible. I would suggest reading through this blog post.
You can create a java bean(POJO) containing all the objects like..
class JavaBean{
private User user;
private UserTOSubscribe userToSubscribe;
private Long openId;
// getter and setter
}
and pass this bean in to the Web service. so web service looks like..
#RequestMapping(method=RequestMethod.POST, value="/subscribeUser.json")
public #ResponseBody Message subscribeUser(#RequestBody JavaBean javaBean) {
...
}

Categories