java - 在JEE(JBoss)环境中的neo4j:

标签 java rest maven neo4j neo4j-ogm

我已经使用Neo4j OGM为Wildfly构建了RESTful Web服务,但是当我访问它时,我得到一个NullPointerException
似乎应该在我的模型类中填充的Map在访问时尚未初始化。为什么会这样呢?

首先,我不得不说,该模块salessupport-ui当前使用javafx作为胖客户端实现,并且可以很好地连接到neo4j社区版本2.2.4,可以正常阅读,书写。
我现在想做的就是我面临的问题,我想使用wildfly作为本身连接到neo4j的服务器,因此javafx客户端应用程序仅将请求发送到wildfly服务器。
我决定使用的协议是REST,在wildfly上已经提供的那种实现很容易。

以下是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中的第一个断点,方法findAll()调用了repository.findAll();
同样也期望第二个,它进入方法GraphRepositoryImpl的内部findAll(...)类和创建context.getSession().loadAll(clazz);的行Session
几步之后,它尝试在方法org.neo4j.ogm.metadata.MetaData中的_classInfo(String,String,String)类中调用domainInfo.getClassInfosWithAnnotation(nodeEntityAnnotation);其中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来调用此代码,将产生预期的结果:[{“ amount”:null,“ currency”:null}]

我在这里有很多简单的东西需要改进,我尝试了很多方法,在Tomcat 8上也发生了同样的异常,但是Rest方法即使在虚拟情况下也无法正常工作,所以我改用Wildfly。
我是在这里找到错误还是在设置中错过了某些东西?

2)项目和代码详细信息

这是有关我的环境,项目结构和遇到此问题时运行的代码的信息。

环境

我的环境如下:

我有Neo4J社区版2.2.4。

我下载了wildfly-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();
    }
}


通用简单休息图存储库界面

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());
    }

}


数据库连接

在salessupport-db中,我们使用以下代码连接到数据库:

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);
}
...
}


附注:这是我关于stackoverflow的第一个问题,我希望我写尽可能少的文章来传达这个问题...

最佳答案

这是@NodeEntity中的Spring Data Neo4j吗?如果是,则必须正确设置Spring,在这里找不到。

关于java - 在JEE(JBoss)环境中的neo4j:,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32490795/

相关文章:

java - 我在 Recycler View 上得到一个 Null Reference

java - Extract Class Eclipse IDE 重构功能有何用处?

java - 在 Java 中使用 ANT 提取文件

java - 查找调用特定方法的代码树

java - 使用 Spring boot 和 JWT 保护 REST Api

java - 将 Jackson ObjectMapper 与 Jersey 一起使用

php - Magento REST API

android - R.Id.在 android 项目中使用 maven 生成的 apklib 时丢失

java - 访问 Java Web 项目中的动态资源

java - 如何以编程方式更新 Nexus 中的 maven-metadata 文件