Skip to main content

JavaFX RESTful Pet Catalog Client

Posted by caroljmcdonald on February 7, 2009 at 7:19 PM PST




http-equiv="content-type">
javafx



Pet Catalog Photos : JavaFX Example Application

Pet Catalog Photos is a simple JavaFX application that displays pet
photos retrieved from a RESTful Pet Catalog app (implemented using
JAX-RS) described in an earlier href="http://weblogs.java.net/blog/caroljmcdonald/archive/2008/08/a_restful_pet_c_1.html">blog
entry and in this href="http://www.netbeans.org/kb/docs/websvc/pet-catalog-screencast.html">screencast. 
This JavaFX example is a modification of the href="http://javafx.com/samples/InterestingPhotos/index.html">Interesting
Photos : JavaFX Example Application.

catalogclient.jpg src="http://weblogs.java.net/blog/caroljmcdonald/archive/catalogclient.jpg"
height="320" width="240">



Understanding the Code


Code Sample from:
 style="color: rgb(0, 0, 0);"> main.fx


      //
Application User Interface

def stage = Stage {

    title: "Pet Catalog"

    resizable: false

    x: bind stageX with inverse

    y: bind stageY with inverse

    width: stageWidth

    height: stageHeight

    visible: true

    style: StageStyle.TRANSPARENT

    scene: Scene {

        content: Group {

           
content: bind stageContent

           
clip: Rectangle {

               
width: stageWidth

               
height: stageHeight

               
arcWidth: 20

               
arcHeight: 20

            }

        }

        fill: Color.TRANSPARENT

    }

}



Stage is the  top level container window required to
display any visible JavaFX objects. The variables title, width
and height
define the the text that appears on the window's top border and its
height and width.

The scene variable defines an instance of the Scene
object literal, which sets the area in which you can place the JavaFX
objects.

Scene is a drawing surface for graphical content and a
container that holds the scene graph nodes. It can be added to Stage,
and JavaFX renders everything on a scene.

The scene instance
variable has a content
variable that is used to hold JavaFX graphical elements and defines the
graphical content of the application. Here the content consists of a Group
Node . The Group Node has
content
variable which is a sequence of child Nodes that will be rendered in
order whenever this Group is rendered. The Group Node has
a clip


variable which specifies a Rectangle which defines the the clipping
shape for this Group
Node.



stage5_1_1_1.JPG



The Group Node content
variable has a data binding  with stageContent
Data binding
allows creating a direct and immediate relationship
between two variables or between a variable and the outcome of a
function or an expression.  
stageContent 
is a sequence of Nodes as shown in the code
below.  Node - is an element in a scene graph. The
following visual objects are examples of javafx.scene.Node
implementations: javafx.scene.image.ImageView, javafx.scene.media.Mediaview,
javafx.ext.swing.*, javafx.scene.shape.*,
and javafx.scene.text.Text. These are leaf nodes, which
cannot have a child element.




 
   
     
Code Sample from: style="color: rgb(0, 102, 0); font-weight: bold;"> style="color: rgb(0, 0, 0);"> main.fx


      //
Application User Interface

var stageContent: Node[];

     

stageContent = [

        bgImage, titleBar,
nextButton, backButton, closeButton,

        titleText, statusText,
thumbImageViewGroup, fullImageView

];

     



stage3.gif

A grid of ImageView is added to
Scene of Stage.




The thumbImageViewGroup variable has a data
binding  with thumbImageViews which is a sequence of

ThumbImageView
which extends ImageView.
ImageView
is a Node used for painting
images loaded with href="http://java.sun.com/javafx/1/docs/api/javafx.scene.image/javafx.scene.image.Image.html">Image
class.  The code below shows how the  thumbImageViews sequence
is initialized to a  grid of  3 columns and 3 rows of  ThumbImageView
.





 
   
     
Code Sample from:  main.fx


var thumbImageViews: ThumbImageView[]; // Thumbnail
images

for(col in [0..2]) {

    for(row in [0..2]) {

        def thumbImageView =
ThumbImageView {

            x:
thumbBaseX + (col * (thumbSize + thumbSpace))

            y:
thumbBaseY + (row * (thumbSize + thumbSpace))

           
fitWidth: thumbSize

           
fitHeight: thumbSize

        }

        insert thumbImageView into
thumbImageViews;

    }

}

var thumbImageViewGroup = Group {

    content: bind thumbImageViews

}

     


