Escolar Documentos
Profissional Documentos
Cultura Documentos
No part of this publication (hardcopy or electronic form) may be reproduced, translated into another
language, or transmitted, in any form or by any means, electronic, mechanical, photocopying, recording,
or otherwise, without the prior written consent of Interwoven. Information in this manual is furnished
under license by Interwoven, Inc. and may only be used in accordance with the terms of the license
agreement. If this software or documentation directs you to copy materials, you must first have permission
from the copyright owner of the materials to avoid violating the law which could result in damages or other
remedies.
This Interwoven product utilizes third-party components under the following copyrights with all rights
reserved: Copyright 1997 Eric Young; 2000-2003, Apache Software Foundation (www.apache.org);
Copyright 1999, ExoLab Group; Copyright 1999-2001, Intalio, Inc. If you are interested in using these
components for other purposes, contact the appropriate vendor.
Interwoven, Inc.
803 11th Ave.
Sunnyvale, CA 94089
http://www.interwoven.com
Printed in the United States of America
Release 2.5.0
Part # 90-15-00-250-201
October 2004
Table of Contents
About This Book 5
Tip on Using This Book. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Prerequisite Knowledge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
ContentServices for TeamSite J2EE Sample Application. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Other Samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Online Documentation Errata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Chapter 1: Overview 9
ContentServices. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
ContentServices Deliverables. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
ContentServices for TeamSite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
The Java Client Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
Behind the Scenes: SOAP and WSDL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Where to Go From Here. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Chapter 2: Developer’s Overview 17
TeamSite Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Additional Concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
Programming Tips . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Part I: Getting Started 23
Chapter 3: Basics 25
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Creating a Factory Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Creating a Client Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
Chapter 4: Files, Directories, and Workareas 31
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Creating and Deleting Workareas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Renaming a Workarea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Accessing Workarea Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Displaying Files in a Workarea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Filtering the File List. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Reading and Writing Entire Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Creating and Deleting Files and Directories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Writing to a File. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Copying and Moving Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Part II: The Sample Application 51
Chapter 5: Getting Started with the
Sample Application 53
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Starting and Shutting Down Tomcat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Adding a JSP Page . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3
Adding a Servlet or Bean. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Chapter 6: Extending the Sample Application 59
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Accepting Login Values from the User . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
Filtering Login Values for the Controller. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Creating a Factory Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Authenticating Users . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Allowing Users to Log Out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Handling Exceptions. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Chapter 7: More on the Sample Application 79
Retrieving a User’s Workarea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Downloading a File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Displaying a List of Modified Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Allowing Direct Submits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Appendix A: Working with WSDL Files 95
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Generating and Using a C# Client Stub . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Appendix B: Status Codes 101
Appendix C: Mapping ContentServices 1.1 to 2.5 107
We are aware that this guide is incomplete. We will be providing additional chapters and code examples
on the Interwoven download site after the TeamSite 6.5 release. Please check there for updates.
If you have opened this guide, you want to use the ContentServicesTM for TeamSite. This
SDK is designed for many different types of developers. The client applications you can
build with it fall into three main groups:
Local Java applications running on the same host as the TeamSite server
Remote Java applications running on a different host, most likely a web or application
server, that use content or functionality in the TeamSite server
Any other application, written in any language and running on any platform (that
supports SOAP version 1.1 or earlier), that uses the TeamSite server
If you want to develop one of these applications using ContentServices for TeamSite, this
guide is for you.
Prerequisite Knowledge
Before you use this cookbook, you should know:
The type of client application you want to build
The language, platform, and technologies you plan to use for your application
Java, for reading the code examples presented here
This guide teaches you how to use ContentServices for TeamSite, along with a little about
SOAP (Simple Object Access Protocol) and WSDL (Web Services Description Language).
Most of the examples are written in Java, with a few in other languages.
5
If you are interested in reading more about industry standard web services, the
ContentServices SDK uses these technology versions:
SOAP 1.1
WSDL 1.1
Java, based on JDK 1.4
The sample application has JSP files, servlets, and beans written in JSP 1.2, Java Servlet API
2.3, and JSTL 1.0.3, all running on Apache Tomcat 4.1.27 (the release known as Catalina).
The sample is distributed as an exploded web application that you can run and as free,
supported source code that you can extend.
For this release, the sample application is distributed in a zip file. Install it according to the
instructions in quick_install_j2ee.html within the zip file. Once you install the sample
application, you might want to read the Quick Tour in tour.html to understand what it does.
As you work with the sample application, you may want to refer to an industry trade book
on the JSP, JSTL, or servlet technologies. Discussing those technologies in depth is beyond
the scope of this guide. You may have your own favorite books, but if not, these are a few
popular ones to help you:
Participating in JSP and servlet developer forums is also quite educational. If you get stuck,
you can often get your questions answered by your fellow developers.
Other Samples
This release also has a short C# example for .NET developers. It’s in the samples zip file, in
the directory samples/dotnet. You can find its installation instructions in the zip file, in
quick_install_j2ee.html. You will also find more information about WSDL files in the
WSDL chapter of this guide.
If you are a Java programmer, you can learn about ContentServices for TeamSite by running
the short Java examples in the samples zip file. You can install them and set up runtime and
development environments by following the instructions in quick_install_java.html.
Conventions
This manual uses the following notation conventions:
iw-home\etc\iw.cfg
means that you must insert the values of iw-home, role and user
yourself.
Monospaced Monospaced bold, used in an example, represents a line of code that
bold
we want to call your attention to.
7
Online Documentation Errata
Additions and corrections to this document (when available) can be downloaded in PDF
format from the following Web site: https://support.interwoven.com.
Overview
ContentServices
ContentServices is Interwoven’s line of developer tools and SDKs. ContentServices SDKs
expose certain Interwoven capabilities as web services across the internet.
Each web service is described by a WSDL, an XML formatted Web Services Definition
Language document. This file defines the requests used to invoke certain server program
capabilities and the possible responses and errors returned by that server.
Web service requests and responses are wrapped in SOAP (Simple Object Access Protocol)
messages, sent across HTTP or HTTPS connections.
These SOAP requests can either be generated directly by a client program or by invoking
client stubs in a specific programming language, such as Java or C#, that in turn generate the
SOAP requests and then translate the SOAP responses back to the application program.
Industry standard J2EE or .NET tools exist to automatically generate client stubs from
WSDL files. By supplying a WSDL file, a software vendor can potentially enable programs
in many different languages to access a given web service.
ContentServices Deliverables
ContentServices SDKs vary in their deliverables.
In some cases, such as the ContentServices for OpenDeploy, the SDK consists of the web
service server (for the host machine) and a commented WSDL, plus sample client stubs and
example programs for at least one programming language.
9
Overview
In other cases, such as ContentServices for TeamSite, the SDK also includes a supported and
documented client library for at least one language.
A client library has an additional layer built on top of its client stubs to provide caching,
iterators, client-side convenience calls, and other features designed to improve client
application performance when accessing those web services. Such libraries are generally
only useful when extensive context and data transfers are often needed before invoking the
services’ primary functionality (which is not the case for all web services).
In these cases, customers who wish to use other languages can still use the supplied WSDLs
to generate client stubs but may want to consider building additional client side
functionality on top of these generated stubs in order to efficiently use those web services.
This release of ContentServices for TeamSite does not use ContentServices Foundation.
Instead, ContentServices for TeamSite continues to use its own access service, as it did in
earlier versions.
Java or J2EE applications that run on a web or application server, use TeamSite content,
and integrate some TeamSite functionality such as workflow or version control. This
type of application might be, for example, a corporate Intranet site with a TeamSite
mini-UI.
Microsoft .NET applications that use technologies such as ASP, Visual Basic, or C#, run
on an external host, and include some TeamSite content or features
Standalone desktop applications written in Java, C++, C#, or other languages that
integrate TeamSite features and use UI components built with a toolkit specific to the
language or platform, such as Java Swing or a Windows UI toolkit
Portals and portlets that run on a centralized portal server. Portlets are typically
developed using the portal vendor’s toolkit, but can use TeamSite functionality through
the ContentServices SDK.
For Java developers, the developer’s kit offers an easy-to-use Java interface and the choice
of local or remote communication with the TeamSite server. For developers working in
other languages, the SDK provides WSDL (Web Services Description Language) files that
can be used to generate client stubs. The stubs provide access for non-Java applications.
This guide describes how to use the ContentServices to build TeamSite client applications.
You might also be interested in the ContentServices UI Toolkit, which allows you to
customize the TeamSite server’s out-of-the-box user interface. Using Content Services for
TeamSite programmatically as described in this guide is a bit more involved, but also more
powerful.
Architecture
ContentServices for TeamSite has two basic modes. The first uses Java Native Interface (JNI)
as its transport, for local applications running on the same host as the TeamSite server.
The second mode uses SOAP to allow either local or remote applications to use the
ContentServices SDK and access the TeamSite server. Your application can use a single
setting in a properties file to indicate the transport, SOAP or JNI. Otherwise, the
ContentServices methods your application uses are the same.
ContentServices JNI
Applications that run on the same host as the TeamSite server (called local applications)
typically use ContentServices JNI for better performance. JNI allows Java code to work
with libraries written in other languages. The ContentServices JNI module is built directly
on top of the TeamSite server. Your application calls the ContentServices Java client
library, and the JNI module converts those calls for the internal TeamSite C++ library.
Java Calls
ContentServices
Local Java Applications
Java Client Interface
JNI Calls
ContentServices SOAP
Remote applications use the service-oriented architecture of ContentServices SOAP. A
remote application functions as a web service client, sending automatically generated SOAP
requests to a web service built into ContentServices for TeamSite.
11
Overview
A web service is a software component with two main features. It is accessible through
SOAP, and it has a WSDL file that defines how clients access it. SOAP allows one
application to send an XML message to another application, regardless of language or
platform. This feature allows almost any application to use the ContentServices for
TeamSite.
Java Calls
Local Calls
SOAP SOAP
Web Server
FastCGI
com.interwoven.cssdk
access Defines users and how they access the TeamSite server
The first step in any ContentServices for TeamSite Java application is creating a factory
object that determines how the application will communicate with the TeamSite server.
The factory object is specific to JNI, or specific to SOAP, or a generic object that reads the
transport type from a properties file.
Keeping things very simple, you might want to create a factory object and then say Hello,
World (a longer version of this example, with a properties file, is described in Chapter 3,
“Basics”).
13
Overview
import com.interwoven.cssdk.factory.*;
import java.util.*;
import java.io.*;
CSFactory factory;
String name;
// display messages
System.out.println( "Factory of type " + name + " created" );
System.out.println( "Hello, World!" );
}
}
If you run this simple Java program on ContentServices SOAP, you will see this output:
This shows that our sample application is using the ContentServices for TeamSite SDK. To
run this sample on ContentServices JNI, you would update the properties file at runtime,
with no need to update code.
The SOAP message has a body and an optional header. The ContentServices method calls
are packaged within the body.
SOAP Envelope
SOAP Body
When the SOAP message is created, the method calls are translated according to a
definition in a WSDL file. WSDL files define how a client calls a web service. The translated
WSDL call appears in the body of the SOAP message and is the same no matter what
language the application is written in.
The SOAP server receives the message and sends it to the C++ library and the TeamSite
server. The TeamSite server, when it receives the request, returns a response. The SOAP
15
Overview
server then packages the TeamSite response into a SOAP response and sends it back to your
client application.
To get started extending or developing with the J2EE sample application, go to Chapter 6,
“Extending the Sample Application.”
To understand WSDL files and how to create a stub for the Java client interface so that you
can use C#, .NET, or other technologies, go to Appendix A, “Working with WSDL Files.”
To get detailed information about the classes and methods in the Java client interface, use
the ContentServices SDK Javadoc, available in the TeamSite server installation, on the
product CD, or from the download site.
Developer’s Overview
TeamSite Overview
TeamSite is an Interwoven product that provides access to:
The Interwoven Content Server, a content repository and virtual file system.
Workflow capabilities, used to automate and control content creation.
TeamSite Templating, used to define, enter, and view structured content as forms.
The ContentCenter user interfaces, ContentCenter Standard and Professional, are browser
entry points into the web application that provides end user access to these and other
capabilities. Not all functionality that exists in the ContentCenter user interfaces, such as
their search and reporting capabilities, are exposed programmatically as APIs in
ContentServices for TeamSite.
Each Interwoven file store partitions its content into areas, each of which is organized in a
directory structure that can be navigated as an ordinary file system.
Each workarea contains a virtual copy of that portion of the Interwoven file system. Each
virtual file copy is automatically replaced by an actual copy as needed. Workareas can be
provided for each user or shared by groups of users. Within a workarea, a file’s content can
be successively modified before being submitted.
Each group of related workareas has one staging area that contains the latest integrated
version of each file in that portion of the Interwoven file system. An integrated file version
reflects, successively, all past submissions of modified versions of that file from the staging
area’s related workareas.
17
Developer’s Overview
Submitting a file from a workarea logically copies the file from that workarea to the staging
area, updating its content and creating a new version. A modified file in a workarea is one
whose content has changed but which hasn’t yet been submitted to the staging area.
Updating a file in a workarea typically replaces it with the latest version currently in the
staging area.
A hole represents an absence of a file or directory. After deleting a file in a workarea, its hole
(with the same name) must be submitted to delete that file from the staging area.
An edition is a logical “snapshot” of the contents of a staging area at a given point in time.
A file’s extended attributes is the series of name-value pairs associated with that file, also
stored within the Interwoven file system but not visible through the directory structure.
TeamSite Workflows
A workflow or job process is used, for example, to assign work to a user or to implement a
review and approval process before submitting a modified file to the staging area.
A workflow consists of a series of tasks. A task can have a number of files attached to it,
allowing them to be part of an assignment or, after being edited, to be easily viewed by an
approver.
Each successive task in a workflow has a series of task comments associated with it, which can
be extended by users involved with that workflow’s execution. This allows users to specify,
for example, the content changes that were made or why a submission was not approved
and what further edits need to be done.
Each file attached to a task has its own comment series as well, allowing detailed
instructions or comments to be made on a per file basis.
Note: Do not confuse workflow templates with TeamSite Templating, described below.
Until a given workflow is done executing, its current status can be queried. After a
workflow is done executing, it can no longer be queried. In addition, all its comments (both
task comments and file comments) are no longer stored.
Even though it is possible to submit files from a workarea directly to the staging area, files
are typically submitted for approval by initiating a submit workflow. This workflow does the
actual submit to the staging area as part of its final task (assuming the reviewer actually
approves the content changes).
A workflow can be designed to achieve many other effects as well, such as generating a
template output file when a given DCR is submitted.
TeamSite Templating
Structured data is represented by a series of data content record files or DCRs. Structured data
is captured by filling out forms or data capture templates. Each set of related DCRs is
associated with a different data type. These are organized into a hierarchy of data categories
and data types, which can be browsed by end users.
For a given data type and DCR, different presentation templates will generate different
formatted output files, which can be previewed. Each template output file contains, in its
extended attributes, the name of the DCR and presentation template from which it was
generated. Similarly, each DCR contains its data type in its extended attributes.
TeamSite Roles
TeamSite users also have one or more roles assigned to them. A user acting as a given role
may be prevented from doing certain TeamSite operations available to other roles. In
increasing order of capability, the standard TeamSite roles are Author, Editor,
Administrator, and Master.
Additional Concepts
The following sections describe more advanced features of the Interwoven file system. You
may wish to return to this section after studying the file system package Javadoc.
Specifying VPaths
An Interwoven file system consists of a default store (multiple stores are supported in
TeamSite 5.5 and later), each subdivided into one or more branches, each possibly subdivided
into sub-branches. Each branch has its own staging area, zero or more workareas, and a
series of editions.
The path describing a workarea is its workarea VPath. The path describing a file’s location
within an area is its area relative path. Combined together, a file’s full VPath describes its
precise location in the Interwoven file system.
A vpath (“version path”) is a path within the TeamSite content repository, specified as one
of the following:
/store/branch+/EDITION/edition
/store/branch+/WORKAREA/area/directory*/file
/store/branch+/STAGING/directory*/file
where “+” indicates 1 or more; * indicates 0 or more, and a path may omit the elements
below it in order to specify just a directory, area, branch, or store.
19
Developer’s Overview
A branch may not be named EDITION, WORKAREA, or STAGING. STAGING is a special area
that every branch has. Thus, a URL command parameter that is an area requires either a
workarea (specified as WORKAREA/workareaname) or STAGING.
/default, a
store.
/default/main, the branch main.
/default/main/pubs, the branch pubs.
/default/main/pubs/EDITION/initial, the edition initial.
/default/main/pubs/STAGING, the STAGING area for the pubs branch.
/default/main/pubs/WORKAREA/uitk, the workarea uitk.
/default/main/pubs/WORKAREA/uitk/guide/examples, a directory.
/default/main/pubs/WORKAREA/uitk/guide/examples/example1, a file.
/default/main/pubs/WORKAREA/uitk/README, a file directly under a workarea.
The path delimiter can be either “/” or “\” when specifying a TeamSite path, but will be
output as: “/” (Unix) or “\” (Windows).
Optionally, a vpath can include the server name by prepending //servername to it, though
doing so is generally not needed.
For more information on specifying a vpath, see the TeamSite Command-Line Tools manual.
A version conflict occurs when a modified file in a workarea is out of date with respect to the
integrated version of that file in the staging area, due to a submission of an equivalent file
(with the same area relative path) from a different workarea associated with the same
staging area.
A file’s version conflict can be resolved either by overwriting the version in the staging area
with the version in the workarea or by overwriting the version in the workarea with the
version from the staging area.
The content of two files in version conflict may or may not be in conflict in the sense of being
able to trivially merge their content differences (in certain circumstances their content
could be identical).
Content merging, if performed, is a client side operation. A client application can read the
content of a modified file in a workarea, update that file by overwriting it with the latest
version from the staging area, read the latest version of the file, perform the content merge
(typically relying on user input for decisions that arise), write the file’s newly merged
content, and then submit that file normally.
Locks
A lock is placed on a file in a workarea and establishes a privileged status for that particular
file with respect to all equivalent files located in different workareas (i.e., with respect to
those files with the same area relative paths in workareas associated with this staging area).
These files may be viewed but can neither be edited nor submitted to the staging area until
either the lock is released or the locked file itself is submitted to the staging area. A lock on a
file is automatically released when that file is submitted (no client side operation is needed).
Potential version conflicts can be avoided if all users always lock and then get the latest
version of a file from the staging area before opening files for modification.
While this avoids versioning conflicts and the need to possibly merge content, end users
may encounter lock conflicts instead, when a file is unavailable for editing due to an
outstanding lock. However, if end users are informed who holds a lock when a lock conflict
occurs, the end user locked out can request (via e-mail or other means) that the user with
the lock either submits the modified file or releases its lock.
Note: Simply releasing the lock in this case creates a potential version conflict. To avoid
this, combine releasing the lock with undoing the unsubmitted changes to the
released file.
Locking Models
When a TeamSite branch is first created, its locking model is specified. There are three
branch locking models supported by TeamSite:
Submit locking—if a file is locked, only users within the workarea where it is locked
may submit the file to the staging area. Users within other workareas are still allowed to
edit their copies of this locked file but may not submit any of them until the user who
holds the lock either submits their version of the file or releases the lock upon it.
Optional write locking—if a file is locked, only users within the workarea where it is
locked may edit (or submit) the file to the staging area. Users within other workareas
are still allowed to view their copies of this locked file but may not open them for
editing (or submit them) until the user who holds the lock either submits their version
of the file or releases the lock upon it.
Mandatory write locking—a file must be locked before it can be edited. Once locked,
users within other workareas can view their copies of this file but may not open them
for editing (or submit them) until the user who holds the lock either submits their
version of the file or releases the lock upon it.
Submit locking is the default and least restrictive locking model. If a file is not locked under
either submit locking or optional write locking, then different copies of the same file can be
freely edited in different workareas, resulting in versions that are in conflict once one copy
has been submitted and then an attempt is made to submit another copy. Within the
ContentCenter GUIs, the merge tool then appears to allow a user to resolve any conflicts in
the actual content of the conflicting files before resolving the version conflict.
21
Developer’s Overview
Programming Tips
Programming to ContentServices for TeamSite poses challenges similar to programming to
any client-server architecture:
Minimize the number of calls from your client application to the TeamSite server.
Client to server calls (“across the wire”) are much more expensive than other calls that
your application program will make.
Avoid stale data. While caching data can reduce the need to make extra calls to the
server, it can occasionally result in an incomplete or inaccurate view of the TeamSite
server’s state. When it is important that the state be accurate, refresh your cached data.
ContentServices provides methods to do so.
Minimize end-user waiting (latency) when transferring a large file or list, by breaking it
into smaller chunks or using an iterator. ContentServices for TeamSite provides
methods for breaking a file stream into chunks and to iterate over collections of objects.
Use them.
Don’t transfer huge amounts of data that you don’t use. This is often the biggest cause
of poor client application performance. ContentServices for TeamSite provides
numerous methods that return only a “skeletal” object, not a fully fleshed out object
with all its members populated. If you’re only using an object to navigate to another
object (say, from a branch to one of its workareas), then request only the skeletal object.
Similarly, whenever possible, filter collections of objects on the server side, before
transferring the objects you need to the client application.
23
24 ContentServices for TeamSite Cookbook
Chapter 3
Basics
Introduction
To start building ContentServices SDK applications, you need to learn certain basic tasks.
The first and most basic is how to create a factory object, which determines whether your
application uses ContentServices JNI or ContentServices SOAP (this chapter presents more
detail than the Overview chapter). This task is part of building any ContentServices SDK
application.
Of course, all applications exist for users. The second basic task you need to learn is how to
accept login values (a user name, password, and role) and use them to authenticate a user on
the TeamSite server.
Task
You need to create a factory object as the first step in building a ContentServices SDK
application. You know whether you want to use ContentServices JNI or ContentServices
SOAP, although this can be configured at runtime.
Solution
Use a generic CSFactory.getClient method and configure the settings for JNI or SOAP in
a properties file that is read at runtime.
Examples
CSMoreHelloWorld.java
Usage:
java CSMoreHelloWorld
Discussion
The first step in any ContentServices SDK application is creating a factory object. The
factory object is an instance of com.interwoven.cssdk.factory.CSFactory or one of its
subclasses, CSLocalFactory or CSSOAPFactory, and determines how your application will
communicate with the TeamSite server.
25
Basics
Because you want to configure the transport (SOAP or JNI) at runtime, create a properties
file first. The next example shows a minimal properties file, with settings for both JNI and
SOAP, but presently set for SOAP (as those lines are uncommented).
Property Value
com.interwoven.cssdk.factory. com.interwoven.cssdk.factory.
CSFactory CSLocalFactory
cssdk.cfg.path Location of the cssdk.cfg file
data.cache.timeoutms Number of milliseconds until data cache timeout.
Default is -1, meaning never time out. A JVM-wide
property affecting the way all CS SDK objects in
the same class loader behave.
Property Value
com.interwoven.cssdk.factory. com.interwoven.cssdk.factory.
CSFactory CSSOAPFactory
serviceBaseURL The base URL of the ContentServices SOAP
server:
http[s]://host:port
http[s]://host:port
data.cache.timeoutms Number of milliseconds until data cache
timeout. Default is -1, meaning never time out.
A JVM-wide property affecting the way all
ContentServices SDK objects in the same class
loader behave.
keystore.location The keystore location. Required if you use SSL
access over HTTPS.
27
Basics
Once you have written the properties file, you can use it to create a generic factory object.
import com.interwoven.cssdk.factory.*;
import com.interwoven.cssdk.common.*;
import java.util.*;
import java.io.*;
CSFactory factory;
String name;
CSVersion version = null;
int major;
int minor;
} catch ( CSException e ) {
System.out.println( "An exception occurred" );
e.printStackTrace();
}
}
}
Hello, World
From the output, you know that CSMoreHelloWorld is communicating with the
ContentServices SDK using SOAP (as indicated by AxisFactory).
See Also
“Creating a Client Object” on page 29” to learn how to make your application start
communicating with the TeamSite server
“Creating a Factory Object” on page 68” to see how the factory object is created in the
J2EE sample application
Task
Now that you have a factory object, you want to create a client object to begin
communicating with the TeamSite server.
Solution
Use the factory object to create a client object using one of the forms of getClient. Then,
use the client object getClient returns to retrieve objects from the TeamSite filesystem.
Example
CreateClient.java
Usage:
java CreateClient username password role
Discussion
The client object represents the user’s session on the TeamSite server. The server returns
the client object if it can authenticate the user with the credentials the user supplies
(typically, a username, password, and role).
If creating a factory object is the first coding step in a ContentServices SDK application,
creating a client object is the second. Once you have the client object, you use it to retrieve
branches, workareas, files, workflows, or anything else relating to the user. You also use it
to end the user’s session.
29
Basics
The factory package has two basic forms of getClient. The getClient method used
most often takes a username, role, and password to identify the user, along with a locale,
application context string, and server name:
To use this form of getClient in your application, you would request a username,
password, and role from your user.
Example 3: Creating a Client Object with User Name, Password, and Role
The other form of getClient takes a session string to identify the user, along with the three
other items:
Use this form of getClient when the user has already been authenticated and has a valid
TeamSite session.
See Also
“Creating a Factory Object” on page 25” to see how to create a factory object.
Introduction
In the ContentServices SDK, all files are subtypes of CSFile. The most common file type is
CSSimpleFile, which represents any file that has content and is stored at a specific vpath
(this is TeamSite terminology; short for version path). Files also include directories,
symbolic links, and holes.
com.interwoven.cssdk.filesys
CSFile CSDir
CSSimpleFile
CSSymlink
CSHole
...
Files are stored in workareas and have both a vpath, represented by CSVPath, and an area
relative path, represented by CSAreaRelativePath. A vpath starts with a leading slash,
followed by the name of a store, then the name main, with optional extra information
before and after. These are all valid vpaths:
/default/main/web/WORKAREA/demo
//everest/default/main/web/WORKAREA/demo
/default/main
/default/main/STAGING
The file’s area relative path is the part of the path after WORKAREA, STAGING, or EDITION and
is available for operations you perform within an area. For the first two vpaths listed above,
the area relative path is demo.
31
Files, Directories, and Workareas
Files have both attributes and content. Attributes contain information about the file, such as
the file’s name, size, last modification date, and so on. You can see the type of attributes you
can retrieve by looking at the getter methods defined in CSFile:
getArea getAttributeModificationDate
getCommonPredecessor getContentModificationDate
getFileRevision getFileRevisionHistory
getLastModifier getLockArea
getLockAreaVPath getLockComment
getLockCreationDate getLockCreator
getLockOwner getName
getPermissions getPredecessors
getRelatedTaskIds getRevisionBranch
getRevisionComment getRevisionNumber
getRevisionString getSubmitRecord
getSuccessors
Once you display the attributes in your application, you can provide a link, icon, or other
mechanism a user clicks to view or edit the file content. Your application can then read an
individual file’s content with CSSimpleFile.read or CSSimpleFile.getInputStream.
A workarea contains files and directories and is contained within a branch. The workarea is
an object that implements CSWorkarea, which inherits from CSArea.
CSCacheableObject
CSArea CSWorkarea
CSNode
A workarea can be updated at any time from the staging area, an edition, or another
workarea. A user can also edit files in a workarea and then submit them to staging, either
directly or for workflow approval.
Workareas always have access rights. The workarea’s owner (of type CSUser) can always
make changes in a workarea. Other users can make changes if the workarea was created
with group access and the users belong to the group. For example, this command creates a
workarea named demo, owned by the user bob, but granting access to any user in the group
webdev:
The tasks you typically want to perform with workareas are displaying a list of files in
workarea’s root directory, displaying all files and directories in the workarea, and
submitting a file directly from the workarea to staging.
Task
You want to create or delete a workarea in the TeamSite filesystem from your application, in
response to some input a user has entered.
Solution
To create a workarea, use the client object to get the branch where the workarea will be
created. Then, from the branch, use createWorkarea.
Deleting a workarea is easy. From the client object, get the workarea. Then, from the
workarea, call the delete method.
Examples
CreateWorkarea.java
Usage:
java CreateWorkarea username password role branch-vpath wa-name group
DeleteWorkarea.java
Usage:
java DeleteWorkarea username password role wa-vpath
Discussion
Remember to always create a workarea from a branch.
When you create a workarea, you must specify CSUser and CSGroup objects as arguments
to createWorkarea. The CSUser is the workarea owner, and the CSGroup is a group that
has access to the workarea.
You are allowed to enter null for either. If you enter null for CSUser, the workarea is
owned by the current session user (specified in the client object). A null value for CSGroup
means that the workarea is private and not shared with a group.
createWorkarea also requires an edition on which the workarea is based. Editions are
readily available from the getBaseEdition, getFirstEdition, and getLastEdition
methods.
33
Files, Directories, and Workareas
try {
System.out.println( "Getting client with username " + username
+ ",
password " + password + ", and role " + role );
client = factory.getClient( username, role,
password, Locale.getDefault(),
"mydemo", null );
} catch ( CSException e ) {
System.out.println( "An exception occurred" );
e.printStackTrace();
}
When deleting a workarea, first use CSClient.getWorkarea to retrieve the workarea with
a vpath. getWorkarea (like many methods in CSClient) uses a Boolean validate
parameter that determines whether the vpath is validated when the workarea is retrieved.
try {
System.out.println( "Getting client with username " + username + ",
password " + password + ", and role " + role );
client = factory.getClient( username, role,
password, Locale.getDefault(),
"mydemo", null );
System.out.println( "Client object obtained" );
} catch ( CSException e ) {
System.out.println( "An exception occurred" );
e.printStackTrace();
}
See Also
“Renaming a Workarea” on page 35 to see how to change a workarea’s name
“Accessing Workarea Properties” on page 36 to display information such as the
workarea name or creator
Renaming a Workarea
Task
You want to rename a workarea, leaving it in the same branch.
Solution
Get the client object, then call getWorkarea from it to get the workarea. From the
workarea, use CSWorkarea.rename. The new workarea name must be unique in the branch,
or the TeamSite server throws a CSObjectAlreadyExistsException.
Example
RenameWorkarea.java
Usage:
java RenameWorkarea username password role old-wa-vpath new-wa-name
Discussion
Renaming a workarea is easy and uses the same pattern as deleting a workarea. You need the
vpath of the existing workarea (to create a CSVPath object) and a String for the new name.
Example 6: Renaming a Workarea (RenameWorkarea.java)
35
Files, Directories, and Workareas
try {
System.out.println( "Getting client with username " + username + ",
password " + password + ", and role " + role );
client = factory.getClient( username, role,
password, Locale.getDefault(),
"mydemo", null );
} catch ( CSException e ) {
System.out.println( "An exception occurred" );
System.out.println( "The workarea was not renamed" );
e.printStackTrace();
}
See Also
“Creating and Deleting Workareas” on page 33 to see how to delete a workarea
Task
You want to display information about the workarea, such as the creator, creation date, or
description, or you want to check if the current user has write access.
Solution
Obtain the factory object, then the client object, as usual. Use the client object with a
CSVPath (converting a String to a CSVPath, if necessary) to get the workarea, a
CSWorkarea object. Then, use the methods in CSArea to get information about the
workarea.
Example
GetWorkareaInfo.java
Usage:
java GetWorkareaInfo username password role wa-vpath
Discussion
Once you have the client object, use getWorkarea to return the workarea. getWorkarea
takes two arguments and has this signature:
Many of the methods in CSClient take a validate argument. The validate argument
specifies whether the object should be validated before it is returned.
If validate is true, the vpath is validated when the workarea is returned, and if the vpath
does not exist, getWorkarea returns null. If validate is false, the vpath is not validated.
If the vpath does not exist, getWorkarea returns a shallow object that is not null. When
you call a method such as getName from the shallow object, the getter method returns an
exception.
try {
System.out.println( "Getting client with username " + username +
", password " + password + ", and role " + role );
client = factory.getClient( username, role,
password, Locale.getDefault(),
"mydemo", null );
System.out.println( "Client object obtained" );
Once you have the workarea, use the getter methods in CSArea to get information about it.
The isWritable method refers to the user authenticated in the client object. When you
run GetWorkareaInfo, it displays workarea information something like this:
37
Files, Directories, and Workareas
Task
You want to retrieve file attributes from a user’s workarea and display a file list.
Solution
Use one of the forms of CSArea.getFiles. The getFiles method retrieves the file
attributes and returns a CSIterator.
You can then iterate through the returned files, using the getter methods in CSFile to
display the file name, size, and other attributes. The actual display is defined by the type of
application you are writing. The example in this task displays file attributes in a command
window.
Example
GetWorkarea.java
Usage:
java GetWorkarea username password role wa-vpath
Discussion
The getFiles method has two forms, a short form and a long one. Use the short form
when you have a specific list of area relative paths and want to return just those files:
public CSFile[] getFiles(CSAreaRelativePath[] filePaths)
Use the long form when you want to return all the files in the root directory of a workarea or
specify some that should be filtered and not returned:
int maxElements)
The CSIterator object returned by the long form works like a standard Java iterator, with
hasNext() and other methods.
Then, use the getter methods defined in CSFile to retrieve, and display various attributes
like file name, size, last modifier, and last modification date.
The displayed files (from the root of the workarea, displayed in order by name) look like
this:
39
Files, Directories, and Workareas
See Also
“Filtering the File List” on page 40 if you want to display only some files in the workarea
“Retrieving a User’s Workarea” on page 79 to see how a user’s workarea is displayed
using JSP and the JSP Standard Tag Library (JSTL) in the J2EE sample application
Task
You want to list only some files in a user’s workarea.
Solution
You need to know the name of the workarea you want to retrieve. In the samples used in this
task, you specify the workarea name on the command line.
Example
GetWorkareaWithRegex.java
Usage:
java GetWorkarea username password role wa-vpath
Discussion
Once you have the workarea name, you can retrieve the file attributes with
CSArea.getFiles. If you want to filter and list only a subset of files in the workarea, you
need to use the long form of getFiles:
The getFiles method filters twice when it returns files, using a combination of
fileTypes, fileTypesForNameRegex, and nameRegex. Both fileTypes and
fileTypesForNameRegex take constants defined in CSFileKindMask that define a group of
files, such as ALLTYPES, DIR, SIMPLEFILE, and so on.
The first filter finds the large group of files that matches fileTypes. From this group, the
second filter finds the small group that matches fileTypesForNameRegex and applies the
regular expression to them. This group can be the same as or smaller than the fileTypes
group. The regular expression applies only to the files in this list.
The files are sorted according to the value of sortKeys, by name, owner, size, or other
values, in ascending or descending order.
A simple example (from GetWorkareaBean in the J2EE sample application) would return
all files in a workarea except holes.
41
Files, Directories, and Workareas
Another example might return attributes for all files in the root of the workarea that end in
.doc.
The getFiles method in Example 12 on page 42 returns only simple files and directories.
It would apply the regular expression to the simple files and return only those that match
(that is, all files ending in .doc). It would also return all directories, without applying the
regular expression.
The getFiles method in Example 12 on page 42 would return just the files ending in .doc.
Even more, because sortArray uses CSSortKey.NAME and true, the files are returned in
ascending order by file name.
See Also
“Reading and Writing Entire Files” on page 43 to see how to read a file’s content
“Displaying Files in a Workarea” on page 38 to learn how to retrieve and display
attributes for all files in the root of the workarea
Task
You want to read a file from the TeamSite server and copy it to another location, such as an
external filesystem for a user to edit.
Solution
Reading a file reads its content, not its attributes (remember that getFiles retrieves
attributes, not content). Bringing content from an external source (the TeamSite server)
and sending it to an external destination (your user’s filesystem) uses input and output
streams. The methods to use are getInputStream and getOutputStream in
CSSimpleFile.
Example
FileDownloadServlet.java
(in the J2EE sample application)
Discussion
Reading and writing file streams reads the entire file. Whether you are reading a stream or
writing a stream, the technique is almost the same:
Open a stream
As long as there is more information, read it or write it
Close the stream
43
Files, Directories, and Workareas
First, let’s look at an example of using getInputStream to read a file’s content from the
TeamSite server, through the ContentServices SDK, to your client application. Typically, a
user will download a file from your client application to a local directory for editing, either
explicitly or implicitly through a user interface.
This example comes from FileDownloadServlet in the J2EE sample application. This
servlet causes the browser to display a dialog box, which the user can use to open or
download the file. The browser does part of the work, so this example doesn’t need to use
an output stream.
The basic technique for reading files is to call getFile with a CSVPath, then use the
returned CSSimpleFile to get the file’s input stream.
InputStream in = null;
try {
// use the csvpath to get the file
CSSimpleFile f = (CSSimpleFile) client.getFile( vpath );
// do the buffering
byte[] buf = new byte[4 * 1024]; // 4K buffer
int bytesRead;
while ((bytesRead = in.read(buf)) != -1) {
out.write(buf, 0, bytesRead);
}
// catch any exceptions
catch (CSException e) {
throw new CSWebAppException(e);
}
// and clean up
finally {
if (in != null) in.close();
}
}
Writing a file copies updated content from a local directory, through your application, then
through the ContentServices SDK, to a workarea on the TeamSite server. (Remember that
it needs to be submitted to staging to be available to users who don’t have access to the
workarea.)
See Also
“Filtering the File List” on page 40 to see how to retrieve and display file attributes
Task
Your application needs to create or delete a file or directory in a workarea, in response to
user input.
Solution
It is easy to create files and directories in a workarea with CSWorkarea.createDirectory
or CSWorkarea.createSimpleFile methods. You can delete a file or directory from a
workarea with CSFile.delete. If the file has been submitted to staging, you also need to
submit its hole to delete the file from staging.
Examples
CreateFile.java
Usage:
java CreateFile username password role wa-vpath file-area-rel-path
DeleteFile.java
Usage:
java DeleteFile username password role vpath
Discussion
Once you have the client object, you can use it to get the workarea. Then, from the
workarea, call createDirectory and createSimpleFile. In this example, the directory
and file names created are hard-coded.
In your application, however, you will want to provide a mechanism for users to enter or
choose a file or directory name to create. When you receive the file or directory name from
45
Files, Directories, and Workareas
the user, convert it to a CSAreaRelativePath object. In Example 14 on page 46, the area
relative path is within the demo workarea you created during the samples setup.
Deleting files is a similar process. You get the area relative paths as strings from your user;
convert them to CSAreaRelativePath objects and build an array; use the array with the
short form of getFiles to get an array of CSFile objects; then, delete each file in the array
with CSFile.delete.
The easiest way to test this example is to run CreateFile, without submitting the file to
staging, then DeleteFile to delete it from the workarea.
See Also
“Filtering the File List” on page 40 to see how to use the long form of getFiles
Writing to a File
Task
You want to write something to a specific point in a file, either an arbitrary string or a user’s
edit. You want to lock the file before you write to it and unlock it after.
Solution
The file you write to must be a simple file, not a directory, symbolic link, or hole. First,
lock the file with CSFile.lock; then, write some edits to it with CSSimpleFile.write.
When you are done, unlock it with CSSimpleFile.unlock and end the user’s TeamSite
session.
Example
WriteToFile.java (run CreateFile first to create an empty file)
Usage:
java CreateFile username password role wa-vpath file-area-rel-path
java WriteToFile username password role source-path target-vpath
You can use comment.txt (in the same directory as WriteToFile) as source-path.
Discussion
Use CSSimpleFile.write when you want to place some edits at a certain point in a file.
The write method has this signature:
This method asks you to write an array of bytes to the file, starting a specific point and
extending for a specific length. You can also choose whether to truncate the file’s existing
content after the write.
A simple way to demonstrate this is to create an empty file, then read a comment from a
text file and write it to the empty file. Of course, you want to lock the file before writing
and unlock it after.
47
Files, Directories, and Workareas
} catch ( CSException e ) {
System.out.println( "An exception occurred" );
e.printStackTrace();
} catch ( IOException io ) {
io.printStackTrace();
} finally {
if ( client != null ) {
client.endSession();
}
}
Example 15 on page 46 reads text from a file (the file suggested for the example is
comment.txt) and writes it to position 0 of the named file. The false value specifies not to
truncate the file after the write.
If you run this example as suggested, creating an empty file and then reading comment.txt
into it, your new file has this content:
a comment to write
See Also
“Reading and Writing Entire Files” on page 43 to see how to read entire files
Task
You want to copy or move files from one workarea to another.
Solution
Use the copy and move methods in CSFile. They both take boolean arguments specifying
whether to overwrite files of the same name in the target location. The example used in this
task takes one source vpath (for CSClient.getFile) and copies the file or directory to a
target area relative path (for CSFile.copy or CSFile.move).
Example
CopyFile.java
Usage:
java CopyFile username password role source-vpath target-area-rel-path
All paths must exist in the TeamSite filesystem.
MoveFile.java
Usage:
java MoveFile username password role source-vpath target-area-rel-path
All paths must exist in the TeamSite filesystem.
Discussion
The copy and move methods both require that you have the source file as a CSFile object.
Your application will probably accept the source vpath as a String from your user. If you
accept one source file name and use getFile to retrieve the file, convert the String to a
CSVPath object, then from the CSVPath get the CSFile.
49
Files, Directories, and Workareas
Then, convert the target location to a CSAreaRelativePath and call copy on the source
CSFile.
Moving files works the same way, except that you use CSFile.move instead of
CSFile.copy.
// do the move; true overwrites existing files of same name in the target
sourceFile.move( targetPath, true );
For copy and move to work, the target location must be valid on the TeamSite server. If the
target location is a file, the boolean parameter specifies whether to overwrite the file. If the
target is a directory, the file is copied or moved into the directory.
See Also
“Creating a Client Object” on page 29 to see how to create the client object needed to
get a single file
51
52 ContentServices for TeamSite Cookbook
Chapter 5
Introduction
The ContentServices SDK sample application demonstrates some ContentServices
functionality, but more important, gives you a place to build JSP pages, servlets, beans, or
other classes to play with the ContentServices SDK or build your own application. The
sample application has a modular model-view-controller design and is built according to
design patterns outlined in the J2EE Blueprints (see http://java.sun.com/blueprints).
This means it’s easy for you to get started and add your own components. The sample
application uses Tomcat 4.1.18, JSP 1.2, the Java Servlet 2.3 API, and the JSP Standard Tag
Library (JSTL) 1.0, as well as the Interwoven ContentServices SDK 2.0 and Teamsite 6.0.
Task
You want to start Tomcat, or shut it down gracefully. You also want to be able to see error
messages or any status messages your application sends you in the Tomcat console window.
53
Getting Started with the Sample Application
Solution
After installing Tomcat and setting environment variables correctly, you start Tomcat by
opening a command window and entering:
> catalina run
When you’re ready, you can shut down Tomcat gracefully by opening a second command
window and entering:
> shutdown
Discussion
After you start Tomcat, you should see messages in the console window like this:
You know you’ve started Tomcat successfully if you see these messages. You can now view
the Tomcat index page by opening a web browser and entering http://localhost:8080. You
should see this window.
The reason to use catalina run to start Tomcat, rather than startup, is to keep the
console window open. If errors occur during startup, you want to see them so that you can
resolve them. In addition, the sample application has informative System.out.println
messages that appear in the console window at certain points. (If you’re wondering about
the names of commands, the servlet container is called Catalina, and the JSP container is
called Jasper; together they make up the Tomcat server.)
welcome file in web.xml, a URL ending in webapp_name will automatically route there, so
that you don’t need to enter the file_name:
Always shut down Tomcat with the shutdown command, rather than using Control-C to
stop the Tomcat process. This allows web applications to shut down gracefully and release
any connections to external resources such as databases or the TeamSite server.
Task
You want to add a JSP page to the sample application.
Solution
A complete web application has various types of resources, which can include JSP pages,
HTML pages, images, style sheets, servlets, applets, beans, custom tag libraries, and other
Java classes. The web.xml deployment descriptor is required.
You can deploy these resources as a group of files in a directory structure (called exploded
form), or you can archive them into a WAR (web application archive) file and deploy just
the archive. Whether you use exploded or web archive form, the directory structure is the
same. During development, we recommend that you use exploded form, so that you can
add one or more components at a time. In addition, some servlet methods work in an
application in exploded form, but not in web archive form. (Please refer to the Java Servlet
2.3 API documentation for details.)
Discussion
The directory structure for an exploded web application looks like this:
/tomcat
/webapps
/your_webapp # this level is the context root
*.jsp
*.html
spring/*.jsp
summer/*.jsp
/images
/WEB-INF
web.xml
/classes
/lib
55
Getting Started with the Sample Application
Directory names within this structure are case-sensitive. You may want to double-check
that you have used WEB-INF, and not web-inf or another variation. On Windows, you can
check this from a command prompt.
The first step is to set up separate development and test directories with the same structure.
This helps ensure a stable test environment. Do your JSP authoring and coding in your
development directory. When components are complete, move them to your test
directory. Your development directory can be anywhere. The test directory must be in
tomcat/webapps.
The top level of the web application (in this example, called your_webapp) is the context
root. In files within your web application, a path beginning with a / refers to a file in the
context root and is known as a context-relative path.
JSP and HTML files can be placed anywhere within the context root except in the WEB-INF
directory. They are usually placed at the top level of the web application or in a directory
under the context root. Images, styles, and other resources the JSP and HTML files use are
placed relative to the JSP and HTML files.
The web application also requires a deployment descriptor, a web.xml file that describes the
application’s resources. The DTD for web.xml is described in the Java Servlet 2.3 API
specification. The sample application that comes with this developer guide has a working
web.xml file. You do not need to update the web.xml when you add a JSP file.
To add a JSP file to the sample application, be sure the file has the right JSP directives,
usually placed at the top, something like these:
<!--
<%@ page contentType="text/html" %>
<%@ page errorPage="error.jsp" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
-->
In this example, the JSP directives are placed within HTML comment tags. This way you
can view the page in an ordinary web browser during development, but the servlet
container still interprets them as JSP tags.
Next, copy the JSP page from your development directory and place it in the right location
in the /webapps directory. There is no need to restart Tomcat when you deploy a JSP page.
Task
You want to add a servlet or bean to the sample web application. A servlet is a Java class that
extends javax.servlet.http. A bean is a Java class that stores data for a JSP (a value bean)
or takes some action and returns data to a value bean (a utility bean).
Solution
First, compile the servlet or bean, then place the class file in a directory structure that
matches the servlet or bean package under /WEB-INF/classes. If you add or replace a
servlet, you need to register it in web.xml, copy the updated web.xml to the web
application directory, and shut down and restart Tomcat. If you replace a bean, you need to
shut down and restart, but you don’t need to change web.xml. If you add a bean, you don’t
need to do either.
Discussion
If you add a servlet in the package com.interwoven.cssdk.examples.servlets, you
would need to use this directory structure under WEB-INF/classes:
/com
/interwoven
/cssdk
/examples
/servlets
your_servlet.class
If you are adding a servlet, you also need to add elements to web.xml. The <servlet>
element describes a servlet, names its class, and gives it initialization parameters, and the
<servlet-mapping> entry maps the servlet to a URL so that you can access it directly from
a browser, or a JSP page can link to it.
<servlet>
<servlet-name>Controller</servlet-name>
<servlet-class>
com.interwoven.cssdk.examples.servlets.Controller
</servlet-class>
<init-param>
<param-name>authorPage</param-name>
<param-value>/author_editor_console.jsp</param-value>
</init-param>
<init-param>
<param-name>masterPage</param-name>
<param-value>/master_console.jsp</param-value>
</init-param>
<init-param>
<param-name>errorPage</param-name>
<param-value>/error.jsp</param-value>
</init-param>
</servlet>
.
.
<servlet-mapping>
<servlet-name>Controller</servlet-name>
<url-pattern>/controller</url-pattern>
</servlet-mapping>
57
Getting Started with the Sample Application
After you edit web.xml, make sure the file is well-formed and validates before you add it to
the Tomcat web application directory. If the XML file isn’t valid, Tomcat will throw an
exception, and you won’t be able to use the application correctly.
The error can be as simple as entering a comment tag within a comment in the XML file.
You can validate web.xml with any XML validation tool (there are many good ones on the
market) or with the TeamSite iwxml_validate.ipl command-line tool. Using
iwxml_validate.ipl, you would enter:
iw-home/bin/iwxml_validate.ipl filename
When the files are ready, place the servlet class in WEB-INF/classes and the updated
web.xml in WEB-INF. Because you have updated web.xml, you need to shut down and
restart Tomcat.
After you do this, you should be able to access the servlet by opening a web browser and
going to http://localhost:8080/servlet-url-pattern. On many web servers, you can also
use a URL like http://localhost:8080/servlet/servlet-url-pattern. In most cases, you
wouldn’t access a bean directly from a browser. Instead, a JSP or servlet would use it and
return the data you need.
See Also
“Adding a JSP Page” on page 55 to learn how to add a JSP page to the sample application
Introduction
This guide includes a sample J2EE application (the Ajuba Corporate Intranet) that
demonstrates how to build a remote application that uses ContentServices SOAP.
The sample is a JSP-and-servlet web application with a TeamSite mini-UI. It has a model-
view-controller architecture based on the J2EE Blueprints. The main reason for this design
is to separate presentation from business logic, put more Java code in reusable components,
and keep the amount of Java code in JSP files to a minimum.
This makes the application much easier to maintain, avoiding the ripple effect that occurs
when a change is made in one file. Another benefit is that programmers can write code and
web designers can design presentation. Even better, this architecture makes using a
sophisticated API, like the ContentServices SDK, quite simple at the presentation layer. In
the JSP files, most of the work with ContentServices is done with simple JSP or JSTL tags.
The components in the sample application are JSP pages, servlets, and beans. Beans are
either value beans that hold data and are written according to the JavaBeans design patterns,
or utility beans that retrieve data or take some other action. Used this way, the beans can be
converted to Enterprise JavaBeans in a full J2EE application.
You should become familiar with the application components and what they do. Once you
learn the components, you will easily be able to add your own servlets and beans to build
your own application.
59
Extending the Sample Application
View author_editor_console.jsp
emptyform.jsp
error.jsp
index.jsp
login.jsp
logout.jsp
master_console.jsp
modified_files_view.jsp
noelements.jsp
submit_approved.jsp
submit_denied.jsp
submit_direct.jsp
task_view.jsp
Controller AuthenticationFilter.java
Controller.java
DispatchSubmitDirect.java
ErrorDispatcherServlet.jav
a
FileDownloadServlet.java
GetModifiedFilesServlet.ja
DoSubmitDirectBean.java
Model - Utility Beans
GetWorkareaBean.java
Legend
Task
You want to display a login form that requires users to enter a username, password, and role
to send to the controller servlet. The controller will use these values to authenticate users
on the TeamSite server. A user can enter just about any string for a username or password,
but must choose from a list of defined roles. (In the next section, we’ll explain how to write
an authentication filter to avoid sending null, empty, or unusable login values to the
controller servlet.)
Solution
The solution requires an HTML login form and a filter that checks the user’s login
parameters before passing them to a servlet that performs the authentication. These pieces
are tied together by entries in web.xml.
In this example, the login form is a JSP file that accepts a user name, password, and role.
Each value is required.
The filter implements javax.servlet.Filter from the Java Servlet API. A filter works on
the request before it is sent to a servlet, or the response before it is sent to a browser. In this
case, the request parameters are username, password, and role, and the filter checks for null
values, empty strings, and invalid entries. If the request parameters pass this check, the filter
routes them to the controller servlet for authentication. If not, the filter forwards the
request to a specialized JSP page that displays an explanatory message.
Files
login.jsp
emptyform.jsp
noelements.jsp
AuthenticationFilter.java
web.xml
Discussion
The first step is to build the HTML form. This example shows a skeletal login form
with a text box, password box, select widget, and submit button, all created with
standard HTML tags. The form names the input values username, password, and role.
61
Extending the Sample Application
<tr colspan=2>
<td align="center">
<input name="username" type="text" class="formElements" size="20">
<br>
<b>username</b><p></td>
</tr>
<tr colspan=2>
<td align="center">
<input name="password" type="password" class="formElements"
size="20">
<br>
<b>password</b><p></td>
</tr>
<tr colspan=2>
<td align="center">
<p>
<select name="role" size="3">
<option value="author">Author
<option value="editor">Editor
<option value="master">Master
</select>
<br>
<b>role</b><p></td>
</td>
</tr>
<tr colspan=2>
<td align="center"><p>
<input name="submit" type="submit" value="Login">
</p>
</td>
</tr>
</table>
</form>
The <form> tag routes the form input to the URL /controller using the <c:url> tag:
This mapping sends the form input to the controller servlet. The <c:url> tag is a JSTL core
library action that applies conversion and encoding rules to a URL used in a JSP page.
Because <c:url> comes from the JSTL core library, you must declare it with a JSP
<%@ taglib> directive.
<servlet>
<servlet-name>Controller</servlet-name>
<servlet-class>com.interwoven.cssdk.examples.servlets.Controller
</servlet-class>
<init-param>
<param-name>authorPage</param-name>
<param-value>/author_editor_console.jsp</param-value>
</init-param>
<param-name>masterPage</param-name>
<param-value>/master_console.jsp</param-value>
</init-param>
<init-param>
<param-name>errorPage</param-name>
</init-param>
</servlet>
.
.
<servlet-mapping>
<servlet-name>Controller</servlet-name>
<url-pattern>/controller</url-pattern>
</servlet-mapping>
See Also
The “Overview” chapter to see how a user login is translated to a SOAP request and
response
Task
You want to filter the login values the user enters so that the controller servlet receives only
valid values to use when authenticating users on the TeamSite server. If the controller
servlet receives a null or empty value, it would throw an exception and the sample
application would be temporarily unusable for that user’s session.
63
Extending the Sample Application
Solution
You can write a filter, a Java class that implements javax.servlet.Filter (from the Java
Servlet 2.3 API). A filter processes an HTTP request from the client before it reaches a
servlet, and then processes the response from the servlet before it reaches the client.
The filter should detect null or empty values and route the user to a JSP page that displays an
explanatory message. If the login values are valid, the filter should send them on to the
controller.
Files
AuthenticationFilter.java
noelements.jsp
invalidelements.jsp
web.xml
Discussion
Because the filter implements javax.servlet.Filter, it needs to define init, destroy,
and doFilter methods. init and destroy are standard servlet methods. The web server
creates just one instance of the filter for the web application.
The servlet container calls init after it creates the filter instance and before the filter
handles any requests. The server calls destroy after the filter has been taken out of service
and all pending requests have completed.
The doFilter method is where the filter’s work is done. You can parse request parameters,
log statistics to a file, or do whatever else is needed, before sending the request and
response on to the next item in the chain. The next item is either another filter or a servlet,
as defined in the web.xml file.
The sample authentication filter has initialization parameters defined in web.xml. This way,
the filter has access to the request parameter names, which are defined in login.jsp. It can
use those names to get the request parameter values.
Example 4: Defining Init Parameters for AuthenticationFilter (web.xml)
The filter is shown in Example 5 on page 66. Remember that it does most of its work in the
doFilter method. Specifically, it gets the names of each initialization parameter, gets the
65
Extending the Sample Application
corresponding request parameter value, checks the parameters for null values and empty
strings, and routes the request to the right place.
package com.interwoven.cssdk.examples.servlets;
import javax.servlet.*;
import java.util.Enumeration;
import java.io.IOException;
try {
// or, grab init param names and get the matching form elements
else {
while ( initParams.hasMoreElements() ) {
// get the name of the init param
String name = (String) initParams.nextElement();
return;
}
The HTML form in login.jsp sends values to the controller servlet. To apply the
authentication filter to the controller, so that the filter handles login values before they
reach the controller, you must register the filter and map it in web.xml. Note that the
<init-param> elements define the filter’s initialization parameters.
See Also
“Accepting Login Values from the User” on page 61 to see how to map the <form> tag
to a servlet
67
Extending the Sample Application
Task
You want to have your sample application communicate with the TeamSite server using
ContentServices SOAP.
Solution
The first step is to create a factory object. The sample application communicates with the
TeamSite server using ContentServices SOAP, so this example shows how to create a SOAP
factory.
The first step is to install the ContentServices SOAP server in your TeamSite directory and
the ContentServices SOAP client software in tomcat\webapps\csdemo\WEB-INF\lib.
Once those are installed, this code in the init method of Controller.java reads the
factory type from the file sampleapp.properties.
Files
Controller.java
web.xml
Discussion
Creating the factory object is the first step you need to take in any ContentServices
application. It defines a factory that creates CSClient objects that communicate with the
TeamSite server using the transport of your choice.
When you create a SOAP factory, you make your application a client of the ContentServices
web service. The CSClient object that you create next will retrieve objects from the
TeamSite server using the SOAP transport.
See Also
“Authenticating Users” on page 69 to see how to create a client object
“Creating a Factory Object” on page 25 to see how to create a ContentServices JNI or
generic factory object
Authenticating Users
Task
You want to authenticate users on the server and make sure the username, password, and
role entered define a valid user. If the user is valid, you want to route to an appropriate JSP
page.
Solution
Before you can authenticate users, you need to define valid users (with passwords) on the
TeamSite host and assign those users TeamSite roles. Then, you need to get a factory object,
as described in “Creating a Factory Object” on page 68.
You use the factory object to authenticate the user. If all goes well, and the user is
authenticated, you are returned a CSClient object that allows you to retrieve files,
workareas, branches, editions, and so on for that user from the TeamSite filesystem, using
the transport type assigned to the factory object.
Files
Controller.java
author_editor_console.jsp
master_console.jsp
Discussion
Because the user has entered a username, password, and role in login.jsp, you can
retrieve them from the HTTP request. Each parameter has a name and a value. The names
are username, password, and role (as you saw in Example 2 on page 62). The values are
what the user enters.
You use the login values from the request, and the factory object, to get a client object (an
instance of CSClient) with getClient. A valid client object tells you that the user is
69
Extending the Sample Application
successfully authenticated. The client object also contains a CSContext object, which holds
information about the current user’s locale, application context, and server.
//
// This method returns a CSClient object if
// authentication is successful; otherwise, it throws
// an exception. The CSClient object is the authentication
// token for the ContentServices server and is added to
// the session as part of the CSUser object.
//
try {
client = factory.getClient(username, role,
password, Locale.getDefault(),
"mydemo", null);
} catch (CSException e) {
throw new CSWebAppException( e );
}
System.out.println( "User authenticated and client object obtained" );
Notice that after we get the client object, we store it in the HTTP session. It’s such a useful
object that all components in the web application need to be able to use it.
See Also
“Displaying a List of Modified Files” on page 87 to see how another component retrieves
the client object from the session
“Allowing Users to Log Out” on page 71 to see how to invalidate the client object and
remove it from the HTTP session when a user logs out
Task
You want to allow users to log out of your application. The application needs to handle the
objects that relate to the user’s session, both the TeamSite session and the HTTP session.
Solution
When a user logs out, you need to invalidate the CSClient object that represents the user
on the TeamSite server and remove it from the HTTP session.
You probably want to offer your user a button or link to click for logout. One way to handle
logout is to map the button or link to a servlet.
<tr>
<form action="<c:url value="/logout" />" method="GET">
<td align="left">
<input name="submit" type="submit" class="formElements"
value="Logout"> </td>
</form>
</tr>
71
Extending the Sample Application
The GET request generated when the user clicks the button is sent to the URL /logout,
which is mapped to LogoutServlet in web.xml. The servlet handles the logout in its doGet
method.
CSClient client;
RequestDispatcher rd;
HttpSession session = req.getSession();
Remember that you end the user’s session on two levels. First, use client.endSession()
(from the ContentServices SDK) to invalidate the CSClient object that the TeamSite server
returned when it authenticated the user.
Then, end the HTTP session your web application uses and take whatever steps are
appropriate. Example 10 on page 72 calls session.invalidate() (from the Java Servlet
API) to end the user’s HTTP session and release any objects the application may have stored
in the session (such as the client object; see Example 8 on page 70).
Files
author_editor_console.jsp
master_console.jsp
modified_files_view.jsp
task_view.jsp
logout.jsp
LogoutServlet.jsp
Discussion
Allowing a user to log out is relatively simple. First, understand that the TeamSite server
does not maintain a real user session. The server returns a session string in the CSContext
object that is embedded in the CSClient object, and all calls made from the same CSClient
object represent the same user, but still it is up to the application to maintain the session.
A web application running on a servlet container typically uses one of two techniques for
tracking sessions. The server can return all information related to the current user with each
response and let the browser send it back as part of the next request. Another way is for the
server to save the client’s state somewhere and send back only an identifier with the
response that the client sends back with the next request.
Either way, the application can use cookies, hidden form fields, or URL rewriting to
identify the user’s session. The session string that is stored in the CSContext object (and
available with CSContext.getSessionString) is useful with any of these techniques for
identifying the user.
See Also
“Creating a Factory Object” on page 68 to learn how to authenticate a user and get a
CSClient object
Handling Exceptions
Task
You want to detect any runtime exception from any component in the web application and
display an error page with information about the exception.
Your application can use different ways of handling exceptions. During development, you
want to see the name of the component that threw the exception, the exception message,
and a stack trace. To prepare your application for end users, you want to catch the
exception and route to a JSP page that offers an informative message.
73
Extending the Sample Application
Solution
The ContentServices SDK sample application handles exceptions for developers. That is,
the application components catch and rethrow exceptions, and the
ErrorDispatcherServlet routes the exception information to a common error page.
The web application needs a common error page, and the error page needs to be
declared in web.xml.
All JSP pages need to identify themselves to the error page if an exception occurs.
The web application needs an ErrorDispatcherServlet that ensures the exception is
dispatched to the error page.
Servlets and filters need to catch and rethrow exceptions so that the
ErrorDispatcherServlet can route them to the error page.
You need to define a new runtime exception class as a subclass of CSRuntimeException
that the web application will throw.
Once you take these steps, and the error page is working, you can start to examine the
ContentServices SDK exceptions that are thrown.
Files
ErrorDispatcherServlet.java
error.jsp
author_editor_console.jsp (as an example)
Discussion
First, define the error page (error.jsp) as a JSP page with the errorPage attribute set to
true:
The error page also uses JSTL expressions to display the source page and exception message
and Java code to display the exception’s stack trace.
Second, each JSP page except the error page needs a line that identifies it as the page having
an exception, should an exception occur. This line uses the JSTL <c:set> tag:
<servlet>
<servlet-name>errorDispatcher</servlet-name>
<servlet-class>
com.interwoven.cssdk.examples.servlets.ErrorDispatcherServlet
</servlet-class>
<init-param>
<param-name>errorPage</param-name>
<param-value>/error.jsp</param-value>
</init-param>
</servlet>
.
.
<servlet-mapping>
<servlet-name>errorDispatcher</servlet-name>
<url-pattern>/errorDispatcher</url-pattern>
</servlet-mapping>
.
.
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/errorDispatcher</location>
</error-page>
The error.jsp page can now display the referring page, exception message, and stack
trace, as in Example 12 on page 75.
75
Extending the Sample Application
You can view the error page by creating an exception. For example, log in with the
username and password of an author, but enter the role master. The exception that occurs
is a CSWebAppException, which is a runtime exception that extends CSRuntimeException
and wraps the root cause exception, CSAuthenticationException. A
CSWebAppException is used so that a servlet can throw it in a doGet or doPost method.
The error page looks like Example 13 on page 76 (although the stack trace is truncated
here).
Page or Servlet
The error occurred in /csdemo/controller
Message
The exception message is Role is not authorized for this user
Stack Trace
The stack trace follows:
com.interwoven.cssdk.examples.exceptions.CSWebAppException:
(Role is not authorized for this user) at
com.interwoven.cssdk.examples.servlets.Controller.doPost(Controller.java:
158) at ...
Root cause: com.interwoven.cssdk.access.CSAuthenticationException:
master(Role is not authorized for this user) ...
The stack trace you saw in Example 13 on page 76 comes from code in Controller.java.
try {
client = factory.getClient(username, role,
password, Locale.getDefault(),
"mydemo", null);
} catch (CSException e) {
throw new CSWebAppException( e );
}
The ContentServices SDK has some common exceptions, used in many methods, that you
should know.
See Also
“Authenticating Users” on page 69 to see how to authenticate users and create a client
object
77
Extending the Sample Application
Task
Once a user is authenticated, you want to retrieve the user’s workarea and display it in a JSP
page.
Solution
The solution has several parts:
Authenticate the user (as in “Authenticating Users” on page 69)
Retrieve the workarea, using a bean to define how information about each file and
directory is stored
Display information about each file using JSTL
Use a widget that allows a user to browse the workarea
Files
GetWorkareaBean.java
FileDataBean.java
Controller.java
author_editor_console.jsp
master_console.jsp
Discussion
The main work of retrieving the workarea is done by GetWorkareaBean. GetWorkareaBean
retrieves attributes for each file in the root of the workarea. It does not retrieve the files
themselves; that will happen later with FileDownloadServlet.
FileDataBean defines the attributes retrieved for each file, including name, size, last
modifier, last modification date, vpath, and kind (meaning, file or directory). Because
FileDataBean follows the JavaBeans design pattern, it is easy to use its values with JSTL in
a JSP file.
79
More on the Sample Application
In the sample application, the users you define share a workarea at the vpath /default/
main/WORKAREA/demo, so this vpath is hard-coded in GetWorkareaBean as the workarea
vpath:
// First, get the vpath of the file without the "//server" prefix
CSVPath pathNoServer = file.getVPath().getPathNoServer();
fileDataList.add(new FileDataBean(file.getName(),
fsize,
file.getLastModifier().getName(),
file.getContentModificationDate(),
vpath,
file.getKind()));
}
Remember that the first method call, to getWorkarea, retrieves information about the
files. The first argument to getWorkarea is the hard-coded vpath to the group workarea.
The second argument is false, which tells the ContentServices SDK that if the workarea
does not exist, it should return a shallow workarea object and validate it if it is called by any
other methods.
The second method call is to getFiles. This call retrieves the actual files in the root of the
workarea, but only to check the file sizes. At this point, getFiles does not return any file
content.
81
More on the Sample Application
The JSP file then uses JSTL tags to retrieve the workarea information from the request
scope and display it. The array of files that Controller.java puts in the request scope is
named files, and the current file in the array is named current.
Remember that fileName, size, lastModDate, and lastModifier are properties of files
defined in FileDataBean.
At this point, the workarea data is displayed exactly as it comes from the TeamSite server,
for example:
Research-Chemicals-Canada.doc 122880 Sun Mar 16 19:49:34 PST 2003
INTERWOVEN\jsmith
If you want to convert the file size to kilobytes, use a different date format, or display the
user name without a domain, you need to manipulate the returned data, perhaps in
FileDataBean.
See Also
“Creating a Factory Object” on page 68 to learn how to authenticate users
“Downloading a File” on page 82 to see how FileDownloadServlet (called by the
/download URL) works
Downloading a File
Task
You want to allow users to click a file name in a JSP page and download a file using a Save As
dialog box from the TeamSite filesystem to a local directory or hard disk.
Solution
Downloading a file with a Save As dialog box is a good job for a servlet. The key is in how
the servlet sets response headers. The servlet also needs a method that retrieves the file’s
content from the TeamSite server.
Files
FileDownloadServlet.java
author_editor_console.jsp
master_console.jsp
Discussion
Downloading a file to a local area is a simple way to allow users to edit files before
submitting the edited version. FileDownloadServlet retrieves the file content from the
TeamSite filesystem, using an unusual response header. The browser typically won’t
recognize the response header, so it throws a Save As dialog box appropriate to the
windowing system used by the client (user’s) computer.
83
More on the Sample Application
The <c:url> tag links the file name to FileDownloadServlet. The <c:param> tags send
the servlet request parameters named path, containing the file’s vpath, and fName,
containing the file name. The filename is linked with an <a href> tag. The value of <a
href> is the JSTL tag <c:url>, which calls a servlet mapped in web.xml to /download. The
servlet allows a user to click a link and download a file from TeamSite 6 to a local directory
or hard disk. The example shows two values being passed to the servlet in the <c:param>
tags, the file’s vpath and name.
Using URLs and URIs in JSP files can be tricky. To link to a file stored in the TeamSite
filesystem safely:
Remember that in a JSP file, a URI that starts with a / is always interpreted by the servlet
container as relative to the context root, the directory in tomcat/webapps where your web
application resides. This can be confusing when you want to refer to a vpath in the TeamSite
file system, such as /default/main.
Once the servlet gets the client object from the session, it can easily retrieve the values of
path and fName from the request. This is why we use a servlet for this job, because it works
so naturally.
We will give the first parameter, path, to the TeamSite server to locate the file. When you
retrieve it from the request, it’s a String, but you can easily convert it to a CSVPath object
with the CSVPath constructor.
The second parameter, fname, appears in the Save As dialog box to show the user which file
she is downloading. The setContentType and setHeader methods use a content type and
response header that are defined in the HTTP specification but unusual to browsers.
85
More on the Sample Application
Now for the returnFile method, which does the work of getting the file from the
TeamSite server so that the servlet can return it to the browser in the response.
InputStream in = null;
try {
// use the csvpath to get the corresponding file
CSSimpleFile f = (CSSimpleFile) client.getFile( vpath );
// do the buffering
byte[] buf = new byte[4 * 1024]; // 4K buffer
int bytesRead;
while ((bytesRead = in.read(buf)) != -1) {
out.write(buf, 0, bytesRead);
}
// catch any exceptions
} catch (CSException e) {
throw new CSWebAppException(e);
} // and clean up
finally {
if (in != null) in.close();
}
}
Once you have the CSVPath object (as you saw in Example 19 on page 85), you can retrieve
the file content with getFile. Use the returned file to get an input stream, specifying a
return value of true to make it thread safe (remember—servlets are multithreaded, so you
must always write them to be thread safe).
From that point, buffer the file content, write it to an output stream, handle exceptions—
and you’re done. The file is sent to the browser, and the browser returns it in the Save As
dialog box so the user can download it.
See Also
“Handling Exceptions” on page 73 to understand how to handle exceptions thrown by
the ContentServices SDK
Task
After a user downloads files, modifies them, and copies the modified versions to the
workarea, you want to display a list of modified files. The user will select from the modified
files list to build a submit files list.
Solution
In the Author/Editor console, the user clicks the Modified Files link to move to the
Modified Files page. Because clicking a link sends an HTTP request, it is easy to use a servlet
to handle the request and return the list of modified files in the response. The
CSWorkarea.getModifiedFiles method returns the modified files, with several options.
Files
author_editor_console.jsp
modified_files_view.jsp
GetModifiedFilesServlet.java
Discussion
Once a user copies a modified file to the workarea, the ContentServices SDK detects it as
modified but not yet submitted. GetModifiedFilesServlet is similar to
FileDownloadServlet, in that it has a doGet method that handles the request and returns a
response, and another method that retrieves the modified files.
The modified file data returned is file attributes, just like the workarea data. Because the
sample application is designed with reusable components, GetModifiedFilesServlet
retrieves the modified file data and returns it as an array of FileDataBean objects. Then, it
is easy to display them in the JSP page, because you learned how to display FileDataBean
properties when you displayed the user’s workarea.
The first step is to add the servlet to the Modified Files link in
author_editor_console.jsp:
Again, we use the <c:url> tag so that the URL defined in web.xml is converted from a
context-relative path to a server-relative path.
87
More on the Sample Application
When the user clicks the link, GetModifiedFilesServlet receives the GET request and
displays modified_files_view.jsp.
Then, the servlet’s doGet method handles the request. As usual, the first thing the servlet
does is get the client object that refers to the current user from the HTTP session.
RequestDispatcher rd = null;
HttpSession session = req.getSession();
// call getModifiedFiles
// pass it the client object
try {
modifiedFiles = getModifiedFiles( client );
} catch (CSException e ) {
System.out.println( "A CSException occurred" );
}
The servlet passes the client object to the getModifiedFiles method, then stores the
modified files in a request attribute to be returned with the response. Now for the
getModifiedFiles method, where we can see the real ContentServices SDK work.
this.client = client;
// Get all the modified files in the root of the workarea (no
// recursion, marked by the CS_EXPAND_NONE arg) no matter who
// is the modifier of the files (as indicated by the 'false' arg).
// For now, we will take just the files in the root of the workarea
// because we don't yet have a widget to display browsable folders
// in the JSP page.
Here again, you can see the power and simplicity of the ContentServices SDK. One call to
getWorkarea gets files attributes for the root directory of the user’s workarea (in this case,
the group workarea named demo). Then, one call to getModifiedFiles returns the
modified files.
You can use several variations of getModifiedFiles. This example returns only the
modified files in the root of the workarea (again, because the sample application doesn’t
have a browseable directory widget yet). If you want to return more files, just specify
CSArea.CS_EXPAND_DEFAULT or CSArea.CS_EXPAND_NONE.
89
More on the Sample Application
The last part of this task is for the JSP page to display the modified files, retrieving them
from the request. In this page, all you need to display is the file name.
<!-- the c:out tag adds the vpath as a string to the request -->
<!-- we are building an array of vpaths named submitFiles -->
<!-- each vpath starts with /default -->
</td>
<td> <img src="images/fiicon.gif"> </td>
<td> <c:out value="${current.fileName}" /> </td>
<td>
</tr>
</c:forEach>
Once again, the <c:forEach> tag is very useful. The array of modified files is named
modifiedFiles (remember Example 22 on page 88) in the request scope, so the JSTL
expression that retrieves it is ${requestScope.modifiedFiles}. To display the file name,
use <c:out>. The <c:url> tag used as a parameter to the <input> tag sends the file’s vpath
to the next servlet when the user checks that file’s box and clicks Submit.
See Also
“Retrieving a User’s Workarea” on page 79 to see how to display the files in the root of
the workarea, especially how to use JSTL tags to work with properties of the files
array
Task
You want to allow master users to submit modified files directly to staging, without
workflow approval. Authors and editors are not allowed to submit direct, however. If you
log in as an author or editor in the sample application and try to do this, you will see an
exception.
Solution
This solution involves two JSP pages, a servlet, a value bean, and a utility bean. In
modified_files_view.jsp, a user can select any number of modified files to submit to
staging. The selected list is sent to DispatchSubmitDirectServlet, which calls
DoSubmitDirectBean to do the work of submitting the files to staging. The submit results
are stored as SubmitResultBean objects, which submit_direct.jsp can easily access with
JSTL tags.
Files
modified_files_view.jsp
DispatchSubmitDirectServlet.java
DoSubmitDirectBean.java
SubmitResultBean.java
submit_direct.jsp
Discussion
Most of the work of the direct submit is done on DoSubmitDirectBean. Submitting files
directly to staging from a workarea is relatively easy. However, it requires an array of
CSPathCommentPair objects, each with an area relative path and a comment. Remember
that the area relative path is the part of the vpath after the WORKAREA, STAGING, or
EDITION placeholder:
vpath /default/main/WORKAREA/demo/Report-Cosmetics-Canada.doc
area relative path demo/Report-Cosmetics-Canada.doc
The files the user selects in modified_files_view.jsp are sent as a String array to
DispatchSubmitDirectServlet, which sends them on to DoSubmitDirectBean.
DoSubmitDirectBean performs a series of conversions, converting the String array to a
CSVPath array, then to a CSAreaRelativePath array, then a CSPathCommentPair array.
91
More on the Sample Application
Once you have the CSPathCommentPair array, you can do the direct submit. With a direct
submit, the method defines whether to overwrite files in staging with versions in the
workarea. All files included in the direct submit are handled the same way.
The result of a direct submit is a CSSubmitResult, from which you can get a CSPathStatus
array or a CSSubmitRecord. Each data type has different information.
CSSubmitResult
CSPathStatus CSSubmitRecord
CSAreaRelativePath comment
primaryStatusCode infoComment
secondaryStatusCode CSEdition
statusMessage
Figure 5: Content of a CSSubmitResul
For the sample application, we are interested in the area relative path and the status
message. These are contained in the CSPathStatus array. We will store them in a
SubmitResultBean, along with the primary and secondary status codes. (Because a
SubmitResultBean is written according to the JavaBeans design patterns, its values can be
easily used in a JSP page with JSTL tags).
.
.
// get the submit status for each path
// each status[i] has a vpath, primary code, secondary code, and message
CSPathStatus[] status = result.getResultOfSubmit();
return submitData;
}
Once the files are submitted, DispatchSubmitDirect stores the submit data in the
response and forwards it to submit_direct.jsp. You can then retrieve the submit data and
display it with JSTL tags.
93
More on the Sample Application
Introduction
A WSDL file describes how to access and use a web service, creating an interface between a
web service and its client. WSDL files are written in XML according to the WSDL
specification, with six primary XML elements:
They define how method calls made in Java or any other language are translated before
they are packaged into the SOAP envelopes sent to and from the ContentServices web
service.
They are used in development tools to generate web service client stubs in various
languages such as C#, VB.Net, or Perl. Any client can instantiate the stub to call the
web service.
They are used in WSDL invocation tools to automatically invoke a web service using a
command or short script.
95
Working with WSDL Files
WSDL
Client
Stub
Client Application
The ContentServices SDK has six WSDL files, structured according to the packages in the
Java client interface. Each WSDL has a URL specified in its <service> element. The URL
locates the WSDL in order to generate the client stub or invoke the web service.
Note: If you changed the HTTP port from 80 to another port number when you installed
the TeamSite server, use your HTTP port number in the URL.
Table 1: The ContentServices SDK WSDL Files
Name Location
AccessService.wsdl http://tsServer:80/iw/services/cm/2.0/
accessservice
contentservices.wsdl http://tsServer:80/iw/services/cm/2.0/
contentservices/ContentServices.wsdl
FileSys.wsdl http://tsServer:80/iw/services/cm/2.0/fileservice
Types.wsdl no URL
Util.wsdl http://tsServer:80/iw/services/cm/2.0/utilservice
Workflow.wsdl http://tsServer:80/iw/services/cm/2.0/
workflowservice
The file contentservices.wsdl is the base WSDL file that describes the entire
functionality of the ContentServices SDK. You can point tools to its URL to create stubs
(see “Generating and Using a C# Client Stub” on page 98 for details). The other WSDL files
describe services that are part of the ContentServices SDK.
In a WSDL file, the <wsdl:portType> element describes the web service as a whole and is
similar to a class. The <wsdl:message> element specifies the requests the web service
receives and the responses it sends back.
Suppose your application accepts login information to authenticate a user on the TeamSite
server. Your application would call the getClient method in CSFactory or one of its
subclasses.
CSInvalidRoleException,
<wsdl:portType name="AccessService">
...
<wsdl:operation name="beginSessionUsingPassword"
parameterOrder="userName roleName password locale appContext
serverName">
<wsdl:documentation>
Begin a CSSDK session using the specified credentials.
</wsdl:documentation>
<wsdl:input message="impl:beginSessionUsingPasswordRequest"/>
<wsdl:output message="impl:beginSessionUsingPasswordResponse"/>
<wsdl:fault message="impl:CSException" name="CSException"/>
</wsdl:operation>
...
</wsdl:portType>
The <operation> element defines an input message, an output message, and what happens
if an exception is thrown. Note that the parameter order is the same as in the method
declaration for getClient.
97
Working with WSDL Files
The <wsdl:message> element, earlier in the WSDL file, describes each parameter sent to
beginSessionUsingPassword (remember—it’s the WSDL equivalent of getClient).
<wsdl:message name="beginSessionUsingPasswordRequest">
<wsdl:documentation>
Begin a CSSDK session using the specified credentials.
</wsdl:documentation>
Task
You want to write a C# program to do something with the ContentServices SDK, say,
retrieve the branches in a store.
Solution
You first need to generate a C# client stub from the ContentServices SDK and then write a
short C# program to run against it. The examples used in this section are in
samples\dotnet.
Discussion
This requires installing the Microsoft .NET framework SDK and a C# compiler. The C#
compiler is named csc.exe and is bundled with the .NET SDK. However, on Windows,
csc.exe might be stored in a location outside the main .NET SDK.
Before you generate the client stub, install TeamSite 6 and the ContentServices SDK
according to the instructions in quick_install_dotnet.html in the samples zip file.
Now you are ready to generate a C# client stub for the ContentServices SDK. Use the wsdl
command that is included with the .NET framework on ContentServices.wsdl, the main
WSDL file that imports the other WSDL files. For convenience, this command is part of a
makefile in the samples, make.cmd.
You may need to edit the port number in make.cmd so that the command can locate the
WSDL file, for example:
Running this command generates cssdk.cs, the C# client stub. The next step is to compile
GetBranches.cs, the sample C# source file. The command to do this, also in make.cmd,
is:
99
Working with WSDL Files
Status Codes
This appendix contains status codes returned by the ContentServices SDK and TeamSite
Content Server. These are the codes returned by CSException.getErrorCode.
In general, an error code of 0 means Success, and all other codes indicate some type of
exception.
101
Status Codes
0 = Success
1 = Generic failure
2 = No such file or directory
3 = No such process
4 = Interrupted system call
5 = I/O error
6 = No such device or address
7 = Arg list too long
8 = Exec format error
9 = Bad file number
10 = No children
11 = Resource temporarily unavailable
12 = Not enough core memory
13 = Permission denied
17 = Workarea, edition or branch already exists
20 = Directory expected, but wasn't one
21 = Directory not expected, but is a directory
22 = Invalid argument
28 = Insufficient space to complete operation
30 = Read-only file system
41 = Link number out of range
42 = Protocol driver not attached
43 = No CSI structure available
44 = Level 2 halted
45 = Resource deadlock condition
46 = No record locks available.
47 = Operation canceled
48 = Operation not supported
71 = Protocol error
132 = No buffers available
151 = Stale file handle
301 = Not super-user
480 = Authentication error
691 = Version number mismatch
905 = Function not yet implemented
910 = Buffer is too small for output
911 = String argument is too long
920 = Object being looked up was not found
921 = Task not done
925 = No such user
930 = RPC connection failure
980 = No authentication was done
981 = No authorization was done
999 = "No" is the response
2000 = Iteration ended
2001 = No iteration entry
2003 = No base edition for workarea create
2004 = No server found
2005 = No archive found
2006 = No branch found
2007 = No workarea found
2008 = No edition found
2009 = No fse found
2010 = No previous fse found
2011 = Workarea directory not found
103
Status Codes
You can use this document as a starting point to map ContentServices SDK 1.1 methods to
ContentServices SDK 2.5.
Because the new ContentServices SDK has been rearchitected from the ground up, some of
the old methods might not have direct equivalents. Instead, you might need to use a
combination of several methods in the new SDK.
There are six packages in the new Java client interface: access, common, factory,
filesys, util, and workflow. Please see the Javadoc for complete method signatures.
addTaskComment workflow.CSTask.addComment
addTaskFileComment workflow.CSTask.addFileComment
addTaskFiles workflow.CSTask.attachFiles
createWorkflow workflow.CSWorkflowEngine.createWorkflow
deleteFiles filesys.CSWorkarea.deleteFiles
editFile util.CSUrlsHelper.getFileUrls
endSession common.CSClient.endSession
finishTask workflow.CSTransitionableTask.chooseTransition
getCredentials common.CSClient.getContext
107
Mapping ContentServices 1.1 to 2.5
For searching:
filesys.CSSimpleFile.getExtendedAttributeNames
getFile common.CSClient.getFile
getFiles filesys.CSArea.getFiles(
CSAreaRelativePath[] filePaths)
getModifiedFiles filesys.CSWorkarea.getModifiedFiles
filesys.CSDir.getModifiedFiles
getTaskById workflow.CSWorkflowEngine.getTask
common.CSClient.getTask
getTasksById workflow.CSWorkflowEngine.getTasks
getTasks workflow.CSWorkflowEngine.getTasksByQuery
getTemplateCategories util.CSTemplating.getTemplateCategories
getWebDeskNewDcrHelper util.CSTemplating.getWebDeskNewDcrHelper
importFiles util.CSUrlsHelper.getImportFilesUrl
isLoggedIn common.CSClient.isValid
ping factory.CSFactory.getServerVersion
Not an exact comparison, but serves the same purpose.
getServerVersion does not require any authorization or
authentication.
readFile filesys.CSSimpleFile.read
filesys.CSSimpleFile.getInputStream
removeTaskFiles workflow.CSTask.detachFiles
submit util.CSUrlsHelper.getSubmitFilesUrl
submitDirect filesys.CSWorkarea.submitDirect
undoChanges filesys.CSWorkarea.update
unlockFiles filesys.CSWorkarea.unlockFiles
update filesys.CSWorkarea.update
uploadFiles util.CSUrlsHelper.getUploadFilesUrl
writeFile filesys.CSSimpleFile.write,
filesys.CSSimpleFile.getOutputStream
109
Mapping ContentServices 1.1 to 2.5