JavaFX Tutorials

Tuesday, August 1, 2017

Wire Level REST Request Logging in TornadoFX

TornadoFX's Rest class integrates RESTful web service calls into your JavaFX app.  There is a switch you can set that will allow you to use the Apache HTTPClient in place of the native Kotlin implementaton typically used in TornadoFX.  One feature that this switch brings is wire-level logging.


This is abbreviated output to a RESTful call https://www.bekwam.net/data/customers.json.  (customer.json is actually a flat file, so don't get too creative with the requests!)

[DEBUG] headers - http-outgoing-0 >> GET /data/customers.json HTTP/1.1
[DEBUG] headers - http-outgoing-0 >> Host: www.bekwam.net
[DEBUG] wire - http-outgoing-0 >> "GET /data/customers.json HTTP/1.1[\r][\n]"
[DEBUG] wire - http-outgoing-0 >> "Accept-Encoding: gzip, deflate[\r][\n]"
[DEBUG] wire - http-outgoing-0 << "HTTP/1.1 200 OK[\r][\n]"
[DEBUG] wire - http-outgoing-0 << "Date: Wed, 02 Aug 2017 00:06:22 GMT[\r][\n]"

To use this in TornadoFX, add in the Apache HTTPClient dependencies to the runtime.  This screenshot is from IntelliJ.

Codec, Logging, HTTPClient, and HTTPCore Libraries Added
These libraries are part of the TornadoFX pom, but they're marked as "provided" to keep the footprint small.  If you don't put these on the classpath and continue with this example, you'll get a runtime error.  The versions can vary; these worked for me

  • commons-codec:commons-codec:1.10
  • org.apache.httpcomponents:httpclient:4.5.3
  • org.apache.httpcomponents:httpcore:4.4.6
  • commons-logging:commons-logging:1.2

Your application will also need the following JVM properties to turn on the logging.

  • -Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog 
  • -Dorg.apache.commons.logging.simplelog.log.org.apache.http=DEBUG  
  • -Dorg.apache.commons.logging.simplelog.log.org.apache.http.wire=TRACE


This TornadoFX program displays a single Button that will call a RESTful web service.  Feel free to run the program against the service. (It's just a file and not real server-side code.)

class RestTestController : Controller() {

    val api : Rest by inject()

    fun load() {
        val response = api.get("/customers.json")
        println("status=${response.status}")
    }
}

class RestTestView : View("My View") {

    val controller : RestTestController by inject()

    override val root = vbox {
        button("Load JSON" ) { 
           setOnAction {       
              controller.load()
        }       
     }   
   }
}

class RestTestApp : App(RestTestView::class) {

    val api : Rest by inject()

    init {
        Rest.useApacheHttpClient()
        api.baseURI = "https://www.bekwam.net/data"    }
}

The default REST implementation is easy-to-use, but if you need additional control to features such as this logging, you can swap out the implementation for the standard Apache HTTPClient with a single call.  You'll need to add some JARs to the classpath -- TornadoFX keeps the footprint small -- and configure the logging from the command line.  There's also a development scenario for temporarily using the Apache version to get your bearings with the API code and switching back once it's basically working.


No comments:

Post a Comment