dimanche 1 août 2010

RESTful client in JavaFX

In this second part, we are going to create a small application in JavaFX to call the restful service created in the first part.
This small application is the same as the one created in an older post : JavaFX and JPA 2.0 with my custom component, but instead of call directly the database with the help of an entity, we are going to call the restful service.

To create this application, we are going to create :
·         a Music JavaFX Bean as model
·         a client to the RESTFul services (and its JSON parser)
·         an JavaFX User Interface

The model
The model is a simple JavaFX Bean which maps one element of the JSON array which is returned when we call the RESTful service
·         An example of the JSON result when you call the service with: Arc as parameter
             
·         the Music JavaFX Bean

Music.fx
package model;

public class Music {
    public var id: Long;
    public var artisteName: String;
    public var albumTitle: String;

    override public function toString():String {
         return "id: {id} ,artisteName: {artisteName} ,albumTitle: {albumTitle}"
  }
}
The Client
Now, let's write the client.
The client is composed of 2 methods:
·         getArtisteNameBeginningBy, which calls the RESTful service by using the JavaFX's HttpRequest class
·         parse, which parses the JSON flux. This method is called by the onInput callback of the HttpRequest class.
The parsing, in itself, uses the JavaFX PullParser to parse the JSON stream and fill the Music JavaFX Bean, and the array of Music JavaFX Bean as the result of the parse method.
MusicClient.fx
package client.rest;

import javafx.data.pull.Event;
import javafx.data.pull.PullParser;
import com.sun.javafx.data.pull.impl.StreamException;
import java.io.InputStream;
import model.Music;
import javafx.io.http.HttpRequest;
import javafx.io.http.URLConverter;

public class MusicClient {

 public var musics:Music[];

 public function getArtisteNameBeginningBy(begining :String) {

     println("begining {begining}");

     var urlConverter = URLConverter{encodeSpaceAsPercent:true};
     var beginings = urlConverter.encodeString(begining);

    var request: HttpRequest = HttpRequest {

        location: "http://localhost:8080/RESTfulServices/rs/ArtisteNameBeginningBy/{beginings}"
        method: HttpRequest.GET

        onInput: function(input: java.io.InputStream) {
            try {
                musics = parse(input);
                //println("musics {musics}");
            } finally {
                input.close();
            }
        }
    }

    request.start();

}

  function parse(input: InputStream): Music[] {

    var musics: Music[];
    var music: Music;

    def parser = PullParser {

        documentType:PullParser.JSON
        input: input

        onEvent: function(event: Event) {

            if (event.type == PullParser.START_ARRAY_ELEMENT) {
                if(event.name == "music" and event.level == 0) {
                    music = Music { };
                }
            } else
            if (event.type == PullParser.END_ARRAY_ELEMENT) {
                if(event.name == "music" and event.level == 0) {
                   insert music into musics;
                }
            } else {
                if(event.name == "id" and
                   event.level == 1 and
                   event.type == PullParser.TEXT ) {

                    music.id = java.lang.Long.parseLong (event.text);

                } else
                if(event.name == "artisteName" and
                   event.level == 1 and
                   event.type == PullParser.TEXT  ) {

                    music.artisteName = event.text;

                } else
                if(event.name == "albumTitle" and
                   event.level == 1 and
                   event.type == PullParser.TEXT ) {

                    music.albumTitle = event.text;
                }
            }
        }
    }
    try{
        parser.parse();
    }catch (e: StreamException){
       println(e.getMessage())
    }
    return musics;
  }
}
The UI
The UI is the same as the UI used in the post: the JavaFX and JPA 2.0 with my custom component[2] , except the calls to the client of the service by the SearchTextBox component.
Main.fx
package javafxrestfulclient;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.control.ListView;
import customcomponent.SearchTextBox;
import client.rest.MusicClient;

var mc:MusicClient = MusicClient{};

Stage {
    title: "Application title"
    width: 600
    height: 250
    scene: Scene {
        stylesheets : ["{__DIR__}resources/mac.css"]
        content: [
            Text {
                font: Font {
                    size: 16
                }
                x: 10
                y: 30
                content: "Search DB"
            }
            SearchTextBox {
                styleClass : "searchTextBox"
                translateX: 10
                translateY: 40
                onResetSearch: function () {
                   println("reset !");
                   delete mc.musics;
                }
                onSearch: function (s: String) {
                    println("Search of : {s}");

                    delete mc.musics;
                    mc.getArtisteNameBeginningBy(s);
                    
                }
            }

            ListView {
                managed: false
                layoutY: 75
                width: 575
                height: 100
                items: bind mc.musics

            }
        ]
    }
}

Aucun commentaire: