background
Recently participated in a key project, in the early stage because of other process reasons, the test time has been delayed for several days, I thought that the stuck point has been solved, and the follow-up process should be smooth and smooth, but I didn't expect people to be on the subway, and the bug came from Dong Dong~
Without any modification to the service interface, an exception is thrown:
java.lang.ClassCastException: java.util.HashMap cannot be cast to cn.xxx.xxx.xxx.xxx.BatchInfo
Troubleshooting process
1. As a veteran driver who writes bugs, the first feeling is that there is a problem with the format of the message that is transmitted, and it can be troubled by simulating the message. So, in the group, I circled the service provider student B to take a look, BG quickly used the test tool + local debug to verify the format of the following message, and found that it was successfully called. . .
2. Synchronous service calls student L, focusing on: 1) the serialization mode of the caller; 2) Whether there is a problem with the logic of the recent code changes. After student L confirms that there is no problem with his logic, he synchronizes student B and student S to see if there is any internal processing logic...
3. When I came the next morning, I quickly wrote a single test to confirm that there was no problem with the format of the packet received by the server. So, I started picking up the code... Spot suspicious code:
BeanUtils.copyProperties(item,cargoInfo)
private List<CargoInfo> convertToCargoInfo(OutboundEventCallbackRequest outboundEventCallbackRequest) {
return outboundEventCallbackRequest.getCargos().stream().map(item -> {
CargoInfo cargoInfo = new CargoInfo();
BeanUtils.copyProperties(item, cargoInfo);
return cargoInfo;
}).collect(Collectors.toList());
}
PS: Client-server class relationship
This is because BeanUtils.copyProperties is a shallow copy, and a shallow copy just calls the set method of the child object, and does not copy all the properties (a memory address referenced). So when making a call, JSF will convert it to a Map because it can't find the corresponding class when deserializing.
The visual diagram is as follows:
Above, the preliminary location of the cause, the solution is clear.
solution
Remove BeanUtils.copyProperties and manually assign a value. This problem was finally solved.
Follow-up reflection
1. Thinking of Mr. Wang Dongyue's words, the more primitive the more stable~
2. If there are many such transformations, it is recommended to use MapStruct
3、谨慎使用BeanUtils.copyProperties,请看: