Friday 5 June 2015

OSLC DXL Services

One of the primary strategies of the IBM Rational division is to continually improve upon the integration capabilities of Rational and non-Rational products.
Keystone to this strategy is Open Services for Lifecycle Collaboration (OSLC). 
However a common complaint heard from providers / consumers of OSLC functionality is that there can be certain business problems that cannot be addressed because they rely on data and/or functionality that are (a) not currently available in the implemented standard or (b) considered too specialized for inclusion in the standard and therefore not planned for future versions.
Yet all is not lost and as OSLC service discovery is extensible it is possible to add services to help close such gaps. 
An excellent example of this can be seen in the introduction of OSLC DXL Services to Rational DOORS.

What are OSLC DXL Services?

Put simply they are an extension to the Rational DOORS OSLC RM V2 interface which allows users to execute Rational DOORS DXL scripts safely and securely across HTTPS.

Yes you can run DXL scripts from DWA! Well not all DXL scripts you have of course and only those registered by Administrator as OSLC DXL service but still this gives your project new possibilities and powers.

What makes DXL Script a OSLC DXL Service?

If you looked at IBM OSLC DXL Service introduction you came across helloWorld.inc:

void getHelloString(string language)
{
    string hello = null
    if ("French" == language) {
        hello = "Bonjour le monde" 
    }
    else if ("Finnish" == language) {
        hello = "Hei maailma"
    }
    else if ("Latin" == language) {
        hello = "Ave mundi" 
    }
    else {
        hello = "Hello world" 
    }

    setDxlServiceResult hello
    print hello "\n" 
}
If you are familiar with DXL you can spot setDxlServiceResult PERM. That is exactly what will set value of hello as the result of the service.

Registering DXL Service

Currently DOORS Database Administrator has to add those services manually using DOORS Perms.

OSLCDXLService os = null
string err = null
string dxlCode = "#include <addins/services/helloWorld.inc>"
err = addOrUpdateOSLCDXLService("helloWorld", "Hello world in several languages", dxlCode, "getHelloString")
if (!null err){
      print err
} else {
      print "Installed Service\n"
}

