Skip to main content

JavaFX HTTP Networking and XML Parsing

February 12, 2009

{cs.r.title}







The recently released JavaFX
platform
allows developers to build rich internet applications
(RIA) that can include audio and video. Using JavaFX, it is
possible to create highly interactive applications. Moreover, it is
possible to easily create content for different devices (desktop,
mobile phone, television, and so on). JavaFX is a compiled
language, like Java, and is highly portable and is based on the
familiar paradigm “Write Once, Run Everywhere.”

JavaFX is focused on the client side, and aims to improve the
look and feel of Java GUIs so that users can experience more
attractive interfaces. Of course, many client applications need to
exchange information with a remote server. Nowadays, the HTTP protocol
and XML are widely accepted as the best choices to exchange
information, so we want to show how easy is in JavaFX to handle
HTTP communication details and how we can parse and extract
information from an XML data structure.

In the article we will assume you are already familiar with the
basic notions of the JavaFX language.

JavaFX Basic Language Concepts

While it is a compiled language, JavaFX mixes the features of
scripting languages with those inherited from Java. Scripting
languages allow for fast and easy application development, while
JavaFX's Java-based heritage allow it to be a robust language.

JavaFX proposes a new coding paradigm: as a declarative
language, it compels us to describe how we want our application to
behave without describing the specific control flow, as we do with
imperative languages. This paradigm is really powerful when we need
to develop GUIs. The basic idea that stands behind that JavaFX GUI
development model is that you "describe" what your interface should
look like. There is a strict relationship between the code and the
"visual structure." Moreover, the order used to declare objects, in
the code, reflects the order used to display them. The overall
result is an elegant way to create a GUI in fewer lines of code; this
makes applications easier to understand and maintain.

Another interesting feature of JavaFX is that it is a statically
typed language, meaning the data type of every variable, function,
and so on is known at compile-time. See the "#resources">Resources section for links to JavaFX tutorials
that explore this trait further.

JavaFX HTTP and XML Package Overview

To develop an application using HTTP protocol and XML, JavaFX
provides several packages, which are shown below:

  • javafx.io.http for handling HTTP
    communication
  • javafx.data.pull and javafx.data.xml
    for XML parsing

The class diagram in Figure 1 shows the classes contained in
these packages.

HTTP and XML packages and classes
Figure 1. Defining the channel rule for the RDBMS Event Generator (click for larger
view)

HTTP and JavaFX

To handle the HTTP protocol, we can use HttpRequest
class in the javafx.io.http package. This class makes
asynchronous HTTP requests to a remote server that supports the HTTP
protocol. The HTTP methods currently supported are:

  • GET
  • POST
  • PUT
  • DELETE

This class is neutral in respect to the data format exchanged, so
we can invoke a remote server and send whatever type of
information we like, as long as we supply an
OutputStream containing the data that must be sent,
using the POST or PUT HTTP methods.

The HttpRequest operation, related to each HTTP
method supported, has a specific lifecycle. We focus our attention
on the lifecycle in the case of HTTP GET method; for other methods
(POST, PUT, DELETE), the lifecycle is very similar. In the
case of an HTTP GET request, the lifecycle is shown in Figure
2.

HTTP GET method request life-cycle
Figure 2: HTTP GET method request lifecycle (click for larger
view)

As we can see from the diagram above, each state of the
lifecycle is defined by a specific value of the internal variables
of the HttpRequest class. Related to each variable
transition, there is a corresponding method that is called during
the transition itself, so that we can control and handle different
states in the HTTP lifecycle. These methods have the same name of
the corresponding variable, prepended with on. For
example, if we want to track when the request is trying to connect
to the server, we will use the onConnecting
function.

It is time we start coding our JavaFX HTTP client. First of all
we have to declare a variable that contains our URL:


def url : String = "http://www.java.net";

Then we create the HTTP request and define our callback
function, which is called when the HTTP request starts
connecting.


HttpRequest {
        location: url;
        onConnecting: function() {
          java.lang.System.out.println("Connecting");
        }
}.enqueue();

Notice the method enqueue() that makes the
request.

