DFS Object service consumer #2a

Rather than leverage the DFS SDK-based .NET assemblies to consume DFS services, some may prefer to leverage Visual Studio’s ability to proxy WSDL/XSD directly and choose instead to involve the Windows Communication Foundation (WCF) designer via Add Service Reference… In this post, I will discuss just such a sample application.

As in the previous example, we’ll build the same Windows Forms application to accomplish the same task (i.e. object name retrieval given object id); however we’ll ignore the .NET productivity layer and proxy the Object service contract directly using Visual Studio and WCF.

After launching Visual Studio, choosing File | New | Project… and creating a new Windows Forms Application project called ObjectServiceConsumer, go to the Solution Explorer, select the project node, right-click and choose Add Service Reference…

Enter the address for the DFS Object service instance to proxy (e.g. the same instance used in the previous example’s browser-based accessibility test). Click Go, and you should see something similar to the dialog captured above. Set the namespace for this reference and choose OK.

Return back to Visual Studio, double-click Form1.cs, after building the same dialog as in the previous example, double-click on the Retrieve button. This will tell Visual Studio to transition from (Windows Forms) designer mode to code editing mode.

Implement your button click handler as follows:

string repositoryName = txtbxRepoName.Text;
string userName = txtbxUserName.Text;
string password = txtbxPwd.Text;
string objId = txtbxObjId.Text; // e.g. a document id of 09123456789abcde

try
{
    ObjectId objectId = new ObjectId();
    objectId.id = objId;
    ObjectIdentity objectIdentity = new ObjectIdentity();
    objectIdentity.Item = objectId;
    objectIdentity.repositoryName = repositoryName;
    ObjectIdentitySet objectIdentitySet = new ObjectIdentitySet();
    objectIdentitySet.Identities = new ObjectIdentity[1];
    objectIdentitySet.Identities[0] = objectIdentity;

    PropertyProfile propertyProfile = new PropertyProfile();
    propertyProfile.filterMode = PropertyFilterMode.SPECIFIED_BY_INCLUDE;
    string[] includeProperties = {"object_name"};
    propertyProfile.IncludeProperties = includeProperties;
    OperationOptions operationOptions = new OperationOptions();
    operationOptions.Profiles = new Profile[1];
    operationOptions.Profiles[0] = propertyProfile;

    DataPackage dataPackage = objectService.get(objectIdentitySet, operationOptions);

    Property[] properties = dataPackage.DataObjects[0].Properties.Properties;
    foreach (Property property in properties)
    {
        if (property.name.Equals("object_name"))
        {
            lblObjName.Text = property.ToString();
        }
    }

    Console.WriteLine("Successfully retrieved object name for object id" + "'" + objId + "': " + lblObjName.Text);
}
catch (Exception ex)
{
    lblObjName.Text = "<error>";
    Console.WriteLine(ex.StackTrace);
    Console.WriteLine("Failed to retrieve object name with exception " + ex.Message);
}
finally
{
    Console.WriteLine("Your cleanup logic goes here.");
}

A few points concerning the above code:

  • There is a private field on the Form class, objectService, that is of type ObjectServicePortClient (i.e. from the WCF-generated proxy code) and is set to null initially.
  • In the Form class constructor, after the standard Windows Forms InitializeComponent(), objectService is set as follows: new ObjectServicePortClient(“ObjectServicePort”);
  • “ObjectServicePort” is a named binding in the WCF-generated proxy code (i.e. declared within app.config).
  • As in the previous example, I’m using a pre-release version of DFS 6.5 for this example, but I’m not using anything that isn’t available in DFS 6.0 SP1–this is a very simple example by design.
  • You should notice some cosmetic differences between the code above and the code here (e.g. more verbose, fewer conveniences, etc.).

You should now be able to build your application and run it. When you enter a valid object id for the specified repository connection, you should see the object name replace “<tbd>” on the dialog.

But, you don’t. Why?

Well, first of all, if you are running your application server with a console window for output message capture, you likely saw the following message:

. . . com.emc.documentum.fs.rt.SerializableException: Authorization failed, could not find identities in service context with token “temporary/127
.0.0.1-1216079837407–1167916486618885387″
        at com.emc.documentum.fs.services.core.ObjectServiceWebService.get(ObjectServiceWebService.java:268) . . .

Looking at the code above, it’s hopefully clear that the variables userName and password aren’t employed. (If you’re using the JetBrains ReSharper add-in for Visual Studio, the IDE (plugin) actually visually indicates this condition.)

So, let’s do some detective work.

Using a web debugging proxy (e.g. Charles), re-run the above code (i.e. with port forwarding in place). After valid data entry and clicking the Retrieve button, you should see an entry in your web debugging proxy session. Examine the SOAP request message (i.e. “pretty printed” for readability’s sake):

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <get xmlns="http://core.services.fs.documentum.emc.com/">
            <forObjects isInternal="false" xmlns="">
                <Identities repositoryName="_DOCBASE_" xmlns="http://core.datamodel.fs.documentum.emc.com/">
                    <ObjectId id="09003023800024ec"/>
                </Identities>
            </forObjects>
            <options xmlns="">
                <Profiles xsi:type="q1:PropertyProfile" isProcessIncludedUnknown="false" xmlns="http://core.datamodel.fs.documentum.emc.com/" xmlns:q1="http://profiles.core.datamodel.fs.documentum.emc.com/">
                    <q1:IncludeProperties>object_name</q1:IncludeProperties>
                </Profiles>
            </options>
        </get>
    </s:Body>
</s:Envelope>

Next, go back to the previous example, and re-run it to capture its SOAP request message. Before you hit Run, though, comment out the following line of code:

context = contextFactory.Register(context);

(We’ll talk more about this in a future post.)

The DFS SDK .NET assemblies-based application issues the following SOAP request message:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Header>
        <ServiceContext token="temporary/127.0.0.1-1216195928765-692634301" xmlns="http://context.core.datamodel.fs.documentum.emc.com/">
            <Identities xsi:type="RepositoryIdentity" userName="_USER_" password="_PWD_" repositoryName="_DOCBASE_" domain="" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
            <RuntimeProperties/>
        </ServiceContext>
    </s:Header>
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <get xmlns="http://core.services.fs.documentum.emc.com/">
            <forObjects isInternal="false" xmlns="">
                <Identities repositoryName="_DOCBASE_" valueType="OBJECT_ID" xmlns="http://core.datamodel.fs.documentum.emc.com/">
                    <ObjectId id="09003023800037c6"/>
                </Identities>
            </forObjects>
            <options xmlns="">
                <Properties xmlns="http://core.datamodel.fs.documentum.emc.com/"/>
                <Profiles xsi:type="q1:PropertyProfile" filterMode="SPECIFIED_BY_INCLUDE" xmlns="http://core.datamodel.fs.documentum.emc.com/" xmlns:q1="http://profiles.core.datamodel.fs.documentum.emc.com/">
                    <q1:IncludeProperties>object_name</q1:IncludeProperties>
                </Profiles>
            </options>
        </get>
    </s:Body>
</s:Envelope>

Yep, there’s definitely a missing header in today’s sample, as coded above. :-)

It’s also worth noting a few things before continuing:

  • The code above requires SSL to avoid cleartext data being sent over the wire. Of course, SSL–and replacing http://… with https://…–only provides transport-level security that is point-to-point in nature (i.e. compared with message-level security that is end-to-end in nature).
  • valueType=”OBJECT_ID” – this is missing on the <Identities> element in today’s example but is present in the previous example
  • <Properties xmlns=”http://core.datamodel.fs.documentum.emc.com/”/> – this is missing in today’s example but is present in the previous example
  • filterMode=”SPECIFIED_BY_INCLUDE” – this is missing on the <Profiles> element in today’s example but is present in the previous example
  • isProcessIncludedUnknown=”false” – this is present in today’s example but is missing in the previous example

Before we solve the case of the missing header, let’s resolve the differences just listed:

...
ObjectIdentity objectIdentity = new ObjectIdentity();
objectIdentity.valueType = ObjectIdentityType.OBJECT_ID; //FIX
objectIdentity.valueTypeSpecified = true; //FIX
...
propertyProfile.filterMode = PropertyFilterMode.SPECIFIED_BY_INCLUDE;
propertyProfile.filterModeSpecified = true; //FIX
...
OperationOptions operationOptions = new OperationOptions();
...
operationOptions.Properties = new PropertySet(); //FIX
...

As for the isProcessIncludedUnknown-based difference aforementioned, a quick read of the reference-level documentation for PropertyProfile.setProcessIncludedUnknown() is helpful: “If false, ignore any property in the includeProperties list that is not a property of the repository type. If true, throw an exception if such a property is specified in the includeProperties list. Default value is false.” That is, the WCF-generated proxy makes this default explicity in its SOAP messages; so, although the two XML messages have this difference, they are functionally equivalent.

Next: Leveraging WCF extensibility to add the missing header that the DFS Object service expects…

DFS Object service consumer #1

In a previous post, I introduced web service support in the EMC Documentum platform for the Microsoft-oriented developer. (BTW, sorry for the time lapse since that post to this one–busy getting an important set of products ready for on-time release. :-) ) In this post, I will focus on such support as provided with DFS via the .NET assemblies (aka productivity layer) within the DFS SDK.

Let’s build a simple Windows Forms application using Microsoft Visual Studio 2008. The purpose of this application will be to retrieve the object name from a piece of content in a Documentum repository associated with a particular object id:

After launching Visual Studio, choosing File | New | Project… and creating a new Windows Forms Application project called ObjectServiceConsumer_PL, go to the Solution Explorer, select the References node under the project, right-click and choose Add Reference…

Navigate to your DFS SDK installation and select the set of .NET assemblies that support the DFS Object service. For example, I tend to install the SDK directly under my C: drive; so, I navigated to C:\emc-dfs-sdk-6.5\lib\dotnet:

(Yes, I’m using a pre-release version of DFS 6.5 for this example, but I’m not using anything that isn’t available in DFS 6.0 SP1–this is a very simple example by design.)

The result under the References node should be as follows:

If you’re already developing with .NET 3.5, you may notice that a couple of .NET 3.5 assemblies are missing in the above view. That’s because I decided to target .NET 3.0 for this example since I don’t require anything more from Windows Communication Foundation since its first release (i.e. DFS supports WCF “v1″ in .NET 3.0).

At this point, verify that you will be able to access an instance of the DFS Object service from your application. That is, deploy emc-dfs.ear file via the standalone DFS installer or with the Content Server installer. Launch your browser of choice and retrieve DFS Object service WSDL (e.g. http://localhost:8080/services/core/ObjectService?wsdl). You should see the service contract in your browser.

Return back to Visual Studio, double-click Form1.cs, after building the dialog shown above, double-click on the Retrieve button. This will tell Visual Studio to transition from (Windows Forms) designer mode to code editing mode.

Implement your button click handler as follows:

string repositoryName = txtbxRepoName.Text;
string userName = txtbxUserName.Text;
string password = txtbxPwd.Text;
string objId = txtbxObjId.Text; // e.g. a document id of 09123456789abcde

try
{
    ContextFactory contextFactory = ContextFactory.Instance;
    IServiceContext context = contextFactory.NewContext();
    RepositoryIdentity repoId = new RepositoryIdentity(repositoryName,
                                                       userName,
                                                       password,
                                                       "");
    context.AddIdentity(repoId);

    context = contextFactory.Register(context); // Module and ContextRoot from app.config
    ServiceFactory serviceFactory = ServiceFactory.Instance;

    IObjectService objectService =
        serviceFactory.GetRemoteService<IObjectService>(context); // Module and ContextRoot from app.config

    ObjectId objectId = new ObjectId(objId);
    ObjectIdentity objectIdentity = new ObjectIdentity(objectId, repositoryName);
    ObjectIdentitySet objectIdentitySet = new ObjectIdentitySet(objectIdentity);

    PropertyProfile propertyProfile = new PropertyProfile();
    propertyProfile.FilterMode = PropertyFilterMode.SPECIFIED_BY_INCLUDE;
    propertyProfile.IncludeProperties.Add("object_name");

    OperationOptions operationOptions = new OperationOptions();
    operationOptions.Profiles.Add(propertyProfile);

    DataPackage dataPackage = objectService.Get(objectIdentitySet, operationOptions);

    List<Property> properties = dataPackage.DataObjects[0].Properties.Properties;

    if (properties != null)
    {
        properties.ForEach(delegate(Property property)
                               {
                                   if (property.Name.Equals("object_name"))
                                   {
                                       lblObjName.Text = property.ToString();
                                   }
                               });
    }

    Console.WriteLine("Successfully retrieved object name for object id" + "'" + objId + "': " + lblObjName.Text);
}
catch (Exception ex)
{
    lblObjName.Text = "<error>";
    Console.WriteLine(ex.StackTrace);
    Console.WriteLine("Failed to retrieve object name with exception " + ex.Message);
}
finally
{
    Console.WriteLine("Your cleanup logic goes here.");
}

As noted above in code comments, you should add an Application Configuration File item to your project. After doing so, open the new app.config file in Visual Studio, select its contents and paste (overwrite) them with the contents copied from the sample App.config file in the DFS SDK (i.e. C:\emc-dfs-sdk-6.5\etc\config\App.config). Be sure to modify data relative to your running DFS Object service instance (e.g. ModuleInfo element attributes like port).

You should now be able to build your application and run it. When you enter a valid object id for the specified repository connection, you should see the object name replace “<tbd>” on the dialog.

Obviously this is a trivial sample. However, as I mentioned this is be design, since what I want to do next is contrast this sample with the same goal implemented without DFS SDK .NET assemblies (i.e. using just Visual Studio, its WCF designer and DFS WSDL/XSD content).

You can download the Visual Studio 2008-based solution for today’s sample here.

Next: Using DFS WSDL/XSD (sans DFS SDK .NET assemblies) from Visual Studio…

Web services, Microsoft developers, WSF and DFS

Shortly after the Documentum 5.2.5 release, customer interest in web services piqued in conjunction with Documentum’s investment in services via service-based business objects. SBOs, as they’re typically referred to, are supported in the Business Object Framework (BOF), which is the codified customization framework for DFC.

So, in order to preserve customer investment in SBOs, the Web Service Framework (WSF) was first released as part of the 5.3 platform release.

Not every SBO is designed to be projected as a web service, though. So, best practice documentation was published to the developer network, which for the most part just captures common sense. (I used to call these web service SBOs “WSBOs.”)

However, service-orientation at the time of D5.3 development was noticeably different than at the time of D6 development. There needed to be a way to target a broader base of existing service implementations (e.g. POJOs) into the realm of Enterprise Content Services.

Rather than controlling web services by insisting on a DFC/BOF (SBO) investment, it was clear that EMC Documentum needed to participate with broader business systems and processes. So, targeting plain old Java objects became a requirement, while also supporting DFC/BOF-based implementations for existing customers.

Rather than forcing service chains to align on content transfer approach, it was clear that EMC Documentum needed to support content transfer choice, empowering each link (service) in the chain to process content on its terms (e.g. as a file or as a stream).

At the same time, the 6.0 platform release provided additional facilities concerning distributed content. So, any new service-oriented offering from EMC Documentum needed to integrate with these facilities and increase their adoption via ease-of-use (integration).

Documentum Foundation Services (DFS) was first released as part of the 6.0 platform release and was designed to meet these, and several other, objectives.

Which brings us back to the .NET-oriented developer. How does DFS service these individuals?

More on each approach, next…

DFC, Microsoft developers, .NET and DFC PIA

In early 2002 Microsoft released .NET 1.0, and it was quite clear that .NET would quickly supplant COM as the mainstream runtime for the Microsoft platform.

Fortunately, .NET provided good (bi-directional) interop with COM (e.g. callable wrappers and interop assemblies). Furthermore, software publishers (ISVs) could produce primary interop assemblies (PIAs) to add functional, deployment and administrative value above that produced by simply pointing Visual Studio at a type library.

So, based on customer requirements and demand, the DFC PIA was born and was first released with DFC 5.2.5.

DFC, DJCB and DFC PIA in relationship

Beyond just producing a strong-named assembly using a Documentum private key, DFC PIA included additional performance tuning as well as some convenience features like advertising deprecated APIs, IntelliSense support in Visual Studio via robust XML documentation, and HTML Help content with example usage. By virtue of being a strong-named assembly, subsequent versions of the DFC PIA shipped with a publisher policy file and assembly, allowing customers to redirect their DFC PIA 5.2.5 consumers to a newer version of the PIA.

Both Documentum Desktop and Documentum Application Builder announced end-of-life plans around D5.3; so the internal need for DJCB was coming to a close. This opportunity was leveraged to reconsider current platform support for .NET developers and what would be needed in the future (e.g. web services). Several data points arose that suggested the need to reset interoperability as follows:

  • Java and .NET are both managed language platforms. A key management facility in both is known as garbage collection. A garbage collector (GC) is responsible for reclaiming resources based on object reference state and other criteria. The Java GC and the .NET GC don’t recognize each other; yet both GC’s can be resident in the same process space. Given this situation, the potential for resource exhaustion due to improper object reference coding arises. In .NET, all COM objects including objects implementing COM interfaces must be released using Marshal.ReleaseComObject or Marshal.FinalReleaseComObject; otherwise, the underlying resources cannot be reclaimed by a GC.
    • Marshal.ReleaseComObject/Marshal.FinalReleaseComObject is low-level “plumbing” code, and as such is typically not the primary domain concern of the business developer.
    • Recall that the DFC .NET interface is the projection of a DFC COM interface, which is, in turn, a projection of a DFC Java interface. The implementation of this interface projection is shared amongst a Java archive (JAR file), a Java-COM bridge DLL and an in-process assembly (PIA). All of this, again, is low-level plumbing that the business developer would rather not be burdened with; however, appropriate Marshal.ReleaseComObject/Marshal.FinalReleaseComObject calls have been delegated unto them.
  • DJCB (and therefore DFC PIA) is about core DFC, not about DFC customizations via BOF (i.e. type-based or service-based business objects–TBOs or SBOs). So, to get similar .NET interop for a custom business object, you would have to re-apply Java-COM bridge technology to that API–assuming that it’s well-formed for .NET interop–and then produce a PIA for the custom business object using the bridge’s COM type library–all low-level plumbing.
    • “Java-COM bridge + PIA” doesn’t scale as well as web services in terms of integration cost. DFS supports web services natively and was designed from the very beginning with SOA in mind.
  • COM has a hard limit of no more than 255 methods per interface. Most object-oriented systems may not encounter this constraint; however, DFC does with respect to sysobject-derived interfaces. That is, DFC 5.3 was OK; however, DFC 6.0 and thereafter surpassed this upper limit. So DJCB literally cannot be revised to accommodate the DFC 6.0 interface, again due to COM-based limitations. Since DJCB is so-constrained, DFC PIA is also limited.
    • Arguably, this highlights the value of Aspects in DFC/BOF.
    • This also highlights why DFS is absolutely not a web service projection of the DFC API. Rather DFS is a coarser-grained API that is less chatty and less overwhelming to understand (e.g. where total number of API methods is concerned).
    • In other words, DFC 6.0 was not developed with DJCB/PIA exposure, unlike DFC 5.3 and 5.3 service packs.
  • There are aspects of the DFC Java API that are not interoperable. Perhaps the most requested feature request concerns byte stream support. That is, DFC specifies ByteArrayInputStream, but .NET doesn’t recognize this Java type.
    • DFS supports byte streaming use cases as follows:
      1. The application invokes DFS from the middle tier, gets a byte array–DFS doesn’t write to disk–which is then returned by the application to the end user.
      2. The application invokes DFS from the middle tier, gets a URL which is then which is then passed by the application to the end user. The end user can stream the content using the URL.
      3. The application invokes DFS from the middle tier. UCF client is deployed on the end user box. Content is streamed by UCF from the CS machine directly to the end user.
    • Also ByteArrayInputStream can be impractical even for Java-based solutions, since the type puts all data in memory (e.g. large file transfer concerns).

Next: Data access (ADO.NET)…

DFC, Microsoft developers, COM and DJCB

Prior to DFS, the primary solution-building, business logic-focused EMC Documentum platform API was Documentum Foundation Classes (DFC).

When I joined Documentum (now EMC) over ten years ago, DFC was under development as part of the significant 4i release (aka “Project Piper”). Back then Microsoft shipped a leading JVM and had one of the best IDEs for Java in Visual J++, according some of my then hardcore Java programming friends. The MSJVM intrinsically supported–among other “features” like delegates that led to the Java cold war (lawsuit) between Sun and Microsoft–interoperability with Microsoft’s major runtime play at that time called COM.

The aforementioned cold war led to Microsoft dropping development and support of MSJVM (and led to .NET, J# and JLCA), ending its Java support with the then-outdated 1.1.4 release from Sun. This meant that in order to support COM-based interop from Java you had to either build or buy. And a build-versus-buy decision was especially relevant to Documentum at the time given that the most widely used client/application was Desktop (aka Desktop Client, or just DTC–later called Desktop Development Kit), not to mention the MFC-based Developer Studio (later called Documentum Application Builder (DAB), which is now replaced by Composer). We opted for build, since there was no buy option available then that met our requirements, and the Documentum Java-COM Bridge (DJCB) was born and was first released with DFC 5.0.

DJCB enabled us to project DFC Java types as DFC COM types via COM type libraries and IDL. It also enabled Documentum to adopt newer JVM technology (e.g. Java 2 collections, Sun Hotspot JVM performance improvements, etc.). Furthermore, in the strong Documentum tradition of supporting existing IT infrastructure such as operating systems, relational databases and application servers, whose JVM was running became less of an issue (e.g. Sun, IBM, BEA (now Oracle), etc.).

Here is perhaps an interesting portion of the original DJCB function specification dated 9/5/2001, which I authored with Victor Spivak, describing why DJCB was pursued:

Why does Documentum need any bridge?

Documentum Foundation Classes, or DFC as it is more commonly referenced, is Documentum’s platform-independent business logic layer. A key benefit of the Java language is platform independence, or “Write Once, Run Anywhere” (i.e. anywhere that supports the Java platform); therefore, DFC is implemented in Java.

Documentum is a platform provider, and as a platform company it supports the two dominant platforms of today: Windows and Java. A significant amount of Windows development is COM-based, and from a developer’s point of view, Documentum APIs on Windows are COM interface methods, etc.

When the DFC first decided to use Java as its implementation language, the Java platform was alive and well on Windows. In fact, Microsoft provided a fairly transparent bridge between COM and Java through its Java Virtual Machine (JVM) very soon after Java’s formal introduction to the general software development community. This bridge benefited Documentum a great deal; through a single implementation with minimal wrapping, Documentum could provide a business logic layer (DFC) that was consumable on both Windows and Java environments. … 

Why does Documentum need a new bridge?

The settlement of the lawsuit between Sun and Microsoft has effectively frozen Microsoft’s use of Java in Windows at version 1.1.4. For its own use, Sun has already completed its end-of-life (EOL) of 1.1.4–only 1.1.8 remains available and supported in the Java 1.1 platform. Since Microsoft’s Java-COM bridge is built into its JVM, this bridge is also frozen at version 1.1.4. However, Java hasn’t stopped growing or maturing.

The Java platform tripled in size between Java 1.1 and Java 1.2, and the Java 2 platform  has continued to grow beyond version 1.2. The current release is 1.3 and version 1.4 is available today as a beta product. …

Clearly the Java platform of today is significantly different than version 1.1.4 of the Java platform.

Developers of a platform adopt the models of that platform. Java 2 offers models that are unsupported by DFC today because DFC is constrained by obsolete bridge technology. That is, Java developers using DFC may be forced to use proprietary workarounds to standard solutions that Java 2 provides (e.g. Java Collection Framework).

Java developers expect to leverage and interact with the facilities of the Java 2 platform (i.e. version 1.2 or later). Their encounter with the current DFC programming model may less than desirable as long as DFC is constrained to a much older Java platform and development model. Critical aspects of the Java platform such as security, extensibility, collections, serialization, multithreading, have undergone significant change. DFC will benefit from these changes but it must first be able to depend on more current Java environments–something it cannot do under the current Microsoft–provided bridge.

It’s not necessary to maintain a lowest common denominator approach any longer in DFC. A new bridge can and should be developed that enables DFC to leverage the Java 2 platform for its own benefit and for the benefit of all Java developers who rely on Documentum as part of their business solutions. Providing more mature facilities in DFC to Java developers should not come at the expense of COM developers [i.e. C++/"Classic VB" developers that use COM to achieve binary compatibility]. Existing DFC APIs continue to appear as COM objects with DJCB as they have with the Microsoft bridge. …

Looking at the need for a new bridge another way, Documentum’s customers as well as Documentum itself suffers from the Sun-Microsoft lawsuit and settlement. Documentum cannot afford to drop its support of COM in the business logic layer. Documentum can also not afford to hand-tie Java business logic to an obsolete version of Java. Developers approaching the Documentum platform from a Java perspective expect our Java APIs to be Java 2-like. DJCB is about healing the wounds caused by Sun and Microsoft to our developer base… DJCB maintains a COM developer’s expectations of DFC leverage, while enabling DFC to meet the expectations of Java developers leverage Documentum’s business logic layer implemented in Java.

Next: DFC PIA…