I have to retuen the message "Data Added" in the api in ResponseBody
Create a api while enters student data
/newStudent
Request Body:
{
"name":"Shubham",
"rollno":22,
"studentid":1
}
Response:
{
"status":"OK",
"message":"Data Added"
}
#RequestMapping("/studentdata")
#ResponseBody
#ResponseStatus(HttpStatus.OK )
You can create a custom response class that looks like this:
class CustomResponse {
private String status;
private String message;
// Constructor/Getters/Setters
}
Then in your controller return ResponseEntity for example:
CustomResponse response = new CustomResponse("OK", "Data Added");
return ResponseEntity.ok(response); // the ok will return HTTP Status 200
Or if you want another HttpStatus, then you can use for example:
return new ResponseEntity<>(response, HttpStatus.CREATED);
^^^^^^^^^^^^^^^^^^
First of all you should create a Response class which will hold status code and your custom message like the following class :
#Data
#AllArgsConstructor
#NoArgsConstructor
public class Response {
private String statusCode;
private String statusMsg;
}
So in your controller where you post the object use ResponseEntity which can allow you to customize HTTP response methods. For example:
#Autowired
private StudentRepository studentRepository;
#PostMapping("/newStudent")
public ResponseEntity<Response> saveEmployee(#RequestBody Student
student){
studentRepository.save(student);
Response response = new Response();
response.setStatusCode("200");
response.setStatusMsg("Your message");
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}
This is how to return custom object in response.
router.post("/newStudent", async (req, res) => {
const { name, rollNo, studentId } = req.data;
// POST data to DB
const result = await AddStudentDataToDB({ name, rollNo, studentId });
res.status(200).json({
status: 'ok',
message: 'Data Added'
});
});
import org.json.simple.JSONObject;
#ResponseBody
#RequestMapping(value = "/studentdata", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
public String message(#RequestBody String transaction) {
String response = "";
JSONObject obj = new JSONObject();
obj.put("status", "OK");
obj.put("message", "Data Added");
response = obj.toJSONString();
return response;
}
It worked for me like this in Response class:
public class Response {
private String statusCode;
private String statusMsg;
public String getStatusCode() {
return statusCode;
}
public void setStatusCode(String statusCode) {
this.statusCode = statusCode;
}
public String getStatusMsg() {
return statusMsg;
}
public void setStatusMsg(String statusMsg) {
this.statusMsg = statusMsg;
}
}
In controller:
#PostMapping("/newStudent")
public ResponseEntity<Response> saveStudent(#RequestBody Student student) {
Student save = service.save(student);
Response response = new Response();
response.setStatusCode("200");
response.setStatusMsg("Data Added");
return ResponseEntity.status(HttpStatus.CREATED).body(response);
}
Related
HttpDataClient.java class is sending dataId to external service and should receive something in response. For my test I should test that RestTemplate and check if I am getting good response.
public class HttpDataClient implements DataClient{
private final static Logger LOGGER = LoggerFactory.getLogger(HttpDataClient.class);
private final RestTemplate restTemplate;
private final ObjectMapper objectMapper = new ObjectMapper();
public HttpDataClient(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
#Override
public DataResponse getData(String dataId) {
try{
JsonNode node = restTemplate.exchange(
String.format("/data/{0}", dataId),
HttpMethod.POST,
new HttpEntity<>(buildRequest(dataId), headers()),
JsonNode.class
).getBody();
return dataResponse(node);
}catch (HttpStatusCodeException e) {
String msg = String.format(
"Error getting data for dataId: {0}",
dataId,
e.getStatusCode(),
e.getResponseBodyAsString());
LOGGER.error(msg);
return dataResponse.failed();
}
}
private MultiValueMap<String, String> headers() {
final LinkedMultiValueMap<String, String> mv = new LinkedMultiValueMap<>();
mv.set(HttpHeaders.CONTENT_TYPE, "application/json");
return mv;
}
private DataResponse dataResponse(JsonNode node) {
return DataResponse.dataResponse(
asString(node, "dataId"),
asString(node, "author"),
asString(node, "authorDataId"),
asString(node, "serverSideDataId")
);
}
private JsonNode buildRequest(String dataId) {
ObjectNode root = objectMapper.createObjectNode();
root.put("dataId", dataId);
return root;
}
}
DataResponse.java
public class DataResponse {
public final String dataId;
public final String author;
public final String authorDataId;
public final String serverSideDataId;
public DataResponse(
String dataId,
String author,
String authorDataId,
String serverSideDataId) {
notNull(dataId, "dataId must be set");
notNull(author, "author must be set");
notNull(authorDataId, "authorDataId must be set");
notNull(serverSideDataId, "serverSideDataId must be set");
this.dataId = dataId;
this.author = author;
this.authorDataId = authorDataId;
this.serverSideDataId = serverSideDataId;
}
public static GameDataResponse gameDataResponse(
String gameId,
String vendor,
String vendorGameId,
String serverSideGameId){
return new GameDataResponse(
gameId,
vendor,
vendorGameId,
serverSideGameId);
}
//TODO PD-849 - add faild method
public static GameDataResponse failed() {
return new GameDataResponse(
failed().gameId,
failed().vendor,
failed().vendorGameId,
failed().serverSideGameId
);
}
}
Interface:
public interface DataService {
DataResponse getData(String dataId);
}
Here is the test class:
#RunWith(MockitoJUnitRunner.class)
public class HttpDataServiceTest {
RestTemplate restTemplate = Mockito.mock(RestTemplate.class);
private final HttpDataService httpDataService = new HttpDataService(restTemplate);
#Test
public void getData(){
ObjectNode responseNode = JsonNodeFactory.instance.objectNode();
responseNode.put("dataId", "");
responseNode.put("author", "");
responseNode.put("authorDataId", "");
responseNode.put("serverSideDataId", "");
Mockito
.when(restTemplate.exchange(
ArgumentMatchers.eq("/data/dataIdTest"),
ArgumentMatchers.eq(HttpMethod.POST),
ArgumentMatchers.any(),
ArgumentMatchers.<Class<JsonNode>>any()))
.thenReturn(new ResponseEntity<>(responseNode, HttpStatus.OK));
httpDataService.getData("dataIdTest");
}
}
So, when I debug I go trough test class and everything works fine, then it goes to HttpDataClient.java class to getData() method and when I am in restTemplate.exchangeI can see thatdataIdis sent, then it goes down to.getBody();` and it breaks. And I don’t get anything in return.
What am I missing here?
Any advice appreciated.
based just on a quick look - try changing
String.format("/data/{0}", dataId)
to
String.format("/data/%s", dataId)
in your DataResponse getData(String dataId) method
I have two classes PlaylistResource which has a method createPlaylist which takes an object of type PlaylistRequest. I want to create a POST request on localhost:9999/playlists I am using Postman and I am not sure how to pass the object of PlaylistRequest which is request to the method createPlaylist.
#XmlType(propOrder= {"title", "artistSeeds", "numberOfSongs"})
#XmlAccessorType(XmlAccessType.FIELD)
public class PlaylistRequest {
private String title = "";
#XmlElement(name = "seeds")
private List<String> artistSeeds;
#XmlElement (name = "size")
private int numberOfSongs = 0;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<String> getArtistSeeds() {
return artistSeeds;
}
public void setArtistSeeds(List<String> artistSeeds) {
this.artistSeeds = artistSeeds;
}
public int getNumberOfSongs() {
return numberOfSongs;
}
public void setNumberOfSongs(int numberOfSongs) {
this.numberOfSongs = numberOfSongs;
}
}
The other class:
#Path("playlists")
public class PlaylistResource implements PlaylistApi {
#Override
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response createPlaylist(PlaylistRequest request) {
if(request == null) {
System.out.println("Was here");
throw new ClientRequestException(new ErrorMessage("no parameter passed."));
}
try {
List<Song> playList = new ArrayList<>();
List<Song> songs = new ArrayList<>();
List<String> artistsIds = new ArrayList<>();
ArtistResource artistsResources = new ArtistResource();
int playlistDefaultSize = 10;
int i = 0;
do {
playList.add(songs.get(i));
i++;
}while( i < playlistDefaultSize);
Playlist playlist = new Playlist();
playlist.setTitle(request.getTitle());
playlist.setSize(songs.size());
playlist.setTracks(playList);
return Response.status(Response.Status.CREATED.getStatusCode()).entity(playlist).build();
} catch (Exception e) {
throw new RemoteApiException(new ErrorMessage(e.getMessage()));
}
}
}
Change this parameter from data class to string,
public Response createPlaylist(PlaylistRequest request) {
to
public Response createPlaylist(String request) {
then convert it using GSON into your data class.
PlaylistRequest request = new Gson().fromJson(request, new TypeToken<PlaylistRequest >(){}.getType());
Simply add a JSON object in Body of request, select Raw Json in Postman and paste the following object:
NOTE: Add a key Content-Type and set its value to application/json in Header of Request
{
"title": "Some title",
"artistSeeds": [
"string1",
"string2"
],
"numberOfSongs": 0
}
HEADER
BODY
I am getting HttpClientErrorException: 400 Bad Request when posting some data to client api.
Exception stack trace:
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:667)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:620)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:498)
Code
Mode class 1: UserApiResponseBean.java
import java.util.List;
public class UserApiResponseBean {
private String userCode;
private String userName;
private List<Department> DepartmentList;
public String getUserCode() {
return userCode;
}
public void setUserCode(String userCode) {
this.userCode = userCode;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public List<Department> getDepartmentList() {
return DepartmentList;
}
public void setDepartmentList(List<Department> departmentList) {
DepartmentList = departmentList;
}
}
Model Class 2: Department.java
public class Department {
private String departmentName;
private String businessArea;
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public String getBusinessArea() {
return businessArea;
}
public void setBusinessArea(String businessArea) {
this.businessArea = businessArea;
}
}
Client Code: Code piece calling client's api
UserApiResponseBean userApiResponseBean = new UserApiResponseBean();
userApiResponseBean.setUserName("userName1");
userApiResponseBean.setUserCode("001");
List<Department> departmentList = new ArrayList<Department>();
Department departmanetData = new Department();
departmanetData.setDepartmentName("Department 1");
departmanetData.setBusinessArea("Business Area 1");
departmentList.add(departmanetData);
userApiResponseBean.setDepartmentList(departmentList);
String userId="userId";
String password="password";
String url = "client api url";
HttpHeaders requestHeader = new HttpHeaders();
String encoding = Base64.getEncoder().encodeToString((userId + ":" + password).getBytes());
requestHeader.add(HttpHeaders.AUTHORIZATION, "Basic " + encoding);
requestHeader.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
requestHeader.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<UserApiResponseBean> requestEntity = new HttpEntity<UserApiResponseBean>(userApiResponseBean, requestHeader);
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
String result = responseEntity.getBody();
Somehow request construction is getting corrupted. Can you please help.
I do not have any json/xml related annotations in Model class, also there is no json/spring rest related data in spring-context.xml. Is that the problem ?
We are using Spring 4.3.0
Client is expecting a json data, they do not have same UserApiResponseBean.java class on their side.
Just adding the converter name isn't enough. Make sure that Jackson2 is present in your classpath
Jackson 2.x – com.fasterxml.jackson.databind
If using Maven
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.3</version>
</dependency>
I am trying to post a request to my service, but it's not working. I am getting 400 Bad Request. I have GET requests that are working perfectly in the same controller.
Here is the method:
#RequestMapping(value = "/assign", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public Form5398Obj arriveTrip(#PathVariable String siteId,
#RequestBody ErrorMsg anError) throws Exception {
System.out.println(anError.toString());
}
The ErrorMessage java class is as follows:
public class ErrorMsg {
private String code;
private String msg;
private String request;
public ErrorMsg(String code, String msg, String request)
{
this.code = code;
this.msg = msg;
this.request = request;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public String getRequest() {
return request;
}
public void setRequest(String request) {
this.request = request;
}
}
I did not configure anything else. What else do I need to do to get it to work? I am using JavaConfig, do I need to add any bean declarations?
I am sending:
with Content-Type: application/json
{
"code" : "101",
"msg" : "Hello Test",
"request" : "1"
}
I believe you need a no-argument constructor for ErrorMsg so that Jackson can instantiate an object to populate for the incoming request. Otherwise it would not know how the parameters in your 3 parameter constructor should be populated.
Try adding the following
public ErrorMsg() {
}
I have a method in a Spring MVC controller as follows:
// Gets a Person via REST.
#RequestMapping(value="/person/{personId}", method=RequestMethod.GET)
public ModelAndView getPerson(#PathVariable("personId") String personId) {
logger.info(RestController.class.getName() + ".getPerson() method called.");
Person person = personService.get(Integer.parseInt(personId));
return new ModelAndView(view,"person", person);
}
The method is working correctly but in the code to process the JSON on the client, I get the following exception:
Unrecognized field "person" (class libraryApp.model.Person), not marked as ignorable (6 known properties: , "personId", "address", "telephone", "books", "name", "email"])
The code is below:
// Set request.
String url = ("http://localhost:8080/Library/rest/person/1");
HttpGetRequest httpGetRequest = new HttpGetRequest(url, "GET", "");
// Make request.
httpGetRequest.get();
// Get response.
if (httpGetRequest.getResponseCode() != 200) {
throw new RuntimeException("Get request failed: HTTP error code: " + httpGetRequest.getResponseCode());
}
else {
// Receive JSON from server and convert to Person.
ObjectMapper mapper = new ObjectMapper();
Person person = mapper.readValue(httpGetRequest.getResponse(), Person.class);
System.out.println("Person:");
System.out.println(person.toString());
if (! (person.getBooks().isEmpty())) {
System.out.println("Books:");
for (Book book : person.getBooks()) {
System.out.println(book.toString());
}
}
}
Person is a simple POJO as follows:
public class Person implements Serializable {
// Attributes.
private Integer personId;
private String name;
private String address;
private String telephone;
private String email;
private List<Book> books;
I am using ModelAndView constructor, ModelAndView(String viewName, String modelName, Object modelObject). So according to the JavaDoc I have to specify a modelName but how can I deal with this on the client?
Now I am getting no response on the client from the following if I use a class called Messages in the following code:
ObjectMapper mapper = new ObjectMapper();
Object obj = mapper.readValue(httpGetRequest.getResponse(), Object.class);
if (obj instanceof Messages) {
Messages m = (Messages) obj;
for (String s : m.getMessages())
System.out.println("Here " + s);
}
Messages is a utility class:
public class Messages {
private List<String> messages;
public Messages() {
messages = new ArrayList<String>();
}
With the controller method now:
#RequestMapping(value="/person/{personId}", method=RequestMethod.GET)
#ResponseBody
public String getPerson(#PathVariable("personId") String personId) {
logger.info(RestController.class.getName() + ".getPerson() method called.");
Person person = personService.get(Integer.parseInt(personId));
ObjectMapper mapper = new ObjectMapper();
try {
Messages m = new Messages();
m.addMessage("SDGSFGSDFGSDFASDG");
return mapper.writeValueAsString(m);
// return mapper.writeValueAsString(person);
}
catch (JsonProcessingException ex) {
return null;
}
}
Logging the client, I get:
Sending Get request: http://localhost:8080/Library/rest/person/1.
Receiving response code: 200.
{messages=[SDGSFGSDFGSDFASDG]}
If there is no re-direction from your GET call, try this:
#RequestMapping(value="/person/{personId}", method=RequestMethod.GET)
#ResponseBody
public String getPerson(#PathVariable("personId") String personId) {
logger.info(RestController.class.getName() + ".getPerson() method called.");
Person person = personService.get(Integer.parseInt(personId));
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(person);
}
Make sure you Messages class is also a POJO
public class Messages implements Serializable{
private List<String> messages;
//setters and getters for messages
}