Spring HAL 消费者返回空资源
Spring HAL consumer returning empty Resource
我想递归地使用 HAL 格式的端点。示例端点响应如下所示:
{
"_embedded" : {
"machineStateClassAnswers" : [ {
"name" : 1,
"extendedTimeSegmentAnswer" : {
"duration" : 24,
"goodParts" : 87,
"rejectedParts" : 16,
"relativeDurationInPercentage" : 17,
"count" : 7,
"averageDuration" : 3.5714
},
"_links" : {
"self" : {
"href" : "http://localhost:1890/equipment/class_1?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
},
"class" : {
"href" : "http://localhost:1890/equipment/class_1?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
}
}
}, {
"name" : 2,
"extendedTimeSegmentAnswer" : {
"duration" : 34,
"goodParts" : 54,
"rejectedParts" : 11,
"relativeDurationInPercentage" : 24,
"count" : 5,
"averageDuration" : 7.8
},
"_links" : {
"self" : {
"href" : "http://localhost:1890/equipment/class_2?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
},
"class" : {
"href" : "http://localhost:1890/equipment/class_2?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
}
}
}, {
"name" : 3,
"extendedTimeSegmentAnswer" : {
"duration" : 86,
"goodParts" : 76,
"rejectedParts" : 15,
"relativeDurationInPercentage" : 60,
"count" : 7,
"averageDuration" : 21.5714
},
"_links" : {
"self" : {
"href" : "http://localhost:1890/equipment/class_3?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
},
"class" : {
"href" : "http://localhost:1890/equipment/class_3?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://localhost:1890/equipment/classes?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
}
}
}
我尝试使用 restTemplate class 和来自 Spring HATEOAS 的 Jackson2HalModule 使用此端点,例如:
@Service
public class TableResponseService {
@Value("${url}")
String url;
private final RestTemplate restTemplate;
public TableResponseService(RestTemplateBuilder restTemplateBuilder) {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.registerModule(new Jackson2HalModule());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
converter.setObjectMapper(mapper);
this.restTemplate = restTemplateBuilder.additionalMessageConverters(Arrays.asList(converter)).build();
}
public Resources<List<MachineStateClassAnswer>> getMachineStates() {
return restTemplate.exchange(url,
HttpMethod.GET,
null,
new ParameterizedTypeReference<Resources<List<MachineStateClassAnswer>>>() {
}
).getBody();
}
}
数据class是:
public class MachineStateClassAnswer extends ResourceSupport {
private Long name;
public ExtendedTimeSegmentAnswer extendedTimeSegmentAnswer;
public MachineStateClassAnswer(Long name, ExtendedTimeSegmentAnswer extendedTimeSegmentAnswer) {
this.name = name;
this.extendedTimeSegmentAnswer = extendedTimeSegmentAnswer;
}
public Long getName() {
return name;
}
public ExtendedTimeSegmentAnswer getExtendedTimeSegmentAnswer() {
return extendedTimeSegmentAnswer;
}
public void setName(Long name) {
this.name = name;
}
public void setExtendedTimeSegmentAnswer(ExtendedTimeSegmentAnswer extendedTimeSegmentAnswer) {
this.extendedTimeSegmentAnswer = extendedTimeSegmentAnswer;
}
}
和
public class ExtendedTimeSegmentAnswer extends BasicTimeSegmentAnswer {
protected Long relativeDurationInPercentage;
protected Long count;
protected Double averageDuration;
public ExtendedTimeSegmentAnswer() {
}
public ExtendedTimeSegmentAnswer(Long duration, Long goodParts, Long rejectedParts, Long count, Double averageDuration) {
super(duration, goodParts, rejectedParts);
this.count = count;
this.averageDuration = averageDuration;
}
public Long getRelativeDurationInPercentage() {
return relativeDurationInPercentage;
}
public Long getDuration() {
return duration;
}
public Long getCount() {
return count;
}
public void setCount(Long count) {
this.count = count;
}
public Double getAverageDuration() {
return averageDuration;
}
public void setAverageDuration(Double averageDuration) {
this.averageDuration = averageDuration;
}
}
并且:
public class BasicTimeSegmentAnswer {
protected Long duration;
protected Long goodParts;
protected Long rejectedParts;
public BasicTimeSegmentAnswer() {
}
public BasicTimeSegmentAnswer(Long duration, Long goodParts, Long rejectedParts) {
this.duration = duration;
this.goodParts = goodParts;
this.rejectedParts = rejectedParts;
}
public Long getDuration() {
return duration;
}
public void setDuration(Long duration) {
this.duration = duration;
}
public Long getGoodParts() {
return goodParts;
}
public void setGoodParts(Long goodParts) {
this.goodParts = goodParts;
}
public Long getRejectedParts() {
return rejectedParts;
}
public void setRejectedParts(Long rejectedParts) {
this.rejectedParts = rejectedParts;
}
}
我的测试:
@Test
public void testConnection(){
System.out.println(tableResponseService.getMachineStates());
}
但是returns:
Resources { content: [], links: [] }
无论我试图改变什么,我就是无法让它工作。
对于任何有类似问题的人,这里是解决方案:
修复消息转换器
this.restTemplate = restTemplateBuilder.messageConverters(converter).build();
( ... 因为 *+json
存在默认转换器)
向 MachineStateClassAnswer 添加默认构造函数 public MachineStateClassAnswer() {}
我想递归地使用 HAL 格式的端点。示例端点响应如下所示:
{
"_embedded" : {
"machineStateClassAnswers" : [ {
"name" : 1,
"extendedTimeSegmentAnswer" : {
"duration" : 24,
"goodParts" : 87,
"rejectedParts" : 16,
"relativeDurationInPercentage" : 17,
"count" : 7,
"averageDuration" : 3.5714
},
"_links" : {
"self" : {
"href" : "http://localhost:1890/equipment/class_1?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
},
"class" : {
"href" : "http://localhost:1890/equipment/class_1?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
}
}
}, {
"name" : 2,
"extendedTimeSegmentAnswer" : {
"duration" : 34,
"goodParts" : 54,
"rejectedParts" : 11,
"relativeDurationInPercentage" : 24,
"count" : 5,
"averageDuration" : 7.8
},
"_links" : {
"self" : {
"href" : "http://localhost:1890/equipment/class_2?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
},
"class" : {
"href" : "http://localhost:1890/equipment/class_2?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
}
}
}, {
"name" : 3,
"extendedTimeSegmentAnswer" : {
"duration" : 86,
"goodParts" : 76,
"rejectedParts" : 15,
"relativeDurationInPercentage" : 60,
"count" : 7,
"averageDuration" : 21.5714
},
"_links" : {
"self" : {
"href" : "http://localhost:1890/equipment/class_3?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
},
"class" : {
"href" : "http://localhost:1890/equipment/class_3?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://localhost:1890/equipment/classes?start=3&end=75&sap_keys=7000_3333&sap_keys=7000_4444"
}
}
}
我尝试使用 restTemplate class 和来自 Spring HATEOAS 的 Jackson2HalModule 使用此端点,例如:
@Service
public class TableResponseService {
@Value("${url}")
String url;
private final RestTemplate restTemplate;
public TableResponseService(RestTemplateBuilder restTemplateBuilder) {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.registerModule(new Jackson2HalModule());
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
converter.setObjectMapper(mapper);
this.restTemplate = restTemplateBuilder.additionalMessageConverters(Arrays.asList(converter)).build();
}
public Resources<List<MachineStateClassAnswer>> getMachineStates() {
return restTemplate.exchange(url,
HttpMethod.GET,
null,
new ParameterizedTypeReference<Resources<List<MachineStateClassAnswer>>>() {
}
).getBody();
}
}
数据class是:
public class MachineStateClassAnswer extends ResourceSupport {
private Long name;
public ExtendedTimeSegmentAnswer extendedTimeSegmentAnswer;
public MachineStateClassAnswer(Long name, ExtendedTimeSegmentAnswer extendedTimeSegmentAnswer) {
this.name = name;
this.extendedTimeSegmentAnswer = extendedTimeSegmentAnswer;
}
public Long getName() {
return name;
}
public ExtendedTimeSegmentAnswer getExtendedTimeSegmentAnswer() {
return extendedTimeSegmentAnswer;
}
public void setName(Long name) {
this.name = name;
}
public void setExtendedTimeSegmentAnswer(ExtendedTimeSegmentAnswer extendedTimeSegmentAnswer) {
this.extendedTimeSegmentAnswer = extendedTimeSegmentAnswer;
}
}
和
public class ExtendedTimeSegmentAnswer extends BasicTimeSegmentAnswer {
protected Long relativeDurationInPercentage;
protected Long count;
protected Double averageDuration;
public ExtendedTimeSegmentAnswer() {
}
public ExtendedTimeSegmentAnswer(Long duration, Long goodParts, Long rejectedParts, Long count, Double averageDuration) {
super(duration, goodParts, rejectedParts);
this.count = count;
this.averageDuration = averageDuration;
}
public Long getRelativeDurationInPercentage() {
return relativeDurationInPercentage;
}
public Long getDuration() {
return duration;
}
public Long getCount() {
return count;
}
public void setCount(Long count) {
this.count = count;
}
public Double getAverageDuration() {
return averageDuration;
}
public void setAverageDuration(Double averageDuration) {
this.averageDuration = averageDuration;
}
}
并且:
public class BasicTimeSegmentAnswer {
protected Long duration;
protected Long goodParts;
protected Long rejectedParts;
public BasicTimeSegmentAnswer() {
}
public BasicTimeSegmentAnswer(Long duration, Long goodParts, Long rejectedParts) {
this.duration = duration;
this.goodParts = goodParts;
this.rejectedParts = rejectedParts;
}
public Long getDuration() {
return duration;
}
public void setDuration(Long duration) {
this.duration = duration;
}
public Long getGoodParts() {
return goodParts;
}
public void setGoodParts(Long goodParts) {
this.goodParts = goodParts;
}
public Long getRejectedParts() {
return rejectedParts;
}
public void setRejectedParts(Long rejectedParts) {
this.rejectedParts = rejectedParts;
}
}
我的测试:
@Test
public void testConnection(){
System.out.println(tableResponseService.getMachineStates());
}
但是returns:
Resources { content: [], links: [] }
无论我试图改变什么,我就是无法让它工作。
对于任何有类似问题的人,这里是解决方案:
修复消息转换器
this.restTemplate = restTemplateBuilder.messageConverters(converter).build();
( ... 因为*+json
存在默认转换器)向 MachineStateClassAnswer 添加默认构造函数
public MachineStateClassAnswer() {}