Last modified by Pascal Robert on 2007/09/03 19:24

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