Quick PERM reference (as it's not yet documented in DOORS DXL Reference Manual)

void setDxlServiceResult(string s)
sets s as the result for DXL Service

string addOrUpdateOSLCDXLService(string n, desc, dxlcode, entryPoint) 
registers dxlcode as the service with name n and description desc. entryPoint specifies the function in dxlcode to be run as entry point of service.

To make life easier OSLC DXL Services management will be soon available in File menu in IBM DOORS client.


Call OSLC DXL Service

Once you have your service registered you can send GET and PUT requests.
Set both the accept and content-type headers to this entry: application/rdf+xml and submit:
 
  • GET request for the DXL service description.
  • PUT request with optional parameters to invoke the service.

helloWorld service registered above could be accessed with URI like https://servername:portnumber/dwa/rm/dxl/helloWorld

As you notice before helloWorld function takes one parameter which should be supplied. You can provide parameters for DXL Services with aid of request content:


<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:doors="http://jazz.net/doors/xmlns/prod/jazz/doors/2.0/">
  <doors:Arguments>
  <doors:arguments>French</doors:arguments>
  </doors:Arguments>
</rdf:RDF>

If you have more then one argument, separate those with comas ','. All arguments are passed to DXL service as strings. If you need to have other types use DXL conversions in your service.


The results


Once DXL Service will finish its operation DWA server will return response with a content in following form:

  dwaOauth.js
was used to GET only protected information from DWA. But calling OSLC DXL Services requires PUT request which should be added.

There's nothing easier:

exports.getDXLServiceResult = function(req, res, dxlService, lang, next, onError) {
    var oa = new OAuth(req.session.oa._requestUrl,
              req.session.oa._accessUrl,
              req.session.oa._consumerKey,
              req.session.oa._consumerSecret,
              req.session.oa._version,
              req.session.oa._authorize_callback,
              req.session.oa._signatureMethod);

        // Try to get protected data
        var post_body = '<?xml version="1.0" encoding="UTF-8"?><rdf:RDF    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"    xmlns:doors="http://jazz.net/doors/xmlns/prod/jazz/doors/2.0/">'
        post_body += '<doors:Arguments><doors:arguments>' + lang +'</doors:arguments></doors:Arguments></rdf:RDF>';

        oa._headers['accept'] = "application/rdf+xml";

        var host = url.parse(location);
        console.log('requesting service ' +host.protocol+"://"+host.host+'/dwa/rm/dxl/'+dxlService + ' with param: '+lang);

        oa.put(host.protocol+"//"+host.host+'/dwa/rm/dxl/'+dxlService,
            req.session.oauth_access_token,
            req.session.oauth_access_token_secret,
            post_body, 
            'application/rdf+xml',
            function (error, data, response) {
                if (!error && next) {
                    next(req, res, data);
                }
                else if (onError) {
                    onError(error);
                }
            }
        );
}

And that's it!.

21 comments:

  1. Hello Andrezej,

    Thanks for your post!!! I try to use OSLC-DXL service as you explain, but the return of helloWord script is:

    <?xml version="1.0"?>
    <rdf:RDF
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:doors="http://jazz.net/doors/xmlns/prod/jazz/doors/2.0/">
    <doors:DxlServiceResult rdf:about="http://dwaserver:port/dwa/rm/dxl/helloWorld">
    <doors:result rdf:parseType="Literal"&gtdxlServiceResult: uninitialised</doors:result>
    </doors:DxlServiceResult>
    </rdf:RDF>

    What "dxlServiceResult: uninitialised" means?

    ReplyDelete
    Replies
    1. Hi Carlos,
      Please check your service DXL code and see if you set setDxlServiceResult

      Delete
    2. I set it as the dxl script example

      Delete
    3. check "Function Name" in File->OSLC->DXL Services if it is the same as the entry function in your DXL script.
      Or (if you have older DOORS) run:
      OSLCDXLService service
      for service in database do
      {
      print service.name", " service.description", "service.functionName"\n"
      }

      and confirm service.functionName matches the entry point

      Delete
    4. Thanks Andrzej,

      I use the 9.5.1 version. So, I execute your script and I get the following result:

      helloWorld, Hello world in several languages, #include

      service.functionName corresponds to the entry point, but the same result is returned.

      Thanks for your help


      Delete
    5. Hi Carlos,

      Your service.functionName is "#include" and that's the problem. If you used script above it should be "getHelloString"

      Open Tools->Edit DXL and run:
      OSLCDXLService os = null
      string err = null

      string dxlCode = "#include \n"
      err = addOrUpdateOSLCDXLService("helloWorld", "Hello world in several languages", dxlCode, "getHelloString")
      if (!null err)
      {
      print err
      }

      make sure the dxlCode point to existing file
      Thanks

      Delete
    6. sorry blogger removed < and > from line with
      #include <addins/services/helloWorld.inc>"

      Delete
    7. Yes, that was my problem ;)

      any idea?

      Delete
    8. have you re run addOrUpdateOSLCDXLService?

      Delete
    9. Andrzej, I found the problem!!!

      It was the service call. I use net.oauth library to access to OSLC-DXL services and my call did not have the configured body, I sent it as parameter!!!

      So, now I send the XML file as body and it works!!!!

      Thanks, thanks for your help!!!!

      Delete
    10. I'm happy you solved your problem!

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. yes, I got the same ;)
      but "#include <addins/services/helloWorld.dxl> " (or actual code loaded) should be service.dxlString, not a service.functionName

      Delete
    2. In fact, when I execute:
      OSLCDXLService service
      for service in database do
      {
      print service.name", " service.description", "service.functionName", "service.dxlString"\n"
      }

      the return is:
      helloWorld, Hello world in several languages, #include <addins/services/helloWorld.dxl>, #include <addins/services/helloWorld.dxl>


      Delete
  3. Hi Andrzej,

    Is there a function to remove OSLC-DXL services, such as "addOrUpdateOSLCDXLService" for adding?

    Thanks

    ReplyDelete
    Replies
    1. Hi Carlos,

      Yes, there are two perms (functions) to remove service (from DXL manual):
      removeOSLCDXLService(string key)
      - The function “removeOSLCDXLService(string key)” removes a service from the configuration. Finds the service by its key (that is, name).

      removeOSLCDXLService(OSLCDXLService service)
      - The function “removeOSLCDXLService(OSLCDXLService service)” removes a service object from the configuration.

      Do not ask my why DXL Help in only in PDF(!) these days but you can find it here:
      http://www-01.ibm.com/support/knowledgecenter/SSYQBZ_9.6.1/com.ibm.doors.requirements.doc/topics/dxl_reference_manual.pdf

      Delete
  4. Thanks!!!

    I have the 9.6 version of DXL manual and it does not contain this information.

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. uh, delted :)
      noError
      move (o below p)
      setDxlServiceResult lastError

      this might help understanding the problem you had

      Delete
  6. Hi,

    How do you call the dxl program via java code?

    Is there any sample codes are available?

    Thanks in advance.

    ReplyDelete
    Replies
    1. Hi Shan,

      use DOORS COM API, see https://www.ibm.com/developerworks/community/forums/html/topic?id=77777777-0000-0000-0000-000014458173&ps=25
      that's C# but you can use Java Jacob Project to achieve the same.

      Thank you

      Delete

Note: only a member of this blog may post a comment.