Wiki source code of WebServices
Hide last authors
1.1 | 1 | = Introduction = | |
2 | |||
3 | The REQUEA Platform is a service oriented platform. Every entity definition can be mapped as a WebService using the SOAP protocol. | ||
4 | |||
5 | Entity Properties become attributes in the Document schema definition. | ||
6 | Operations become SOAP operations. | ||
7 | |||
8 | = Calling REQUEA as a Web Service = | ||
9 | |||
10 | The SOAP Servlet generates automatically WSDL and accept SOAP request over HTTP(s) based on the Entity definition. | ||
11 | |||
12 | The syntax for the WebService servlet is the following: | ||
13 | |||
14 | http://[server]/dysoweb/ws/wsdl.ws?doc=[entity name] | ||
15 | |||
16 | So for example: | ||
17 | |||
18 | http://localhost:8080/dysoweb/ws/wsdl.ws?doc=custTest | ||
19 | |||
20 | |||
21 | == Using Visual Studio 2010 == | ||
22 | |||
23 | You can map automatically the REQUEA Web service as a service reference in Visual Studio: | ||
24 | |||
25 | [[image:img45.png]] | ||
26 | |||
27 | |||
28 | [[image:img46.png||alt="Entering the Web service WSDL URL"]] | ||
29 | |||
30 | |||
31 | [[image:img47.png||alt="Discovering Service Operations"]] | ||
32 | |||
33 | [[image:img48.png]] | ||
34 | |||
35 | |||
1.2 | 36 | ||
37 | === invoking the client === | ||
38 | |||
39 | <?xml version="1.0" encoding="utf-8" ?> | ||
40 | <configuration> | ||
41 | <system.serviceModel> | ||
42 | <bindings> | ||
43 | <basicHttpBinding> | ||
44 | <binding name="Book" closeTimeout="00:01:00" openTimeout="00:01:00" | ||
45 | receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" | ||
46 | bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" | ||
47 | maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" | ||
48 | messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" | ||
49 | useDefaultWebProxy="true"> | ||
50 | <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" | ||
51 | maxBytesPerRead="4096" maxNameTableCharCount="16384" /> | ||
52 | **<security mode="TransportCredentialOnly">** | ||
53 | **~ <transport clientCredentialType="Basic" realm="" />** | ||
54 | **~ </security>** | ||
55 | </binding> | ||
56 | </basicHttpBinding> | ||
57 | </bindings> | ||
58 | <client> | ||
59 | <endpoint address="http://192.168.122.1:8080/dysoweb/ws/soap.ws" | ||
60 | binding="basicHttpBinding" bindingConfiguration="Book" contract="RequeaService.Book" | ||
61 | name="Book" /> | ||
62 | </client> | ||
63 | </system.serviceModel> | ||
64 | </configuration> | ||
65 | |||
66 | |||
67 | |||
68 | |||
69 | |||
70 | |||
71 | |||
72 | |||
1.1 | 73 | = Calling a Web Service in REQUEA = | |
74 | |||
75 | Invoking a Web Service from REQUEA requires that you adapt the semantics of the Web Service and wrap it as a JavaScript Plugin service. | ||
76 | |||
77 | The wrapping code should be written in Java. | ||
78 | |||
79 | There are (at least) two ways to wrap the code and invoke the Web Service: | ||
80 | |||
81 | * using Apache Axis | ||
82 | * using SaaJ and XML | ||
83 | |||
84 | == Using Apache Axis == | ||
85 | |||
86 | Using Apache Axis you can generate Java wrappers around the Web Service and invoke those wrapper from the Java code. | ||
87 | |||
88 | In this example, we will use the ViaMichelin SOAP API. | ||
89 | |||
90 | 1 - Generate the stubs | ||
91 | |||
92 | This is done with the Axis tool WSDL2Java: | ||
93 | |||
94 | {{code language="java"}} | ||
95 | java org.apache.axis.wsdl.WSDL2Java http://www.viamichelin.com/ws/services/Geocoding?wsdl | ||
96 | {{/code}} | ||
97 | |||
98 | |||
99 | This will generate some java classes, that you should include in your plugin project: | ||
100 | |||
101 | com\viamichelin\ws\geo\GeoCoordinates.java | ||
102 | com\viamichelin\ws\localization\Address.java | ||
103 | com\viamichelin\ws\localization\FindLocation.java | ||
104 | com\viamichelin\ws\localization\FindLocations.java | ||
105 | com\viamichelin\ws\localization\GeocodingRequest.java | ||
106 | com\viamichelin\ws\localization\InputAddress.java | ||
107 | com\viamichelin\ws\localization\Location.java | ||
108 | com\viamichelin\ws\localization\Poi.java | ||
109 | com\viamichelin\ws\localization\PoiDatasheet.java | ||
110 | com\viamichelin\ws\localization\PoiDescriptionList.java | ||
111 | com\viamichelin\ws\localization\PoiId.java | ||
112 | com\viamichelin\ws\localization\PoiMetaNumList.java | ||
113 | com\viamichelin\ws\localization\PoiMetaStringList.java | ||
114 | com\viamichelin\ws\localization\service\Geocoding.java | ||
115 | com\viamichelin\ws\localization\service\GeocodingService.java | ||
116 | com\viamichelin\ws\localization\service\GeocodingServiceLocator.java | ||
117 | com\viamichelin\ws\localization\service\GeocodingSoapBindingStub.java | ||
118 | com\viamichelin\ws\object\Integer.java | ||
119 | |||
120 | === Calling the Web Service === | ||
121 | |||
122 | The call is done within the plugin script in a jsFunction_execute for example: | ||
123 | |||
124 | {{code language="java"}} | ||
125 | |||
126 | |||
127 | InputAddress[] addressList = new InputAddress[1]; | ||
128 | addressList[0] = inputAddress; | ||
129 | request.setAddressesList(addressList); | ||
130 | |||
131 | // call the web service | ||
132 | GeocodingServiceLocator locator = new GeocodingServiceLocator(); | ||
133 | Geocoding service = locator.getGeocoding(); | ||
134 | |||
135 | String login = registry.getParam("com.requea.viamichelin.login"); | ||
136 | String passwd = registry.getParam("com.requea.viamichelin.password"); | ||
137 | if(login == null || passwd == null) { | ||
138 | throw new RegistryException("Viamichelin service not properly configured. Missing login or password"); | ||
139 | } | ||
140 | String url = registry.getParam("com.requea.viamichelin.url"); | ||
141 | if(url != null) { | ||
142 | locator.setGeocodingEndpointAddress(url); | ||
143 | } | ||
144 | |||
145 | try { | ||
146 | FoundLocationList result = service.getLocationsList(request, login+"|"+passwd)[0]; | ||
147 | if(result.getFoundLocations().length > 0) { | ||
148 | FoundLocation loc = result.getFoundLocations()[0]; | ||
149 | return new GeocodedLocation(loc.getLocationDesc()); | ||
150 | } else { | ||
151 | // nothing found | ||
152 | return null; | ||
153 | } | ||
154 | } catch(Exception e) { | ||
155 | throw new EndUserException(e); | ||
156 | } | ||
157 | |||
158 | {{/code}} | ||
159 | |||
160 | |||
161 | === Setting up classpath and dependencies === | ||
162 | |||
163 | in your pom.xml, you need to add the axis dependencies for inclusion in your bundle: | ||
164 | |||
165 | {{code language="xml"}} | ||
166 | <dependency> | ||
167 | <groupId>axis</groupId> | ||
168 | <artifactId>axis</artifactId> | ||
169 | <version>1.4</version> | ||
170 | <scope>provided</scope> | ||
171 | </dependency> | ||
172 | {{/code}} | ||
173 | |||
174 | and for the bundle class path: | ||
175 | |||
176 | {{code language="xml"}} | ||
177 | <Bundle-ClassPath> | ||
178 | ., | ||
179 | lib/axis-1.4.jar, | ||
180 | lib/axis-jaxrpc-1.4.jar, | ||
181 | lib/axis-saaj-1.4.jar, | ||
182 | lib/axis-wsdl4j-1.5.1.jar, | ||
183 | lib/commons-discovery-0.2.jar | ||
184 | </Bundle-ClassPath> | ||
185 | {{/code}} | ||
186 | |||
187 | [[Download the complete pom.xml>>attach:pom.xml||title="Download the pom.xml"]] | ||
188 | |||
189 | == Using SAAJ == | ||
190 | |||
191 | Using SAAJ, you can invoke the Web service without having to generate stubs. | ||
192 | |||
193 | It is a lower level protocol, allowing for a finer control of the WebService invokation, at the expense of the simplicity. | ||
194 | |||
195 | Here is a snipet of code that does a SAAJ invokation: | ||
196 | |||
197 | {{code language="java"}} | ||
198 | Thread th = Thread.currentThread(); | ||
199 | ClassLoader cl = th.getContextClassLoader(); | ||
200 | // build a GetList request | ||
201 | try { | ||
202 | th.setContextClassLoader(this.getClass().getClassLoader()); | ||
203 | String userName = registry.getParam("username"); | ||
204 | String password = registry.getParam("password"); | ||
205 | String strURL = registry.getParam("endpoint"); | ||
206 | |||
207 | SOAPConnectionFactory factory = SOAPConnectionFactory.newInstance(); | ||
208 | SOAPConnection connection = factory.createConnection(); | ||
209 | URL endpoint = new URL(strURL); | ||
210 | |||
211 | // this web services requires the SOAPAction. | ||
212 | MessageFactory mf = MessageFactory.newInstance(); | ||
213 | SOAPMessage message = mf.createMessage(); | ||
214 | MimeHeaders hd = message.getMimeHeaders(); | ||
215 | hd.addHeader("SOAPAction", "urn:WS/"+action); | ||
216 | |||
217 | SOAPHeader header = message.getSOAPHeader(); | ||
218 | // adds auth info in the header | ||
219 | Element elAuth = header.getOwnerDocument().createElementNS( | ||
220 | "urn:WS", "AuthenticationInfo"); | ||
221 | elAuth.setAttribute("xlmns", "urn:WS"); | ||
222 | XMLUtils.addElement(elAuth, "userName", userName); | ||
223 | XMLUtils.addElement(elAuth, "password", password); | ||
224 | header.appendChild(elAuth); | ||
225 | |||
226 | // include the request in the body | ||
227 | SOAPBody body = message.getSOAPBody(); | ||
228 | body.appendChild(body.getOwnerDocument().adoptNode( | ||
229 | elRequest.cloneNode(true))); | ||
230 | |||
231 | SOAPMessage response = connection.call(message, endpoint); | ||
232 | // fault? | ||
233 | Element elBody = response.getSOAPBody(); | ||
234 | Element elFault = XMLUtils.getChild(elBody, "Fault"); | ||
235 | if(elFault != null) { | ||
236 | log.severe(XMLUtils.getChildText(elFault, "faultstring")); | ||
237 | throw new EndUserException(XMLUtils.getChildText(elFault, "faultstring")); | ||
238 | |||
239 | } | ||
240 | |||
241 | Element elResp = XMLUtils.getChild(elBody, "urn:WS", respName); | ||
242 | // close the connection | ||
243 | connection.close(); | ||
244 | |||
245 | return elResp; | ||
246 | |||
247 | } catch(Exception e) { | ||
248 | throw new RegistryException(e); | ||
249 | |||
250 | } finally { | ||
251 | th.setContextClassLoader(cl); | ||
252 | } | ||
253 | {{/code}} | ||
254 | |||
255 | |||
256 | Required dependencies in your project: | ||
257 | |||
258 | {{code language="xml"}} | ||
259 | <dependency> | ||
260 | <groupId>javax.xml</groupId> | ||
261 | <artifactId>saaj-api</artifactId> | ||
262 | <version>1.3</version> | ||
263 | </dependency> | ||
264 | <dependency> | ||
265 | <groupId>com.sun.xml.messaging.saaj</groupId> | ||
266 | <artifactId>saaj-impl</artifactId> | ||
267 | <version>1.3</version> | ||
268 | </dependency> | ||
269 | {{/code}} | ||
270 | |||
271 | and the plugin section in the pom.xml | ||
272 | |||
273 | {{code language="xml"}} | ||
274 | <plugin> | ||
275 | <groupId>com.requea.dysoapp</groupId> | ||
276 | <artifactId>maven-dysoapp-bundle</artifactId> | ||
277 | <extensions>true</extensions> | ||
278 | <configuration> | ||
279 | <instructions> | ||
280 | <Bundle-Name>${pom.name}</Bundle-Name> | ||
281 | <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName> | ||
282 | <Export-Package /> | ||
283 | <Import-Package> | ||
284 | org.apache.commons.logging, | ||
285 | org.osgi.framework, | ||
286 | com.requea.app, | ||
287 | com.requea.util, | ||
288 | com.requea.util.xml, | ||
289 | org.w3c.dom, | ||
290 | javax.net.*, | ||
291 | javax.crypto.*, | ||
292 | javax.xml.*, | ||
293 | javax.activation, | ||
294 | org.mozilla.javascript;version=1.7.2, | ||
295 | javax.imageio.*, | ||
296 | org.xml.*, | ||
297 | !org.jvnet.*, | ||
298 | !com.sun.* | ||
299 | </Import-Package> | ||
300 | <Bundle-Activator>com.requea.myplugin.Activator</Bundle-Activator> | ||
301 | <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency> | ||
302 | </instructions> | ||
303 | </configuration> | ||
304 | </plugin> | ||
305 | {{/code}} |