Skip to content

Commit

Permalink
Merge pull request #10 from Bahmni/BAH-3124
Browse files Browse the repository at this point in the history
BAH-3124 | added Encounter create/update events
  • Loading branch information
kavitha-sundararajan authored Jul 27, 2023
2 parents ba41bfc + a477277 commit a67910b
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.databind.ObjectMapper;
import org.bahmni.module.events.api.listener.AppointmentAdvice;
import org.bahmni.module.events.api.listener.EncounterAdvice;
import org.bahmni.module.events.api.listener.PatientAdvice;
import org.bahmni.module.events.api.publisher.EventPublisher;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
Expand Down Expand Up @@ -86,6 +87,26 @@ public DefaultPointcutAdvisor appointmentAdviceAdvisor(AspectJExpressionPointcut
return advisor;
}

@Bean
public EncounterAdvice encounterEventAdvice() {
return new EncounterAdvice();
}

@Bean
public AspectJExpressionPointcut encounterEventAdvicePointcut() {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression("execution(* org.openmrs.api.EncounterService.saveEncounter(..))");
return pointcut;
}

@Bean
public DefaultPointcutAdvisor encounterAdviceAdvisor(AspectJExpressionPointcut encounterEventAdvicePointcut, EncounterAdvice encounterEventAdvice) {
DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
advisor.setPointcut(encounterEventAdvicePointcut);
advisor.setAdvice(encounterEventAdvice);
return advisor;
}

