Enumerating values in a WSDL

0 Likes
When working with a SOAP based web service, the communications take place over HTTP or preferably HTTPS (so they are secure) and usually have an XML based body with information in it.

There is a language defined, WSDL, the Web Services Description Language, that is itself XML based and explains how the web service should work. It explains what the nodes are, the syntax types, and more. I rarely ever read a raw WSDL file, instead, the most common thing is to open it in a tool like Smart Bear Software's SOAP UI.

This is useful when developing a SOAP driver to communicate to some web service. You can read more about one approach to doing this, where I documented the steps involved in writing a SOAP driver to Salesforce.com in this series of articles:
Series: Getting Started Building a SOAP Driver for IDM

Another place you might use a SOAP call defined by a WSDL file is if you wanted to automate actions to the User Application. The User App has a SOAP endpoint that you can send documents into, and cause it to take certain actions. Perhaps you need to create a new Role object, or associate a Role to a Resource based on a user request. Perhaps your HR system is connected to your Identity Manager system and when a new Department code becomes available, you want to create a Role object to represent it.

Fernando Frietas, a former Novell Technical Support guy wrote a really neat shell script for Unix systems, that allows you to make these SOAP calls on the command line. You can read more and get the script here:
BASH functions to perform SOAP calls to RBPM

I wrote a bunch of articles explaining how the script works and how you could easily extend it to do more than he defined.

Enhancing the UA Bash extension for Resources
Enhancing the UA Bash extension for createRole
Series: Adding New Functions to the UA Bash extension

One other IDM related use case might be to use a Workflow, with an Integration Activity, to call the User App SOAP web service. When you explain all the steps, this seems sort of cyclical, but it does work. An event in the Identity Vault (say HR creates a new department code) cause a driver to do a Start Workflow call, with the name and information about a new Role to be created. A simple workflow is called that copies the form data into flowdata and passes it to the Integration Activity (running as part of User Application), which then makes a SOAP call back to User Application, to create a Role. Then just to be fun, perhaps you have a driver that detects the Role (object class of nrfRole) is created and then does some other activity, perhaps uses that event to trigger another workflow to create a Resource. When that is done, perhaps trigger on the Resource creation (object class of nrfResource) a Start Workflow to a workflow that calls the associateResource SOAP call. It does seem like we get into some cyclical events.

Regardless of how you are using a SOAP WSDL file, you need to understand what it says. The problem is, that often there are fields that may or may not related to obvious things. For example, sometimes the web service is developed first and then the GUI web interface is developed to consume them. But in the process, the field names get changed. Thus while the SOAP node may be called arg0, the field you would see to enter data into might be called Employee ID. How do you figure out which field in the WSDL maps to which data the application needs?

A real world example of this is the IMS Global schema for Student Information Systems (SIS) that is designed to allow an SIS to interact with a LMS (Learning Management System). The IMS Global LIS 2.0 schema seems to have gotten a lot of uptake in the industry and everyone seems to use it. However, as you can imagine, a schema, designed by committee, (and boy was it a committee) with dozens of vendors sticking their noses into it, the names of fields cannot match every case.

Vendor A may call the field Class. Vendor B may call it Course. Vendor C may call it EnrollmentInfo, and then finally the IMS Global schema may call it something else entirely. How do you map one field to the other? Well first you look for documentation, then you hope someone has posted a useful example, and finally you make an educated guess. In the case of IMS's LIS schema, they defined queries as optional, so it seems no vendors implemented it. In that case, you have to write blindly, not knowing what is there already. (Not the greatest model, in my mind). But because of that you cannot use the trick of trying the query version of the function you need to use, see what values are returned and try those values.

If you are lucky the names are obvious and easy to figure out. If you are luckier, the vendor may even document the SOAP calls well. If you are less lucky, they just compiled the web service, had it auto generate a WSDL, and it is impossible to figure out. I have worked with all three cases. Alas, the User Application WSDL is a combination of some poorly named fields, and weak documentation on the items that matter.

One area that I always found painful, was when there was a field that clearly took a value, but what is that value? A Boolean field for example. You would assume it would take a value like:
     true or false
     1 or 0
     Y or N

