.NET API for Oracle UCM Version 2.0

The past few weeks I’ve been revisiting one of my old projects, the .NET API for Oracle UCM, which I’ve always felt was powerful but also missing some functionality.  The original project was a pretty simple API modeled after Oracle’s own idcserver package usually used in Site Studio JSP development.  I’ve always liked the simplicity of the idcserver API as you can basically make any content server service call using just a couple of simple objects.  Implementing the same design in .NET(and later Flex) turned out to be a pretty successful(I think) model as well.  The original API is one of the most popular downloads and I’ve received quite a bit of positive feedback about it.

What’s new with Version 2.0

The improvements to version 2.0 center around a couple different areas:

Direct communication with the content server

This was probably my biggest motivator towards developing a new version of the API as the web filter to content server communication is somewhat of an undocumented mystery.  I’ve written a couple custom filters to integrate UCM with some third part security/SSO providers, but never have really picked apart the actual protocol that’s going back and forth.  Turns out it’s basically just passing HTTP through, but there are a couple values you can add to set authentication.

If you’re ever curious about what happens after your request is made to the web server, you can actually connect to the content server on its listener port(usually 4444) with a telnet terminal.  If you turnon  the CGI_SEND_DUMP on from the filter administration page it will log all calls made to the content server from the web server plugin.  Those logged requests can then be copied out of the log, modified and then pasted in to the telnet window.  Make sure that if you’re using telnet or even this API that the server you are executing from is included in the host or IP filter for the content server, else you won’t be able to connect.

Asynchronous, Multithreaded Execution

I started out planning for just asynchronous execution and then broke a bit more off with the threading(threads are addictive).  What I was looking for was the capability to make a content server request and then for the result to be passed back via an event.  The previous version’s process consisted of an executeService call, waiting inline until the request is completed and then retrieving results from the ServerBean.  The entire process usually takes less than a second, but a more elegant method might be for the executeService call to be made and then for an event handler to process the results when they arrive.  This new version supports the old method and the new event handler.

In addition to the events, the API is also multi threaded so when running in asynchronous mode each content server request runs in it’s own in it’s own thread.  Calling executeService will queue up a content server request and also create and activate a new execution object for your next call.

The API has a setting for the maximum number of threads which can run concurrently.   So if you make 1000 requests the content server will not receive 1000 requests all on top of each other.  Rather it will queue up all 1000 requests, keeping only the max number of threads active during processing.

The Object Model

In copying the idcserver package, I originally figured copying the idcserver object model would make things easier to pick up and learn, but unfortunately I think it was also a little trickier to extend and customize.  The API was flexible and powerful, but if you wanted to build a more robust API, say one specific to your application or organization, things were a bit trickier to extend.

In this new version I’ve set up a more flexible object model(as well as breaking backwards compatibility..sorry about that).  Every object used in the API is referenced by interface, but also encapsulates all functionality in abstract classes.  The only class that this does not apply to is the ExecutionManagerFactory, which is basically a static class used only to create a new ExecutionManager object (the new server bean).

Some Examples

Looking at some code examples with the new API, you’ll find that for the most part they aren’t too different than the old version.  Most of the methods are still named the same only the object types have changed.

Check In New

This example is a synchronous inline operation which checks in a file.  If you compare it to code used with version 1 the similaritites should pop right out.

