State Transitions for Change Requests
Early Working Draft This is used to explore how to support state transitions for CM ChangeRequest resources for a couple of scenarios. In being under development, it is NOT recommended
Motivation
One of the more important properties of a Change Request is the state property. "State" specifies the location of a Change Request in a workflow.
Since different Change Request service providers use different properties (or even sets of properties) and different values to represent the Change Request's state, it is almost impossible for another application to programmatically query or manipulate the state of a change request in a robust and predictable way. This becomes even more problematic if customization allows to modify state value sets and workflows even further.
Therefore we've introduced the concept of "State Predicates" in OSLC-CM v2. A State Predicate is a stable and well defined facade that represents an important state of a Change Request. It can be used like an ordinary (but read-only) attribute of type boolean. State Predicates are read-only for two reasons: first, it is difficult to turn a change of a (boolean) predicate unambiguously into a corresponding state transition of the Change Request. Secondly, in many service providers the state attribute underlying the predicate is read-only.
Since predicates are read-only, it is not possible to modify a predicate in order to trigger a state transition of the Change Request. So we need a mechanism that allows us to initiate a state transition in a way that is similarly stable and well defined as State Predicates.
Ussage scenarios support:
- CmOfRequirements
- Requires the typical usage of a "head-less" operation
- One case, user is finished working (resolving CRs) (see cm:actionResolve). Would be ideal to ask for reviewers to be added (this case could use delegated)
- Another case, user "applies" the changes and closes CR (see cm:actionClose). Not typical that additional info is passed/needed with the action.
- ITOpsToDev
- Limited to notification like scenaios
- Development has delivered a fix for a defect, associated ticket is "marked fix is ready". Is this a state transition or just a simple field is updated?
- Typically is head-less
- IDE Integration
- Rob will provide actions desired
- Head-less highly desired, not many have collected much data.
- Would be good to move CR status based on desired end state, without regard to immediate next states.
- Need for metadata on action - SofiaYeung
- when closing, it would be good to collect additional data for duplicate (dup of what) or more info needed (for example a list of reasons). Rob sees this need as well.
Proposal
Our approach is to introduce the notion of "Actions". An action is a "verb" that can be applied to a Change Request in order to trigger a state transition.
We see basically two usage styles for Actions:
- Programmatic use to perform a specific state transition:
E.g some integration code needs to bring a Change Request into the "Ready for Review" state. For this an action with clearly defined semantics needs to exist in the spec. It is not possible to programmatically "find" these actions by using any kind of meta information (aka Shapes). This is similar to the predefined State Predicates.
To simplify programmatic use of these actions, action execution should be as tolerant as possible with respect to their preconditions. So if a Change Request is in a state that normally does not allow the immediate execution of the desired state transition, but requires an intermediate state first, Actions should be as "lenient" as possible, and introduce the necessary intermediate state transitions automatically behind the scenes.
- Building a generic UI for all Actions supported by the Change Request:
In this case the semantics of the individual actions doesn't really matter since an end user selects an action by name (and is expected to understand its meaning). Typically these actions correspond to the state transitions used in the underlying service provider. Two variants are possible:
- The "Delegated UI" Approach:
Here all aspects of performing a state transition is delegated back to service provider. This includes presenting the actions that are allowed in the current state of the change request, collecting optional parameters that are required before the selected state transition can take place, and presenting any errors that might occur as a result of the state transition.
- The "Interpret Meta Information" Approach:
Here a generic UI for selecting actions is constructed based on meta information provided by the Change Request. Since this is expected to cover the same aspects as in the Delegated UI approach, it puts considerable implementation burden on clients.
For the first use case we propose to introduce predefined actions into the OSLC specification (similarly to what has been done for the State Predicates). Here are some example actions:
Action |
Description |
oslc_cm:actionResolve |
Mark the resource as Resolved. Typically, the predicate oslc_cm:fixed becomes true |
oslc_cm:actionClose |
Mark the resource as completely done, meaning no further work is occurring. Typically, the predicate oslc_cm:open becomes false |
oslc_cm:actionStartWorking |
Mark the resource as 'In Progress', meaning that the resource is actively being worked on. Typically, the predicate oslc_cm:inprogress becomes true |
oslc_cm:actionReopen |
Mark that the resource is falsely in a resolved state. Typically, the predicate oslc_cm:open becomes true |
Both variants of the second use case could be easily covered by existing OSLC concepts: Delegated UI and Resource Shapes.
Syntax
Here is a proposal how to represent Actions.
Actions are exposed as single-valued read-only properties of type Resource in a Change Request resource. The URI of such a reference property ("Action URI") points to the resource that handles the state transition. A resource can be updated by a HTTP POST to the Action URI. The request body of the HTTP POST MUST contain the resource URI that the transition will be applied. The request body MAY contain additional property values to be updated along with the state transition via the action. A HTTP GET on the action URI SHOULD return information about that action (TBD define this action descriptor).
The Change Request resource representation
SHOULD only include the actions that are applicable to the current state of the resource. If an action is performed and the precondition for a state transition is not met, the request
MUST respond with a 409 Conflict status code.
An attempt to update an action property explicitly in a PUT or PATCH request
SHOULD be answered with a 409 Conflict HTTP status code. Their presence in a resource representation used for an update via PUT
MUST NOT prevent the resource from being updated.
Basic Example
A change request resource representation with actions and predicates:
<oslc_cm:ChangeRequest
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/terms/"
xmlns:oslc_cm="http://open-services.net/ns/cm#"
rdf:about="http://example.com/bugs/2314">
<dc:title> Provide import </dc:title>
<dc:identifier> 2314 </dc:identifier>
<oslc_cm:open>true</oslc_cm:open>
<oslc_cm:inprogress>false</oslc_cm:inprogress>
<oslc_cm:fixed>false</oslc_cm:fixed>
<oslc_cm:approved>false</oslc_cm:approved>
<oslc_cm:actionResolve rdf:resource="http://example.com/bugs/action/resolve"/>
<oslc_cm:actionStartWorking rdf:resource="http://example.com/bugs/action/start"/>
</oslc_cm:ChangeRequest>
To change the CR's state to 'In Progress', you would transition the CR by POST'ing to the
oslc_cmx:actionStartWorking
action URL:
POST /bugs/action/start HTTP/1.1
<oslc_cm:ChangeRequest ...
rdf:about="http://example.com/bugs/2314">
...
</oslc_cm:ChangeRequest>
After the request, the CR resource representation will look like
<oslc_cm:ChangeRequest
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/terms/"
xmlns:oslc_cm="http://open-services.net/ns/cm#"
rdf:about="http://example.com/bugs/2314">
<dc:title> Provide import </dc:title>
<dc:identifier> 2314 </dc:identifier>
<oslc_cm:open>true</oslc_cm:open>
<oslc_cm:inprogress>true</oslc_cm:inprogress>
<oslc_cm:fixed>false</oslc_cm:fixed>
<oslc_cm:approved>false</oslc_cm:approved>
<oslc_cm:actionResolve rdf:resource="http://example.com/bugs/action/resolve"/>
</oslc_cm:ChangeRequest>
A GET request on a action URI SHOULD reveal additional information about the action.
GET /bugs/action/resolve HTTP/1.1
<oslc_cm:Action
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/terms/"
xmlns:oslc="http://open-services.net/ns/core#"
xmlns:oslc_cm="http://open-services.net/ns/cm#"
rdf:about="http://example.com/bugs/action/resolve">
<dc:title>Resolve</dc:title>
<dc:description>Indicates work is complete on the change request.</dc:description>
<oslc:resourceShape rdf:resource="http://example.com/bugs/action/resolve/shape"/>
</oslc_cm:Action>
Resource: Action
Prefixed Name |
Occurs |
Read Only |
Value-type |
Representation |
Range |
Description |
dcterms:title |
exactly-one |
true |
XMLLiteral |
N/A |
N/A |
Title (reference: Dublin Core) of the action |
dcterms:description |
zero-or-one |
true |
XMLLiteral |
N/A |
N/A |
Description (reference: Dublin Core) of the action |
oslc:resourceShape |
zero-or-many |
true |
Resource |
Reference |
oslc:ResourceShape |
Resource Shape that provides hints as to resource property value-types and allowed values. |
Supporting material
*
Experimental State Transition proposal
Outstanding Items
- Look at GET on the action URI.
- Explore delegated UIs for state transitions.
ToDo?
These are the items needed to complete the work on state predicates.
- Work through "Outstanding Items" section
- Elaborate and prioritize the scenarios we really need to support: programmatic, delegated, etc. (See CmMeetings20120215.)
- Put in references to various alternatives that are discussed for RESTful state transitions, like: REST by Design, etc.
- Complete "Other approaches considered" with pros and cons, why cons are bad to make that list
- Flush out current approach, adding references to previous work
- How best to define actions:
- have a multi-valued property oslc_cm:action ?
- having scenario specific property like oslc_cm:actionResolve ?
- define the "kind" of action by using a specialized oslc_cm:ActionResolve ?
- identify the "kind" of action by using a predicate such as oslc:usage oslc_cm:actionResolve ?
- or a combination of any of the above? Use both cm:action and cm:actionResolve and the object would be the same URI. Generic clients would know what cm:action meant. Smarter clients would know the additional semantics of cm:actionResolve
- Resolve differences in Experimental State Transition proposal
Other approaches considered
Identify what alternatives were considered and why the proposed solution is preferred.
1. Using PUT to transition the state on a specialized action URI
Similar to current proposal, only using PUT rather than POST.
Cons:
- PUT semantics imply that you're updating the action itself rather than the change request (e.g., PUT /bugs/actions/startWorking implies that you're modifying the start working action). In other words, what you send in the request body has to be made available at the request URI.
POST, on the other hand, does not have these restrictions. See
http://tools.ietf.org/html/rfc2616#section-9.5.
2. Using PUT to update the resource and just modify the state predicates, making the server map what that means to current action mode
Pros:
- Simple
- Builds on existing state predicate design in OSLC-CM 2.0.
Cons:
- Often more than one action can lead to a particular state predicate value. It's not clear which action the provider should use.
- No way to express what fields are required to move to this state (e.g., using shapes) or other information about actions.
3. Creating a new state predicate which has multiple values which could be standardized - then using PUT to just update that property (say oslc_cm:state )
Pros:
Cons:
- Breaks with previous design. Concerns about backwards compatibility.
- Multiple actions might lead to a particular state. (Same problem as with 2 above.)
- Multiple "real" states in a particular change management provider might map to the standard OSLC state values.