Novell’s Identity Manager product has a couple of major parts to it. Of course with Identity Manager 4.0 coming out soon there are more components coming, but for now lets address the simpler model we have with the Identity Manager 3.6.1 release.
There are really two major pieces to the puzzle, and when you spend time in either part, you recognize the commonality, until you have to switch to the other side. The first is the more traditional event driven policy side. That takes events from a remote system, filters, processes, and sends them to the Identity Vault. And the converse. Then there is the second component that handles more of user interaction, the Provisioning side. This allows a user to request access to a resource can handle approvals and what not. This has evolved into a much more coherent and comprehensive solution. In fact many of the new features coming in the next release of Identity Manager will be working through the Provisioning side.
The thing about Provisioning is that it is a really big space. There is so much going on with it. I tried to explain some of that complexity in this series of articles:
I am not sure I really covered it, since I missed Roles, Resources, Teams, and much of the DAL in that article series. Anyway, I think we need more articles on the product and some of the various issues involved in running it.
The more I work in this space, the more interesting error messages I run into, and I think are worth spending some time talking about. I recently posted a discussion about errors that occur in starting a User Application JBoss application server instance in the article:
I like writing articles about error codes and error events, since I hope that others who run into it will pop some string into the Google search box and find my article which might help them with the problem.
Some of my error code articles can be found at:
AD driver related:
eDirectory driver related:
JDBC Driver Related:
SAP HR driver related:
User Application driver related:
And many other articles. You can find my entire collection of 200+ articles at:
Recently I was working on a system where we actually made a Cancel a Running Workflow workflow. Sounds silly right?
Well it turns out, if you want to cancel a running workflow in a DirXML Policy, there is no token Cancel Workflow. There is a Start Workflow token. This is basically a wrapper around the SOAP call, and it behaves very much like you would do it in soapUI or something that supports making SOAP calls.
So it is ‘easy’ to start a workflow, but hard to stop one. Well easy in the sense that there is a token. Turns out to be a bit of a tricky to use token, and I am working on more articles on that process, like these:
I have more in that series. Man have I been collecting start workflow error traces! Does that mean I am doing something right, or something wrong? You be the judge!
Well to solve the Cancel a workflow problem, we made an easy to start workflow, that when passed the Request ID value, will stop the running workflow. So yes, we call a workflow to stop a workflow. You use the cards you are dealt. Heck for a variety of reasons we did a Approve a Workflow workflow as well. These are things it would be nice to have tokens to do.
This is a trivial three step workflow. Start, make a SOAP call, and Finish. As usual the devil is in the details, and the SOAP call is quite an interesting thing and probably the topic of its own complete article. If ever you use the Integration Activity in a Workflow, you will see a very different view in Designer. This is about all that remains of the SilverStream Composer tool that was let fade into the sunset. Composer was basically an XML mapping tool, that had an astonishingly complex UI to use. (If you think Designer’s Provisioning view has a tough User Interface (UI) then you never saw Composer!) You get a small segment of it in the Integration Activity, and I wish we had more of it available to use in IDM these days! The next best thing will likely be the RaDD tool (Rapid Driver Development tool) from Omnibond, the guys who brought us the Fan out and Bi-directional Unix, Linux, Mainframe (RACF, Top Secret, and ACF2), and Midrange (AS400, aka i5os) drivers as well as the Scripting driver. They were talking about it at BrainShare and I am very much looking forward to getting my dirty little paws on it as soon as it is available! You can read more about it at:
Anyway, one of the things the Integration Activity needs is a WSDL file, the Web Services Descriptor Language file. This basically provides a definition (in XML of course, these are Web Services after all) of the available web services being provided.
Well it turns out the User Application has both SOAP and REST interfaces. I have yet to play with REST, but am getting deeper and deeper into SOAP with User Application. When you log into the User Application web page as the User App administrator, on the Administration tab you should see a Web Services pane on the bottom left. You can download the WSDL files for each of the User App components. There are WSDLs for:
Directory Layer Service
For this function, you need the Provisioning WSDL. When you drag an Integration Activity onto your Provisioning Request Definition’s (PRD) workflow pallet, you get asked immediately for a path to the WSDL file. You browse your file system, and find it. It gets parsed, and you get a list of functions made available according to the WSDL’s definitions. Now when you look in the Properties tab, when the Integration Activity is highlighted there is a WSDL path item. Alas, it does not seem editable after it is set. Indeed, to make it worse, if you check your project into SVN (Subversion, a Version Control package that Designer supports) the path is part of the code that comes to a new Designer instance, if you import the project from SVN, but the file path on Linux and Windows would be radically different (c:\projects\acme\provisioning.wsdl vs /opt/acme/data/wsdl/provisioning.wsdl).
If you are not using SVN, you are missing an opportunity to both back up your work, but also to manage changes, in case you need to revert back to get some old code versions. Version control is really important, and it forms if absolutely nothing else a form of backup. But more so, in the case of Policy stuff, it is pretty easy when making major code changes, to copy the current mostly working rule, disable one copy, and work in the new copy so that you can easily fall back if you make a mistake.
In Provisioning this is much harder, and often simple changes can require complex changes. With SVN you could revert back, grab some code you changed in a way that ended up being incorrect, move forward back to the current project state, and paste the pieces back in.
But if you are using SVN, then the file path issue becomes an issue when you try to work on a different machine. We ran into this recently at a client, where Designer started showing this error as soon as we tried to open the Provisioning Request Definition (PRD) for the Cancel a Workflow workflow:
java.lang.NullPointerException at com.novell.soa.eai.integrationActivity.impl.IntegrationActivity.initFromEMF(IntegrationActivity.java:350) at com.novell.soa.eai.integrationActivity.impl.IntegrationActivity.setOriginalWSDLDoc(IntegrationActivity.java:361) at com.novell.soa.eai.integrationActivity.impl.IntegrationActivity.setup(IntegrationActivity.java:265) at com.novell.soa.eai.integrationActivity.impl.IntegrationActivity.read(IntegrationActivity.java:216) at com.novell.soa.eai.integrationActivity.impl.IntegrationActivity.readEMF(IntegrationActivity.java:202) at com.novell.prov.prd.ui.workflow.model.ActivityDiagram.initChildren(ActivityDiagram.java:171) at com.novell.prov.prd.ui.workflow.model.ActivityDiagram.
(ActivityDiagram.java:71) at com.novell.prov.prd.ui.workflow.FlowEditor.setInput(FlowEditor.java:997) at org.eclipse.gef.ui.parts.GraphicalEditor.init(GraphicalEditor.java:318) at com.novell.prov.prd.ui.workflow.FlowEditor.init(FlowEditor.java:690) at com.novell.prov.prd.ui.PRDEditor.createWorkFlowPage(PRDEditor.java:464) at com.novell.prov.prd.ui.PRDEditor.createPages(PRDEditor.java:608) at org.eclipse.ui.part.MultiPageEditorPart.createPartControl(MultiPageEditorPart.java:310) at org.eclipse.ui.internal.EditorReference.createPartHelper(EditorReference.java:661) at org.eclipse.ui.internal.EditorReference.createPart(EditorReference.java:428) at org.eclipse.ui.internal.WorkbenchPartReference.getPart(WorkbenchPartReference.java:594) at org.eclipse.ui.internal.EditorReference.getEditor(EditorReference.java:266) at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditorBatched(WorkbenchPage.java:2820) at org.eclipse.ui.internal.WorkbenchPage.busyOpenEditor(WorkbenchPage.java:2729) at org.eclipse.ui.irnal.WorkbenchPage.access$11(WorkbenchPage.java:2721) at org.eclipse.ui.internal.WorkbenchPage$10.run(WorkbenchPage.java:2673) at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2668) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2652) at org.eclipse.ui.internal.WorkbenchPage.openEditor(WorkbenchPage.java:2643) at com.novell.prov.pal.ui.actions.handler.ProvActionHandler.handleOpenAction(Unknown Source) at com.novell.prov.pal.ui.actions.handler.ProvActionHandler.handleAction(Unknown Source) at com.novell.prov.pal.ui.provview.views.ProvisioningView$6.run(Unknown Source) at com.novell.prov.pal.ui.provview.views.ProvisioningView$8.doubleClick(Unknown Source) at org.eclipse.jface.viewers.StructuredViewer$1.run(StructuredViewer.java:799) at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37) at org.eclipse.core.runtime.Platform.run(Platform.java:880) at org.eclipse.ui.internal.JFaceUtil$1.run(JFaceUtil.java:48) at org.eclipse.jface.util.SafeRunnable.run(SafeRunnable.java:175) at org.eclipse.jface.viewers.StructuredViewer.fireDoubleClick(StructuredViewer.java:797) at org.eclipse.jface.viewers.AbstractTreeViewer.handleDoubleSelect(AbstractTreeViewer.java:1419) at org.eclipse.jface.viewers.StructuredViewer$4.widgetDefaultSelected(StructuredViewer.java:1173) at org.eclipse.jface.util.OpenStrategy.fireDefaultSelectionEvent(OpenStrategy.java:237) at org.eclipse.jface.util.OpenStrategy.access$0(OpenStrategy.java:234) at org.eclipse.jface.util.OpenStrategy$1.handleEvent(OpenStrategy.java:295) at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1003) at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3823) at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3422) at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2384) at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2348) at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2200) at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:495) at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:288) at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:490) at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) at com.novell.idm.rcp.DesignerApplication.start(DesignerApplication.java:118) at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:193) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:386) at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:549) at org.eclipse.equinox.launcher.Main.basicRun(Main.java:504) at org.eclipse.equinox.launcher.Main.run(Main.java:1236)
As usual with Java errors, the final error is often not that useful. You can see this by focusing in on the first three lines of the error message:
java.lang.NullPointerException at com.novell.soa.eai.integrationActivity.impl.IntegrationActivity.initFromEMF(IntegrationActivity.java:350) at com.novell.soa.eai.integrationActivity.impl.IntegrationActivity.setOriginalWSDLDoc(IntegrationActivity.java:361) at com.novell.soa.eai.integrationActivity.impl.IntegrationActivity.setup(IntegrationActivity.java:265) at com.novell.soa.eai.integrationActivity.impl.IntegrationActivity.read(IntegrationActivity.java:216) at com.novell.soa.eai.integrationActivity.impl.IntegrationActivity.readEMF(IntegrationActivity.java:202)
Null Pointer Exception seems like the most common Java error I run into and is functionally meaningless, beyond telling you that the value it was given to look at is missing or incorrect. Oh well. However, if you look at the function classes that are in the Java stack, you can see a number of things. First lets look at the basic class path for most of these calls, which is:
Well lets break that down. The first part, com.novell makes it clear that although we are working in Designer which is really a Java application environment called Eclipse with custom plugins from Novell, this is a Novell class being called that is erroring.
Next we see ‘soa’, which I think stands for Service Oriented Architecture, which is really another way of saying Web Services, or at least a model of a multi tier system, in which web services are often involved.
Enterprise Application Integration, ‘eai’ is yet another flavour of SOAP related functionality. I do not know the correct words for each of these pieces along the way, but it is sufficient to know this is all SOAP related.
integrationActivity.impl.IntegrationActivity is the next part and makes it clear what part of the functionality we are working in. This is all about the SOAP integration activity we are using inside the PRD.
Finally, lets look at the first few functions within that Integration Activity class that are involved. We have:
You actually read these sometimes from the bottom up, other times top down. Starting all the way at the bottom is too much information, as who cares if it is related to drawing a window or some other low level Eclipse function. Usually what we want it is at the top of the stack. But once you are at the top, you want to read the last 3-6 items from the bottom up.
EMF is the Eclipse Modeling Framework, which is how Eclipse (The underlying environment that is Designer) reads and manages data. So when we see readEMF being called, we know it is reading some kind of information for the window about to be opened as an Eclipse window. Read then setup make sense as being the next logical steps.
Finally we get to the heart of the issue, the setOriginalWSDLDoc, well in my case, I was running Designer 3.5.1 on Windows XP, and my colleague who had checked in the project to our shared SVN server was running 64 bit Open SUSE on his laptop. Obviously the path to the WSDL is different on Linux than it would be on Windows as I gave the example earlier.
Now as it turns out if you edit the PRD file in a text editor, from within the Designer Workspace, you can see the actual line that defines the file. Hehe. I love editing files raw. You do need to be careful, since the file contains the localization information, and if you save it incorrectly you will loose all your localization information.
What we did was copy the file to a local path, and then edit the PRD file to point at the right location.
What I found interesting was that the Integration Activity is stored within that PRD as a Base64 encoded string and it looks like the contents of the WSDL functions are included in the definition, so having the file seems kind of redundant. But Designer will error if you do not have it correctly when you try and open the PRD.
Hopefully if anyone else runs into this issue, it will help you figure out what is going on faster. More importantly I hope that the approach I took in figuring out what was happening in the unhelpful top level error (Null Pointer Exception) by looking at the Java stack trace will be useful in figuring out what is causing other errors you might run into.
Disclaimer: As with everything else at NetIQ Cool Solutions, this content is definitely not supported by NetIQ, so Customer Support will not be able to help you if it has any adverse effect on your environment. It just worked for at least one person, and perhaps it will be useful for you too. Be sure to test in a non-production environment.