Sun Java Solaris Communities My SDN Account Join SDN
 
Article

Achieving Interoperability with Ajax using Java and .NET Technologies

 
By Marina Fisher and Gerald Beuchelt, Sun Microsystems, August 2007  

Articles Index

Web 2.0 is a term, defined by O'Reilly Media, that is used to describe the current and foreseeable next generation of the internet, where the web is evolving to be a platform on which applications will be built, as opposed to simply being a delivery mechanism for monolithic applications. Examples of Web 2.0 applications can be seen in MySpace and Wikipedia for user-contributed content, and Google Maps and Calendars as platforms on which other applications can be built. Along with these comes the new development paradigm, Ajax, which is intended to provide a better user experience in running Web 2.0 applications.

The theory behind Ajax is simple - in the past, using a web site or application involved making a request from a server and waiting for the response to be rendered on the page before continuing. In many cases, this could be terribly inefficient, as only a small part of the page would be updated. If that part could be asynchronously updated, then the user wouldn't be sitting in an idle state waiting for an entire page refresh, and could act on the information that they have while waiting for the new piece to download asynchronously. Ajax empowers this through a browser object called the XMLHTTPRequest object, which can be controlled by JavaScript to make a call to a back-end service, setting up a callback function to handle the response from that service. JavaScript code then can use the browser's Document Object Model (DOM) to write the updates 'in place' on the page, giving an asynchronous update. A great example of this is Google Maps, which uses the XMLHttpRequest to download the tiles of the map that are adjacent to the one that the user is currently inspecting. When the user drags the mouse around the map, the new tiles appear instantly, not incurring a round trip delay as they've already been cached, a feature that has enabled Google Maps to reach 'killer-application' status on the web.

Figure 1 shows a high level architectural view of how the Ajax technique works in the interaction between the browser and the web server.

 Ajax Interaction Between Browser and Web Server.
Figure 1. Ajax Interaction Between Browser and Web Server.
 

On the client side, an Ajax application relies on XMLHttpRequest to invoke remote back-end services, creating what is known as a mashup. Back-end services will likely return complex values, including web services, which will return SOAP-Encoded Results, or web applications which can return anything from HTML markup, to text-over-http, to CSV, document formats such as Excel spreadsheets, and more. JavaScript is then used on the client side to consolidate the content and present a mashup to the end user.

The problem occurs when the JavaScript coder has to handle parsing these diverse formats in creating a mashup, a task that JavaScript, as a simple scripting language isn't equipped for.

With this problem in mind, and with the inherent complexity of developing in JavaScript, tools vendors are coming up with toolkits that allow a server-side paradigm to be used in building Ajax applications. The theory is straightforward - technology such as JSP or ASP.NET has been used for years to allow this, where the application developer builds a server application that 'generates' HTML and JavaScript markup, which is then delivered to the client and executed. This technique fits neatly for the development of Ajax applications and there are a number of open source toolkits, such as Dojo, Google Web Toolkit, and Yahoo Ajax Library among others, that help to build Ajax applications. However, caution must be exercised with this approach, as it can lead to interoperability challenges. Consider the situation where a mashup application has to consume web services that run on different technology stacks. This is where the interoperability issues arise; the rest of this article will explore some of them.

In "Java EE .NET Interoperability: Integration Strategy, Patterns, and Best Practices", the Java and .NET interoperability constraints across presentation, business, integration, and resource tiers were raised. Web 2.0 introduces a new layer of complexity to this - where particularly in the mashup scenario, you can be faced with interoperability challenges between the browser and the services layer. With earlier web applications, the browser was tightly knit to a single presentation tier, and its content dictated by this tier. In the case of a mashup, the browser is no longer tightly knit to a single server, and can be receiving content from many diverse ones, including third parties, in order to 'mash' all the information up into a usable application. Additionally, there can be a number of different browser technology platforms that each server needs to manage, giving a 'many to many' relationship that has inherent complexity. At the moment, it's essential to test Web 2.0 application functionalities under a variety of browsers, as your applications will be widely available on the internet and they will be accessed through different browsers.

First, let's look at how ASP.NET uses Ajax to consume a web service.

As part of ASP.NET Ajax, Microsoft has extended the HTTP handlers for web services, so that if you call a web service that runs on an ASP.NET Ajax-enabled platform and postfix it with '/js', ASP.NET Ajax will automatically generate a JavaScript proxy that can be used to call this web service. For this to work you must decorate the service with a ScriptService() attribute. This approach is reducing the complexity involved with calling web services from Ajax. You can see an example of this in Figure 2.

Automatically generating a JavaScript Proxy in ASP.NET Ajax.
Figure 2. Automatically generating a JavaScript Proxy in ASP.NET Ajax
 

Here is a sample copy of the the JS code auto generated by appending /js to a [ScriptService()] enabled web service.

