grouper-users - RE: Help with accessing web services
Subject: Grouper Users - Open Discussion List
List archive
- From: Paul Gazda <>
- To: Chris Hyzer <>, "" <>
- Subject: RE: Help with accessing web services
- Date: Mon, 2 Mar 2009 14:03:49 -0700
- Accept-language: en-US
- Acceptlanguage: en-US
Thanks, Chris. Those things will help. The warnings will be
most useful during development when you can watch for them when testing. I do have a follow-up question to the previous enhancement
you made, now that I am understanding a little better how
things work: “I made some improvements to the 1.4 branch to address your
issues: https://bugs.internet2.edu/jira/browse/GRP-230 1. If there is no
lookup object on an insert, it should be ok 2. If there is a
lookup, with a name, on an insert, and the name is the same as the group name
(nonlookup), then thats ok 3. If an insert, and
the group already exists, then give the error GROUP_ALREADY_EXISTS” Wouldn’t it be better to not throw an exception in the case
of GROUP_ALREADY_EXISTS, but rather to set the success status to “F” and return the WsResultMeta object normally instead of having to retrieve
it within a catch block with gwse.getContainerResponseObject()?
I think I should check the result of every operation by examining “getSuccess()” anyway, and since the GROUP_ALREADY_EXISTS condition is similar to the others that are specified in the
javadoc (SUBJECT_NOT_FOUND, SUBJECT_DUPLICATE), it seems that it is more
consistent to treat it as a possible expected outcome of an insert rather than
as an exception. And just to be clear on point 3,
the GROUP_ALREADY_EXISTS error would only occur if the saveMode
is “INSERT”, correct? Thanks. Paul Gazda From: Chris Hyzer
[mailto:] I created a jira to
improve the javadoc: https://bugs.internet2.edu/jira/browse/GRP-239 You would access
warning on a group save with: wsGroupSaveResults.getResponseMetadata().getResultWarnings() Also, I picture them
being for human consumption. i.e. if you get a warning back, might want
to log it, and followup at some point. I don’t think you would
programmatically address them. However, for unit tests, I will probably
use keys and friendly descriptions: WARNING_KEY1: This
is the warning description WARNING_KEY2: This
is another warning I also made a jira
for that: https://bugs.internet2.edu/jira/browse/GRP-240 Regards, Chris From: Paul Gazda
[mailto:] I’m just suggesting ways to minimize accidental misuse of
those methods. I don’t think it is critical issue. The idea of “user mode”
beans sounds most promising to me, but maybe the more complex solutions aren’t
warranted at this point. Perhaps some additional explanation in the javadoc for
these methods would be helpful. Warnings could be helpful, but I don’t see
anywhere in the WSResultMeta javadoc that indicates how to access a warning.
How do you access them? A drawback of warnings is that they present a practical
problem of what to do with them when using the api? Since they are free-form
text, it would be difficult to anticipate what they might mean unless they were
standardized like result codes. Paul Gazda From: Chris Hyzer
[mailto:] > I was only thinking of inserts, not updates for the
errors. So it would be scenario 2. I think on an insert, the displayName should be blank… since
if you changed any display extensions of parent stems, it wouldn’t do anything,
so why be allowed to put anything in there? However, we are already live,
so its hard to mandate that. Maybe a warning if you enter anything in displayName
on insert? > > But your response does show that I don’t understand the
interrelationship of the methods. I assumed that in an update situation, if you
had > this: > displayName =
stemDisplayName:displayExtension > and you did this: > wsGroup.setDisplayExtension(“newDisplayExtension”); > the displayName would be updated to “stemDisplayName:newDisplayExtension”. > > From your explanation in 3, I get the impression that
you would have to do this: > wsGroup.setDisplayExtension(“newDisplayExtension”); >
wsGroup.setDisplayName(“stemDisplayName:newDisplayExtension”); > > I’m not understanding why the methods
setDisplayExtension and setExtension exist at all if the values ultimately have
to be also set by > setName and setExtension. Those beans are used for multiple purposes. They are
marshaled from XML, in which case all getters and setters need to exist and be
simple (not affect each other). Also, you can use those beans for the
API, in which case you need to know what you are doing. I think warnings
are the best way… We could have a second set of objects for people to
use, and then I could convert those to beans for communication, or we could use
interfaces somehow with multiple implementations, but I was hoping not to have
to do either of those. We could also put the beans in “user-mode” where
it would do that logic for you, but in default mode they are simple. That
is something I am more open to if server side warnings arent enough. The
advantage to limiting it to server side warnings is that WS users who arent
using the client API would also benefit… Thoughts? Chris From: Paul Gazda
[mailto:] I was only thinking of inserts, not updates for the errors.
So it would be scenario 2. But your response does show that I don’t understand the
interrelationship of the methods. I assumed that in an update situation, if you
had this: displayName = stemDisplayName:displayExtension and you did this: wsGroup.setDisplayExtension(“newDisplayExtension”); the displayName would be updated to “stemDisplayName:newDisplayExtension”. From your explanation in 3, I get the impression that you
would have to do this: wsGroup.setDisplayExtension(“newDisplayExtension”); wsGroup.setDisplayName(“stemDisplayName:newDisplayExtension”); I’m not understanding why the methods setDisplayExtension
and setExtension exist at all if the values ultimately have to be also set by
setName and setExtension. Paul Gazda From: Chris Hyzer
[mailto:] Yeah… we have some
options here, I would prefer to do only #1, but I am open to 2 and 3 if people
want them: 1.
If
there is a mismatch, I could not throw an error, and instead just put some text
in the warning field in the response to the web service (there is a warning
field where free-form text can go). *This
is my preference* a.
The
use case where errors wouldn’t work is: retrieve a group, set the
displayExtension to something different, don’t bother syncing up the
displayName, and saving it. 2.
If
it is an insert, and things don’t match, and its not because they are blank,
then I could throw an error (not sure why someone would do that). 3.
If
it is an update, and the displayName is different than it used to be, but not
in sync with the displayExtension, I could throw an error. Im not sure
about this one, its probably ok, but might affect some legitimate uses Regards, Chris From: Paul Gazda
[mailto:] Thanks. It makes sense the way you explain it. Just an
opinion, but it might be better if an explanatory error is thrown if a user
tries to set a conflicting extension or displayExtension for a groupSave
operation. Paul Gazda From: Chris Hyzer
[mailto:] Yes! Finally a
request which doesn’t look like a bug. Though I admit it is weird. One of the
requirements for web services was to have the same object retrieved from web
services, be sent on a save. However, the 4 fields of a group have some
redundancy: name =
stemName:extension displayName =
stemDisplayName:displayExtension so… if you send a
name which is not in sync with the extension, then it will disregard the
extension. If you send a
displayName which is not in sync with the displayExtension, it will disregard
the displayName. Might seem a little
weird, but it makes sense if you think about it. Well, at least it does
for me… J I updated the
groupSave documentation to mention this: https://wiki.internet2.edu/confluence/display/GrouperWG/Group+Save OK? You should be able
to pull the group up in the UI or GSH and see consistent results. Thanks, Chris From: Paul Gazda
[mailto:] Chris, Thanks very much for your quick response and feature
enhancement. It works great! I did discover what looks like a bug in the grouperClient
display from the line command. Some of the data is mixed up. The displayName
field shows data for display extension, and the extension field shows the last
node of the group name, even though I intentionally set the extension to a
different value as a test. Program code:
wsGroup.setName("NAU:group name");
wsGroup.setDisplayName("NAU:group display name");
wsGroup.setExtension("group extension");
wsGroup.setDisplayExtension("group display extension");
wsGroup.setDescription("group description");
wsGroupToSave.setSaveMode("INSERT"); wsGroupSaveResults =
gcGroupSave.execute(); grouper.client.properties: webService.findGroups.output = Index ${index}: name:
${wsGroup.name}, displayName: ${wsGroup.display Name}, extension: ${wsGroup.extension}, displayExtension:
${wsGroup.displayExtension}, description: ${wsGroup.description}$newline$ java -jar grouperClient.jar --operation=findGroupsWs
--queryFilterType=FIND_BY_STEM_NAME --stemName=NAU Index 0: name: NAU:group name, displayName: NAU:group
display extension, extension: group name, displayExtension: group display
extension, description: group description Paul Gazda From: Chris Hyzer
[mailto:] I made some
improvements to the 1.4 branch to address your issues: https://bugs.internet2.edu/jira/browse/GRP-230 1. If there is no
lookup object on an insert, it should be ok 2. If there is a lookup,
with a name, on an insert, and the name is the same as the group name
(nonlookup), then thats ok 3. If an insert, and
the group already exists, then give the error GROUP_ALREADY_EXISTS Get 1.4 branch with: cvs
-d:pserver::/home/cvs/i2mi login cvs
-d:pserver::/home/cvs/i2mi export -r
GROUPER_1_4_BRANCH grouper cvs
-d:pserver::/home/cvs/i2mi export -r
GROUPER_1_4_BRANCH grouper-ws Regards, Chris From: Paul Gazda
[mailto:] Chris, A special response code would be ideal, since the INSERT
saveMode implies that you are counting on the group not existing yet. However,
I can analyze the error message for a phrase if necessary, but the problem I am
having is that I do not get “group already exists with name:” anywhere in my
error message. You show this: Bad response from web service: resultCode: PROBLEM_SAVING_GROUPS,
There were 0 successes and 1 failures of saving groups. java.lang.RuntimeException: edu.internet2.middleware.grouper.exception.GroupAddException: group
already exists with name: 'aStem:aGroup4', What I get is this: "Bad response from web service: resultCode:
PROBLEM_SAVING_GROUPS, There were 0 successes and 1 failures of saving groups. java.lang.RuntimeException: java.lang.RuntimeException: Must not pass in a name for an
insert, Problem in HibernateSession: HibernateSession: isNew: false,
isReadonly: false, grouperTransactionType: READ_WRITE_NEW, Problem in HibernateSession: HibernateSession: isNew: true,
isReadonly: false, grouperTransactionType: READ_WRITE_NEW at
edu.internet2.middleware.grouper.ws.soap.WsGroupToSave.save(WsGroupToSave.java:365) . . . Paul Gazda From: Chris Hyzer
[mailto:] Sorry, this email
slipped by me. I run this from grouper client API public static void main(String[] args) { WsGroupToSave wsGroupToSave = new WsGroupToSave(); wsGroupToSave.setSaveMode("INSERT"); wsGroupToSave.setWsGroupLookup(new WsGroupLookup(null, null)); WsGroup wsGroup = new WsGroup(); wsGroup.setDisplayExtension("a group4"); wsGroup.setExtension("aGroup4"); wsGroup.setName("aStem:aGroup4"); wsGroupToSave.setWsGroup(wsGroup); try { WsGroupSaveResults wsGroupSaveResults = new
GcGroupSave().addGroupToSave(wsGroupToSave).execute(); //prints SUCCESS_INSERTED when it works System.out.println(wsGroupSaveResults.getResults()[0].getResultMetadata().getResultCode()); } catch (GcWebServiceError gwse) { WsGroupSaveResults
wsGroupSaveResults = (WsGroupSaveResults)gwse.getContainerResponseObject(); System.out.println(wsGroupSaveResults.getResults()[0].getResultMetadata().getResultCode()); gwse.printStackTrace(); } } When it is not
there, it prints: SUCCESS_INSERTED When it is there, it
prints: edu.internet2.middleware.grouperClient.ws.GcWebServiceError: Bad
response from web service: resultCode: PROBLEM_SAVING_GROUPS, There were 0
successes and 1 failures of saving groups. java.lang.RuntimeException: edu.internet2.middleware.grouper.exception.GroupAddException: group already exists with name: 'aStem:aGroup4', Here are the
possible response codes to a group save: http://viewvc.internet2.edu/viewvc.py/grouper-ws/grouper-ws/doc/api/edu/internet2/middleware/grouper/ws/soap/WsGroupSaveResult.WsGroupSaveResultCode.html?root=I2MI&view=co Do you want a special
response code for an insert that indicates the group was already there, or is
EXCEPTION good enough? Thanks, Chris From: Paul Gazda
[mailto:] Hi Chris. Thanks for the great help on how to access web services from
within a java program. Your example worked great. I am now venturing out and
trying to do a GroupSave using the GrouperClient.java code as a guide. The save
operation works, but if I try to save a group name that already exists and get
an error message, I want to be able to determine that the error was due to the
group already existing rather than some other reason. I have been unable to determine
this from the error message that is returned. I set saveMode = "INSERT" because I do not want to
modify an existing group if it exists. If the group already exists, I get this
error message: Grouper error attempting to save group. edu.internet2.middleware.grouperClient.ws.GcWebServiceError:
Bad response from web service: resultCode: PROBLEM_SAVING_GROUPS, There were 0
successes and 1 failures of saving groups. java.lang.RuntimeException: java.lang.RuntimeException: Must
not pass in a name for an insert, Problem in HibernateSession: HibernateSession: isNew: false,
isReadonly: false, grouperTransactionType: READ_WRITE_NEW, Problem in HibernateSession: HibernateSession: isNew: true,
isReadonly: false, grouperTransactionType: READ_WRITE_NEW I do not see anything in the error message that tells me the
group already exists. e.getMessage() does not give me any different
information. Is there a way I can tell if the GroupSave failure is due to
the group already existing? Thanks. Paul Gazda From: Chris Hyzer
[mailto:] I think the easiest
and best way to use grouper web services by code is to use the grouper client
API. Here is an example below that I tested and it works. All the
configuration is in the grouper.client.properties file, and you only need the
grouperClient.jar. Here are the classes you should be using: Here are all the
underlying beans: Full javadoc: http://middleware.internet2.edu/dir/groups/grouper/grouper/1.4.1/gc/api/index.html Here are example
grouper client calls: That said, I need to
put more examples on the grouper client website, if you need help doing
something, let me know and I can beef up the docs. Your other code
either needs all the dependent jars, or to use the classes in the classpath of
the grouperClient.jar. I took in a minimal number of 3rd party
jars into the grouper client jar, and changed their classpath so nothing
conflicts. I wanted this to be very easy for non java people to use, so
it is one jar and one config file, and an easy command line. Java is not
as easy to kick off with multiple jars, and less easy to upgrade etc…
there are disadvantages here (like your confusion), but I think the pros
outweigh the cons. Regards, Chris /* * @author mchyzer * $Id$ */ package edu.internet2.middleware.grouperClient.poc; import edu.internet2.middleware.grouperClient.api.GcFindStems; import
edu.internet2.middleware.grouperClient.ws.beans.WsFindStemsResults; import edu.internet2.middleware.grouperClient.ws.beans.WsResultMeta; import edu.internet2.middleware.grouperClient.ws.beans.WsStem; import
edu.internet2.middleware.grouperClient.ws.beans.WsStemQueryFilter; /** * */ public class FindStem { /** * @param args */ public static void main(String[] args) { GcFindStems gcFindStems = new
GcFindStems(); WsStemQueryFilter wsStemQueryFilter = new WsStemQueryFilter(); wsStemQueryFilter.setStemName("penn"); wsStemQueryFilter.setStemQueryFilterType("FIND_BY_STEM_NAME_APPROXIMATE");
gcFindStems.assignStemQueryFilter(wsStemQueryFilter); WsFindStemsResults wsFindStemsResults =
gcFindStems.execute(); WsResultMeta resultMetadata =
wsFindStemsResults.getResultMetadata(); if (!"T".equals(resultMetadata.getSuccess())) { throw new RuntimeException("Error finding stems: " + resultMetadata.getSuccess() + ", " + resultMetadata.getResultCode() + ", " + resultMetadata.getResultMessage()); } WsStem[] wsStems =
wsFindStemsResults.getStemResults(); if (wsStems != null) { for (WsStem wsStem : wsStems) { System.out.println(wsStem.getName()); } } } } |
- RE: Help with accessing web services, Paul Gazda, 03/02/2009
Archive powered by MHonArc 2.6.16.