【问题标题】:Neo4J CDI silent failure when changing @ApplicationScoped into @SessionScoped将@ApplicationScoped 更改为@SessionScoped 时,Neo4J CDI 静默失败
【发布时间】:2014-01-13 14:30:31
【问题描述】:

我将我的 Bean 迁移到 CDI,但我遇到了 Neo4j 的一个奇怪行为,它不会持久保存节点(但正确完成事务),没有任何错误迹象。

更令人困惑的是,添加节点的相同调用在 postCosntructor 内部调用时有效,但在从 REST 服务调用时无效! (g() 是从另一个未显示的 RestService 类调用的)

@Named
@SessionScoped
public class MyNeo4JController implements Serializable
{
   @Inject
   private Neo4JGraph neo4jGraph;
   public MyNeo4JController()
   {
     if (neo4jGraph == null)
        {
            neo4jGraph = new Neo4JGraph();
        }
   }

   @PostConstruct
   void postConstruct()
   {
        f();
   }

   public void f()
   {
     getGraphStorage().addNode("F");
   }

   public void g()
   {
     getGraphStorage().addNode("G");
   }
}

@Singleton
public class Neo4JGraph
{
    private static final String FILESYSTEM_DB = "target/neo4j-db";
    private GraphDatabaseService graphDb;
    public void addNode(String name)
    {
        Transaction tx = graphDb.beginTx();
        try
        {
            Node newNode = graphDb.createNode();
            newNode.setProperty("name", name);
            tx.success();
        }
        catch (Exception e)
        {
            e.printStackTrace();
            tx.failure();
        }
        finally
        {
            tx.finish();
        }
        return true;
    }

    public void setUp(String rootUuid)
    {
        if (graphDb == null)
        {
            graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(FILESYSTEM_DB);
            indexManager = graphDb.index();
            index = indexManager.forNodes("indexNodes");
            registerShutdownHook();
            setGraphRootUUIDString(rootUuid);
        }
    }
}

CDI 和 neo4J 之间是否存在某种神秘的不兼容性,或者我遗漏了什么?

编辑: 好的,显然我通过将 MyNeo4JController 中的 @SessionScoped 更改为 @ApplicationScoped 来缩小错误范围,现在节点被保留。 请注意,在这两种情况下都没有返回错误,但是使用 SessionScoped 没有添加节点!

有人知道为什么吗?因为我不能将此类保留为 ApplicationScoped!

【问题讨论】:

    标签: jakarta-ee neo4j cdi


    【解决方案1】:

    从 SessionScoped bean 中删除构造函数将解决问题。使用现有代码,您每次创建新会话时都会创建一个新数据库。

    【讨论】:

    • 我实际上是在使用与 FILESYSTEM_DB = "target/neo4j-db"; 相同的数据库创建一个新的数据库对象。如果我从 bean 中删除构造函数,数据库是如何初始化的?
    • GraphDataBaseService 实例是数据库服务器实例本身——不仅仅是一个会话或连接。如果您以嵌入式方式使用它(就像您所做的那样),您必须将其作为单例保存在您的应用程序中,并在您的应用程序停止时强制正确关闭 - 最好的办法是在 PostConstruct 方法中创建 GraphDataBaseService 实例并关闭它在 ApplicationScoped bean 的 PreDestroy 方法中,只是将实例返回给其他 bean(RequestScoped、SessionScoped 等客户端),而无需任何进一步的魔法。他们需要正确执行交易。
    猜你喜欢
    • 2014-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2016-06-08
    • 2016-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多