Now we want to read the response body. We can do that using the
InputStream provided by the function
onInput. We need to add this piece of code to our
client.


    onInput: function(is: InputStream) {
      try {
        var responseSize : Integer = is.available();
        java.lang.System.out.println("Response size {responseSize}");
      }
      finally {
        is.close();
      }
    }

The last step is to handle any exceptions that can occur during
the HTTP request. The HTTPRequest has a function that
is called whenever an exception occurs. So we can add the
exception-handling code below to our client.


    onException: function(ex : Exception) {
      System.out.println("Error: {ex.getMessage()}");
    }

If you run the client using NetBeans, you should see output
similar to Figure 3:

<br "Client log" />

Figure 3: Client log

In the package javafx.io.http, there are two other
classes called HttpHeaders and
HttpStatus. The first class defines a set of constants
that map the corresponding HTTP header value names. The second
class defines a set of constants corresponding to the possible HTTP
response codes.

XML API

As we said, many clients today send data over HTTP using an
XML format, and JavaFX offers the capability to easily parse an XML
document. We focus our attention now on the other
two packages, shown before in Figure 1:

  • javafx.data.xml
  • javafx.data.pull

The package javafx.data.pull contains the classes
to parse an XML document, while the javafx.data.xml
package defines some constants and handles qualified names. The
parser is event-based (similar to the "http://java.sun.com/javase/6/docs/api/javax/xml/parsers/SAXParser.html">
SAX parser
) and it supports two different data formats:

  • XML
  • JSON

For this article, we'll focus our attention on the XML data
format.

The PullParser class, the heart of JavaFX's
document parser, accepts several attributes that can be used to
control the parser. First of all, we need to declare the document
type we want to parse, which we do by using the class attribute
documentType. This string can have two values:

  • PullParser.XML is used for parsing XML
  • PullParser.JSON is used for parsing JSON

After we declare the document type, we need to supply the input
document to parse. The parser accepts an input stream, and as we
will see later, this is very handy when we need to parse an XML
document retrieved from an HTTP request. To declare the input
stream we need to set the value of the input
variable.

So it is time we create an instance of our
PullParser, as shown below:


 parser = PullParser {
  documentType: PullParser.XML;
  input: xmlFileInputStream;
}

While the parser analyzes the document, it generates a set of
events. We need to implement a callback function to be called in
response to these events. The callback function is called
onEvent and in its body, we implement our logic to
extract information from the document, which we will do later.

The function signature is onEvent(event : Event),
where the Event class belongs to the package
javafx.data.pull. This class contains all the
information related to the pull-parsing event, and we can use it to
extract the information we need. The type declares the
type of event, as one of the values defined in
PullParser. We are interested in the following types of
events:

  • START_DOCUMENT: This event is generated at the
    beginning of document parsing.
  • START_ELEMENT: This event is generated when the
    parser finds a new starting element. We can use this event to read
    the element attribute.
  • END_ELEMENT: This event is generated when the
    parser finds the end of the element. We can use it to read the text
    contained in the element.
  • END_DOCUMENT: This event is generated when the
    parser reaches the end of the document.

There are other events that can be used for JSON
documents; if you're interested, have a look at the "http://java.sun.com/javafx/1/docs/api/javafx.data.pull/javafx.data.pull.PullParser.html">
PullParser
documentation. At any rate, here's an
onEvent skeleton implementation to react to the
START_ELEMENT and END_ELEMENT events.


  onEvent: function(event : Event) {
        /* We start analyzing the different event types */
        if (event.type == PullParser.START_ELEMENT) {
          /* Here we implement our logic to handle the start element event, 
            for example to extract the attribute values and so on */
        }
        else if (event.type == PullParser.END_ELEMENT) {
          /* Here we implement our logic to handle the end element */
        }
  }

During the parsing process, some errors can occur. We can manage
them verifying the type of Event generated by the
parser.

Integrating the HTTP and XML APIs

Now that we have described these two APIs, it is time we look at
the most interesting part: how we can integrate everything so that
we can code a complete XML-over-HTTP client. This can be useful if
we want to have a client that exchanges information with a remote
server.

