Related considerations when using web services

Sometimes issues occur when invoking certain LiveCycle services operations by using web services. The objective of this discussion is to identify those issues and provide a solution, if one is available.

Invoking service operations asynchronously

If you attempt to asynchronously invoke a LiveCycle service operation, such as the Generate PDF’s htmlToPDF operation, a SoapFaultException occurs. To resolve this issue, create a custom-binding XML file that maps the ExportPDF_Result element and other elements into different classes. The following XML represents a custom binding file.

<bindings     
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:jxb="http://java.sun.com/xml/ns/jaxb" jxb:version="1.0" 
       xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
     wsdlLocation="http://localhost:8080/soap/services/GeneratePDFService?wsdl&amp;async=true&amp;lc_version=9.0.0" 
       xmlns="http://java.sun.com/xml/ns/jaxws"> 
       <enableAsyncMapping>false</enableAsyncMapping> 
       <package name="external_customize.client"/> 
       <enableWrapperStyle>true</enableWrapperStyle> 
       <bindings node="/wsdl:definitions/wsdl:types/xsd:schema[@targetNamespace='http://adobe.com/idp/services']/xsd:element[@name='ExportPDF_Result']">            
           <jxb:class name="ExportPDFAsyncResult">             
           </jxb:class> 
       </bindings> 
       <bindings node="/wsdl:definitions/wsdl:types/xsd:schema[@targetNamespace='http://adobe.com/idp/services']/xsd:element[@name='CreatePDF_Result']">            
           <jxb:class name="CreatePDFAsyncResult">             
           </jxb:class> 
       </bindings> 
       <bindings node="/wsdl:definitions/wsdl:types/xsd:schema[@targetNamespace='http://adobe.com/idp/services']/xsd:element[@name='HtmlToPDF_Result']">            
           <jxb:class name="HtmlToPDFAsyncResult">             
           </jxb:class> 
       </bindings> 
       <bindings node="/wsdl:definitions/wsdl:types/xsd:schema[@targetNamespace='http://adobe.com/idp/services']/xsd:element[@name='OptimizePDF_Result']">            
           <jxb:class name="OptimizePDFAsyncResult">             
           </jxb:class> 
       </bindings> 
       <!--bindings node="//wsdl:portType[@name='GeneratePDFService']/wsdl:operation[@name='HtmlToPDF_Result']">               
           <jxb:class name="HtmlToPDFAsyncResult"/>             
       </bindings--> 
</bindings>

Use this XML file when creating Java proxy files by using JAX-WS. (See Creating Java proxy classes using JAX-WS.)

Reference this XML file when executing the JAX-WS tool (wsimport.exe) by using the –b command line option. Update the wsdlLocation element in the binding XML file to specify the URL of LiveCycle.

To ensure that asynchronous invocation works, modify the end point URL value and specify async=true. For example, for Java proxy files that are created with JAX-WS, specify the following for the BindingProvider.ENDPOINT_ADDRESS_PROPERTY.

http://server:port/soap/services/ServiceName?wsdl&async=true&lc_version=9.0.0

The following list specifies other services that need a custom binding file when invoked asynchronously:

  • PDFG3D

  • Task Manager

  • Application Manager

  • Directory Manager

  • Distiller

  • Rights Management

  • Document Management

Differences in J2EE application servers

Sometimes a proxy library created using a specific J2EE application server does not successfully invoke LiveCycle that is hosted on a different J2EE application server. Consider a proxy library that is generated using LiveCycle that is deployed on WebSphere. This proxy library cannot successfully invoke LiveCycle services that are deployed on the JBoss Application Server.

Some LiveCycle complex data types, such as PrincipalReference, are defined differently when LiveCycle is deployed on WebSphere as compared to the JBoss Application Server. Differences in the JDKs used by the different J2EE application services are the reason why there are differences in WSDL definitions. As a result, use proxy libraries that are generated from the same J2EE application server.

Accessing multiple services using web services

Due to namespace conflicts, data objects cannot be shared between multiple service WSDLs. Different services can share data types and, therefore the services share the definition of these types in the WSDLs. For example, you cannot add two .NET client assemblies that contain a BLOB data type to the same .NET client project. If you attempt to do so, a compile error occurs.

The following list specifies data types that cannot be shared between multiple service WSDLs:

  • User

  • Principals

  • PrincipalReference

  • Groups

  • Roles

  • BLOB

