Professional Documents
Culture Documents
DFS An OverView
DFS An OverView
DFS An OverView
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
PART I
DFS Explained 6
Client Example 10
Custom Services-Composer 18
Examples 18
Internal Use 3
PART II
Code Overview 44
References 46
Appendix 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.
Developers who are in initial stage of learning DFS.They must have basic knowledge of documentum.
REVISION HISTORY:
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.
Internal Use 5
Part I
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
• 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.
◦ 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.
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:
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:
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:
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.
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.
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.
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;
@SuppressWarnings("unchecked")
public static void main(String [] args) throws ServiceInvocationException {
try
{
// Get a ContextFactory so that we can
// create a ServiceContext
System.out.println("Creating ContextFactory");
ContextFactory contextFactory = ContextFactory.getInstance();
Internal Use 11
System.out.println("Populating RepositoryIdentity");
repoId.setRepositoryName(repositoryName);
repoId.setUserName(userName);
repoId.setPassword(userPassword);
// Create ObjectIdentity objects with our DQL qualifications and repository name
ObjectIdentity targetObjectIdentity1 = new ObjectIdentity(qualification1, repositoryName);
ObjectIdentity targetObjectIdentity2 = new ObjectIdentity(qualification2, repositoryName);
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);
}
}
}
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.
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.
• 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
Internal Use 15
• Determine Service Architecture
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)
@XmlAttribute
private boolean _lifeCycleAttached;
@XmlAttribute
private String _currentState;
Internal Use 16
{
this._currentState=currentState;
}
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.
@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)
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
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:
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)
@XmlAttribute
private boolean _lifeCycleAttached;
@XmlAttribute
private String _currentState;
Internal Use 19
public boolean isLifeCycleAttached()
{
return _lifeCycleAttached;
}
public String getCurrentState()
{
return _currentState;
}
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.
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
Code Snippet:
import com.emc.training.service.LifeCycleInfos;
import com.emc.training.service.client.ICustomLifeCycleService;
Run the client code as java application .If everything is fine it should consume custom service.
Internal Use 25
Part II
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.
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.
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.
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:
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.
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:
build.properties
Internal Use 28
build.xml
<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>
<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>
<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.
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();
}
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];
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;
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());
}
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();
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";
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();
}
}
Internal Use 37
{
return m_repository;
}
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:
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:
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:
In the method we are creating RepositoryIdentity object and adding it ServiceContext Object.
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);
}
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:
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
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