org.openmrs.api.APIException: Editing some fields on Obs is not allowed

In the meantime if you really really want to try a snapshot version of emrapi module, you might as well switch most of the other modules to snapshots too, it will be less painful

@mksd the reason why you are getting this error is because you are not setting the manual flush mode from a transactional method. As a result, on calling ObsService.saveObs, spring starts a new transaction, which by convention, sets the flush mode, for an existing session, back to auto, hence overwriting your manual value. See: https://github.com/joshlong/spring-framework/blob/master/spring-orm-hibernate4/src/main/java/org/springframework/orm/hibernate4/HibernateTransactionManager.java#L453

Your unit test passes because our unit test methods are transactional. Therefore, spring uses an existing transaction, with its already configured manual flush mode session, instead of starting a new one. See: https://github.com/openmrs/openmrs-core/blob/master/api/src/test/java/org/openmrs/test/BaseContextSensitiveTest.java#L105

As for work arounds, you have two options:

  1. In the openmrs platform, we could set the manual flush mode right withing ObsServiceImpl.saveObs()
  2. Create a transactional service layer method, in your module, and set the manual flush mode from there. As done here: https://github.com/openmrs/openmrs-module-emrapi/blob/705b1ffac29af7b1579801ad18fc446561e58ea2/api/src/main/java/org/openmrs/module/emrapi/encounter/EmrEncounterServiceImpl.java#L115

Thanks a million @dkayiwa for spending the time! That’s awesome.

The example you pointed to displays a class that is transactional in its entirety, but I assume that setting @Transactional to a single method is also a valid option? I will try an report.

Is this an option from Platform design standpoint? If yes then please let’s do it. If you look, the only reason why I had to introduce a 2.0 compatible resource with ad-hoc unit tests… etc, is precisely to work around the issue being discussed here. This would go away is that sort of thing was handled by ObsServiceImpl from scratch.

Regarding platform design, @wyclif started a discussion here: Improving the way we save immutable objects Personally, am in for it. :smile:

Yes @Transactional can be on a single method.

@dkayiwa for some reason, this stopped working(I think it used to work before). Here’s this solution implemented here https://github.com/openmrs/openmrs-module-attachments/blob/master/omod-2.0/src/main/java/org/openmrs/module/attachments/rest/AttachmentResource2_0.java#L17-L18.

This test https://github.com/openmrs/openmrs-module-attachments/blob/master/omod-2.0/src/test/java/org/openmrs/module/attachments/rest/AttachmentRestController2_0Test.java#L98-L108 passes but the error is thrown at runtime on platform 2.3.0 and 2.1.x.

@ivange94 are you able to reproduce it from here? qa-refapp.openmrs.org

If yes, what are the steps?

@dkayiwa yes.

Visit the patient dashboard page for John Taylor

I just added an attachment. Open the attachments page by clicking the arrow. You’ll see the attachment Dev setup. To edit it, you need to click the caption and enter a new caption in the input field. But have the dev console open so you can see the network requests while doing it. When you click save, it’ll return a 500 response with the error message like in the screenshot below.

1 Like

I do not think that what you have, has ever worked. Those changes need to be in a transactional service method.

2 Likes

Thanks @dkayiwa, this works (see PR here).

@ivange94 could you try it against a recent version of Core? I tried with Ref App 2.7.0/Core 2.0.6 and it solves the issue there.

1 Like

Thanks for looking into this.