Let's suppose that our JavaFX client application invokes a
servlet that returns an XML file with the structure shown
below:


&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;data&gt;
  &lt;person id="1"&gt;
        &lt;name&gt;Mikey&lt;/name&gt;
        &lt;surname&gt;Mouse&lt;/surname&gt;
  &lt;/person&gt;
&lt;/data&gt;

This is a simple XML file, but it is enough for the purpose of
our example. Our goal is for our client to connect to the test
servlet and retrieve the XML content, and then parse it and show the
extracted information. To do that, we need to change the
HttpRequest function onInput so that
when we start receiving the XML document we parse it, too. The code
below shows how to do it:


  onInput: function(is: InputStream) {
    try {              
      PullParser {
        input: is;
        onEvent: function (event : Event) {                     
                  // We handle the event
                }
          }.parse();
    }
    finally {
      is.close();
    }   
  }     

Notice how we have added the PullParser to the
onInput function, and that we set the parser input
stream to the one received from the HttpRequest. Now
we just need to handle the events as we described before:


....
    if (event.type == PullParser.START_ELEMENT and event.level == 1) {
      java.lang.System.out.println("Start a new element {event.qname.name}");
      var qAttr : QName = QName {name : "id"};
      var attVal : String = event.getAttributeValue(qAttr);
      java.lang.System.out.println("Attribute ID value {attVal}");
    }
    else if (event.type == PullParser.END_ELEMENT) {
      var nodeName : String = event.qname.name;
      java.lang.System.out.println("End element {nodeName}");
      // Now we extract the text only if the node is name or surname
      if (nodeName == "name" or nodeName == "surname") {
        var textVal : String = event.text;
        java.lang.System.out.println("Text {textVal}");
      }
    }

....

It is useful to analyze the code step by step. In the case of a
PullParser.START_ELEMENT event, we use the
event.level variable. This tells us at which line the
event occurs (starting from zero, the XML document root). We know
already that the id attribute is present only on the
first line, so we limit the extraction to this line only. Then we
create a QName object setting, the name
variable to our attribute name, and then we extract the value.

In the case of PullParser.END_ELEMENT, we want to
extract the node content. To do this, we use the text
variable that contains the node value.

If everything works properly we will see the parsed items in the
console, as shown in Figure 4.

"470" alt="HTTP request with XML parsing" />

Figure 4. HTTP request with XML parsing

Conclusion

In this article, we explored some essential features of JavaFX,
focusing our attention on two important aspects: XML and HTTP. We
discovered how easy is to develop a simple client that makes an HTTP
request and parses the XML response. This is a basic example, but it
can be further expanded adding other features; for example,
connecting to a site and retrieving pictures.

Resources


width="1" height="1" border="0" alt=" " />
Francesco Azzola is an electronic engineer with more than ten years' experience in architecting and developing EE applications.
Related Topics >> Web Services and XML   |   

Comments

POJOs can do the same

Nice writeup! Motivated me to do a little comparison to plain old Java objects here: http://www.uhilger.de/default/2009/02/25/1235516714487.html

POJOs can do the same

hi, Where is the binding to an opengl hardware accelerated visual container for the XML content... KArel

POJOs can do the same

Karel, do you refer to my blog post? It does not have such binding. My blog post only describes how to do HTTP requests and parse XML responses with POJOs. I.e., the same what is described here for JavaFX. Ulrich

just simplify a development environment

thanks for the article, as I read last, JavaFX was a great technology introduced, in fact environment development support, interoperability and simplifying programming model are also a main reason to implement this technology at period of time.

Nice Sample Article explaining HTTP and XML usage in JavaFX

Hi I am newbies in JavaFX and this article provides very nice initial understanding how JavaFX generates a HTTP request and parse the response XML I have a same small module in my project which generates a WebService and parse response XML It would be great if you let me know any more information on this same subject for my reference. Thanks

Hi, Does anyone have the

Hi, Does anyone have the sample code for this article? I`m new to Java FX, I would like also to ask if someone can help me do a Sax Parser in FX, and build a DOM tree after that :) Thanks