Issue
I can't figure out what the problem is. I am using postgre DB. When I run a test for the GET method, an error occurs, for the second day I can not solve it.
Here is my Entity class
import lombok.*;
import lombok.experimental.FieldDefaults;
import javax.persistence.*;
@Entity
@Table(name = "cities_catalog")
@FieldDefaults(level = AccessLevel.PRIVATE)
@Data
@NoArgsConstructor
public class PostgreCity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Integer id;
@Column(name = "name")
String name;
public PostgreCity(String name) {
this.name = name;
}
}
here is my Repository class
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface CityRepository extends JpaRepository<PostgreCity, Integer> {
}
here is my Controller class
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.experimental.FieldDefaults;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@AllArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class CityPostController {
@Autowired
CityRepository cityRepository;
@GetMapping(value = "/get")
public List<PostgreCity> get(){
List<PostgreCity> list = this.cityRepository.findAll();
return list;
}
}
here is my Junit test class
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import java.util.HashMap;
import static org.junit.jupiter.api.Assertions.*;
class CityPostControllerTest extends RequestService {
@Autowired
CityRepository cityRepositoryp;
Integer id;
@BeforeEach
void setUp() {
}
@AfterEach
void tearDown() {
}
@Test
void get() {
ResponseEntity<PostgreCity> responseEntity = this.get(PostgreCity.class);
assertNotNull(responseEntity);
assertEquals(HttpStatus.OK.value(), responseEntity.getStatusCodeValue());
}
@Override
public String getPath() {
return "/get";
}
}
here is my RequestService class
import io.egrow.eugene.insurance.InsuranceApplicationTests;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.*;
public abstract class RequestService extends InsuranceApplicationTests {
@Autowired
TestRestTemplate testRestTemplate;
public <T> ResponseEntity<T> patchNoAuth(String payload, Class<T> tClass) {
HttpHeaders headers = getHeaderWithoutAuthentication();
HttpEntity<String> entity = new HttpEntity<>(payload, headers);
return testRestTemplate.exchange(this.getPath(), HttpMethod.PATCH, entity, tClass);
}
public <T> ResponseEntity<T> get(Class<T> tClass) {
return testRestTemplate.getForEntity(this.getPath(), tClass);
}
private HttpHeaders getHeaderWithoutAuthentication() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
public abstract String getPath();
}
here is error message when I run test.
org.springframework.web.client.RestClientException: Error while extracting response for type [class io.egrow.eugene.insurance.boundary.databases.postgre.models.cities.PostgreCity] and content type [application/json;charset=utf-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `io.egrow.eugene.insurance.boundary.databases.postgre.models.cities.PostgreCity` from Array value (token `JsonToken.START_ARRAY`); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `io.egrow.eugene.insurance.boundary.databases.postgre.models.cities.PostgreCity` from Array value (token `JsonToken.START_ARRAY`)
at [Source: (PushbackInputStream); line: 1, column: 1]
Solution
The problem is here:
ResponseEntity<PostgreCity> responseEntity = this.get(PostgreCity.class);
You are expecting a single entity but in the RestController you have a List:
@GetMapping(value = "/get")
public List<PostgreCity> get(){
List<PostgreCity> list = this.cityRepository.findAll();
return list;
}
For getting the list you can use the ParameterizedTypeReference, like so:
ResponseEntity<List<PostgreCity>> responseEntity =
restTemplate.exchange(
"/get",
HttpMethod.GET,
null,
new ParameterizedTypeReference<List<PostgreCity>>() {}
);
List<PostgreCity> postgreCities = responseEntity.getBody();
For more details and reference can have a look at this tutorial:
https://www.baeldung.com/spring-resttemplate-json-list
Answered By - cdr89
Answer Checked By - David Marino (JavaFixing Volunteer)