I am using spring-data-rest to expose REST API. One of my search method returns list of entities. The repository and rest response as follows
List<Order> findByKeywordContaining(String keyword);
Search Response:
{
"_embedded":{
"orders":[
{
"keyword":"Iron mattress",
"name":"Hostel",
"_links":{
"self":{
"href":"http://localhost:8081/orders/2"
},
"order":{
"href":"http://localhost:8081/orders/2"
}
}
},
{
"keyword":"Iron",
"name":"Weat strong",
"_links":{
"self":{
"href":"http://localhost:8081/orders/40"
},
"order":{
"href":"http://localhost:8081/orders/40"
}
}
}
]
},
"_links":{
"self":{
"href":"http://localhost:8081/orders/search/findByKeywordContaining?keyword=iron"
}
}
}
Now I am using RestTemplate to consume this response to process in client side as follows
List<Order> orders = restOperations.exchange(new URI(url), HttpMethod.GET, null, new ParameterizedTypeReference<Resource<List<Order>>>() {}).getBody().getContent();
The above code works fine for a single object in response, but if the response contains multiple objects. The code throws the following error
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized field "_embedded" (class org.springframework.hateoas.Resource), not marked as ignorable (3 known properties: , "links", "content", "page"])
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@6a2bc870; line: 2, column: 18] (through reference chain: org.springframework.hateoas.Resource["_embedded"]); nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "_embedded" (class org.springframework.hateoas.Resource), not marked as ignorable (3 known properties: , "links", "content", "page"])
What I am missing here? How to consume the above response as a List?
Order.java
public class Order {
private int id;
private String name;
private String keyword;
private Agent agent;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public Agent getAgent() {
return agent;
}
public void setAgent(Agent agent) {
this.agent = agent;
}
Full Error Stack
21:39:30.746 [http-bio-8080-exec-36] DEBUG c.o.x.o.accessor.XWorkMethodAccessor - Error calling method through OGNL: object: [com.ams.order.actions.ViewOrderSearchAction@5218c8df] method: [viewOrderSearch] args: [[]]
org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized field "_embedded" (class org.springframework.hateoas.Resource), not marked as ignorable (2 known properties: , "links", "content"])
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@7583f177; line: 2, column: 18] (through reference chain: org.springframework.hateoas.Resource["_embedded"]); nested exception is com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "_embedded" (class org.springframework.hateoas.Resource), not marked as ignorable (2 known properties: , "links", "content"])
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@7583f177; line: 2, column: 18] (through reference chain: org.springframework.hateoas.Resource["_embedded"])
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(MappingJackson2HttpMessageConverter.java:181) ~[spring-web-3.2.17.RELEASE.jar:3.2.17.RELEASE]
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.read(MappingJackson2HttpMessageConverter.java:173) ~[spring-web-3.2.17.RELEASE.jar:3.2.17.RELEASE]
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:94) ~[spring-web-3.2.17.RELEASE.jar:3.2.17.RELEASE]
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:724) ~[spring-web-3.2.17.RELEASE.jar:3.2.17.RELEASE]
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:709) ~[spring-web-3.2.17.RELEASE.jar:3.2.17.RELEASE]
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:527) ~[spring-web-3.2.17.RELEASE.jar:3.2.17.RELEASE]
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:482) ~[spring-web-3.2.17.RELEASE.jar:3.2.17.RELEASE]
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:455) ~[spring-web-3.2.17.RELEASE.jar:3.2.17.RELEASE]
at com.ams.service.OrderSearcherImpl.searchForName(OrderSearcherImpl.java:49) ~[classes/:na]
at com.ams.order.actions.ViewOrderSearchAction.viewOrderSearch(ViewOrderSearchAction.java:61) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_101]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_101]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_101]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_101]
at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:891) [ognl-3.0.6.jar:na]
at ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1293) [ognl-3.0.6.jar:na]
at ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68) ~[ognl-3.0.6.jar:na]
at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:117) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:108) [xwork-core-2.3.20.jar:2.3.20]
at ognl.OgnlRuntime.callMethod(OgnlRuntime.java:1369) [ognl-3.0.6.jar:na]
at ognl.ASTMethod.getValueBody(ASTMethod.java:90) [ognl-3.0.6.jar:na]
at ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) [ognl-3.0.6.jar:na]
at ognl.SimpleNode.getValue(SimpleNode.java:258) [ognl-3.0.6.jar:na]
at ognl.Ognl.getValue(Ognl.java:494) [ognl-3.0.6.jar:na]
at ognl.Ognl.getValue(Ognl.java:458) [ognl-3.0.6.jar:na]
at com.opensymphony.xwork2.ognl.OgnlUtil$2.execute(OgnlUtil.java:309) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.ognl.OgnlUtil.compileAndExecute(OgnlUtil.java:340) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.ognl.OgnlUtil.getValue(OgnlUtil.java:307) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:423) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:287) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:250) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:167) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:265) [xwork-core-2.3.20.jar:2.3.20]
at org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:76) [struts2-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:138) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:191) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:253) [struts2-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:100) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:145) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:171) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:164) [struts2-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:229) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:73) [struts2-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:125) [struts2-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:91) [struts2-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:139) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:193) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:189) [xwork-core-2.3.20.jar:2.3.20]
at com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:244) [xwork-core-2.3.20.jar:2.3.20]
at org.apache.struts2.impl.StrutsActionProxy.execute(StrutsActionProxy.java:54) [struts2-core-2.3.20.jar:2.3.20]
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:564) [struts2-core-2.3.20.jar:2.3.20]
at org.apache.struts2.dispatcher.ng.ExecuteOperations.executeAction(ExecuteOperations.java:81) [struts2-core-2.3.20.jar:2.3.20]
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:99) [struts2-core-2.3.20.jar:2.3.20]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.67]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.67]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:186) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) [spring-security-web-3.2.4.RELEASE.jar:3.2.4.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343) [spring-web-3.2.17.RELEASE.jar:3.2.17.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260) [spring-web-3.2.17.RELEASE.jar:3.2.17.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.67]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.67]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241) [catalina.jar:7.0.67]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) [catalina.jar:7.0.67]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220) [catalina.jar:7.0.67]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122) [catalina.jar:7.0.67]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505) [catalina.jar:7.0.67]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169) [catalina.jar:7.0.67]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103) [catalina.jar:7.0.67]
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956) [catalina.jar:7.0.67]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116) [catalina.jar:7.0.67]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423) [catalina.jar:7.0.67]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079) [tomcat-coyote.jar:7.0.67]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625) [tomcat-coyote.jar:7.0.67]
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:318) [tomcat-coyote.jar:7.0.67]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_101]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_101]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-coyote.jar:7.0.67]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_101]
Caused by: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "_embedded" (class org.springframework.hateoas.Resource), not marked as ignorable (2 known properties: , "links", "content"])
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@7583f177; line: 2, column: 18] (through reference chain: org.springframework.hateoas.Resource["_embedded"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:79) ~[jackson-databind-2.2.2.jar:2.2.2]
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:555) ~[jackson-databind-2.2.2.jar:2.2.2]
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:708) ~[jackson-databind-2.2.2.jar:2.2.2]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1160) ~[jackson-databind-2.2.2.jar:2.2.2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:315) ~[jackson-databind-2.2.2.jar:2.2.2]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) ~[jackson-databind-2.2.2.jar:2.2.2]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888) ~[jackson-databind-2.2.2.jar:2.2.2]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2094) ~[jackson-databind-2.2.2.jar:2.2.2]
at org.springframework.http.converter.json.MappingJackson2HttpMessageConverter.readJavaType(MappingJackson2HttpMessageConverter.java:178) ~[spring-web-3.2.17.RELEASE.jar:3.2.17.RELEASE]
... 105 common frames omitted
Resource<>
). I don't think there's a predefined class that can be consumed. The reason is the individual collection property, in your case"orders"
. Your best shot is probably something likeResources<Map<String, List<Order>>>>
. Or you create your own class. – Swale