Engineering WS-I compliant Web services for IBM Lotus Domino V8

See how to engineer LotusScript-based Web services for IBM Lotus Domino V8 that comply with WS-I Basic Profile 1.1. Using the Discussion database template as an example, learn how to design and implement Web services for Lotus Domino V8 and maintain backward compatibility with Lotus Domino V7.0.2.

Share:

Stephen Kruger (Stephen_Kruger@ie.ibm.com), SOA Architect, IBM

Stephen Kruger is the SOA Architect for IBM's SOA Growth Projects, working out of the Dublin Software Lab in Ireland. Prior to this position, he led advanced development at the Xerox Research Centre in France, working on projects in the domain of linguistic and image processing for find automated solutions in document management. Before that he worked as an engineer in JavaSoft at Sun Microsystems International Centre for Network Computing in Grenoble, France.



Massimiliano Parlione (mparlion@ie.ibm.com), Senior Software Engineer, IBM

Massimiliano Parlione is a senior software engineer in IBM's Dublin Software Lab, Ireland. He has been with IBM since October 2006. He received his honours bachelor degree (Laurea) in Computer Science from the University of L'Aquila in July 1995 and a doctorate in Computer Engineering from the University La Sapienza of Rome in April 2000. Before joining IBM in Ireland, Dr. Parlione worked in Italy as Senior Consultant for Herzum software in Genova, as Software Engineer for IBM Rome's Tivoli Lab in the Performance and Availability area, as Executive Officer for the Marche region's IT department where he supervised projects for the regional health service, as contractor for the Italian Research Council (CNR) in Rome, and for Texas Instruments in Avezzano, Italy. As a consultant he has been involved with various business verticals including government organizations (Autonomous Province of Bozen - Italy), pharmaceutical wholesale (Alliance Boots - Italy, UK), and product development companies (Infogix, Aspect - both in USA). He co-authored the IBM REdbooks, "Introducing IBM Tivoli Monitoring for Web Infrastructure" and ";IBM Tivoli Monitoring Version 5.1.1 Creating Resource Models and Providers."



David Mills, Software Engineer, IBM

David Mills is a software engineer with IBM in Ireland. He attended University College Cork, Ireland studying Computer Science, where he graduated with an honours Bachelor of Science in 2006. He joined IBM as part of the Extreme Blue program in June 2006. As part of Extreme Blue he worked on an innovative IP Telephony project with three other graduates, which was presented to an Expo in Nice, France. He is currently part of the SOA Team in Dublin, Ireland.



Stephen McNena (StephenMcNena@ie.ibm.com), Software Engineer, IBM

Stephen Mc Nena is a software engineer with IBM in Ireland. He attended the Galway Mayo Institute of Technology, Ireland, studying Software Development, where he completed a National Diploma in Software Development in 2004 and graduated with an honours Bachelor of Science in Software Development in 2005. He joined the Dublin Software Lab, IBM in November 2006. He is currently part of the SOA Team in Dublin, Ireland.



Matt Healy (HEALYMAT@ie.ibm.com), Software Engineer, IBM

Matt Healy is a software engineer with IBM Ireland. He attended the Dublin Institute of Technology (DIT), Ireland, studying Computer Science. He graduated with an honours Bachelor of Science in 2004 and continued with a research masters degree, "Investigating Text Message Classification Using Case-base Reasoning," at the DIT. He joined the Dublin Software Lab, IBM Ireland, in September 2006. He is currently part of the SOA Team in Dublin, Ireland. He co-authored a conference paper "An Assessment of Case-based Reasoning for Short Text Message Classification" at AICS '05.



Frederic Biava (BIAVAFRE@ie.ibm.com), Software Engineer, IBM

Frederic Biava is a software engineer with IBM Ireland. He graduated with a degree (Maitrise) in Computer Science at the University of Marseille Luminy (France). He then completed a masters degree (D.E.S.S.) at the University of Avignon, where he graduated in 2004. He worked for HP technical support for a year. He joined the Dublin Software Lab, IBM Ireland in November 2006. He is currently part of the SOA Team in Dublin, Ireland.



15 May 2007

Also available in Chinese Japanese

