Projects‎ > ‎

SPML2

SPML2 Service Design

SPML2 OpenPTK Service

A service was created for OpenPTK which was tested against Oracle Waveset (formerly Sun Identity Manager). This service uses the Oasis OpenSPML2 java library. This service met the needs of integration with Sun Identity Manager, however, several issues were found when testing this with other vendors SPML2 servers. These issues were related to the oasis openspml2 implementation. Due to these issues, extending the openspml2 to enable configuration changes of the default behaviour is being considered.


A Facade for the Spml2Client Class

The Spml2Client is the "main" class/interface that Java developers use to implement SPML2 functionality. The default JDK (OASIS), available here, may not meet vendor specific requirements. A vendor may extend this class or change how the class is used.
Because of this, the various implementations of the Spml2Client class will be "abstracted" with a OpenPTK facade-pattern interface called ClientFacadeIF. An abstract class called ClientFacade implements the ClientFacadeIF interface and provides common method implementations. A number of feature specific classes are being created to address the differences between the various implementations of Spml2Client:

Class Name Facade For
ClientFacadeOASIS org.openspml.v2.client.Spml2Client
ClientFacadeOpenPTK org.openptk.openspml.v2.client.OpenPTKSpml2Client
ClientFacadeWaveset com.sun.idm.rpc.spml2.SessionAwareSpml2Client

The ClientFacadeIF interface has the following methods:

   public void init(String url) throws Spml2Exception;

   public void init(String url, String username, String password) throws Spml2Exception;

   public void init(String url, String username, String password, String proxyHost, int proxyPort) throws Spml2Exception;

   public Response send(Request req) throws Spml2Exception, Spml2ExceptionWithResponse;

   public String sendRequest(Request req) throws Spml2Exception;

   public String send(String xml) throws Spml2Exception;

   public void setMonitor(RPCRouterMonitor m);

   public void setTrace(boolean b);

   public void setSOAPAction(String action);

When the Operations class initializes, it will look for a property called client.classname. The class must implement the ClientFacadeIF interface. The Operations instance will create an object using the classname then call the class's init() method.


Oracle Identity Manager (OIM)

The Oracle Identity Manager (OIM) supports SPML2. The SPML2 features have been tested with OIM version 9.1.0.2 deployed to Weblogic. The SPML2OIMOperations class extends the SPML2Operations class to support the following provisioning operations:

  • Create
  • Read
  • Update
  • Delete
  • Search
  • Password Change
  • Password Reset

The SPML2OIMOperations class uses the ClientFacadeOpenPTK class to access the SPML2 Client implementation.


Oracle Waveset (formerly Sun Identity Manager)

The Oracle Waveset provisioning product support SPML2. The SPML2 features have been tested with Waveset version 8.1 deployed to Glassfish. The SPML2WavesetOperations class extends the SPML2Operations class to support the following operations:

  • Create
  • Read
  • Update
  • Delete
  • Search
  • Password Change
  • Password Reset

The SPML2WavesetOperations class uses the ClientFacadeWaveset class to access the SPML2 Client implementation.

Issues found with the spml2 library

  1. Invalid Attribute Name validation
    private static final String REGEX =
    "((([0-2](\\.[0-9]+)+)|([a-zA-Z]+([a-zA-Z0-9]|[-])*))(;([a-zA-Z0-9]|[-])+)*)";
  2. Proper Handling of null attribute values (avoid NPE)
  3. XML Namespace prefix handling
  4. Allow for search filters wrapping in an and filter so that vendorX will accept the filter . For example:

Here is what vendorX server wants:

<and>
<dsml:filter>
<dsml:equalityMatch name="Users.Last Name">
<dsml:values>Walsh</dsml:values>
</dsml:equalityMatch>
</dsml:filter>
<dsml:filter>
<dsml:equalityMatch name="Users.Xellerate Type">
<dsml:values>End-User</dsml:values>
</dsml:equalityMatch></dsml:filter>
<dsml:filter>
<dsml:equalityMatch name="Object Class">
<dsml:values>Users</dsml:values>
</dsml:equalityMatch>
</dsml:filter>
</and>

