Someone just pointed out that the light-weight XML parser included in Stringtree did not handle explicit CDATA blocks. The version in SVN now has provisional support for this.
If you need a simple and fast parser for textual data, then this should be all you need. For XML documents containing opaque binary data in a CDATA block, this may not be ideal. Currently CDATA blocks are loaded as String objects, and this can lead to incorrect data for bytes which do not represent valid characters in the current character set.
I am currently planning for the next version of the Stringtree XMLReader to offer the option of extracting a CDATA block as an unprocessed byte array.
I have experimented with Maven a few times, but never been particularly impressed.
Recently, however, one of my users has been bugging me to make the Stringtree and Mojasef classes and sources available in a Maven-style repository, for easier integration with Maven (or Maven-like) build tools and workflows. So I have done it. The current versions of key Stringtree and Mojasef files are now available from the Stringtree repository at the following URLs:
The Stringtree and Mojasef build scripts now include a “publish” target which uploads such artefacts to appropriate places in the repository, so future versions should continue to be available.
This is the first time I have done this, so I would welcome comments from any readers who actually use Maven (or buildr, or anything else which supports this repository format). In particular, I am interested in opinions on whether it is OK to simply replace artefacts with the same names and locations for minor tweaks and bug-fixes, or whether even the smallest change should result in the generation and upload of a new version with a new name and location.
This post is the first of a series describing the use and implementation of the Stringtree HTTP Client.
Recently I have been working with systems which talk to each other using REST/HTTP. Providing services and resources is pretty simple using Mojasef, but accessing such resources and consuming such services (in client code and in tests) has always seemed a bit more clumsy than it should be. I tried Apache HTTPClient and HttpUnit, but both seemed cumbersome for simple tasks, and bring in several hundred KB or more of dependencies, which can really bloat a small client application. I’m sure there are others, but I got bored with looking, and instead wrote my own simple HTTP Client which does the things I need without dragging in tons of extra stuff.
The Stringtree HTTP Client consists of just four classes, with no dependencies other than the standard Java APIs:
The point of these classes is to allow simple construction and calling of all valid HTTP requests, including the ability to set and read headers and cookies, simulate the submission of an HTML form, and support both textual and binary content data.
As a very simple example, consider the following code which issues a GET request to a specified URL:
HTTPClient client = new HTTPClient();
Document response = client.get("http://localhost:8080/?a=b");
System.out.println("response content type=" + response.getHeader("Content-Type"));
System.out.println("response content=" + response.getContentAsString());
The above code example shows basic usage of the Stringtree HTTP Client. In more general terms, usage is as follows:
- Create an object of the HTTPClient class.
- Set any long-lived settings, such as cookies or a user-agent.
- Call one of the request methods with appropriate parameters.
- Read returned headers and content as required from the returned Document object.
- Repeat from (3) for each new request.
A slightly more complex example using a POST request to submit an HTML form might look like:
HTTPClient client = new HTTPClient("Mozilla/5.0 (example)");
Form form = new Form();
Document response = client.post("http://localhost:8080/update", form);
boolean ok = "200".equals(response.getHeader(HTTPClient.HTTP_RESPONSE_CODE));
All the request methods return an org.stringtree.http.Document object. This object represents the structure of an HTTP request or response: a collection of name/value headers (which may contain duplicate names), and a block of “content” which may be considered as text or as a sequence of bytes. The HTTPClient code does make one simplifying concession; as seen in the above POST example the HTTP response code is added as a pseudo-header with the name “http.response.code”.
This should be enough to get started playing with the Stringtree HTTP Client. In the next post I will discuss the possibilities for creating and configuring an HTTPClient object in full detail.