0

我正在尝试将 neo4j-cypher-dsl 导入到非托管服务器扩展中。我可以启动扩展,但是当我调用使用 DSL 代码的 REST API 方法时,我在日志中看到以下错误:

javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.lang.NoClassDefFoundError: org/neo4j/cypherdsl/core/Cypher
    at org.glassfish.jersey.servlet.WebComponent.serviceImpl(WebComponent.java:410) ~[jersey-container-servlet-core-2.34.jar:?]
   ...

知道为什么会这样吗?

4

1 回答 1

3

Michael here,Neo4j Cypher-DSL 的作者。

让我从我们的社区网站交叉发布我的答案。如果你接受它会很好。

这工作得很好。你还记得用你的代码打包 Cypher-DSL 吗?Cypher-DSL 不是 Neo4j 数据库的模块/库。它作为单独的工件分发。因此,如果您想在扩展或插件中使用它,则必须将其打包。我通常建议maven-assembly-plugin. 另一种方法是 Shade-Plugin。

这是一个工作示例,首先pom.xml是依赖项。注意 Neo4j 核心是如何在提供的范围内的(因为扩展部署到 Neo4j 中,因此提供了 api)以及 Cypher-DSL 是如何编译范围(Mavens)默认的:

<?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>org.example</groupId>
    <artifactId>some-extension</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.release>11</maven.compiler.release>
        <neo4j.version>4.4.3</neo4j.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j</artifactId>
            <version>${neo4j.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.neo4j</groupId>
            <artifactId>neo4j-cypher-dsl</artifactId>
            <version>2022.0.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.9.0</version>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.1.1</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

注意汇编插件的配置。我使用预定义的 descriptorRef jar-with-dependencies

生成的 JAR 将包含重新打包的库。正如我所说,阴影是另一种选择(也可以重命名包)。

第三个选项将像往常一样打包您的代码(瘦 jar),将其作为插件添加到 neo4j 以及 cypher-dsl.jar。

无论如何,这是供参考的示例代码:

package org.neo4j.examples.server.unmanaged;

import static org.neo4j.cypherdsl.core.Cypher.parameter;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.neo4j.cypherdsl.core.Cypher;
import org.neo4j.cypherdsl.core.Expression;
import org.neo4j.cypherdsl.core.Functions;
import org.neo4j.cypherdsl.core.renderer.Configuration;
import org.neo4j.cypherdsl.core.renderer.Renderer;
import org.neo4j.dbms.api.DatabaseManagementService;
import org.neo4j.string.UTF8;

@Path("/helloworld")
public class HelloWorldResource {
    private final DatabaseManagementService dbms;

    public HelloWorldResource(@Context DatabaseManagementService dbms) {
        this.dbms = dbms;
    }

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/{nodeId}")
    public Response hello(@PathParam("nodeId") long nodeId) {

        // Let's make sure we trigger the messages ;)
        try {
            Cypher.returning((Expression) null);
        } catch (Exception e) {
            System.out.println("oops… " + e.getMessage());
        }

        var anyNode = Cypher.anyNode("n");
        var statement = Cypher.match(anyNode)
            .where(Functions.id(anyNode).isEqualTo(parameter("nodeId").withValue(nodeId))).returning(anyNode).build();
        var cypher = Renderer.getRenderer(Configuration.prettyPrinting()).render(statement);
        return Response.status(Status.OK).entity(UTF8.encode("Here's a nice query\n\n" + cypher + "\n\n")).build();
    }
}

调用时,结果如下所示:

curl --user neo4j:secret localhost:7474/examples/unmanaged/helloworld/4711
Here's a nice query

MATCH (n)
WHERE id(n) = $nodeId
RETURN n

并且服务器打印我在代码中的输出,证明消息资源不是这种事情的原因(oops… At least one expressions to return is required.)。

于 2022-01-20T19:22:34.053 回答