static void CheckInAFile()
{
  //create a new execution manager object
  ICSExecutionManager em = ExecutionManagerFactory.CreateExecutionManager();
  //set the connection mode.  We're going direct to the content server
  em.ConnectionDetails.ConnectionMode = ConnectionMode.ContentServer;
  //set the host
  em.ConnectionDetails.ContentServerHost = "localhost";
  //set the relative web root
  em.ConnectionDetails.ContentServerRelativeWebRoot = "stellent";
  //set the user to run the operation under
  em.ContentServerUser = "sysadmin";
  //set the service and other metadata
  em.putLocal("IdcService", "CHECKIN_NEW");
  em.putLocal("dDocTitle", "Picture of Me");
  em.putLocal("dDocType", "Image");
  em.putLocal("dSecurityGroup", "Public");
  em.putLocal("dDocAuthor", "sysadmin");
   //set the file
   em.putLocal("primaryFile", new FileInfo(@"C:\file.jpg));
   //execute the service
   em.executeService();
   //check the response
   Console.WriteLine(em.getLocal("StatusMessage"));
 }

This example demonstrates how the asyncronous, multi-threaded execution is utilized. The code will execute three search calls as three different users on the content server. Each execution will occur in it’s own thread, with the results being handled by the same event.


static void AsyncSearchByUser(){
  //create a new execution manager object
  ICSExecutionManager em = ExecutionManagerFactory.CreateExecutionManager();
  //set the connection to the content server
  em.ConnectionDetails.ConnectionMode = ConnectionMode.ContentServer;
  //set the host
  em.ConnectionDetails.ContentServerHost = "localhost";
  //set the relative web root
  em.ConnectionDetails.ContentServerRelativeWebRoot = "stellent";
  //this will be Asynchronous execution
  em.ProcessMode = ProcessMode.Asynchronous;
  //attach a complete event
  em.OnExecutionComplete += new OUCSNET.events.ExecutionCompleteHandler(SearchOnExecutionComplete);

//first call will be as the user droe
  em.ContentServerUser = "droe";
  //set the search crtiera, we want a count of everything
  em.putLocal("IdcService", "GET_SEARCH_RESULTS");
  em.putLocal("QueryText", "");
  //execute the server.
  //Since this is Asynchronous, exection will continue right on
  //with this search result request running in it's own thread
  em.executeService();

//Once executeService is called a new Execution object is created
  //and made active in the execution manager
  //even though its the same em interface this is a new execution
  //object

//this one will run as sysadmin
  em.ContentServerUser = "sysadmin";
  em.putLocal("IdcService", "GET_SEARCH_RESULTS");
  em.putLocal("QueryText", "");
  em.executeService(); //execute and move on

//repeat running as user
  em.ContentServerUser = "user";
  em.putLocal("IdcService", "GET_SEARCH_RESULTS");
  em.putLocal("QueryText", "");
  em.executeService();

//Since we are running asynchronously
  //this should be the first line in the std out.
  Console.WriteLine("All Executions Called");
}

//The event handler for the exection object
static void SearchOnExecutionComplete(object sender, EventArgs e)
{
  //convert the sender object to an ICSExecution object
  ICSExecution execution = (ICSExecution)sender;
  //output some results
  Console.WriteLine(execution.ContentServerUser
 + " can access "
 + execution.getLocal("TotalRows")
 + " content items");
  //disposing the execution object will remove it
  //from the internal list of execution objects
  execution.Dispose();
}

Probably More Work To Do

There is an outstanding issue with the API, with regards to NTLM authentication.  The previous version utilized the .NET WebRequest object for content server communication which supported NTLM authentication.  This version, because it needs to connect to both the web server and the content server directly is using the TCPClient object which is basically one step up from a raw socket connection.  Any protocols(beyond TCP) need to be implemented manually, and NTLM has been a bit tricky to configure, basic authentication however seems to work just fine.

This version of the API obviously has quite a bit more functionality in it and I fully expect there to be some bugs that appear(though I hope they don’t).  At the very least I think there will probably be some suggestions for better behavior by API, and so if have some or if you find an issue, please let me know by posting them to the forums.

Not The Last Version

This will not be the last version of the API, so if you have any ideas I’d love to hear them.  Eventually I’m hoping this project will develop in to something close to par with Oracle’s own Content Integration Suite.  So far I am loosely planning on developing some web examples using the API with ASP.NET as well as some examples for .NET 3.5.

The new version of the API can be downloaded here:

.NET API for Oracle UCM Version 2.0

About David Roe

Thanks for visiting ContentOnContentManagment.com, my name is David Roe and this is my blog. I work for Ironworks Consulting as a technical lead/architect in our enterprise content management group. My primary focus is implementing Oracle Universal Content Server, which was formerly known as Stellent Content Server. Prior to focusing in Stellent, my work centered around .NET integrations with other content managment systems as well as content management systems built on the .NET framework. I plan on keeping this blog mostly technical in nature. I’m not really one for the Coke vs. Pepsi debates, so plan on seeing quite a bit of ”how to” content. Please feel free to download and use any of the code examples available on the site. As you might imagine none of it is supported or warented..do we need a disclaimer? I do ask that you leave any references to me or this site in the comments though.
This entry was posted in .NET, C#, Content Management. Bookmark the permalink.

3 Responses to .NET API for Oracle UCM Version 2.0

  1. spooner says:

    Hi,

    Is it possible to set the HTTP_INTERNETUSER variable when connecting to the web server rather than the content server?

    We’ve currently got a library at the moment that uses the WSDL Generator component, but I couldn’t see anything that can be done with that security wise other than setting a username/password pair.

  2. David Roe says:

    The short answer is yes, though you would have to modify the API a little to add the value to the headers.

    The question I would have though is “why do you need to?”. Version 2 of the API supports basic authentication and version 1 also supports NTLM.

    If you use version 2(this one), than you can connect straight in to the content server and will only need the user name.

  3. Pingback: David Roe Updates .Net API for Oracle ECM « John’s Blog