Я пытаюсь сопоставить две сущности с хранилищем данных Google и запросить их через Crnk.
Все работает нормально, за исключением случая отношения один к одному, когда целью отношения является нуль.
@JsonApiResource(type = "drivers")
@Entity
public class Driver {
@JsonApiId
@Id
private String id;
private String name;
private Ref<Car> car;
@JsonApiRelation
public Car getCar() {
return this.car != null ? car.get() : null;
}
@JsonApiRelation
public void setCar(Car car) {
this.car = car != null ? Ref.create(car) : null;
}
// other getters and setters
}
@JsonApiResource(type = "cars")
@Entity
public class Car {
@JsonApiId
@Id
private String id;
private String brand;
@JsonApiRelation
public Engine getEngine() {
return engine != null ? engine.get() : null;
}
public void setEngine(Engine engine) {
this.engine = Ref.create(engine);
}
// other getters and setters
}
Я помещаю JsonApiRelation в методы, так как Crnk завершается ошибкой при непосредственном размещении в поле, я полагаю, из-за разницы между типами поля и методов доступа.
Соответствующая часть репозиториев выглядит следующим образом:
public class ObjectifyBasedRepository<TClass>
extends ResourceRepositoryBase<TClass, String> {
private Class<TClass> resourceClass;
private Function<TClass, String> idGetter;
private BiConsumer<TClass, String> idSetter;
protected ObjectifyBasedRepository(
Class<TClass> resourceClass,
Function<TClass, String> idGetter,
BiConsumer<TClass, String> idSetter) {
super(resourceClass);
this.resourceClass = resourceClass;
this.idGetter = idGetter;
this.idSetter = idSetter;
}
@Override
// TODO: remove this method when the filters get implemented in findAll
// (super.findOne impl simply adds a filter on the id)
public TClass findOne(String id, QuerySpec queryspec) {
TClass resource = OfyService.ofy()
.load()
.type(resourceClass).id(id)
.now();
return resource;
}
@Override
public ResourceList<TClass> findAll(QuerySpec querySpec) {
List<TClass> resourceList = OfyService.ofy()
.load()
.type(resourceClass)
.list();
ResourceList<TClass> resources =
new DefaultResourceList<>(resourceList, null, null);
return resources;
}
@Override
public <S extends TClass> S save(S resource) {
OfyService.ofy()
.save()
.entity(resource)
.now();
return resource;
}
// + create and delete
}
При запросе водителя, который владеет автомобилем, все идет хорошо, я могу получить водителя, перейти к машине, используя ссылки, приведенные в ответе, и т. Д.
Но как только я пытаюсь получить драйвер, в котором driver.getCar()
возвращает null
, я получаю следующее исключение:
java.lang.NullPointerException
at io.crnk.core.engine.internal.utils.MultivaluedMap.getUnique(MultivaluedMap.java:46)
at io.crnk.core.engine.internal.utils.MultivaluedMap.getUnique(MultivaluedMap.java:41)
at io.crnk.core.repository.foward.ForwardingRelationshipRepository.findOneTarget(ForwardingRelationshipRepository.java:156)
at io.crnk.core.engine.internal.repository.RelationshipRepositoryAdapterImpl$5.invoke(RelationshipRepositoryAdapterImpl.java:183)
at io.crnk.core.engine.internal.repository.ResponseRepositoryAdapter$RepositoryRequestFilterChainImpl.doFilter(ResponseRepositoryAdapter.java:241)
at io.crnk.core.engine.internal.repository.RelationshipRepositoryAdapterImpl.findOneTarget(RelationshipRepositoryAdapterImpl.java:193)
at io.crnk.core.engine.internal.dispatcher.controller.RelationshipsResourceGet.handleAsync(RelationshipsResourceGet.java:50)
at io.crnk.core.engine.internal.dispatcher.controller.BaseController.handle(BaseController.java:48)
at io.crnk.core.engine.internal.http.DocumentFilterChainImpl.doFilter(DocumentFilterChainImpl.java:28)
at io.crnk.core.engine.internal.http.JsonApiRequestProcessor.processAsync(JsonApiRequestProcessor.java:159)
at io.crnk.core.engine.internal.http.JsonApiRequestProcessor.processAsync(JsonApiRequestProcessor.java:124)
at io.crnk.core.engine.internal.http.HttpRequestDispatcherImpl.process(HttpRequestDispatcherImpl.java:71)
at io.crnk.servlet.CrnkServlet.service(CrnkServlet.java:81)
at com.wizy.jsonapi.SampleCrnkServlet.service(SampleCrnkServlet.java:50)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:867)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1623)
at com.googlecode.objectify.ObjectifyFilter.doFilter(ObjectifyFilter.java:48)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:134)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:48)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
at com.google.appengine.tools.development.jetty9.StaticFileFilter.doFilter(StaticFileFilter.java:123)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366)
at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349)
at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1610)
at com.google.appengine.tools.development.DevAppServerRequestLogFilter.doFilter(DevAppServerRequestLogFilter.java:44)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1602)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:540)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:524)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1588)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1345)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1557)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1247)
at com.google.appengine.tools.development.jetty9.DevAppEngineWebAppContext.doScope(DevAppEngineWebAppContext.java:94)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at com.google.appengine.tools.development.jetty9.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:595)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:502)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:132)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
at java.lang.Thread.run(Thread.java:748)
Я что-то упустил?