reverse ajax implementation

Web development has changed a lot over the past few years. Today, we expect fast and dynamic access to applications over the web. In this new article series, we learn how to use Reverse Ajax (Reverse Ajax) technology to develop event-driven web applications to achieve a better user experience. The client-side example uses the JQuery JavaScript library. In this first article, we explore different Reverse Ajax techniques, using downloadable examples to learn how to use the streaming and long polling methods. Comet.

  foreword

  Web development has come a long way in the past few years, and we've moved far beyond linking together static web pages that would cause the browser to refresh and wait for the page to load. What is needed now are fully dynamic applications that can be accessed over the web, and these applications usually need to be as fast as possible, providing near real-time components. In this new five-part article series, learn how to use Reverse Ajax (Reverse Ajax) techniques to develop event-driven web applications.

  In this first article, we'll learn about Reverse Ajax, polling, streaming, Comet, and long polling, learn how to implement different Reverse Ajax communication techniques, and explore each advantages and disadvantages of this method. You can download the corresponding source code for the examples in this article.

  Ajax, Reverse Ajax, and WebSocket

  Asynchronous JavaScript and XML (Ajax), a browser feature accessible through JavaScript that allows a script to send an HTTP request to a website behind the scenes without reloading the page. Ajax has been around for over a decade, and despite its name containing XML, you can pass almost anything in an Ajax request, the most commonly used data is JSON, which is very close to JavaScript syntax and consumes less bandwidth. Listing 1 shows an example of this, an Ajax request to retrieve the name of a place by its zip code.

  Listing 1. Example Ajax request

var url ='http://www.geonames.org/postalCodeLookupJSON?postalcode='
  + $('#postalCode').val() +'&country='
  + $('#country').val() +'&callback=?';
  $.getJSON(url, function(data) {
  $('#placeName').val(data.postalcodes[0].placeName);
});

  In the downloadable source code for this article, you can see this example in action in listing1.html.

  Reverse Ajax (Reverse Ajax) is essentially such a concept: it can send data from the server to the client. In a standard HTTP Ajax request, data is sent to the server. Reverse Ajax can simulate sending an Ajax request in some specific ways. Client sends events (low latency communication).

  WebSocket technology comes from HTML5, is a relatively recent technology, and many browsers already support it (Firefox, Google Chrome, Safari, etc.). WebSocket enables a two-way, full-duplex communication channel, which opens a connection with a certain HTTP request called the WebSocket handshake, and uses some special headers. The connection remains active, and you can write and receive data in JavaScript just as if you were using a raw TCP socket. WebSocket will be covered in the second part of this article series.

  Reverse Ajax Technique

  The purpose of reverse Ajax is to allow the server to push information to the client. Ajax requests are stateless by default and can only be sent from the client to the server. You can work around this limitation by using techniques to simulate reactive communication between server and client.

  HTTP polling and JSONP polling

  Polling involves making a request from the client to the server for some data, which is obviously a pure Ajax HTTP request. In order to get server-side events as quickly as possible, the polling interval (the time between two requests) must be as small as possible. But there is such a disadvantage: if the interval is reduced, the client browser will issue more requests, many of which will not return any useful data, and this will waste bandwidth and resources in vain. Process resources.

  The timeline in Figure 1 illustrates a situation where the client issues some polling requests, but no information is returned, and the client must wait until the next poll to get the events received by the two servers.

  Figure 1. Reverse Ajax using HTTP polling

      

  JSONP polling is basically the same as HTTP polling, the difference is that JSONP can make cross-domain requests (requests that are not within your domain). Listing 1 uses JSONP to get place names by zip code. A JSONP request is usually identifiable by its callback parameters and return content, which is executable JavaScript code.

  To implement polling in JavaScript, you can use setInterval to make periodic Ajax requests, as shown in Listing 2:

  Listing 2. JavaScript polling

setInterval(function() {
  $.getJSON('events', function(events) {
    console.log(events);
  });
}, 2000);

  The polling demo in the source code of the article shows the bandwidth consumed by the polling method, and the interval is small, but you can see that some requests do not return events. Listing 3 shows the output of this polling example.

  Listing 3. Polling demo output

