IBM Research
 

Porting WBI Plugins from 4.3 and 4.4 to 4.5

Porting from WBI 4.1

If your plugin was written for WBI 4.1, you should first examine our instructions for Porting from 4.1 to 4.3

Porting from WBI 4.3 and 4.4

Porting in the strict sense of the word should not be necessary if your plugin works with WBI 4.3 or 4.4. WBI 4.5 is backwards-compatible with plugins written for WBI 4.3 and 4.4. However, a number of new APIs have been added to WBI 4.5 that should make plugins easier to write and in some cases allow better performance. In some cases, the new APIs provide a better way of performing some function and we have deprecated the old API. The old APIs still work in WBI 4.5, but we may stop supporting them or remove them from a future version of WBI. The improvements fall into a few major categories:

  • HTTP and MIME header parsing and storage
  • Use of character streams instead of byte streams for character data
  • Use of objects instead of byte streams for certain kinds of data
  • Simplified handling of request rejection by Megs
  • New classes for handling HTTP Cookie and Set-Cookie headers
Next we briefly discuss how to take advantage of the new APIs.

HTTP and MIME Headers

Here is a short list of classes that have been deprecated:

  • com.ibm.wbi.protocol.http.HttpRequest
  • com.ibm.wbi.protocol.http.HttpResponse
  • com.ibm.wbi.protocol.http.HttpBase
  • com.ibm.wbi.protocol.http.HttpHeader
Several new classes are added:
  • com.ibm.wbi.protocol.http.HttpHeaderAscii
  • com.ibm.wbi.protocol.http.HttpRequestHeader
  • com.ibm.wbi.protocol.http.HttpResponseHeader
  • com.ibm.wbi.util.MimeHeaderAscii
  • com.ibm.wbi.util.HeaderField
The HttpHeaderAscii class serves as a base class for HttpRequestHeader and HttpResponseHeader. There are several improvements over the old HttpRequest and HttpResponse classes. Request and response headers are treated equally and used internally by the DocumentInfo class. DocumentInfo now returns a reference to the HttpRequestHeader or HttpResponseHeader it is using internally. This allows a header field to be set or changed much more easily:
  HttpResponseHeader hrh = docinfo.getHttpResponseHeader();
  hrh.set("Content-Type", "text/html");
Contrast this with the old way of accomplishing the same operation:
  HttpResponse h = new HttpResponse(docinfo.getResponseHeader());
  h.set("Content-Type", "text/html");
  docinfo.setReponseHeader(h.produceHeaderWithoutContent());
The old way went through two unnecessary iterations of serialization and parsing which are now avoided. For more information, see the API documentation for HttpHeaderAscii, HttpRequestHeader, and HttpResponseHeader.

A new class is provided for dealing with parameterized headers. com.ibm.wbi.util.HeaderField allows you to deal conveniently with paramaterized headers. For example:

  DocumentInfo docinfo = (DocumentInfo)e.getRequestInfo();
  HttpResponseHeader hrh = docinfo.getHttpResponseHeader();
  HeaderField hf = hrh.parseHeaderField("Content-Type");
  String type = hf.getValue();
  String charset = hf.getParameter("charset");

  // If the original Content-Type was "text/html; charset=iso-8859-1",
  // "type" would now hold the string "text/html" and "charset" would
  // now hold the string "iso-8859-1".

  // Note that "hf" is a stand-alone object.  The next line will
  // change the charset for "hf", but not for "hrh":
  hf.setParameter("charset", "iso-2022-jp");

  // If you want the value changed in "hrh" as well, you must do this:
  hrh.set("Content-Type", hf);

For more information, see the documentation on MimeHeaderAscii and HeaderField.

Character Streams

WBI 4.5 introduces a new way to handle character data. Two new classes are added, com.ibm.wbi.MegReader and com.ibm.wbi.MegWriter. These classes handle streamed character data in a way analagous to the way com.ibm.wbi.MegInputStream and com.ibm.wbi.MegOutputStream have always handled binary data. All data objects transferred through WBI have a binary representation (i.e., a representation as an ordered stream of eight-bit bytes). Thus, the MegInputStream and MegOutputStream are still available to all Megs. However, many objects transferred (e.g., HTML files and text files) can be represented as characters rather than bytes. The MegReader and MegWriter are intended to be used for such objects.

To get the input for your Meg as a character stream, use com.ibm.wbi.RequestEvent.getMegReader(). The output writer is obtained from com.ibm.wbi.RequestEvent.getMegWriter(). It is possible that either of these methods will throw an exception. com.ibm.wbi.NotCharDataException is thrown if the input or output is not representable as a stream of characters. This is determined by looking at the Content-Type field of the appropriate header (request or response) at the time you make the call. For example, if you call getMegReader() and the content type is "image/gif", NotCharDataException will be thrown. The same is true of getMegWriter(). If you want to read in binary data and write out character data, this is possible. You need to make sure the content type is correct at the time you call getMegReader() or getMegWriter(). For example, if your Meg reads in GIFs and converts them to HTML files, you could do it like this:


  void handleRequest(RequestEvent e) throws IOException {
    DocumentInfo docinfo = (DocumentInfo)e.getRequestInfo();
    MegInputStream in = e.getMegInputStream();

    // Read in the GIF image from "in" into some object.

    // If you call getMegWriter() now, NotCharDataException will be
    // thrown, because the content type is still "image/gif".
    docinfo.getHttpResponseHeader().set("Content-Type",	"text/html");

    // Now you can safely call getMegWriter()
    MegWriter out = e.getMegWriter();

    // Write your HTML representation of the image to "out".

  }

The other exception that might be thrown by getMegReader() or getMegWriter() is java.io.UnsupportedEncodingException. This is a standard Java exception. It is thrown if the character stream uses an encoding that is not supported by your Java platform.

MegObjects

In addition to passing character streams and byte streams between Megs, it is now possible to pass objects. This functionality could be used, for example, to pass a parsed DOM tree between Megs, eliminating the need to repeated parsing and serialization. Even if you use this functionality, your Meg will still be able to interoperate with old Megs who do not use it. Objects that are passed to Megs which do not use the MegObject APIs will be automatically converted to byte or character streams. For more information, see the MegObject overview.

Request Rejection

There is now a simpler way for Megs to indicate that they may reject a request even after having read some of the input. Formerly, a Meg had to use com.ibm.wbi.MegInputStream.mark(). This was difficult to explain and could have caused further confusion with the introduction of MegReader and MegObject. Now, the method com.ibm.wbi.RequestEvent.mayReject() and com.ibm.wbi.RequestEvent.wontReject() handle this functionality for all types of input a Meg can receive. For more information, see the documentation for RequestRejectedException, RequestEvent.mayReject(), and RequestEvent.wontReject().

HTTP Cookies

The com.ibm.wbi.protocol.http.HttpCookie class has been reworked and the com.ibm.wbi.protocol.HttpSetCookie class has been added. These classes enable easy inspection of HTTP "Cookie" and "Set-Cookie" headers, respectively. For details, see the documentation for HttpCookie and HttpSetCookie.