Changes for page Web Services-Problems
Last modified by Francis Labrie on 2007/10/15 16:21
From version 5.1
edited by smmccraw
on 2007/07/08 09:46
on 2007/07/08 09:46
Change comment:
There is no comment for this version
To version 9.1
edited by Francis Labrie
on 2007/10/15 16:21
on 2007/10/15 16:21
Change comment:
There is no comment for this version
Summary
-
Page properties (3 modified, 0 added, 0 removed)
Details
- Page properties
-
- Title
-
... ... @@ -1,1 +1,1 @@ 1 - Programming__WebObjects-WebServices-Problems1 +Web Services-Problems - Author
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki. smmccraw1 +XWiki.flabrie - Content
-
... ... @@ -1,70 +1,64 @@ 1 -= Problems = 1 +|=((( 2 +Contents 3 +))) 4 +|((( 5 +{{section}} 6 +1. [[#Problems>>doc:||anchor="Problems"]] 7 +11. [[#DirectToWebService can't return a WSDL with secure HTTPS references in it>>doc:||anchor="DirectToWebService can't return a WSDL with secure HTTPS references in it"]] 8 +11. [[#SOAP serializers and deserializers registered with ~~{~~{WOWebServiceRegistrar}} class doesn't appear in the WSDL schema>>doc:||anchor="SOAP serializers and deserializers registered with {{WOWebServiceRegistrar}} class doesn't appear in the WSDL schema"]] 9 +11. [[#DirectToWebService can't return a WSDL with custom namespace and definitions name in it>>doc:||anchor="DirectToWebService can't return a WSDL with custom namespace and definitions name in it"]] 10 +11. [[#WOWebServiceClient class can't connect to a server that requires an authentication>>doc:||anchor="WOWebServiceClient class can't connect to a server that requires an authentication"]] 11 +11. [[#Web Services can't return a WSDL with secure HTTPS references specifying port other than the default 443>>doc:||anchor="Web Services can't return a WSDL with secure HTTPS references specifying port other than the default 443"]] 12 +{{/section}} 13 +))) 2 2 15 += Problems = 16 + 3 3 This section describes some problems and bugs that sometimes occur when using //WebObjects Web Services//. 4 4 5 -== DirectToWebService can't return a WSDL with secure HTTPS references in it 19 +== DirectToWebService can't return a WSDL with secure HTTPS references in it == 6 6 7 - **Authors:** Francis Labrie 8 - 21 +**Authors:** Francis Labrie 9 9 **Affected products:** //WebObjects// 5.2.x, 5.3.x 23 + **Bug reference:** [[rdar:~~/~~/3546304>>url:rdar://3546304||shape="rect"]] 10 10 11 - **Bugreference:**rdar:~/~/354630425 +=== Problem: === 12 12 13 - ===Problem: ===27 +A //DirectToWebService// defined Web Services doesn't return correct WSDL document, even if the correct procedure (see [[doc:WO.Secure Web Services]]) is followed. So only classes oriented Web Services manually registered with the {{code language="none"}}com.webobjects.appserver.WOWebServiceRegistrar{{/code}} class seems to generate a correct WSDL. 14 14 15 - A//DirectToWebService// defined Web Services doesn't return correct WSDL document, even if the correct procedure (see Secure Web Services) is followed. So only classes oriented Web Services manually registered with the {{code}}com.webobjects.appserver.WOWebServiceRegistrar{{/code}} class seems to generatea correct WSDL.29 +=== Solution: === 16 16 17 - ===Solution:===31 +Darel Lee from Apple told me that right now, the dynamic WSDL generation is not exposed to developers so there currently isn't a clean solution to perform this. One workaround is to hardcode rules (of {{code language="none"}}com.webobjects.directtoweb.Assignment{{/code}} type) with the {{code language="none"}}serviceLocationURL{{/code}} key for each operation that you want to use secure HTTPS references. For instance: 18 18 19 -Darel Lee from Apple told me that right now, the dynamic WSDL generation is not exposed to developers so there currently isn't a clean solution to perform this. One workaround is to hardcode rules (of {{code}}com.webobjects.directtoweb.Assignment{{/code}} type) with the {{code}}serviceLocationURL{{/code}} key for each operation that you want to use secure HTTPS references. For instance: 20 - 21 -{{panel}} 22 - 23 - {code} 24 - 25 -{{/panel}} 26 - 27 -((operationName="anOperation") and (serviceName="Service")) -> 28 - 29 -{{panel}} 30 - 31 - serviceLocationURL="https://host.net/cgi-bin/Service.woa/ws/Service" 32 - 33 -{{/panel}} 34 - 35 35 {{code}} 36 36 35 +((operationName="anOperation") and (serviceName="Service")) -> 36 + serviceLocationURL="https://host.net/cgi-bin/Service.woa/ws/Service" 37 37 38 -If you need all operation to be called using the secure protocol, you can also define a more generic rule like this one: 39 - 40 - 41 41 {{/code}} 42 42 43 -(serviceName="Service") -> 44 - serviceLocationURL="https:~/~/host.net/cgi-bin/Service.woa/ws/Service" 40 +If you need all operation to be called using the secure protocol, you can also define a more generic rule like this one: 45 45 46 46 {{code}} 47 47 44 +(serviceName="Service") -> 45 + serviceLocationURL="https://host.net/cgi-bin/Service.woa/ws/Service" 48 48 49 -h2. SOAP serializers and deserializers registered with 50 50 {{/code}} 51 51 52 -WOWebServiceRegistrar{{code}} class doesn't appear in the WSDL schema 53 - *Authors:* Francis Labrie 49 +== SOAP serializers and deserializers registered with {{code language="none"}}WOWebServiceRegistrar{{/code}} class doesn't appear in the WSDL schema == 54 54 55 - *Affected products:* _WebObjects_ 5.2.x, 5.3.x 51 +**Authors:** Francis Labrie 52 + **Affected products:** //WebObjects// 5.2.x, 5.3.x 53 + **Bug reference:** [[rdar:~~/~~/3546330>>url:rdar://3546330||shape="rect"]] 56 56 57 - *Bugreference:*rdar://354633055 +=== Problem: === 58 58 57 +Custom SOAP serializers and deserializers registered to Web Services with {{code language="none"}}com.webobjects.appserver.WOWebServiceRegistrar{{/code}} class are never added to the types / schema definition of the WSDL. The only type definitions shown are the following: 59 59 60 -h3. Problem: 61 -Custom SOAP serializers and deserializers registered to Web Services with {{/code}}com.webobjects.appserver.WOWebServiceRegistrar{{code}} class are never added to the types / schema definition of the WSDL. The only type definitions shown are the following: 59 +{{code}} 62 62 63 -{{/code}} 64 - 65 -{{panel}} 66 - 67 - <types> 61 +<types> 68 68 <schema targetNamespace="http://lang.java/" xmlns:soapenc= 69 69 "http://schemas.xmlsoap.org/soap/encoding/" xmlns= 70 70 "http://www.w3.org/2001/XMLSchema"> ... ... @@ -80,7 +80,7 @@ 80 80 </complexContent> 81 81 </complexType> 82 82 <element name="ArrayOf_xsd_any" nillable="true" type= 83 - "lang:ArrayOf_xsd_any"/> 77 + "lang:ArrayOf_xsd_any"/> 84 84 </schema> 85 85 <schema targetNamespace="http://www.apple.com/webobjects/ 86 86 webservices/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/ ... ... @@ -89,7 +89,7 @@ 89 89 <element name="entityName" type="xsd:string"/> 90 90 <element name="primaryKeys" type="lang:ArrayOf_xsd_any"/> 91 91 </complexType> 92 - <element name="EOGlobalID" type="tns:EOGlobalID"/> 86 + <element name="EOGlobalID" type="tns:EOGlobalID"/> 93 93 <complexType name="EOEnterpriseObject"> 94 94 <element name="entityName" type="xsd:string"/> 95 95 <element name="globalID" type="webobjects:EOGlobalID"/> ... ... @@ -98,90 +98,102 @@ 98 98 </schema> 99 99 </types> 100 100 101 -{{/ panel}}95 +{{/code}} 102 102 97 +=== Solution: === 98 + 99 +You must know that all complexe data types referred in operations will be added to the WSDL types definition. But if a complexe type makes references to others complexe types, you should make sure you add proper calls in the {{code language="none"}}writeSchema(Types){{/code}} method of the class serializer. For example: 100 + 103 103 {{code}} 104 104 103 +public boolean writeSchema(Types types) 104 +throws Exception { 105 + ... 106 + // Add type for Foo 107 + String prefixedName = types.writeType(Foo.class, _FooQName); 108 + ... 105 105 106 - h3. Solution:107 - I don't know any dynamic workaround right now... But a static and complete WSDL can be shared through a direct action. It's not very handy though...110 + return true; 111 +} 108 108 109 -h2. DirectToWebService can't return a WSDL with custom namespace and definitions name in it 110 - *Authors:* Francis Labrie 113 +{{/code}} 111 111 112 - *Affectedproducts:*_WebObjects_5.2.x,5.3.x115 +Unfortunately, I don't know a dynamic workaround for all possible cases right now. At least a static and complete WSDL can be shared through a direct action, but it's not very handy though... 113 113 114 - *Bugreference:*117 +== DirectToWebService can't return a WSDL with custom namespace and definitions name in it == 115 115 119 +**Authors:** Francis Labrie 120 + **Affected products:** //WebObjects// 5.2.x, 5.3.x 121 + **Bug reference:** 116 116 117 -h3. Problem: 118 -A _DirectToWebService_ defined Web Services can't return a WSDL with custom values for properties like namespaces and definitions name. Worse, the generated namespace can even contains WebObjects application instance number or the wrong hostname. 123 +=== Problem: === 119 119 120 -h3. Solution: 121 -Base on a tips from Darel Lee, I've found in the 122 -{{/code}} 125 +A //DirectToWebService// defined Web Services can't return a WSDL with custom values for properties like namespaces and definitions name. Worse, the generated namespace can even contains WebObjects application instance number or the wrong hostname. 123 123 124 - com.webobjects.webservices.generation.//private.WOWSDLTemplate{{code}} class some extras key definitions read from theuser.d2wmodel DirectToWebService rule file. For instance:127 +=== Solution: === 125 125 126 -* *serviceLocationURL:* a key that allow the setting of the location URL for an operation. This is usefull if you need your WebServices to be reached using a secure HTTPS reference; 127 -* *WSDLDefinitionName:* a key that allow the definitions name change. So instead of having "ServiceNameDefinition", you can set this value; 128 -* *WSDLTargetNamespace:* a key that allow the namespace change. This is the most usefull: you can avoid dynamic generation depending on WebObjects HTTP Adaptor? with this. 129 +Base on a tips from Darel Lee, I've found in the {{code language="none"}}com.webobjects.webservices.generation._private.WOWSDLTemplate{{/code}} class some extras key definitions read from the {{code language="none"}}user.d2wmodel{{/code}} //DirectToWebService// rule file. For instance: 129 129 131 +* **serviceLocationURL:** a key that allow the setting of the location URL for an operation. This is usefull if you need your WebServices to be reached using a secure HTTPS reference; 132 +* **WSDLDefinitionName:** a key that allow the definitions name change. So instead of having "ServiceNameDefinition", you can set this value; 133 +* **WSDLTargetNamespace:** a key that allow the namespace change. This is the most usefull: you can avoid dynamic generation depending on WebObjects HTTP Adaptor with this. 134 + 130 130 Here is an example of rule definition changing the above values: 131 131 132 -{{/code}} 133 -(serviceName="Service") -> 134 - WSDLTargetNamespace="https:~/~/host.net/cgi-bin/Service.woa/ws/Service" 135 -(serviceName="Service") -> 136 - WSDLDefinitionName="AnotherDefinition" 137 -((operationName="anOperation") and (serviceName="Service")) -> 138 - serviceLocationURL="https:~/~/host.net/cgi-bin/Service.woa/ws/Service"// 139 - 140 140 {{code}} 141 141 142 -h2. WOWebServiceClient class can't connect to a server that requires an authentication (WO 5.2.x, Bug ID 3568441) 143 - *Authors:* Francis Labrie 139 +(se(serviceName="Service") -> 140 + WSDLTargetNamespace="https://host.net/cgi-bin/Service.woa/ws/Service" 141 +(serviceName="Service") -> 142 + WSDLDefinitionName="AnotherDefinition" 143 +((operationName="anOperation") and (serviceName="Service")) -> 144 + serviceLocationURL="https://host.net/cgi-bin/Service.woa/ws/Service" 144 144 145 - *Affected products:* _WebObjects_ 5.2.x, 5.3.x146 +{{/code}} 146 146 147 - *Bug reference:*rdar://3568441148 +== WOWebServiceClient class can't connect to a server that requires an authentication == 148 148 150 +**Authors:** Francis Labrie 151 + **Affected products:** //WebObjects// 5.2.x, 5.3.x 152 + **Bug reference:** [[rdar:~~/~~/3568441>>url:rdar://3568441||shape="rect"]] 149 149 150 -h3. Problem: 151 -The 152 -{{/code}} 154 +=== Problem: === 153 153 154 -com.webobjects.webservices.client.WOWebServiceClient{{code}} class can't connect to a server that requires a Basic HTTP Authentication despite the fact this class offers a way to register a security delegate (see {{ /code}}setSecurityDelegateForServiceNamed(Object, String){{code}} instance method).156 +The {{code language="none"}}com.webobjects.webservices.client.WOWebServiceClient{{/code}} class can't connect to a server that requires a Basic HTTP Authentication despite the fact this class offers a way to register a security delegate (see {{code language="none"}}setSecurityDelegateForServiceNamed(Object, String){{/code}} instance method). 155 155 156 -Normally, the {{ /code}}processClientRequest(MessageContext){{code}} delegate method (see {{/code}}com.webobjects.webservices.support.WOSecurityDelegate{{code}}interface documentation) would allow an easy way to set a username and a password to the message context. But there is a problem related to the design of the class: to register a security delegate, the {{/code}}WOWebServiceClient{{code}} class has to fetch the Web Services Definition Language (WSDL) XML document. But to get access to this WSDL, an authentication header must be set. This is the classic chicken and egg problem...158 +Normally, the {{code language="none"}}processClientRequest(MessageContext){{/code}} delegate method (see {{code language="none"}}com.webobjects.webservices.support.WOSecurityDelegateinterface{{/code}} documentation) would allow an easy way to set a username and a password to the message context. But there is a problem related to the design of the class: to register a security delegate, the {{code language="none"}}WOWebServiceClient{{/code}} class has to fetch the Web Services Definition Language (WSDL) XML document. But to get access to this WSDL, an authentication header must be set. This is the classic chicken and egg problem... 157 157 158 -h3. Solution: 159 -The best would be to add a default method to {{/code}}WOWebServiceClient{{code}} class to register a default security delegate that is not related to a service name before the class fetch the WSDL. But unfortunately, all key methods that would allow this kind of behavior change are privates, so subclassing is not a solution... 160 +=== Solution: === 160 160 161 - But aworkaround is stillpossible:162 +The best would be to add a default method to {{code language="none"}}WOWebServiceClient{{/code}} class to register a default security delegate that is not related to a service name before the class fetch the WSDL. But unfortunately, all key methods that would allow this kind of behavior change are privates, so subclassing is not a solution... 162 162 163 -# Fetch the WSDL document yourself and store it to the local filesystem, using the java.net.URL instance and setting up the Basic HTTP Authentication header field of the {{/code}}java.net.URLConnection{{code}} yourself; 164 -# Instanciate another {{/code}}java.net.URL{{code}} class that refer to the local WSDL document file; 165 -# Instanciate the {{/code}}com.webobjects.webservices.client.WOWebServiceClient<>code> class using the file URL; 164 +But a workaround is still possible: 166 166 166 +1. Fetch the WSDL document yourself and store it to the local filesystem, using the java.net.URL instance and setting up the Basic HTTP Authentication header field of the {{code language="none"}}java.net.URLConnection{{/code}} yourself; 167 +1. Instanciate another {{code language="none"}}java.net.URL{{/code}} class that refer to the local WSDL document file; 168 +1. Instanciate the {{code language="none"}}com.webobjects.webservices.client.WOWebServiceClient{{/code}} class using the file URL; 167 167 1. Set for each service a security delegate that will add the proper credential information for the Basic HTTP Authentication. 168 168 169 169 That's it. It looks like a big hack, but it works... 170 170 171 -~=== Web Services can't return a WSDL with secure HTTPS references specifying port other than the default 443 === 172 -~: '''Authors:''' Francis Labrie<br> 173 -~: '''Affected products:''' ''WebObjects'' 5.2.x, 5.3.x<br> 174 -~: '''Bug reference:''' rdar:~/~/4196417<br> 173 +== Web Services can't return a WSDL with secure HTTPS references specifying port other than the default 443 == 175 175 176 -~==== Problem: ==== 175 +**Authors:** Francis Labrie 176 + **Affected products:** //WebObjects// 5.2.x, 5.3.x 177 + **Bug reference:** [[rdar:~~/~~/4196417>>url:rdar://4196417||shape="rect"]] 178 + 179 +=== Problem: === 180 + 177 177 HTTPS protocol references can be published in Web Services WSDL. But unfortunately, WebObjects seems to ignore ports other than the default 443. 178 178 179 -This problem is related to the bad way <code>com.webobjects.appserver.WORequest{{code}} build the URL prefix: if the protocol is secure and no port (i.e. 0) is set when calling the {{/code}}//completeURLPrefix(StringBuffer,boolean,int){{code}} method, the port will always be 443. Unfortunately, Web Services {{/code}}com.webobjects.appserver.//private.WOWebService{{code}} class seems to call this method without setting the port number.183 +This problem is related to the bad way {{code language="none"}}com.webobjects.appserver.WORequest{{/code}} builds the URL prefix: if the protocol is secure and no port (i.e. 0) is set when calling the {{code language="none"}}_completeURLPrefix(StringBuffer, boolean, int){{/code}} method, the port will always be 443. Unfortunately, Web Services {{code language="none"}}com.webobjects.appserver._private.WOWebService{{/code}} class seems to call this method without setting the port number. 180 180 181 -h3. Solution: 182 -To work around this bug, you can subclass the {{/code}}com.webobjects.appserver.WORequest{{code}} class like this: 185 +=== Solution: === 183 183 184 -{{/code}} 187 +To work around this bug, you can subclass the {{code language="none"}}com.webobjects.appserver.WORequest{{/code}} class like this: 188 + 189 +{{code}} 190 + 185 185 package com.smoguli.appserver; 186 186 187 187 import com.webobjects.appserver.WORequest; ... ... @@ -188,63 +188,51 @@ 188 188 import com.webobjects.foundation.NSData; 189 189 import com.webobjects.foundation.NSDictionary; 190 190 191 -/ 192 - 193 -{{panel}} 194 - 197 +/** 195 195 * This class provide fixed {@link com.webobjects.appserver.WORequest} methods. 196 196 * To use it, just overload the {@link com.webobjects.appserver.WOApplication. 197 - * createRequest(String,String,String,NSDictionary,NSData,NSDictionary)} method 200 + * createRequest(String,String,String,NSDictionary,NSData,NSDictionary)} method 198 198 * to instanciate this class instead. 199 199 * 200 - * @author 203 + * @author Francis Labrie <francis.labrie at smoguli.com> 201 201 */ 202 - 203 -{{/panel}} 204 - 205 205 public class WOFixedRequest extends WORequest { 206 206 207 - / 207 + /** 208 + * @see com.webobjects.appserver.WORequest#WORequest(String,String,String, 209 + * NSDictionary,NSData,NSDictionary) 210 + */ 211 + public WOFixedRequest(String method, String url, String httpVersion, NSDictionary headers, NSData content, NSDictionary info) { 212 + super(method, url, httpVersion, headers, content, info); 213 + } // WOFixedRequest 208 208 209 -* @see com.webobjects.appserver.WORequest#WORequest(String,String,String, 210 -* NSDictionary,NSData,NSDictionary) 211 - **/ 212 - public WOFixedRequest(String method, String url, String httpVersion, NSDictionary headers, NSData content, NSDictionary info) { 213 - super(method, url, httpVersion, headers, content, info); 214 - } ~/~/ WOFixedRequest** 215 + /** 216 + * This method builds the URL prefix into the <code>urlPrefix</code> buffer 217 + * with the appropriate protocol (<code>http</code> or <code>https</code>) 218 + * and the right TCP port. But unlike the {@link com.webobjects.appserver. 219 + * WORequest#_completeURLPrefix(StringBuffer,boolean,int} method, it 220 + * supports secure HTTP protocol (<code>https</code>) with port other than 221 + * <code>443</code>, even if the <code>port</code> parameter is set 222 + * <code>0</code>. 223 + * 224 + * @param urlPrefix the buffer that receives the contructed URL. 225 + * @param isSecure a flag indicating if the protocol is secure. 226 + * @param port the port number. 227 + */ 228 + public void _completeURLPrefix(StringBuffer urlPrefix, boolean isSecure, int port) { 229 + if(isSecure && (port == 0)) { 230 + String serverPort; 215 215 216 - / 232 + serverPort = _serverPort(); 233 + if((serverPort != null) && !serverPort.equals("443")) { 234 + try { 235 + port = Integer.parseInt(serverPort); 236 + } catch(NumberFormatException exception) {} // catch 237 + } // if 238 + } // if 217 217 218 -* This method builds the URL prefix into the <code>urlPrefix</code> buffer 219 -* with the appropriate protocol (<code>http</code> or <code>https</code>) 220 -* and the right TCP port. But unlike the {@link com.webobjects.appserver. 221 -* WORequest#//completeURLPrefix(StringBuffer,boolean,int} method, it // 222 -* supports secure HTTP protocol (<code>https</code>) with port other than 223 -* <code>443</code>, even if the <code>port</code> parameter is set 224 -* <code>0</code>. 225 - 226 -* @param urlPrefix the buffer that receives the contructed URL. 227 -* @param isSecure a flag indicating if the protocol is secure. 228 -* @param port the port number. 229 - **/ 230 - public void //completeURLPrefix(StringBuffer urlPrefix, boolean isSecure, int port) { 231 - if(isSecure && (port == 0)) { 232 - String serverPort;//** 240 + super._completeURLPrefix(urlPrefix, isSecure, port); 241 + } // _completeURLPrefix 242 +} // WOFixedRequest 233 233 234 - serverPort = //serverPort(); 235 - if((serverPort [[image:= null) &&]]serverPort.equals("443")) { 236 - try { 237 - port = Integer.parseInt(serverPort); 238 - } catch(NumberFormatException exception) {} ~/~/ catch 239 - } ~/~/ if 240 - } ~/~/ if// 241 - 242 - super.//completeURLPrefix(urlPrefix, isSecure, port); 243 - } ~/~/ //completeURLPrefix 244 -} ~/~/ WOFixedRequest 245 - 246 -{{code}} 247 - 248 - 249 -Category:WebObjects 250 250 {{/code}}