To avoid this problem, it is recommended that you fully-qualify the data types. For example, consider a .NET application that references both the Forms service and Signature service using a service reference. Both service references will contain a BLOB class. To use a BLOB instance, fully-qualify the BLOB object when you declare it. This approach is shown in the following code example. For information about this code exampe, see Digitally Signing Interactive Forms.

The following C# code example signs an interactive form that is rendered by the Forms service. The client application has two service references. The BLOB instance that is associated with the Forms service belongs to the SignInteractiveForm.ServiceReference2 namespace. Likewise, the BLOB instance that is associated with the Signature service belongs to the SignInteractiveForm.ServiceReference1 namespace. The signed interactive form is saved as a PDF file named LoanXFASigned.pdf.

???/** 
    * Ensure that you create a .NET project that uses  
    * MS Visual Studio 2008 and version 3.5 of the .NET 
    * framework. This is required to invoke a  
    * LiveCycle service using MTOM. 
    *      
    * For information, see "Invoking LiveCycle using MTOM" in Programming with LiveCycle   
    */ 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.ServiceModel; 
using System.IO; 
 
//A reference to the Signature service  
using SignInteractiveForm.ServiceReference1; 
 
//A reference to the Forms service  
using SignInteractiveForm.ServiceReference2; 
 
namespace SignInteractiveForm 
{ 
       class Program 
       { 
           static void Main(string[] args) 
           { 
               try 
               { 
                   //Because BLOB objects are used in both service references 
                   //it is necessary to fully-qualify the BLOB objects 
 
                   //Retrieve the form -- invoke the Forms service 
                   SignInteractiveForm.ServiceReference2.BLOB formData = GetForm(); 
 
                   //Create a BLOB object associated with the Signature service 
                   SignInteractiveForm.ServiceReference1.BLOB sigData = new SignInteractiveForm.ServiceReference1.BLOB(); 
 
                   //Transfer the byte stream from one Forms BLOB object to the  
                   //Signature BLOB object 
                   sigData.MTOM = formData.MTOM; 
 
                   //Sign the Form -- invoke the Signature service 
                   SignForm(sigData); 
               } 
               catch (Exception ee) 
               { 
                   Console.WriteLine(ee.Message); 
               } 
           } 
 
           //Creates an interactive PDF form based on a XFA form - invoke the Forms service 
           private static SignInteractiveForm.ServiceReference2.BLOB GetForm() 
           { 
 
               try 
               { 
                   //Create a FormsServiceClient object 
                   FormsServiceClient formsClient = new FormsServiceClient(); 
                   formsClient.Endpoint.Address = new System.ServiceModel.EndpointAddress("http://hiro-xp:8080/soap/services/FormsService?blob=mtom"); 
 
                   //Enable BASIC HTTP authentication 
                   BasicHttpBinding b = (BasicHttpBinding)formsClient.Endpoint.Binding; 
                   b.MessageEncoding = WSMessageEncoding.Mtom; 
                   formsClient.ClientCredentials.UserName.UserName = "administrator"; 
                   formsClient.ClientCredentials.UserName.Password = "password"; 
                   b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic; 
                   b.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly; 
                   b.MaxReceivedMessageSize = 2000000; 
                   b.MaxBufferSize = 2000000; 
                   b.ReaderQuotas.MaxArrayLength = 2000000; 
 
                   //Create a BLOB to store form data 
                   SignInteractiveForm.ServiceReference2.BLOB formData = new SignInteractiveForm.ServiceReference2.BLOB(); 
                   SignInteractiveForm.ServiceReference2.BLOB pdfForm = new SignInteractiveForm.ServiceReference2.BLOB(); 
 
                   //Specify a XML form data 
                   string path = "C:\\Adobe\Loan.xml"; 
                   FileStream fs = new FileStream(path, FileMode.Open); 
 
                   //Get the length of the file stream  
                   int len = (int)fs.Length; 
                   byte[] ByteArray = new byte[len]; 
 
                   fs.Read(ByteArray, 0, len); 
                   formData.MTOM = ByteArray; 
 
                   //Specify a XML form data 
                   string path2 = "C:\\Adobe\LoanSigXFA.pdf"; 
                   FileStream fs2 = new FileStream(path2, FileMode.Open); 
 
                   //Get the length of the file stream  
                   int len2 = (int)fs2.Length; 
                   byte[] ByteArray2 = new byte[len2]; 
 
                   fs2.Read(ByteArray2, 0, len2); 
                   pdfForm.MTOM = ByteArray2; 
 
                   PDFFormRenderSpec renderSpec = new PDFFormRenderSpec(); 
                   renderSpec.generateServerAppearance = true; 
 
                   //Set out parameter values 
                   long pageCount = 1; 
                   String localValue = "en_US"; 
                   FormsResult result = new FormsResult(); 
 
                   //Render an interactive PDF form 
                   formsClient.renderPDFForm2( 
                       pdfForm, 
                       formData, 
                       renderSpec, 
                       null, 
                       null, 
                       out pageCount, 
                       out localValue, 
                       out result); 
 
                   //Write the data stream to the BLOB object 
                   SignInteractiveForm.ServiceReference2.BLOB outForm = result.outputContent; 
                   return outForm; 
               } 
               catch (Exception ee) 
               { 
                   Console.WriteLine(ee.Message); 
               } 
               return null; 
           } 
 