calling the RESTful  Pet Catalog Web Service 



Information and URLs for pet photos is obtained by performing an HTTP
GET request on a RESTful Catalog service by using the JavaFX
asynchronous HTTP API
(javafx.io.http.HttpRequest).  HttpRequest
allows one to specify a location and method
and start a HTTP operation with the function enqueue()
The content of the HTTP response can be accessed in the onInput
callback function. onInput calls the PhotoPullParser.parse
function to parse the XML.The onDone Callback is invoked
when the request has finished execution, onDone calls
the updateImages() function, explained later, which
updates the images displayed in the Photo-Grid. 








 
   
     
Code Sample from: main.fx


function loadImageMetadata() {

    var start=page * 9;  

    var request: HttpRequest = HttpRequest {

       

        location:
"http://localhost:8080/catalog/resources/items/?start={start}&max=9"

        method: HttpRequest.GET

           

        onInput: function(input:
java.io.InputStream)
{                            
     

            
var parser = PhotoPullParser{};

            
photos = parser.parse(input);    

        }

           

        onDone: function() {

            
updateImages();

        }

    }

    request.enqueue();

}

     


The response XML document contains a list of
information about available photos. The document
contains the following information about each photo:

  • id
  • imagethumburl
  • imageurl
  • server
  • name
  • price
  • productid
  • description

Here is example XML returned from the RESTFul Catalog Service:

   

 uri="http://localhost:8080/catalog/resources/items/">

       uri="http://localhost:8080/catalog/resources/items/1/">

          
This black and white colored cat is super
friendly./description>

          
1

          
http://localhost:8080/catalog/images/anthony-s.jpg

          
http://localhost:8080/catalog/images/anthony.jpg

          
Friendly Cat

          
307.10

          
feline01

      

   ...

  




The
response document is
parsed by using the JavaFX XML pull parser
(javafx.data.pull.PullParser) to
extract information about
the photos.

The parser supplies a sequence of Events as it process the document
under application control. XML and JSON are the two data formats
currently supported.  The PullParser can be used with the
onEvent
callback, which reports the current parse event.  The
onEvent
callback shown below parses the xml item elements
into an instance of the Photo class. When the item END_ELEMENT 
, , 
is reached,  the
photo 
variable is inserted into the photos sequence.





 
   
     
Code Sample from: PhotoPullParser.fx

     
import javafx.data.pull.PullParser;

     

public class PhotoPullParser {

     

  public function parse(input: InputStream): Photo[] {

     

    // Information about all catalog photos

    var photos: Photo[];

    var photo: Photo;

     

    // Parse the input data (Photo Metadata) and
construct Photo instance

    def parser = PullParser {

     

        input: input

     

        onEvent: function(event:
Event) {

            if
(event.type == PullParser.START_ELEMENT) {

               
if(event.qname.name == "item" and event.level == 1) {

                   
photo = Photo { };

               
}

            }
else

            if
(event.type == PullParser.END_ELEMENT) {

               
if(event.qname.name == "item" and event.level == 1) {

                  
insert photo into photos;

               
} else

               
if(event.qname.name == "id" and event.level == 2) {

                   
photo.id = event.text;

               
} else

               
if(event.qname.name == "name" and event.level == 2) {

                   
photo.name = event.text;

               
} else

               
if(event.qname.name == "imagethumburl" and event.level == 2) {

                   
photo.imagethumburl = event.text;

               
} else

               
if(event.qname.name == "imageurl" and event.level == 2) {

                   
photo.imageurl = event.text;

               
} else

               
if(event.qname.name == "description" and event.level == 2) {

                   
photo.description = event.text;

               
} else

               
if(event.qname.name == "productid" and event.level == 2) {

                   
photo.productid = event.text;

               
}

            }

        }

    }

    parser.parse();

    return photos;

  }

}

     

A sequence of photo objects is constructed by parsing
the response
XML.


Code Sample from: Photo.fx


public class Photo {

    public var id: String;

    public var imagethumburl: String;

    public var imageurl: String;

    public var name: String;

    public var price: String;

    public var description: String;

    public var productid: String;

}

     





The onDone
Callback is invoked when the HttpRequest
has finished execution, onDone calls the
updateImages()
function, shown below.




Code Sample from:  main.fx


// Load image and data specified in given Photo object

