user2521960
user2521960

Reputation: 21

Using SpringRestGraphDatabase API to work within transaction

I'm new to graph db and i'm having problems to get the api work within a transaction.

I have a simple code that uses the neo4j graph db api to create nodes and relationship. My code runs in JUnit and tries to create 2 nodes and a relationship between them using begin and end transaction given below.

The code works fine in a happy scenario. However, if something fails within the code, the nodes are still committed into the graph database. Not sure if i'm doing something wrong out here. I would have expected the 2 nodes created to be rolled back.

Here is the code snippet:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/applicationContext.xml" })
public class RestBatchLoaderTest {  

    @Autowired
    SpringRestGraphDatabase graphDatabaseService;

@Test
public void createNode() {
    Transaction tx =graphDatabaseService.beginTx();

    try {
        Map<String,Object> nodeprops1 = new HashMap<String, Object>();
        nodeprops1.put("name", "James Parker");
        nodeprops1.put("age", Integer.valueOf(11));
        Node james = graphDatabaseService.createNode(nodeprops1);           
        Assert.assertNotNull(james);

        Map<String,Object> nodeprops2 = new HashMap<String, Object>();
        nodeprops2.put("name", "Bing P");
        nodeprops2.put("age", Integer.valueOf(34));
        Node bing= graphDatabaseService.createNode(nodeprops2);

        Node aa = null;
                    // Failure point: should rollback the previous node in the finally.
        graphDatabaseService.remove(aa);            


        Map<String,Object> relprops = new HashMap<String, Object>();
        RelationshipType type = new RelationshipType() {

            @Override
            public String name() {
                return "MARRIED_TO";
            }
        };
        graphDatabaseService.createRelationship(joe, jane, type, relprops);
        tx.success();

    } finally {
        tx.finish();
    }
}

The graphDatabaseService object is autowired using spring configuration. Here is the configuration:

<neo4j:config graphDatabaseService="graphDatabaseService"/>
<bean id="graphDatabaseService" class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
    <constructor-arg value="http://localhost:7474/db/data/"/>
</bean>

Also, I notice tx object is an instance of NullTransaction when graphDatabaseService.beginTx() is called in the code above.

Any ideas, what is going wrong?

Thanks.

Upvotes: 1

Views: 925

Answers (2)

user2521960
user2521960

Reputation: 21

I think figured out what the problem was. The configuration needs to have batch enabled - true. Also i used the RestAPI wrapper to the graph database object to run it as one atomic code. See code below:

@Autowired
SpringRestGraphDatabase graphDatabaseService;

private RestAPI restAPI;

@Before
public void init(){
    this.restAPI = ((RestGraphDatabase)graphDatabaseService).getRestAPI();
}

@Test
public void testEnableBatchTransactions() throws Exception {
    System.setProperty(Config.CONFIG_BATCH_TRANSACTION,"true");
    Transaction tx = restAPI.beginTx();
    try {
        Node n1 = restAPI.createNode(map("name", "node1"));
        Node n2 = restAPI.createNode(map("name", "node2"));
        Node n3 = restAPI.createNode(map("name", "node3"));
        //String s = null;
        //s.toString();
        Node n4 = restAPI.createNode(map("name", "node4"));      
        tx.success();
    } finally {
         tx.finish();
    }


    assertTrue(tx instanceof BatchTransaction);
} 

Also System.setProperty(Config.CONFIG_BATCH_TRANSACTION,"true"); enables the batch mode.

To test this, try un-commenting the code snippet and run the test. Nodes n1, n2 and n3 will not be committed in the db.

Upvotes: 1

PerfectPixel
PerfectPixel

Reputation: 1968

You specified graphDatabaseService.remove(aa); as your failure point as aa is NULL. Looking into the documentation of org.springframework.data.neo4j.rest.SpringRestGraphDatabase there is no Exception documented that is being thrown if the node is NULL. Have you verified that an exception is actually thrown? Otherwise your code will run through to tx.success();. If an exception is thrown, please specify further what version of neo4j and spring you are using.


Edit:

After reading a little more, I see in the source of org.springframework.data.neo4j.rest.SpringRestGraphDatabase that it should give you a NullTransaction that basically does nothing (see here). Furthermore, the Spring Data neo4j documentationstates that each operation is in its own transaction as the neo4j REST adapter does not allow transaction that span over multiple operations (see here).

Upvotes: 0

Related Questions