           //Sign the form -- invoke the Signature service 
           private static void SignForm(SignInteractiveForm.ServiceReference1.BLOB inDoc) 
           { 
 
               try 
               { 
                   //Create a SignatureServiceClient object 
                   SignatureServiceClient signatureClient = new SignatureServiceClient(); 
                   signatureClient.Endpoint.Address = new System.ServiceModel.EndpointAddress("http://hiro-xp:8080/soap/services/SignatureService?blob=mtom"); 
 
                   //Enable BASIC HTTP authentication 
                   BasicHttpBinding b = (BasicHttpBinding)signatureClient.Endpoint.Binding; 
                   b.MessageEncoding = WSMessageEncoding.Mtom; 
                   signatureClient.ClientCredentials.UserName.UserName = "administrator"; 
                   signatureClient.ClientCredentials.UserName.Password = "password"; 
                   b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic; 
                   b.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly; 
                   b.MaxReceivedMessageSize = 2000000; 
                   b.MaxBufferSize = 2000000; 
                   b.ReaderQuotas.MaxArrayLength = 2000000; 
 
                   //Specify the name of the signature field 
                   string fieldName = "form1[0].grantApplication[0].page1[0].SignatureField1[0]"; 
 
                   //Create a Credential object 
                   Credential myCred = new Credential(); 
                   myCred.alias = "secure"; 
 
                   //Specify the reason to sign the document 
                   string reason = "The document was reviewed"; 
 
                   //Specify the location of the signer 
                   string location = "New York HQ"; 
 
                   //Specify contact information 
                   string contactInfo = "Tony Blue"; 
 
                   //Create a PDFSignatureAppearanceOptions object  
                   //and show date information 
                   PDFSignatureAppearanceOptionSpec appear = new PDFSignatureAppearanceOptionSpec(); 
                   appear.showDate = true; 
 
                   //Sign the PDF document 
                   SignInteractiveForm.ServiceReference1.BLOB signedDoc = signatureClient.sign( 
                       inDoc, 
                       fieldName, 
                       myCred, 
                       HashAlgorithm.SHA1, 
                       reason, 
                       location, 
                       contactInfo, 
                       appear, 
                       true, 
                       null, 
                       null, 
                       null); 
 
                   //Populate a byte array with BLOB data that represents the signed form 
                   byte[] outByteArray = signedDoc.MTOM; 
 
                   //Save the signed PDF document 
                   string fileName = "C:\\Adobe\LoanXFASigned.pdf"; 
                   FileStream fs2 = new FileStream(fileName, FileMode.OpenOrCreate); 
 
                   //Create a BinaryWriter object 
                   BinaryWriter w = new BinaryWriter(fs2); 
                   w.Write(outByteArray); 
                   w.Close(); 
                   fs2.Close(); 
               } 
 
               catch (Exception ee) 
               { 
                   Console.WriteLine(ee.Message); 
               } 
           } 
       } 
} 
 

Services starting with the letter I produce invalid proxy files

The name of some LiveCycle generated proxy classes are incorrect when using Microsoft .Net 3.5 and WCF. This issue occurs when proxy classes are created for the IBMFilenetContentRepositoryConnector, IDPSchedulerService or any other service whose name starts with the letter I. For example, the name of the generated client in case of IBMFileNetContentRepositoryConnector is BMFileNetContentRepositoryConnectorClient. The letter I is missing in the generated proxy class.