function loadImage(photo: Photo, thumbImageView: ThumbImageView): Void
{

    thumbImageView.image = Image {

        url: "{photo.imagethumburl}";

        width: thumbSize

        height: thumbSize

        backgroundLoading: true

        placeholder:
thumbImageView.image

    };

    thumbImageView.photo = photo;

  

// Update images displayed in Photo-Grid

function updateImages() {

    for(i in [0..8]) {

        var photoIndex = i;

       
loadImage(photos[photoIndex], thumbImageViews[i]);

    }

}

     

updateImages updates
the images displayed in the thumbImageViewGroup by 
updating the thumbImageView Image URLs to
the photo URLs parsed from the HTTP response style="font-family: monospace;">.

The photos are then fetched and displayed in Stage as a
grid. The imagethumburl
, imageurl are used
to
retrieve and
then display photos. The ImageView
class knows how to
retrieve the image using the URL and display it. Once the photo is
retrieved,
it is displayed in Scene of class="code-attribute">Stage through the use
of data binding.





If the user clicks a thumb photo, the normal photo is loaded and
shown.

catalogclientlarge.jpg




When the user clicks a thumb photo, the ThumbImageView
onMouseClicked
function sets the fullImageView url to the clicked photo's
larger image url and sets the fullImageView show variable to true.




Code Sample from:  main.fx


// Initialize fullscreen ImageView

var fullImageView = FullImageView {

    translateX: thumbBaseX

    translateY: thumbBaseY

    visible: false

}

     

// To display thumb image

class ThumbImageView extends ImageView {

   

    public override var onMouseClicked =
function(e:MouseEvent) {   

      // Load larger image

      fullImageView.image = Image {

         url: "{photo.imageurl}"

         placeholder: image

         backgroundLoading: true

       };

    }  

    fullImageView.show = true;

}

     

When the fullImageView show variable is set to true,
The FullImageView Node's 
visible variable
is set to true which
specifies that this
Node and any subnodes should be rendered as part of the
scene graph. The  fader() function causes the fullImageView
to fade in or out. The FullImageView Node's  style="font-weight: bold;"> opacity
 style="color: rgb(204, 0, 0); font-weight: bold;"> 
variable
specifies how opaque (that is, solid) the Node appears. Animation
occurs along a timeline, represented by a
javafx.animation.Timeline object. Each timeline contains one or more
key frames, represented by javafx.animation.KeyFrame objects. The value
of the time instance variable, 3s,
defines the elapsed time at which the values within the key frame will
be set in a single cycle of the Timeline object. The play()
method plays the timeline as defined.




Code Sample from:  FullImageView.fx


public class FullImageView extends ImageView {

     

    public var show = false on replace {

        if(useEffects) {

           
fader();

        } else {

            style="color: rgb(204, 0, 0);">visible = show;

        }

    }

    var timeline:Timeline = Timeline {

        rate: bind timelineRate with
inverse

        keyFrames: [

           
KeyFrame {

               
time: 3s

               
values: [ opacity
=> 1.0 tween Interpolator.LINEAR ]

            }

        ]

    };

    function fader() {    

        if(show) {

           
timeline.time = 0s;

           
timelineRate = 1.0;

           
      opacity
= 0.0;

            style="color: rgb(204, 0, 0);">visible = true;

        } else {

           
timeline.time = 3s;

           
timelineRate = -3.0;

            style="font-weight: bold; color: rgb(204, 0, 0);">opacity = 1.0;

        }   

        timeline.play();

    }

     



stage4.gif



Clicking the normal photo again restores the thumb photo grid. The user
can
navigate to the next or previous set of photos by clicking << and
>> arrow buttons. 
Clicking the nextButton calls the onNext() function which increments
the page number and calls loadImageMetadata();



Code Sample from:  main.fx


// Display next set of photos

var nextButton = ImageButton {

    selectImage: Image {

        url:
"{__DIR__}images/next_h.png"

    };        

    onMouseClicked: function(e) {

        style="font-weight: bold;">onNext();

    }

}

     

// Load image and data specified in given Photo object

function onNext() {

    fullImageView.show = false;

    page++;

    //updateImages();

    loadImageMetadata();

}

     




Running the code

Netbeans
6.5 has plugins for JavaFX.  If  you don't have Netbeans
6.5  download
and install it, then  go to Tools..Plugins and select the JavaFX
plugins.  You can also href="http://java.sun.com/javafx/downloads/">download the JavaFX SDK
without Netbeans, but I'm going to focus on using JavaFX with Netbeans.


To start learning JavaFX  you can start off with the doc href="http://javafx.com/docs/gettingstarted/javafx/create-first-javafx-app.jsp">Creating
Your First JavaFX Application and/or with the tutorial  href="http://java.sun.com/javafx/1/tutorials/core/getStarted/index.html">Learning
the JavaFX Script Programming Language. 


Running the RESTful Catalog service

  1. Download the href="https://techdayscode.dev.java.net/servlets/ProjectDocumentList?folderID=10285">sample
    code and extract its contents. You should now see the newly
    extracted directory
    as /catalog, where
    is the directory
    where you unzipped the sample package. For example, if you extracted
    the contents to C:\ on a Windows machine,
    then your newly created directory should be at C:\catalog.
  2. Start NetBeans IDE. Click Open Project in the File menu and
    select the catalog directory you just
    unzipped.
  3. Start the MySQL or JavaDB database as follows:
    • Click the Services tab in the NetBeans IDE.
    • Expand the databases node. You should see the MySQL server
      or JavaDB database in the list of databases.

      databaselist.jpg

    • Right-mouse click on the MySQL or JavaDB server database and
      select
      Start.
  4. Create the catalog database as follows:
    • Right-mouse click on the MySQL or JavaDB server database and
      select
      Create Database.
    • Enter the database name petcatalog and userid root and
      password admin. This will open a New
      Database Connection window. Click O.K. to accept the displayed
      settings.
  5. Create the tables in the MySQL catalog database as follows:
    • Expand the Drivers node. You should see a driver for the
      petcatalog
      database in the list of drivers.

      driverlist.jpg

    • Right-mouse click on the petcatalog driver and select Connect.
    • Right-mouse click on the petcatalog driver and select Execute
      Command. This will open up a SQL command window.
    • Copy the contents of the catalog.sql file
      in the catalog directory and paste the contents into the
      SQL command window.
    • Click the Run SQL icon runsql.jpg
      (Ctrl+Shift+E) above the SQL command window.
    • Open the 
      catalog/setup/sun-resources.xml file and verify that the property
      values it specifies match those of the database style="color: rgb(204, 0, 0);">you created (jndi
      datasource, username, password...). For example



        jndi-name="catalog"
      />

          style="color: rgb(204, 0, 0);">"User" value="root"/>

          style="color: rgb(204, 0, 0);">"Password" value="admin"/>

          style="color: rgb(204, 0, 0);">"serverName" value="localhost"/>

          style="color: rgb(204, 0, 0);">"portNumber" value="3306"/>

          style="color: rgb(153, 0, 0);">"databaseName"
      value="petcatalog"
      />

          value="jdbc:mysql://localhost:3306/petcatalog"/>

       

      Edit the property values as
      necessary to match the database you
      created
      .
  6. Build the project as follows:


    • Right click the catalog
       node in
      the
      Projects window.

           

    •      
    • Select Clean and Build Project.

             

           

    •    

     

  7.  
  8. Run the project as follows:

       

       

           
    • Right click the catalog
node in
the
Projects window.
  • Select Run Project.
  • When you run the project, your browser should display and empty html
    page at
    http://localhost:8080/catalog

    /  (this is
    the service not the client).



    Running the JavaFX Pet Catalog Client



       
    1. Download the href="https://techdayscode.dev.java.net/servlets/ProjectDocumentList?folderID=10285">sample
      code and extract its contents. You should now see the newly
      extracted directory
      as /catalog
    , where
    is the directory
    where you unzipped the sample package. For example, if you extracted
    the contents to C:\ on a Windows machine,
    then your newly created directory should be at C:\catalogclient.
  • In NetBeans IDE, click Open Project in the File menu and
    select the catalogclient directory you just
    unzipped.
  • Run the project as follows:
    • Right click the catalogclient  node in
      the
      Projects window.
    • Select Run Project.
  • When you run the project, your browser should display the Pet Catalog
    Client.

    References

    • href="http://javafx.com/samples/index.html">JavaFX samples
    • href="http://weblogs.java.net/blog/caroljmcdonald/archive/2008/08/a_restful_pet_c_1.html">RESTful
      Pet Catalog example






    Related Topics >>

    Comments

    THANK YOU SOOOOOO MUCH

    THANK YOU SOOOOOO MUCH CAROL. This was the best tutorial that helped me to connect my javafx app with flickr web services. I really appreciate your work, just keep on. Thanks again