我正在尝试将两个实体映射到google数据存储区,并通过Crnk查询它们。
一切正常,除了在关系目标为null的一对一关系的情况下。
@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放在字段上时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)
我想念什么吗?