[Editor's Note: The IBM Lotus Domino V8 features and updates described in this article reflect the Beta software. This article and its screenshots may or may not reflect the functionality of the final shiping product.]

This article illustrates the development of Web services for Lotus Domino V8 while maintaining backward compatibility with Lotus Domino V7.0.2. The example used in this article is a set of Web services for the Discussion database template. This solution is part of the ongoing Service-Oriented Architecture (SOA) Growth Project initiatives run by IBM in the Dublin Software Lab to facilitate the adoption of SOA-based solutions by augmenting IBM products with technology enablers that facilitate integration in an SOA. There are two main objectives for this particular solution:

  1. Engineer a Web service layer on the Discussion database template to expose the key template functionality for consumption by a Web service client.
  2. Ensure that the resultant Web services conform to the WS-I Basic Profile 1.1 to promote interoperability across different Web service engines and programming languages.

Due to its widespread use, the Discussion database template was chosen as a representative candidate to expose some of its functionalities as Web services. A database created from the discussion template allows multiple users to create, delete, and modify topics, responses to topics, and responses to responses. In addition, these topics and responses can be public or private, and they can be filtered according to the views in the database. Each author can create, modify, and delete his or her own profile, and some privileged authors can read the profiles of others.

The solution is architected to expose three logical Web services:

  • ViewManager. Responsible for management of views.
  • ProfileManager. Responsible for managing the Author profiles.
  • ThreadManager. Responsible for handling topics and responses.

The solution is implemented with LotusScript due to its maturity and widespread use in the Lotus Domino development community. The WS-I interoperability is verified by using the WS-I Interoperability Testing Tool for the Basic Profile 1.1.

This article summarizes our experience delivering this solution and discusses best practices for developing your own Web services using Lotus Domino V8. It also highlights several pitfalls and workarounds for achieving WS-I compliance for Lotus Domino V8 and compatibility with Lotus Domino V7.0.2. Lotus Domino V7.0.2 compatibility is a major requirement because organizations may take some time to migrate to Lotus Domino V8.

Design

This section gives an overview of the architecture used in the Domino Discussion database Web services application. It highlights the limitations in Lotus Domino that constrained the design choices; it describes the interfaces exposed and how to achieve compatibility between Lotus Domino V7.0.2 and V8.

The Discussion database Web services are designed as stateless Web services. In some circumstances, stateful Web services are more appropriate, for example, to offer a paging mechanism to list the topics and responses in a database. Stateful Web services do not fail over in a clustered Lotus Domino environment because Lotus Domino does not offer asynchronous replication among nodes to replicate sessions and states. For this reason, and for the sake of simplicity, we chose to implement stateless Web services.

Web services

The Discussion database Web services are functionally decomposed into three different services.

  • The DiscussionProfileManager allows managing the current user's profile and allows administrators to manage other users' profiles such as listing and deleting profiles.
  • The DiscussionViewManager is used to list the views and folders in a database and the sortable columns for each view. It is used in conjunction with the methods that work with views in the DiscussionThreadManager.
  • The DiscussionThreadManager is responsible for managing topics, responses, and categories. It exposes a group of Create, Read, Update, Delete, Exists, and List (CRUDEL) operations to work with topics, responses, and categories together with some methods to mark documents read and unread. Some operations are available in single or bulk mode, such as an updateTopic and updateTopics.

The Web services LIST methods return lists of topics, responses, authors, view names, and folder names. The methods offer multiple alternatives to allow returned lists to be sorted according to a sort criteria. The lists returned can be filtered according to a Notes Formula language query, a query by example, or a view. Some list methods that offer a simple paging mechanism are stateless. To use these methods, the user has to pass the page number and the number of elements desired. The documents are collected at each call; therefore, hypothetically, the same element may be returned in two different pages if the database changed between the calls.

Data transfer objects

The data transfer objects (DTOs), or value types as they are known in the Lotus Domino Web services documentation, are custom classes used to exchange data between the Web services and the clients.

For the Discussion database, we have the following DTOs as shown in figure 1:

  • Author is a class representing an author profile. It contains an author ID, author name, display name, email, phone number, body, goal, role, subject, categories, is-private, a modified date, and a created date.
  • Topic is a class that represents a topic in the Discussion database. It contains a document ID, a subject, a body, categories, a modified date, a created date, and mark-as-private attributes. The body does not contain any binaries such as attachments.
  • Response is a class that represents a response to a topic or a response to another response in the Discussion database. It contains a document ID, a parent ID, a subject, a body, categories, a modified date, a created date, and mark-as-private attributes. The body does not contain any binaries such as attachments.
  • SortItem is a class containing a field name and a sort order pair. It is used by SortCriteria to determine the sorting order of topics, responses, and authors returned by the list methods.
  • SortCriteria is a class containing a collection of SortItems and a name attribute. It is used by list methods to specify how to order topics, responses, and authors according to multiple attributes and orders contained in SortItems.
  • IDList is a class used for bulk updates that contains a list of IDs and a type attribute whose legal values are topic, response, and any.
Figure 1. Data transfer objects
Data transfer objects

Errors

The Web services throw custom errors containing the fields specifying:

  • Error message. Detail about the error that occurred.
  • Error number. A code to identify the error.
  • Line number. The location where the error is thrown in the script.
  • Database name. The name of the database in use.
  • Function name. The function in which the error occurred.
  • Web service name. The name of the Web service where the error occurred.

Errors are classified into the following groups:

  • DiscussionError signals any error generated during the normal Web service usage.
  • IllegalArgumentError is thrown every time an argument is not considered valid, for example, when a null value is passed to a method as a parameter.
  • UpdateError is thrown by the bulk update methods if one or more of the documents are not updated successfully. When thrown, it contains a list of IDs (either topics or responses) not updated.
  • UpdateConflictError is thrown when there is an attempt to modify the current document's modified date with an earlier date.

Compatibility

The Web services were designed to use the same interfaces for both Lotus Domino V7.0.2 and Lotus Domino V8 while the implementation uses a workaround to achieve source code portability as described in the "Implementation" section of this article.


Implementation

In this section, we describe the Web services implementation and the issues discovered while implementing them across Lotus Domino V7.0.2 and Lotus Domino V8. We describe how to work with the development environment to provide cross compatibility for the LotusScript implementation, how to handle LotusScript arrays, nulls, and complex data types passed to a Web service, how errors are handled, and how we reproduced the same behavior found in Lotus Notes for securing the Web services. We used Java 1.4, Axis 1.4 and Junit 3.8 to create a test suite to test the implementation. The test suite was continuously built and run with Ant and Cruisecontrol.

Development Environment

Lotus Domino V8 has a more advanced Web services engine than Lotus Domino V7.0.2, so it is not possible to use IBM Lotus Domino Designer V8 to create Web services that run on Lotus Domino V7.0.2. When a Lotus Domino Designer V8 Web service running in a Lotus Domino V7.0.2 server is accessed using a Web browser, the following error is displayed.

"This version of the Web Service design is not supported on this server"

Lotus Domino Designer V7.0.2 Web services work well in Lotus Domino V8 servers. This also means that Web services created or edited with Lotus Domino Designer V8 cannot be edited with Lotus Domino Designer V7.0.2 or later. The warning shown in figure 2 appears when you open a Lotus Domino V8 Web service in Lotus Domino Designer V7.0.2:

Figure 2. IBM Lotus Domino Designer error dialog box
Designer error dialog box

Arrays as parameters and return values

The list methods provided by the Discussion database Web services return arrays of data transfer objects. LotusScript does not provide the ability to return arrays in functions. Normally, arrays are returned using the Variant object in LotusScript, but for Web services, the Variant does not provide enough information to facilitate WSDL generation. To help in correcting WSDL generation, we use a holder class. A holder class is a LotusScript class object derived from the INOUT_HOLDER class (as defined in lsxsd.lss). The generated WSDL removes the holder class. The client side sees only a returned array as expected when working with Web services. The developerWorks articles, "Practical Web services in IBM Lotus Domino 7: Writing and testing simple Web services" and "Lotus Notes/Domino 7 Web Services" explain in more detail how to return arrays from LotusScript Web service methods using array holder classes.

NOTE: The lsxsd.lss is a library that contains classes that allow you to pass string arrays, files, and dates. This file can be found in your local Notes program directory.

Listings 1 and 2 show examples of a holder class and its generated section of the WSDL showing the AuthorDTO array.

Listing1. AuthorDTOArray_Holder Sample
Class AuthorDTOArray_Holder as INOUT_HOLDER
'The AuthorDTO array holder class
Public value() As AuthorDTO
...
...
End Class
Listing 2. The generated WSDL
<complexType name="AUTHORDTOArray">
  <sequence>
     <element maxOccurs="unbounded" minOccurs="0" name="item" type="impl:AUTHORDTO"/>
  </sequence>
</complexType>

Unfortunately, there are no instructions on how to pass arrays as parameters to LotusScript Web service methods. During the development of the Discussion database Web services, we tried two different approaches, passing arrays directly (listing 3) and using holder classes (listing 4) for both primitive and complex types.

Listing 3. Passing arrays directly sample
	Sub markListRead(ids() As String)
...
End Sub

Sub markTopicsRead(topics() as TopicDTO)
...
End Sub
Listing 4. Using array holder classes sample
	Sub markListUnread(ids As STRINGARRAY_HOLDER)
...
End Sub

Sub markTopicsUnread(topics As TopicDTOArray_Holder)
...
End Sub

Both approaches work in Lotus Domino V8. These work in Lotus Domino V7.0.2 using RPC Encoded WSDL. We don't use RPC encoding because it is not part of the WS-I Basic Profile 1.1. These approaches don't work in Lotus Domino V7.0.2 using the other encodings by default. When using arrays or array holders for primitive types, the Web service methods receive empty arrays from the Axis-based test client. When using arrays or array holders for complex types, a Web service fault is returned to the client containing the error message shown in listing 5.

Listing 5. Error message
“Web service (DiscussionThreadManager) object does not have specified member 
TOPICS in method MARKTOPICSREAD: value "" at element  quot;urn:DefaultNamespace:
MARKTOPICSREAD/TOPICS"”

It is possible to make the arrays work by manually editing the WSDLs from listing 6 to listing 7.

Listing 6. Generated WSDL
<complexType name="ArrayOf_xsd_string">
	<complexContent>
		<restriction base="soapenc:Array">
			<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
		</restriction>
	</complexContent>
</complexType>
Listing 7. Manually edited WSDL
<complexType name="ArrayOf_xsd_string">
	<sequence>
		<element maxOccurs="unbounded" minOccurs="0" name="item" type="xsd:string"/>
	</sequence>
</complexType>

The workaround to this problem is to use a custom class that acts as a container for the array but does not extend INOUT_HOLDER. In Lotus Domino V8 , any custom class containing one field that is an array is automatically treated as an array holder. To avoid this behavior and to create a consistent interface whether the LotusScript is deployed on Lotus Domino V7.0.2 or Lotus Domino V8 Beta, use custom classes containing more than one field as shown in listing 8.

Listing 8. IDList sample
Class IDList

	Public ids() As String

	Public type As String

End Class

Null values and complex types

LotusScript native data types, such as String, Integer, or Boolean, do not allow null values. To use null values, for example, to pass a null value for the body field in the topic DTO, we used the data types in the lsxsd.lss library, such as XSD_String or XSD_Boolean, which allow null values. Listing 9 shows a TopicDTO class with a field of type XSD_String, and the corresponding section in the generated WSDL in listing 10 shows that the body attribute is nillable.

Listing 9. TopicDTO sample
Class TopicDTO
	Public body As XSD_STRING
	...
End Class
Listing 10. TopicDTO WSDL fragment
	<complexType name="TOPICDTO">
   <sequence>
      <element name="BODY" nillable="true" type="xsd:string"/>
...
...
   </sequence>
</complexType>

When a Web service method with a complex type parameter receives a null or an instance with some attributes having null values, Lotus Domino V7.0.2 and Lotus Domino V8 behave differently. Lotus Domino V8 treats the nulls as the LotusScript Nothing (that is, null in other programming languages) whereas Lotus Domino V7.0.2 instantiates these with default values. Numeric fields are given the value 0, and string fields have the empty string value. Classes are instantiated with all their primitive type attributes given default values. This behavior requires different approaches for null checking in Lotus Domino V7.0.2 and Lotus Domino V8.

The code in listing 11 first checks if the response passed is null, and, if not, then checks if the required fields are null.

Listing 11. createResponse for Lotus Domino V8 sample
	Function createResponse(response As ResponseDTO) As ResponseDTO
	If response Is Nothing Then
		Error 1, "Response is null."
	End If

	If response.parentID Is Nothing Then
		Error 1, "The Responses parent ID is null."
	End If
	...
End Function

This code works correctly in Lotus Domino V8, but in Lotus Domino V7.0.2 the response instance is never Nothing because it is instantiated to the default value. If a response is passed, then parentID is never Nothing for the same reason.

Listing 12. createResponse for Lotus Domino V7 sample
		Function createResponse(response As ResponseDTO) As ResponseDTO
	If response.ID Is Nothing Then
		Error 1, "Response is null."
	End If

	If response.parentID.GetValueAsString = "" Then
		Error 1, "The Responses parent ID is null."
	End If
	...
End Function

In Lotus Domino V7.0.2, the code in listing 12 works due to the automatic instantiation of objects when a null parameter is received as input. In Lotus Domino V8, the null parameters become Nothing in LotusScript, so response.ID would cause an error if response were Nothing, and response.parentID.GetValueAsString would cause an error if the parentID field were Nothing.

The workaround to create code that works in both Lotus Domino V7.0.2 and Lotus Domino V8 requires an If statement to branch the code depending upon the LotusScript version. When developing a Web service that is backward compatible from Versioon 8 to Version V7.0.2, we need a way of determining on which version the Web service is running. This information can be found using the Getthreadinfo() function as shown in listing 13. Using an If statement, the Getthreadinfo(LSI_THREAD_VERSION) function returns the LotusScript version for Lotus Domino V7.0.2, which is 5.0.0.07B. Lotus Domino V7.0.2 executes the code in the If branch, and later versions execute in the Else branch.

Listing 13. LotusScript version checking sample
	Function createResponse(response As ResponseDTO) As ResponseDTO
	If CStr(GetThreadInfo(LSI_THREAD_VERSION)) <= "5.0.0.07B" Then
		' Domino 7.0.2 or earlier
		If response.ID Is Nothing Then
			Error 1, "Response is null."
		End If

		If response.parentID.GetValueAsString = "" Then
			Error 1, "The Responses parent ID is null."
		End If
	Else
		' Later than Domino 7.0.2
		If response Is Nothing Then
			Error 1, "Response is null."
		End If

		If response.parentID Is Nothing Then
			Error 1, "The Responses parent ID is null."
		End If

	End IF
	...
End Function

Errors

Here we describe how LotusScript handles errors and how you can leverage this to implement Web service errors that provide some useful information to the client. LotusScript provides three functions to examine the current error state and to display the error information. These functions are:

  • Error(). Returns the associated error message.
  • Err(). Returns the associated error number.
  • Erl(). Returns the line number on which the error occurred.

Web services faults are thrown in LotusScript by using a special out parameter that is an instance of a WS_Fault class (available in the lsxsd.lss library) as shown in the developerWorks article "Practical Wenb services in IBM Lotus Domino 7: Writing complex Web services." See listing 14.

Listing 14. Faults sample
Function foo(fault As WS_FAULT) As ...
		
	Fault.SetFault True
	Fault.setFaultString "error message" 

End Function

Lotus Domino V8 handles custom errors that are extensions of the WS_Fault class. It enables Axis 1.4 to generate errors as subclasses of AxisFault, and these are caught when an error occurs. The code in listing 15 uses the OnError statement to catch runtime errors and uses a custom throwFault function that instantiates DiscussionError. DiscussionError is a custom class (a fault) that contains the error message, the function name where it is generated, and the database name containing the Web services. The function name is collected through the GetThreadIfo(LSI_THREAD_PROC) function. For serviceability, the errors are logged into the logging database using the nLog.logError function when they are generated.

Listing 15. createTopic sample
	Function createTopic(topic As TopicDTO, fault As DiscussionError) As TopicDTO
 On Error Goto FAULT
 ... 
 Exit Function
FAULT:
 Set fault = throwFault(fault, GetThreadInfo(LSI_THREAD_PROC), database.FileName)
 nLog.LogError Err, "Error in " & GetThreadInfo(LSI_THREAD_PROC) & " : " & Error & " 
			Line : " & Erl
 Exit Function
End Function

Lotus Domino V7.0.2 does not return SOAP fault subtype member data. As a result, all errors regardless of the custom class used in Lotus Domino V7.0.2 are treated as AxisFault exceptions at runtime by the client and not as the custom error. For instance, Axis 1.4 generates a custom exception class, but it is never thrown at runtime by the Web service. We have not discovered a workaround for this.

Security

The user access privileges provided by the Web services are consistent with those enforced by the Lotus Notes client. In Lotus Domino, each document has an Authors field and a Readers field; see the Lotus Domino Designer documentation. The Authors field determines who can edit or update a document. The Readers field controls who can read a document. For consistency between the Lotus Notes client and the Web services, when a topic or a response is created, the user is added to the Authors field. If the user chooses to make the topic or the response private, the user is added to the Readers field. The topics and responses have a Boolean field to mark them private or public.


Deploying the DiscussionProfileManager

In this section, we describe how to configure Lotus Domino to expose secure Web services and how to deploy them. As an example, we show how to deploy the DiscussionProfileManager Web service developed for the Discussion database. You can follow the same steps for the other two Web services developed for this solution: the DiscussionThreadManager and the DiscussionViewManager.

Configuring security

To allow users to access the Web services in a secure way, Lotus Domino should use the embedded Web server with the HTTPS protocol.

To configure your server you should:

  1. Launch the IBM Lotus Domino Administrator client.
  2. Select the Configuration tab.
  3. Open the Server document.
  4. Select the Ports tab.
  5. Select the Internet Ports tab.
  6. Click the Edit Server button.
  7. Change to enable the HTTPS and disable the HTTP.

To authenticate users, they must have enabled an Internet password. This password can be set in the Domino Directory by editing your person document with your Notes client.

Deploying the DiscussionProfileManager manually

To deploy this Web service, follow these steps:

  1. Open the target database in Lotus Domino Designer.
  2. Select Shared Code, and then select Web Services in the Navigator.
  3. Click New Web Service.
  4. Enter a name for the Web service in the Web Service properties box, for example, DisscussionProfileManager.
  5. Enter DiscussionProfileManager as the Port Type Class as shown in figure 3.
Figure 3. Web Service properties box
Web Service properties box
  1. Choose the Security tab of the Web Service properties box as shown in figure 4.
  2. Select "Run as web user" option. This allows users to invoke the Web service using their user name and Internet password.
Figure 4. Security tab of Web Service properties box
Security tab of Web Services properties box
  1. Choose the Advanced tab of the Web Service properties box.
  2. Enter suitable names for Port type name, Service element name, and Service port name (Lotus Domino automatically populates these if the fields are left blank). For an example of the DiscussionProfileManager see figure 5.
  3. Select the desired encoding method.
Figure 5. Advanced tab of the Web Service properties box
Advanced tab of the Web Service properties box
  1. Close the Web Service properties box.
  2. Delete the text Option Base from the options section.
  3. Open DiscussionProfileManager.lss in a text editor such as Microsoft Notepad.
  4. Copy all the text in DiscussionProfileManager.lss.
  5. Select the Declarations section of the new Web service in Lotus Domino Designer as shown in figure 6.
Figure 6. Declarations section of Web service
Declarations section of Web service
  1. Paste in the Web service.
  2. Save and close the Web service.

The Web services will now be available at:

http://<DominoServer>/<Database Path>/DiscussionProfileManager

NOTE: The Web service engine is configured as single threaded by default. To change this default configuration, you need to connect to the server with the Lotus Domino Administrator client, select the Server icon on the left pane, open the list, select the Current Server Document, go to the Internet Protocols tab, click the Domino Web Engine tab, and change the Web Agents setting "Run Web agents concurrently?" entry from Disabled to Enabled as shown in figure 7. Then perform an HTTP task restart or restart the server.

For further details consult the IBM Redpaper, "IBM Lotus Domino for iSeries, performance, and tuning."

Figure 7. Web Agents concurrency setting
Web Agents concurrency setting

WS-I compliance

The goal of WS-I compliance is to guarantee the interoperability of the Discussion database Web services to allow their consumption by clients using other compliant Web service technologies. For example, J2ME clients require all Web Service Description Language (WSDL) definitions to be WS-I compliant.

The Web Services Interoperability Organisation has developed a testing tool that evaluates Web service conformance to Basic Profile 1.1. This tool tests Web service implementations using a non-intrusive, black-box approach. The tool's focus is on the interaction between a Web service and user applications. To execute these tests, we used the Interoperability Testing Tool 1.1.

The testing tool comprises a Monitor, an Analyzer (see figure 8), and a variety of supporting files. The Monitor acts as both a message capture and logging tool. It intercepts the messages and the logger reformats them and stores them for later analysis into a message log. The Monitor is implemented using a man in the middle approach to intercept and record messages. The Analyzer is the analysis tool that verifies the conformance of Web services to WS-I Profiles. It analyzes the messages sent to and from a Web service, after these have been logged in the message log by the Monitor.

For further details, see the WS-I Organization resources for Web services developers to create interoperable Web services and to verify that their results are compliant with WS-I guidelines.

Figure 8. Interoperability test tool
Interoperability test tool

Instructions on how to use the Interoperability Test Tool are included with the tool.

Tests performed on the Discussion database Web services

Lotus Domino allows publishing Web services using the following encodings:

  • Document Wrapped
  • Document Literal
  • RPC Literal
  • RPC Encoded

RPC-encoded Web services are not part of WS-I Basic Profile 1.1, and thus, they are not considered further for this article. During the development of the Web services, we performed both static and dynamic WS-I compliance testing for both Lotus Domino V7.0.2 and Lotus Domino V8 for the other three encodings: Document Wrapped, Document Literal, and RPC Literal.

The static test involves using the Analyzer to perform a static analysis of each Web service WSDL. The dynamic test involves using the Monitor to record SOAP messages between the Web service and client; in this case, the client is a JUnit Test Suite based on Axis 1.4. The Monitor logs the SOAP messages in a log file that is then analyzed by the Analyzer tool. A generated conformance report file states whether the Web service is WS-I compliant or not.

Lotus Domino V7.0.2 and V8 WS-I failures

Lotus Domino V7.0.2 generates a WSDL that fails the WS-I Interoperability Tests in the following cases:

  • When Document Literal and Document Wrapped encodings are used
  • When arrays are used within the Web services
  • When RPC Literal encoded Web services contain SOAP faults
  • When Document Literal encoded Web services have methods that take more than one parameter

Lotus Domino V8 generates WSDLs that fail the WS-I Interoperability Tests in the following cases:

  • When RPC Literal encoded Web services contain SOAP faults
  • When Document Literal encoded Web services have methods that take more than one parameter
  • When Document Literal encoded Web services have parameters that are not unique

These WS-I failures are explained in detail here with samples of the incorrect WSDL and the changes required to make the WSDL compliant. As described in the Lotus Domino Designer documentation, several WSDL or XML schema constructs have limited or no supported mappings to LotusScript or Java. They are not supported by Lotus Domino Designer when trying to import WSDLs.

Array representation

Lotus Domino V7.0.2 -generated WSDLs for Web services containing arrays are not WS-I compliant. This affects the following encodings:

  • Domino V7 Document Literal
  • Domino V7 Document Wrapped
  • Domino V7 Document RPC Literal

The WS-I tests failed with the following error:

"An Array declaration uses - restricts or extends - the soapenc:Array type,
or the wsdl:arrayType attribute is used in the type declaration."

For the three different encodings, arrays are represented in the WSDL by the code in listing 16.

Listing 16. Generated WSDL
<complexType name="ArrayOf_xsd_string">
	<complexContent>
		<restriction base="soapenc:Array">
			<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
		</restriction>
	</complexContent>
</complexType>

The workaround for this problem is to manually edit the WSDLs and to import them into Lotus Domino Designer (for more information on importing WSDLs into Lotus Domino Designer, see the section, "Importing WSDLs"). To make it WS-I compliant, remove the <complexContent> tag and replace it with <sequence> tag as shown in listing 17.

Listing 17. Compliant WSDL
<complexType name="ArrayOf_xsd_string">
	<sequence>
		<element maxOccurs="unbounded" minOccurs="0" name="item" type="xsd:string"/>
	</sequence>
</complexType>

Namespace attribute

For WS-I compliance, the namespace attribute cannot be contained in any soapbind:body, soapbind:header, soapbind:headerfault, soapbind:fault elements. This problem affects the following WSDL encodings:

  • Domino V7.0.2 Document Literal
  • Domino V7.0.2 Document Wrapped

After running the WS-I test tool the following error message is given:

"A document-literal binding in a DESCRIPTION MUST NOT have
the namespace attribute specified on contained soapbind:body,soapbind:header, soapbind:headerfault
and soapbind:fault elements."

Listing 18 shows the part of a generated WSDL that is not WS-I compliant for both Document Wrapped and Document Literal, which contains the namespace attribute.

Listing 18. Generated WSDL
<wsdl:binding name="DiscussionProfileManagerSoapBinding"
		type="impl:DiscussionProfileManagerPort">
		<wsdlsoap:binding style="document"
			transport="http://schemas.xmlsoap.org/soap/http" />
		<wsdl:operation name="GETVERSION">
			<wsdlsoap:operation soapAction="" />
			<wsdl:input name="GETVERSIONRequest">
				<wsdlsoap:body namespace="urn:DefaultNamespace"
					use="literal" />
			</wsdl:input>
			<wsdl:output name="GETVERSIONResponse">
				<wsdlsoap:body namespace="urn:DefaultNamespace"
					use="literal" />
			</wsdl:output>
		</wsdl:operation>

To solve this problem, manually edit the WSDL and remove the namespace attribute from the <wsdlsoap:body> tag as shown in the WSDL sample in listing 19. Then import the WSDL into Lotus Domino Designer.

Listing 19. Compliant WSDL
<wsdl:binding name="DiscussionProfileManagerSoapBinding"
		type="impl:DiscussionProfileManagerPort">
		<wsdlsoap:binding style="document"
			transport="http://schemas.xmlsoap.org/soap/http" />
		<wsdl:operation name="GETVERSION">
			<wsdlsoap:operation soapAction="" />
			<wsdl:input name="GETVERSIONRequest">
				<wsdlsoap:body use="literal" />
			</wsdl:input>
			<wsdl:output name="GETVERSIONResponse">
				<wsdlsoap:body use="literal" />
			</wsdl:output>		
</wsdl:operation>

WSDL element attribute

This error occurs when the <wsdl:part> tag, in the <wsdl:message> tag is defined using the type attribute for header and fault elements. This error affects the following encodings:

  • Domino V7.0.2 RPC Literal
  • Domino V8 RPC Literal

The message given for this error is:

"A wsdl:binding in a DESCRIPTION MUST refer, in each of itssoapbind:header,
soapbind:headerfault and soapbind:fault elements, only to wsdl:part element(s) that have been defined
using the element attribute."

Because faults and headers do not contain parameters, soapbind:fault, soapbind:header, and soapbind:headerfault assume, per WSDL 1.1, that the value of the style attribute is document. All wsdl:part elements with a style attribute whose value is document that are bound to soapbind:body are defined using the element attribute. This requirement does the same for soapbind:fault, soapbind:header, and soapbind:headerfault elements.

NOTE: The header and fault elements for RPC Literal Web services should be defined in the same style as in Document Literal encoding as per assertion requirement R2205.

A non-WS-I compliant WSDL is shown in listing 20. Notice the use of the type attribute in the <wsdl:part> tag.

Listing 20. Generated WSDL
<complexType name="DISCUSSIONERROR">
	<sequence>
		...
		...
	</sequence>
</complexType>
...
...
<wsdl:message name="DISCUSSIONERROR">
   <wsdl:part name="DISCUSSIONERROR" type="impl:DISCUSSIONERROR" />
</wsdl:message>

To change this WSDL so that it is WS-I compliant, manually add <element> tags around the <complexType> tag and change the type attribute in the <wsdl:part> tag to an element attribute. An example of the compliant WSDL is shown in listing 21. After editing the WSDL, import the edited WSDL into Lotus Domino Designer.

Listing 21. Compliant WSDL
<element name="DISCUSSIONERROR">
	<complexType>
		<sequence>
			...
			...
		</sequence>
	</complexType>
</element>
...
...
<wsdl:message name="DISCUSSIONERROR">
   <wsdl:part name="DISCUSSIONERROR" element="impl:DISCUSSIONERROR" />
</wsdl:message>

Message element has more than one part element

This error occurs when there are more than one <wsdl:part> elements inside the <wsdl:message> tag for the following encodings:

  • Domino V7.0.2 Document Literal
  • Domino V8 Document Literal

These encodings failed the WS-I tests with the following error message:

"A document-literal binding which does not specify the parts attribute, has more than one wsdl:part in the associated wsdl:message element."

Listing 22 shows the offending part of the generated WSDL.

Listing 22. Generated WSDL
	<wsdl:message name="LISTAUTHORSBYEXAMPLEANDSORTCRITERIARequest">
		<wsdl:part element="impl:EXAMPLE" name="EXAMPLE" />
		<wsdl:part element="impl:SORT" name="SORT" />
</wsdl:message>

When you define a document/literal service, you can have, at most, one body part in your input message and one body part in your output message. Therefore, your Web service cannot have more than one parameter being passed into a method. If you intend to use methods with more than one parameter, you have to use the Document Wrapped encoding to be compliant.

A binding has operations that are not unique

This error is due to message elements containing non-unique parts. This error affects the following encodings:

  • Domino V7.0.2 Document Literal
  • Domino V8 Document Literal

After running the WS-I tests the following error message occurs:

"A binding has operations that are not unique."

A section of the non-compliant WSDL is shown in listing 23. Notice that some of the part elements inside the message elements, such as the ID element, are not unique.

Listing 23. Generated WSDL
...
...
<wsdl:types>
		<schema targetNamespace="urn:DefaultNamespace"
			xmlns="http://www.w3.org/2001/XMLSchema">
<element name="ID" type="xsd:string" />
<element name="AUTHOR" type="impl:AUTHORDTO" />
...
...
</schema>
	</wsdl:types>

<wsdl:message name="GETVERSIONRequest">
	Part element missing
	</wsdl:message>

<wsdl:message name="DELETEAUTHORPROFILERequest">
		<wsdl:part element="intf:ID" name="ID" />
	</wsdl:message>

<wsdl:message name="READAUTHORPROFILERequest">
		<wsdl:part element="intf:ID" name="ID" />
	</wsdl:message>

<wsdl:message name="EXISTSAUTHORPROFILERequest">
		<wsdl:part element="intf:ID" name="ID" />
	</wsdl:message>

<wsdl:message name="UPDATEAUTHORPROFILERequest">
		<wsdl:part element="intf:AUTHOR" name="AUTHOR" />
	</wsdl:message>

<wsdl:message name="CREATEAUTHORPROFILERequest">
	<wsdl:part element="intf:AUTHOR" name="AUTHOR" />
</wsdl:message>
...
...

To conform to the WS-I Basic Profile 1.1, all message elements must contain parts that are unique. The corresponding compliant sections of the WSDL are shown in listing 24. Notice how the element declarations and the element name in the <wsdl:part> tags are now all unique. This workaround can be cumbersome if there are many methods in your Web service. We suggest that you use Document Wrapped encoding. Read about "The wrapped document/literal convention" by Anne Thomas Manes.

Listing 24. Compliant WSDL
<wsdl:types>
	<schema targetNamespace="urn:DefaultNamespace"
		xmlns="http://www.w3.org/2001/XMLSchema">
		<element name="GETVERSIONReturn" type="xsd:string" />
<element name="ID_1" type="xsd:string" />
<element name="ID_2" type="xsd:string" />
<element name="ID_3" type="xsd:string" />
...
<element name="AUTHOR_1" type="impl:AUTHORDTO" />
<element name="AUTHOR_2" type="impl:AUTHORDTO" />
...
...

<wsdl:message name="GETVERSIONRequest">
	There must be one part element here
	</wsdl:message>

<wsdl:message name="DELETEAUTHORPROFILERequest">
		<wsdl:part element="intf:ID_1" name="ID" />
	</wsdl:message>

<wsdl:message name="EXISTSAUTHORPROFILERequest">
		<wsdl:part element="intf:ID_2" name="ID" />
	</wsdl:message>
<wsdl:message name="READAUTHORPROFILERequest">
		<wsdl:part element="intf:ID_3" name="ID" />
	</wsdl:message>
<wsdl:message name="UPDATEAUTHORPROFILERequest">
		<wsdl:part element="intf:AUTHOR_1" name="AUTHOR" />
	</wsdl:message>

<wsdl:message name="CREATEAUTHORPROFILERequest">
	<wsdl:part element="intf:AUTHOR_2" name="AUTHOR" />
</wsdl:message>
...
...

Importing WSDL

In Lotus Domino Designer, it is possible to create Web services by inputting code and having Lotus Domino Designer generate the WSDL or by importing a WSDL and having Lotus Domino Designer generate the code signatures for the Web service interface. The Web services described throughout this article had their WSDLs generated by Lotus Domino Designer. Sometimes it is preferable to use an existing WSDL, for example, to change Lotus Domino Designer-generated WSDLs to make them WS-I compliant.

To create a Web service by importing WSDL, do the following:

  1. Open the target database in Lotus Domino Designer.
  2. Select Shared Code, then Web Services in the Navigator pane.
  3. Click New Web Service.
  4. Close the Web Service Properties box.
  5. Select Import WSDL and click OK on the warning dialog box.
  6. Select the desired WSDL file and click Open.

This generates the LotusScript function signatures for the Web service. If the generated interface is modified and the Web service is saved, Lotus Domino Designer overwrites the imported WSDL with its own auto-generated WSDL. To prevent this and to keep the imported WSDL, it is important to do the following before continuing with the Web service implementation:

  1. Open the Web Service properties box shown in figure 9 by right-clicking the code pane.
  2. Enter a name for the Web service.
  3. Select the "Warn if the WSDL interface is modified" option.
Figure 9. Web Service properties box
Web Service properties box
  1. Close the Web Service properties box.
  2. Save the Web service.

The WS-I static compliance tests can be easily integrated in an Ant-based build environment and automatically executed by a build automation tool such as CruiseControl. We advise that you continuously check if the exposed Web services are compliant while the solution is under construction.

For the Domino Discussion database Web services, Lotus Domino V7.0.2 does not generate WS-I compliant WSDL documents, but the WSDL documents can be manually edited to achieve WS-I compliance and then imported into Lotus Domino Designer. With Lotus Domino V8, the only encoding that has never failed the generation of WS-I compliant WSDL documents is the Document Wrapped encoding. All other encodings have to be manually edited to be WS-I compliant.

In general, Lotus Domino V7.0.2 can generate compliant WSDLs only with the RPC Literal encoding as long as neither arrays nor faults are used. Lotus Domino V8 generates compliant WSDLs with the RPC literal encoding when no faults are used, with Document Literal encoding when all the methods have only one parameter and when all method parameters have unique names, and Document Wrapped encoding.


Conclusion

In this article, we described how to engineer Web services for Lotus Domino V8. We used the Discussion database as an example. We described the Web services architecture, how we decomposed their functionalities, how data is transferred between the Web services and a client, and we defined the possible errors that could occur. We gave an overview of how to implement the Web services, of how to achieve compatibility with Lotus Domino V7.0.2, of issues we encountered and of workarounds to address them. We suggested how to configure Lotus Domino to allow secure connections over HTTPS and how users can authenticate to access the Web services with the same user privileges as the Notes client. We then described how to deploy the Web services in a Domino database using Lotus Domino Designer.

We performed the WS-I interoperability testing and highlighted that the Web services for the Discussion database should be exposed with the Document Wrapped encoding. This is the only encoding that has passed the compliance tests for Lotus Domino V8 when Lotus Domino generates the WSDLs. Our Web services published with Lotus Domino V7 do not pass the interoperability tests regardless of the encoding of the generated WSDLs. WS-I-compliant WSDL documents can be created by manually editing the WSDLs, and then importing them into Lotus Domino Designer.

The Discussion database Web services used as examples for this article can be found in the Lotus Sandbox.

Acknowledgments

We would like to add a special thank you to Gordon Hegfield, Steve Nikopoulos and John Grosjean for a technical review of the article.

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into IBM collaboration and social software on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Lotus, SOA and web services
ArticleID=219538
ArticleTitle=Engineering WS-I compliant Web services for IBM Lotus Domino V8
publish-date=05152007