It is hard to know, and if there is no query function to return example values it can be very hard to figure out.

I only recently (perhaps in the last year) noticed that if you open the WSDL XML file in a text editor, you will see a node like:

 <xsd:simpleType name="RoleAssignmentActionType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="grant"/>
<xsd:enumeration value="revoke"/>
<xsd:enumeration value="extend"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="RoleAssignmentActionType" type="tns:RoleAssignmentActionType"/>


I grabbed that example above from the Role service WSDL from the User App. They used to expose links to download the WSDL files in the User App administrative interface in the RBPM (Roles Based Provisioning Module) configuration section, but I think that is going away. Regardless, one of the available web services was not listed, so you needed to know how to get it regardless, via a URL.

Go to https://Your.UserApp.domain.com/IDMProv/role/service?WSDL to get a page you can save as the WSDL file. No authentication needed. Insert the proper base URL for your User Application as well as proper port as makes sense. Also, the string 'role' in the URL can be replaced with 'resource', 'notification', or 'provisioning' to get to the proper SOAP endpoint and thus web service. This is one of those where you have to know about the end point to ask for it situations. It helped when the User App UI had buttons to download the WSDL files. But as noted before at least one was missing. (I actually forget which one that is now).

What that XML snippet tells me is that the RoleAssigmentActionType field syntax is thus defined, and has three possible values, grant, revoke, and extend. (That by the way is how I learned you can extend a Role Grant to a user instead of just removing the old one, and re-adding it with a new expiration date. It is amazing what you can find spelunking through text files).

This is great since it tells you the allowed values. Now I always open my WSDL files in SOAP UI, and I had never seen this information in there before, which caused me a lot of pain over the years. I am sure this is obvious to some, but this came as news to me, that the information was in the WSDL.

What is also nice is that in most cases where I have looked, the type definitions are available at the top of the file, which means they are often the first things you will see. As I think back on this, I realized, that I had seen a snippet like this posted in the forums by one of the developers years ago, but did not recognize it at the time. This is one of those cases, where just a tiny bit more information would really have helped me a great deal. The developer posted the snippet, but did not explain where it came from. I.e He handed me a fish, but did not teach me how to fish. Alas. I do wish I had known this years earlier.

When I open the Role web service WSDL file from User Application in SOAP UI, it shows me a bunch of API calls it supports. One of which is requestRoleAssignmentRequest().

SOAP UI renders it from the information in the WSDL to look like this:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://www.novell.com/role/service">
<soapenv:Header/>
<soapenv:Body>
<ser:requestRolesAssignmentRequest>
<!--Optional:-->
<ser:assignRequest>
<ser:actionType>?</ser:actionType>
<ser:assignmentType>?</ser:assignmentType>
<ser:correlationID>?</ser:correlationID>
<ser:effectiveDate>?</ser:effectiveDate>
<ser:expirationDate>?</ser:expirationDate>
<ser:identity>?</ser:identity>
<ser:originator>?</ser:originator>
<ser:reason>?</ser:reason>
<ser:roles>
<!--Zero or more repetitions:-->
<ser:dnstring>
<ser:dn>?</ser:dn>
</ser:dnstring>
</ser:roles>
<ser:sodOveridesRequested>
<!--Zero or more repetitions:-->
<ser:sodjustification>
<ser:justification>?</ser:justification>
<ser:sodDN>?</ser:sodDN>
</ser:sodjustification>
</ser:sodOveridesRequested>
</ser:assignRequest>
</ser:requestRolesAssignmentRequest>
</soapenv:Body>
</soapenv:Envelope>


The problem is, what value goes in actionType. That is clearly expecting something specific. Prior to finding out that the information was in the WSDL I would look for documentation that would explain it. Or perhaps Google search for an example to learn from. This is also part of why I like to write about the SOAP end points that User App exposes, since they seem so hard to understand.

Now the good news is, you get some information about what can go in a node, at least in the context of child nodes, where you see XML comments like this:

<!--Zero or more repetitions:-->


This is important, since if this is not shown, you should send the node empty if you have no value, not absent. When Zero or more repetitions are allowed you can send it without the indicated child nodes entirely.