var WebService=function() {
this._timeout = 0;
this._userContext = null;
this._succeeded = null;
this._failed = null;
}
WebService.prototype={
HelloWorld:Sys.Net._WebMethod._createProxyMethod(this,"HelloWorld", "WebService.HelloWorld",false),_get_path: function() { return WebService.get_path(); },
    set_timeout: function(value) { this._timeout = value; },
    get_timeout: function() { return this._timeout; },
    set_defaultUserContext: function(value) { this._userContext = value; },
    get_defaultUserContext: function() { return this._userContext; },
    set_defaultSucceededCallback: function(value) { this._succeeded = value; },
    get_defaultSucceededCallback: function() { return this._succeeded; },
    set_defaultFailedCallback: function(value) { this._failed = value; },
    get_defaultFailedCallback: function() { return this._failed; }
}
WebService._staticInstance = new WebService();
WebService.set_path = function(value) { WebService._staticInstance._path = value; }
WebService.get_path = function() { return WebService._staticInstance._path; }
WebService.set_timeout = function(value) { WebService._staticInstance._timeout = value; }
WebService.get_timeout = function() { return WebService._staticInstance._timeout; }
WebService.set_defaultUserContext = function(value) { WebService._staticInstance._userContext = value; }
WebService.get_defaultUserContext = function() { return WebService._staticInstance._userContext; }
WebService.set_defaultSucceededCallback = function(value) { WebService._staticInstance._succeeded = value; }
WebService.get_defaultSucceededCallback = function() { return WebService._staticInstance._succeeded; }
WebService.set_defaultFailedCallback = function(value) { WebService._staticInstance._failed = value; }
WebService.get_defaultFailedCallback = function() { return WebService._staticInstance._failed; }
WebService.set_path("/AjaxEnabledWebSite2/WebService.asmx");
WebService.HelloWorld= function(onSuccess,onFailed,userContext) {WebService._staticInstance.HelloWorld(onSuccess,onFailed,userContext); }
 

Now all a developer needs to do to access this web service is to create a JavaScript reference to this URI, and have the Microsoft ASP.NET Ajax JavaScript libraries in the browser cache. That way, speaking to the web service is easily done, through the proxy. Microsoft has taken one step further to make this even simpler, by adding the concept of a ServiceReference to the server side code, which, when run, will generate all the required JavaScript.

A server reference looks like this in ASP.NET

<Services>
    <atlas:ServiceReference Path="MyWebService.asmx" />
</Services>
 

Basically, this gets parsed by ASP.NET into a block of JavaScript that calls the URI of the service, appends '/js' to it to get the JavaScript proxy back, and then loads that proxy into the cache so that the rest of your code can access it.

But what happens if the distant service is not written on the Microsoft stack, or even if the stack is Microsoft, but not ASP.NET Ajax enabled? Appending '/js' to the URI will give an HTTP 400 - as it is a bad request. Obviously the out-of-the-box interoperability is not available. To explore a workaround, you can look into the Microsoft Windows Communication Foundation (WCF), "Indigo." The WCF framework provides APIs to support Representational State Transfer (ReST) and Plain Old XML (POX), both of which are also supported on the Java side. SOAP also remains one of the widely used interoperability standards. These two options bring flexibility to the mashup developers. Below is a diagram that outlines possible integration.

Interaction between the Ajax and Web Service components.
Figure 3. Interaction between the Ajax and Web Service components
 
Traditional SOAP-Based Interoperability
 

Starting with a simple Ajax application on the Java side, we'll use NetBeans open source IDE with the jMaki Ajax plug-in. Then, drag-and-drop a visual component such as Dojo Fish Eye into the index.jsp page and add a custom-built interactive Hello World widget. The Hello World, just like any jMaki component, is composed of three constituents - HTML, CSS, and JavaScript. This widget dynamically displays the content that the user types in the text field by asynchronously passing individual characters through the XMLHttpRequest object to the server. This code shows the JavaScript logic that processes the user entry:

    var wid = widget.uuid;
    var service = widget.service;

    function getXmlHttpReq(url) {
        if (window.XMLHttpRequest) {
            return new XMLHttpRequest();
        } else if (window.ActiveXObject) {
            return new ActiveXObject("Microsoft.XMLHTTP");
        }
    }
    this.submitData = function() {
        var target = document.getElementById(uuid + "_hello");
        var req = getXmlHttpReq(service);

        req.onreadystatechange = function() {
            if (req.readyState == 4) {
                if (req.status == 200) {
                    target.innerHTML = req.responseText;
                }
            }
        };
        req.open("POST", service, true);
        var name= document.getElementById(uuid + "_name");
        req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        req.send("name=" + name.value + "&uuid=" + wid);
    }
   
}

var jshello = new HelloWorld();
jmaki.attributes.put(widget.uuid, jshello);
 

