BroadleafCommerce/BroadleafCommerce — pull request #35 by phillipuniverse (2013-03-26 21:50:35+00:00)
Title: Making Workflows Better

This will also serve as step 1 of documentation and drive further discussions.

## Activity Configuration
Each Activity is configured to have an 'order' property, and now `Activity` will implement Spring's `Ordered` interface:

```java
public interface Activity extends BeanNameAware, Ordered
...
public abstract class BaseActivity {
...
//activities that do not explicitly override this will go at the end
protected int order = Ordered.HIGHEST_PRECEDENCE;

public int getOrder() {
return order;
}

public void setOrder(int order) {
this.order = order;
}
...
```

## `SequenceProcessor` Configuration
The `BaseProcessor` (from which `SequenceProcessor` extends) will now sort the lists based on Spring's `OrderComparator.INSTANCE`, which will be invoked during `afterPropertiesSet()`. This has the advantage of sorting in-place as well:
```java
@Override
public void afterPropertiesSet() throws Exception {
OrderComparator.sort(activities);
}
```

## Framework Activities
The ordering defined for each Activity will use the '1000' range (1000, 2000, 3000, etc). This configuration would look like this as defined in bl-framework-applicationContext-workflow (this is the blPricingWorkflow):
```xml

```

## Module Activities
Modules will use the 100 range to insert themselves in-between framework activities. For instance, the `addItemWorkflow` bean definition in the inventory module looks like this today:
```xml

```
This can now be refactored to something much much simpler:
```xml

```

## Edge Cases
### 1. What if you want to replace a framework activity?
> Since all Activities will now be bean references, you should be able to redeclare as necessary

### 2. What if you want to change the ordering of a framework activity?
> The p:order elements should **not** undergo the merge process and thus will not be overridable in a project-specific applicationContext. This is preferred as there shouldn't really be a case for them doing that. However, if they REALLY want to override it, they can simply replace the bean definition and return whatever they want for the `getOrder()` method in that replaced activity

### 3. What if a client configures an activity with the same order that we have in the framework or an additional module?
> An exception will be thrown and startup will be suspended. This could potentially be a configurable property within a `SequenceProcessor` (much like the sequence corruption detection) but users should not attempt to step on additional activities. If they want to override, they can just override the bean reference. If the user configures turns off this detection, then the activities will be ordered in the order they are defined in the application context merge

### 4. What if 2 modules configure activities in the same order? *(this is a very likely occurrence in a multi-module environment)*
> Same as 3. The user will have to go in and explicitly set the ordering of the activities. This sucks because you'd have to subclass each activity to provide their own relative order. Could you do this with XML? Perhaps if you redeclared the activity bean and provided the 'p:order' attribute it would just override it.

## Problems With the Approach
1. The response to item 4 of the 'Edge Cases' section is very kluge. In order to really accomplish this, the user would have to subclass the bean definition of both of the module activities and then provide ordering for both of them
2. Simply setting an 'order' property and skipping by defined increments seems too 'loose' of a paradigm. Perhaps investing the extra time into how Spring orders security filters ('before', 'after', etc).