[client] checking for events...
[client] no event
[client] checking for events...
[client]2 events
[event] At Sun Jun 0515:17:14 EDT 2011
[event] At Sun Jun 0515:17:14 EDT 2011
[client] checking for events...
[client]1 events
[event] At Sun Jun 0515:17:16 EDT 2011

  Pros and cons of polling implemented in JavaScript:

  1. Advantages: It is easy to implement, does not require any server-side specific functions, and works on all browsers.

  2. Disadvantage: This method is rarely used because it is not scalable at all. Just imagine the amount of bandwidth and resources lost with 100 clients each making 2 second polling requests where 30% of the requests return no data.

  Piggyback

  Piggyback polling is a smarter approach than polling because it drops all non-essential requests (those that don't return data). There is no time interval, and the client sends a request to the server when needed. The difference is that on the part of the response, the response is split into two parts: the response to the requested data and the response to the server event, if either part occurred. Figure 2 gives an example.

  Figure 2. Reverse Ajax using piggyback polling

  When implementing piggyback technology, usually all Ajax requests on the server side may return a mixed response. There is an implementation example in the download of the article, as shown in Listing 4 below.

  Listing 4. Piggyback code example

$('#submit').click(function() {   $.post('ajax', function(data) {     var valid = data.formValid;     // handle the validation result     // and then handle the rest of the response (events)     processEvents(data. events);   }); });






  Listing 5 shows some piggyback output.

  Listing 5. Sample piggyback output

[client] checking for events...
[server] form valid ? true
[client]4 events
[event] At Sun Jun 0516:08:32 EDT 2011
[event] At Sun Jun 0516:08:34 EDT 2011
[event] At Sun Jun 0516:08:34 EDT 2011
[event] At Sun Jun 0516:08:37 EDT 2011

  You can see the result of the form validation and the events attached to the response. Again, this approach has some pros and cons:

  1. Advantages: There is no request that does not return data, because the client controls when to send the request, and consumes less resources. This method is also available on all browsers and does not require special features on the server side.

  2. Disadvantage: When the events accumulated on the server side need to be transmitted to the client, you don't know at all, because this requires a client behavior to request them.

  Comet

  Reverse Ajax using polling or piggybacking is very limited: it doesn't scale, and it doesn't provide low-latency communication (as soon as events hit the server, they get to the browser as fast as possible). Comet is a web application model in which a request is sent to the server and remains alive for a long time until it times out or a server event occurs. After that request completes, another long-lived Ajax request is sent to wait for another server-side event. With Comet, a web server can send data to a client without an explicit request.

  One of the great advantages of Comet is that each client always has a communication link open to the server. The server can push events to the client by submitting (finalizing) the response as soon as the event arrives, or it can even be accumulated and sent continuously. Because requests are kept open for a long time, special functionality is required on the server side to handle all these long-lived requests. Figure 3 gives an example. (Part 2 of this article series explains server-side constraints in more detail).

  Figure 3. Reverse Ajax using Comet

  Comet implementations can be divided into two categories: those using streaming and those using long polling.

  Comet using HTTP streaming

  In streaming mode, a persistent connection is opened. There will only be one long-lived request (#1 in Figure 3), because every event that arrives at the server is sent over this same connection. Therefore, the client needs a way to separate the different responses sent over the same connection. Technically speaking, two common streaming techniques include Forever IFrame (hidden IFrame), or the multi-part feature of the XMLHttpRequest object used to create Ajax requests in JavaScript.

  Forever Iframe

  The Forever Iframe technique involves placing a hidden Iframe tag on the page whose src attribute points to the servlet path that returns server-side events. Every time an event arrives, the servlet writes and refreshes a new script tag with JavaScript code inside, the iframe's content is appended to this script tag, and the content in the tag is executed.

  1. Advantages: Simple implementation, available on all browsers that support iframe.

  2. Disadvantages: There is no way to implement reliable error handling or track the status of the connection, because all connections and data are handled by the browser through HTML tags, so you have no way to know when the connection is over. was disconnected.

  Multi-part XMLHttpRequest

  The second technique, which is more reliable, is to use the multi-part flag supported by some browsers (such as Firefox) on the XMLHttpRequest object. The Ajax request is sent to the server and remains open, and each time an event arrives, a multipart response is written over the same connection. Listing 6 shows an example.

  Listing 6. Example JavaScript code to set up a Multi-part XMLHttpRequest

var xhr = $.ajaxSettings.xhr();
xhr.multipart =true;
xhr.open('GET', 'ajax', true);
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4) {
    processEvents($.parseJSON(xhr.responseText));
  }
};
xhr.send(null);

  On the server side, things are a little more complicated. First you have to set up multipart requests, then suspend the connection. Listing 7 shows how to suspend an HTTP streaming request. (Part 3 of this series will cover these APIs in more detail.)

  Listing 7. Using the Servlet 3 API to suspend an HTTP streaming request in a servlet

protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {   // start request pending   AsyncContext asyncContext = req.startAsync();   asyncContext.setTimeout(0);   // send back multipart delimiter to client   resp.setContentType("multipart/x-mixed-replace; boundary=\""   + boundary +"\"");   resp.setHeader("Connection", "keep-alive");   resp.getOutputStream().print( "--"+ boundary);   resp.flushBuffer();   // put the async context in the list for future use only   asyncContexts.offer(asyncContext); }













  Now, you can iterate over all pending connections and write data to them each time an event occurs, as shown in Listing 8:

  Listing 8. Using the Servlet 3 API to send events to pending multipart requests

for (AsyncContext asyncContext : asyncContexts) {
  HttpServletResponse peer = (HttpServletResponse)
  asyncContext.getResponse();
  peer.getOutputStream().println("Content-Type: application/json");
  peer.getOutputStream().println();
  peer.getOutputStream().println(new JSONArray()
  .put("At "+new Date()).toString());
  peer.getOutputStream().println("--"+ boundary);
  peer.flushBuffer();
}

  The section in the Comet-straming folder of the downloadable file for this article illustrates HTTP streaming, and when you run the example and open the home page, you'll see that events appear on the page almost immediately, albeit out of sync, as soon as they hit the server. Also, if you open the Firebug console, you can see that only one Ajax request is open. If you look a little further down, you'll see the JSON response attached in the Response tab, as shown in Figure 4:

  Figure 4. FireBug view of an HTTP streaming request

  As usual, the approach has some advantages and disadvantages:

  1. Advantages: Only one persistent connection is opened, which is the Comet technology that saves most of the bandwidth usage.

  2. Disadvantage: Not all browsers support the multi-part flag. Certain widely used libraries, such as the Java implementation of CometD, have been reported to have problems with buffering. For example, some data chunks (multiple parts) may be buffered and then sent only when the connection is complete or the buffer is full, which may introduce higher than expected latency.

  Comet using HTTP long polling

  Long polling (long polling) mode involves the technique of opening connections. The connection is kept open by the server, and as soon as an event occurs, the response is committed and the connection is closed. next. A new long-polling connection is reopened by the client waiting for new events to arrive.

  You can implement HTTP long polling using script tags or plain XMLHttpRequest objects.

  script tag

  Just like an iframe, its goal is to attach script tags to the page for script execution. The server side will: suspend the connection until an event occurs, then send the script content back to the browser, and then reopen another script tag to get the next event.

  1. Advantages: Because it is based on HTML tags, all this technology is very easy to implement and can work across domains (by default, XMLHttpRequest does not allow sending requests to other domains or subdomains).

  2. Disadvantages: Similar to iframe technology, error handling is missing, you can't get the status of the connection or have the ability to interfere with the connection.

  XMLHttpRequest long polling

  The second, and recommended way to implement Comet is to open an Ajax request to the server and wait for a response. The server side needs some specific functionality to allow the request to be suspended, as soon as an event occurs, the server side will send back the response in the pending request and close the request, exactly like you close the output stream of the servlet response . The client then uses this response and opens a new long-lived Ajax request to the server, as shown in Listing 9:

  Listing 9. Example JavaScript code to set up a long polling request

function long_polling() {
  $.getJSON('ajax', function(events) {
    processEvents(events);
    long_polling();
  });
}
long_polling();

  On the backend, the code also uses the Servlet 3 API to suspend requests, just as HTTP streams do, but you don't need all the multipart processing code, and Listing 10 gives an example.

  Listing 10. Suspending a long-polling Ajax request

protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
  AsyncContext asyncContext = req.startAsync();
  asyncContext.setTimeout(0);
  asyncContexts.offer(asyncContext);
}

  When the event is received, it simply fetches all pending requests and completes them, as shown in Listing 11:

  Listing 11. Completing a long-polling Ajax request when an event occurs

while (!asyncContexts.isEmpty()) {
  AsyncContext asyncContext = asyncContexts.poll();
  HttpServletResponse peer = (HttpServletResponse)
  asyncContext.getResponse();
  peer.getWriter().write(
    new JSONArray().put("At " + new Date()).toString());
  peer.setStatus(HttpServletResponse.SC_OK);
  peer.setContentType("application/json");
  asyncContext.complete();
}

  In the accompanying source download, the comet-long-polling folder contains a sample long polling web application that you can run with the mvn jetty:run command.

  1. Advantages: It is easy for the client to implement a good error handling system and timeout management. This reliable technique also allows a round trip between connections to the server, even if the connection is non-persistent (a good thing when your application has many clients). It works on all browsers; you just need to make sure that the XMLHttpRequest object you use is used to send simple Ajax requests.

  2. Disadvantages: Compared with other technologies, there are no important disadvantages. Like all the technologies we have discussed, this method still relies on stateless HTTP connections, which requires special functions on the server side. Hang up the connection.

  suggestion

  Because all modern browsers support the Cross-Origin Resource Share (CORS) specification, which allows XHR to perform cross-origin requests, script-based and iframe-based techniques have become an obsolete need.

  The best way to implement and use Comet as a Reverse Ajax is through the XMLHttpRequest object, which provides a real connection handle and error handling. Considering that not all browsers support the multi-part flag, and multi-part streams may encounter buffering issues, it is recommended that you choose to use the XMLHttpRequest object via HTTP long polling (a simple Ajax request that hangs on the server side) Comet mode, all browsers that support Ajax also support this approach.

  in conclusion

  This article provides an entry-level introduction to Reverse Ajax technology. It explores different ways to implement Reverse Ajax communication and explains the advantages and disadvantages of each implementation. Your specific situation and application needs will influence your choice of the most appropriate method. But in general, if you want the best compromise in terms of low-latency communication, timeout and error detection, simplicity, and good support for all browsers and platforms, then choose to use Ajax long-term Comet for polling requests.

This article series explores how to use Reverse Ajax (Reverse Ajax) technology to develop event-driven web applications. Part 1 introduces several different ways to implement reverse Ajax communication: polling (polling), piggyback (piggyback) ) and Comet using long-polling and streaming. In this article, we learn a new technique for implementing reverse Ajax: using WebSocket, a new HTML5 API. WebSocket can be implemented natively by browser vendors, or through a bridge that delegates calls to a hidden Flash component called FlashSocket. This article also discusses some of the server-side constraints imposed by Reverse Ajax techniques.

  foreword

  Today, users expect fast, dynamic applications that are accessible via the web. This article series shows how to use Reverse Ajax (Reverse Ajax) technology to develop event-driven web applications. Part 1 of the series covered Reverse Ajax, polling, streaming, Comet, and long polling. You've seen how Comet uses HTTP long polling, which is the best way to implement Reverse Ajax reliably, since all existing browsers support it.

  In this article, we will learn how to implement Reverse Ajax using WebSocket. Code examples are used to help illustrate WebSocket, FlashSocket, server-side constraints, request-scoped services, and suspending long-lived requests. You can download the source code used in this article.

  prerequisite

  Ideally, to fully appreciate this article, you should have some familiarity with JavaScript and Java. The examples created in this article were built using Google Guice, a dependency injection framework written in Java. To understand the content of this article, you should be familiar with the concepts of dependency injection frameworks such as Guice, Spring or Pico.

  To run the examples in this article, you'll also need the latest versions of Maven and the JDK (see Resources).

  WebSocket

  WebSocket, which appeared in HTML5, is a reverse Ajax technology that is newer than Comet. WebSocket enables a two-way full-duplex communication channel, which is supported by many browsers (Firefox, Google Chrome, and Safari). Connections are opened with an HTTP request known as the WebSocket handshake, which uses some special headers. The connection remains active, and you can use JavaScript to write and receive data as if using a raw TCP socket.

  The initial input for a WebSocket URL is ws:// or wss:// (on SSL).

  The timeline in Figure 1 illustrates communication using WebSocket. An HTTP handshake with specific headers is sent to the server, and then either the server or the client can use some kind of socket (socket) through JavaScript, which can be used to asynchronously communicate through event handlers. Receive data.

  Figure 1. Reverse Ajax using WebSocket

  When you run the WebSocket example in the source code downloadable for this article, you should see output similar to Listing 1. It explains how client-side events happen and how they are immediately displayed on the client side. When the client sends some data, the server responds to the client's sending behavior.

  Listing 1. WebSocket example in JavaScript

[client] WebSocket connection opened
[server] 1 events
[event] ClientID =0
[server] 1 events
[event] At Fri Jun 1721:12:01 EDT 2011
[server] 1 events
[event] From 0 : qqq
[server] 1 events
[event] At Fri Jun 1721:12:05 EDT 2011
[server] 1 events
[event] From 0 : vv

  Normally, in JavaScript you would use WebSocket as illustrated in Listing 2, if your browser supports it.

  Listing 2. JavaScript client example

var ws = new WebSocket('ws://127.0.0.1:8080/async');
ws.onopen = function() {     // called when the connection is opened }; ws.onerror = function(e) {     // at Called when an error occurs, such as when the connection is broken }; ws.onclose = function() {     // called when the connection is closed }; ws.onmessage = function(msg) {     // send a message from the server to the client // msg.data contains     the message }; // Here is how to send some data to the server ws.send('some data'); // Close the socket ws.close();















  The data sent and received can be of any type, WebSocket can be thought of as a TCP socket, so it's up to the client and server to know what type of data to send back and forth. The example here sends a JSON string.

  If you look closely at the HTTP request in your browser's console (or Firebug) after the JavaScript WebSocket object is created, you should see WebSocket-specific headers. Listing 3 gives an example.

  Listing 3. Example HTTP request and corresponding headers

Request URL:ws://127.0.0.1:8080/async
Request Method:GET
Status Code:101 WebSocket Protocol Handshake

Request Headers
Connection:Upgrade
Host:127.0.0.1:8080
Origin:http://localhost:8080
Sec-WebSocket-Key1:1 &1~ 33188Yd]r8dp W75q
Sec-WebSocket-Key2:17; 229 *043M 8
Upgrade:WebSocket
(Key3):B4:BB:20:37:45:3F:BC:C7

Response Headers
Connection:Upgrade
Sec-WebSocket-Location:ws://127.0.0.1:8080/async
Sec-WebSocket-Origin:http://localhost:8080
Upgrade:WebSocket
(Challenge Response):AC:23:A5:7E:5D:E5:04:6A:B5:F8:CC:E7:AB:6D:1A:39

  The WebSocket handshake uses all of these headers to authenticate and set up a long-lived connection. The WebSocket JavaScript object also contains two useful properties:

  ws.url: Returns the URL of the WebSocket server
  ws.readyState: Returns the value of the current connection state
  1. CONNECTING = 0
  2. OPEN = 1
  3. CLOSED = 2

  The processing of WebSocket on the server side is a little more complicated, and there is no Java specification that supports WebSocket in a standard way. To use the WebSocket functionality of a web container (such as Tomcat or Jetty), you have to tightly couple your application code with container-specific libraries to access the WebSocket functionality.

  The examples in the websocket folder of the sample code use Jetty's WebSocket API because we are using the Jetty container. Listing 4 shows the handler for WebSocket. (Part 3 of this series will use a different backend WebSocket API.)

  Listing 4. WebSocket handler for the Jetty container

public final class ReverseAjaxServlet extends WebSocketServlet {
  @Override
  protected WebSocket doWebSocketConnect(HttpServletRequest request,String protocol) {
    return [...]
  }
}

  As far as Jetty is concerned, there are several ways of handling the WebSocket handshake, the easier one is to subclass Jetty's WebSocketServlet and implement the doWebSocketConnect method. This method requires you to return an instance of Jetty's WebSocket interface, which you must implement and return some kind of endpoint that represents the WebSocket connection. Listing 5 provides an example.

  Listing 5. Example WebSocket implementation

class Endpoint implements WebSocket { Outbound outbound; @Override public void onConnect(Outbound outbound) {   this.outbound = outbound; } @Override public void onMessage(byte opcode, String data) {   // Called when a message is received   // You usually use This is the method } @Override public void onFragment(boolean more, byte opcode,byte[] data, int offset, int length) { //   When a piece of content is completed, onMessage is called   // Usually not written in this method something } @Override public void onMessage(byte opcode, byte[] data, int offset, int length) {   onMessage(opcode, new String(data, offset, length)); } @Override public void onDisconnect() {





















  outbound =null;
}
}

  To send a message to the client, you need to write a message to outbound, as shown in Listing 6:

  Listing 6. Sending a message to the client

if (outbound != null && outbound.isOpen()) {
  outbound.sendMessage('Hello World !');
}

  To disconnect and close the WebSocket connection to the client, use outbound.disconnect().

  WebSocket is a very powerful way to achieve two-way communication without delay, Firefox, Google Chrome, Opera and other modern browsers support this practice. According to the jWebSocket website:

  1. Chrome has included localized WebSocket since version 4.0.249.
  2. Safari 5.x includes localized WebSocket.
  3. Firefox 3.7a6 and 4.0b1+ include localized WebSocket.
  4. Opera has included localized WebSocket since 10.7.9.67.

  For more on jWebSocket, see Resources.

  advantage

  WebSocket is powerful, bi-directional, low-latency, and easy to handle errors. It doesn't have as many connections as Comet long polling, and it doesn't have some of the disadvantages that Comet streams have. Its API is also easy to use and can be used directly without an additional layer, while Comet requires a good library to handle reconnections, timeouts, Ajax requests, confirmations, and choosing different transports (Ajax long polling and jsonp round robin inquiry).

  shortcoming

  The disadvantages of WebSocket are these:

  1. is a new specification from HTML5, which is not yet supported by all browsers.

  2. There is no request scope (request scope), because WebSocket is a TCP socket rather than an HTTP request. Request services with scope, such as Hibernate's SessionInViewFilter, are not easy to use. Hibernate is a persistence framework that provides a filter around HTTP requests. At the beginning of the request, it sets a context (including transaction and JDBC connection) boundary in the request thread; at the end of the request, the filter destroys this context.

  FlashSocket

  For browsers that don't support WebSocket, there are libraries that fall back to FlashSocket (via Flash's socket). These libraries usually provide the same official WebSocket API, but they do so by delegating the call to a hidden Flash component included in the website.

  advantage

  FlashSocket transparently provides the functionality of WebSocket, even on browsers that do not support HTML5 WebSocket.

  shortcoming

  FlashSocket has the following disadvantages:

  1. It needs to install the Flash plug-in (usually, all browsers will have this plug-in).

  2. It requires that port 843 of the firewall is open, so that the Flash component can issue an HTTP request to retrieve the policy file containing the domain authorization. The library should have a fallback action or give an error if port 843 is unreachable, all of this processing takes some time (up to 3 seconds, depending on the library), and it slows down the website.

  3. Connections to port 843 may be rejected if the client is behind a proxy server.

  The WebSocketJS project provides a bridge that requires at least version 10 of Flash to provide WebSocket support for Firefox 3, Inernet Explorer 8 and Internet Explorer 9.

  suggestion

  Compared with Comet, WebSocket brings more benefits. In day-to-day development, client-side supported WebSockets are faster and generate fewer requests (thus consuming less bandwidth). However, since not all browsers support WebSocket, the best option for the Reverse Ajax library is to be able to detect support for WebSocket and fall back to Comet (long polling) if WebSocket is not supported. )superior.

  Since these two technologies need to get the best practices from all browsers and maintain compatibility, my suggestion is to use a client-side JavaScript library that provides an abstraction layer on top of these technologies. Parts 3 and 4 of this series explore some libraries, and Part 5 explains their applications. On the server side, as discussed in the next section, things are a little more complicated.

  Reverse Ajax constraints on the server side

  Now that you have an overview of the Reverse Ajax solutions available on the client side, let's look at the Reverse Ajax solutions on the server side. So far, the examples have used mostly client-side JavaScript code. On the server side, to accept reverse Ajax connections, certain technologies require specific functionality to handle long-lived connections compared to the short HTTP requests you're familiar with. In order to get better scalability, a new threading model should be used, which requires a specific API in Java to suspend requests. Also, as with WebSocket, you must properly manage the scope of the services used in your application.

  Threads and non-blocking I/O

  Typically, web servers associate a thread or process with each incoming HTTP connection. This connection can be persistent (keep-alive), so that multiple requests can be made over the same connection. In this example, the Apache web server can be configured in mpm_fork or mpm_worker mode to change this behavior. Java web servers (and application servers are included - it's the same thing) will typically use a separate thread for each incoming connection.

  Generating a new thread will cause memory consumption and resource waste, because it does not guarantee that the generated thread will be used. A connection may be established, but no data is being sent from the client or server. Regardless of whether this thread is used or not, it will consume memory and CPU resources for scheduling and context switching. Also, when configuring a server using threaded mode, you usually need to configure a thread pool (setting the maximum number of threads to handle incoming connections). If this value is misconfigured, too small, you will end up with thread starvation; requests will wait until a thread becomes available to process them, and response times will drop as the maximum number of concurrent connections is reached. On the other hand, configuring a high value can cause out-of-memory exceptions, and spawning too many threads can consume all available heap of the JVM, causing the server to crash.

  Java recently introduced a new I/O API called non-blocking I/O. This API uses a selector to avoid the practice of binding a thread every time a new HTTP connection is established on the server side. When data arrives, an event will be received, and then a thread will be allocated to handle the request. Therefore, this approach is called a thread-per-request pattern. It allows web servers, such as WebSphere and Jetty, to use a fixed number of threads to accommodate and handle increasing user connections. With the same hardware configuration, a web server running in this mode scales much better than one running in a thread-per-connection model.

  In Philip McCarthy's (author of Comet and Reverse Ajax) blog, there is an interesting benchmark on the scalability of these two threading modes (see Resources for links). In Figure 2, you'll find the same pattern: Threading stops working when there are too many connections.

  Figure 2. Benchmarks for threading mode

  One thread per connection mode (Threads in Figure 2) usually has a better response time, because all threads are started, ready and waiting, but when the number of connections is too high, it will stop Provide services. In the thread-per-request pattern (Continuations in Figure 2), threads are used to service incoming requests, and connections are handled through a NIO selector. Response time may be slower, but threads are recycled, so this solution scales better for high-capacity connections.

  To understand how threads work behind the scenes, think of a LEGO™ brick as a selector, identified by a pin every time an incoming connection reaches the LEGO brick. LEGO bricks/selectors have as many pins (as many keys) as there are connections. Then, only one thread is needed to wait for new events to occur, and then iterate over these pins. When something happens, the selector thread retrieves the key value from the event, and then a thread can be used to service the incoming request.

  The "Rox Java NIO Tutorial" tutorial has good examples of using NIO in Java (see Resources).

  Services with request scope

  Many frameworks provide services or filters to handle web requests to servlets. For example, a filter would:

  1. Bind the JDBC connection to a request thread so that only one connection is used for the entire request.

  2. Commit the changes at the end of the request.

  Another example is the Guice Servlet extension for Google Guice (a dependency injection library). Like Spring, Guice can bind services within the scope of a request, with an instance being created at most once for each new request (see Resources for more information).

  Common practices include caching the user object retrieved from the repository in the request using the user id, which is taken from the clustered HTTP session. In Google Guice, you might have code like that shown in Listing 7.

  Listing 7. Request-scoped bindings

@Provides
@RequestScoped
Member member(AuthManager authManager,
MemberRepository memberRepository) {
  return memberRepository.findById(authManager.getCurrentUserId());
}

  When a member is injected into a class, Guice will try to get the object from the request, if not found, it will perform a repository call and put the result in the request.

  Request scoping can be used with any reverse Ajax solution other than WebSocket, any other solution that relies on HTTP requests, short or long lived, each request will pass through servlet distribution system, filters will be executed. When completing a paused (long-lived) HTTP request, you will learn in subsequent parts of this series that there is another way to make the request go through the filter chain again.

  For WebSocket, data arrives directly on the onMessage callback function, just like in the case of TCP sockets. There is no HTTP request to deliver this data, so there is no request context to fetch or store scoped objects. So using a service that requires a scoped object in the onMessage callback will fail. The guice-and-websocket example in the downloadable source code shows how to bypass this restriction so that request-scoped objects can still be used in the onMessage callback. When you run this example and click each button on the web page to test an Ajax call (request-scoped), a WebSocket call, and a WebSocket call using a mock request scope, you get the results shown in Figure 3. output shown.

  Figure 3. WebSocket handler using request-scoped services

  You may encounter these problems when using any of the following techniques:

  1. Spring

  2. Hibernate

  3. Any other framework that requires a request-scoped or per-request model, such as OpenSessionInViewFilter.

  4. Any system that uses the ThreadLocal facility inside a filter to scope variables to the requesting thread and access those variables later.

  Guice has an elegant solution, shown in Listing 8:

  Listing 8. Simulating a request scope in WebSocket's onMessage callback

// When calling doWebSocketMethod
// save a reference to the request
HttpServletRequest request = [...]
Map, Object> bindings = new HashMap, Object>();
// I have a service that needs a request to get a session
// so I provide a request, but you can provide any other
bindings you might need
bindings.put(Key.get(HttpServletRequest.class), request);
ServletScopes.scopeRequest(new Callable() {   @Override   public Object call() throws Exception {   // call your repository or any service     outbound.sendMessage([...]);     return null;   } }, bindings).call();






  Suspend long-lived requests

  If using Comet, there is another obstacle, that is, how does the server side suspend a long-lived request without affecting performance, and then resume and complete the request as quickly as possible when the server-side event arrives?

  Obviously, you can't simply let the requests and responses sit there, that would lead to thread starvation and high memory consumption. Suspends a long-lived request in non-blocking I/O, which requires a unique API in Java. The Servlet 3.0 specification provides such an API (see Part 1 of this series). Listing 9 gives an example.

  Listing 9. Using Servlet 3.0 to define an asynchronous servlet

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:j2ee="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml
/ns/j2ee/web-app_3.0.xsd">

<servlet>
<servlet-name>events</servlet-name>
<servlet-class>ReverseAjaxServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>

<servlet-mapping>
<servlet-name>events</servlet-name>
<url-pattern>/ajax</url-pattern>
</servlet-mapping>

</web-app>

  After defining an asynchronous servlet, you can use the Servlet 3.0 API to suspend and resume a request, as shown in Listing 10:

  Listing 10. Suspending and resuming a request

AsyncContext asyncContext = req.startAsync();
// save a reference to asyncContext somewhere

// then when needed, in another thread you can resume and complete
HttpServletResponse req =
(HttpServletResponse) asyncContext.getResponse();
req .getWriter().write("data");
req.setContentType([...]);
asyncContext.complete();

  Before Servlet 3.0, each container had and still has its own mechanism. Jetty continuations are a well-known example; many reverse Ajax libraries in Java rely on Jetty continuations. It's not fancy, and it doesn't require your application to run on a Jetty container. The clever thing about this API is that it detects which container you're running in, and if it's running on another container, like Tomcat or Grizzly, then falls back to the Servlet 3.0 API if it's available. This is fine with Comet, but currently you have no choice but to use container-specific features if you want to take advantage of WebSocket.

  The Servlet 3.0 specification has not yet been released, but many containers have implemented this API, as it is also a standard practice for implementing Reverse Ajax.

  conclusion

  WebSocket, despite its shortcomings, is a very powerful reverse Ajax solution. It's not currently implemented in all browsers, and it's not easy to use on the Java server side without the help of a Reverse Ajax library. Because you're not using the standard request-response style, you can't rely on scoped execution of the filter chain. Comet and WebSocket require server-side container-specific features, so when using a newer container, you need to be aware that it may not be extended in this regard.

  Stay tuned for Part 3 of this series, which explores the different server-side APIs for Comet and WebSocket, and you'll also learn about Atomsphere, a reverse Ajax framework.

  download

  Description name size download method

  Article source code reverse_ajaxpt2_source.zip 14KB    HTTP

  References

  1. " Start using HTML5 WebSockets today " (Nettuts+): Revisit how to run a WebSocket server in PHP, and consider how to build a client to send and receive messages over the WebSocket protocol.

  2. " The WebSocket API " (W3C, July 2011): The API defined by this specification enables web pages to use the WebSocket protocol to communicate with remote hosts in two directions.

  3.  Browsers supported by jWebSocket : Understand all aspects of browsers supported by jWebSocket and Flash socket bridge.

  4. Learn more about Servlet 3.0's support for asynchronous processing .

  5. Philip McCarthy's blog post Comet & Java: Threaded Vs Nonblocking I/O has more content.

  6. The Rox Java NIO Tutorial This tutorial collects some of the author's experience in using the Java NIO library, as well as dozens of tips, tricks, suggestions, and admonitions that flood the Internet.

  7. Read about these on Wikipedia:

  7.1 Ajax
  7.2 Reverse Ajax
  7.3 Comet
  7.4 WebSockets

  8. " Exploring Reverse AJAX " (Google Maps .Net Control Blog, August 2006): Get some introductory notes on reverse Ajax techniques.

  9. " Cross-domain communications with JSONP, Part 1: Combine JSONP and jQuery to quickly build powerful mashups " (developerWorks, February 2009): Learn how to combine the humble cross-domain communication technique (JSONP) with a flexible JavaScript library ( JQuery) combined to build some powerful aggregation applications with astonishing speed.

  10. " Cross-Origin Resource Sharing (CORS) " specification (W3C, July 2010): Learn more about this mechanism, which allows XHR to perform cross-origin requests.

  11. " Build Ajax applications with Ext JS " (developerWorks, July 2008): Get an overview of this framework that greatly enhances JavaScript development.

  12. " Compare JavaScript frameworks " (developerWorks, February 2010): Gain a holistic view of the frameworks that have greatly enhanced JavaScript development.

  13. " Mastering Ajax, Part 2: Make asynchronous requests with JavaScript and Ajax " (developerWorks, January 2006): Learn how to use Ajax and the XMLHttpRequest object to create a request/response model that never makes the user wait for the server to respond.

  14. " Create Ajax applications for the mobile Web " (developerWorks, March 2010): Learn how to use Ajax to build cross-browser smartphone Web applications.

  15. " Where and when to use Ajax in your applications " (developerWorks, February 2008): Learn how to use Ajax to improve your website while avoiding a bad user experience.

  16. " Improve the performance of Web 2.0 applications " (developerWorks, December 2009): Explore different browser-side caching mechanisms.

  17. " Introducing JSON " (JSON.org): Get an introductory introduction to JSON syntax.

  18.  developerWorks Web development zone : Get a variety of articles talking about Web-based solutions.

  19.  developerWorks podcasts : Listen to a variety of interesting interviews and discussions with software developers.

  20.  developerWorks technical events and webcasts : Keep an eye on developerWorks technical events and webcast progress.

  Get products and technologies

  1.  WebSocketJS (WebSocket Flash Bridge) : Get this HTML5 WebSocket implementation powered by Flash.

  2.  Google Guice : Get Google Guice, a lightweight dependency injection framework for Java 5 and above.

  3.  Jetty : Get Jetty, a web server and javax.servlet container, with support for WebSocket.

  4. Apache  Maven : Get Maven, a software project management and containment tool.

  5.  Java Development Kit, Version 6 : Get the Java Platform, Standard Edition (Java SE), which allows you to develop and deploy Java on desktops and servers, as well as in today's demanding embedded environments application.

  6. Try IBM software for free, download the use version, log in for online trial, use the product in a sandbox environment, or access it through the cloud. There are more than 100 trial versions of IBM products to choose from.

  discuss

  1. Create your developerWorks profile now and set up a watchlist on Reverse Ajax . Connect and stay connected with the developerWorks community .

  2. Find other developerWorks members interested in web development .

  3. Share your knowledge: Join a developerWorks group that focuses on web topics .

4. Roland Barcia talks about Web 2.0 and middleware  in his blog .

  5. Follow the shared bookmarks on web topics of developerWork members .

  6. Get answers fast: Visit the Web 2.0 Apps Forum .

  7. Get answers fast: Visit the Ajax Forum .

Guess you like

Origin blog.csdn.net/2301_77162959/article/details/131025413