Vous êtes sur la page 1sur 50

AUTHOR : Mohd Wasil

DOMAIN : Enterprise Solution


MAIL ID: mohd.wasil@tcs.com

Internal Use 1
Copyright Notice

The information in this manual is furnished for your use only and is subject to change without notice.
Copying, modifying or distributing this document in violation of the license agreement is expressly
prohibited.

<Note: License Agreement, Trademark Notice, Confidentiality Clause can be included as applicable.
Information given here can be vetted by a legal expert.>

Internal Use 2
Index Table

Content Page No.

PART I

Documentum Foundation Services 5

DFS Explained 6

DFS Data Model 7

Building Consumer Code 9

Client Example 10

Description of Steps for Consuming Service 12

Creating Custom Services 14

Service Implementation Steps 14

Custom DataObject Example 15

Custom Services-Composer 18

Examples 18

Java Client Development 25

Internal Use 3
PART II

Consuming DFS without the DFS Productivity Layer 26

Using JDK 1.6.0 or higher version 26

Using Apache Ant 28

Sample Consumer Files using JAX-WS 32

Running the Consumer using ANT 39

Integrating with Eclipse IDE 40

Configuring the project 42

Code Overview 44

References 46

Appendix 47

Possible Errors and their resolution 47

Part I 47

Part II 49

Internal Use 4
ABOUT THIS MANUAL

PURPOSE:

This manual is divided into two parts The first part is a reference manual for understaing SOA,detailed understanding of
DFS as SOA and consuming/developing web services using JAVA framework.The second part is consuming DFS services
using wsdl file.In second part we shall guide how to generate java proxy classes(using wsimport utility) from wsdl file and
consume DFS services without DFS SDK jars.Consuming DFS services using Axis2 and developing client using .NET is
out of scope of this manual.

WHO SHOULD READ THIS MANUAL:

Developers who are in initial stage of learning DFS.They must have basic knowledge of documentum.

REVISION HISTORY:

Name Version No. Description

DFS-An Overview 1 Consuming services using DFS Java


productivity layer and creating custom services
using DFS.

Action taken Preceding New Page No Revision Description


(Add/Del/Chg.) Page No

This document and any revised pages are subject to document control. Please keep them up-to-date using the release notice
from the distributor of the document.

Approved by: Date:

Authorized by: Date:

Internal Use 5
Part I

Documentum Foundation Services

This Document covers giving brief overview of SOA ,detailed unsderstanding of DFS as SOA and consuming/developing
web services using JAVA framework.Consuming services using .NET and wsdl is out of scope of this document

Understanding SOA

Basic SOA includes :

• service provider
• service consumer
• service registry(UDDI)

UDDI registry returns the service contract to the consumer.The contract is in the form of WSDL. WSDL stands for Web
Services Description Language ,is based on XML , is used to describe and locate Web services. Services are not bound to
any specific platform or prog. language The goal of service oriented architectures (SOAs) is to provide a one-stop-shop for
business service clients by wrapping the proprietary protocols of heterogeneous systems into easy-to-use web services
that all speak the same language, namely SOAP (Simple Object Access Protocol) over HTTP
SOAP a communication protocol .SOAP provides a way to communicate between applications running on different
operating systems, with different technologies and programming languages ,it is a format for sending messages via
internet ,it is platform independent and is based on XML

Internal Use 6
DFS Explained

EMC Documentum Foundation Services (DFS) are a set of technologies that enable service-oriented
programmatic access to the EMC Documentum Content Server platform and related products. It
includes the following technologies.
DFS SDK:

The DFS Software Development Kit (SDK) includes the DFS productivity layer and build tools that can be used to build
custom services or consume services.

• DFS productivity layer


This layer consists of Java proprietary and third party libraries and .NET proprietary assemblies that assist in
writing DFS consumers and custom services.
It provides the following advantages:

◦ Transparent exception handling through marshalling and unmarshalling of SOAP faults that are returned by
the service. The consumer will display the stack trace of the exception as it would an exception thrown by an
application running in the local JVM or .NET runtime
◦ Transparent invocation of UCF and handling of UCF content transfer
◦ Simplified security and registration of service contexts, which are objects that maintain the state of the service
◦ The ability to execute the service either remotely via web services or locally within the same JVM (Java only)

One can develop DFS consumer applications using either the Java or .NET productivity layer or by using the
WSDL interface.consumers.

DFS Productivity Layer Consumer


To utilize the DFS productivity layer, you must include the appropriate JAR files or .NET assemblies in your
development environment.

• WSDL Based Consumer


DFS is implemented with standard web services technology, so you can access them with web service
consumers that use standard tools. You do not need any proprietary software for a service consumer to
connect to and use DFS. DFS makes all functionality available to WSDL-based consumers.
• DFS tools
The DFS tools provide functionality for creating services based on Java source code (“code first”), services
based on WSDL (“WSDL first”), or client runtime support for existing services based on WSDL.These tools can
be used through a Composer interface, or scripted using Ant. Composer interface is the easiest way to build
service artifacts and archive them into deployable .ear file.In this document we have explained building service
artifact and other files through composer interface.
Basic flow of Web Service:

Internal Use 7
DFS Data Model

The DFS data model comprises the object model for data passed to and returned by Enterprise Content services.
This includes the following :

DataPackage,DataObject, ObjectIdentity,Property,Content,Permissions,Relationship,Other classes related to DataObject

DataPackage:

The DataPackage class defines the fundamental unit of information that contains data passed to and returned by services
operating in the DFS framework. A DataPackage is a collection of DataObject instances, which is typically passed to, and
returned by, Object service operations such as create, get, and update.

DataObject:

A DataObject is a representation of an object in an ECM repository.A DataObject instance is potentially large and complex,
and much of the work in DFS service consumers will be dedicated to constructing the DataObject instances.

ObjectIdentity:

ObjectIdentity An ObjectIdentity uniquely identifies the repository object referenced by the DataObject.An ObjectIdentity
instance contains a repository name and an identifier that can take various forms:

OBJECT_ID Identifier value is of type ObjectId, OBJECT_PATH Identifier value is of type ObjectPath, which contains a
String expression specifying the path to the object and QUALIFICATION Identifier value is of type Qualification, which
can take the form of a DQL
expression fragment.

Example:

ObjectIdentity[] objectIdentities = new ObjectIdentity[4];


// repository only is required to represent an object that has not been created
objectIdentities[0] = new ObjectIdentity(repName);
// show each form of unique identifier
ObjectId objId = new ObjectId("090007d280075180");
objectIdentities[1] = new ObjectIdentity<ObjectId>(objId, repName);
Qualification qualification = new Qualification("dm_document where r_object_id = '090007d280075180'");
objectIdentities[2] = new ObjectIdentity<Qualification>(qualification, repName);
ObjectPath objPath = new ObjectPath("/testCabinet/testFolder/testDoc");
objectIdentities[3] = new ObjectIdentity<ObjectPath>(objPath, repName);

ObjectIdentitySet:

An ObjectIdentitySet is a collection of ObjectIdentity instances, which can be passed to an Object service operation so that
it can process multiple repository objects in a single service interaction. An ObjectIdentitySet is analogous to a
DataPackage, but is passed to service operations such as move,copy, and delete that operate only against existing repository
data, and which therefore do not require any data from the consumer about the repository objects other than their identity.

Property:

A DataObject optionally contains a PropertySet, which is a container for a set of Property objects.Each Property in normal
usage corresponds to a property (also called attribute) of a repository object represented by the DataObject. A Property
object can represent a single property, or an array of properties of the same data type. Property arrays are represented by
subclasses of ArrayProperty, and correspond to repeating attributes of repository objects.