Here is what the openspml APIs produce, by default:

    <dsml:filter xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core'>
      <dsml:and>
        <dsml:equalityMatch name='lastname'>
          <dsml:value>Proxy</dsml:value>
        </dsml:equalityMatch>
        <dsml:equalityMatch name='firstname'>
          <dsml:value>RM</dsml:value>
        </dsml:equalityMatch>
      </dsml:and>
    </dsml:filter>
  1. DSMLvalues plural - VendorX expects all DSMLvalues to be plural, even if there is only a single value. openspml apis (Oracle Waveset expects a the singular of value if there is only one, and the plural if there are more than one.)

VendorX wants:

<dsml:values>End-User</dsml:values> 

Here is what the openspml APIs produce, and SIM uses:

<dsml:values>End-User</dsml:values> 
  1. SPML SOAP Response wrapper

Proposed Solution

The openspml2 toolkit will be added to our repository. This will provide a baseline for a version of the toolkit that we will maintain to add some configuration setting to the api which are not possible without our own codebase. We will attempt to contribute all our changes back to the community in order to integration the configuration enhancement for others.

This is primarily to support a specific vendors implementation of SPML2. The plan is to make the changes configurable through an openptk service in order to coexist with the current spml2 service implementation.

The code will be placed in:

trunk/openptk/ext/Misc/SPML2/src/java

This will initially be the oasis code, then the changes to allow the configurability we need will be added on top of it. The oasis openspml2 source is CDDL based so we will need to include the license for that, which I will do. We are also required to leave the headers in the files we modify and add additional comments for any changes, which I will do.

License

https://openspml.dev.java.net/

New Classes

Name Description
OpenPTKSpml2Client.java Client implementation which will call all other openspml2 apis.

This class should be used instead of the default Spml2Client class. It supports the same "methods" so it should work just like the other class. There was no value in "extending" because too many internal methods needed to be changed. Merged logic that was in Spml2Client and SimpleSOAPClient into this one class. The class assembles the required vendorX SOAP Header and SOAP Body sections. It uses the setUser() and setPassowrd() methods (or constructor) to obtain the user data, which is used in the SOAP Header. In addition to "wrapping" the SPML2 Requests with "<m:processRequest...>" This class has to also unwrap a returned "<m:processRequesstResponse>" XML Element. If this is not done, the XML Marshallers fail because they are expecting a "pure" DSML/SPML2 payload.

Add and "strip" the <m:processRequestResponse> tag from around the SPML2 request and response

Openspml2 Source files affected:

Name Package
AttributeDescriptionValue.java org.openspml.v2.profiles.dsml
BasicFilter.java org.openspml.v2.profiles.dsml
DSMLAttr.java org.openspml.v2.profiles.dsml
FilterSet.java org.openspml.v2.profiles.dsml
DSMLModification.java org.openspml.v2.profiles.dsml
DSMLValue.java org.openspml.v2.profiles.dsml
NamedItem.java org.openspml.v2.profiles.dsml
XmlBuffer org.openspml.v2.util.xml
OpenPTKReflectiveXMLMarshaller org.openspml.v2.util.xml
OpenPTKSpml2Client org.openptk.openspml.v2.client

OpenPTK-Service-SPML2.jar

Used by:  
SVN dir: trunk/openptk/ext/Service/SPML2
Java source: ${dir}/src/java
Notes: Implements the spi interfaces for ServiceIF and OperationsIF
Package Name Description Action Status
org.openptk.spi Service interface move SPML2 code from "Framework" JAR  
org.openptk.spi.operations Operations interface move SPML2 code from "Framework" JAR  

Example interaction with OIM

SPML2 Examples:



*********************************************************************************************************************************************************************
*********************************************************************************************************************************************************************


OIM Expects this:
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Header><wsa1:OIMUser soapenv:mustUnderstand="0" xmlns:wsa1="http://xmlns.oracle.com/OIM/provisioning"><wsa1:OIMUserId xmlns:wsa1="http://xmlns.oracle.com/OIM/provisioning">user1</wsa1:OIMUserId><wsa1:OIMUserPassword xmlns:wsa1="http://xmlns.oracle.com/OIM/provisioning">password1</wsa1:OIMUserPassword></wsa1:OIMUser></soapenv:Header>
<soapenv:Body><m:processRequest xmlns:m="http://xmlns.oracle.com/OIM/provisioning"><sOAPElement>
<addRequest returnData="everything" xmlns="urn:oasis:names:tc:SPML:2:0" xmlns:dsml="urn:oasis:names:tc:DSML:2:0:core">
<data>

