Grouper Web Services

  • How does paging work with web services
    • Unfortunately you cannot get back the total count in the result, so you can page.  If the result size is less than page size, then there is not another page.  If not, make another query and see if there are more results.
    • Paging with cursor is better than paging without cursor since records can be skipped if they are edited while the paging is taking place
    • These examples are for getGroups, example URL and headers:

      POST https://grouper-ws.school.edu/grouperWs/servicesRest/v4_0_000/subjects/sources/pennperson/subjectId/10021368/groups
      Content-Type: application/x-www-form-urlencoded
    • Paging with cursor example (recommended)
      • Request first page (pick a sort field and if ascending, in this case getting all so just use id)

        wsLiteObjectType=WsRestGetGroupsLiteRequest&sortString=id&ascending=true&pageSize=3&pageNumber=1
      • Request next page (note the page last cursor field is the last id sent in previous request (cursor)

        wsLiteObjectType=WsRestGetGroupsLiteRequest&sortString=id&ascending=true&pageSize=3&pageLastCursorFieldType=string&pageCursorFieldIncludesLastRetrieved=false&pageIsCursor=true&pageLastCursorField=00ffd24ae5f84e6ebb68b1779577c0cd
    • Paging without cursor example (not recommended)
      • Request first page

        wsLiteObjectType=WsRestGetGroupsLiteRequest&sortString=id&ascending=true&pageSize=3&pageNumber=1
      • Request next page

        wsLiteObjectType=WsRestGetGroupsLiteRequest&sortString=id&ascending=true&pageSize=3&pageNumber=2
  • Subject attributes can be exposed via web service
    • First off, you need to have the subject api configuration to get attribute from the DB / LDAP
      • Here is an example from a JDBC2 subject source

        # now you can count up from 0 to N of attributes for various cols.  The name is how to reference in subject.getAttribute()
        subjectApi.source.pennperson.param.subjectAttributeCol0.value = pennname
        
        # you can count up from 0 to N of attributes for various cols.  The name is how to reference in subject.getAttribute()
        subjectApi.source.pennperson.param.subjectAttributeName0.value = PENNNAME
      • You can test this from GSH

        groovy:000> grouperSession = GrouperSession.startRootSession();
        ===> 4a29e140d3b346558c7c23ed996d1d8a,'GrouperSystem','application'
        groovy:000> subject = SubjectFinder.findByIdOrIdentifier("mchyzer", true);
        ===> Subject id: 10021368, sourceId: pennperson, name: Chris Hyzer
        groovy:000> subject.getAttributeValue("pennname")
        ===> mchyzer
    • Subject attributes are exposed via web service in the grouper-ws.properties

      # subject attribute names to send back when a WsSubjectResult is sent, comma separated                                              
      # e.g. name, netid                                                                                                                  
      # default is none                                                                                                                   
      ws.subject.result.attribute.names =
      
      # subject result attribute names when extended data is requested (comma separated)                                                  
      # default is name, description                                                                                                      
      # note, these will be in addition to ws.subject.result.attribute.names                                                              
      ws.subject.result.detail.attribute.names = PENNNAME
      
      
    • Then when a subject is returned, since ws.subject.result.attribute.names is blank, no custom attribute are returned by default

      [mchyzer@flash pennGroupsClient-2.4.0]$ java -jar grouperClient.jar --operation=getSubjectsWs --subjectIdentifiers=mchyzer --debug=true
      Reading resource: grouper.client.properties, from: /home/mchyzer/grouper/pennGroupsClient-2.4.0/grouper.client.properties
      WebService: connecting as user: 'someuser'
      WebService: connecting to URL: 'https://server.school.edu/grouperWs/servicesRest/v2_4_000/subjects'
      
      ################ REQUEST START (indented) ###############
      
      POST /grouperWs/servicesRest/v2_4_000/subjects HTTP/1.1
      Connection: close
      Authorization: Basic xxxxxxxxxxxxxxxx
      User-Agent: Jakarta Commons-HttpClient/3.1
      Host: somehost.school.edu:-1
      Content-Length: 171
      Content-Type: text/xml; charset=UTF-8
      
      <WsRestGetSubjectsRequest>
        <wsSubjectLookups>
          <WsSubjectLookup>
            <subjectIdentifier>mchyzer</subjectIdentifier>
          </WsSubjectLookup>
        </wsSubjectLookups>
      </WsRestGetSubjectsRequest>
      
      ################ REQUEST END ###############
      
      
      
      ################ RESPONSE START (indented) ###############
      
      HTTP/1.1 200 OK
      Date: Wed, 17 Apr 2019 18:12:37 GMT
      Set-Cookie: JSESSIONID=xxxxxxxxxxxx; HttpOnly
      X-Grouper-resultCode: SUCCESS
      X-Grouper-success: T
      X-Grouper-resultCode2: NONE
      Content-Type: application/xml;charset=UTF-8
      Vary: Accept-Encoding
      Connection: close
      Transfer-Encoding: chunked
      
      <WsGetSubjectsResults>
        <wsSubjects>
          <WsSubject>
            <identifierLookup>mchyzer</identifierLookup>
            <resultCode>SUCCESS</resultCode>
            <success>T</success>
            <id>10021368</id>
            <name>Chris Hyzer</name>
            <sourceId>pennperson</sourceId>
          </WsSubject>
        </wsSubjects>
        <resultMetadata>
          <resultCode>SUCCESS</resultCode>
          <resultMessage>Queried 1 subjects</resultMessage>
          <success>T</success>
        </resultMetadata>
        <responseMetadata>
          <resultWarnings></resultWarnings>
          <millis>11</millis>
          <serverVersion>2.4.0</serverVersion>
        </responseMetadata>
      </WsGetSubjectsResults>
      
      ################ RESPONSE END ###############
      
      
      Output template: Index: ${index}: success: ${success}, code: ${wsSubject.resultCode}, subject: ${wsSubject.id}, available variables: wsGetSubjectsResults, grouperClientUtils, index, wsSubject, wsGroup, success
      Index: 0: success: T, code: SUCCESS, subject: 10021368
      Elapsed time: 957ms
      [mchyzer@flash pennGroupsClient-2.4.0]$ 
    • If you request the subject detail (attrs in ws.subject.result.detail.attribute.name), then they will be returned

      [mchyzer@flash pennGroupsClient-2.4.0]$ java -jar grouperClient.jar --operation=getSubjectsWs --subjectIdentifiers=mchyzer --debug=true --includeSubjectDetail=true
      Reading resource: grouper.client.properties, from: /home/mchyzer/grouper/pennGroupsClient-2.4.0/grouper.client.properties
      WebService: connecting as user: 'user'
      WebService: connecting to URL: 'https://server.school.edu/grouperWs/servicesRest/v2_4_000/subjects'
      
      ################ REQUEST START (indented) ###############
      
      POST /grouperWs/servicesRest/v2_4_000/subjects HTTP/1.1
      Connection: close
      Authorization: Basic xxxxxxxxxxxxxxxx
      User-Agent: Jakarta Commons-HttpClient/3.1
      Host: fastprod-medium-a-01.apps.upenn.edu:-1
      Content-Length: 217
      Content-Type: text/xml; charset=UTF-8
      
      <WsRestGetSubjectsRequest>
        <includeSubjectDetail>T</includeSubjectDetail>
        <wsSubjectLookups>
          <WsSubjectLookup>
            <subjectIdentifier>mchyzer</subjectIdentifier>
          </WsSubjectLookup>
        </wsSubjectLookups>
      </WsRestGetSubjectsRequest>
      
      ################ REQUEST END ###############
      
      
      
      ################ RESPONSE START (indented) ###############
      
      HTTP/1.1 200 OK
      Date: Wed, 17 Apr 2019 18:16:55 GMT
      Set-Cookie: JSESSIONID=xxxxxxxxxxxx; HttpOnly
      X-Grouper-resultCode: SUCCESS
      X-Grouper-success: T
      X-Grouper-resultCode2: NONE
      Content-Type: application/xml;charset=UTF-8
      Vary: Accept-Encoding
      Connection: close
      Transfer-Encoding: chunked
      
      <WsGetSubjectsResults>
        <subjectAttributeNames>
          <string>name</string>
          <string>description</string>
          <string>PENNNAME</string>
          <string>EMAIL</string>
        </subjectAttributeNames>
        <wsSubjects>
          <WsSubject>
            <identifierLookup>mchyzer</identifierLookup>
            <resultCode>SUCCESS</resultCode>
            <success>T</success>
            <id>10021368</id>
            <name>Chris Hyzer</name>
            <sourceId>pennperson</sourceId>
            <attributeValues>
              <string>Chris Hyzer</string>
              <string>Chris Hyzer (mchyzer, 10021368) (active) Staff - Isc-applications & Information Services - Application Architect (also: Alumni)</string>
              <string>mchyzer</string>
              <string>mchyzer@upenn.edu</string>
            </attributeValues>
          </WsSubject>
        </wsSubjects>
        <resultMetadata>
          <resultCode>SUCCESS</resultCode>
          <resultMessage>Queried 1 subjects</resultMessage>
          <success>T</success>
        </resultMetadata>
        <responseMetadata>
          <resultWarnings></resultWarnings>
          <millis>121</millis>
          <serverVersion>2.4.0</serverVersion>
        </responseMetadata>
      </WsGetSubjectsResults>
      
      ################ RESPONSE END ###############
      
      
      Output template: Index: ${index}: success: ${success}, code: ${wsSubject.resultCode}, subject: ${wsSubject.id}, available variables: wsGetSubjectsResults, grouperClientUtils, index, wsSubject, wsGroup, success
      Index: 0: success: T, code: SUCCESS, subject: 10021368
      Elapsed time: 1106ms
      [mchyzer@flash pennGroupsClient-2.4.0]$ 
    • Or you can request individual attributes

      [mchyzer@flash pennGroupsClient-2.4.0]$ java -jar grouperClient.jar --operation=getSubjectsWs --subjectIdentifiers=mchyzer --debug=true --subjectAttributeNames=PENNNAME
      Reading resource: grouper.client.properties, from: /home/mchyzer/grouper/pennGroupsClient-2.4.0/grouper.client.properties
      WebService: connecting as user: 'user'
      WebService: connecting to URL: 'https://server.school.edu/grouperWs/servicesRest/v2_4_000/subjects'
      
      ################ REQUEST START (indented) ###############
      
      POST /grouperWs/servicesRest/v2_4_000/subjects HTTP/1.1
      Connection: close
      Authorization: Basic xxxxxxxxxxxxxxxx
      User-Agent: Jakarta Commons-HttpClient/3.1
      Host: fastprod-medium-a-01.apps.upenn.edu:-1
      Content-Length: 243
      Content-Type: text/xml; charset=UTF-8
      
      <WsRestGetSubjectsRequest>
        <subjectAttributeNames>
          <string>PENNNAME</string>
        </subjectAttributeNames>
        <wsSubjectLookups>
          <WsSubjectLookup>
            <subjectIdentifier>mchyzer</subjectIdentifier>
          </WsSubjectLookup>
        </wsSubjectLookups>
      </WsRestGetSubjectsRequest>
      
      ################ REQUEST END ###############
      
      
      
      ################ RESPONSE START (indented) ###############
      
      HTTP/1.1 200 OK
      Date: Wed, 17 Apr 2019 18:26:29 GMT
      Set-Cookie: JSESSIONID=xxxxxxxxxxxx; HttpOnly
      X-Grouper-resultCode: SUCCESS
      X-Grouper-success: T
      X-Grouper-resultCode2: NONE
      Content-Type: application/xml;charset=UTF-8
      Vary: Accept-Encoding
      Connection: close
      Transfer-Encoding: chunked
      
      <WsGetSubjectsResults>
        <subjectAttributeNames>
          <string>PENNNAME</string>
        </subjectAttributeNames>
        <wsSubjects>
          <WsSubject>
            <identifierLookup>mchyzer</identifierLookup>
            <resultCode>SUCCESS</resultCode>
            <success>T</success>
            <id>10021368</id>
            <name>Chris Hyzer</name>
            <sourceId>pennperson</sourceId>
            <attributeValues>
              <string>mchyzer</string>
            </attributeValues>
          </WsSubject>
        </wsSubjects>
        <resultMetadata>
          <resultCode>SUCCESS</resultCode>
          <resultMessage>Queried 1 subjects</resultMessage>
          <success>T</success>
        </resultMetadata>
        <responseMetadata>
          <resultWarnings></resultWarnings>
          <millis>207</millis>
          <serverVersion>2.4.0</serverVersion>
        </responseMetadata>
      </WsGetSubjectsResults>
      
      ################ RESPONSE END ###############
      
      
      Output template: Index: ${index}: success: ${success}, code: ${wsSubject.resultCode}, subject: ${wsSubject.id}, available variables: wsGetSubjectsResults, grouperClientUtils, index, wsSubject, wsGroup, success
      Index: 0: success: T, code: SUCCESS, subject: 10021368
      Elapsed time: 1180ms
      [mchyzer@flash pennGroupsClient-2.4.0]$ 
    • dsf
  • Which SOAP call should I use for getting the list of groups that group A is a member of?

To get a list of groups that A is a member of, call getGroups, there is a soap example there. Note: just use g:gsa as the subject source, and the group name as the subjectIdentifier, or the group uuid as the subjectId. You can change the query to ask about immediate, effective, nonimmediate, etc. I think you can get similar information from getMemberships (using the same subject call as described above)

  • Can I run grouper web services against any version of Grouper?

No, you should use the version of Grouper bundled in the web services.  This makes it a little complicated if you have a UI / GSH / etc running against your Grouper DB.  You will need to keep them in sync...

  • Why are there three flavors or web services (SOAP, XML-HTTP, REST-Lite)?

SOAP is supported since many schools required it.  REST-Lite is supported because many schools required it.  XML-HTTP is supported because Axis2 gives it for free when building a SOAP web service.  This way the same SOAP interface can be accessed by clients who only want to talk HTTP and XML and not SOAP.

  • Why is the rampart .aar file named GrouperServiceWssec.aar, but the URL is still /services/GrouperService?

The URL for ramprt or not is the same.  Inside the services.xml in the .aar files, it configures the app name.  grouper-ws will not work if you change this (unless to do other build activities also)

  • Why is there a "simple" operation for every non simple operation in SOAP and XML-HTTP?

The non-simple operations are batchable if the client wants to do one operation multiple times with one request.  The simple operations are for if the client only needs to do one thing (e.g. assign a member to a group and not assign multiple members to a group).  Also, there is a valuable side effect that for the XML-HTTP, if the operation only has scaler input params (and not complex types or arrays), that the input does not need XML, it can be in the query string for GET or in the http form param pairs in the body for POST.

It is confusing that there are so many different ways to call grouper via web service.  The documentation will be improved to make it easier to find the best strategy.

  • Why element named "return" (by axis)

This is an unfortunate "feature" by axis, the default element is named "return" which is a keyword in many programming languages, so if the language automatically converts the xml to an object graph, then it will be broken.  Chris will followup with Axis to see if there is a fix for this

  • Why returning error codes and messages and not just use SOAP faults?

For two of three of the flavors of web services SOAP faults are not an option since they are not SOAP.  Also, for SOAP batched, the status of each line item needs to be returned for the client to process, and a SOAP fault would preclude that.  Also, the fewer SOAP specific features that are used, the more widespread the compatibility will be.  All three flavors of web service use the same underlying logic, so the more consistent the better.

  • Can we add a service for subject search?

Yes, this will be added

  • No labels