I’m getting following error if I try to return List which I get from field in my entity class. If I create List myself then I don’t get this error. I’m using SpringBoot 3.3.2 with Java 17.
Error:
"message": "Exception occurred: HttpMessageNotWritableException: Could not write JSON: class java.lang.String cannot be cast to class java.util.UUID (java.lang.String and java.util.UUID are in module java.base of loader 'bootstrap')",
<code>{
"message": "Exception occurred: HttpMessageNotWritableException: Could not write JSON: class java.lang.String cannot be cast to class java.util.UUID (java.lang.String and java.util.UUID are in module java.base of loader 'bootstrap')",
}
</code>
{
"message": "Exception occurred: HttpMessageNotWritableException: Could not write JSON: class java.lang.String cannot be cast to class java.util.UUID (java.lang.String and java.util.UUID are in module java.base of loader 'bootstrap')",
}
Controller Class
For testing purpose, I’m calling OrderRequestEntity directly from here and I’ve made sure that entity exists in database for given UUID. You can find OrderRequestEntity class after TestDto1, TestDto2 and GenericResponse in this post.
<code> @GetMapping("/res1")
private ResponseEntity<GenericResponse<TestDto1>> responseTest1(@RequestParam Integer num) {
TestDto2 testDto2 = new TestDto2();
List<UUID> uuidList = new ArrayList<>();
uuidList.add(UUID.randomUUID());
uuidList.add(UUID.randomUUID());
OrderRequestEntity entity = orderRequestRepository.findById(UUID.fromString("158790c2-ce63-4d00-b053-33f5a72782e7")).orElse(null);
uuidList = entity.getItems();
testDto2.setId(UUID.randomUUID());
testDto2.setUuidList2(uuidList);
TestDto1 testDto1 = new TestDto1();
testDto1.setId(UUID.randomUUID());
testDto1.setTestDto2(testDto2);
return ResponseEntity.ok(new GenericResponse<>(true, "response got", testDto1));
<code> @GetMapping("/res1")
private ResponseEntity<GenericResponse<TestDto1>> responseTest1(@RequestParam Integer num) {
TestDto2 testDto2 = new TestDto2();
List<UUID> uuidList = new ArrayList<>();
switch (num) {
case 1: {
uuidList.add(UUID.randomUUID());
uuidList.add(UUID.randomUUID());
break;
}
case 2: {
OrderRequestEntity entity = orderRequestRepository.findById(UUID.fromString("158790c2-ce63-4d00-b053-33f5a72782e7")).orElse(null);
uuidList = entity.getItems();
}
}
testDto2.setId(UUID.randomUUID());
testDto2.setUuidList2(uuidList);
TestDto1 testDto1 = new TestDto1();
testDto1.setId(UUID.randomUUID());
testDto1.setTestDto2(testDto2);
return ResponseEntity.ok(new GenericResponse<>(true, "response got", testDto1));
}
</code>
@GetMapping("/res1")
private ResponseEntity<GenericResponse<TestDto1>> responseTest1(@RequestParam Integer num) {
TestDto2 testDto2 = new TestDto2();
List<UUID> uuidList = new ArrayList<>();
switch (num) {
case 1: {
uuidList.add(UUID.randomUUID());
uuidList.add(UUID.randomUUID());
break;
}
case 2: {
OrderRequestEntity entity = orderRequestRepository.findById(UUID.fromString("158790c2-ce63-4d00-b053-33f5a72782e7")).orElse(null);
uuidList = entity.getItems();
}
}
testDto2.setId(UUID.randomUUID());
testDto2.setUuidList2(uuidList);
TestDto1 testDto1 = new TestDto1();
testDto1.setId(UUID.randomUUID());
testDto1.setTestDto2(testDto2);
return ResponseEntity.ok(new GenericResponse<>(true, "response got", testDto1));
}
TestDto1
private TestDto2 testDto2;;
<code>
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestDto1 {
private UUID id;
private TestDto2 testDto2;;
}
</code>
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestDto1 {
private UUID id;
private TestDto2 testDto2;;
}
TestDto2
private List<UUID> uuidList2;
<code>@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestDto2 {
private UUID id;
private List<UUID> uuidList2;
private Point point1;
private Point point2;
}
</code>
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestDto2 {
private UUID id;
private List<UUID> uuidList2;
private Point point1;
private Point point2;
}
GenericResponse
public class GenericResponse<T> {
@JsonInclude(JsonInclude.Include.NON_NULL)
private String correlationId = MDC.get("correlationId");
public GenericResponse(boolean success, String message, T data) {
public GenericResponse(T data) {
<code>@Data
@NoArgsConstructor
@AllArgsConstructor
public class GenericResponse<T> {
private boolean success;
@JsonInclude(JsonInclude.Include.NON_NULL)
private String message;
private String correlationId = MDC.get("correlationId");
private T data;
public GenericResponse(boolean success, String message, T data) {
this.success = success;
this.message = message;
this.data = data;
}
public GenericResponse(T data) {
this.success = true;
this.data = data;
}
}
</code>
@Data
@NoArgsConstructor
@AllArgsConstructor
public class GenericResponse<T> {
private boolean success;
@JsonInclude(JsonInclude.Include.NON_NULL)
private String message;
private String correlationId = MDC.get("correlationId");
private T data;
public GenericResponse(boolean success, String message, T data) {
this.success = success;
this.message = message;
this.data = data;
}
public GenericResponse(T data) {
this.success = true;
this.data = data;
}
}
OrderRequestEntity (Here the field which I’m interested in is “items”, for which I’ve written converter to convert it to JSON when we’re storing it in DB and back to List when we’re trying to get items from the entity).
@Table(name = "order_request")
public class OrderRequestEntity {
@Column(name = "restaurant_location", columnDefinition = "Geometry(Point, 4326)")
private Point restaurantLocation;
@Column(name = "delivery_location", columnDefinition = "Geometry(Point, 4326)")
private Point deliveryLocation;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customer_id")
private CustomerEntity customerEntity;
@Column(name = "customer_id", updatable = false, insertable = false)
@Column(name = "restaurant_id")
private UUID restaurantId;
@Convert(converter = UUIDListConvertor.class)
private List<UUID> items;
@Enumerated(EnumType.STRING)
@Column(name = "payment_type")
private PaymentType paymentType;
@Enumerated(EnumType.STRING)
@Column(name = "order_request_status")
private OrderRequestStatusType orderRequestStatusType;
@Column(name = "created_on")
private Instant createdOn;
@Column(name = "updated_on")
private Instant updatedOn;
protected void onCreate() {
this.createdOn = this.updatedOn = Instant.now();
protected void onUpdate() {
this.updatedOn = Instant.now();
<code>@Data
@Entity
@Table(name = "order_request")
public class OrderRequestEntity {
@Id
@GeneratedValue
@Column(name = "id")
private UUID id;
@Column(name = "restaurant_location", columnDefinition = "Geometry(Point, 4326)")
private Point restaurantLocation;
@Column(name = "delivery_location", columnDefinition = "Geometry(Point, 4326)")
private Point deliveryLocation;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customer_id")
private CustomerEntity customerEntity;
@Column(name = "customer_id", updatable = false, insertable = false)
private UUID customerId;
@Column(name = "restaurant_id")
private UUID restaurantId;
@Convert(converter = UUIDListConvertor.class)
@Column(name = "items")
private List<UUID> items;
@Enumerated(EnumType.STRING)
@Column(name = "payment_type")
private PaymentType paymentType;
@Enumerated(EnumType.STRING)
@Column(name = "order_request_status")
private OrderRequestStatusType orderRequestStatusType;
@Column(name = "created_on")
private Instant createdOn;
@Column(name = "updated_on")
private Instant updatedOn;
@PrePersist
protected void onCreate() {
this.createdOn = this.updatedOn = Instant.now();
}
@PreUpdate
protected void onUpdate() {
this.updatedOn = Instant.now();
}
}
</code>
@Data
@Entity
@Table(name = "order_request")
public class OrderRequestEntity {
@Id
@GeneratedValue
@Column(name = "id")
private UUID id;
@Column(name = "restaurant_location", columnDefinition = "Geometry(Point, 4326)")
private Point restaurantLocation;
@Column(name = "delivery_location", columnDefinition = "Geometry(Point, 4326)")
private Point deliveryLocation;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "customer_id")
private CustomerEntity customerEntity;
@Column(name = "customer_id", updatable = false, insertable = false)
private UUID customerId;
@Column(name = "restaurant_id")
private UUID restaurantId;
@Convert(converter = UUIDListConvertor.class)
@Column(name = "items")
private List<UUID> items;
@Enumerated(EnumType.STRING)
@Column(name = "payment_type")
private PaymentType paymentType;
@Enumerated(EnumType.STRING)
@Column(name = "order_request_status")
private OrderRequestStatusType orderRequestStatusType;
@Column(name = "created_on")
private Instant createdOn;
@Column(name = "updated_on")
private Instant updatedOn;
@PrePersist
protected void onCreate() {
this.createdOn = this.updatedOn = Instant.now();
}
@PreUpdate
protected void onUpdate() {
this.updatedOn = Instant.now();
}
}
UUIDListConvertor
public class UUIDListConvertor extends JsonConverter<List<UUID>> {
<code>@Converter
public class UUIDListConvertor extends JsonConverter<List<UUID>> {
}
</code>
@Converter
public class UUIDListConvertor extends JsonConverter<List<UUID>> {
}
JsonConverter
public class JsonConverter<T> implements AttributeConverter<T, String> {
private final TypeReference<T> typeReference = new TypeReference<T>() {};
private final ObjectMapper objectMapper = new ObjectMapper();
public String convertToDatabaseColumn(T object) {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Failed to serialize JSON data", e);
public T convertToEntityAttribute(String json) {
return objectMapper.readValue(json, typeReference);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Failed to deserialize JSON data", e);
<code>@Converter
public class JsonConverter<T> implements AttributeConverter<T, String> {
private final TypeReference<T> typeReference = new TypeReference<T>() {};
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public String convertToDatabaseColumn(T object) {
try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Failed to serialize JSON data", e);
}
}
@Override
public T convertToEntityAttribute(String json) {
try {
return objectMapper.readValue(json, typeReference);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Failed to deserialize JSON data", e);
}
}
}
</code>
@Converter
public class JsonConverter<T> implements AttributeConverter<T, String> {
private final TypeReference<T> typeReference = new TypeReference<T>() {};
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public String convertToDatabaseColumn(T object) {
try {
return objectMapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Failed to serialize JSON data", e);
}
}
@Override
public T convertToEntityAttribute(String json) {
try {
return objectMapper.readValue(json, typeReference);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Failed to deserialize JSON data", e);
}
}
}
pom.xml
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-postgresql</artifactId>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-spatial</artifactId>
<version>6.5.2.Final</version>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.15.0</version>
<code>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-spatial</artifactId>
<version>6.5.2.Final</version>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>8.0</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.15.0</version>
</dependency>
</code>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-core</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-database-postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-spatial</artifactId>
<version>6.5.2.Final</version>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>8.0</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.15.0</version>
</dependency>
Expected outcome is that List is properly set in TestDto2 and we get it in response as well. But when I set it from OrderRequestEntity, I get an error shared above. This error does not show up when we manually add uuids to the list. I suspect it is due to convertor which is associated with items field in OrderRequestEntity.
To check if that is the issue I used debugger and I observed that values are successfully getting set in the List uuidList2 of TestDto2 but at the time when program reaches the end to give response, error occurs.