@Bean
public EventPublisher eventPublisher(JmsTemplate jmsTemplate) {
return new EventPublisher(jmsTemplate, new ObjectMapper());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package org.bahmni.module.events.api.listener;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bahmni.module.events.api.model.BahmniEventType;
import org.bahmni.module.events.api.model.Event;
import org.openmrs.Encounter;
import org.openmrs.module.webservices.rest.web.ConversionUtil;
import org.openmrs.module.webservices.rest.web.representation.Representation;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.lang.NonNull;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import static org.bahmni.module.events.api.model.BahmniEventType.*;

public class EncounterAdvice implements AfterReturningAdvice, ApplicationEventPublisherAware, MethodBeforeAdvice {

private final Logger log = LogManager.getLogger(EncounterAdvice.class);

private ApplicationEventPublisher eventPublisher;

private final ThreadLocal<Map<String,Integer>> threadLocal = new ThreadLocal<>();
private final String ENCOUNTER_ID_KEY = "encounterId";


@Override
public void afterReturning(Object returnValue, Method method, Object[] arguments, Object target) {
Map<String, Integer> encounterInfo = threadLocal.get();
// TODO: This is a workaround to avoid publishing duplicate events because currently the event is getting called twice. Need to find out the reason and resolve it.
if (encounterInfo != null) {
BahmniEventType eventType = encounterInfo.get(ENCOUNTER_ID_KEY) == null ? BAHMNI_ENCOUNTER_CREATED : BAHMNI_ENCOUNTER_UPDATED;
threadLocal.remove();
Encounter encounter = (Encounter) returnValue;

Object representation = ConversionUtil.convertToRepresentation(encounter, Representation.FULL);
Event event = new Event(eventType, representation, encounter.getUuid());
eventPublisher.publishEvent(event);

System.out.println("Successfully published event with uuid : " + encounter.getUuid());
}
}

@Override
public void setApplicationEventPublisher(@NonNull ApplicationEventPublisher applicationEventPublisher) {
this.eventPublisher = applicationEventPublisher;
}

@Override
public void before(Method method, Object[] objects, Object o) {
Encounter encounter = (Encounter) objects[0];
Map<String, Integer> encounterInfo = new HashMap<>(1);
encounterInfo.put(ENCOUNTER_ID_KEY, encounter.getId());
threadLocal.set(encounterInfo);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ public enum BahmniEventType {
BAHMNI_PATIENT_CREATED("bahmni-patient"),
BAHMNI_PATIENT_UPDATED("bahmni-patient"),
BAHMNI_APPOINTMENT_CREATED("bahmni-appointment"),
BAHMNI_APPOINTMENT_UPDATED("bahmni-appointment");
BAHMNI_APPOINTMENT_UPDATED("bahmni-appointment"),
BAHMNI_ENCOUNTER_CREATED("bahmni-encounter"),
BAHMNI_ENCOUNTER_UPDATED("bahmni-encounter");

private final String topic;
BahmniEventType(String topic) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package org.bahmni.module.events.api.listener;

import org.bahmni.module.events.api.model.BahmniEventType;
import org.bahmni.module.events.api.model.Event;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.openmrs.Encounter;
import org.openmrs.module.webservices.rest.web.ConversionUtil;
import org.openmrs.module.webservices.rest.web.representation.Representation;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.context.ApplicationEventPublisher;

import java.util.UUID;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;

@PowerMockIgnore("javax.management.*")
@PrepareForTest({ ConversionUtil.class })
@RunWith(PowerMockRunner.class)
public class EncounterAdviceTest {

private final EncounterAdvice encounterAdvice = new EncounterAdvice();

private ApplicationEventPublisher applicationEventPublisher;

@Before
public void setUp() {
applicationEventPublisher = mock(ApplicationEventPublisher.class);
encounterAdvice.setApplicationEventPublisher(applicationEventPublisher);
}

@Test
public void shouldVerifyBahmniEventPublishIsCalledGivenEncounterIsCreated() {
Encounter newEncounter = getEncounter();
PowerMockito.mockStatic(ConversionUtil.class);
Object[] args = {newEncounter};
newEncounter.setId(null);
encounterAdvice.before(null, args, null);
PowerMockito.when(ConversionUtil.convertToRepresentation(getEncounter(), Representation.FULL)).thenReturn(newEncounter);

encounterAdvice.afterReturning(getEncounter(), null, null, null);

verify(applicationEventPublisher, times(1)).publishEvent(any(Event.class));
}

@Test
public void shouldPublishCreateEventGivenEncounterIsCreated() {
Encounter newEncounter = getEncounter();

PowerMockito.mockStatic(ConversionUtil.class);
PowerMockito.when(ConversionUtil.convertToRepresentation(getEncounter(), Representation.FULL)).thenReturn(newEncounter);

Object[] args = {newEncounter};
newEncounter.setId(null);
encounterAdvice.before(null, args, null);
encounterAdvice.afterReturning(newEncounter, null, null, null);

ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class);
verify(applicationEventPublisher, times(1)).publishEvent(eventArgumentCaptor.capture());

Event event = eventArgumentCaptor.getValue();
assertEquals(BahmniEventType.BAHMNI_ENCOUNTER_CREATED, event.eventType);
}

@Test
public void shouldPublishUpdateEventGivenEncounterIsUpdated() {
Encounter newEncounter = getEncounter();

PowerMockito.mockStatic(ConversionUtil.class);
PowerMockito.when(ConversionUtil.convertToRepresentation(getEncounter(), Representation.FULL)).thenReturn(newEncounter);

Object[] args = {newEncounter};
encounterAdvice.before(null, args, null);
encounterAdvice.afterReturning(newEncounter, null, null, null);

ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class);
verify(applicationEventPublisher, times(1)).publishEvent(eventArgumentCaptor.capture());

Event event = eventArgumentCaptor.getValue();
assertEquals(BahmniEventType.BAHMNI_ENCOUNTER_UPDATED, event.eventType);
}

@Test
public void shouldVerifyPublishedContentForAEncounter() {
Encounter newEncounter = getEncounter();

PowerMockito.mockStatic(ConversionUtil.class);
PowerMockito.when(ConversionUtil.convertToRepresentation(getEncounter(), Representation.FULL)).thenReturn(newEncounter);

Object[] args = {newEncounter};
encounterAdvice.before(null, args, null);
encounterAdvice.afterReturning(newEncounter, null, null, null);

ArgumentCaptor<Event> eventArgumentCaptor = ArgumentCaptor.forClass(Event.class);
verify(applicationEventPublisher, times(1)).publishEvent(eventArgumentCaptor.capture());

Event event = eventArgumentCaptor.getValue();
assertEquals(BahmniEventType.BAHMNI_ENCOUNTER_UPDATED, event.eventType);
assertEquals(newEncounter.getUuid(), event.payloadId);
}

private Encounter getEncounter() {
Encounter encounter = new Encounter();
encounter.setUuid(UUID.randomUUID().toString());
encounter.setId(123);
return encounter;
}
}

0 comments on commit a67910b

Please sign in to comment.