Internal Use 8
Example:
Property[] properties ={
new StringProperty("subject", "dangers"),
new StringProperty("title", "Dangers"),
new NumberProperty("short", (short) 1),
new DateProperty("my_date", new Date()),
new BooleanProperty("a_full_text", true),
new ObjectIdProperty("my_object_id", new ObjectId("090007d280075180")),
new StringArrayProperty("keywords", new String[]{"lions", "tigers", "bears"}),

//A PropertySet is a container for named Property objects,
PropertySet propertySet = new PropertySet();
for (Property property : properties)
{
propertySet.set(property);
}

PropertyProfile:

A PropertyProfile defines property filters that limit the properties returned with an object by a service.There are many other
profile which you can set to leverage required behavior from service:
ContentProfile ,PermissionProfile, CheckinProfile,DeleteProfile,SchemaProfile,ContentTransferProfile and many more.
PropertyProfile, like other profiles, is generally set in the OperationOptions passed to a service operation.

You specify how PropertyProfile filters returned properties by setting its PropertyFilterMode.

Example:

PropertyProfile propertyProfile = new PropertyProfile();


propertyProfile.setFilterMode(PropertyFilterMode.SPECIFIED_BY_INCLUDE);
ArrayList<String> includeProperties = new ArrayList<String>();
includeProperties.add("title");
includeProperties.add("object_name");
includeProperties.add("r_object_type");
propertyProfile.setIncludeProperties(includeProperties);
OperationOptions operationOptions = new OperationOptions();
operationOptions.setPropertyProfile(propertyProfile);
dataPackage = objectService.get(objIdSet, operationOptions);

This will return only these specified properties (shown in dark) while callling Object service operation(create/get etc.).

Same way we can set ContentTransferProfile which will decide which mode of content transfer mechanism should take
place i.e. MTOM/BASE64/UCF.

ContentTransferProfile contentTransferProfile =new ContentTransferProfile();


contentTransferProfile.setTransferMode(ContentTransferMode.BASE64);
//contentTransferProfile.setTransferMode(ContentTransferMode.UCF);
context.setProfile(contentTransferProfile);

We can set the profile either in the IServiceContext object i.e. 'context' or in the OperationOption object.In latter case profile
set will be applicable to all the operation but in former case it will be specific to particular operation.
Similarly we have other profiles, for detailed description please refer DFS Development guide.

Internal Use 9
Building Consumer Code

To develop consumer one need either Composer or Eclipse , composer comes bundled with DFS SDK jars so developing
consumer side via composer is relatively easy same for creating custom service .

There are six core services which provides Content Mangament functionality as similar as vis DFC API.They are as follows
Object Service
Version Control Service
Schema Service
Query Service
Search Service
Workflow Service
For details description of these core service and their operation please refer DFS SDK javadocs.In this example we have
described how to consume ObjectService get(ObjectIdentity ,OoperationOption) operation to retrieve the object in the
repository.

We will be going through steps of consuming service:

Step 1: Verify the DFS server is running:


You should verify that the DFS server application is running and that you have the correct address and
port for the service endpoints.DFS server can be either standalone server or DFS services are running on
documentum Content server installation ,in which case application will be listening on port 9080.

In either case a DFS service endpoint address will take the following form:
protocol ://hostname:port/services/moduleName/serviceName
For example:
http://localhost:8888/services/core/ObjetServices?wsdl

Step2: In Eclipse create new project and add all DFS SDK Jars via 'Add External Jar' option present in configure build
path and also add class folder as “etc”.Edit dfc.properties file placed under etc folder.

Go to etc/config folder and edit dfs-client.xml change the <ModuleInfo/> tag to appropriate DFS server details

Internal Use 10
<ModuleInfo name="core" protocol="http" host="157.227.65.105" port="9080"
contextRoot="services">
</ModuleInfo>

Go to etc folder and edit dfc.properties file with relevant content server host and port.

Step 3:For easy reference we have provided consumer code.

Client Example:SimpleClient.java

package com.bluefishgroup.sopapilla;
import java.util.Iterator;
import com.emc.documentum.fs.datamodel.core.*;
import com.emc.documentum.fs.datamodel.core.context.RepositoryIdentity;
import com.emc.documentum.fs.datamodel.core.profiles.PropertyFilterMode;
import com.emc.documentum.fs.datamodel.core.profiles.PropertyProfile;
import com.emc.documentum.fs.datamodel.core.properties.Property;
import com.emc.documentum.fs.datamodel.core.properties.PropertySet;
import com.emc.documentum.fs.datamodel.core.properties.StringProperty;
import com.emc.documentum.fs.rt.ServiceInvocationException;
import com.emc.documentum.fs.rt.context.ContextFactory;
import com.emc.documentum.fs.rt.context.IServiceContext;
import com.emc.documentum.fs.rt.context.ServiceFactory;
import com.emc.documentum.fs.services.core.client.IObjectService;

public class SimpleClient {

@SuppressWarnings("unchecked")
public static void main(String [] args) throws ServiceInvocationException {

// Set important variables


String repositoryName = "UADCTM";
String userName = "dmadmin";
String userPassword = "dmadmin";

try
{
// Get a ContextFactory so that we can
// create a ServiceContext
System.out.println("Creating ContextFactory");
ContextFactory contextFactory = ContextFactory.getInstance();

// Use the ContextFactory to create


// a ServiceContext for a service
System.out.println("Creating ServiceContext");
IServiceContext serviceContext = contextFactory.newContext();

// Create a RepositoryIdentity to store the


// repository credentials on the ServiceContext
System.out.println("Creating RepositoryIdentity");
RepositoryIdentity repoId = new RepositoryIdentity();

// Populate the repository credentials

Internal Use 11
System.out.println("Populating RepositoryIdentity");
repoId.setRepositoryName(repositoryName);
repoId.setUserName(userName);
repoId.setPassword(userPassword);

// Add the populated RepositoryIdentity to the ServiceContext


System.out.println("Adding RepositoryIdentity to ServiceContext");
serviceContext.addIdentity(repoId);

// Get an ObjectService from the ServiceFactory


IObjectService objectService = ServiceFactory.getInstance().getRemoteService(IObjectService.class,
serviceContext);

// Query the repository for objects matching our criteria


// Build object qualifications using the criteria expressed in DQL syntax
Qualification qualification1 = new Qualification("dm_acl where object_name ='Test_DFS'");
Qualification qualification2 = new Qualification("dm_acl where object_name ='Test_DFS 2 Eclipse'");

// Create ObjectIdentity objects with our DQL qualifications and repository name
ObjectIdentity targetObjectIdentity1 = new ObjectIdentity(qualification1, repositoryName);
ObjectIdentity targetObjectIdentity2 = new ObjectIdentity(qualification2, repositoryName);

// Create an ObjectIdentitySet that contains the ObjectIdentity objects


ObjectIdentitySet objIdSet = new ObjectIdentitySet();
objIdSet.addIdentity(targetObjectIdentity1);
objIdSet.addIdentity(targetObjectIdentity2);

// Create an empty OperationOptions object


OperationOptions opts = new OperationOptions();

// Create an empty DataPackage to hold the resulting objects


DataPackage dataPackage = new DataPackage();

// Create an empty PropertySet to hold the resulting object properties


PropertySet properties = new PropertySet();

// to get all properties of an object


PropertyProfile propertyProfile=new PropertyProfile();
propertyProfile.setFilterMode(PropertyFilterMode.ALL);
opts.setPropertyProfile(propertyProfile);

// Execute ObjectService.get() which hopefully


// returns a populated DataPackage
dataPackage = objectService.get(objIdSet, opts);

// Iterate through the DataObject objects in the result DataPackage


Iterator iterator = dataPackage.getDataObjects().iterator();

while(iterator.hasNext()){
System.out.println("######## GETTING OBJECT PROPERTIES #########");
DataObject thisDataObject = (DataObject) iterator.next();
// Write out some properties for this DataObject
properties = thisDataObject.getProperties();
System.out.println("Object Name: " + properties.get("object_name").getValueAsString());

Internal Use 12
System.out.println("Creation Date: " + properties.get("r_object_id").getValueAsString());
}

}
catch (Exception e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

Description of Steps for Consuming Service:

• Create and Populate a Service Context:


//Get a ContextFactory so that we can create a ServiceContext
ContextFactory contextFactory = ContextFactory.getInstance();
// Use the ContextFactory to create a ServiceContext for a service
IServiceContext serviceContext = contextFactory.newContext();
// Create a RepositoryIdentity to store the repository credentials on the ServiceContext
RepositoryIdentity repoId = new RepositoryIdentity();
// Populate the repository credentials
repoId.setRepositoryName(repositoryName);
repoId.setUserName(userName);
repoId.setPassword(userPassword);

// Add the populated RepositoryIdentity to the ServiceContext


serviceContext.addIdentity(repoId);
• Instantiate a DFS service:
// Get an ObjectService from the ServiceFactory
IObjectService objectService =ServiceFactory.getInstance().
.getRemoteService(IObjectService.class,serviceContext)
• Get object From Repository and setting it to ObjectIdentity:
// Build object qualifications using the criteria expressed in DQL syntax
Qualification qualification1 = new Qualification("dm_acl where object_name ='Test_DFS'");
// Create ObjectIdentity objects with our DQL qualifications and repository name
ObjectIdentity targetObjectIdentity1 = new ObjectIdentity(qualification1, repositoryName);
// Create an ObjectIdentitySet that contains the ObjectIdentity objects
ObjectIdentitySet objIdSet = new ObjectIdentitySet();
objIdSet.addIdentity(targetObjectIdentity1);

Internal Use 13
• Calling an Operation of Object Service (get()):
get(ObjectIdentiySet objIdSet, OperationOption opt): It is a operation present in obejctService, which retrieve
object present in the repository and returns DataPackage Object which contains collection of DataObject
.DataObject inturns contains ObjectIdentitySet which inturn holds one or more ObjectIdentity Object .This
ObjectIdentity uniquely determine object present in the repository.

dataPackage = objectService.get(objIdSet, opts);


opts is object of OperationOption class it contains preference which will be taken into consideration while
executing the operation .In our case we have set the PropertyProfile
PropertySet properties = new PropertySet();
//to get all properties of an object
PropertyProfile propertyProfile=new PropertyProfile();
propertyProfile.setFilterMode(PropertyFilterMode.ALL);
opts.setPropertyProfile(propertyProfile);

• Iterate Over the Result:

// Iterate through the DataObject objects in the result DataPackage


Iterator iterator = dataPackage.getDataObjects().iterator();
while(iterator.hasNext())
{
System.out.println("######## GETTING OBJECT PROPERTIES #########");
DataObject thisDataObject = (DataObject) iterator.next();
// Write out some properties for this DataObject
properties = thisDataObject.getProperties();
System.out.println("Object Name: " + properties.get("object_name").getValueAsString());
System.out.println("Creation Date: " + properties.get("r_object_id").getValueAsString());
}

Run the code as Run as >Java Application and check for the desired output.

Internal Use 14
Creating Custom Services

DFS services can be implemented either as Business Object Framework (BOF) Service-based Business
Objects (SBOs), or as Plain Old Java Objects (POJOs).Most of the times creating services as POJO is more attractive choice
as it reduces technical overhead of implementing and deploying SBOs.However one can expose current SBOs functionality
in custom DFS services.DFS SDK and Composer make it easy to build and deploy custom services.EMC recommends
using Composer to create custom services.

Service implementaion Guidelines:

• A service must be SOA compliant ,it should have an appropriate level of granularity.They should avoid
ʺchattinessʺ, be sensitive to round-trip overhead, and anticipate relatively low bandwidth and high latency.
• Service whereever possible should use DFS object model.The service should specify stateless operations that
perform a single unambiguous function that the service consumer requires.In oher words DFS services should
be stand alone.
• The service should specify parameters and return values that are easily bound to XML.
• DFS services should be registered with a UDDI registry and discoverable by developers in an enteprise

Service Implementation Steps:

Determine Service architecture


• Create a new POJO(Plain Old Java object)
• Use an existing SBO(Service Based Object)

Create and annotate Custom DataObject(optional)


Create and annotate POJO/SBO
• Chain existing services.
• Implementing additional logic
Use Documentum Composer to:
• Build and compile the service and data Obejcts
• Package the service and dataobjects into EAR file
• Generate source artifact for consumer of custom services
Deploy the custom service EAR file
Create and deploy the client of the custom service

These steps are desribed below in detail .

Internal Use 15
• Determine Service Architecture

Custom services can be built in one of two ways:


• Create a new POJO In this case we have to built it from the ground so it is up to conform to SOA
guidelines.Hence an advantage and as it is POJO it has no reliance on deployed business objects.Only
disadvantage of building POJO is that it should be built from scratch
• Expose an existing SBO(Service-based Business object) as a DFS service
This way we can leverage an organisation's existing investment in SBOs.But exposing SBO as DFS service has its
disadvantages :not all SBOs are capable of being exposed as a DFS service,even SBOs that can be exposed might
be lacking an optimal SOA design,relies on proper deployment of SBOs

• Create and annotate Custom DataObject


Custom data object must be annotated correctly to be built into custom service EAR file.
Annotate with standard JAXB annotation.Java Architecture for XML binding allow mapping of java classses
to XML .JAXB allows two main features: the ability to marshal java objects into XML and the reverse
i.e. to unmarshal back into java object. .This is necessary so DFS services know how to encode and decode
custom dataobject to and from XML.The custom data obejct is sent as XML “over the wire”.

Two main annotation for class level variable:


@XmlAttribute-used for primitive data type
@XmlElement-user for container class(eg: java.util.List)
These anotaion are defined in “javax.xml.bind.annotation” package.

Custom DataObject Example


package com.emc.training.service;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlType(name="LifeCycleInfos",namespace="http://service.training.emc.com")
@XmlRootElement(name="LifeCycleInfos")
@XmlAccessorType(XmlAccessType.FIELD)

public class LifeCycleInfos {

@XmlAttribute
private boolean _lifeCycleAttached;
@XmlAttribute
private String _currentState;

public boolean isLifeCycleAttached()


{
return _lifeCycleAttached;
}
public String getCurrentState()
{
return _currentState;
}

protected void setCurrentState(String currentState)

Internal Use 16
{
this._currentState=currentState;
}

protected void setisLifeCycleAttached(boolean attached)


{
this._lifeCycleAttached=attached;
}
}

• Create and annotate POJO/SBO

In this we are focussing on creating a POJO service only where we will build a class that contains the logic for
service and will create operation which must be defined as a separate method in the class.Custom operation logic
can make calls to other existing DFS or custom services(chaining) , Leverage existing DFS objects , Leverage
custom data objects as input/return parameters ,Contain lower-level DFC code

The java class for a custom services(either as POJO or an SBO) must be annotated correctly .These annotation
serve as a metadata to DFS service design-time tools,if they are not present build process will fail.

DFS tools provide two type of annotation:

@DfsPojoService
@DfsBofService
These annotation are defined in “com.emc.documentum.fs.rt.annotations” package.

Code Example:

import com.emc.documentum.fs.rt.annotations.DfsPojoService;
@DfsPojoService(targetNamespace="http://service.training.emc.com", requiresAuthentication=false)

public class CustomLifeCycleService {


}

import com.emc.documentum.fs.rt.annotations.DfsBofService;
import javax.xml.bind.annotation.XmlAccessorType;
@DfsBofService(serviceName="customSBOService")
@XmlAccessorType(XmlAccessType.FIELD)
public class KeywordSBO extends DfService implements IKeywordSBO {
}

• Accessing an IserviceContext
Inorder for a custom service to instantiate other DFS services, it needs access to an IServiceContext Custom
Services uses a different approach then DFS Clients.
DFS clients use the ContextFactory.newContext() method to create a new IServiceContext object.
But custom DFS services will use ContextFactory.getContext() method
This method does not create a new IServiceContext object. Instead it returns a reference to the IServiceContext that
was used during its own instantiation

IServiceContext context = ContextFactory.getInstance().getContext();

Internal Use 17
• Instantiating Other Services in POJO

Within the service code for custom service ,instantiation of other services can occur in two ways:
A)Instantiating services explicitly
Example:

ICustomLifeCycleService customLifeCycleService =sf.getService(ICustomLifeCycleService.class,


serviceContext, "customLifeCycle","http://127.0.0.1:9081/customservice");

B)Instantiate services implicitly


To achieve second aim a dfs-client.xml must be packaged in the EAR file along with the custom service.This
allows the custom service to lookup the host and context root information for services it will chain together.
Example:

IObjectService objService =ServiceFactory.getInstance().getRemoteService(IObjectService.class,


serviceContext);

• Implementing Additional Logic


When no other existing services can provide the desired functionality,it becomes necessary to create the logic from
scratch . This could potentially include lower-level DFC code.To include DFC code within the custom service,you
must have access to a DFC session manager.
DFS provides utility to a class that provides easy access to a DFC session manager
Use the DfcSessionManager.getSessionManager() method to gain access to a DFC IDfSessionManager object.

Example:

IDfSessionManager sessionManager=DfcSessionManager.getSessionManager();
IDfSession session=sessionManager.getSession(repository);
IDfSysObject docObj=(IDfSysObject)session.getObjectByPath(pathToDocument);
// perform DFC Custom logic here....

Internal Use 18
Custom Services-Composer

Documentum Composer provides an extremely convenient way to build and package custom services and their associated
data objects.It comes with an internal installation of the DFS SDK,abstracts the Ant Build process(calls the appropriate Ant
Targets).Hence one doesnt have to worry about various ant task i.e generateModel ,generateArtifacts, buildService,
packageService, generateService tasks. .All these task are performed at backend when one is building the project. Hence it
eases the creation of EAR and JAR files .EMC recommends the use of Documentum Composer when creating custom
services.
In Composer create two files for easy reference we are attaching source code :
LifeCycleInfos.java: Custom DataObject
CustomLifeCycleService.java: Custom Service
In this custom service we have one operation which is taking to arguments :repository and pathToDocument .We assume
that lifecycle is attached to the document which is passed as path in the operation.This service uses low level DFC code to
promote the documents lifecycle.
public LifeCycleInfos promoteDocument(String repository,String pathToDocument)
Examples:

LifeCycleInfos.java
package com.emc.training.service;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
@XmlType(name="LifeCycleInfos",namespace="http://service.training.emc.com")
@XmlRootElement(name="LifeCycleInfos")
@XmlAccessorType(XmlAccessType.FIELD)

public class LifeCycleInfos {

@XmlAttribute
private boolean _lifeCycleAttached;
@XmlAttribute
private String _currentState;

Internal Use 19
public boolean isLifeCycleAttached()
{
return _lifeCycleAttached;
}
public String getCurrentState()
{
return _currentState;
}

protected void setCurrentState(String currentState)


{
this._currentState=currentState;
}

protected void setisLifeCycleAttached(boolean attached)


{
this._lifeCycleAttached=attached;
}
}

CustomLifeCycleService.java
package com.emc.training.service;

import com.documentum.fc.client.DfAuthenticationException;
import com.documentum.fc.client.DfIdentityException;
import com.documentum.fc.client.DfPrincipalException;
import com.documentum.fc.client.DfServiceException;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSessionManager;
import com.documentum.fc.client.IDfSysObject;
import com.documentum.fc.common.DfException;
import com.emc.documentum.fs.rt.annotations.DfsPojoService;
import com.emc.documentum.fs.rt.context.DfcSessionManager;
import com.emc.documentum.fs.rt.impl.ResourceLookupException;

@DfsPojoService(targetNamespace="http://service.training.emc.com", requiresAuthentication=false)

Internal Use 20
public class CustomLifeCycleService {
public LifeCycleInfos promoteDocument(String repository,String pathToDocument) throws ResourceLookupException
{
LifeCycleInfos linfo=new LifeCycleInfos();
try {
IDfSessionManager sessionManager=DfcSessionManager.getSessionManager();

IDfSession session=sessionManager.getSession(repository);
IDfSysObject docObj=(IDfSysObject)session.getObjectByPath(pathToDocument);
System.out.println("Print the output from DFS Service"+docObj.getCurrentState());
if(docObj==null)
{
throw new Exception("Service cant locate document"+pathToDocument);
}

docObj.promote(null,false,false);
linfo.setCurrentState(docObj.getCurrentStateName());
linfo.setisLifeCycleAttached(true);

} catch (DfIdentityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DfAuthenticationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DfPrincipalException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DfServiceException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (DfException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();}return linfo;}}

Internal Use 21
Add following resource in the package service element of dfs-build.xml file located in DFS SDK
<path location="${dfs.sdk.etc}/dfc.properties"/>
<path location="${dfs.sdk.etc}/dfc.keystore"/>
Please ensure that dfc.properties and dfc.keystore file is present at DFS SDK /etc folder.

Define the moduleName and context root which is used to access the wsdl file for the custom service.

Build the project via right click on project>build project .Behind the scene dfs-client builder will be invoked by composer
which will generate source artifact /serviceModel.xml/wsdl files which contains the contract of the service etc.Behind the
scene composer calls clean and artifact Ant Targets.Similar to image shown below should appear in console:

Internal Use 22
Export the custom service into an EAR file.

This utility will package all the files created into EAR file which will be deployed in JMS/stanalone DFS server.

On clicking Export service arhive following screen comes up...

Internal Use 23
Click on Add Jar and add following jars present in DFS SDK jars.

bpm_infra.jar
ci.jar
collaboration.jar
extended-search-api.jar
workflow.jar
certjFIPS.jar
configservice-api.jar
configservice-impl.jar
jsafeFIPS.jar

If you are chaining services then you have to add Runtime Resources. Click on Select under Runtime Resources and add
dfs-client.xml file from DFS SDK .

On doing Service Archiving EAR files gets created .Behind the scene Composer calls package Ant Target

Backend the scene <moduleName-remote.jar> is created which is used for consuming custom services on client side.

Deploy the EAR file to the target JEE application server in the deploy directory as shown below:

Internal Use 24
• Java Client Development

Now to consume the service we need to build client side code.


Java class artifacts are created during the custom service build process which generated JAR file <moduleName>-
remote.jar. These artifacts are necessary inorder to build clients of the custom service JAR file needs to be added to
the CLASSPATH of the DFS client application

Code Snippet:

import com.emc.training.service.LifeCycleInfos;
import com.emc.training.service.client.ICustomLifeCycleService;

ICustomLifeCycleService customLifeCycleService =sf.getService(ICustomLifeCycleService.class,


serviceContext, "customLifeCycle")
LifeCycleInfos linfo;
info = customLifeCycleService.promoteDocument(repository, pathToDocument);

Add in dfs-client.xml following lines:

<ModuleInfo name="customLifeCycle" protocol="http" host="localhost" port="9081"


contextRoot="customservice">
</ModuleInfo>

Run the client code as java application .If everything is fine it should consume custom service.

Internal Use 25
Part II

Consuming DFS without the DFS Productivity Layer:

In some scenarios, using the DFS productivity layer is not possible, such as not being able to use a Java 1.5 JDK,or where
one dont have to use DFS SDK jars to build consumer code.Here we will discuss above scenarios in detail of how to
consume DFS service without using DFS jars or JDK.

Consuming DFS with an Axis2 or JAXWS consumer:

There are two ways to consume DFS service either usng Axis2 or JAXWS.Axis2 is a plugin which can be integrated with
eclipse .As we are not using DFS SDK to build consumer we need to generate proxy classes.Axis2/JAXWS helps in
generating those proxy classes which will be used in building consumer code.In this case we shall provide wsdl file to
generate client proxies.Here we will be discussing genrating proxy classes using JAWS.
There are two ways to generate consumer code using JAXWS.

• Using JDK 1.6.0 or higher version:

JDK 1.6 or higher bundles wsimport file which helps in generating proxy classes.Set JAVA_HOME and PATH environment
variable as C:\Program Files\Java\jdk1.6.0_12 and C:\Program Files\Java\jdk1.6.0_12\bin respectively.

Go to command prompt and follow below steps:

Step 1: Create and save a simple-binding.xjb file that contains the following content:
<?xml version="1.0" encoding="UTF8"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings>
<xjc:simple />
</jaxb:globalBindings>
</jaxb:bindings>

This file enables simple binding mode in JAX-WS, which is needed to generate the client proxies correctly.

Step 2: In the absence of the DFS productivity layer, service contexts can be registered by calling the
ContextRegistryService.
Generate the proxies for the ContextRegistryService with the following command
wsimport -d classOutputDirectory -s javaOutputDirectory -extension -keep -b path/to/simplebinding. Xjb
http://host:port/services/core/runtime/ContextRegistryService?wsdl
where the variables represent the following values:
• classOutputDirectory — the directory where you want the class files for the client proxies to be output to
• javaOutputDirectory — the directory where you want the java files for the client proxies to be output to
• path/to — the path of the simple-binding.xjb file
• host:port — the host and port where DFS is located

Internal Use 26
As ContextRegistryService.wsdl file is default service provided by EMC, it is recommended to use wsdl files located in
your local machine DFS SDK .This makes generating proxy files faster.In this case make sure in command prompt you
browse to that location where your wsdl files are present and edit wsdl file the following element shown in bold

<soap:address location="REPLACE_WITH_ACTUAL_URL"/>
with
http://host:port/services/core/runtime/ContextRegistryService?wsdl
In Command prompt use following command:

wsimport -d classOutputDirectory -s javaOutputDirectory path to ContextRegistryService.wsdl


example:
>wsimport -d classes -s src C:\DFS_WorkSpace\Axis2TestService\emc-dfs-sdk-6.5\etc\wsdl\ContextRegistryService.wsdl

Make sure that classses and src folder are present in current directory.

Step 3: Generate the proxies for each DFS service that you want to consume with the following command
wsimport -d classOutputDirectory -s javaOutputDirectory -extension -keep -b path/to/simplebinding. Xjb
http://host:port/services/core/services/SchemaService?wsdl
If one is not able to generate proxy classes using above command one can skip simple-binding.xjb file in the command
shown below:
wsimport -d classOutputDirectory -s javaOutputDirectory http://host:port/services/core/runtime/ContextRegistryService?
wsdl

Internal Use 27
• Using Apache Ant

Ant(Another Neat Tool) is a Java based build tool . Ant uses Java classes and XML scripts to provide an automated way to
build applications . Ant functionality includes: extract source from a version control system, create directories, delete
directories, compile code, generate javadoc, jar files, copy files and many more.Before generating proxy classes one need
to develop system environment to enable Ant working.

Following things needs to be installed in your system .

• JAX-WS RI 2.1 from https://jax-ws.dev.java.net/


• Apache Ant 1.7 or higher from http://ant.apache.org/bindownload.cgi
• Java 5 JDK or higher version java 5 JDK
• DFS 6 or higher

To install ant unzip the apache-ant-1.7.0-bin.zip add a new environment variable “ANT_HOME” pointing to the directory
where ant is installed . Set “PATH” to bin folder of ant installable.In our case we have set above path as :
ANT_HOME: C:\Downloads\apache-ant-1.7.0
PATH C:\Downloads\apache-ant-1.7.0\bin
To check whether ant is installed properly or not goto command prompt and type ant .Build failed should come
up as it is not able to locate build.xml file.If some error comes make sure that CLASSPATH environment variable
is unset.

Ant uses ant build.xml file in which we define targets and each targets have set of tasks for example to compile
java files task is “javac”. Same way we can create custom tasks to meet our requirements.In our case we have
created a custom task named as “wsimport” as shown below:

<target name="artifacts" depends="create.simple.binding.file" >


<taskdef name="wsimport"
classname="com.sun.tools.ws.ant.WsImport"
classpathref="jaxws.classpath"/>/>

Copy build.xml and build.properties file to your local machine.

build.properties

jaxws.home=C:/Documents and Settings/340661/My Documents/Downloads/jaxws-src/jaxws-ri-20070501


schema.service.wsdl=http://host:portservices/core/SchemaService?wsdl
context.registry.service.wsdl=http://host:port/services/core/runtime/ContextRegistryService?wsdl
src.dir=./src
build.dir=./build
generated.dir=./generated

Internal Use 28
build.xml

<!-- Builds and runs the JAX-WS samples -->


<project name="JaxWsDfs" default="info">
<property file="build.properties" />
<path id="jaxws.classpath">
<fileset dir="${jaxws.home}/lib">
<include name="**/*.jar" />
</fileset>
<pathelement location="${build.dir}" />
</path>
<target name="all" depends="clean, artifacts, compile" />

<target name="create.simple.binding.file">
<mkdir dir="${generated.dir}"/>
<!-- Do not change white space or formatting of the following block. It is susceptible to whitespace errors -->
<echo file="${generated.dir}/simple-binding.xml"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings>
<xjc:simple />
</jaxb:globalBindings>
</jaxb:bindings>]]>
</echo>
<!-- End block -->
</target>

<target name="artifacts" depends="create.simple.binding.file" >


<mkdir dir="${generated.dir}/classes" />
<mkdir dir="${generated.dir}/src" />
<taskdef name="wsimport"
classname="com.sun.tools.ws.ant.WsImport"
classpathref="jaxws.classpath"/>
<wsimport
destdir="${generated.dir}/classes"
sourcedestdir="${generated.dir}/src"
keep="true"
extension="true"
wsdl="${schema.service.wsdl}"
binding="${generated.dir}/simple-binding.xml" />
<wsimport
destdir="${generated.dir}/classes"
sourcedestdir="${generated.dir}/src"
keep="true"
extension="true"
wsdl="${context.registry.service.wsdl}"
binding="${generated.dir}/simple-binding.xml" />

</target>

<target name="compile">
<mkdir dir="${build.dir}" />
<javac destdir="${build.dir}" failonerror="true">

Internal Use 29
<src path="${src.dir}" />
<src path="${generated.dir}/src" />
<classpath refid="jaxws.classpath"/>
</javac>
</target>

<target name="clean">
<delete dir="${generated.dir}"/>
<delete dir="${build.dir}"/>
</target>

<property name="runtime.classpath" value="


./build;
./resources;
${jaxws.home}/lib/activation.jar;
${jaxws.home}/lib/FastInfoset.jar;
${jaxws.home}/lib/http.jar;
${jaxws.home}/lib/jaxb-api.jar;
${jaxws.home}/lib/jaxb-impl.jar;
${jaxws.home}/lib/jaxb-xjc.jar;
${jaxws.home}/lib/jaxws-api.jar;
${jaxws.home}/lib/jaxws-rt.jar;
${jaxws.home}/lib/jsr173_api.jar;
${jaxws.home}/lib/jsr181-api.jar;
${jaxws.home}/lib/jsr250-api.jar;
${jaxws.home}/lib/mimepull.jar;
${jaxws.home}/lib/resolver.jar;
${jaxws.home}/lib/saaj-api.jar;
${jaxws.home}/lib/saaj-impl.jar;
${jaxws.home}/lib/sjsxp.jar;
${jaxws.home}/lib/stax-ex.jar;
${jaxws.home}/lib/streambuffer.jar" />

<target name="run.schema.service.demo">
<input
message="Enter username:"
addproperty="repo.username"/>
<input
message="Enter password. WILL DISPLAY ONSCREEN IN CLEAR TEXT!"
addproperty="repo.password"/>
<exec executable="java.exe">
<arg value="-classpath" />
<arg path="${runtime.classpath}" />
<arg value="com.emc.documentum.fs.samples.jaxws.SchemaServiceDemoRunner"/>
<arg value="${repo.username}"/>
<arg value="${repo.password}"/>
</exec>
</target>
<target name="info">
<echo message="Available tasks for JAX-WS DFS consumer samples"/>
<echo message="--------------------------------------------"/>
<echo message="ant clean - clean the project"/>
<echo message="ant artifacts - generate JAX-WS proxies"/>
<echo message="ant compile - compile the proxies and clients"/>
<echo message="ant run.schema.service.demo - run the Schema service demo main method"/>
</target></project>

Internal Use 30
In order to run build.xml file edit build.properties file to appropriate service wsdl file and JAXWS 2.1 installation
directory. Please dont forget to edit build.properties file as it is being used by ant script i.e. build.xml file for generating
proxy classes.Pre-requiste for editing build.properties file is that you must have JAX WS 2.1 installed on your machine
Your folder structure should appear like this.

Go to the path where you have copied build.xml and build.properties file ,open command prompt and type ant. Something
shown below should come up.

Run ant artifacts command .

Code generated will be in generated folder containing proxy java files which looks similar to java files present in DFS
SDK Jars but these are client proxies generated from wsdl files.

Internal Use 31
Sample Consumer Files using JAX-WS :

Samples which we are using for building consumer code consumes SchemaService. Here we are fetching repository
information .It have five java files:

“SchemaServiceDemoRunner.java” ,”SchemaServiceDemo.java”,”ServiceContextHelper.java”,”ServiceProperties.java”.
and “SchemaUtil.java”

SchemaServiceDemoRunner.java

package com.emc.documentum.fs.samples.jaxws;

import com.emc.documentum.fs.datamodel.core.schema.RepositoryInfo;

import javax.xml.bind.JAXBException;
import java.net.MalformedURLException;

/**
* Runs the schewma service demo; gets the name of the repository.
* The main method entry point is in this class.
*/
public class SchemaServiceDemoRunner
{
SchemaServiceDemo m_schemaServiceDemo;
ServiceProperties m_serviceProperties;

public SchemaServiceDemoRunner ()
{
m_serviceProperties = new ServiceProperties();
}

public void setSchemaServiceDemo (String userName, String password)


{
String contextRegistryURL = m_serviceProperties.getContextRegistryURL();
String contextRoot = m_serviceProperties.getContextRoot();
String repository = m_serviceProperties.getRepository();
try
{
m_schemaServiceDemo = new SchemaServiceDemo(
userName,
password,
repository,
contextRegistryURL,
contextRoot);
}
catch (MalformedURLException mfE)
{
mfE.printStackTrace();
}
catch (JAXBException jxE)
{
jxE.printStackTrace();
}
}

Internal Use 32
private RepositoryInfo getRepositoryInfo ()
{
SchemaUtil schemaUtil = new SchemaUtil(
m_schemaServiceDemo.getServiceContext(),
m_schemaServiceDemo.getServicePort());
RepositoryInfo repositoryInfo = schemaUtil.getRepositoryInfo();
// Run with -ea VM param to turn on assertions
assert (repositoryInfo != null);
assert (repositoryInfo.getName().equals(m_serviceProperties.getRepository()));
System.out.println("Repository name from demo.properties and SchemaService Operation
matched"+repositoryInfo.getName());
return repositoryInfo;
}
public static void main (String[] args)
{
String userName = args[0];
String password = args[1];

SchemaServiceDemoRunner schemaServiceDemoRunner = new SchemaServiceDemoRunner();


schemaServiceDemoRunner.setSchemaServiceDemo(userName, password);
schemaServiceDemoRunner.getRepositoryInfo();
}}

SchemaUtil.java

package com.emc.documentum.fs.samples.jaxws;
import com.emc.documentum.fs.datamodel.core.schema.RepositoryInfo;
import com.emc.documentum.fs.datamodel.core.context.RepositoryIdentity;
import com.emc.documentum.fs.datamodel.core.context.ServiceContext;
import com.emc.documentum.fs.services.core.SchemaServicePort;
/**
* Method demonstrates getting repository info from Schema service.
*/
public class SchemaUtil
{
private ServiceContext m_serviceContext;
private SchemaServicePort m_servicePort;

public SchemaUtil (ServiceContext serviceContext, SchemaServicePort servicePort)


{
m_serviceContext = serviceContext;
m_servicePort = servicePort;
}

public RepositoryInfo getRepositoryInfo ()


{
RepositoryInfo repositoryInfo = null;
try
{
System.out.println("Invoking the getRepositoryInfo operation on the port.");
repositoryInfo = m_servicePort.getRepositoryInfo(
((RepositoryIdentity)
(m_serviceContext.getIdentities().get(0))).getRepositoryName(), null);
System.out.println("Repository Name: " + repositoryInfo.getName());

Internal Use 33
catch (Exception e)
{
e.printStackTrace();
}
return repositoryInfo;
}}

SchemaServiceDemo.java

package com.emc.documentum.fs.samples.jaxws;

import javax.xml.namespace.QName;
import javax.xml.bind.JAXBException;
import com.sun.xml.ws.developer.WSBindingProvider;
import com.emc.documentum.fs.datamodel.core.context.RepositoryIdentity;
import com.emc.documentum.fs.datamodel.core.context.ServiceContext;
import com.emc.documentum.fs.services.core.SchemaService;
import com.emc.documentum.fs.services.core.SchemaServicePort;
import com.sun.xml.ws.api.message.Header;
import java.net.URL;
import java.net.MalformedURLException;
/**
* Sets up the Schema service port and service context header.
*/
public class SchemaServiceDemo
{
private ServiceContext m_serviceContext;
private SchemaServicePort m_servicePort;
private String m_contextRegistryURL;
private String m_contextRoot;

public SchemaServiceDemo (
String user, String password, String repository, String contextRegistryURL, String contextRoot)
throws MalformedURLException, JAXBException
{
setServiceContext(user, password, repository);
m_contextRoot = contextRoot;
m_contextRegistryURL = contextRegistryURL;

setServicePort(getContextHeader());
}

public ServiceContext getServiceContext ()


{
return m_serviceContext;
}

public SchemaServicePort getServicePort ()


{
return m_servicePort;
}

private void setServiceContext (String user, String password, String repository)


{
RepositoryIdentity identity = new RepositoryIdentity();
identity.setUserName(user);

Internal Use 34
identity.setPassword(password);
identity.setRepositoryName(repository);
m_serviceContext = new ServiceContext();
m_serviceContext.getIdentities().add(identity);
}
private void setServicePort (Header contextHeader) throws MalformedURLException
{
String schemaServiceURL = m_contextRoot + "/core/SchemaService";
SchemaService schemaService = new SchemaService(
new URL(schemaServiceURL),
new QName("http://core.services.fs.documentum.emc.com/", "SchemaService"));
System.out.println("Retrieving the port from the Schema Service");
m_servicePort = schemaService.getSchemaServicePort();

WSBindingProvider wsbp = ((WSBindingProvider) m_servicePort);


wsbp.setOutboundHeaders(contextHeader);
}

// Places the service context in the header if m_contextRegistryURL is null


// Otherwise, registers the service context, which will then contain a token.
private Header getContextHeader () throws JAXBException
{
ServiceContextHelper serviceContextHelper = new ServiceContextHelper();
Header contextHeader;
if (m_contextRegistryURL == null)
{
contextHeader = serviceContextHelper.getAsSoapHeader(m_serviceContext);
}
else
{
contextHeader = serviceContextHelper.register(m_serviceContext, m_contextRegistryURL);
}
return contextHeader;
}}

ServiceContextHelper.java

package com.emc.documentum.fs.samples.jaxws;

import javax.xml.namespace.QName;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.bind.JAXBException;
import com.emc.documentum.fs.rt.services.ContextRegistryService;
import com.emc.documentum.fs.rt.services.ContextRegistryServicePort;
import com.emc.documentum.fs.datamodel.core.context.ServiceContext;
import com.sun.xml.ws.api.message.Headers;
import com.sun.xml.ws.api.message.Header;
import com.sun.xml.bind.api.JAXBRIContext;
import java.net.URL;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
* Helper methods for getting the service context as a SOAP header. Service context can be registered,

Internal Use 35
* in which case the SOAP header contains a token obtained from the ContextRegistryService;
* or not registered, in which case the SOAP header contains the service context itself.
*/
public class ServiceContextHelper
{
private static final String WSSE_NAMESPACE =
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
private static final String WSU_NAMESPACE =
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
private static final String EMC_RAD = "http://schemas.emc.com/documentum#ResourceAccessToken";

public Header register (ServiceContext s, String contextRegistryURL)


{
String token = null;
try
{
ContextRegistryService registryService = new ContextRegistryService(
new URL(contextRegistryURL),
new QName("http://services.rt.fs.documentum.emc.com/", "ContextRegistryService"));
ContextRegistryServicePort port = registryService.getContextRegistryServicePort();

// second argument to register method is of form "http://host:port/services/core"


token = port.register(s, contextRegistryURL.substring(0, contextRegistryURL.length() - 31));
System.out.println("Registered the service context with token: " + token);
}
catch (Exception e)
{
e.printStackTrace();
}
return addTokenToHeader(token);
}

public Header getAsSoapHeader (ServiceContext serviceContext) throws JAXBException


{
JAXBRIContext jaxbContext = (JAXBRIContext)(JAXBRIContext.newInstance(ServiceContext.class));
return Headers.create(jaxbContext, serviceContext);
}
private Header addTokenToHeader (String token)
{
Element wsseSecurity = null;
Element wsseToken;
try
{
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

wsseSecurity = document.createElementNS(
WSSE_NAMESPACE, "wsse:Security"
);
wsseToken = (Element) wsseSecurity.appendChild(
document.createElementNS(
WSSE_NAMESPACE, "wsse:BinarySecurityToken"
));
wsseToken.setAttribute("QualificationValueType", EMC_RAD);
wsseToken.setAttributeNS(WSU_NAMESPACE, "wsu:Id", "RAD");
wsseToken.setTextContent(token);
}

Internal Use 36
catch (ParserConfigurationException e)
{
e.printStackTrace();
}
return Headers.create(wsseSecurity);
}}

ServiceProperties.java

package com.emc.documentum.fs.samples.jaxws;

import com.emc.documentum.fs.datamodel.core.content.ContentTransferMode;

import java.util.Properties;
import java.io.IOException;

/**
* Stores service properties set in demo.properties.
*/
public class ServiceProperties
{
private String m_repository;
private String m_contextRoot;
private String m_contextRegistryURL;
private String m_testFilePath;
private String m_testFileFormat;
private ContentTransferMode m_contentTransferMode;

public ServiceProperties ()
{
try
{
initProperties();
}
catch (IOException e)
{
e.printStackTrace();
}
}

private void initProperties () throws IOException


{
Properties properties = new Properties();
properties.load(this.getClass().getClassLoader().getResourceAsStream("demo.properties"));
m_repository = (String) properties.get("repository");
m_contextRoot = (String) properties.get("contextRoot");
m_contextRegistryURL = (String) properties.get("contextRegistryURL");
m_testFilePath = (String) properties.get("testFilePath");
m_testFileFormat = (String) properties.get("testFileFormat");

String contentTransferMode = (String) properties.get("contentTransferMode");


m_contentTransferMode = (contentTransferMode.equals("MTOM")) ? ContentTransferMode.MTOM :
ContentTransferMode.BASE_64;
}

public String getRepository ()

Internal Use 37
{
return m_repository;
}

public String getContextRoot ()


{
return m_contextRoot;
}

public String getContextRegistryURL ()


{
return m_contextRegistryURL;
}

public String getTestFilePath ()


{
return m_testFilePath;
}

public ContentTransferMode getContentTransferMode ()


{
return m_contentTransferMode;
}

public String getTestFileFormat ()


{
return m_testFileFormat;
}}

demo.properties

repository=****
contextRoot=http://host:port/services
contextRegistryURL=http://host:port/services/core/runtime/ContextRegistryService
contentTransferMode=MTOM

Internal Use 38
Ensure that you have demo.properties file under resources folder in the directory where generated folder is present. it is
used by ServiceProperties.java files for gettign basic information.Create a folder named as src and copy all five java files to
src.Your folder structure should be similar to as shown below:

Running the Consumer using ANT:

Now goto command prompt and run


>ant run.schema.service.demo
it will prompt for username and password of the user which is present in your repository.On entering the credentials it will
call getRepositoryInfo operation declared in SchemaService.

Internal Use 39
Integrating with Eclipse IDE

Same thing can be configured in Eclipse IDE .Create a new Java project. Make sure to import all necessary JAX WS jars
and add resources folder as source .
Generate Proxy classes which will be used for building client using Java JDK 1.6. or Using Apache Ant .
Add all proxy classes along with the client (java files given above) in src directory as shown below ,copy all the java files
to src as shown below in red.

Internal Use 40
Add all JAX-WS jars and apart from src as source, add one more(resources folder) as source shown below in red.

Internal Use 41
Configuring the project:

Right click on project goto Run as and select Run Configurations..

In Java Application(left side bar) right click and select new and edit Main tab on top right side.Provide the class in which
main method is present.In our case it is SchemaServiceDemoRunner.java file.Search and select this file.

Internal Use 42
Goto Arguments tab and provide username and password respectvely as runtime arguments.

Click on apply and then click run .Following should appear on console

Internal Use 43
Code Overview

Step 1:

we have created client by registering service context to the SOAP header .Before registering service context it needs to be
created wherein we will set Repository Identity.

Code Snippets:

SchemaServiceDemo.setServiceContext(user, password, repository);

In the method we are creating RepositoryIdentity object and adding it ServiceContext Object.

private void setServiceContext (String user, String password, String repository)


{
RepositoryIdentity identity = new RepositoryIdentity();
identity.setUserName(user);
identity.setPassword(password);
identity.setRepositoryName(repository);
m_serviceContext = new ServiceContext();
m_serviceContext.getIdentities().add(identity);
}

Step 2:

we need to get the Header wherein we will register the service context.

Code Snippets:

getContextHeader()
{
contextHeader = serviceContextHelper.register(m_serviceContext,m_contextRegistryURL);
}

public Header register (ServiceContext s, String contextRegistryURL)


{
ContextRegistryService registryService = new ContextRegistryService( new URL(contextRegistryURL),
new QName("http://services.rt.fs.documentum.emc.com/", "ContextRegistryService"));
ContextRegistryServicePort port = registryService.getContextRegistryServicePort();
token = port.register(s, contextRegistryURL.substring(0, contextRegistryURL.length() - 31));
}

Internal Use 44
Step 3:

Service port(m_serviceport through which we will be callling service operations) needs to be set wherein we will get
SchemaServicePort

Code Snippets:

setServicePort(getContextHeader());
private void setServicePort (Header contextHeader) throws MalformedURLException
{
SchemaService schemaService = new SchemaService( new URL(schemaServiceURL),
new QName("http://core.services.fs.documentum.emc.com/", "SchemaService"));
m_servicePort = schemaService.getSchemaServicePort();
WSBindingProvider wsbp = ((WSBindingProvider) m_servicePort);
wsbp.setOutboundHeaders(contextHeader);
}

Step 4:

As we have service port we can call operation related to that service.In our case we are calling getRepositoryInfo
operation of SchemaService via SchemaServicePort.

Code Snippets:

RepositoryInfo repositoryInfo = null;


repositoryInfo = m_servicePort.getRepositoryInfo(((RepositoryIdentity)
(m_serviceContext.getIdentities().get(0))).getRepositoryName(), null);
repositoryInfo.getName();

Internal Use 45
• References
◦ SOA Development with DFS
◦ DevelopingWebServices_withDocumentum- Documentum Technical White Paper
◦ DFS development guide Version 6.5
◦ DFS deployment guide Version 6.5
◦ Leveraging Web Services toIntegrate with EMC Documentum in SOA-WhitePaper

• Useful Links:

Part I

http://www.bluefishgroup.com/library/2007/introduction-to-dfs-web-services-client-programming/
https://community.emc.com/message/511205#511205
https://community.emc.com/message/367292#367292
https://community.emc.com/message/509907#509907
https://community.emc.com/message/367924#367924
https://community.emc.com/message/369828#369828

Part II

https://community.emc.com/message/296966#296966
https://community.emc.com/message/4417#4417
https://community.emc.com/message/370144#370144
https://community.emc.com/message/368216#368216
http://publib.boulder.ibm.com/infocenter/wasinfo/v6r1/index.jsp?topic=
%2Fcom.ibm.websphere.wsfep.multiplatform.doc%2Finfo%2Fae%2Fae%2Frwbs_wsimport.html
http://java.sun.com/developer/technicalArticles/J2SE/jax_ws_2/
https://community.emc.com/message/9085#9085
https://community.emc.com/message/370386#370386

Internal Use 46
Appendix

Possible Errors and their resolution:

Part I

• Errors 1:
could not find dfs-client.xml|app.config in classpath to identify default contextRoot and moduleName. at
com.emc.documentum.fs.rt.impl.DfsClientConfigManager.getDefaultModuleInfo(DfsClientConfigManager.ja
va:69) at
com.emc.documentum.fs.rt.context.ServiceFactory.getRemoteService(ServiceFactory.java:127) at
com.emc.documentum.fs.rt.context.ServiceFactory.getRemoteService(ServiceFactory.java:100) at
com.emc.trainig.DFSLogic.startLogic(DFSLogic.java:29)

Resolution:
Add dfs-sdk/etc to the class path .Edit dfs-client.xml with host and port of DFS server which can be either
standalone or jboss present in content server installation.
<ModuleInfo name="core" protocol="http" host="localhost" port="8888" contextRoot="services">
</ModuleInfo>

• Error 2:
com.emc.documentum.fs.rt.ServiceInvocationException: Service
"com.emc.documentum.fs.services.core.acl.AccessControlService" is not available at url:
"http://localhost:8888/services/core/AccessControlService?WSDL"
com.emc.documentum.fs.rt.context.impl.DfsSoapService.newWebServiceClient(DfsSoapService.java:156)
at com.emc.documentum.fs.rt.context.impl.DfsSoapService.getInstance(DfsSoapService.java:46)
Resolution:
Check whether DFS server is running or Check dfs-sdk/etc added to classpath or check whether
dfs-client.xml points to correct DFS server.

• Error 3:
[generateModel] java.lang.LinkageError: JAXB 2.0 API is being loaded from the bootstrap classloader, but
this RI (from jar:file:/C:/Documents%20and%20Settings/username/My%20Documents/DCTM
%20Lib/mycomposerworkspace/DocumentumCoreProject/dfs6.5/emc-dfs-sdk-6.5/lib/java/jaxws/jaxb-
impl.jar!/com/sun/xml/bind/v2/model/impl/ModelBuilder.class) needs 2.1 API. Use the endorsed directory
mechanism to place jaxb-api.jar in the bootstrap classloader

Resolution:

copy jaxb-api.jar, jaxb-impl.jar, jaxws-api.jar to \lib\endorsed directory of JEE application server where yo
have deployed dfs.ear file.

Internal Use 47
• Error 4:
java.lang.IllegalArgumentException at javax.xml.bind.JAXBContext.newInstance(Unknown Source) at
javax.xml.bind.JAXBContext.newInstance(Unknown Source) at
com.emc.documentum.fs.rt.context.impl.ClientReflectionServiceInvoker.setAdditionalParameters(ClientRefle
ctionServiceInvoker.java:215) at
com.emc.documentum.fs.rt.context.impl.ClientReflectionServiceInvoker.invoke(ClientReflectionServiceInvok
er.java:156)
Resolution:
Try resolution for “error 5” or make sure that you have atleast these jars in your EAR file under App-Inf/lib
directory
commons-cli-1.0.jar,commons-lang-2.1.jar,emc-dfs-rt-remote.jar,emc-dfs-services-
remote.jar,FastInfoset.jar,http.jar,jaxb-impl.jar,jaxb-xjc.jar,jaxws-api.jar,jaxws-rt.jar,jsr181-api.jar,jsr250-
api.jar,resolver.jar,saaj-api.jar,saaj-impl.jar,sjsxp.jar,stax-ex.jar,streambuffer.jar,ucf-installer.jar

• Error 5:
java.lang.NoClassDefFoundError: Could not initialize class com.rsa.certj.cert.CertificateException
Resolution:
NoClassDefFoundError is different from ClassNotFoundException .Class may be present but it is not able to
locate that class file due to some legay issue or that class is being found, but either it is being loaded from
another jar in your classpath or is missing a dependency.
In this case add dfc.keystore file to dfs-sdk/etc folder and alter the dfs-build.xml to include the dfc.keystore
file as a resource in the packageService task. Add corresponding jars if not present in Export Service Archive
Operation and then create a EAR file ,redeploy it again on DFS server .If issue persists please check ECN
community forum.Some useful links are given below:
https://community.emc.com/message/515536#515536
https://community.emc.com/message/369719#369719
https://community.emc.com/message/479311#479311

• Error 6:
Error configuring application listener of class
com.sun.xml.ws.transport.http.servlet.WSServletContextListener
java.lang.ClassNotFoundException: com.sun.xml.ws.transport.http.servlet.WSServletContextListener

Resolution:
Go to endorsed directory at ‘jboss-4.x.x.GA\lib\endorsed’ location. Then delete all jars (related to JAXB,
JAXWS and JAAS) from there except the following ones- Serializer.jar ,Xalan.jar , xercesImpl.jar and copy
JAX-WS RI jars here

Internal Use 48
Part II

• Error 7
SchemaServiceURL:::...null/core/SchemaService java.net.MalformedURLException: no protocol:
null/core/SchemaService at java.net.URL.<init>(URL.java:567) at java.net.URL.<init>(URL.java:464) at
java.net.URL.<init>(URL.java:413) at
com.test.documentum.fs.samples.jaxws.SchemaServiceDemo.setServicePort(ObjectServiceDemo

Resolution:
Incorrect path of SchemaService URL leads to this error.Check build.properties file and make sure that you have
the correct wsdl URL .

• Error 8
BUILD FAILED
C:\Documents and Settings\340661\Desktop\DFS\Code Generated Using Ant\build.xml:42: You are running on
JDK6 which comes with JAX-WS 2.1 API, but this tool requires JAX-WS 2.2 API. Use the endorsed standards
override mechanism (http://java.sun.com/javase/6/docs/technotes/guides/standards/), or set xendorsed="true" on
<wsimport>

Resolution:

This error comes when we are using lower version of JAX-WS. one can install JAX WS-2.1 ,or can set
xendorsed =”true” in build.xml file as shown below:
<wsimport
xendorsed=”true”
destdir="${generated.dir}/classes"
sourcedestdir="${generated.dir}/src"
keep="true"
extension="true"
wsdl="${schema.service.wsdl}"
binding="${generated.dir}/simple-binding.xml" />

It is recommended not to make any changes in build.xml file other workaround is to install JAX-WS 2.1 .

• Error 9
Serializable Exception :com.emc.documentum.fs.services.core.SerializableException "Delete" operation failed for
object:
Resolution:
SerializableException means that there is an exception on the server side, which was serialized for the client. If you
catch the exception then print the whole stacktrace (exception.printStackTrace()) and you will get more
information of the issue. Otherwise you can check server log where your DFS is installed

Internal Use 49
• Error 10
java.lang.NullPointerException at java.util.Properties$LineReader.readLine(Properties.java:365) at
java.util.Properties.load(Properties.java:293) at
com.test.documentum.fs.samples.jaxws.ServiceProperties.initProperties(ServiceProperties.java:38) at
com.test.documentum.fs.samples.jaxws.ServiceProperties.<init>(ServiceProperties.java:26)
Resolution:
Ensure that resource folder is added asd source .It contains demo.properties files whch is used by
ServiceProperties.java.

• Error 11

BUILD FAILED
C:\Documents and Settings\340661\Desktop\DFS\Code Generated Using Ant\build.xml:34: C:\Documents
and Settings\340661\Desktop\DFS\Code Generated Using Ant\Documents and Settings340661My
DocumentsDownloadsjaxws-ri\lib not found

Resolution:
This error comes when either JAX-WS is not installed properly or the URL mentioned in build.properties
“jaxws.home” element is incorrect.Make sure that jaxws.home should point to installation directory of JAX-
WS.Replace \ with / .
Example:
jaxws.home=C:\Documents and Settings\340661\My Documents\Downloads\jaxws-src\jaxws-ri-20070501
jaxws.home=C:/Documents and Settings/340661/My Documents/Downloads/jaxws-src/jaxws-ri-20070501
URL shown in bold is correct

Internal Use 50

Vous aimerez peut-être aussi