troig troig - 12 days ago 7
Java Question

SDN Migration to 4.2: How does @Transactional works?

I'm trying to upgrade versions of SDN (

4.2.0.M1
) and neo4j-ogm (
2.0.5
) to the latest snapshots
4.2.0.BUILD-SNAPSHOT
and
2.1.0-SNAPSHOT
.

Following the migration guide and some advises from other SO questions, I've wrapped all methods that interact with neo4j session with
@Transactional
. It's working fine with most of the cases, but there still are some exceptions (
Transaction is not current for this thread
) that I cannot understand.

Let me give an example:

@Service
public class ContactServiceImpl implements ContactService {

@Inject
private Session session;

//...

@Override
@Transactional
public void addContact(String userId, String contactId) {
Contact contact = new Contact();
// Fill contact data

session.save(contact);
}

@Override
public void addContacts(String userId, Set<User> newContacts) {
for (User contact : CollectionUtils.emptyIfNull(newContacts)) {
addContact(userId, contact.getId());
}
}
}


Here I've only annotated with
@Transaction
the
addContact
method, because It's the only one that interacts direcly with SDN, at least this was my thought :)

However, If I call the
addContacts
method, which simply iterates a list and call the annotated
addContact
method, It fails with the exception mentioned before. If I also annotate this method, it simply works well, but I don't understand why. Maybe I'm missing some basics about spring
@Transactional
annotation behaviour, so sorry if it's a brainless question.

Can anyone clarify why I need to annotate both methods?
Thanks in advance

Answer

@Transactional is a bit more complicated than most people think. What looks like it should work actually doesn't and sometimes vice versa.

In your case you have hit an unfriendly Spring issue: not understanding how @Transactional AOP proxying works when calling transactional methods from within the same class.

This snippet from the official documenation is a good starting point to get a rough idea about the basics of Spring's transaction proxying.

A quick search of StackOverflow brought me this answer which does a great job of explaining the phenomenon you are seeing.

Note: As of version 4.2, SDN now fully implements the Spring Transaction Platform.