<dsml:attr name="objectclass"><dsml:value>Users</dsml:value></dsml:attr><dsml:attr name="Users.User ID"><dsml:value>Jane Doe</dsml:value></dsml:attr><dsml:attr name="Users.First Name"><dsml:value>Jane</dsml:value></dsml:attr><dsml:attr name="Users.Last Name"><dsml:value>Doe</dsml:value></dsml:attr><dsml:attr name="Organizations.Organization Name"><dsml:value>Xellerate Users</dsml:value></dsml:attr><dsml:attr name="Users.Xellerate Type"><dsml:value>End-User</dsml:value></dsml:attr><dsml:attr name="Users.Role"><dsml:value>Full-Time</dsml:value></dsml:attr><dsml:attr name="Users.Password"><dsml:value>welcome</dsml:value></dsml:attr>

</data>
</addRequest></sOAPElement></m:processRequest></soapenv:Body></soapenv:Envelope>






Add API results (after inserting the data element only for an addRequest):

<addRequest xmlns='urn:oasis:names:tc:SPML:2:0' requestID='rid-spmlv2' executionMode='synchronous'>
  <data>
    <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='objectclass'>
      <dsml:values>Users</dsml:values>
    </dsml:attr>
    <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.User ID'>
      <dsml:values>zgrey7</dsml:values>
    </dsml:attr>
    <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.First Name'>
      <dsml:values>Zane</dsml:values>
    </dsml:attr>
    <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Last Name'>
      <dsml:values>Grey7</dsml:values>
    </dsml:attr>
    <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Password'>
      <dsml:values>Passw0rd</dsml:values>
    </dsml:attr>
    <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Role'>
      <dsml:values>Full-Time</dsml:values>
    </dsml:attr>
    <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Organizations.Organization Name'>
      <dsml:values>Xellerate Users</dsml:values>
    </dsml:attr>
    <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Xellerate Type'>
      <dsml:values>End-User</dsml:values>
    </dsml:attr>
  </data>
</addRequest>

===========================
<addResponse xmlns='urn:oasis:names:tc:SPML:2:0' status='success'>
  <pso>
    <psoID ID='Users:84'/>
    <data>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.User ID'>
        <dsml:value>ZGREY7</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Key'>
        <dsml:value>84</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Last Name'>
        <dsml:value>Grey7</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.First Name'>
        <dsml:value>Zane</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Xellerate Type'>
        <dsml:value>End-User</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Creation Date'>
        <dsml:value>2009-12-09 16:09:53.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Updated By'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Update Date'>
        <dsml:value>2009-12-09 16:09:55.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Status'>
        <dsml:value>Active</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Disable User'>
        <dsml:value>0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Lock User'>
        <dsml:value>0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Organizations.Key'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Role'>
        <dsml:value>Full-Time</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Organizations.Organization Name'>
        <dsml:value>Xellerate Users</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Provisioned Date'>
        <dsml:value>2009-12-09 16:09:53.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Change Password At Next Logon'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='objectclass'>
        <dsml:value>Users</dsml:value>
      </dsml:attr>
    </data>
    <capabilityData mustUnderstand='true' capabilityURI='urn:oasis:names:tc:SPML:2:0:reference'>
      <spmlref:reference xmlns='urn:oasis:names:tc:SPML:2:0' xmlns:spmlref='urn:oasis:names:tc:SPML:2:0:reference' typeOfReference='memberOf'>
        <spmlref:toPsoID ID='Groups:3'/>
      </spmlref:reference>
    </capabilityData>
  </pso>
</addResponse>

Status:  success



    
    
    
    





*********************************************************************************************************************************************************************
*********************************************************************************************************************************************************************


Search API results:


