Wizard API updated!
Tim Boudreau has released a new version of the Swing Wizard library (version 0.997) that fixes the WizardException bug reported in JavaWorld's recent Open Source Java Project profile. The article's examples have been reworked to test out the new, improved WizardException. Thanks, Tim, for this helpful fix!
Open Source Java Projects: The Wizard API

Newsletter sign-up

Sign up for our technology specific newsletters.

Enterprise Java
View all newsletters

Email Address:

Services orchestration for AJAX

Execute process definition on the client side

AJAX (Asynchronous JavaScript and XML) is now widely known as a technique used in client-side interactions. However, AJAX requires special coding for asynchronous requests and for server-side programming. This article proposes a new AJAX approach that executes the process definition on the client. It allows you to orchestrate services synchronously and apply the MVC (Model View Controller) pattern, so you will find coding similar to server-side programming. Before discussing the new approach, let's take a look at the problems with AJAX currently.

AJAX typically communicates with the Web server using asynchronous requests so that other tasks can be executed while waiting for a response. It enables the user to interact with the browser, rather than the standard Web application. But once you decide to use AJAX, you have to struggle with callback functions. Look at the following code that executes two functions:

Listing 1. Execute two functions

funcA();
funcB();

You may expect that funcB() executes after funcA() is complete. But on the client-side, we must check whether the code calls an asynchronous request. If it does, the functions execute in parallel. funcB() starts executing without waiting for a response from funcA(). In this case, the response of funcA() is processed in the callback function (e.g., cbA()), which means we must handle an additional function for each function. Also, the use of a callback function causes problems that break the process flow and complicates the orchestration of functions. If you want to execute another function, for example, funcC() after funcA() and funcB() are complete, you must implement logic to join the callback functions, as shown in Listing 2 and the parallel pattern illustrated in Figure 1. In the list and figure, callback functions for funcA() and funcB() are defined as cbA() and cbB(), respectively.

Listing 2. Join the two functions

var count = 2;
funcA();
funcB();

function cbA() {
   if (--count == 0) funcC();
}

function cbB() {
   if (--count == 0) funcC();
}

Figure 1. Parallel vs. sequential pattern

funcC() is now invoked sequentially; however, the function is tightly coupled with cbA() and cbB(). If funcC() needs to be replaced with funcD(), we must modify the callback functions; that is, the use of a callback function affects the reusability of funcA() and funcB().

Also, if you want to execute funcA() and funcB() synchronously, without blocking code, you must invoke funcB() in cbA(), as shown in Listing 3 and in the sequential pattern illustrated in Figure 1. cbA() and funcB() are also tightly coupled.

Listing 3. Execute two functions sequentially

funcA();

function cbA() {
   funcB();
}

In addition, as shown in these code listings, we must implement the flow control ourselves using JavaScript to make asynchronous and/or synchronous requests.

Services orchestration

Thus far, we have found the following problems with AJAX code:

  • Process flow interrupted by callback functions
  • Tight coupling among functions
  • Flow control is intertwined in functions

One reason why we are encountering problems is that AJAX is inherently based on an asynchronous model. A synchronous model, rather than an asynchronous one, is intuitive and more natural for most developers. It would prove helpful if, somehow, our asynchronous requests could be changed to synchronous ones. Moreover, the parallel pattern should be easily acceptable when the developer requires it, and flow control should be separated from the components properly. These requirements don't seem that special because they are standard for server-side development. Our goal is to apply server-side style to our client-side asynchronous model.

To achieve this goal, this article takes a process-centric approach that describes methods for execution as services in process definition XML using J-SOFA (Java/JavaScript Services Orchestration for Actions), an open source framework for orchestrating services. It provides two service orchestrators for the client and server. The client-side orchestrator invokes JavaScript functions, and invocations of Java objects and Web services are delegated to a server-side orchestrator, as shown in Figure 2.

Figure 2. Services to be executed by orchestrators

The services are invoked synchronously, so you simply describe tags step-by-step. The following XML represents sequential flow, which executes server-side methodA() and methodB(). The developer doesn't have to describe callback functions in the XML because J-SOFA makes asynchronous requests and handles the callback functions internally.

Listing 4. Sequential flow

<process>
   <service name="MyService" operation="methodA" runAt="server" />
   <service name="MyService" operation="methodB" runAt="server" />
</process>

If you need to apply a parallel pattern, it can be described using the fork tag, which splits the flow and asynchronously executes the tags in the body. The following code invokes methodA() and methodB() in parallel, and then exits from the fork tag after those two methods complete. You don't have to implement the code for forking and merging in your components.

Listing 5. Parallel flow

<process>
   <fork>
      <service name="MyService" operation="methodA" runAt="server" />
      <service name="MyService" operation="methodB" runAt="server" />
   </fork>
</process>

To execute the process, just call the Jsofa.execute() function with the XML path in your HTML:

Listing 6. JavaScript code that executes the process

Jsofa.execute("sample.xml");

In addition to the fork tag, J-SOFA currently supports the following basic tags:

  • service: Invoke an operation (JavaScript, Java object, or Web service)
  • httpRequest: Send an HTTP request (client-side only)
  • if: Execute if test condition is true
  • choose/when/otherwise: Execute one of the paths
  • forEach: Execute iteratively with loop counter or variable
  • while: Execute iteratively while test condition is true
  • group: Organize two or more tags into one group
  • sleep: Wait for specified time
  • subProcess: Execute a sub-process in another process space

Furthermore, a process can contain server-side tags using the runAt attribute. J-SOFA basically executes the tags on the client-side; however, when it finds the runAt attribute with the value server, the tag and the child nodes are transformed to the server and executed there. When the server-side process has completed, the updated context is sent back to the client, and the rest of the tags execute on the client.

1 | 2 |  Next >

Discuss

Start a new discussion or jump into one of the threads below:

Subject Replies Last post


Resources