I'm having problems with my mapping configuration. Whenever I get an order by its ID, I'm having no problems whatsoever. However, once I attempt to get every single order using entityListToResponseModelList, every single ID, aggregate or not, returns null in postman. My mapping seems correct, yet I get a warning telling me that I have "umapped target properties". Here's the full warning:
#13 16.36 /usr/src/app/src/main/java/com/example/clothingstore/ordersubdomain/mapperlayer/OrderResponseMapper.java:63: warning: Unmapped target properties: "orderId, productId, customerId, employeeId". Mapping from Collection element "Order order" to "OrderResponseModel orderResponseModel".
#13 16.36 List<OrderResponseModel> entityListToResponseModelList(List<Order> orders);
^
My ResponseMapper:
package com.example.clothingstore.ordersubdomain.mapperlayer;
import com.example.clothingstore.customersubdomain.datalayer.Customer;
import com.example.clothingstore.employeesubdomain.datalayer.Employee;
import com.example.clothingstore.ordersubdomain.datalayer.Order;
import com.example.clothingstore.ordersubdomain.presentationlayer.OrderController;
import com.example.clothingstore.ordersubdomain.presentationlayer.OrderResponseModel;
import com.example.clothingstore.productsubdomain.datalayer.Product;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.springframework.hateoas.Link;
import java.util.List;
import java.util.stream.Collectors;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
@Mapper(componentModel = "spring")
public interface OrderResponseMapper {
@Mapping(expression = "java(order.getOrderIdentifier().getOrderId())", target = "orderId")
@Mapping(expression = "java(order.getProductIdentifier().getProductId())", target = "productId")
@Mapping(expression = "java(product.getName())", target = "name")
@Mapping(expression = "java(product.getPrice())", target = "price")
@Mapping(expression = "java(order.getCustomerIdentifier().getCustomerId())", target = "customerId")
@Mapping(expression = "java(customer.getBillingAddress().getStreetAddress())", target = "streetAddress")
@Mapping(expression = "java(customer.getBillingAddress().getPostalCode())", target = "postalCode")
@Mapping(expression = "java(customer.getBillingAddress().getCity())", target = "city")
@Mapping(expression = "java(customer.getBillingAddress().getProvince())", target = "province")
@Mapping(expression = "java(order.getEmployeeIdentifier().getEmployeeId())", target = "employeeId")
@Mapping(expression = "java(employee.getLastName())", target = "lastName")
@Mapping(expression = "java(order.getDeliveryStatus().name())", target = "deliveryStatus")
@Mapping(expression = "java(order.getShippingPrice())", target = "shippingPrice")
@Mapping(expression = "java(order.getTotalPrice())", target = "totalPrice")
OrderResponseModel entityToResponseModel(Order order, Product product, Customer customer, Employee employee);
@AfterMapping
default void addLinks(@MappingTarget OrderResponseModel model){
Link selfLink = linkTo(methodOn(OrderController.class)
.getOrderByOrderId(model.getOrderId()))
.withSelfRel();
model.add(selfLink);
Link ordersLink =
linkTo(methodOn(OrderController.class)
.getOrders())
.withRel("All orders");
model.add(ordersLink);
}
@Mapping(expression = "java(order.getOrderIdentifier().getOrderId())", target = "orderId")
@Mapping(expression = "java(order.getProductIdentifier().getProductId())", target = "productId")
@Mapping(expression = "java(order.getCustomerIdentifier().getCustomerId())", target = "customerId")
@Mapping(expression = "java(order.getEmployeeIdentifier().getEmployeeId())", target = "employeeId")
List<OrderResponseModel> entityListToResponseModelList(List<Order> orders);
}
And a few other classes that I feel like probably have nothing to do with my problem, but I'm including them for good measure.
OrderResponseModel
package com.example.clothingstore.ordersubdomain.presentationlayer;
import com.example.clothingstore.common.enums.DeliveryStatus;
import com.example.clothingstore.common.identifiers.CustomerIdentifier;
import com.example.clothingstore.common.identifiers.EmployeeIdentifier;
import com.example.clothingstore.common.identifiers.OrderIdentifier;
import com.example.clothingstore.common.identifiers.ProductIdentifier;
import lombok.*;
import org.springframework.hateoas.RepresentationModel;
import java.math.BigDecimal;
@EqualsAndHashCode(callSuper = true)
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class OrderResponseModel extends RepresentationModel<OrderResponseModel> {
String orderId;
String productId;
String name;
BigDecimal price;
String customerId;
String streetAddress;
String postalCode;
String city;
String province;
String employeeId;
String lastName;
String deliveryStatus;
BigDecimal shippingPrice;
BigDecimal totalPrice;
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getCustomerId() {
return customerId;
}
public void setCustomerId(String customerId) {
this.customerId = customerId;
}
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
}
Schema:
CREATE TABLE IF NOT EXISTS orders (
id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
order_id VARCHAR(36) UNIQUE,
product_id VARCHAR(36),
name VARCHAR(50),
price DECIMAL(10, 2),
customer_id VARCHAR(36),
street_address VARCHAR(50),
postal_code VARCHAR(50),
city VARCHAR(50),
province VARCHAR(50),
employee_id VARCHAR(36),
last_name VARCHAR(50),
delivery_status VARCHAR(50),
shipping_price DECIMAL(10, 2),
total_price DECIMAL(10, 2),
FOREIGN KEY (product_id) REFERENCES products(product_id),
FOREIGN KEY (customer_id) REFERENCES customers(customer_id),
FOREIGN KEY (employee_id) REFERENCES employees(employee_id),
INDEX idx_customer_id (customer_id),
INDEX idx_employee_id (employee_id),
INDEX idx_order_id (order_id)
);
getOrders function:
@Override
public List<OrderResponseModel> getOrders() {
List<Order> orders = orderRepository.findAll();
return orderResponseMapper.entityListToResponseModelList(orders);
}
And the postman response as well.
I've tried adding getters and setters myself, without the use of lombok. I've tried mapping my entityListToResponseModel. I played around with my Request Mapper to no avail.
Thanks in advance for the help! And apologies if this question doesn't meet standards, it's my first time posting on here.
Yeah, you just have to make a forEach (in your orderServiceImpl getAllOrders() function) to be able to use the entityListToResponseModel for all your entries individually instead of using your entityListToResponseModelList to be able to properly and completely map each order.