<spmlsearch:searchRequest xmlns='urn:oasis:names:tc:SPML:2:0' xmlns:spmlsearch='urn:oasis:names:tc:SPML:2:0:search' requestID='oim-rid' executionMode='synchronous' returnData='everything'>
  <spmlsearch:query scope='pso'>
      <dsml:and xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core'>
        <dsml:filter>
        <dsml:equalityMatch name='Users.Last Name'>
          <dsml:values>Walsh</dsml:values>
        </dsml:equalityMatch>
        </dsml:filter>
        <dsml:filter>
        <dsml:equalityMatch name='Object Class'>
          <dsml:values>Users</dsml:values>
        </dsml:equalityMatch>
        </dsml:filter>
        <dsml:filter>
        <dsml:equalityMatch name='Users.Xellerate Type'>
          <dsml:values>End-User</dsml:values>
        </dsml:equalityMatch>
        </dsml:filter>
      </dsml:and>
    <spmlsearch:basePsoID ID=' '/>
  </spmlsearch:query>
</spmlsearch:searchRequest>

Response: 

<spmlsearch:searchResponse xmlns='urn:oasis:names:tc:SPML:2:0' xmlns:spmlsearch='urn:oasis:names:tc:SPML:2:0:search' status='success'>
  <spmlsearch:pso>
    <psoID ID='Users:4'/>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.User ID'>
        <dsml:value>JWALSH</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Key'>
        <dsml:value>4</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Last Name'>
        <dsml:value>Walsh</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.First Name'>
        <dsml:value>John</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Manager Key'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Manager Login'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Manager First Name'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Manager Last Name'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Xellerate Type'>
        <dsml:value>End-User</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Creation Date'>
        <dsml:value>2009-09-01 15:18:59.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Identity'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Note'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Updated By'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Update Date'>
        <dsml:value>2009-10-14 13:53:23.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Row Version'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Status'>
        <dsml:value>Deleted</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Disable User'>
        <dsml:value>0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Lock User'>
        <dsml:value>0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Organizations.Key'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Role'>
        <dsml:value>Full-Time</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Organizations.Organization Name'>
        <dsml:value>Xellerate Users</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Email'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.AD Reference'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Start Date'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.End Date'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Provisioning Date'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Deprovisioning Date'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Provisioned Date'>
        <dsml:value>2009-09-01 15:18:59.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Deprovisioned Date'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Middle Name'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Change Password At Next Logon'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
    <capabilityData mustUnderstand='true' capabilityURI='urn:oasis:names:tc:SPML:2:0:reference'>
      <spmlref:reference xmlns='urn:oasis:names:tc:SPML:2:0' xmlns:spmlref='urn:oasis:names:tc:SPML:2:0:reference' typeOfReference='memberOf'>
        <spmlref:toPsoID ID='ALL USERS'/>
      </spmlref:reference>
    </capabilityData>
  </spmlsearch:pso>
  <spmlsearch:pso>
    <psoID ID='Users:61'/>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.User ID'>
        <dsml:value>TWALSH</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Key'>
        <dsml:value>61</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Last Name'>
        <dsml:value>Walsh</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.First Name'>
        <dsml:value>Sally3</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Manager Key'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Manager Login'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Manager First Name'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Manager Last Name'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Xellerate Type'>
        <dsml:value>End-User</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Creation Date'>
        <dsml:value>2009-10-15 15:17:29.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Identity'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Note'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Updated By'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Update Date'>
        <dsml:value>2009-12-09 13:24:04.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Row Version'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Status'>
        <dsml:value>Active</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Disable User'>
        <dsml:value>0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Lock User'>
        <dsml:value>0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Organizations.Key'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Role'>
        <dsml:value>Full-Time</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Organizations.Organization Name'>
        <dsml:value>Xellerate Users</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Email'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.AD Reference'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Start Date'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.End Date'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Provisioning Date'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Deprovisioning Date'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Provisioned Date'>
        <dsml:value>2009-10-15 15:17:29.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Deprovisioned Date'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Middle Name'>
        <dsml:value></dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Change Password At Next Logon'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
    <capabilityData mustUnderstand='true' capabilityURI='urn:oasis:names:tc:SPML:2:0:reference'>
      <spmlref:reference xmlns='urn:oasis:names:tc:SPML:2:0' xmlns:spmlref='urn:oasis:names:tc:SPML:2:0:reference' typeOfReference='memberOf'>
        <spmlref:toPsoID ID='ALL USERS'/>
      </spmlref:reference>
    </capabilityData>
  </spmlsearch:pso>
</spmlsearch:searchResponse>

Received search response.









*********************************************************************************************************************************************************************
*********************************************************************************************************************************************************************


