I want to make a service with Spring's RestTemplate, in my service side the code is like this :
#PostMapping(path="/savePersonList")
#ResponseBody
public List<Person> generatePersonList(#RequestBody List<Person> person){
return iPersonRestService.generatePersonList(person);
}
In client side if I call the service with this code:
List<Person> p = (List<Person>) restTemplate.postForObject(url, PersonList, List.class);
I can't use the p object as List<Person>, it will become a LinkedHashList.
After some research I find a solution that said I have to call the service with exchange method:
ResponseEntity<List<Person>> rateResponse = restTemplate.exchange(url, HttpMethod.POST, personListResult, new ParameterizedTypeReference<List<Person>>() {});
and with this solution the server can't take the object and raise an exception , what's the correct way?
Check if your code is like below. This should work.
//header
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
//person list
List<Person> personList = new ArrayList<Person>();
Person person = new Person();
person.setName("UserOne");
personList.add(person);
//httpEnitity
HttpEntity<Object> requestEntity = new HttpEntity<Object>(personList,headers);
ResponseEntity<List<Person>> rateResponse = restTemplate.exchange(url, HttpMethod.POST, requestEntity,new ParameterizedTypeReference<List<Person>>() {});
It may be helpful for you.
List<Integer> officialIds = null;
//add values to officialIds
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
HttpEntity<List<Integer>> request = new HttpEntity<List<Integer>>(officialIds,
headers);
ResponseEntity<YourResponseClass[]> responses =
restTemplate.postForEntity("your URL", request , YourResponseClass[].class );
List<YourResponseClass> list = Arrays.asList(responses.getBody());
I had similar challenge, and here are my 2 cents.
My Controller Class with POST Mapping
#PostMapping("/fetch/projects")
public ResponseEntity<List<Project>> getAllProjects(#RequestBody List<UserProject> userProject) {
// Convert List of projectIds to List of Long using Lambda Functions
List<Long> projectIds = userProject.stream().map(UserProject::getProjectId).collect(Collectors.toList());
List<Project> projectList = projectService.getAllProjectsByProjectIds(projectIds);
log.info("<< Fetching Projects based on Project Ids !");
return new ResponseEntity<List<Project>>(projectList, HttpStatus.OK);
}
My Static URL for the above controller
final String projectBaseUri = "http://localhost:6013/api/v1/project/fetch/projects";
My Caller Service
protected List<Project> getProjectsByIds(List<UserProject> userProject) {
String url = projectBaseUri;
log.info("Project URL : " + url);
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Object> requestEntity = new HttpEntity<Object>(userProject,headers);
ResponseEntity<List<Project>> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity,new ParameterizedTypeReference<List<Project>>() {});
return response.getBody();
}
Related
I'm currently working on a Spring Boot CRUD RESTful API with an User entity that consists of two parameters : name and id. Its endpoints are :
POST REQUEST IN /users - Create an user
GET REQUEST IN /users/{id} - List a specific user by its id
GET REQUEST IN /users - List all users
PUT REQUEST IN /users/{id} - Update a specific user by its id
DELETE REQUEST IN /users/{id} - Delete a specific user by its id
Each endpoint is built with a controller and a service to implement its logic.
I've already wrote unit tests for my controllers and services, now i'm trying to build integration tests to assert that my endpoints work properly as a group of components.
No mocking involved, all this will be done by using the TestRestTemplate and asserting that every operation was executed correctly and every response checked with its expected value.
The following are the tests I've already built :
#SpringBootTest(classes = UsersApiApplication.class,
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UserControllerTest {
#LocalServerPort
private int port;
TestRestTemplate restTemplate = new TestRestTemplate();
HttpHeaders headers = new HttpHeaders();
private void instantiateNewUser() {
User userNumberFour = new User();
userNumberFour.setName("Four");
userNumberFour.setId(4L);
ResponseEntity<User> responseEntity = restTemplate
.postForEntity(createURLWithPort("/users"), userNumberFour, User.class);
}
#Test
public void createNewUserTest() {
User testUser = new User();
testUser.setName("Test User");
testUser.setId(5L);
ResponseEntity<User> responseEntity = restTemplate
.postForEntity(createURLWithPort("/users"), testUser, User.class);
assertEquals(201, responseEntity.getStatusCodeValue());
assertEquals(responseEntity.getBody(), testUser);
}
#Test
public void listSpecificUserTest() throws JSONException {
instantiateNewUser();
HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
createURLWithPort("/users/4/"),
HttpMethod.GET, httpEntity, String.class);
String expectedResponseBody = "{id:4,name:Four}";
assertEquals(200, responseEntity.getStatusCodeValue());
JSONAssert.assertEquals(expectedResponseBody, responseEntity.getBody(), false);
}
#Test
public void listAllUsersTest() throws JSONException {
instantiateNewUser();
HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
createURLWithPort("/users"),
HttpMethod.GET, httpEntity, String.class);
//All instantiated users
ArrayList<String> expectedResponseBody = new ArrayList<>(Collections.emptyList());
expectedResponseBody.add("{id:1,name:Neo}");
expectedResponseBody.add("{id:2,name:Owt}");
expectedResponseBody.add("{id:3,name:Three}");
expectedResponseBody.add("{id:4,name:Four}");
assertEquals(200, responseEntity.getStatusCodeValue());
JSONAssert.assertEquals(String.valueOf(expectedResponseBody), responseEntity.getBody(), false);
}
#Test
public void deleteSpecificUserTest() throws JSONException {
instantiateNewUser();
HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
createURLWithPort("/users/4/"),
HttpMethod.DELETE, httpEntity, String.class);
assertEquals(204, responseEntity.getStatusCodeValue());
JSONAssert.assertEquals(null, responseEntity.getBody(), false);
}
private String createURLWithPort(String uri) {
return "http://localhost:" + port + uri;
}
}
As you can see, it's missing the PUT request method test, which is the update endpoint.
To implement its logic, i need to send a message body with the content that will override the old users characteristics, but how?
This is what i made so far :
#Test
public void updateSpecificUserTest() throws JSONException {
instantiateNewUser();
HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
createURLWithPort("/users/4/"),
HttpMethod.PUT, httpEntity, String.class);
String expectedResponseBody = "{id:4,name:Four Updated}";
assertEquals(200, responseEntity.getStatusCodeValue());
JSONAssert.assertEquals(expectedResponseBody, responseEntity.getBody(), false);
}
Would appreciate if someone could help with this one, didn't found the answer online.
HttpEntity<String> httpEntity = new HttpEntity<String>(null, headers);
You have sent body as null. Also you can use mockMvc it is better approach then rest template.
User testUser = new User();
testUser.setName("Test User");
HttpEntity<String> httpEntity = new HttpEntity<String>(testUser, headers);
https://howtodoinjava.com/spring-boot2/testing/spring-boot-mockmvc-example/
So, the solution to my problem really was that I was sending a null request body in my httpEntity.
I also needed to set the content type to JSON :
#Test
public void updateSpecificUserTest() throws JSONException, JsonProcessingException {
instantiateNewUser();
User updatedUser = new User();
updatedUser.setName("Updated");
updatedUser.setId(4L);
ObjectMapper mapper = new ObjectMapper();
String requestBody = mapper.writeValueAsString(updatedUser);
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> httpEntity = new HttpEntity<String>(requestBody, headers);
ResponseEntity<String> responseEntity = restTemplate.exchange(
createURLWithPort("/users/4/"),
HttpMethod.PUT, httpEntity, String.class);
String expectedResponseBody = "{id:4,name:Updated}";
assertEquals(200, responseEntity.getStatusCodeValue());
JSONAssert.assertEquals(expectedResponseBody, responseEntity.getBody(), false);
}
Say,
I have a method getTemplateData() and I want to mock a restTemplate.exchange() method call in that
public List<String> getTemplateData(String templateId, String storeId, String projectId) {
RestTemplate restTemplate = new RestTemplate();
Map<String, String> bodyObject = new HashMap<>();
bodyObject.put("functionalAreaId", templateId);
bodyObject.put("storeId", storeId);
bodyObject.put("projectId", projectId);
HttpEntity<?> requestEntity = new HttpEntity<>(bodyObject, null);
ResponseEntity<List<String>> result =
restTemplate.exchange(
BaseUrl + "/template",
HttpMethod.POST,
requestEntity,
new ParameterizedTypeReference<List<String>>() {});
List<String> screens = result.getBody().stream().collect(Collectors.toList());
log.info(
"Completed executing the method getTemplateData for the templateId:{} and storeId:{}",
templateId,
storeId);
return screens;
}
I want to mock the line
ResponseEntity<List<String>> result =
restTemplate.exchange(
BaseUrl + "/template",
HttpMethod.POST,
requestEntity,
new ParameterizedTypeReference<List<String>>() {});
Is it possible to mock a statement in Java?
Yes, that can be mocked.
#Test
public void test() {
// let's create mock first, you can use annotation also
RestTemplate mockTemplate = Mockito.mock(RestTemplate.class);
Mockito.when(mockTemplate.exchange(Mockito.eq(BaseUrl + "/template"),
Mockito.eq(HttpMethod.POST),
Mockito.eq(requestEntity),
Mockito.any(ParameterizedTypeReference.class))
.thenReturn(new ResponseEntity<>(Arrays.asList("data"), HttpStatus.OK))
}
Can some one tell me how to send a POST request with raw data parameters as in the picture below
i have tried the following code but its not working
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
JsonObject properties = new JsonObject();
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
try {
properties.addProperty("app_id", appId);
properties.addProperty("identity","TestAPI");
properties.addProperty("event", "TestCompleted");
properties.addProperty("testType", t.getTestType());
properties.addProperty("testName",t.getTestName());
properties.addProperty("chapter","");
properties.addProperty("module","");
properties.addProperty("pattern",t.getTestPattern());
HttpEntity<String> request = new HttpEntity<>(
properties.toString(), headers);
// params.add("properties", properties.toString());
restTemplate.postForObject(url, request, String.class);
can someone help?
Try this :
#RestController
public class SampleController {
#RequestMapping("/req")
public String performReqest(){
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
JsonObject properties = new JsonObject();
properties.addProperty("no", "123");
properties.addProperty("name", "stackoverflow");
HttpEntity<String> request = new HttpEntity<>(properties.toString(), headers);
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.postForObject("http://localhost:4040/student", request, String.class);
return "Response from Server is : "+response;
}
#RequestMapping("/student")
public String consumeStudent(#RequestBody Student student){
System.out.println(student);
return "Hello.."+student.name;
}
}
class Student{
public int no;
public String name;
public Map<String,String> properties;
}
Don't forgot to move Student class and change all field to private with require getters and setters.
Above code is only for demo purpose.
Please try with this:
ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
Did u tried using postmaster and checked the output first. If its working then you can go for post or exchange method. exchange returns and post dont.
try this:
URI uri = new URI("something");
Map<String, Object> params = new HashMap<>();
params.put("app_id", "something");
params.put("identity", something);
HttpEntity<Map<String, String>> request = new HttpEntity(params , headers);
ResponseEntity<String> response = restTemplate.postForEntity(uri, request, String.class);
I want to make a service with Spring's RestTemplate, in my service side the code is like this :
#PostMapping(path="/savePersonList")
#ResponseBody
public List<Person> generatePersonList(#RequestBody List<Person> person){
return iPersonRestService.generatePersonList(person);
}
In client side if I call the service with this code:
List<Person> p = (List<Person>) restTemplate.postForObject(url, PersonList, List.class);
I can't use the p object as List<Person>, it will become a LinkedHashList.
After some research I find a solution that said I have to call the service with exchange method:
ResponseEntity<List<Person>> rateResponse = restTemplate.exchange(url, HttpMethod.POST, personListResult, new ParameterizedTypeReference<List<Person>>() {});
and with this solution the server can't take the object and raise an exception , what's the correct way?
Check if your code is like below. This should work.
//header
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
//person list
List<Person> personList = new ArrayList<Person>();
Person person = new Person();
person.setName("UserOne");
personList.add(person);
//httpEnitity
HttpEntity<Object> requestEntity = new HttpEntity<Object>(personList,headers);
ResponseEntity<List<Person>> rateResponse = restTemplate.exchange(url, HttpMethod.POST, requestEntity,new ParameterizedTypeReference<List<Person>>() {});
It may be helpful for you.
List<Integer> officialIds = null;
//add values to officialIds
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
HttpEntity<List<Integer>> request = new HttpEntity<List<Integer>>(officialIds,
headers);
ResponseEntity<YourResponseClass[]> responses =
restTemplate.postForEntity("your URL", request , YourResponseClass[].class );
List<YourResponseClass> list = Arrays.asList(responses.getBody());
I had similar challenge, and here are my 2 cents.
My Controller Class with POST Mapping
#PostMapping("/fetch/projects")
public ResponseEntity<List<Project>> getAllProjects(#RequestBody List<UserProject> userProject) {
// Convert List of projectIds to List of Long using Lambda Functions
List<Long> projectIds = userProject.stream().map(UserProject::getProjectId).collect(Collectors.toList());
List<Project> projectList = projectService.getAllProjectsByProjectIds(projectIds);
log.info("<< Fetching Projects based on Project Ids !");
return new ResponseEntity<List<Project>>(projectList, HttpStatus.OK);
}
My Static URL for the above controller
final String projectBaseUri = "http://localhost:6013/api/v1/project/fetch/projects";
My Caller Service
protected List<Project> getProjectsByIds(List<UserProject> userProject) {
String url = projectBaseUri;
log.info("Project URL : " + url);
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<Object> requestEntity = new HttpEntity<Object>(userProject,headers);
ResponseEntity<List<Project>> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity,new ParameterizedTypeReference<List<Project>>() {});
return response.getBody();
}
I want to send JSON as an input from Microservice M1 to a Microservice M2.
M1 and M2 both are on different machines.
I am new to Spring Boot,
I found some code but I am unable to get it.
Please help.
make a class on both microservices or make a jar of that class and add to both microservices so that they both can access the same data.
Lets say the class is
class TestData{
private String name;
private String id;
// getters and setters
}
Now you can send data from M1 to M2 as following
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
TestData data = new TestData();
HttpEntity<?> entity = new HttpEntity<Object>(data,headers);
ResponseEntity<Object> responseEntity = restTemplate.exchange("url", HttpMethod.POST, entity, Object.class);
In Microservice M2 you can write a controller to get the data and process it as follows
#RequestMapping(value="/url",method=RequestMethod.POST)
public Object do(#RequestBody TestData data){
// do something
return //something
}
Let's Say Your Have MicroService1 which needs to send JSONObject => JsonObject to another MicroService2 which is on different Machine but on same network .
Sender Side:
RestTemplate restTemplate = new RestTemplate();
String jsonString = restTemplate.postForObject("http://10.177.7.128:8080/user/insertJsonObject",jsonObject,String.class);
Syntax for restTemplate.postForObject is:
ResponseType var1 = restTemplate.postForObject("network ip Address:portnumber/path",JSONObject,ResponseType)
To Know the URI go to System Preferences > Network
To Receive the object at the receiver Side
#RequestMapping(value="/user/insertJsonObject", method=RequestMethod.POST)
public String updateProductSold(#RequestBody JSONObject jsonObject) {
...Body
...
...
return responseStatus;
Here is the sample code
public class Test {
public static void main(String[] args) {
String jsonString = "{\"id\" : \"123\",\"name\" : \"Tom\",\"class\" : {\"subject\" : \"Math\",\"teacher\" : \"Jack\"}}";
RestTemplate restTemplate = new RestTemplate();
String url = "http://192.1168.1.190:8080/test" // url for second service
System.out.println(responserEntityValue(jsonString,restTemplate,url,HttpMethod.POST,String.class));
}
public ResponseEntity<String> responserEntityValue(final String body, final RestTemplate restTemplate,
final String uRL, final HttpMethod requestMethod, final Class<String> stringClass) {
HttpHeaders headers = new HttpHeaders();
// Set all headers
headers.add(DatabaseConstants.CONTENT_TYPE, "application/json");
HttpEntity<String> request = new HttpEntity<>(body, headers);
return restTemplate.exchange(uRL, requestMethod, request, stringClass);
}