Creating Custom Transaction Event Listener in Neo4J 4.x

Tapan Sharma
2 min readNov 29, 2020

--

This post discusses the steps that are needed to register a custom transaction event listener with Neo4J 4.x.

For those who are working on Neo4J 3.x, kindly go through the post by Max, here: https://maxdemarzi.com/2015/03/25/triggers-in-neo4j/

Starting from 4.x, Neo4J changed the APIs for event listener registration and hence the 3.x code need to be modified accordingly.

I am writing this post because I could not find the proper documentation or code for custom transaction event listener. For the benefit of others, I am listing down the steps and sharing the boilerplate code for the same.

“A transaction event listener can be registered to receive Neo4j database transaction events. Once it has been registered at a DatabaseManagementService instance, it receives transaction events for the database with which it was registered”.

For reference from Neo4J:

https://neo4j.com/docs/java-reference/current/transaction-management/unique-nodes/#transactions-events

Although the above link contains some code for handling transaction events, however, it is not complete and also require some changes.
Do go through the theoretical section to understand the interfaces and beforeCommit, afterCommit, and afterRollback methods.

The Real Stuff

You need to create an extension factory extending ExtensionFactory of Neo4J Kernel API, and annotate it with @ServiceProvider. This annotation helps in registering the factory with Neo4J plugin manager.

@ServiceProvider
public class Neo4JTransactionEventListenerExtensionFactory extends ExtensionFactory<Neo4JTransactionEventListenerExtensionFactory.Dependencies>
{
@Override
public Lifecycle newInstance(final ExtensionContext extensionContext, final Dependencies dependencies)
{
final GraphDatabaseAPI db = dependencies.graphdatabaseAPI();
final LogService log = dependencies.log();
final DatabaseManagementService databaseManagementService = dependencies.databaseManagementService();
return new CustomGraphDatabaseLifecycle(log, db, dependencies, databaseManagementService);
}
interface Dependencies
{
GraphDatabaseAPI graphdatabaseAPI();
DatabaseManagementService databaseManagementService();
AvailabilityGuard availabilityGuard();
LogService log();
}
public static class CustomGraphDatabaseLifecycle extends LifecycleAdapter
{
private final GraphDatabaseAPI db;
private final Dependencies dependencies;
private Neo4JTransactionEventListener transactionEventhandler;
private final DatabaseManagementService databaseManagementService;
public CustomGraphDatabaseLifecycle(final LogService log, final GraphDatabaseAPI db, final Dependencies dependencies,final DatabaseManagementService databaseManagementService)
{
this.log = log;
this.db = db;
this.dependencies = dependencies;
this.databaseManagementService = databaseManagementService;
}
@Override
public void start()
{
if (this.db.databaseName().compareTo("system") != 0)
{
this.transactionMonitorEventhandler = new Neo4JTransactionMonitorEventListener(this.db, this.log);
this.databaseManagementService.registerTransactionEventListener(this.db.databaseName(), this.transactionEventhandler);
}
}
@Override
public void shutdown()
{
this.databaseManagementService.unregisterTransactionEventListener(this.db.databaseName(), this.transactionEventhandler);
}
}
public Neo4JTransactionEventListenerExtensionFactory()
{
super(ExtensionType.DATABASE, "neo4JTransactionEventHandler");
}
}

Neo4jTransactionEventListener needs to implement TransactionEventListener:

public class Neo4JTransactionEventListener implements TransactionEventListener<Object>
{
GraphDatabaseService db;
LogService log;
public Neo4JTransactionEventListener(final GraphDatabaseService graphDatabaseService, final LogService logsvc)
{
this.db = graphDatabaseService;
this.log = logsvc;
}
public Object beforeCommit(final TransactionData data, final Transaction transaction, final GraphDatabaseService databaseService) throws Exception
{
// TODO Auto-generated method stub
return null;
}
public void afterCommit(final TransactionData data, final Object state, final GraphDatabaseService databaseService)
{
// TODO Auto-generated method stub
}
public void afterRollback(final TransactionData data, final Object state, final GraphDatabaseService databaseService)
{
// TODO Auto-generated method stub
}
}

Enter following dependencies in your maven project:

https://mvnrepository.com/artifact/org.neo4j/neo4j, and https://mvnrepository.com/artifact/org.neo4j/server-api

Build the jar using JDK 11 and place it under Neo4J plugins directory.

That’s it! Start handling Neo4j Events!

--

--

Tapan Sharma
Tapan Sharma

Written by Tapan Sharma

0 Followers

Research Scholar, Technology Architect at Precisely, #DataScience #Bigdata #DataIntegrity #MasterDataManagement, Twitter/LinkedIn: @tapansharma04

Responses (1)