I’m going to post this here as a reminder to other OpenMRS developers (and myself) and to hopefully save a few hours/days of debugging. The key to getting transactions to work correctly in the webapp is to, well, tell Spring that we’re in a transaction. You can do this by simply putting an
@Transactional annotation in the *Service java interface.
Without that key piece of text, the service and its methods will still work. However, they’ll work in a readonly kind of way. All data written to the database will be rolled back when the body of work has completed. This little error manifested itself recently after our reporting code-a-thon. During the event we had to create a new API service, which is only done maybe a few times a year. The service didn’t get the @Transactional tag and so therefore all database editing failed that went through the ReportService. The unit tests set up for the object passed, but that is because a unit test happens all within a single transaction — the rollback is always done after the completion of the test anyway.
I added a note to http://openmrs.org/wiki/OpenMRS_API about the requirement, but I’m sure there will be an OpenMRS developer in the future struggling with their object not saving or updating in the database and be completely baffled by it.