When a published service returns a KeyValue entity, its serialization to JSON fails because the metadata is null.
We do not add metadata when returning entities from datastore, but add it in the UI when adding KVEntity to the container:
22:06:21.009 ERROR c.h.a.r.a.c.RestControllerExceptionHandler- Exception in REST controller
java.lang.IllegalStateException: metaClass is null
at com.haulmont.cuba.core.entity.KeyValueEntity.getMetaClass(KeyValueEntity.java:71) ~[cuba-global-7.2.4.jar:7.2.4]
at com.haulmont.cuba.core.app.serialization.EntitySerialization$EntitySerializer.serializeEntity(EntitySerialization.java:217) ~[cuba-global-7.2.4.jar:7.2.4]
at com.haulmont.cuba.core.app.serialization.EntitySerialization$EntitySerializer.serialize(EntitySerialization.java:212) ~[cuba-global-7.2.4.jar:7.2.4]
at com.haulmont.cuba.core.app.serialization.EntitySerialization$EntitySerializer.serialize(EntitySerialization.java:189) ~[cuba-global-7.2.4.jar:7.2.4]
at com.google.gson.internal.bind.TreeTypeAdapter.write(TreeTypeAdapter.java:81) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:208) ~[gson-2.8.6.jar:na]
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:145) ~[gson-2.8.6.jar:na]
at com.google.gson.Gson.toJson(Gson.java:704) ~[gson-2.8.6.jar:na]
at com.google.gson.Gson.toJson(Gson.java:683) ~[gson-2.8.6.jar:na]
at com.google.gson.Gson.toJson(Gson.java:638) ~[gson-2.8.6.jar:na]
at com.google.gson.Gson.toJson(Gson.java:618) ~[gson-2.8.6.jar:na]
at com.haulmont.cuba.core.app.serialization.EntitySerialization.objectToJson(EntitySerialization.java:115) ~[cuba-global-7.2.4.jar:7.2.4]
at com.haulmont.addon.restapi.api.common.RestParseUtils.serialize(RestParseUtils.java:126) ~[restapi-rest-api-7.2.0.jar:na]
at com.haulmont.addon.restapi.api.service.ServicesControllerManager._invokeServiceMethod(ServicesControllerManager.java:189) ~[restapi-rest-api-7.2.0.jar:na]
at com.haulmont.addon.restapi.api.service.ServicesControllerManager.invokeServiceMethodGet(ServicesControllerManager.java:83) ~[restapi-rest-api-7.2.0.jar:na]
at com.haulmont.addon.restapi.api.controllers.ServicesController.invokeServiceMethodGet(ServicesController.java:62) ~[restapi-rest-api-7.2.0.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_172]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_172]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_172]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_172]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) [spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) [spring-webmvc-5.2.3.RELEASE.jar:5.2.3.RELEASE]
KeyValueEntity can be obtained from different sources or created on-the-fly. So we cannot rely on presence of MetaClass in it. The only reliable solution is to serialize to JSON without using MetaClass at all.
Environment
Description of the bug or enhancement
When a published service returns a KeyValue entity, its serialization to JSON fails because the metadata is null. We do not add metadata when returning entities from datastore, but add it in the UI when adding KVEntity to the container:
During serialization we invoke
And got NPE.
See https://www.cuba-platform.com/discuss/t/exception-in-rest-controller/12424
Run the application add a Customer and then try to invoke a published service using http://localhost:8080/app/rest/v2/services/restapithouthgs_RestService/getBuyer URL
Expected behavior Entity should be returned
Actual behavior