Invoking the SOAP Web service with Ajax: Building a Web service client

Source: Internet
Author: User
Tags array object extend header object model string access websphere application server
Ajax|web|web Services | client
"Guide" This article describes how to use asynchronous JavaScript and XML (asynchronous JavaScript and XML, AJAX) design patterns to implement a Web browser based SOAP Web service client.

AJAX has been widely used in many well-known WEB application services, such as GMail, Google Maps, Flickr, and odeo.com. By using asynchronous XML messaging, AJAX provides Web developers with a way to extend the value and functionality of their Web applications. The Web services JavaScript Library that is described here expands the infrastructure to enhance AJAX design patterns by introducing support for invoking SOAP-based WEB services.

Invoking Web services from the browser

Invoking a SOAP Web service from a Web browser can be cumbersome because most popular Web browsers are slightly different in generating and processing XML. All browsers are implemented consistently and there are few standard APIs or features for XML processing.

One of the mechanisms in which browsers implement consistent support is the XMLHttpRequest API, which is the core of the AJAX design pattern. Another recent article by Philip McCarthy, published by the DeveloperWorks website, describes the API in detail. XMLHttpRequest is a JavaScript object used to execute asynchronous HTTP requests. Philip McCarthy describes a sequence diagram in his article (see Figure 1), which is helpful in understanding how the XMLHttpRequest object supports AJAX design (see Resources for a link to the full text).



Figure 1. Philip McCarthy's AJAX sequence diagram

From this diagram, you can see clearly how the XMLHttpRequest object works. Some JavaScript that runs in a Web browser creates a XMLHttpRequest instance and a function for asynchronous callbacks. The script then uses the XMLHttpRequest object to perform HTTP operations on the server. When a response is received, the callback function is invoked. Within the callback function, the returned data may be processed. If the returned data happens to be XML, the XMLHttpRequest object will automatically resolve the data using the XML processing mechanism built into the browser.

Unfortunately, the main difficulty with using AJAX methods is the detailed process of XMLHttpRequest objects parsing XML automatically. For example, suppose the data I am requesting is a SOAP envelope that contains elements from many different XML namespaces, and I want to extract the value of the property attr in Yetanotherelement. (See Listing 1)

Listing 1. A SOAP envelope that contains multiple namespaces







xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance" >

<s:Header/>

<s:Body>

<m:someelement xmlns:m= "Http://example" >





xmlns:m= "Urn:example" >





xmlns:n= "Urn:foo"/>

</n:someOtherElement>

</m:someElement>

</s:Body>

</s:Envelope>

In Mozilla browsers and Firefox browsers, extracting attr property values is very simple, as shown in Listing 2.

Listing 2. Methods for retrieving attr attribute values in Mozilla and Firefox cannot be used in Internet Explorer

var m = El.getelementsbytagnamens (

' Urn:example ',

' yetanotherelement ') [0].

Getattributens (

' Urn:foo ',

' attr ')

Alert (m); Displays ' abc '

About security

Because of the many practical security issues involved, by default, XMLHttpRequest objects in most Web browsers are limited to interacting with resources and services that are hosted in the same domain as the Web page that the user is viewing. For example, if I am accessing a page in http://example.com/myapp/, XMLHttpRequest will only allow access to resources located in the example.com domain. This precaution is necessary to prevent malicious application code from potentially inappropriate access to information that it should not be able to access. Because the Web service client described here is based on XMLHttpRequest, this restriction also applies to the Web service that you will invoke.

If you need to be able to access WEB services that are located in another domain, you can use the following two logical solutions:

    • Digitally sign JavaScript. By digitally signing a JavaScript script, you tell the Web browser that the script will not perform any malicious activity, and that restrictions on the data that XMLHttpRequest can access should also be canceled.
    • Use a proxy. A simple solution is to pass all requests from XMLHttpRequest by proxy resources located in the same domain as the loaded page. The agent forwards the XMLHttpRequest request to the remote location and returns the result to the browser. From the point of view of the XMLHttpRequest object, this interaction occurs within the existing security configuration.

Unfortunately, the above code cannot be run in Internet Explorer Version 6 because the browser not only does not implement the Getelementsbytagnamens feature, but it actually uses a very bad method--the XML The prefix of the namespace is treated as part of its element and attribute name.

Internet Explorer lacks support for XML namespaces, which makes it difficult to deal with namespace-intensive XML formats, such as SOAP in a browser-independent manner. Even if you want to do something as simple as extracting property values from the results, you must write special code that enables consistent expectations in multiple browsers. Fortunately, this particular code can be encapsulated and reused.

In order to invoke Web services from a Web browser and handle SOAP messages reliably, you need to understand some security issues first (see sidebar, "About security"). In addition, you will need to write a JavaScript script library (Figure 2) to abstract inconsistencies in the underlying browser XML implementation so that you can work directly with WEB service data.

Figure 2. Invoking Web services through JavaScript in a Web browser that uses Web services JavaScript Library

