AOP after advice to void Lab Tests when OpenMRS Order is voided

Hi,

I need to implement after AOP advice to void module entities like Lab Tests when ever OpenMRS Order entity is voided. (Our module entity Lab Test has a one to one mapping to OpenMRS Orders entity.) In OpenMRS, whenever an encounter is voided, its all linked Orders are also voided and this will eventually trigger voidOrder(…) method. Therefore, I’m implementing After advice on “voidOrder” method. And this does not work.

<!--  APO Support -->
<advice>
	<point>org.openmrs.api.OrderService</point>
	<class>org.openmrs.module.commonlabtest.aop.AfterOrderVoidAdvice</class>
</advice>

I have written advice as below by implementing AfterReturningAdvice.

public class AfterOrderVoidAdvice implements AfterReturningAdvice {

private Log log = LogFactory.getLog(this.getClass());

/*
 * (non-Javadoc) * @see
 * org.springframework.aop.AfterReturningAdvice#afterReturning(java.lang.Object,
 * java.lang.reflect.Method, java.lang.Object[], java.lang.Object)
 * 
 * depends on org.openmrs.api.impl.OrderServiceImpl
 */
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {

	log.info("======== in After Advice " + method.getName() + "========");

	if (method.getName().equalsIgnoreCase("voidOrder")) {

		log.info("<<<<<<<  Method: " + method.getName() + ". After advice called. >>>>>>>>");

		if (returnValue != null)
			log.info(returnValue.toString());

	}
}

When I replace the point with EncounterService, it works but setting point to OrderService does not invoke advice.

Can anyone please suggest how to solve this problem?

@dkayiwa @darius

Can you make sure that the encounters have unvoided orders while your are pointing to OrderService? OrderService.voidOrder() will be called if there are any unvoided orders for encounter - See here

1 Like

Yes, I have made this sure by searching for the encounters records in database which have unvoided Orders, but it does not work.

@dkayiwa @darius @wyclif Please help me resolve this issue. Its quite weird that the same advice works for Encounter Service (method name: saveEncounter) but not for OrderService (method name: voidOrder)?

Which version of the OpenMRS platform are you running?

it’s 2.1.2

Can you run in debug mode and tell us what happens at the point that @suthagar23 mentioned above?

I’m actually unable to debug module api, I have set the configuration settings as localhost and port 1045 which I specified while setting up OpenMRS SDK server.

This Aspect class is added to module api project

I’m now able to debug module api but it does not go in openmrs-api code although I have set a break point in EncounterService class.

Do you have unit tests for this?

@dkayiwa I have verified that it never executes the line which @suthagar23 had pointed earlier.

Now, my question at this point is how does Encounter object holds orders that have already voided properties set to true? Is there an AOP implemented? @dkayiwa can you please explain why it has all linked orders already voided?

I have also tried to set the advice to saveEncounter method, and then checking the orders on returned Encounter object that if they are voided or not. But in this scenario, the sequence is a problem. If I void encounter, it first fetches the already voided orders and then executes the advice which is obviously something which is not required.

@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {

	log.info("======== in After Advice " + method.getName() + "========");

	if (method.getName().equalsIgnoreCase("saveEncounter")) {
		if (returnValue != null) {
			
			Encounter encounter = (Encounter) returnValue;
			Set<Order> orders = (Set<Order>) encounter.getOrders();

			for (Order o : orders) {
				if (!o.isVoided())
					log.info(" ==== > Order # " + o.getOrderId() + " is voided.");
				// void corresponding LabTest entity that has one to one mapping to this Order
			}
		}

	}
}

thanks for you support!

No, I don’t have…

Can you set up such a test? Here are examples of tests for AOP: https://github.com/openmrs/openmrs-module-locationbasedaccess/tree/master/api/src/test/java/org/openmrs/module/locationbasedaccess/aop

1 Like

@tahira Can you push your code to GitHub and share with us? It’s hard to find the issues with a short part of code.

1 Like

My problem is solved. I have implemented Advice on voidEncounter and unvoidEncounter methods. I am catching the returned encounter and fetching its orders and I’m then able to void/unvoid Lab Test objects that are mapped to those OpenMRS Order objects.

Thanks @dkayiwa and @suthagar23 for your continuous support.

@dkayiwa Unit Tests can be found here: https://github.com/tahiraniazi/openmrs-module-commonlabtest/tree/CLM-1/api/src/test/java/org/openmrs/module/commonlabtest/aop