Changes for page Web Services-Problems
Last modified by Francis Labrie on 2007/10/15 16:21
From version 2.1
edited by Pascal Robert
on 2007/09/03 19:32
on 2007/09/03 19:32
Change comment:
There is no comment for this version
To version 4.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
Summary
-
Page properties (3 modified, 0 added, 0 removed)
Details
- Page properties
-
- Title
-
... ... @@ -1,1 +1,1 @@ 1 -Web Services-Problems 1 +Programming__WebObjects-Web Services-Problems - Author
-
... ... @@ -1,1 +1,1 @@ 1 -XWiki. probert1 +XWiki.smmccraw - Content
-
... ... @@ -1,8 +1,8 @@ 1 -= Problems = 1 += Problems = 2 2 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 == 5 +== DirectToWebService can't return a WSDL with secure HTTPS references in it == 6 6 7 7 **Authors:** Francis Labrie 8 8 ... ... @@ -10,51 +10,61 @@ 10 10 11 11 **Bug reference:** rdar:~/~/3546304 12 12 13 -=== Problem: === 13 +=== Problem: === 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 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 generate a correct WSDL. 16 16 17 - {{code}}17 +=== Solution: === 18 18 19 -com.webobjects. appserver.WOWebServiceRegistrar19 +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 20 21 -{{ /code}}21 +{{panel}} 22 22 23 - classseems to generate acorrect WSDL.23 + {code} 24 24 25 - === Solution: ===25 +{{/panel}} 26 26 27 - Darel Lee from Appletold me thatright now, the dynamic WSDL generationis not exposed to developers so there currently isn'taclean solutionto perform this. One workaroundis to hardcode rules(ofcom.webobjects.directtoweb.Assignment type) with the serviceLocationURL key foreach operation that you want to use secureHTTPSreferences. For instance:27 +((operationName="anOperation") and (serviceName="Service")) -> 28 28 29 +{{panel}} 30 + 31 + serviceLocationURL="https://host.net/cgi-bin/Service.woa/ws/Service" 32 + 33 +{{/panel}} 34 + 29 29 {{code}} 30 30 31 -((operationName="anOperation") and (serviceName="Service")) -> 32 - serviceLocationURL="https://host.net/cgi-bin/Service.woa/ws/Service" 33 33 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 + 34 34 {{/code}} 35 35 36 -If you need all operation to be called using the secure protocol, you can also define a more generic rule like this one: 43 +(serviceName="Service") -> 44 + serviceLocationURL="https:~/~/host.net/cgi-bin/Service.woa/ws/Service" 37 37 38 38 {{code}} 39 39 40 -(serviceName="Service") -> 41 - serviceLocationURL="https://host.net/cgi-bin/Service.woa/ws/Service" 42 42 49 +h2. SOAP serializers and deserializers registered with 43 43 {{/code}} 44 44 45 -=== SOAP serializers and deserializers registered with WOWebServiceRegistrar class doesn't appear in the WSDL schema === 52 +WOWebServiceRegistrar{{code}} class doesn't appear in the WSDL schema 53 + *Authors:* Francis Labrie 46 46 47 -Authors:Francis Labrie 48 -Affected products:WebObjects5.2.x, 5.3.x 49 -Bug reference:rdar:~/~/3546330 55 + *Affected products:* _WebObjects_ 5.2.x, 5.3.x 50 50 51 - ====Problem:====57 + *Bug reference:* rdar://3546330 52 52 53 -Custom SOAP serializers and deserializers registered to Web Services with com.webobjects.appserver.WOWebServiceRegistrar class are never added to the types / schema definition of the WSDL. The only type definitions shown are the following: 54 54 55 -{{code}} 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: 56 56 57 -<types> 63 +{{/code}} 64 + 65 +{{panel}} 66 + 67 + <types> 58 58 <schema targetNamespace="http://lang.java/" xmlns:soapenc= 59 59 "http://schemas.xmlsoap.org/soap/encoding/" xmlns= 60 60 "http://www.w3.org/2001/XMLSchema"> ... ... @@ -70,7 +70,7 @@ 70 70 </complexContent> 71 71 </complexType> 72 72 <element name="ArrayOf_xsd_any" nillable="true" type= 73 - "lang:ArrayOf_xsd_any"/> 83 + "lang:ArrayOf_xsd_any"/> 74 74 </schema> 75 75 <schema targetNamespace="http://www.apple.com/webobjects/ 76 76 webservices/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/ ... ... @@ -79,7 +79,7 @@ 79 79 <element name="entityName" type="xsd:string"/> 80 80 <element name="primaryKeys" type="lang:ArrayOf_xsd_any"/> 81 81 </complexType> 82 - <element name="EOGlobalID" type="tns:EOGlobalID"/> 92 + <element name="EOGlobalID" type="tns:EOGlobalID"/> 83 83 <complexType name="EOEnterpriseObject"> 84 84 <element name="entityName" type="xsd:string"/> 85 85 <element name="globalID" type="webobjects:EOGlobalID"/> ... ... @@ -88,137 +88,153 @@ 88 88 </schema> 89 89 </types> 90 90 91 -{{/ code}}101 +{{/panel}} 92 92 93 - ==== Solution: ====103 +{{code}} 94 94 105 + 106 +h3. Solution: 95 95 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... 96 96 97 -=== DirectToWebService can't return a WSDL with custom namespace and definitions name in it === 109 +h2. DirectToWebService can't return a WSDL with custom namespace and definitions name in it 110 + *Authors:* Francis Labrie 98 98 99 -Authors:Francis Labrie 100 -Affected products:WebObjects5.2.x, 5.3.x 101 -Bug reference: 112 + *Affected products:* _WebObjects_ 5.2.x, 5.3.x 102 102 103 - ====Problem:====114 + *Bug reference:* 104 104 105 -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. 106 106 107 -==== Solution: ==== 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. 108 108 109 -Base on a tips from Darel Lee, I've found in the com.webobjects.webservices.generation.//private.WOWSDLTemplate class some extras key definitions read from the user.d2wmodel DirectToWebService rule file. For instance~:// 120 +h3. Solution: 121 +Base on a tips from Darel Lee, I've found in the 122 +{{/code}} 110 110 111 -* **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; 112 -* **WSDLDefinitionName:** a key that allow the definitions name change. So instead of having "ServiceNameDefinition", you can set this value; 113 -* **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. 124 +com.webobjects.webservices.generation.//private.WOWSDLTemplate{{code}} class some extras key definitions read from the user.d2wmodel DirectToWebService rule file. For instance: 114 114 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 + 115 115 Here is an example of rule definition changing the above values: 116 116 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 + 117 117 {{code}} 118 118 119 -(se(serviceName="Service") -> 120 - WSDLTargetNamespace="https://host.net/cgi-bin/Service.woa/ws/Service" 121 -(serviceName="Service") -> 122 - WSDLDefinitionName="AnotherDefinition" 123 -((operationName="anOperation") and (serviceName="Service")) -> 124 - serviceLocationURL="https://host.net/cgi-bin/Service.woa/ws/Service" 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 125 125 126 - {{/code}}145 + *Affected products:* _WebObjects_ 5.2.x, 5.3.x 127 127 128 - ===WOWebServiceClientclass can't connectto a server thatrequires an authentication (WO 5.2.x, Bug ID3568441) ===147 + *Bug reference:* rdar://3568441 129 129 130 -Authors:Francis Labrie 131 -Affected products:WebObjects5.2.x, 5.3.x 132 -Bug reference:rdar:~/~/3568441 133 133 134 -==== Problem: ==== 150 +h3. Problem: 151 +The 152 +{{/code}} 135 135 136 - Thecom.webobjects.webservices.client.WOWebServiceClientclass 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 setSecurityDelegateForServiceNamed(Object, String) instance method).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). 137 137 138 -Normally, the processClientRequest(MessageContext) delegate method (see com.webobjects.webservices.support.WOSecurityDelegateinterface 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 WOWebServiceClientclass 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... 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... 139 139 140 -==== Solution: ==== 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... 141 141 142 - The best would betoadda default method to WOWebServiceClientclass toregister a default security delegate that isnot relatedto a service name before the classfetch the WSDL. But unfortunately, all key methodshat would allowthis kind of behavior change areprivates, soubclassing is not a solution...161 +But a workaround is still possible: 143 143 144 -But a workaround is still possible: 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; 145 145 146 -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 java.net.URLConnection yourself; 147 -1. Instanciate another java.net.URL class that refer to the local WSDL document file; 148 -1. Instanciate the com.webobjects.webservices.client.WOWebServiceClient<>code> class using the file URL; 149 149 1. Set for each service a security delegate that will add the proper credential information for the Basic HTTP Authentication. 150 150 151 151 That's it. It looks like a big hack, but it works... 152 152 153 -=== Web Services can't return a WSDL with secure HTTPS references specifying port other than the default 443 === 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> 154 154 155 -Authors:Francis Labrie 156 -Affected products:WebObjects5.2.x, 5.3.x 157 -Bug reference:rdar:~/~/4196417 158 - 159 -==== Problem: ==== 160 - 176 +~==== Problem: ==== 161 161 HTTPS protocol references can be published in Web Services WSDL. But unfortunately, WebObjects seems to ignore ports other than the default 443. 162 162 163 -This problem is related to the bad waycom.webobjects.appserver.WORequestbuild the URL prefix: if the protocol is secure and no port (i.e. 0) is set when calling the//completeURLPrefix(StringBuffer,boolean,int)method, the port will always be 443. Unfortunately, Web Servicescom.webobjects.appserver.//private.WOWebServiceclass seems to call this method without setting the port number. 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. 164 164 165 -==== Solution: ==== 181 +h3. Solution: 182 +To work around this bug, you can subclass the {{/code}}com.webobjects.appserver.WORequest{{code}} class like this: 166 166 167 -To work around this bug, you can subclass the com.webobjects.appserver.WORequest class like this: 184 +{{/code}} 185 +package com.smoguli.appserver; 168 168 169 -{{code}} 170 - 171 - package com.smoguli.appserver; 172 - 173 173 import com.webobjects.appserver.WORequest; 174 174 import com.webobjects.foundation.NSData; 175 175 import com.webobjects.foundation.NSDictionary; 176 176 177 -/** 191 +/ 192 + 193 +{{panel}} 194 + 178 178 * This class provide fixed {@link com.webobjects.appserver.WORequest} methods. 179 179 * To use it, just overload the {@link com.webobjects.appserver.WOApplication. 180 - * createRequest(String,String,String,NSDictionary,NSData,NSDictionary)} method 197 + * createRequest(String,String,String,NSDictionary,NSData,NSDictionary)} method 181 181 * to instanciate this class instead. 182 182 * 183 - * @author 200 + * @author Francis Labrie <francis.labrie at smoguli.com> 184 184 */ 202 + 203 +{{/panel}} 204 + 185 185 public class WOFixedRequest extends WORequest { 186 186 187 - /** 188 - * @see com.webobjects.appserver.WORequest#WORequest(String,String,String, 189 - * NSDictionary,NSData,NSDictionary) 190 - */ 191 - public WOFixedRequest(String method, String url, String httpVersion, NSDictionary headers, NSData content, NSDictionary info) { 192 - super(method, url, httpVersion, headers, content, info); 193 - } // WOFixedRequest 207 + / 194 194 195 - /** 196 - * This method builds the URL prefix into the <code>urlPrefix</code> buffer 197 - * with the appropriate protocol (<code>http</code> or <code>https</code>) 198 - * and the right TCP port. But unlike the {@link com.webobjects.appserver. 199 - * WORequest#_completeURLPrefix(StringBuffer,boolean,int} method, it 200 - * supports secure HTTP protocol (<code>https</code>) with port other than 201 - * <code>443</code>, even if the <code>port</code> parameter is set 202 - * <code>0</code>. 203 - * 204 - * @param urlPrefix the buffer that receives the contructed URL. 205 - * @param isSecure a flag indicating if the protocol is secure. 206 - * @param port the port number. 207 - */ 208 - public void _completeURLPrefix(StringBuffer urlPrefix, boolean isSecure, int port) { 209 - if(isSecure && (port == 0)) { 210 - String serverPort; 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** 211 211 212 - serverPort = _serverPort(); 213 - if((serverPort != null) && !serverPort.equals("443")) { 214 - try { 215 - port = Integer.parseInt(serverPort); 216 - } catch(NumberFormatException exception) {} // catch 217 - } // if 218 - } // if 216 + / 219 219 220 - super._completeURLPrefix(urlPrefix, isSecure, port); 221 - } // _completeURLPrefix 222 -} // WOFixedRequest 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;//** 223 223 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 224 224 {{/code}}