Version 4.1 by smmccraw on 2007/07/08 09:46

Hide last authors
smmccraw 4.1 1 = Problems =
Pascal Robert 2.1 2
3 This section describes some problems and bugs that sometimes occur when using //WebObjects Web Services//.
4
smmccraw 4.1 5 == DirectToWebService can't return a WSDL with secure HTTPS references in it ==
Pascal Robert 2.1 6
7 **Authors:** Francis Labrie
8
9 **Affected products:** //WebObjects// 5.2.x, 5.3.x
10
11 **Bug reference:** rdar:~/~/3546304
12
smmccraw 4.1 13 === Problem: ===
Pascal Robert 2.1 14
smmccraw 4.1 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.
Pascal Robert 2.1 16
smmccraw 4.1 17 === Solution: ===
Pascal Robert 2.1 18
smmccraw 4.1 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:
Pascal Robert 2.1 20
smmccraw 4.1 21 {{panel}}
Pascal Robert 2.1 22
smmccraw 4.1 23 {code}
Pascal Robert 2.1 24
smmccraw 4.1 25 {{/panel}}
Pascal Robert 2.1 26
smmccraw 4.1 27 ((operationName="anOperation") and (serviceName="Service")) ->
Pascal Robert 2.1 28
smmccraw 4.1 29 {{panel}}
30
31 serviceLocationURL="https://host.net/cgi-bin/Service.woa/ws/Service"
32
33 {{/panel}}
34
Pascal Robert 2.1 35 {{code}}
36
37
smmccraw 4.1 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
Pascal Robert 2.1 41 {{/code}}
42
smmccraw 4.1 43 (serviceName="Service") ->
44 serviceLocationURL="https:~/~/host.net/cgi-bin/Service.woa/ws/Service"
Pascal Robert 2.1 45
46 {{code}}
47
48
smmccraw 4.1 49 h2. SOAP serializers and deserializers registered with
Pascal Robert 2.1 50 {{/code}}
51
smmccraw 4.1 52 WOWebServiceRegistrar{{code}} class doesn't appear in the WSDL schema
53 *Authors:* Francis Labrie
Pascal Robert 2.1 54
smmccraw 4.1 55 *Affected products:* _WebObjects_ 5.2.x, 5.3.x
Pascal Robert 2.1 56
smmccraw 4.1 57 *Bug reference:* rdar://3546330
Pascal Robert 2.1 58
59
smmccraw 4.1 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:
Pascal Robert 2.1 62
smmccraw 4.1 63 {{/code}}
64
65 {{panel}}
66
67 <types>
Pascal Robert 2.1 68 <schema targetNamespace="http://lang.java/" xmlns:soapenc=
69 "http://schemas.xmlsoap.org/soap/encoding/" xmlns=
70 "http://www.w3.org/2001/XMLSchema">
71 <complexType name="Class">
72 <sequence/>
73 </complexType>
74 <complexType name="ArrayOf_xsd_any">
75 <complexContent>
76 <restriction base="soapenc:Array">
77 <attribute ref="soapenc:arrayType" wsdl:arrayType=
78 "xsd:any[]"/>
79 </restriction>
80 </complexContent>
81 </complexType>
82 <element name="ArrayOf_xsd_any" nillable="true" type=
smmccraw 4.1 83 "lang:ArrayOf_xsd_any"/>
Pascal Robert 2.1 84 </schema>
85 <schema targetNamespace="http://www.apple.com/webobjects/
86 webservices/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/
87 soap/encoding/" xmlns="http://www.w3.org/2001/XMLSchema">
88 <complexType name="EOGlobalID">
89 <element name="entityName" type="xsd:string"/>
90 <element name="primaryKeys" type="lang:ArrayOf_xsd_any"/>
91 </complexType>
smmccraw 4.1 92 <element name="EOGlobalID" type="tns:EOGlobalID"/>
Pascal Robert 2.1 93 <complexType name="EOEnterpriseObject">
94 <element name="entityName" type="xsd:string"/>
95 <element name="globalID" type="webobjects:EOGlobalID"/>
96 <element name="properties" type="soapenc:Struct"/>
97 </complexType>
98 </schema>
99 </types>
100
smmccraw 4.1 101 {{/panel}}
Pascal Robert 2.1 102
smmccraw 4.1 103 {{code}}
Pascal Robert 2.1 104
smmccraw 4.1 105
106 h3. Solution:
Pascal Robert 2.1 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...
108
smmccraw 4.1 109 h2. DirectToWebService can't return a WSDL with custom namespace and definitions name in it
110 *Authors:* Francis Labrie
Pascal Robert 2.1 111
smmccraw 4.1 112 *Affected products:* _WebObjects_ 5.2.x, 5.3.x
Pascal Robert 2.1 113
smmccraw 4.1 114 *Bug reference:*
Pascal Robert 2.1 115
116
smmccraw 4.1 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.
Pascal Robert 2.1 119
smmccraw 4.1 120 h3. Solution:
121 Base on a tips from Darel Lee, I've found in the
122 {{/code}}
Pascal Robert 2.1 123
smmccraw 4.1 124 com.webobjects.webservices.generation.//private.WOWSDLTemplate{{code}} class some extras key definitions read from the user.d2wmodel DirectToWebService rule file. For instance:
Pascal Robert 2.1 125
smmccraw 4.1 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
Pascal Robert 2.1 130 Here is an example of rule definition changing the above values:
131
smmccraw 4.1 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
Pascal Robert 2.1 140 {{code}}
141
smmccraw 4.1 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
Pascal Robert 2.1 144
smmccraw 4.1 145 *Affected products:* _WebObjects_ 5.2.x, 5.3.x
Pascal Robert 2.1 146
smmccraw 4.1 147 *Bug reference:* rdar://3568441
Pascal Robert 2.1 148
149
smmccraw 4.1 150 h3. Problem:
151 The
152 {{/code}}
Pascal Robert 2.1 153
smmccraw 4.1 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).
Pascal Robert 2.1 155
smmccraw 4.1 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...
Pascal Robert 2.1 157
smmccraw 4.1 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...
Pascal Robert 2.1 160
smmccraw 4.1 161 But a workaround is still possible:
Pascal Robert 2.1 162
smmccraw 4.1 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;
Pascal Robert 2.1 166
167 1. Set for each service a security delegate that will add the proper credential information for the Basic HTTP Authentication.
168
169 That's it. It looks like a big hack, but it works...
170
smmccraw 4.1 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>
Pascal Robert 2.1 175
smmccraw 4.1 176 ~==== Problem: ====
Pascal Robert 2.1 177 HTTPS protocol references can be published in Web Services WSDL. But unfortunately, WebObjects seems to ignore ports other than the default 443.
178
smmccraw 4.1 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.
Pascal Robert 2.1 180
smmccraw 4.1 181 h3. Solution:
182 To work around this bug, you can subclass the {{/code}}com.webobjects.appserver.WORequest{{code}} class like this:
Pascal Robert 2.1 183
smmccraw 4.1 184 {{/code}}
185 package com.smoguli.appserver;
Pascal Robert 2.1 186
187 import com.webobjects.appserver.WORequest;
188 import com.webobjects.foundation.NSData;
189 import com.webobjects.foundation.NSDictionary;
190
smmccraw 4.1 191 /
192
193 {{panel}}
194
Pascal Robert 2.1 195 * This class provide fixed {@link com.webobjects.appserver.WORequest} methods.
196 * To use it, just overload the {@link com.webobjects.appserver.WOApplication.
smmccraw 4.1 197 * createRequest(String,String,String,NSDictionary,NSData,NSDictionary)} method
Pascal Robert 2.1 198 * to instanciate this class instead.
199 *
smmccraw 4.1 200 * @author Francis Labrie <francis.labrie at smoguli.com>
Pascal Robert 2.1 201 */
smmccraw 4.1 202
203 {{/panel}}
204
Pascal Robert 2.1 205 public class WOFixedRequest extends WORequest {
206
smmccraw 4.1 207 /
Pascal Robert 2.1 208
smmccraw 4.1 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**
Pascal Robert 2.1 215
smmccraw 4.1 216 /
Pascal Robert 2.1 217
smmccraw 4.1 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;//**
Pascal Robert 2.1 233
smmccraw 4.1 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
Pascal Robert 2.1 250 {{/code}}