This wiki is locked. Future workgroup activity and specification development must take place at our new wiki. For more information, see this blog post about the new governance model and this post about changes to the website.

Purpose

A temporary page to collect scenarios, arguments, and information needed to define states and state transitions of CM resources.

Introduction

Probably the most important property of a Change Request is the status property. "Status" specifies the location of a Change Request in a workflow. In queries the status property is used to filter change request (e.g. all change requests that are "fixed") and it is used to perform state transitions on a change request, e.g. closing a change request as "fixed".

The problem is that different CM systems use different properties (or even a set of properties, like RTC's "state" and "resolution" attributes) and different values to represent the change request's state. Even providing access to meta data does not help because knowing all possible state values does not reveal the semantics of a state.

In addition customization makes it possible to modify state value sets and workflows even further. This makes it almost impossible for another application to query or manipulate the state of a change request in a robust way.

In the following proposal we try to find a way to introduce state semantics for Change Requests. Based on this, applications can manipulate Change Requests in a "robust" way independent from the underlying CM system or any customizations that took place.

Please note that the proposal is not meant to help with creating a generic UI for manipulating the status of a Change Request.

Proposal

To address the problems from above in OSLC-CM v2 we propose to use the concept of "predicates" and "actions" instead of manipulating state properties directly via GET and PUT.

A "predicate" is basically a synthetic property representing a semantic aspect of a change request. E.g. whether a change request is "fixed" is a useful Boolean predicate for change requests. A predicate has the characteristic of a "facade" because it hides the details of where (which attribute) and how (which value) the state is represented. E.g. for RTC a "fixed" predicate would be implemented as the condition "state = resolved AND resolution = fixed". But clients would not need to know this implementation detail.

Predicates can be used like real read-only properties of a change request, so they can be specified in GET operations and queries. They can not be used in PUT or POST operations because in many cases a state transition is more involved than just changing the value of an property. E.g. depending on the process used a transition to "fixed" could enforce a verification step which would introduce additional intermediate states and require a signature. That's the reason why state transitions are performed through "actions".

Corresponding to a predicate is a set of "actions" that allow to perform a state transition on the Change Request. So for the predicate "fixed" it would make sense to provide an action "resolve to fixed" and maybe an "reopen as unfixed" action. Actions can take additional arguments. So a "resolve as duplicate" action would require a reference (URI) of another Change Request.

Since a predicate should only cover a specific aspect of a change request, we envision that OSLC-CM v2 defines a small set of predicates for different use cases. E.g. one predicate covers a fundamental but abstract state like Open and another predicate can be used to determine whether a Change Request is fixed.

Representing Predicates and Actions in a RESTful way

To keep things simple, we propose that predicates are directly mapped to a property. So in a GET operation on the Change Request the predicate's value is returned for the property.

For representing actions I see these choices:

  1. Posting the action as part of a "command" resource to a specific URL (TODO: find reference to "command" approach). The command resource contains the action, the change resource, and any additional properties that are required for the action, e.g. another change request for a "Resolve as Duplicate" action.
  2. Specifying the action as a value for an additional query-argument "action" used in a PUT (or POST) request. So if a PUT updates a changes resource, the additional action argument triggers that the specified action is performed.
  3. Using a specific URL for every action. The action URLs are available through the predicate property and the list of actions contains only those actions that are available in the current state of the Change Resource. Doing a PUT on one of these action URLs updates the resource and performs the action. (This is the HATEOAS principle. See "Level 3" in Martin Fowler's article Richardson Maturity Model: steps toward the glory of REST)
  4. Adding a new property "action" to the Change Resource. The value is the action to be performed on PUT. On GET the property "action" would not be returned.

The advantage of methods 2-4 is that any additional properties that are required for the action, can be passed quite naturally because they are already part of the resource definition, whereas in the first method, a newly introduced command resource needs to include the required properties explicitly.

Methods 2 and 4 both use additional non-obvious properties or arguments to encode "verbs". This does not align well with a RESTful approach.

The third method has the advantage over the second that no "URL path-math" is necessary and that the structure of a URL is not constrained in any way.

Since we do not see any advantage in the additional complexity of the first method, we propose that we use the third method.

Predicates

Predicates are exposed as single-value read-only properties on a Change Request resource. An attempt to update them explicitly in a partial update request SHOULD be answered with a 409 Conflict HTTP status code. Their presence in a resource representation used for an update via PUT MUST be silently ignored. Predicates MUST be queryable. The table below lists the proposed predicates. The authoritative list will be found in CmSpecificationV2.

Property Type Occurs Title Description
oslc_cm:open boolean at-most-one, readOnly Open Whether or not the resource is in an open state
oslc_cm:inprogress boolean at-most-one, readOnly InProgress? Whether or not the resource in a state indicating that active work is occurring
oslc_cm:fixed boolean at-most-one, readOnly Fixed Whether or not the resource has been fixed
oslc_cm:closed boolean at-most-one, readOnly Closed Whether or not the resource is completely done, meaning no further work is occurring
oslc_cm:approved boolean at-most-one, readOnly Approved Whether or not the resource has been approved

Dependencies: If oslc_cm:inprogress is true, oslc_cm:open must also be true

Actions

Actions are exposed as single-value 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. An attempt to update an action property explicitly in a partial update request SHOULD be answered with a 409 Conflict HTTP status code. Their presence in a resource representation used for an update via PUT MUST be silently ignored.

An Action URI has the same update semantics as the canonical resource URI. A resource can be updated by a PUT to the Action URI. It can also be updated by a partial update request via PATCH (OSLCCorePartialUpdateDRAFT) to the Action URI. Along with the update, the state transition is performed. HTTP requests other than PUT and PATCH (or a POST used with X-HTTP-Method-Override) SHOULD be answered with a 405 Method Not Allowed HTTP status code.

The CR 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 be answered with a 409 Conflict status code.

An action typically leads to a change in a predicate property. The spec doesn't guarantee any specific dependencies, however.

The table below lists the proposed actions. The authoritative list will be found in CmSpecificationV2.

Property Type Occurs Description
oslc_cm:actionResolve Resource at-most-one, readOnly Mark the resource as Resolved. Typically, the predicate oslc_cm:fixed becomes true
oslc_cm:actionClose Resource at-most-one, readOnly Mark the resource as completely done, meaning no further work is occurring. Typically, the predicate oslc_cm:closed becomes true
oslc_cm:actionStartWorking Resource at-most-one, readOnly 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 Resource at-most-one, readOnly Mark that the resource is falsely in a resolved state. Typically, the predicate oslc_cm:open becomes true

Basic Example

A CM 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/xmlns/cm/2.0#" 

  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:closed>false</oslc_cm:closed>
  <oslc_cm:approved>false</oslc_cm:approved>
  <oslc_cm:actionResolve rdf:resource="http://example.com/bugs/2314/resolve"/>
  <oslc_cm:actionStartWorking rdf:resource="http://example.com/bugs/2314/start"/>
</oslc_cm:ChangeRequest>

To change the CR's state to 'In Progress', you would update the CR using the oslc_cm:actionStartWorking action URL:

PUT /bugs/2314/start HTTP/1.1
<oslc_cm:ChangeRequest ...
  rdf:about="http://example.com/bugs/2314">
...
</oslc_cm:ChangeRequest>

After the update, 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/xmlns/cm/2.0#" 

  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:closed>false</oslc_cm:closed>
  <oslc_cm:approved>false</oslc_cm:approved>
  <oslc_cm:actionResolve rdf:resource="http://example.com/bugs/2314/resolve"/>
</oslc_cm:ChangeRequest>

Example with parameters

Actions can rely on additional properties being set in order to succeed. An example (not proposed for the OSLC-CM 2.0 spec):

Predicate:

oslc_cm:duplicate boolean at-most-one, readOnly Open Whether or not the resource is a duplicate of another resource

Action:

oslc_cm:actionResolveAsDuplicate Resource at-most-one, readOnly Mark the resource as a duplicate of another resource. Requires exactly one oslc_cm:duplicateOf property

A CM resource representation to start with:

<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/xmlns/cm/2.0#" 

  rdf:about="http://example.com/bugs/2314">

  <dc:title> Provide import </dc:title>
  <dc:identifier> 2314 </dc:identifier>
  <oslc_cm:duplicate>false</oslc_cm:duplicate>
  <oslc_cm:actionResolveAsDuplicate rdf:resource="http://example.com/bugs/2314/dupe"/>
</oslc_cm:ChangeRequest>

To resolve this CR as a duplicate of another CR, you would

PUT /bugs/2314/dupe HTTP/1.1
<oslc_cm:ChangeRequest ...
  rdf:about="http://example.com/bugs/2314">
  ...
  <oslc_cm:duplicateOf rdf:resource="http://example.com/bugs/2352"/>
  ...
</oslc_cm:ChangeRequest>

After the update, the CR resource representation looks 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/xmlns/cm/2.0#" 

  rdf:about="http://example.com/bugs/2314">

  <dc:title> Provide import </dc:title>
  <dc:identifier> 2314 </dc:identifier>
  <oslc_cm:duplicate>true</oslc_cm:duplicate>
  <oslc_cm:duplicateOf rdf:resource="http://example.com/bugs/2352"/>
  <oslc_cm:actionResolveAsDuplicate rdf:resource="http://example.com/bugs/2314/dupe"/>
</oslc_cm:ChangeRequest>

Notes

  • Should priority and severity (currently having a type of 'any' in the spec) also be exposed as predicates with fixed values like 'high', 'medium', 'low', 'unassigned'?
  • Partial update should support a no-op in order to efficiently trigger an action without modifying anything else in the resource

-- PatrickStreule - 13 May 2010

Topic revision: r12 - 20 May 2010 - 12:08:15 - SteveSpeicher
 
This site is powered by the TWiki collaboration platform Copyright � by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Contributions are governed by our Terms of Use
Ideas, requests, problems regarding this site? Send feedback