Version 1.1 by smmccraw on 2007/07/08 10:35

Show last authors
1 This documentation was written by Andrew Lindesay (http:~/~/www.lindesay.co.nz) in 2006 as part of supported code in the LEWOStuff framework, but this material has been transcribed here. It was written around the time of WebObjects 5.2 and 5.3 on the 1.4 JVM.
2
3 AXIS provides a number of handlers for ultimately executing the WS. This generally works in the WebObjects environment out of the box. However, in the case of a servlet deployment, the URLs are manipulated by the servlet container so they look something like this.
4
5 {{panel}}
6
7 ...ects/FOO.woa/ws/FooService<font color="red">;jsessionid=abc.i1</font>?wsdl
8
9 {{/panel}}
10
11 If a client starts a session on a WS invocation then you want all subsequent requests to return to this same servlet container (Here we assume a redundant deployment where there are a number of servlet containers.) where the session resides. However the servlet-container's HTTP adaptor typically only knows this by looking at the modified URL. Unfortunately, the default WSDL generated by AXIS would have a section like this.
12
13 {{code}}
14 ...
15 <wsdl:service name="FooService">
16 {panel}
17 <wsdl:port name="FooService" binding="impl:FooService SoapBinding">
18 <wsdlsoap:address location="http://foo.co.nz/FOO/WebObjects/FOO.woa/ws/FooService"/>
19 </wsdl:port>
20 {panel}
21 </wsdl:service>
22 ...
23
24 {{/code}}
25
26 A WSDL like this does not contain the modified URL caused by the context having a session in the location for the service. The example handler //LEWOWebServicesWSDLLocationHandler// below which is supplied in LEWOStuff will correct the location supplied in the WSDL to contain the session information. To install this handler for use in WebObjects, locate the //server.wsdd// file within your project and modify the following section so that it appears as follows.
27
28 {{code}}
29 ...
30 <transport name="http">
31 {panel}
32 <requestFlow>
33 <handler type="HTTPActionHandler"/>
34 <handler type="URLMapper"/>
35 <handler type="java:nz.co.lindesay.common.webobjects.LEWOWebServicesWSDLLocationHandler"/>
36 </requestFlow>
37 {panel}
38 </transport>
39
40 {{/code}}
41
42 You then need to put the following class into your project.
43
44 {{code}}
45
46 package nz.co.lindesay.common.webobjects;
47
48 /*
49 ------------------------------------------------------------
50 LICENSE
51 ------------------------------------------------------------
52
53 Copyright (c) 2006, Andrew Lindesay
54 All rights reserved.
55
56 Redistribution and use in source and binary forms, with or
57 without modification, are permitted provided that the
58 following conditions are met:
59
60 * Redistributions of source code must retain the above
61 {panel}
62 copyright notice, this list of conditions and the
63 following disclaimer.
64 {panel}
65
66 * Redistributions in binary form must reproduce the above
67 {panel}
68 copyright notice, this list of conditions and the
69 following disclaimer in the documentation and/or other
70 materials provided with the distribution.
71 {panel}
72
73 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
74 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
75 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
76 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
77 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
78 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
79 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
80 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
81 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
82 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
83 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
84 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
85 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
86 SUCH DAMAGE.
87
88 ------------------------------------------------------------
89 */
90
91 import com.webobjects.foundation.*;
92 import com.webobjects.appserver.*;
93
94 import org.apache.axis.*;
95
96 /**
97 {panel}
98 * <P>This class is an AXIS request handler that is designed to
99 * manipulate the outbound WSDL that is generated for a
100 * request. The manipulation undertaken here is to modify the
101 * location of the actual service. The reason for doing this is
102 * that if you have a web service deployed into a servlet
103 * container as a WO application, the session'ed URLs can look
104 * a bit like this.</P>
105 *
106 * <P><TT>http://foo.co.nz/FOO/WebObjects/FOO.woa/ws/FooService;jsessionid=abc.i1?wsdl</TT></P>
107 *
108 * <P>However, once the URL is returned as a location for a service
109 * from AXIS, the session part at the end is removed and if you are
110 * using a multi-container deployment, the subsequent requests will
111 * not arrive at the correct servlet container.</P>
112 *
113 * <P>By installing this AXIS handler, this problem is resolved.
114 * To install it, locate the "<TT>server.wsdd</TT>" file in your
115 * WO project and add the following line to the "<I>requestFlow</I>"
116 * handler list as the last item in the list. This should be the
117 * request flow in the HTTP transport section.</P>
118 *
119 * <P><TT>&lt;handler type="java:nz.co.lindesay.common.webobjects.LEWOWebServicesWSDLLocationHandler"/&gt;</TT></P>
120 *
121 * <P>This should also work with the "<I>wotaskd</I>" deployment
122 * style as well.</P>
123 */
124 {panel}
125
126 public class LEWOWebServicesWSDLLocationHandler extends org.apache.axis.handlers.BasicHandler
127 {
128
129 // --------------------------------------------------------------
130
131 public LEWOWebServicesWSDLLocationHandler() { super(); }
132
133 // --------------------------------------------------------------
134
135 /**
136 {panel}
137 * <P>This is the AXIS hook where we can manipulate the outbound
138 * WSDL.</P>
139 */
140 {panel}
141
142 public void generateWSDL(MessageContext msgContext) throws AxisFault
143 {
144 WOContext context = WOWebServiceUtilities.currentWOContext();
145 WORequest request = context.request();
146 String host = LEWOHelper.getExternalHostnameFromInboundRequest(request);
147 int port = LEWOHelper.getExternalPortFromInboundRequest(request);
148 int appi = request.applicationNumber();
149
150 if((null==host)||(0==host.length()))
151 throw new IllegalStateException("the host cannot be determined from the inbound request.");
152
153 if(context.hasSession())
154 context.session();
155
156 StringBuffer sb = new StringBuffer();
157
158 sb.append("http://");
159 sb.append(host);
160
161 if(-1!=port)
162 {
163 sb.append(":");
164 sb.append(Integer.toString(port));
165 }
166
167 String path = context.urlWithRequestHandlerKey(
168 request.requestHandlerKey(),
169 request.requestHandlerPath(),
170 null);
171
172 // Unless the context has a session, we can't get it to come back
173 // to a specific instance, but in the case of a 'wotaskd' deploy,
174 // there is no way to specify the session for a WSDL request, so
175 // we'll do a nasty hack to make this work.
176
177 if((-1!=appi)&&(!context.hasSession()))
178 {
179 String webServiceRequestHandlerKey = WOApplication.application().webServiceRequestHandlerKey();
180 String startPath = request.adaptorPrefix()+"/"+request.applicationName()+".woa"; // ''/cgi-bin/WebObjects/Foo.woa''
181
182 if(!path.startsWith(startPath))
183 throw new IllegalStateException("The path '"+path+"' should have started with '"+startPath+"'");
184
185 if(path.startsWith(startPath+"/"+webServiceRequestHandlerKey))
186 {
187 StringBuffer pathSB = new StringBuffer();
188
189 pathSB.append(startPath);
190 pathSB.append("/");
191 pathSB.append(Integer.toString(appi));
192 pathSB.append(path.substring(startPath.length()));
193
194 path = pathSB.toString();
195 }
196 }
197
198 sb.append(path);
199
200 msgContext.setProperty(MessageContext.WSDLGEN_SERV_LOC_URL,sb.toString());
201 }
202
203 // --------------------------------------------------------------
204
205 /**
206 {panel}
207 * <P>Basically there is nothing to do here because we are not
208 * interested in messing with the request/response cycle - rather
209 * we want only to manipulate the WSDL.</P>
210 */
211 {panel}
212
213 public void invoke(MessageContext msgContext) throws AxisFault
214 {
215 }
216
217 // --------------------------------------------------------------
218
219 }
220
221 {{/code}}
222
223 Although this is slightly crude, it should produce the correct result in the WSDL.