Transactions in custom procedures not rolling back on failure

Hello.

Apologies if the question is trivial but I'm new with the platform.
I'm writing custom Java procedures for Neo4j and I noticed that transactions marked as failure are not being rolled back. Here's a sample code:

@Context
public GraphDatabaseService db;

@Procedure(value = "xxx.yyy.create", mode = Mode.WRITE)
@Description("Create new node")
public Stream<NodeResult> create(@Name("map") final Map<String, Object> map,
        @Name("direction") final String direction,
        @Name("relationshipType") final String relationshipType)
            throws GraphServicesException {
    final String string = JsonUtils.serialize(map);
    final MyClass myClass = JsonUtils.deserializeObj(string, MyClass.class);
    if (null == myClass) {
        return Stream.empty();
    }
    try (Transaction tx = db.beginTx()) {
        try {
            final Node node = GraphUgcService.create(db, myClass, direction, relationshipType);
            if (null != node) {
                tx.success();
                return Stream.of(new NodeResult(node));
            }
        } catch (final GraphServicesException e) {
            logger.error("Insert failed for: " + string, e);
            throw e;
        } finally {
            tx.failure();
        }
    }
    return Stream.empty();
}

The transaction above is never rolled back even though tx.failure() is executed.

I've noticed that tx at runtime is of class PlaceboTransaction, if that helps. Finally, if I access tx.currentTransaction at runtime and call failure() on it, it does roll back. Any idea of what's wrong?

Thanks in advance.

In most cases you don't have to do transaction management in a procedure yourself. You're inheriting a transactional context from the statement containing the proceudre call.
Any exception being thrown by your procedure will rollback the transaction.

If you want to manage transactions explicitly you have to create a new thread and do gds.beginTx() there.

Alternatively you can also add @Context public ProcedureTransaction procedureTransaction; and run its terminate() or failure() method.