WorkflowInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { try { final Method method = invocation.getMethod(); final Workflow[] workFlowAnnotations = method.getAnnotationsByType(Workflow.class); checkForBadSignatures(invocation); final String correlationId = checkForCorrelationId(invocation.getArguments()); Workflow workflow = workFlowAnnotations[0]; localContext.registerNew(generateWorkflowIdentifier(method, workflow), workflow.version(), workflow.description(),correlationId, fluxClientConfigurationProvider.get().getClientElbId()); registerEventsForArguments(invocation.getArguments()); invocation.proceed(); connectorProvider.get().submitNewWorkflow(localContext.getStateMachineDef()); return null ; } finally { this.localContext.reset(); } } WorkflowInterceptor(); @VisibleForTesting  WorkflowInterceptor(LocalContext localContext, Provider<FluxRuntimeConnector> connectorProvider,
                               Provider<ObjectMapper> objectMapperProvider, Provider<FluxClientConfiguration> fluxClientConfigurationProvider); @Override Object invoke(MethodInvocation invocation);  }
@Test public void shouldRegisterNewDefinitionWithLocalContext() throws Throwable { final Method invokedMethod = simpleWorkflowForTest.getClass().getDeclaredMethod("simpleDummyWorkflow", StringEvent.class, IntegerEvent.class); workflowInterceptor.invoke(dummyInvocation(invokedMethod)); final String expectedWorkflowIdentifer = new MethodId(invokedMethod).toString() + _VERSION + "1"; Mockito.verify(localContext, times(1)).registerNew(expectedWorkflowIdentifer, 1, "",null, null); }
@Test public void shouldSubmitNewDefinitionAfterMethodIsInvoked() throws Throwable { workflowInterceptor.invoke(dummyInvocation(simpleWorkflowForTest.getClass().getDeclaredMethod("simpleDummyWorkflow", StringEvent.class, IntegerEvent.class))); Mockito.verify(fluxRuntimeConnector, times(1)).submitNewWorkflow(any(StateMachineDefinition.class)); }
@Test public void shouldRefreshLocalContext() throws Throwable { try { workflowInterceptor.invoke(dummyInvocation(simpleWorkflowForTest.getClass().getDeclaredMethod("badWorkflow"))); } catch (IllegalSignatureException e) { } verify(localContext, times(1)).reset(); }
@Test(expected = IllegalSignatureException.class) public void shouldNotAllowWorkflowMethodsThatReturnAnything() throws Throwable { workflowInterceptor.invoke(dummyInvocation(simpleWorkflowForTest.getClass().getDeclaredMethod("badWorkflow"))); }
@Test public void testWorkflowInterception_WithActualParameters() throws Throwable { final MutableInt getEventNameCall = new MutableInt(0); doAnswer(invocation -> { Event argument = (Event) invocation.getArguments()[0]; final int currentValue = getEventNameCall.intValue(); getEventNameCall.increment(); return argument.name() + currentValue; }).when(localContext).generateEventName(any(Event.class)); final Method invokedMethod = simpleWorkflowForTest.getClass().getDeclaredMethod("simpleDummyWorkflow", StringEvent.class, IntegerEvent.class); final StringEvent testStringEvent = new StringEvent("someEvent"); final IntegerEvent testIntegerEvent = new IntegerEvent(1); workflowInterceptor.invoke(dummyInvocation(invokedMethod,new Object[]{testStringEvent,testIntegerEvent})); verify(localContext,times(1)).addEvents( new EventData(SimpleWorkflowForTest.STRING_EVENT_NAME + "0", StringEvent.class.getName(), objectMapper.writeValueAsString(testStringEvent), CLIENT), new EventData(SimpleWorkflowForTest.INTEGER_EVENT_NAME + "1", IntegerEvent.class.getName(), objectMapper.writeValueAsString(testIntegerEvent), CLIENT) ); }
@Test public void testWorkflowInterception_WithActualParameters_WithContextId() throws Throwable { when(localContext.generateEventName(any(Event.class))).thenReturn("someNewEvent"); final Method invokedMethod = simpleWorkflowForTest.getClass().getDeclaredMethod("simpleDummyWorkflowWithCorrelationEvent", StringEventWithContext.class, IntegerEvent.class); final StringEventWithContext testStringEvent = new StringEventWithContext("someString","aContextId"); final IntegerEvent testIntegerEvent = new IntegerEvent(1); workflowInterceptor.invoke(dummyInvocation(invokedMethod,new Object[]{testStringEvent,testIntegerEvent})); verify(localContext,times(1)).registerNew( new MethodId(invokedMethod).toString()+_VERSION+"1",1,"", "aContextId", null); }
@Test(expected = IllegalSignatureException.class) public void testSignatureCheck_shouldNotAllowParamsThatAreNotEvents() throws Throwable { workflowInterceptor.invoke(dummyInvocation(SimpleWorkflowForTest.class.getDeclaredMethod("badWorkflowWithNonEventParams", String.class))); }
@Test(expected = IllegalSignatureException.class) public void testSignatureCheck_shouldNotAllowCollections() throws Throwable { workflowInterceptor.invoke(dummyInvocation(SimpleWorkflowForTest.class.getDeclaredMethod("badWorkflowWithCollectionOfEvents", Collection.class))); }
@Test public void testSignatureCheck_shouldAllowVarArgMethods() throws Throwable { when(localContext.generateEventName(any(Event.class))).thenReturn("someName"); final StringEvent wfParam1 = new StringEvent("foobar"); final StringEvent wfParam2 = new StringEvent("foobar2"); final MethodInvocation invocation = dummyInvocation(SimpleWorkflowForTest.class.getDeclaredMethod("simpleDummyWorkflow", StringEvent[].class), new Object[]{new StringEvent[]{wfParam1,wfParam2}}); workflowInterceptor.invoke(invocation); verify(localContext,times(1)).registerNew( new MethodId(invocation.getMethod()).toString()+_VERSION+"1", 1l, "", null, null); final EventData expectedData1 = new EventData("someName" , "com.flipkart.flux.client.intercept.SimpleWorkflowForTest$StringEvent", objectMapper.writeValueAsString(wfParam1), CLIENT); final EventData expectedData2 = new EventData("someName", "com.flipkart.flux.client.intercept.SimpleWorkflowForTest$StringEvent", objectMapper.writeValueAsString(wfParam2), CLIENT); verify(localContext,times(1)).addEvents(expectedData1,expectedData2); }