We've already reviewed the XMLHttpRequest object creation, open() and send() methods, and onreadystatechange settings, which define a callback function to process the response. A readyState == 4 indicates that the request has been loaded. A request status == 200 indicates that the HTTP status is "OK"; the asynchronous request has been returned and the response is retrieved through req.responesText(). The index.jsp page, shown below is also quite simple.

Index.jsp page.
Figure 4. Index.jsp page
 

The way to access the widget is by

<a:ajax name="helloworld" service="helloService.jsp" />
 

Building and running the jMaki application will automatically compile and deploy applications under the open source GlassFish application server. You can download the NetBeans IDE along with the application server as a single distribution.

HelloWorld Ajax Application.
Figure 5. HelloWorld Ajax Application
 

Next we will change our application to integrate it with a .NET web service. Here is the Hello .NET service that returns a greeting message to the user:

ASP.NET HelloService.
Figure 6. ASP.NET HelloService
 

This web service is ready to be deployed under IIS, and upon its invocation you can see the following:

NET WS Deployed Under IIS.
Figure 7. .NET WS Deployed Under IIS
 

Next, we need to import the .NET Web Service WSDL, shown below, into the NetBeans IDE to automatically generate corresponding artifacts.

ASP.NET Web Services WSDL.
Figure 8. ASP.NET Web Services WSDL
 

Let's update the helloService.jsp in our Java-based Ajax application with the .NET service. Here is the listing of helloService.jsp:

<ol>
<%@page import="org.tempuri.*" %>    
<%
    String name= request.getParameter("name");
    
    // Access the .NET Web Service
    NetService1Soap service = new NetService1().getNetService1Soap();
    String res = service.helloService(name);
    out.println();
    out.println(res);
%>
</ol>
 

Rebuilding and running the application yields the following output:

A Java Ajax client accessing .Net Web Service.
Figure 9. A Java Ajax client accessing .Net Web Service
 

What we have illustrated is a way to interoperate between a .NET service and a jMaki Ajax application using SOAP as an underlying communication protocol. With the growing popularity of Web 2.0, ReSTful web services supported by Yahoo, Flickr and many others have become quite popular. A ReST-style web service is accessed through URI-addressable semantics of the HTTP protocol, which significantly simplifies integration effort on the client side. As a result, the Web 2.0 services interoperability between .NET and Java stacks is gradually shifting towards ReST.

ReST/POX Interoperability with WCF
 

Windows Communication Foundation (WCF), formerly known as "Indigo", is the communication stack of the .NET Framework 3.0. Most notably, a large number of WS-* protocols such as WS-Security, WS-ReliableMessaging, MTOM and WS-Policy are now part of the core web service stack. Formerly, developers needed to resort to the Web Services Enhancement (WSE) packages that enjoyed only limited support from Microsoft and were really targeted at early adopters. Also, because of the emerging nature of many of the WS-* specifications, interoperability between WSE and other WS-* implementing SOAP stacks was sketchy at best.

WCF changes this, having been redesigned with WS-* support in mind, and tested against Sun's Web Services Interoperability Technologies (WSIT) and other companies' SOAP stacks. Enabling any of the WS-* protocols is typically not very hard and requires often only a few lines of code or some configuration in the deployment .config files.

Another significant enhancement is the ReST (also known as POX - "Plain Old XML") operation mode for WCF web services. From the implementation standpoint, the POX service uses the API and infrastructure for the traditional web services, but before being sent over the wire, the SOAP envelope and the headers are stripped from the message. This is achieved by setting the MessageVersion to None. This can be done by creating a custom binding in the configuration file:

  <system.serviceModel>
    <services>
      <service name="MyService">
        <endpoint 
          address="service" 
          contract="IMyService" 
          binding="customBinding" 
          bindingConfiguration="poxBinding" />
      </service>
    </services>
    <bindings>
      <customBinding>
        <binding name="poxBinding">
          <textMessageEncoding 
            messageVersion="None" />
          <httpTransport 
            manualAddressing="true" />
        </binding>
     < /customBinding>
    </bindings>
  </system.serviceModel>
 

There are a few details that need to be attended to. It is good style in WCF - along the SOA tenet of contract-driven development - to define interfaces for the web services and decorate those with the ServiceContract() attribute. For POX services, the signature of the POX service must be as follows:

Message thisIsAPoxMethod(Message request)
 

The incoming Message can be used to determine the context of the incoming ReST request. For example. the request URI for an HTTP GET can be obtained by evaluating the Message.Properties.Via attribute.

Here is the actual .NET ReST/POX web service, Service.cs, which we will invoke from the Ajax application implemented with the jMaki Ajax framework. This service returns the time:

using System;
using System.ServiceModel;
using System.Runtime.Serialization;

using System.Runtime.Serialization;
using System.ServiceModel.Channels;
using System.Net;