The Web Services JavaScript Library (ws.js) in Figure 2 is a set of JavaScript objects and utilities that provide basic support for a SOAP 1.1-based WEB service. Ws.js defines the following objects:

ws. Call: A WEB service client packaged with XMLHttpRequest

ws. Qname:xml qualified name implementation

ws. Binder: The basis of a custom XML serializer/deserialization

ws. Handler: The basis of the request/response handler

soap. Element: The basic SOAP element that wraps the XML DOM

soap. The Envelope:soap Envelope object extends SOAP. Element

soap. The Header:soap Header object extends SOAP. Element

soap. The Body:soap body object extends SOAP. Element

xml: Cross-platform practical approach for XML processing

The core of Ws.js is WS. The call object, which provides a way to invoke the Web service. Ws. Call is primarily responsible for interacting with the XMLHttpRequest object and handling the SOAP response.

Ws. The Call object exposes the following three methods:

Add_handler. Add a request/response handler to the processing chain. The handler object is invoked before and after calling the Web service to support extensible pre-call processing and post-call processing.

invoke. Will specify the SOAP. The Envelope object is sent to the Web service, and then the callback function is invoked after the response is received. Use this method when calling a document-style WEB service that uses text XML encoding.

Invoke_rpc. Creates a SOAP that encapsulates the RPC style request. Envelope and sends it to the WEB service. When a response is received, the callback function is invoked.

In the usual case, WS. The call object is simply a thin wrapper (thin wrapper) at the top of the XMLHttpRequest object that can perform a number of simplified processing operations. These actions include setting the SOAPAction HTTP Header required by the SOAP 1.1 specification.

using Ws.js


The WEB Services JavaScript Library provides a very simple API.

soap.* objects (Soap.element, SOAP. Envelope, SOAP. Header and SOAP. Body) provides a way to build and read a SOAP envelope, as shown in Listing 3, so that the underlying details of the processing XML Document Object model are smoothly abstracted.

Listing 3. Building a SOAP Envelope

var envelope = new SOAP. Envelope ();

var body = Envelope.create_body ();

var el = body.create_child (new WS. QName (' method ', ' Urn:foo '));

Listing 4 shows the SOAP envelope generated by the code in Listing 3.

Listing 4. Building a SOAP Envelope

<envelope xmlns= "http://schemas.xmlsoap.org" >

<Body>

<method xmlns= "Urn:foo" >

<param>bar</param>

</method>

</Body>

</Envelope>

If the SOAP envelope you are creating represents an RPC-style request, then soap. The BODY element provides an easy way to SET_RPC (as shown in Listing 5), which constructs a complete RPC request--containing a specified operation name, a specified array of input parameters, and a URI for a SOAP-encoded style.

Listing 5. Building an RPC request envelope

var envelope = new SOAP. Envelope ();

var body = Envelope.create_body ();

BODY.SET_RPC (

New WS. QName (' param ', ' urn:foo '),

New Array (

{name: ' param ', Value: ' Bar '}

), SOAP. Noencoding

);

Each parameter is passed as a JavaScript object structure and may have the following properties:

name. A string or WS that specifies the name of the parameter. QName object. Necessary.

value. The value of the parameter. If the value is not a simple data type (for example, a string, integer, or other), you should specify a WS that serializes the value into the appropriate XML structure. Binder. Necessary.

Xsitype: WS of the XML schema instance type that identifies the parameter. QName (for example, xsi:type= "int" corresponds to xsitype:new WS.) QName (' int ', ' Http://www.w3.org/2000/10/XMLSchema ')). Optional.

Encodingstyle: The URI that identifies the SOAP encoding style used by the parameter. Optional.

Binder: WS that can serialize parameters into XML. Binder implementation. Optional.

For example, if you want to specify a parameter named "ABC", XML namespace is "Urn:foo", Xsi:type is "int" and the value is "3", I will use the following code: The new Array ({name:new WS. QName (' abc ', ' Urn:foo '), Value:3, Xsitype:new WS. QName (' int ', ' Http://www.w3.org/2000/10/XMLSchema ')}).

Once I have constructed SOAP for the service request. Envelope, I'll take that SOAP. Envelope passed to WS. The Invoke method of the Call object in order to invoke the method encoded in the envelope: (New WS. Call (Service_uri)). Invoke (envelope, callback) Another option is to manually build SOAP. Envelope. I'll take the argument WS. QName, parameter arrays, and encoding styles are passed to WS. The Invoke_rpc method of the Call object, as shown in Listing 6.

Listing 6. Use WS. The call object invokes the Web service



var Nsuri = ' Urn:foo ';

var qn_op = new WS. QName (' method ', Nsuri);



CALL.INVOKE_RPC (

Qn_op,

New Array (

{name: ' param ', Value: ' Bar '}

), SOAP. Noencoding,

function (Call,envelope) {

Envelope is the response SOAP. Envelope

The XML Text of the response is in arguments[2]

}

);