I was recently explaining all this to a colleague who is working on integration activities in a workflow (Hey Dixit!) and realized that SOAP UI must show this information somehow. I never did figure out how to turn that on, or look it up, so I finally decided to push through and really try to figure it out, and I finally did. (I was very happy, I think I confused poor Dixit as to why this silly little thing was so exciting).

It turns out, if you go to the File menu (I tried in 5.0 and 5.2 of SOAP UI and it is basically in the same place, just some bits look different) and select Preferences.

Go to the WSDL Settings tab. There is a field, labeled, "Type comment" and it has a further explanation of "Generate comments with type information in new requests".

Simply enable this, and things change when you next create a request.

A quick summary of those steps could be:
File, Preferences, WSDL Settings, Type comment: "Generate comments with type information in new requests"

Now if the project has been opened in SOAP UI already, then it has already generated all the request documents, and for each one you wish the new format, you would have to right click and select New Request, which will create a Request2 object. Conversely it might be easier to delete the project and just re-open it with this new setting. This way all your requests have the extra information.

Here is an example of the requestRolesAssignment() function call, with the extra comment with type information.


<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://www.novell.com/role/service">
<soapenv:Header/>
<soapenv:Body>
<ser:requestRolesAssignmentRequest>
<!--Optional:-->
<ser:assignRequest>
<!--type: RoleAssignmentActionType - enumeration: [grant,revoke,extend]-->
<ser:actionType>?</ser:actionType>
<!--type: RoleAssignmentType - enumeration: [USER_TO_ROLE,GROUP_TO_ROLE,ROLE_TO_ROLE,CONTAINER_TO_ROLE,CONTAINER_WITH_SUBTREE_TO_ROLE]-->
<ser:assignmentType>?</ser:assignmentType>
<!--type: string-->
<ser:correlationID>?</ser:correlationID>
<!--type: dateTime-->
<ser:effectiveDate>?</ser:effectiveDate>
<!--type: dateTime-->
<ser:expirationDate>?</ser:expirationDate>
<!--type: string-->
<ser:identity>?</ser:identity>
<!--type: string-->
<ser:originator>?</ser:originator>
<!--type: string-->
<ser:reason>?</ser:reason>
<ser:roles>
<!--Zero or more repetitions:-->
<ser:dnstring>
<!--type: string-->
<ser:dn>?</ser:dn>
</ser:dnstring>
</ser:roles>
<ser:sodOveridesRequested>
<!--Zero or more repetitions:-->
<ser:sodjustification>
<!--type: string-->
<ser:justification>?</ser:justification>
<!--type: string-->
<ser:sodDN>?</ser:sodDN>
</ser:sodjustification>
</ser:sodOveridesRequested>
</ser:assignRequest>
</ser:requestRolesAssignmentRequest>
</soapenv:Body>
</soapenv:Envelope>


The two big differences are the two where it is non-obvious what values should go there. A DN field, is obviously a DN. It would be nice if the <identity> node and the <originator> node would clarify if they are expecting a DN or a string. (I always forget, one is a DN, I think Identity, and originator, oddly enough is just a string).

We thus see that the RoleAssignmentActionType is grant, revoke, or extend. The RoleAssignmentType is much more interesting and all specific strings.
USER_TO_ROLE
GROUP_TO_ROLE
ROLE_TO_ROLE
CONTAINER_TO_ROLE
CONTAINER_WITH_SUBTREE_TO_ROLE

Thus if you wanted to build a hierarchy of Roles, you would actually use this function, but specify ROLE_TO_ROLE as the assignmentType. Which is slightly inconsistent with what you might have expected. I still do not know if there is any additional magic that happens, that just writing the proper values in nrfChildRole and nrfParentRole on the Level 20 roles would miss, but I have been informed over and over, that it is not supported if done in that direct manner, so use the SOAP call please.

As you can see, finding this silly little setting in SOAP UI has rocked my world. So much so I have been going back over other SOAP projects I have worked on in SOAP UI where I had trouble finding the proper string values to see if they were all there sitting in the WSDL without my knowing it all along.

Labels:

How To-Best Practice
Comment List
Anonymous
Parents Comment Children
No Data
Related Discussions
Recommended