Web services today are an evolutionary step in designing distributed applications. Web services are the building blocks for creating open distributed systems. These allow organizations and individuals to develop open standard applications that can be used globally by development houses. One early example is .NET Passport (see http://www.passport.com/Consumer/DotNETBranding.asp?lc=1033), a convenient authentication service hosted by Microsoft.
The Lightweight Directory Access Protocol (LDAP) helps companies arrange directory information in a hierarchy. With LDAP, a "directory" refers to an existing collection of information, similar to a "Yellow Pages." It can be explained as a database, which uses a hierarchical structure to store information. It offers performance advantages over conventional databases, and its operations are familiar to database users. For example, it can be used to create employee search pages to easily locate people/resources and information about them.
This is the first of two articles on the use of Web services with an LDAP server. In this article we will create a ColdFusion Web service using Macromedia, Inc.'s ColdFusion Components (CFCs) that will access an LDAP server to retrieve search results. We will deploy the Web service using the ColdFusion MX (CFMX) Administrator, which will be accessed by our sample application.
In this article we will consume this Web service via a Web client written in CFMX. In the next article, we will consume this Web service written in ColdFusion MX through mobile devices, e.g., handheld devices like Compaq's iPAQ or a Personal Digital Assistant (PDA), WAP (Wireless Application Protocol) phones, etc. The client in the next article for Web services will be written in ASP.NET and VB.NET using the Microsoft Mobile Internet Toolkit (MMIT) (see http://msdn.microsoft.com/vstudio/device/mitdefault.asp).
What Are Web Services?
Web services are enterprise applications that transfer and exchange data, automate processes, and share tasks over the Internet. They help organizations overcome the barriers of remote cross-platform interoperability. Web services offer organizations a way to use the Internet as an arena for business collaboration, where services can be consumed and integrated within and across groups.. Web services are a class of Internet-based applications that increase interoperability and lower the costs of data sharing and application integration. Web services are based on open standards like Extensible Markup Language (XML), the Simple Object Access Protocol (SOAP), and the HyperText Transfer Protocol (HTTP) that enable applications to communicate with one another and exchange data regardless of location, operating system, or language.
Web Services: Further Explanation
A service is an application that can be accessed through a programmable interface. Users can access these services using a closely coupled distributed computing protocol, such as Distributed Component Object Model (DCOM) (formerly Network OLE), Common Object Request Broker Architecture (CORBA), or Remote Method Invocation (RMI). These protocols are very effective for building a specific application. They limit the flexibility of the system. The tight coupling used in these architectures limits the reusability of individual services. Each of the protocols is inhibited by dependencies on vendor implementations, platforms, or languages that severely limit interoperability. Also note that none of these protocols operate effectively over the Web.
The main advantage of Web services is that they are based on established industry standards. The services are described in XML and are communicated over an existing HTTP infrastructure. Web services primarily use HTTP and SOAP to make data available that Web applications can use to connect to each other over the Internet. Web Services expose business objects (such as COM objects, Java Beans, etc.) to SOAP calls over HTTP that enable them to execute remote function calls. The Web Service clients can then invoke method calls on remote objects by using SOAP and HTTP over the Web. These are exposed and discovered using standards like Universal Description, Discovery, and Integration (UDDI) and DISCO (abbreviation of Discovery).
The Internet supports universal communication using loosely coupled connections. Web protocols are completely vendor-, platform-, and language-independent. The resulting effect is an architecture that eliminates the usual constraints of DCOM, CORBA, or RMI. Web services support Web-based access, easy integration, and service reusability.
The following diagram displays how remote function calls using SOAP over HTTP are used to invoke methods on a Web service at Location B. The structure of the Web service components is exposed using Web Services Description Language (WSDL). WSDL is an XML document describing the attributes and interfaces of the Web service. The output is rendered as XML and passed back to the user at Location A.
Figure 1
Web services also can be written and called in most any language: VC++, C#, VB, Java and ColdFusion MX. This article uses ColdFusion MX to write and invoke its Query LDAP Web service.
LDAP: An Introduction
LDAP is a protocol for accessing existing on-line directory services. It runs directly over TCP and can be used to access a standalone LDAP directory service or to access a directory service that is back-ended by X.500. A directory is like a database, but tends to contain more descriptive, attribute-based information. The information in a directory is generally read much more often than it is written. As a consequence, directories don't usually implement the complicated transaction or rollback schemes regular databases use for doing high-volume complex updates. Directory updates are typically simple all-or-nothing changes, if they are allowed at all. Directories are tuned to give quick-response to high-volume lookup or search operations.
What kind of information is stored in a directory? The LDAP directory service model is based on entries. An entry is a collection of attributes that has a name, called a distinguished name (DN). The DN is used to refer to the entry uniquely, like a Primary Key in a database. Each of the entry's attributes has a type and one or more values. The types are typically like "sn" for last name, "mail" for email address, or "telephonenumber" for telephone numbers.
In an LDAP, directory entries are arranged in a hierarchical tree-like structure that reflects geographic and/or organizational boundaries. Entries representing countries appear at the top of the tree. Below them are entries representing states or national organizations. Below them might be entries representing people, organizational units, printers, documents, or anything else. Figure 2 shows an example LDAP directory tree.
In addition, LDAP allows you to control which attributes are required and allowed in an entry through the use of a special attribute called objectclass. The values of the objectclass attribute determine the schema rules the entry must obey.
Figure 2: An Example LDAP Directory Tree.
An entry in LDAP is referenced by its distinguished name, which is constructed by taking the name of the entry itself (called the relative distinguished name, or RDN) and concatenating the names of its ancestor entries. For example, the entry for Puneet Kukreja in the example above has an RDN of "cn=Puneet Kukreja" and a DN of "cn=Puneet Kukreja, o=Monash University, c=AU". The full DN format is described in RFC 1779, "A String Representation of Distinguished Names" (see http://www.ietf.org/rfc/rfc1779.txt?number=1779).
The Build Process
Having gained an introductory background, we will start the process of building the Web service using the new ColdFusion MX technology and good old Web forms.
All of us are familiar with search because it is performed on every major Web site today and is an essential part of any corporate intranet. The input parameters from our search page will be submitted to the Web service that will run the search against an LDAP server.
Tools to Create a Web Service
The tools that will be used to build this Web service are:
Any text editor or HTML rendering tool to write our Web form
Macromedia, Inc.'s ColdFusion MX Server (Beta Edition) to host the Web service
Macromedia Dreamweaver MX Studio (Beta Edition) to write the Web service and the Web service client
Designing the Application
The Web form will submit the search request to the Web service, which will in turn contact the LDAP server to retrieve the search results. When we start to build this application, we will see how Web Services and ColdFusion Components fit together.
ColdFusion Web Service
Look at some sample code before we write our actual Web service in order to understand the basics.
<!--- Name of the Component - - ->
<cfcomponent name="ComponentName">
<!--- Name of the Function - - ->
<cffunction name="FunctionName" access="remote" returntype="any">
<!--- Definition of the arguments that will be returned - - ->
<cfargument name="ArgumentName" type="string" required="true">
<!--- Setting a variable to return the result to the client - - ->
<cfset returnResult="Result">
<!--- Using cfreturn to actually return the result back to the client- - ->
<cfreturn returnResult >
<!--- Closing the function tag - - ->
</cffunction>
<!--- Closing the Component tag- - ->
</cfcomponent>
The cfcomponent tag indicates the CFC, much like the HTML tag indicates the beginning and end of an HTML page.
The cffunction tag indicates the functionality of the component. There can be multiple cffunction tags in a single component. When we invoke the CFC from our ColdFusion page, any one of the functions can be called. This is especially useful if there are sets of related functionality that we want to move to a separate file for maintainability of code.
The cffunction tag has five attributes. Dreamweaver MX inserts three attributes as a default:
Name - The name of the function needs to be unique in the CFC page so that it can be called from the function individually.
Access - This determines who can access the component method by client type. If we leave the access set to public, then any other CFML page on the ColdFusion server will be able to access the CFC. If we change the access to remote, then that enables the CFC to be called as a Web service.
Returntype - This attribute gives data type validation for returned values.
Client to Consume the Web Service
Once we have written the CFC it is very easy to call it.
For this article we will call it from a ColdFusion page; in the next article we will call this Web service from a .NET client. In the ColdFusion page where you want to call the CFC, use the cfinvoke tag. In the cfinvoke tag, we can call individual functions inside of the CFC and specify the name of the return variables that are returned from the CFC.
Here is a skeleton code for invoking the Web service. We will write a complete Web service and invoke it in Part 2. This is just to make us aware of what is happening and how the return code is structured.
<!--- Using CFInvoke to call the component/Web service to return the results - - ->
<cfinvoke
component="ComponentName" <!--- Component Name defined earlier - - ->
method="FunctionName" <!--- Function Name defined earlier - - ->
returnvariable="returnResult" <!--- Return variable defined earlier - - ->
>
<!--- Calling the arguments defined earlier in the CFComponent - - ->
<cfinvokeargument name="ArgumentName " value="ArgumentValue"/>
<!--- Closing the CFInvoke tag - - ->
</cfinvoke>
<!--- Outputting the result from the component/Web service to the client - - ->
<cfoutput># returnResult#</cfoutput>
This explains the basics of building a Web service in ColdFusion and also the client to consume it.
An Explanation of CFLDAP
The CFLDAP tag in ColdFusion helps to query the LDAP server.
SERVER - Required. Host name ("ldap.server.name") or IP address ("111.111.000.000") of the LDAP server.
PORT - Optional. Port defaults to the standard LDAP port, 389.
USERNAME - Optional. If no username is specified, the LDAP connection will be anonymous.
PASSWORD - Optional. Password corresponds to username.
ACTION - Optional. Specifies the LDAP action. There are five possible values:
Query -- (Default) Returns LDAP entry information only. Requires NAME, START, and ATTRIBUTES attributes.
Add -- Adds LDAP entries to the LDAP server. Requires ATTRIBUTES.
Modify -- Modifies LDAP entries on an LDAP server with the exception of the distinguished name ("DN") attribute. Requires DN, ATTRIBUTES.
ModifyDN -- Modifies the distinguished name attribute for LDAP entries on an LDAP server. Requires DN, ATTRIBUTES.
Delete -- Deletes LDAP entries on an LDAP server. Requires DN.
NAME - Required for ACTION="Query". The name you assign to the LDAP query.
TIMEOUT - Optional. Specifies the maximum amount of time in seconds to wait for LDAP processing. Defaults to 60 seconds.
MAXROWS - Optional. Specifies the maximum number of entries for LDAP queries.
START - Required for ACTION="Query". Specifies the distinguished name of the entry to be used to start the search.
SCOPE - Optional. Specifies the scope of the search from the entry specified in the START attribute for ACTION="Query". There are three possible values:
OneLevel -- (Default) Searches all entries one level beneath the entry specified in the START attribute.
Base -- Searches only the entry specified in the START attribute.
Subtree -- Searches the entry specified in the START attribute as well all entries at all levels beneath it.
ATTRIBUTES - Required for ACTION="Query", Add, ModifyDN, and Modify. For queries, specifies the comma-separated list of attributes to be returned for queries. Can also be used to specify the list of update columns for ACTION="Add" or "Modify". When used with ACTION="Add" and Action="Modify", separate multiple attributes with a semicolon. When used with ACTION="ModifyDN", ColdFusion passes attributes to the LDAP server without performing any syntax checking.
FILTER - Optional. Specifies the search criteria for ACTION="Query". Attributes are referenced in the form: "(attribute operator value)". Example: "(sn=Kukreja)". Default is "objectclass=*".
SORT - Optional. Specifies the attribute to sort query results by. Enter Asc for an ascending sort and Desc for a descending sort.
DN - Required for ACTION="Add", Modify, ModifyDN, and Delete. Specifies the distinguished name for update actions. Example: "cn=Puneet Kukreja, o=Monash University, c=AU".
Building the Application
1. The Search Page
The search page is a standard Web form, and can be written in HTML, or ColdFusion, or any other Web programming language.
Snapshot:
The code:
<!--- HTML Starts Here --->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>LDAP CFC</title>
</head>
<body>
<h2>LDAP Search using a ColdFusion Web Service</h2>
<form name="SearchDetails" method="post" action="ldapsearch2.cfm">
<table width="385">
<tr>
<td colspan="2">
<p><br>
<b>Please enter first name or last name to search</b></p>
<p> </p>
</td>
</tr>
<tr valign="top">
<td width="127"> <b>Search Name</b></td>
<td width="246">
<input name="cfcName" type="Text" id="cfcName" tabindex="1" maxlength="50">
</td>
</tr>
<tr valign="top">
<td width="127">
<input tabindex="2" type="Submit" name="Search" value=" << Search >>">
</td>
</tr>
</table>
</form>
</body>
</html>
This form will submit to ldapsearch2.cfm, which will invoke the Web service.
2. The Results Page
We use this page to invoke the Web service and display the results that have been retrieved.
<!--- cfparam is used specify default values for parameters and specify
parameters that are required. It requires a variable name passed to it.--->
<cfparam name="form.cfcName" default="">
<!--- As explained before, we use the cfinvoke tag to define the
method/function that will be retrieved from the CFComponent/Web service. An
interesting point to note here is that instead of using Component, as we did in
the skeleton code, we use webservice and define the location of the Web service.
In this case the URL of the Web Service from the local CF server. That is
returning the returnVariable "GetPerson".--->
<cfinvoke
method="SearchPerson"
webservice="http://localhost:8500/TestDev/ldapconnect_queryreturn.cfc?wsdl"
returnVariable="GetPerson"
>
<!--- We will define what argument needs to be invoked from the Web
service. In this case it is called cfcName, which is the field name of the
search field. This is the argument name that is being returned from the Web
service as we will see in the next step.--->
<cfinvokeargument name="cfcName" value="#cfcName#">
<!--- We close the cfinvoke tag.--->
</cfinvoke>
Following that is a simple HTML form code that has the following lines in it that need an explanation.
<!---We use cfdump to get the results from the Web service, and we use the
variable defined as var that will hold the value of the results returned using
the ColdFusion function recordcount. GetPerson in this case is the
returnVariable explained earlier, and it also has been defined in the cfinvoke
tag. --- >
Your search returned <cfdump var="#GetPerson.recordcount#"> results</b>
<!--- We use cfdump again to finally retrieve the results that give us the
results screen.--->
<cfdump var="#GetPerson#">
Having discussed the mechanism of submitting the results, getting the results back, and displaying them allows us to discuss the much-awaited Web service that helps us do all of the above. The service actually contains all the business logic of the application.
3. The Web Service
The Web service has been written in ColdFusion, and with the new CFMX we can expose any CF Component as a Web service by defining two parameters:
In the cffunction tag, define access="remote" and
Then to view its Web Services Description Language (WSDL) in the browser window, just add ?wsdl to the CFC code as follows for our application.
http://localhost:8500/TestDev/ldapconnect_queryreturn.cfc?wsdl
The page that has the component/Web service code is called ldapconnect_queryreturn.cfc. If we append it with ?wsdl, it will give us the WSDL for the Web service which is displayed as follows.
<!---The cfcomponent is new to CFMX. It is used to define the name of the
component, as is displayname. The hint is used in the self-documentation that is
generated by ColdFusion Studio MX for the component. --->
<cfcomponent displayName="LDAPComponent" hint="Component used to access LDAP">
If in the browser window we enter the name of the page that is the Web service. In this case it's http://localhost:8500/TestDev/ldapconnect_queryreturn.cfc . Then we will see the following documentation for the Component/Web service that has been generated by the ColdFusion Administrator.
This has the name of the method that can be called on the Web service, which in our case is SearchPerson.
It gives the path of the Web service and also the return string -- cfcName.
<!--- The next tag, cffunction, defines the name of the function/method
that is documented above. We define access = "remote" which enables this
function to be called as a Web service. The output is set to 0 because we do not
want the function to output the results. The return type is set to query so the
calling page understands that it is returning a query result. --->
<cffunction name="SearchPerson" access="remote" output="0" returntype="query">
<!---cfargument is the argument that will be passed from the calling page to the component and then returned back to the results page.--->
<cfargument name="cfcName" type="string" required="false"/>
<!---The cfldap tag is used to make all the magic happen. We define an
action that is a query and give the tag a name that will help us to return the
results that are obtained. We define the attributes that are to be returned in
the query. The start parameter is defined to start the search that will be
basically starting from your organization root. The scope is defined as subtree
so that the query searches in all the subtrees of the LDAP structure tree. The
filter is set to cn, a filter that will search for a common name like the one
passed in the search criteria through #cfcName#. The * enables a wild-card
search in the cn parameter. Finally we define our server on which the search is
to be performed.--->
<cfldap
action="QUERY"
name="GetPerson"
attributes="cn,telephonenumber,mail"
start="o=Your Organisation, c=Your Country"
scope="subtree"
filter="cn=*#cfcName#*"
server="yourcompany.ldap.server">
<!---We use cfreturn with the name of the query GetPerson to send the
results back to the search result page that uses the cfdump tag to display the
results.--->
<cfreturn GetPerson>
<!---Closes the cffunction tag.--->
</cffunction>
<!---Closes the cfcomponent tag.--->
</cfcomponent>
There is something we must do in order to use this application. The Web service must be registered on our local CFMX Administrator by doing the following:
Log in to CFMX Administrator.
Choose the Web Services option under Data and Services that will give you a screen as follows:
Enter the name of the Web service. I have used "Using LDAP Web Service." The WSDL URL, again, is
http://localhost:8500/TestDev/ldapconnect_queryreturn.cfc?wsdl.
Click the Add Web Services button and the Web service will be added, and we are ready to test it.
We have written a ColdFusion Web service that queries an LDAP server. In the next article we will use a .NET mobile client to invoke this Web service.
About the Author
Puneet Kukreja is a Webmaster/DBA with the IT Faculty at Monash University Melbourne, where he is also studying for a Research Masters. Puneet has been researching Web services and mobile portals for almost a year. He may be reached at puneet.kukreja@infotech.monash.edu.au.
Acknowledgments
Chris Peiris Monash University, Australia, School of Computer Science and Software Engineering, Faculty of Information Technology
Paul W. Wille ISITE Design, Inc., Portland, Oregon
Leon Troeth Monash University, Australia, Directory Manager, Infrastructure Services, Information Technology Services
In the second article of his series on Indigo web services, Chris Peiris explains how to host an Indigo web service and examines the IIS, self hosting, and Windows Activation Service hosting options. He then provides step-by-step instructions and sample code for an IIS-hosted and self-hosted Indigo web service. [Read This Article][Top]
In the first part of his series on Microsoft Indigo, Chris Peiris examines the basics of SOA, explains how Indigo fits into the picture and the problems it solves. He then introduces Indigo's programming model and finishes by building a sample Indigo web service using the Microsoft .Net Framework 2.0. [Read This Article][Top]
Adnan Masood concludes his discussion of Microsoft SQL Server Analysis services and Microsoft SQL Server Reporting services. In the final part, he discusses Reporting Server web services and using custom code in reports. [Read This Article][Top]
This article explains the features of the IE Web service behavior and shows how to asynchronously communicate with an ASP.NET Web service directly from the client.
[Read This Article][Top]
Calvin Luttrell shows how to validate e-mail addresses stored in Excel 2003 and
provides a special function for solving that pesky problem Yahoo! mail servers cause. [Read This Article][Top]
This short article describes a quick and easy way to provide some security to an ASP.NET Web service by modifying its associated documentation file. [Read This Article][Top]
Kerberos authentication is the cornerstone of Windows operating system authentication architecture. Web Services Enhancement 2.0 (WSE 2.0) extends Kerberos support to ASP.NET Web services. Chris Peiris explains the support for this new feature in WSE 2.0. [Read This Article][Top]
Chip Irek examines the architectural issues and component design issues of building a .NET application in a service-oriented architecture. [Read This Article][Top]
Thiru Thangarathinam shows how to use asynchronous Web services, Windows
Service applications, server-based timer components and .NET XML API classes to create high-performance, scalable, and flexible applications. [Read This Article][Top]
Part one showed how to transform XML data into HTML by using an XSL stylesheet from within a .NET application. This part explains how to make use of XSLT Extension objects and invoke a C# class method from an XSL stylesheet. [Read This Article][Top]
Mailing List
Want to receive email when the next article is published? Just Click Here to sign up.