Skip to content

Commit

Permalink
Switch from using WorkflowDefinition to using AbstractWorkflowDefinni…
Browse files Browse the repository at this point in the history
…tion to allow different implementation in the future
  • Loading branch information
gmokki committed May 15, 2015
1 parent b3e4015 commit 7c326dd
Show file tree
Hide file tree
Showing 15 changed files with 56 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nitorcreations.nflow.engine.internal.config.NFlow;
import com.nitorcreations.nflow.engine.internal.workflow.StoredWorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.AbstractWorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowState;

@Component
Expand All @@ -58,7 +58,7 @@ public void setObjectMapper(@NFlow ObjectMapper nflowObjectMapper) {
this.nflowObjectMapper = nflowObjectMapper;
}

public void storeWorkflowDefinition(WorkflowDefinition<? extends WorkflowState> definition) {
public void storeWorkflowDefinition(AbstractWorkflowDefinition<? extends WorkflowState> definition) {
StoredWorkflowDefinition storedDefinition = convert(definition);
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("type", definition.getType());
Expand Down Expand Up @@ -108,7 +108,7 @@ public StoredWorkflowDefinition mapRow(ResultSet rs, int rowNum) throws SQLExcep
});
}

StoredWorkflowDefinition convert(WorkflowDefinition<? extends WorkflowState> definition) {
StoredWorkflowDefinition convert(AbstractWorkflowDefinition<? extends WorkflowState> definition) {
StoredWorkflowDefinition resp = new StoredWorkflowDefinition();
resp.type = definition.getType();
resp.description = definition.getDescription();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
import com.nitorcreations.nflow.engine.listener.WorkflowExecutorListener.ListenerContext;
import com.nitorcreations.nflow.engine.service.WorkflowDefinitionService;
import com.nitorcreations.nflow.engine.service.WorkflowInstanceService;
import com.nitorcreations.nflow.engine.workflow.definition.AbstractWorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.NextAction;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowSettings;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowState;
import com.nitorcreations.nflow.engine.workflow.instance.WorkflowInstance;
Expand Down Expand Up @@ -85,7 +85,7 @@ private void runImpl() {
logger.debug("Starting.");
WorkflowInstance instance = workflowInstances.getWorkflowInstance(instanceId);
logIfLagging(instance);
WorkflowDefinition<? extends WorkflowState> definition = workflowDefinitions.getWorkflowDefinition(instance.type);
AbstractWorkflowDefinition<? extends WorkflowState> definition = workflowDefinitions.getWorkflowDefinition(instance.type);
if (definition == null) {
rescheduleUnknownWorkflowType(instance);
return;
Expand Down Expand Up @@ -170,7 +170,7 @@ private int busyLoopPrevention(WorkflowSettings settings,
}

private WorkflowInstance saveWorkflowInstanceState(StateExecutionImpl execution, WorkflowInstance instance,
WorkflowDefinition<?> definition, WorkflowInstanceAction.Builder actionBuilder) {
AbstractWorkflowDefinition<?> definition, WorkflowInstanceAction.Builder actionBuilder) {
if (definition.getMethod(execution.getNextState()) == null && execution.getNextActivation() != null) {
logger.info("No handler method defined for {}, clearing next activation", execution.getNextState());
execution.setNextActivation(null);
Expand Down Expand Up @@ -211,8 +211,8 @@ private boolean isNextActivationImmediately(StateExecutionImpl execution) {
return execution.getNextActivation() != null && !execution.getNextActivation().isAfterNow();
}

private NextAction processState(WorkflowInstance instance, WorkflowDefinition<?> definition, StateExecutionImpl execution,
WorkflowState currentState) {
private NextAction processState(WorkflowInstance instance, AbstractWorkflowDefinition<?> definition,
StateExecutionImpl execution, WorkflowState currentState) {
WorkflowStateMethod method = definition.getMethod(instance.state);
if (method == null) {
execution.setNextState(currentState);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import org.springframework.util.ReflectionUtils.MethodFilter;

import com.nitorcreations.nflow.engine.internal.workflow.WorkflowStateMethod.StateParameter;
import com.nitorcreations.nflow.engine.workflow.definition.AbstractWorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.Mutable;
import com.nitorcreations.nflow.engine.workflow.definition.NextAction;
import com.nitorcreations.nflow.engine.workflow.definition.StateExecution;
Expand All @@ -44,7 +43,7 @@ public class WorkflowDefinitionScanner {
knownImmutableTypes.addAll(asList(Boolean.TYPE, Boolean.class, Byte.TYPE, Byte.class, Character.TYPE, Character.class, Short.TYPE, Short.class, Integer.TYPE, Integer.class, Long.TYPE, Long.class, Float.TYPE, Float.class, Double.TYPE, Double.class, String.class, BigDecimal.class, BigInteger.class, Enum.class));
}

public Map<String, WorkflowStateMethod> getStateMethods(@SuppressWarnings("rawtypes") Class<? extends AbstractWorkflowDefinition> definition) {
public Map<String, WorkflowStateMethod> getStateMethods(Class<?> definition) {
final Map<String, WorkflowStateMethod> methods = new LinkedHashMap<>();
doWithMethods(definition, new MethodCallback() {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

import org.joda.time.DateTime;

import com.nitorcreations.nflow.engine.workflow.definition.AbstractWorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.NextAction;
import com.nitorcreations.nflow.engine.workflow.definition.StateExecution;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.instance.WorkflowInstance;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
Expand Down Expand Up @@ -39,7 +39,7 @@ public class ListenerContext {
/**
* The definition of the workflow.
*/
public final WorkflowDefinition<?> definition;
public final AbstractWorkflowDefinition<?> definition;

/**
* The name of the state of the workflow instance before processing.
Expand Down Expand Up @@ -69,7 +69,7 @@ public class ListenerContext {
*/
public final Map<Object, Object> data = new LinkedHashMap<>();

public ListenerContext(WorkflowDefinition<?> definition, WorkflowInstance instance, StateExecution stateExecution) {
public ListenerContext(AbstractWorkflowDefinition<?> definition, WorkflowInstance instance, StateExecution stateExecution) {
this.definition = definition;
this.instance = instance;
this.stateExecution = stateExecution;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import com.nitorcreations.nflow.engine.internal.config.NFlow;
import com.nitorcreations.nflow.engine.internal.dao.WorkflowDefinitionDao;
import com.nitorcreations.nflow.engine.workflow.definition.AbstractWorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowState;

Expand All @@ -35,7 +36,7 @@ public class WorkflowDefinitionService {
private static final Logger logger = getLogger(WorkflowDefinitionService.class);

private final AbstractResource nonSpringWorkflowsListing;
private final Map<String, WorkflowDefinition<? extends WorkflowState>> workflowDefitions = new LinkedHashMap<>();
private final Map<String, AbstractWorkflowDefinition<? extends WorkflowState>> workflowDefitions = new LinkedHashMap<>();
private final WorkflowDefinitionDao workflowDefinitionDao;
private final boolean persistWorkflowDefinitions;

Expand All @@ -53,7 +54,7 @@ public WorkflowDefinitionService(@NFlow AbstractResource nflowNonSpringWorkflows
*/
@Autowired(required=false)
public void setWorkflowDefinitions(Collection<WorkflowDefinition<? extends WorkflowState>> workflowDefinitions) {
for (WorkflowDefinition<? extends WorkflowState> wd : workflowDefinitions) {
for (AbstractWorkflowDefinition<? extends WorkflowState> wd : workflowDefinitions) {
addWorkflowDefinition(wd);
}
}
Expand All @@ -63,15 +64,15 @@ public void setWorkflowDefinitions(Collection<WorkflowDefinition<? extends Workf
* @param type Workflow definition type.
* @return The workflow definition or null if not found.
*/
public WorkflowDefinition<?> getWorkflowDefinition(String type) {
public AbstractWorkflowDefinition<?> getWorkflowDefinition(String type) {
return workflowDefitions.get(type);
}

/**
* Return all managed workflow definitions.
* @return List of workflow definitions.
*/
public List<WorkflowDefinition<? extends WorkflowState>> getWorkflowDefinitions() {
public List<AbstractWorkflowDefinition<? extends WorkflowState>> getWorkflowDefinitions() {
return new ArrayList<>(workflowDefitions.values());
}

Expand All @@ -89,7 +90,7 @@ public void postProcessWorkflowDefinitions() throws IOException, ReflectiveOpera
initNonSpringWorkflowDefinitions();
}
if (persistWorkflowDefinitions) {
for (WorkflowDefinition<?> definition : workflowDefitions.values()) {
for (AbstractWorkflowDefinition<?> definition : workflowDefitions.values()) {
workflowDefinitionDao.storeWorkflowDefinition(definition);
}
}
Expand All @@ -107,8 +108,8 @@ private void initNonSpringWorkflowDefinitions() throws IOException, ReflectiveOp
}
}

private void addWorkflowDefinition(WorkflowDefinition<? extends WorkflowState> wd) {
WorkflowDefinition<? extends WorkflowState> conflict = workflowDefitions.put(wd.getType(), wd);
public void addWorkflowDefinition(AbstractWorkflowDefinition<? extends WorkflowState> wd) {
AbstractWorkflowDefinition<? extends WorkflowState> conflict = workflowDefitions.put(wd.getType(), wd);
if (conflict != null) {
throw new IllegalStateException("Both " + wd.getClass().getName() + " and " + conflict.getClass().getName() +
" define same workflow type: " + wd.getType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import org.springframework.transaction.annotation.Transactional;

import com.nitorcreations.nflow.engine.internal.dao.WorkflowInstanceDao;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.AbstractWorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.instance.QueryWorkflowInstances;
import com.nitorcreations.nflow.engine.workflow.instance.WorkflowInstance;
import com.nitorcreations.nflow.engine.workflow.instance.WorkflowInstance.WorkflowInstanceStatus;
Expand Down Expand Up @@ -58,13 +58,13 @@ public WorkflowInstance getWorkflowInstance(int id) {
*/
@SuppressFBWarnings(value = "BC_UNCONFIRMED_CAST_OF_RETURN_VALUE", justification = "getInitialState().toString() has no cast")
public int insertWorkflowInstance(WorkflowInstance instance) {
WorkflowDefinition<?> def = workflowDefinitionService.getWorkflowDefinition(instance.type);
AbstractWorkflowDefinition<?> def = workflowDefinitionService.getWorkflowDefinition(instance.type);
if (def == null) {
throw new RuntimeException("No workflow definition found for type [" + instance.type + "]");
}
WorkflowInstance.Builder builder = new WorkflowInstance.Builder(instance);
if (instance.state == null) {
builder.setState(def.getInitialState().toString());
builder.setState(def.getInitialState().name());
} else {
if (!def.isStartState(instance.state)) {
throw new RuntimeException("Specified state [" + instance.state + "] is not a start state.");
Expand Down Expand Up @@ -99,7 +99,7 @@ public boolean updateWorkflowInstance(WorkflowInstance instance, WorkflowInstanc
builder.setStatus(null);
} else {
String type = workflowInstanceDao.getWorkflowInstance(instance.id).type;
WorkflowDefinition<?> definition = workflowDefinitionService.getWorkflowDefinition(type);
AbstractWorkflowDefinition<?> definition = workflowDefinitionService.getWorkflowDefinition(type);
builder.setStatus(definition.getState(instance.state).getType().getStatus());
}
WorkflowInstance updatedInstance = builder.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ protected AbstractWorkflowDefinition(String type, S initialState, S errorState)
}

protected AbstractWorkflowDefinition(String type, S initialState, S errorState, WorkflowSettings settings) {
this(type, initialState, errorState, settings, null);
}

protected AbstractWorkflowDefinition(String type, S initialState, S errorState, WorkflowSettings settings,
Map<String, WorkflowStateMethod> stateMethods) {
Assert.notNull(initialState, "initialState must not be null");
Assert.isTrue(initialState.getType() == WorkflowStateType.start, "initialState must be a start state");
Assert.notNull(errorState, "errorState must not be null");
Expand All @@ -46,7 +51,11 @@ protected AbstractWorkflowDefinition(String type, S initialState, S errorState,
this.initialState = initialState;
this.errorState = errorState;
this.settings = settings;
this.stateMethods = new WorkflowDefinitionScanner().getStateMethods(getClass());
if (stateMethods != null) {
this.stateMethods = stateMethods;
} else {
this.stateMethods = new WorkflowDefinitionScanner().getStateMethods(getClass());
}
requireStateMethodExists(initialState);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ public void run() {
}

WorkflowStateProcessor fakeWorkflowExecutor(int instanceId, final Runnable fakeCommand) {
return new WorkflowStateProcessor(instanceId, null, null, null, null, env, (WorkflowExecutorListener) null) {
return new WorkflowStateProcessor(instanceId, null, null, null, null, env, null, (WorkflowExecutorListener) null) {
@Override
public void run() {
fakeCommand.run();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
Expand All @@ -17,6 +18,7 @@
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { DaoTestConfiguration.class })
@ActiveProfiles("nflow.db.h2")
@DirtiesContext
public class DatabaseInitializerTest {

@Rule
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

import com.nitorcreations.nflow.engine.internal.dao.WorkflowDefinitionDao;
import com.nitorcreations.nflow.engine.internal.executor.BaseNflowTest;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.AbstractWorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowState;

public class WorkflowDefinitionServiceTest extends BaseNflowTest {
Expand Down Expand Up @@ -62,7 +62,7 @@ public void initDuplicateWorkflows() throws Exception {

@Test
public void demoWorkflowLoadedSuccessfully() {
List<WorkflowDefinition<? extends WorkflowState>> definitions = service.getWorkflowDefinitions();
List<AbstractWorkflowDefinition<? extends WorkflowState>> definitions = service.getWorkflowDefinitions();
assertThat(definitions.size(), is(equalTo(1)));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.springframework.core.env.Environment;
import org.springframework.core.io.AbstractResource;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
Expand All @@ -27,12 +28,13 @@
import com.nitorcreations.nflow.engine.internal.dao.StatisticsDao;
import com.nitorcreations.nflow.engine.internal.dao.WorkflowDefinitionDao;
import com.nitorcreations.nflow.engine.internal.dao.WorkflowInstanceDao;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.AbstractWorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowState;

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("nflow-engine-test")
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
@DirtiesContext
public class WorkflowDefinitionServiceWithSpringTest {

@Configuration
Expand Down Expand Up @@ -76,7 +78,7 @@ public StatisticsDao statisticsDao() {

@Test
public void springWorkflowDefinitionsAreDetected() {
List<WorkflowDefinition<? extends WorkflowState>> definitions = service.getWorkflowDefinitions();
List<AbstractWorkflowDefinition<? extends WorkflowState>> definitions = service.getWorkflowDefinitions();
assertThat(definitions.size(), is(equalTo(1)));
assertThat(definitions.get(0).getType(), is(new SpringDummyTestWorkflow().getType()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

import com.nitorcreations.nflow.engine.internal.dao.ExecutorDao;
import com.nitorcreations.nflow.engine.service.WorkflowDefinitionService;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.AbstractWorkflowDefinition;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowState;
import com.nitorcreations.nflow.engine.workflow.definition.WorkflowStateType;
import com.nitorcreations.nflow.engine.workflow.instance.WorkflowInstance;
Expand Down Expand Up @@ -54,15 +54,15 @@ public TestDataGenerator(ExecutorDao executors, WorkflowDefinitionService workfl

public List<WorkflowInstance> generateWorkflowInstances(int count) {
List<WorkflowInstance> result = new ArrayList<>();
List<WorkflowDefinition<? extends WorkflowState>> definitions = workflowDefinitions.getWorkflowDefinitions();
List<AbstractWorkflowDefinition<? extends WorkflowState>> definitions = workflowDefinitions.getWorkflowDefinitions();
for (int i = 0; i < count; i++) {
result.add(generateWorkflowInstance(definitions));
}
return result;
}

private WorkflowInstance generateWorkflowInstance(List<WorkflowDefinition<? extends WorkflowState>> definitions) {
WorkflowDefinition<? extends WorkflowState> definition = selectRandom(definitions);
private WorkflowInstance generateWorkflowInstance(List<AbstractWorkflowDefinition<? extends WorkflowState>> definitions) {
AbstractWorkflowDefinition<? extends WorkflowState> definition = selectRandom(definitions);
DateTime nextActivation = new DateTime().minusYears(5).plusSeconds(random.nextInt(172800000)); // 2000 days
WorkflowState state = selectRandomState(definition, nextActivation);
WorkflowInstanceStatus status = selectRandomStatus(state, nextActivation);
Expand Down Expand Up @@ -92,7 +92,7 @@ private <T> T selectRandom(List<T> alternatives) {
}

@SuppressWarnings({ "unchecked", "rawtypes" })
private WorkflowState selectRandomState(WorkflowDefinition definition, DateTime instanceNextActivation) {
private WorkflowState selectRandomState(AbstractWorkflowDefinition definition, DateTime instanceNextActivation) {
if (instanceNextActivation.isAfterNow()) {
return selectRandomState(definition.getStates(), asList(start));
} else if (instanceNextActivation.isAfter(new DateTime().minusWeeks(1))) {
Expand All @@ -115,10 +115,9 @@ private WorkflowState selectRandomState(Set<WorkflowState> allStates, List<Workf

/**
* Generates actions by backtracking from the randomized current state to a start state.
*
* @param actionId
*/
private List<WorkflowInstanceAction> generateWorkflowInstanceActions(WorkflowDefinition<? extends WorkflowState> definition,
private List<WorkflowInstanceAction> generateWorkflowInstanceActions(
AbstractWorkflowDefinition<? extends WorkflowState> definition,
WorkflowState currentState, DateTime nextActivation) {
List<WorkflowInstanceAction> result = new ArrayList<>();
Set<WorkflowState> cyclePrevention = new HashSet<>();
Expand Down
Loading

0 comments on commit 7c326dd

Please sign in to comment.