[ServiceContract()]
public interface IMyService
{
    // Add action and ReplyAction
    [OperationContract(Action = "*", ReplyAction = "*")]
    Message MyOperation1(Message request);
}


// Add ServiceBehaviour
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Prefix)]
public class MyService : IMyService
{
    // Rewrite the method to take and return Message
    public Message MyOperation1(Message request)
    {
        return Message.CreateMessage(MessageVersion.None, 
                                     String.Empty, 
                                     (object)DateTime.Now.ToString("T"));
    }
}
 

Here is the result of invoking the service:

WCF ReST Style Web Service Invocation.
Figure 10. WCF ReST Style Web Service Invocation
 

We now open the NetBeans IDE and implement an Ajax application using the jMaki Ajax framework that accesses the earlier-implemented .NET ReST style service. To access the cross domain .NET web service, we need to specify the service URL in the XMLHttpRequest property file xhp.json. This file is located the under resources folder of the web project.

{"id": "localtime", 
         "url":"http://localhost:1651/WCF_POX_Service/Service.svc/service",
         "apikey" : "appid=jmaki-key"
        }    
 

And now in the index.jsp of the default web page, we add all the necessary visual components to our mashup page, like Flickr images, as well as the clock that will be configured to retrieve time from a remote .NET service in the following manner:

  jmaki.doAjax({url: 'http://localhost:8081/AjaxEx/xhp?key=localtime', callback: function(req) { var _req=req; postProcess(_req);}}); 
 

Here is the snippet of the application code using the jMaki Ajax framework available as the NetBeans plugin:

Ajax Application Using the jMaki NetBeans Plug-in.
Figure 11. Ajax Application Using the jMaki NetBeans Plug-in
 

Here is the result of running the sample mashup application:

Ajax Interoperability Sample with .NET ReST Style WS.
Figure 12. Ajax Interoperability Sample with .NET ReST Style WS
 

As you can see, this Ajax sample pulls the contents from different resources including the ASP.NET Ajax ReST/POX style service, thus achieving interoperability.

More on ASP.NET Ajax

ASP.NET Ajax was released in early 2007. This initial release contains some core functionality like a script manager and an update panel (that defines the boundary of updateable content). A fairly rich set of widgets is available from Microsoft's community development site. Integration of these widgets is not yet as seamless as the jMaki/Dojo integration in NetBeans, but interested developers can get access to the code and start developing solutions. The source code for both the core ASP.NET Ajax runtime and the widget set is available. Microsoft promised proper Visual Studio integration and they seem to be on track for the 'Orcas' release of their IDE.

There has been some significant confusion about the future of the ASP.NET Ajax Bridge component (similar to the XMLHttpRequest Proxy in jMaki): The bridging component was part of the early "Atlas" previews, but was ultimately dropped. There have been some indications in Microsoft's public forums that this functionality could be put back in the core Ajax runtime, but so far there is no clear indication of when this might happen.

In order to satisfy the demands for new functionality and extended features, Microsoft has started to preview release extensions called "ASP.NET Ajax Futures". For example, the current May 2007 release features new components to use with Microsoft's "Silverlight" rich client application platform.

Conclusion
 

Web 2.0 is a significant step forward in the user experience, but at the same time the underlying technologies and toolkits are still evolving. While Ajax and the associated frameworks that allow rich internet applications to be created are growing in stature and power, it is highly recommended that you consider interoperability as a major factor in deciding how to build your applications and which techniques to use. That includes selecting a standards-based data interchange format such as XML or JSON, factoring out data transformation from the actual processing logic, deciding on a client- or a server-side proxy to overcome browser's cross-domain security scheme. These and many other factors contribute towards interoperability of Web 2.0 applications. In addition, leading industry vendors including Sun, Google, IBM, BEA, and others, are collaborating as part of the OpenAjax Alliance to enable a higher degree of interoperability by promoting a vision of a common Ajax platform across the industry. A number of innovative Web 2.0 technologies from Sun were assembled into the Sun Web Developer Pack, specifically ReSTful Web Services API, WADL, ROME API, project jMaki and more.

Resources
Rate and Review
Tell us what you think of the content of this page.
Excellent   Good   Fair   Poor  
Comments:
Your email address (no reply is possible without an address):
Sun Privacy Policy

Note: We are not able to respond to all submitted comments.

Oracle is reviewing the Sun product roadmap and will provide guidance to customers in accordance with Oracle's standard product communication policies. Any resulting features and timing of release of such features as determined by Oracle's review of roadmaps, are at the sole discretion of Oracle. All product roadmap information, whether communicated by Sun Microsystems or by Oracle, does not represent a commitment to deliver any material, code, or functionality, and should not be relied upon in making purchasing decisions. It is intended for information purposes only, and may not be incorporated into any contract.