Modify API results:

requestXML - This is the result of the openspml api prior to sending the request to the server:
"<modifyRequest xmlns='urn:oasis:names:tc:SPML:2:0' requestID='request-2' executionMode='synchronous' returnData='everything'>
  <psoID ID='Users:21'/>
  <modification modificationMode='add'>
      <dsml:modification xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.First Name' operation='add'>
        <dsml:value>Jenny</dsml:value>
      </dsml:modification>
  </modification>
</modifyRequest>
"


Prior to sending the request, the openptkSPML2Client (sendAndReceive) will :

1) Add the authentication information in the header
2) <m:processRequestResponse> is wrapped prior to sending to the server

soapXml - this is the exact string send to the server

"<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><soapenv:Header><wsa1:OIMUser soapenv:mustUnderstand="0" xmlns:wsa1="http://xmlns.oracle.com/OIM/provisioning"><wsa1:OIMUserId xmlns:wsa1="http://xmlns.oracle.com/OIM/provisioning">xelsysadm</wsa1:OIMUserId><wsa1:OIMUserPassword xmlns:wsa1="http://xmlns.oracle.com/OIM/provisioning">Passw0rd</wsa1:OIMUserPassword></wsa1:OIMUser></soapenv:Header>
<soapenv:Body><m:processRequest xmlns:m="http://xmlns.oracle.com/OIM/provisioning"><sOAPElement><modifyRequest xmlns='urn:oasis:names:tc:SPML:2:0' requestID='request-2' executionMode='synchronous' returnData='everything'>
  <psoID ID='Users:21'/>
  <modification modificationMode='add'>
      <dsml:modification xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.First Name' operation='add'>
        <dsml:value>Jenny</dsml:value>
      </dsml:modification>
  </modification>
</modifyRequest>
</sOAPElement></m:processRequest></soapenv:Body></soapenv:Envelope>"


responseXML - this is the complete string returned from the server:
"<env:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><env:Header></env:Header><env:Body env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><m:processRequestResponse xmlns:m="http://xmlns.oracle.com/OIM/provisioning"><modifyResponse xmlns="urn:oasis:names:tc:SPML:2:0" status="success"><pso xmlns="urn:oasis:names:tc:SPML:2:0"><psoID ID="Users:21"></psoID><data xmlns="urn:oasis:names:tc:DSML:2:0:core"><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.User ID"><value>BCHILDS</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Key"><value>21</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Last Name"><value>Childs</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.First Name"><value>Jenny</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Xellerate Type"><value>End-User</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Creation Date"><value>2009-10-14 10:28:58.0</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Updated By"><value>1</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Update Date"><value>2009-12-07 15:20:02.0</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Status"><value>Active</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Disable User"><value>0</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Lock User"><value>0</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Organizations.Key"><value>1</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Role"><value>Full-Time</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Organizations.Organization Name"><value>Xellerate Users</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Provisioned Date"><value>2009-10-14 10:28:57.0</value></attr><attr xmlns="urn:oasis:names:tc:DSML:2:0:core" name="Users.Change Password At Next Logon"><value>1</value></attr></data><capabilityData xmlns="urn:oasis:names:tc:SPML:2:0:reference" capabilityURI="urn:oasis:names:tc:SPML:2:0:reference" mustUnderstand="true"><reference xmlns="urn:oasis:names:tc:SPML:2:0:reference" typeOfReference="memberOf"><toPsoID ID="Groups:3"></toPsoID></reference></capabilityData></pso></modifyResponse></m:processRequestResponse></env:Body></env:Envelope>"

