我已经使用RESTful OGM为野生苍蝇构建了一个Neo4j web服务,但是当我访问它时,我会得到一个NullPointerException。似乎应该使用我的模型类填充的Map在被访问时还没有初始化。为什么会发生这种情况?
首先,我不得不说,这个模块salessupport-ui目前是使用javafx作为胖客户端实现的,它可以很好地连接到neo4j社区版本2.2.4,读写没有问题。我现在想要做的--这是我面临的问题--我想使用通配符作为一个服务器,它本身连接到neo4j,因此javafx应用程序只向通配符服务器发送请求。我决定使用的协议是REST,已经在通配符上提供的实现是resteasy。
下面是1)异常和一些调试信息,2)关于我的上下文、项目结构和我的类的代码的详细信息。
1.问题
下面是调试时的异常和我的发现。
异常
现在,当我通过在浏览器中输入http://localhost:8080/salessupport-restsvc/rest/address/list来调用此REST服务时,会引发以下异常:
00:07:38,458 ERROR [io.undertow.request] (default task-5) UT005023: Exception handling request to /salessupport-restsvc/rest/address/list: org.jboss.resteasy.spi.UnhandledException: java.lang.NullPointerException
at org.jboss.resteasy.core.ExceptionHandler.handleApplicationException(ExceptionHandler.java:76)
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:212)
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:149)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:372)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:86)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:72)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:282)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:261)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:80)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:172)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:199)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:774)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
at org.neo4j.ogm.metadata.MetaData.entityType(MetaData.java:231)
at org.neo4j.ogm.session.Neo4jSession.entityType(Neo4jSession.java:451)
at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:55)
at org.neo4j.ogm.session.delegates.LoadByTypeDelegate.loadAll(LoadByTypeDelegate.java:94)
at org.neo4j.ogm.session.Neo4jSession.loadAll(Neo4jSession.java:114)
at groupid.salessupport.db.core.ApplicationContext$GraphRepositoryImpl.findAll(ApplicationContext.java:74)
at groupid.salessupport.restsvc.impl.SimpleRestGraphRepositoryImpl.findAll(SimpleRestGraphRepositoryImpl.java:29)
at groupid.salessupport.restsvc.impl.AddressRestImpl$Proxy$_$$_WeldClientProxy.findAll(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:137)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:296)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:250)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:237)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:356)
... 32 more调试信息
SimpleRestGraphRepositoryImpl中的第一个断点,即调用repository.findAll();的方法findAll()。GraphRepositoryImpl类,以方法findAll(...)和行context.getSession().loadAll(clazz);创建Session。_classInfo(String,String,String)中的_classInfo(String,String,String)类中尝试调用domainInfo.getClassInfosWithAnnotation(nodeEntityAnnotation); where nodeEntityAnnotation="org.neo4j.ogm.annotation.NodeEntity"。DomainInfo类方法getClassInfosWithAnnotation中,映射annotationNameToClassInfo为空。我希望它充满我的模型,这显然发生在javafx环境中,而不是在JavaEE env中。这是那种方法
public List<ClassInfo> getClassInfosWithAnnotation(String annotation) {
return annotationNameToClassInfo.get(annotation);
}为了进行检查,如果REST机制正常工作,我会在AddressRestImpl>旁边放置一个类
@Path("dummy")
public class DummyImpl {
@GET
@Path("list")
@Produces(MediaType.APPLICATION_JSON)
public List<Amount> getAll() {
return Arrays.asList(new Amount());
}
}通过导航到http://localhost:8080/salessupport-restsvc/rest/dummy/list在浏览器中调用它,结果是预期的:{“金额”:null,“货币”:null}
这里我有很多简单的东西需要改进,我已经尝试了很多方法,在Tomcat 8上也会发生同样的异常,但是在那里其他的方法甚至在虚拟的情况下也不起作用,所以我转向了野蝇。我是否在这里发现了一个bug,还是在我的设置中有一些简单的遗漏?
2)工程及守则详情
下面是有关我的环境、项目结构和当我遇到这个问题时运行的代码的信息。
环境
我的环境如下:
我有Neo4J社区版2.2.4。
我下载了通配符-9.0.1.Final,除了一个与我的NVidia驱动程序软件冲突的管理端口之外,我把所有东西都保留了下来。
项目结构
我有一个maven多模块应用程序,它由以下模块组成:
<modules>
<module>salessupport-ui</module>
<module>salessupport-intf</module>
<module>salessupport-db</module>
<module>salessupport-restsvc</module>
</modules>这些依赖关系如下:
salessupport-intf <-- salessupport-db
^
|-- salessupport-ui
|-- salessupport-restsvc依赖关系
让我解释一下依赖关系:
salessupport父母有一个如下所示的依赖管理定义:
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm</artifactId>
<version>1.1.2</version>
<exclusions>
<exclusion>
<groupId>org.neo4j.app</groupId>
<artifactId>neo4j-server</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>salessupport-intf使用以下依赖项:
<dependencies>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm</artifactId>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
</dependencies>salessupport-restsvc pom.xml是
<?xml version="1.0"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>groupid</groupId>
<artifactId>salessupport</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>salessupport-restsvc</artifactId>
<name>salessupport-restsvc</name>
<url>http://maven.apache.org</url>
<properties>
<jersey.version>1.19</jersey.version>
<resteasy.version>3.0.11.Final</resteasy.version>
</properties>
<dependencies>
<dependency>
<groupId>groupid</groupId>
<artifactId>salessupport-intf</artifactId>
</dependency>
<dependency>
<groupId>groupid</groupId>
<artifactId>salessupport-db</artifactId>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>${resteasy.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<version>${resteasy.version}</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<version>${resteasy.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
</dependencies>
<packaging>war</packaging>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>${version.war.plugin}</version>
<configuration>
<!-- webXml>src\main\webapp\WEB-INF\web.xml</webXml -->
<failOnMissingWebXml>false</failOnMissingWebXml>
<packagingExcludes>
org.neo4j.server.rest.discovery,
org.neo4j.server.rest.web
</packagingExcludes>
</configuration>
</plugin>
</plugins>
</build>
</project>代码
这是相关的课程。
GraphRepository接口
我定义了我的自定义GraphRepository接口:
public interface GraphRepository<S> {
Iterable<S> findAll(Iterable<Long> nodeIds);
Iterable<S> findAll();
void delete(S arg0);
S save(S arg0);
}模型类
有一些模型类,例如:
package groupid.salessupport.db.model;
import java.text.DecimalFormat;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.NodeEntity;
@NodeEntity(label="Amount")
public class Amount {
@GraphId Long id;
private Double amount;
private Currency currency;
public Currency getCurrency() {
return currency;
}
public void setCurrency(Currency currency) {
this.currency = currency;
}
public Double getAmount() {
return amount;
}
public void setAmount(Double amount) {
this.amount = amount;
}
@Override
public String toString() {
return new DecimalFormat().format(amount)+" "+currency;
}
}和
@NodeEntity(label="Currency")
public class Currency extends BaseObject {
@Override
public String toString() {
return getName();
}
}通用简单Rest图形库接口
public interface ISimpleRestGraphRepository<T> {
@DELETE
@Path("delete")
@Consumes(MediaType.APPLICATION_JSON)
public void delete(T arg0);
@PUT
@Path("save")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public T save(T arg0);
@GET
@Path("list")
@Produces(MediaType.APPLICATION_JSON)
public Iterable<T> findAll();
@POST
@Path("listbyids")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Iterable<T> findAll(Iterable<Long> arg0);
}REST接口金额定义
@Path("amount")
public interface AmountRest extends ISimpleRestGraphRepository<Amount> {
}REST活化剂
@ApplicationPath("/rest")
public class JaxRsActivator extends Application {
}REST服务的通用实现
@RequestScoped
public class SimpleRestGraphRepositoryImpl<T> implements ISimpleRestGraphRepository<T> {
private final GraphRepository<T> repository;
public SimpleRestGraphRepositoryImpl(GraphRepository<T> repository) {
this.repository = repository;
}
@Override
public void delete(T arg0) {
repository.delete(arg0);
}
@Override
public T save(T arg0) {
return repository.save(arg0);
}
@Override
public Iterable<T> findAll() {
return repository.findAll();
}
@Override
public Iterable<T> findAll(Iterable<Long> arg0) {
return repository.findAll(arg0);
}
}..。以及具体的解决办法:
public class AmountRestImpl extends SimpleRestGraphRepositoryImpl<Amount> implements AmountRest {
public AmountRestImpl() {
super(NeoRepositories.getInstance().getAmountRepository());
}
}DB连接
在salessupport中,我们用一些代码连接到数据库:
public class ApplicationContext {
private SessionFactory sessionFactory;
private Session openSession;
public ApplicationContext() {
}
public SessionFactory getSessionFactory() {
if (sessionFactory == null) {
sessionFactory = new SessionFactory("groupid.salessupport.db.model");
}
return sessionFactory;
}
public Session getSession() {
if (openSession == null) {
openSession = getSessionFactory().openSession("http://localhost:7474",
"username", "password"); // it is not really like this
}
return openSession;
}
public <S,G extends GraphRepository<S>> GraphRepository<S> getGraphRepository(Class<S> clazz) {
return new GraphRepositoryImpl<S>(this, clazz);
}
public static class GraphRepositoryImpl<S> implements GraphRepository<S> {
private ApplicationContext context;
private Class<S> clazz;
public GraphRepositoryImpl(ApplicationContext context, Class<S> clazz) {
this.context = context;
this.clazz = clazz;
}
@Override
public Iterable<S> findAll(Iterable<Long> nodeIds) {
List<Long> listNodeIds;
if (nodeIds instanceof List) {
listNodeIds = (List<Long>) nodeIds;
} else {
listNodeIds = new LinkedList<>();
for (Long l : nodeIds) {
listNodeIds.add(l);
}
}
return context.getSession().loadAll(clazz,listNodeIds);
}
@Override
public Iterable<S> findAll() {
return context.getSession().loadAll(clazz);
}
@Override
public void delete(S arg0) {
Session session = context.getSession();
Transaction transaction = session.beginTransaction();
context.getSession().delete(arg0);
transaction.commit();
transaction.close();
}
@Override
public S save(S arg0) {
Session session = context.getSession();
Transaction transaction = session.beginTransaction();
session.save(arg0);
transaction.commit();
transaction.close();
return arg0;
}
}
}用法
实现者使用“单例”快速而脏地获取此GraphRepository的实例:
public class NeoRepositories {
private ApplicationContext context;
private static final NeoRepositories INSTANCE = new NeoRepositories();
private NeoRepositories() {
context = new ApplicationContext();
}
public GraphRepository<Person> getPersonRepository() {
return context.getGraphRepository(Person.class);
}
public static NeoRepositories getInstance() {
return INSTANCE;
}
public GraphRepository<Amount> getAmountRepository() {
return context.getGraphRepository(Amount.class);
}
...
}这是我关于堆叠溢出的第一个问题,我希望我写的越少越好,越多越好.
发布于 2017-03-26 19:59:15
在https://github.com/neo4j/neo4j-ogm/issues/48中有一个更新,它已经用新的neo4j版本>2实现了。
我在https://github.com/mkirchmann/hello-neo4j-ogm上提供了整个源代码,不能保证所有的东西都正常工作或者一切都是正确的,至少列出一种类型的所有节点都是可能的。不要忘记正确设置ogm.properties 。
该解决方案的关键是用于新4j-ogm的vfs驱动程序,可在https://github.com/mkirchmann/neo4j-ogm-resourceresolver-vfs中找到(它已从ctpconsulting中分叉,使用版本2.1.1和mvn安装,以便在本地maven存储库中可用)
pom.xml
下面的pom.xml正在设置必要的(可能更多,不确定),以便能够成功地进行Rest调用。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>de.neuenberger</groupId>
<artifactId>hello-neo4j-ogm</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>HelloNeo4jOgmOnWildFly</name>
<description>Very Simple configuration to use neo4j ogm on WildFly application server</description>
<packaging>war</packaging>
<properties>
<neo4jogmversion>2.1.1</neo4jogmversion>
<resteasy.version>3.1.1.Final</resteasy.version>
<version.war.plugin>3.0.0</version.war.plugin>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>${resteasy.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-multipart-provider</artifactId>
<version>${resteasy.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.ctp.neo4j</groupId>
<artifactId>neo4j-ogm-resourceresolver-vfs</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>javax.el</groupId>
<artifactId>javax.el-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-core</artifactId>
<version>${neo4jogmversion}</version>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-ogm-http-driver</artifactId>
<version>${neo4jogmversion}</version>
</dependency>
<dependency>
<groupId>javax.enterprise</groupId>
<artifactId>cdi-api</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>${version.war.plugin}</version>
<configuration>
<!-- webXml>src\main\webapp\WEB-INF\web.xml</webXml -->
<failOnMissingWebXml>false</failOnMissingWebXml>
<packagingExcludes>
org.neo4j.server.rest.discovery,
org.neo4j.server.rest.web
</packagingExcludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release</url>
</repository>
<repository>
<id>neo4j</id>
<name>Neo4j</name>
<url>http://m2.neo4j.org/</url>
</repository>
</repositories>
</project>感谢大家的贡献和支持!
发布于 2015-09-10 07:48:26
这是@NodeEntity从弹簧数据Neo4j打来的吗?如果是,则必须正确设置Spring,这一点我在这里找不到。
https://stackoverflow.com/questions/32490795
复制相似问题