繁体   English   中英

在JEE(JBoss)环境中的neo4j:

[英]neo4j in JEE (JBoss) environment:

我已经使用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(); findAll()
  • 第二个也是期望的,它将进入内部GraphRepositoryImpl类以找到方法findAll(...)和行context.getSession().loadAll(clazz); 这将创建一个Session
  • 几步之后,它尝试在org.neo4j.ogm.metadata.MetaData _classInfo(String,String,String)方法中的org.neo4j.ogm.metadata.MetaData类中调用domainInfo.getClassInfosWithAnnotation(nodeEntityAnnotation); 其中nodeEntityAnnotation="org.neo4j.ogm.annotation.NodeEntity"
  • DomainInfo类方法getClassInfosWithAnnotation ,该方法随后被调用,地图annotationNameToClassInfo DomainInfo为空。 我希望它会被我的模型填充,这显然发生在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);
}
...
}

PS:这是我关于stackoverflow的第一个问题,希望我写的尽可能少的东西尽可能多地传达这个问题...

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

https://github.com/neo4j/neo4j-ogm/issues/48中 ,有一个更新,该更新已通过neo4j-ogm版本> 2实施。

我在https://github.com/mkirchmann/hello-neo4j-ogm上提供了整个源代码,不能保证一切正常或一切正确,至少应该列出一种类型的整个节点。 并且不要忘记正确设置ogm.properties

解决方案的关键是neo4j-ogm的vfs驱动程序 ,可以在https://github.com/mkirchmann/neo4j-ogm-resourceresolver-vfs中找到(已从ctpconsulting分叉,使用2.1.1版和mvn install以使其在您本地的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>

感谢大家的贡献和支持!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM