fbpx

Using the 5.3 Web Services Framework

Introduction

The Web Services Framework allows a developer to expose a Service-based Business Object (SBO) as a web service.
It is packaged independently from DFC 5.3, and requires a seperate download from the EMC product site.

Developers getting started with the framework should devote some time to reading the “Web Services Framework Development
Guide”, also available on the EMC site. This document includes an overview of web services in general, and includes
technical details (and sample code) for creating an SBO and packaging and deploying it as a web service.

Where this document falls short, however, is on the client side invocation of these web services. A recent article posted on the
Documentum Developer Program site entitled “Enable a SBO as a Web Service and Consume it from .NET Client” addresses
this issue for the .NET environment. Unfortunately, .NET turns out to be the easy case. Visual Studio has some built in “magic”
such as “Add a Web Reference” that makes adding a reference to your web service trivial. But what if you wanted to do the same
thing in Java?

This article will address this question, and provide you with all the tips, tricks, and sample code you need to use the
Web Services Framework in a Java environment.

Accessing Web Services

So, you’ve written your SBO and you’ve used Documentum Application Builder (DAB) to enable it as
a web service and add it to the web services war file. You’ve exported this war file and deployed it out to an application
server. As part of this process a Web Service Description Language (WSDL) definition has been
generated for your web service, as well as the DocbaseCredentialsService that Documentum provided with
the Web Services Framework. Now that these definitions are out there, what do you do with them?

If we were in the .Net environment we would have clicked “Add Web Reference” within Visual Studio and specified the URL
for the generated WSDL (for example, the DocbaseCredentialsService might be deployed to something like
http://localhost:8080/ws/services/DocbaseCredentials?wsdl). This would have created a new web reference and namespace for the
service within our project. But what if we are creating a Java client and so don’t have access to the tools provided with
Visual Studio?

We use a Java based tool of course, and the industry standard is the Axis tool WSDL2Java
[org.apache.axis.wsdl.WSDL2Java]. We need to use WSDL2Java to generate proxies for all web services that
we want to access in the client environment. These proxies are objects with methods that correspond to the ones described
in the WSDL. For example, we need to be able to access the DocbaseCredentialsService for
authentication with the repository. We run the tool from a command line:

java org.apache.axis.wsdl.WSDL2Java http://localhost:8080/ws/services/DocbaseCredentials?wsdl

The target namespace from the WSDL is mapped to the package structure of the generated files.
Since this webservice has a namespace of http://documentum.com/ws/2005/framework, the generated files will be:

com.documentum.ws._2005.framework.DocbaseAuthenticationFailure
com.documentum.ws._2005.framework.DocbaseCredentials
com.documentum.ws._2005.framework.DocbaseCredentialsInfo
com.documentum.ws._2005.framework.DocbaseCredentialsService
com.documentum.ws._2005.framework.DocbaseCredentialsServiceLocator
com.documentum.ws._2005.framework.DocbaseCredentialsSoapBindingStub
com.documentum.ws._2005.framework.WebServiceException

Run the WSDL2Java tool against the WSDL definition of each web service that you would like to use in your client application.
Include these files in your project and presto, you have access to your web services!

Note: Depending on your IDE, you might have built in capabilities similar to
those found in Visual Studio. Using WSDL2Java, however, will eleviate you from your dependence on your IDE, and in this
author’s opinion, is probably the way to go.

Authentication

All communication with the respository first requires
user authentication. The Web Services Framework provides a mechanism for this authentication via the DocbaseCredentialsService.
Using the proxies that we just generated, we can construct a DocbaseCredentialsInfo object with our credentials, and use this
to retrieve an authentication token.

DocbaseCredentialsServiceLocator credentialsLocator = new DocbaseCredentialsServiceLocator();
DocbaseCredentials credentials = credentialsLocator.getDocbaseCredentials();

String repository = “repository_name”;
String domain = “mydomain”;
String username = “user”;
String password = “password”;

DocbaseCredentialsInfo info = new DocbaseCredentialsInfo(repository, domain, password, username);

String token = credentials.newCredentials(info, true);

Ok, while authenticating against a repository is nice, what we really want to do is use a custom web service to
interact with the docbase. We learned above how to access in Java any custom web service that we have deployed.
For example, let’s say we have created an SBO called DfObjectManagement that provides methods for working with repository
objects. We enable this as a web service using DAB and provide it with a namespace of
http://mycompany.com/services/dctm. We know that our SBO code will obtain a session to do the work, but when
we wrote our SBO, we didn’t know anything about a security token. Now that we have this token, how do we use this to
prove our credentials in our subsequent web service calls?

We would first generate the proxy classes for the DfObjectManagement web service using the WSDL2Java tool just
like we did above for the DocbaseCredentialsService. We use those generated files to get a handle on the web service.
Now here is where it gets interesting. When we generated the proxy, we generated objects with methods corresponding
to our SBO methods. When we use these proxy classes, each method invocation is translated into a SOAP
request and it is this SOAP request that is sent to the corresponding web service object on the application server.
So, we not only have a means to call our SBO methods, but we also have a means to enable callers to include information
in the SOAP headers. We put the security token into the SOAP header of the web service.

DfObjectManagementServiceLocator omLocator = new DfObjectManagementServiceLocator();
DfObjectManagement objectManager = omLocator.getDfObjectManagement();

String namespace = “http://mycompany.com/services/dctm”;
SOAPHeaderElement header = new org.apache.axis.message.SOAPHeaderElement(namespace, “DocumentumSecurityToken”);
header.setPrefix(“”);
header.setActor(javax.xml.soap.SOAPConstants.URI_SOAP_ACTOR_NEXT);
javax.xml.soap.SOAPElement element = header.addChildElement(“token”);
element.addTextNode(token);

Stub omServiceStub = (org.apache.axis.client.Stub)objectManager;
omServiceStub.setHeader(header);

The Web Services Framework knows all about this “DocumentumSecurityToken”, and when you make a method call to your
web service, it reads this token out of the SOAP header and uses it to authenticate you before proceeding with your
implementation logic. You don’t have to do anything special in the SBO – the framework takes care of it all for you.

File Transfer

Great, now we know how to access our web services, and how to authenticate against the repository so that we can use
them. When we enabled our SBO as a web service, DAB had generated web service operation methods equivilant to all of our SBO
methods, and we are using these methods on our proxy objects just like we would have if we were using the SBO directly. We
know that the proxy is translating each method invocation into a SOAP request object and is sending this to the corresponding
web service object on the application server. Conversely, the web service object translates the SBO’s response into a SOAP
response and sends the response back to our client proxy. The proxy translates the response into the appropriate return
arguments and returns them to us. This is completely straight forward and exactly how it happens until we get to an operation where we want to import
or export an actual document from the repository. When the request calls for actual content transfer, things get
a tad more complicated.

The Web Services Framework provides two mechanisms for transferring content files between the client
and application server: Base64 encoding and United Client Facilities (UCF).
You designate with types of file transfer you would like to allow in DAB as part of the process of enabling your SBO as a
web service. When an SBO method involves content transfer, the web service operation name that is generated for that method
in the WSDL includes a suffix indicating the means of transfer. Operations that are set to use base64 encoding are named
>methodnameXferBase64 and operations using UCF are named methodnameXferUcf (where methodname is
the name of the method in the SBO). In addition to the suffix modification, the web service operations also use different
parameter and return types for the content files than the types used in the underlying SBO. Where an SBO would have used
a standard java.io.File, operations using base64 encoding will represent the file content as a standard byte
array [byte[]], and UCF operations will use a String containing the fully qualified path to the location of the
file on the content machine.

Invoking UCF-based file transfer operations from the Java client environment are covered in detail in the Web Services
Framework Development Guide. While invoking an operation that uses base64 encoding does not require any steps unique to
Documentum (and so it is not covered at any length in their documentation), there are still some technical details that are not
intuitively obvious. Namely, the processing required to properly encode and decode the byte stream.

Base64 File Export Operations

A web service call that involves the exporting of a File using base64 encoding will return a base64 encoded
byte[] to the caller. Once the byte[] is retrieved, the client will need to base64 decode it.
The decoding is NOT handled by the framework. For example, say we have a web service method that returns
us a byte[] data. Before we can actually use this data stream to create a File object on the client machine,
we need to first base64 decode it.

byte[] data = proxy.objectExportXferBase64(repository, objectId);
String dataString = new String(data);
byte[] bytes = org.apache.axis.encoding.Base64.decode(dataString);
File file = new File(“C:/”, “MyExportFile.txt”);
FileOutputStream fos = new FileOutputStream(file);
fos.write(bytes);
fos.close();

Base64 File Import Operations

A web service call that involves an upload of a File to the repository will take as input a base64 encoded
byte[]. Before calling the web service, the client will need to read the local file as a byte[]
and encode it using base64. For example, say we have a file on the local client machine “C:/MyFile.txt” that we would like to
import into the repository. We would have to perform the following pre-processing:

File file = new File(“C:/MyFile.txt”);
FileInputStream stream = new FileInputStream(file);
int size = stream.available();
byte[] bytes = new byte[size];
stream.read(bytes);
stream.close();

String dataString = org.apache.axis.encoding.Base64.encode(bytes);
byte[] data = dataString.getBytes();

Further Reading

Here is a full list of the documents referenced in this article, as well as other documents that may prove userful when
getting started with the Web Services Framework:

Like this article?

Share on facebook
Share on Facebook
Share on twitter
Share on Twitter
Share on linkedin
Share on Linkdin
Share on pinterest
Share on Pinterest

Leave a comment