payloadXML - This is the results from the server without the header information, and with the body wrapper (m:processRequestResponse) removed:
"<?xml version="1.0" encoding="UTF-8"?><modifyResponse xmlns="urn:oasis:names:tc:SPML:2:0" status="success"><pso><psoID ID="Users:21"/><data xmlns="urn:oasis:names:tc:DSML:2:0:core"><attr name="Users.User ID"><value>BCHILDS</value></attr><attr name="Users.Key"><value>21</value></attr><attr name="Users.Last Name"><value>Childs</value></attr><attr name="Users.First Name"><value>Jenny</value></attr><attr name="Users.Xellerate Type"><value>End-User</value></attr><attr name="Users.Creation Date"><value>2009-10-14 10:28:58.0</value></attr><attr name="Users.Updated By"><value>1</value></attr><attr name="Users.Update Date"><value>2009-12-07 15:20:02.0</value></attr><attr name="Users.Status"><value>Active</value></attr><attr name="Users.Disable User"><value>0</value></attr><attr name="Users.Lock User"><value>0</value></attr><attr name="Organizations.Key"><value>1</value></attr><attr name="Users.Role"><value>Full-Time</value></attr><attr name="Organizations.Organization Name"><value>Xellerate Users</value></attr><attr name="Users.Provisioned Date"><value>2009-10-14 10:28:57.0</value></attr><attr name="Users.Change Password At Next Logon"><value>1</value></attr></data><capabilityData xmlns="urn:oasis:names:tc:SPML:2:0:reference" capabilityURI="urn:oasis:names:tc:SPML:2:0:reference" mustUnderstand="true"><reference typeOfReference="memberOf"><toPsoID ID="Groups:3"/></reference></capabilityData></pso></modifyResponse>"

Note:  There is a data element surrounding the attr's


3) Prior to unmarshalling, the data element is removed



To fix:  xmlBuffer.java and (addEndTag)
ReflectiveXMLMarshaller.java (processElementFields, processAttributeFields)


Note the marshalling back to xml (the data wrapper around the att's is supressed)



===========================
<modifyResponse xmlns='urn:oasis:names:tc:SPML:2:0' status='success'>
  <pso>
    <psoID ID='Users:21'/>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.User ID'>
        <dsml:value>BCHILDS</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Key'>
        <dsml:value>21</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Last Name'>
        <dsml:value>Childs</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.First Name'>
        <dsml:value>Jenny</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Xellerate Type'>
        <dsml:value>End-User</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Creation Date'>
        <dsml:value>2009-10-14 10:28:58.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Updated By'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Update Date'>
        <dsml:value>2009-12-07 15:20:02.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Status'>
        <dsml:value>Active</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Disable User'>
        <dsml:value>0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Lock User'>
        <dsml:value>0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Organizations.Key'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Role'>
        <dsml:value>Full-Time</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Organizations.Organization Name'>
        <dsml:value>Xellerate Users</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Provisioned Date'>
        <dsml:value>2009-10-14 10:28:57.0</dsml:value>
      </dsml:attr>
      <dsml:attr xmlns:dsml='urn:oasis:names:tc:DSML:2:0:core' name='Users.Change Password At Next Logon'>
        <dsml:value>1</dsml:value>
      </dsml:attr>
    <capabilityData mustUnderstand='true' capabilityURI='urn:oasis:names:tc:SPML:2:0:reference'>
      <spmlref:reference xmlns='urn:oasis:names:tc:SPML:2:0' xmlns:spmlref='urn:oasis:names:tc:SPML:2:0:reference' typeOfReference='memberOf'>
        <spmlref:toPsoID ID='Groups:3'/>
      </spmlref:reference>
    </capabilityData>
  </pso>
</modifyResponse>









*********************************************************************************************************************************************************************
*********************************************************************************************************************************************************************


Delete API results:


run-single:
<deleteRequest xmlns='urn:oasis:names:tc:SPML:2:0' requestID='request-2' executionMode='synchronous' recursive='true'>
  <psoID ID='Users:21'>
    <containerID ID='Users'/>
  </psoID>
</deleteRequest>

===========================
<deleteResponse xmlns='urn:oasis:names:tc:SPML:2:0' status='success'/>


Developer Notes

For version 2.0,

The version of the spml2 libraries used in the build must be selected based on whether OIM or SIM is used. All operations except search will coexist. In order for search to work properly, the correct SPML2 library must be used.

The ant build process has been extended to allow the command line build process to specify which SPML2 library to include.

Addition to the PROJECT file to control the build process:

  1. SPML2 library to use in build openptk version
  2. idm_8_openspml2-toolkit - Use for Sun Identity Manager integration
  3. openptk-openspml2-toolkit - Use for Oracle Identity Manager integration
    SPML2_LIBRARY=idm_8_openspml2-toolkit

See Issue 153 for additional details.

For Other development builds (Netscape project), the correct SPML2 library must be included in the openptk.war file which is built.

Comments