When invoking the Invoke method or the Invoke_rpc method, WS. The call object creates a basic XMLHttpRequest object, passes the XML element containing the SOAP envelope, receives and resolves the response, and then invokes the provided callback function.

In order to be able to extend the preprocessing and reprocessing of SOAP messages, WS. The Call object allows you to register a set of WS. The Handler object, as shown in Listing 7. These objects are called for each request, every response, and every error in the call cycle. Can be extended by the WS. Handler a JavaScript object to implement a new handler.

Listing 7. Create and register a response/response handler

var MyHandler = Class.create ();

Myhandler.prototype = (new WS. Handler ()). Extend ({

On_request:function (envelope) {

Pre-request processing

},

On_response:function (Call,envelope) {

Post-response, Pre-callback processing

},

On_error:function (Call,envelope) {

}

});

var call = new WS. Call (...);

Handlers are most useful for inserting or extracting information in a SOAP envelope that is being passed. For example, you can imagine that a handler automatically inserts the appropriate Web service addressing (Web Services addressing) element into the Header of the SOAP Envelope, as shown in the example in Listing 8.

Listing 8. A handler example that adds a WEB service addressing operation Header to the request

var wsaddressinghandler = Class.create ();

Wsaddressinghandler.prototype = (new WS. Handler ()). Extend ({



Envelope.create_header (). Create_child (

New WS. QName (' Action ', ' http://ws-addressing ', ' WSA ')

). Set_value (' http://www.example.com ');

}

Ws. The Binder object (listing 9) executes SOAP. The custom serialization and deserialization of the Element object. Ws. The implementation of Binder must provide the following two methods:

to_soap_element. Serializes a JavaScript object into SOAP. Element. The first parameter passed in is the value to serialize. The second parameter is SOAP. Element, you must serialize the values that you want to serialize to SOAP. Element. The method does not return any values.

To_value_object. The SOAP. The Element is deserialized to a JavaScript object. The method must return a deserialized value object.

Listing 9. Ws. Binding Implementation Example

var mybinding = Class.create ();

Mybinding.prototype = (new WS. Binding ()). Extend ({



...

},

To_value_object:function (Element) {

...

}

A simple example

I have provided an example project to illustrate the basic functionality of the Web Services JavaScript Library. The Web services that the demo uses, as shown in Listing 10, have been implemented in WebSphere application Server and provide a simple Hello world feature.

Listing 10. A simple Java-based "Hello World" Web service

package example;

public class HelloWorld {

public string SayHello (string name) {

Return "Hello" + name;

}

}

After implementing the service and deploying it to WebSphere application Server, the WSDL description of the service (listing 11) defines the SOAP message you need to pass (to invoke the Hello World Service).

Listing 11. Code Snippets for HELLOWORLD.WSDL

<wsdl:porttype name= "HelloWorld" >

<wsdl:operation name= "SayHello" >





Name= "Sayhellorequest"/>





Name= "Sayhelloresponse"/>

</wsdl:operation>

</wsdl:portType>



By using the Web services JavaScript Library, you can implement a method that invokes the Hello World Service, as shown in Listing 12.

Listing 12. Use WS. Call calls the HelloWorld service

 



...

<script

type= "Text/javascript"

src= "Scripts/prototype.js" ></SCRIPT>

<script

type= "Text/javascript"

src= "Scripts/ws.js" ></SCRIPT>

<script type= " Text/javascript

Function SayHello (name, container) {

var call = new WS. Call ('/ajaxws/services/helloworld ');

var nsuri = ' http://example ';

var qn_op = new WS. QName (' SayHello ', Nsuri);

var qn_op_resp = new WS. QName (' Sayhelloresponse ', Nsuri); 

Call.invoke_rpc (

Qn_op,

New Array (

{name: ') Name ', value:name}

), NULL,

Function (call,envelope) {

var ret =

Envelope.get_body (). Get _all_children () [0].

Get_all_children () [0].get_value ();

container.innerhtml = ret;

$ (' soap '). InnerHTML = arguments[2].escapehtml ();

}

);

}

</script>


...

You can then invoke the Hello World Service anywhere in our WEB application by calling the SayHello function. See listing 13.

Listing 13. Calling the SayHello function

<body>

<input name= "name" id= "name"/>

<input value= "Invoke the Web Service"



/>

<div id= "Container" >result:

<div id= "Result" >

</div>

<div id= "Soap" >

</div>

</div>

</body>

The result of the successful call is shown in Figure 3. Running the example in Mozilla, Firefox, and Internet Explorer should get the same result.

Figure 3. The Hello world example in Firefox

Subsequent sections

Using the Web Services JavaScript Library, you can incorporate basic SOAP Web services into your Web application in a simple, browser-independent manner. In the next section of this series, you can explore not only how to use the library to invoke more advanced Web services based on the Web Services Resource Framework (Ws-resource framework) series specification, but also how to extend the Web service functionality and integrate it into a Web application 。

<

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.