GlassFish and MySQL, Part 4: Creating a RESTful Web Service and JavaFX Client

   
By Ed Ort and Carol McDonald, March 2009  

Introduction | The Application | Building the Application

The Application

The web application discussed in this article is an updated version of the pet catalog application discussed in Part 2. The updated pet catalog application allows users to access an online catalog of pets. Users can display thumbnail images of pets in the catalog. As Figure 4 shows, the application displays the thumbnail images in a grid. When the user clicks the next button, that is, the button with the right arrow, the display scrolls forward through the thumbnail images of pets in the catalog. When the user clicks the back button, that is, the button with the left arrow, the display scrolls backward. Notice that when the user moves the mouse pointer over a thumbnail image, the application displays the name of that pet. When a user moves the mouse pointer to a different thumbnail image, the application displays the name of the other pet.

Thumbnail Images of Pets in the Catalog
Figure 4. Thumbnail Images of Pets in the Catalog
 

A user can display a larger image of a pet, as shown in Figure 5, by clicking its thumbnail image. Clicking the larger image restores the display of the thumbnail grid.

Larger Image of a Pet in the Catalog
Figure 5. Larger Image of a Pet in the Catalog
 

Unlike the initial version of the application, the updated application does not allow users to add, edit, or delete items in the catalog.

Inside the Application

Here are the major changes in the updated pet catalog application:

  • The database schema and content of the catalog are simplified to contain only an item table.
  • The model is simplified to contain only item entities.
  • The controller layer and view layer are replaced by a RESTful web service and JavaFX client.

Let's examine each of these changes. You can view the code by downloading and expanding the RESTful Pet Catalog service ( catalog) and JavaFX Pet Catalog Client ( catalogclient) packages.

The Catalog

As was the case in the initial version of the pet catalog application, the catalog is contained in a MySQL database named petcatalog. Recall that the petcatalog database in the initial version of the application has four tables: category, product, item, and address. The catalog used in the updated version of the application has been simplified to contain one item table. In addition, the schema and content of the item table is slightly changed. For each item, the table contains an identification (ID) number, product ID, name, description, URL of the item's image, URL of the item's thumbnail image, and price.

Here are two rows in the item table.

   +----+-----------+----------+---------------------------------+--------------------------------------------------+---------------------------------------------------+--------+
   | id | productid | name     | description                     | imageurl                                         | imagethumburl                                     | price  |
   +----+-----------+----------+---------------------------------+--------------------------------------------------+---------------------------------------------------+--------+
   | 1  | feline01  | Friendly | This black and white colored cat| http://localhost:8080/catalog/images/anthony.jpg | http://localhost:8080/catalog/images/anthony-s.jpg| 307.10 |
   |    |           | Cat      | is super friendly. Anyone       |                                                  |                                                   |        |
   |    |           |          | passing by your front yard will |                                                  |                                                   |        |
   |    |           |          | find him purring at their feet  |                                                  |                                                   |        |
   |    |           |          | and trying to make a new friend.|                                                  |                                                   |        |
   |    |           |          | His name is Anthony, but I call |                                                  |                                                   |        |
   |    |           |          | him Ant as a nickname since he  |                                                  |                                                   |        |
   |    |           |          | loves to eat ants and other     |                                                  |                                                   |        |
   |    |           |          | insects.                        |                                                  |                                                   |        |
   +----+-----------+----------+---------------------------------+--------------------------------------------------+---------------------------------------------------+--------+
   | 2  | feline02  | Fluffy   | A great pet for a hair stylist! | http://localhost:8080/catalog/images/bailey.jpg  | http://localhost:8080/catalog/images/bailey-s.jpg | 307.00 |
   |    |           | Cat      | Have fun combing Bailey''s      |                                                  |                                                   |        |
   |    |           |          | mane. Maybe trim his whiskers?  |                                                  |                                                   |        |
   |    |           |          | He is very patient and loves to |                                                  |                                                   |        |
   |    |           |          | be pampered.                    |                                                  |                                                   |        |
   +----+-----------+----------+---------------------------------+--------------------------------------------------+---------------------------------------------------+--------+

 

When you expand the catalog package, you will see a directory named catalog. Find a file named catalog.sql in the catalog directory. The file contains the SQL statements that create the updated item table and fill it with data.

The Model

Navigate to the catalog/src/java/model directory. The content of this directory represents the model for the updated application. Notice that the model has only an entity class, Item, which represents the item table in the petcatalog database. The initial version of the application contains additional entity classes for the Address, Category, and Product tables in the petcatalog database. An instance of the Item entity represents a row of data in the item table.

Here is part of the source code for the Item class:

   package model;

   import java.io.Serializable;
   ...

   @Entity
   @Table(name = "item")
   ...

   public class Item implements Serializable {
       private static final long serialVersionUID = 1L;
       @Id
       @Basic(optional = false)
       @Column(name = "id")
       private Integer id;
       @Column(name = "productid")
       private String productid;
       @Column(name = "name")
       private String name;
       @Column(name = "description")
       private String description;
       @Column(name = "imageurl")
       private String imageurl;
       @Column(name = "imagethumburl")
       private String imagethumburl;
       @Column(name = "price")
       private BigDecimal price;

       ...

       //getters and setters
       ...
 
The Web Service

Navigate to the catalog/src/java/service directory. You will see three classes in that directory: ItemsResource, ItemResource, and PersistenceService. The ItemsResource and ItemResource classes represent the RESTful web service resources for the application. The PersistenceService class is a Java Persistence API helper class.

Web Service Resources: The ItemsResource and ItemResource classes are RESTful web service resources that represent items in the pet catalog. The ItemsResource class represents a list of items in the catalog. The ItemResource class represents a specific item in the catalog.

Recall that to address a resource in REST, you specify its URI. However, to communicate with a resource, you must also specify a communication protocol such as HTTP. Table 3 lists the URIs and HTTP methods that correspond to the resources in the pet catalog application.

Table 3: URIs and HTTP Methods for REST Resources in the Pet Catalog Application
 
Resource
URI Path
HTTP Methods
Meaning
ItemsResource
/items
GET
POST
List all items in the catalog.
Add an item to the catalog.
ItemResource
/items/{id}
GET
PUT
DELETE
Get an item representation.
Update an item in the catalog.
Delete an item from the catalog.
 

The source code for the resource specifies the resource's applicable path and HTTP methods.

The ItemsResource Class: The ItemsResource class includes methods that retrieve a collection of Item objects and create an instance of an Item object for posting. Here is part of the source code for the ItemsResource class:

   Path("/items/")
   public class ItemsResource {

       @GET
       @Produces({"application/xml", "application/json"})
       public ItemsConverter get(
         @QueryParam("start") @DefaultValue("0") int start,
         @QueryParam("max") @DefaultValue("10") int max,
         @QueryParam("expandLevel") @DefaultValue("1") int expandLevel,
         @QueryParam("query") @DefaultValue("SELECT e FROM Item e") String query) {
           PersistenceService persistenceSvc = PersistenceService.getInstance();
           try {
               persistenceSvc.beginTx();
               return new ItemsConverter(getEntities(start, max, query), uriInfo.getAbsolutePath(), expandLevel);
           } finally {
               persistenceSvc.commitTx();
               persistenceSvc.close();
           }
       }

       @POST
       @Consumes({"application/xml", "application/json"})
       public Response post(ItemConverter data) {
           PersistenceService persistenceSvc = PersistenceService.getInstance();
           try {
               persistenceSvc.beginTx();
               EntityManager em = persistenceSvc.getEntityManager();
               Item entity = data.resolveEntity(em);
               createEntity(data.resolveEntity(em));
               persistenceSvc.commitTx();
               return Response.created(uriInfo.getAbsolutePath().resolve(entity.getId() + "/")).build();
           } finally {
               persistenceSvc.close();
           }
       }

       protected Collection<Item> getEntities(int start, int max, String query) {
               EntityManager em = PersistenceService.getInstance().getEntityManager();
               return em.createQuery(query).setFirstResult(start).setMaxResults(max).getResultList();
           }

 

The ItemsResources class is annotated with a number of JAX-RS annotations as follows:

  • The @Path annotation identifies /items as the URI path for which the ItemsResource class will serve requests.
     
  • The @GET annotation indicates that the get() method responds to HTTP GET requests. Methods such as this that serve REST requests are called resource methods.
     
  • The @Produces annotation specifies the format of the response, in this case, XML or JavaScript Object Notation (JSON)-formatted data.
     
  • The @QueryParam annotations specify input parameters for the get() method. When the get() method is invoked, the input value of start is injected into the corresponding input argument.
     
  • The @DefaultValue annotation specifies a default value for an argument if no input value is given.
     
  • The @POST annotation indicates that the post() method responds to HTTP POST requests.
     
  • The @Consumes annotation indicates that the post() method can accept XML or JSON-formatted data sent by the client.

The get() method returns the ItemsConverter class , which is a Java Architecture for XML Binding (JAXB)-annotated class that marshals a list of Item objects into XML or JSON format.

The post() method returns a Response object. This object is used to contain the response to an HTTP request, such as a status code. Notice too that the post() method uses the ItemConverter class as an argument. The ItemConverter class is a JAXB-annotated class whose resolveEntity method returns an Item entity corresponding to the input argument data.

The getEntities() method uses the EntityManager to create a Query object for executing Java Persistence query language statements that can return a list of items. The Query class supports pagination through its setFirstResult() and setMaxResults() methods. The expression query.setMaxResults(max) sets the maximum number of results to retrieve. The expression query.setFirstResult(start) sets the position of the first result to retrieve.

The ItemResource Class: The ItemResource class includes methods that retrieve, update, and delete an individual Item object. Here is part of the code for the class:

   public class ItemResource {
       @Context
       protected UriInfo uriInfo;
       @Context
       protected ResourceContext resourceContext;
       protected Integer id;


       @GET
       @Produces({"application/xml", "application/json"})
       public ItemConverter get(
          @QueryParam("expandLevel") @DefaultValue("1") int expandLevel) {
                   PersistenceService persistenceSvc = PersistenceService.getInstance();
               try {
                   persistenceSvc.beginTx();
                   return new ItemConverter(getEntity(), uriInfo.getAbsolutePath(), expandLevel);
               } finally {
                   PersistenceService.getInstance().close();
               }
       }


       @PUT
           @Consumes({"application/xml", "application/json"})
           public void put(ItemConverter data) {
               PersistenceService persistenceSvc = PersistenceService.getInstance();
               try {
                   persistenceSvc.beginTx();
                   EntityManager em = persistenceSvc.getEntityManager();
                   updateEntity(getEntity(), data.resolveEntity(em));
                   persistenceSvc.commitTx();
                } finally {
                   persistenceSvc.close();
                }
           }

       @DELETE
           public void delete() {
               PersistenceService persistenceSvc =
                PersistenceService.getInstance();
               try {
                   persistenceSvc.beginTx();
                   deleteEntity(getEntity());
                   persistenceSvc.commitTx();
               } finally {
                   persistenceSvc.close();
               }
           }
 

As is the case for the ItemsResource class, the ItemResource class is marked with @GET, @PUT, @Produces, @DefaultValue, and @Consumes annotations. In addition, the delete() method in the ItemResource class is marked with a @DELETE annotation, which indicates that the method responds to HTTP Delete requests.

Converters

If you navigate to the catalog/src/java/converter directory, you'll find three classes: ItemsConverter, ItemConverter, and UriResolver. The ItemsConverter class uses JAXB APIs to marshal a collection of one or more Item objects to XML or JSON format. JAXB provides a convenient way to bind an XML schema or JSON to a representation in Java code. This makes it easy to incorporate XML or JSON data and processing functions in applications based on Java technology even if you do not know much about XML or JSON. The JAXB term for converting Java objects to XML or JSON is marshalling.

Here is part of the code for the ItemsConverter class:

   @XmlRootElement(name = "items")
   public class ItemsConverter {


       @XmlElement
           public Collection<ItemConverter>getItem() {
           ...
           return items;
           }


       @XmlAttribute
           public URI getUri() {
               return uri;
           }
 

The annotations in the ItemsConverter class are JAXB annotations that specify the mapping of Java objects to XML schema or JSON-formatted data as follows:

  • @XmlRootElement marks items as a top-level XML node or JSON object.
  • @XmlElement marks the collection of items as an XML or JSON element.
  • @XmlAttribute marks the uri JavaBeans property as an XML attribute or JSON property.

The ItemConverter class models an Item object, with getter and setter methods for the object's properties. Here is part of the code for the ItemConverter class:

   @XmlRootElement(name = "item")
   public class ItemConverter {


       @XmlElement
           public Integer getId() {
               return (expandLevel > 0) ? entity.getId() : null;
           }

       public void setId(Integer value) {
               entity.setId(value);
           }
 

The UriResolver class is a utility class that is used by the ItemConverter class to resolve a URI into an entity.

The JavaFX Client

The expanded catalogclient download contains the code for the JavaFX client, which accesses the RESTful web service resources in the pet catalog application. When you expand catalogclient, you will see a directory named catalogclient. Navigate to the catalogclient/src/catalog directory. You will see a class in that directory named Main.fx. This is the main JavaFX class for the client.

The Main.fx class retrieves information from the pet catalog for display in a UI. Let's first look at the part of the class that retrieves the information. Then let's examine the code that displays the UI.

Retrieving the Content: Content retrieval is handled primarily by the loadImageMetadata() function. Here is part of the source code in the function:

   function loadImageMetadata() {
       var start=page * 9;

       var httpRequestError: Boolean = false;

       // Submit HttpRequest
       var request: HttpRequest = HttpRequest {

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

           onInput: function(input: java.io.InputStream) {
               try {
                   var parser = PhotoPullParser{
                       onDone: function( data:Photo[] ) {
                          photos = data;
                          if(not httpRequestError) {
                            loadComplete = true;
                            updateImages();
                          }
                       }
                   };
                   parser.parse(input);

               } finally {
                   input.close();
               }
           }
       }

       request.enqueue();
   }
 

The loadImageMetadata() function uses the javafx.io.http.HttpRequest class to send an HTTP GET request to the Catalog RESTful Web Service. The request.enqueue() function starts the HTTP GET operation.

The HttpRequest object literal specifies two instance variables: location, whose value is the target location of the request, and method, whose value is the type of request. The location value, http://localhost:8080/catalog/resources/items/, is the URI for the RESTful web service provided by the ItemsResource class in the catalog application.

Recall that the ItemsResource class includes a get() method that responds to HTTP GET requests and that retrieves a collection of Item objects from the item table in the pet catalog. The URI is appended with arguments that specify the starting index position, start={start}, and maximum number of resources to retrieve, max=9.

The HTTP GET request retrieves the following information in XML format:

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

For example, here is a snippet of the XML retrieved for items in the catalog:

   <items uri="http://localhost:8080/catalog/resources/items/">
       <item uri="http://localhost:8080/catalog/resources/items/1/">
           <description>This black and white colored cat is super friendly.</description>
           <id>1</id>
           <imagethumburl>http://localhost:8080/catalog/images/anthony-s.jpg</imagethumburl>
           <imageurl>http://localhost:8080/catalog/images/anthony.jpg</imageurl>
           <name>Friendly Cat</name>
           <price>307.10</price>
           <productid>feline01</productid>
       </item>
   ...
   </items>
 

The HttpRequest class also has callback functions that are called to indicate changes in state as the operation progresses. The onInput callback function is invoked when the response to the HTTP GET request is returned. Here, the callback uses the catalog.parser.PhotoPullParser to parse the response, extract information from it, and put the extracted information for each item in a Photo object instance.

When the PhotoPullParser finishes parsing the response, it calls the onDone callback function, passing it the parsed data in a sequence of Photo objects. The onDone callback calls the updateImages() function in Main.fx. The source code for the updateImages() function is as follows:

   function updateImages() {
       println(" updateImages..Page {page+1}");
       for(i in [0..8]) {
           var photoIndex = i;
           loadImage(photos[photoIndex], thumbImageViews[i]);
       }

       title = "";
       status = "Page {page+1}";
}
 

The updateImages() function uses the loadImages() function to load data about the thumbnail image for each item that corresponds to a Photo object instance. The function loads the data into a class named ThumbImageView. Here is the code for the loadImage() function:

   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;

   }
 

The ThumbImageView class extends the javafx.scene.image.ImageView class. The ImageView class is a scene graph node that is used for rendering images -- it can retrieve and display an image based on the image's URL.

The PhotoPullParser Class: If you navigate to the catalogclient/src/catalog/parser directory, you will find the PhotoPullParser class. As its name implies, the class parses and extracts photo-related information. Here is part of the source code in the PhotoPullParser class:

   import javafx.data.pull.PullParser;

   public class PhotoPullParser {

       // Information about all catalog photos
       var photos: Photo[];
       var photo: Photo;

       // Completion callback that also delivers parsed photo metadata
       public var onDone: function(data : Photo[]) = null;

       def parseEventCallback = function(event: Event) {
           if (event.type == PullParser.START_ELEMENT) {
               processStartEvent(event)
           } else if (event.type == PullParser.END_ELEMENT) {
               processEndEvent(event)
           }else if (event.type == PullParser.END_DOCUMENT) {
               if (onDone != null) {
                   onDone(photos);
               }
           }
       }
       function processStartEvent(event: Event) {
           if(event.qname.name == "item" and event.level == 1) {
             photo = Photo {};
           }
       }
       function processEndEvent(event: Event) {
           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 == "imageurl" and event.level == 2) {
               photo.imageurl = event.text;
           }
           ...
       }
       public function parse(input: InputStream) {

           // Parse the input data (Photo Metadata) and construct Photo instance
           def parser = PullParser {
               input: input
               onEvent: parseEventCallback
           }

           parser.parse();
       }
   }
 

The PhotoPullParser's parse function calls the parse() method in the javafx.data.PullParser class, which parses the input stream. When the PullParser's parse() method encounters the start or end of an element, it calls the onEvent function of the PullParser instance. The PhotoPullParser allocates a Photo object in response to the start of an <item> element event. The parser populates the Photo object when it encounters an END_ELEMENT event for each XML element within the <item> element. When the parser encounters the end of an item element, it inserts the populated Photo object into a sequence of Photo objects. When it reaches the END_DOCUMENT element, the parser calls the onDone(photos) callback function, passing it the sequence of Photo objects.

The Photo Class: The Photo class models the content of an item in the pet catalog. You can find the class in the catalogclient/src/catalog/model directory. Here is the source code for the Photo class:

   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;
   }
 

Displaying the UI: Here is the code in Main.fx that displays the UI:

   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
       }
   }
 

Recall that in JavaFX, the Stage class is used to render a window. It is the top-level container required to display any visible JavaFX objects. The Stage object literal in Main.fx specifies instance variables for things like title, height, and width, which respectively define the text that appears in the window's top border, the window height, and window width. The values of the x and y instance variables respectively specify the horizontal and vertical position of the window when it is displayed.

Notice that both instance variables are bound to the value of other variables, that is, stageX and stageY. The with inverse clause makes the binding bidirectional. This means that when the value of x changes, the changed value is automatically assigned to stageX, and when the value of stageX changes, the changed value is automatically assigned to x. Bidirectional binding is also specified for y and stageY.

The Scene object specifies the scene that holds the objects to be rendered in the window. The content of the Scene object, that is, the value of the content instance variable, consists of a Group node.

A Group node contains a sequence of child Node objects that are rendered in order whenever the Group node is rendered. The Group node specifies a content instance variable. This variable identifies the child nodes that will be rendered. In addition, the Group node has a clip instance variable, which defines the clipping shape -- that is, the shape of the boundary -- for the Group node. Here, the clipping shape is a rectangle with rounded corners. The values of the arcWidth and arcHeight instance variables specify the horizontal and vertical diameter of the arc in the corners of the rectangle, respectively.

Notice that the content instance variable for the Group node is bound to a variable named stageContent. As the following code shows, the stageContent variable is a node in the scene graph for the UI and contains a sequence of objects.

   var stageContent: Node[];

   stageContent = [
           bgImage, titleBar, nextButton, backButton, closeButton,
           titleText, statusText, thumbImageViewGroup, fullImageView
   ];
 

Table 4 describes each object in the sequence.

Table 4: Objects in the stageContent Node
 
Object
Description
bgImage
An ImageView object that renders the background image for the UI. The background image is in the catalogclient/src/catalog/images directory.
titleBar
A Rectangle object for the UI title bar.
nextButton
An ImageButton object that renders the next button, that is, the button with the right arrow. The ImageButton class is a custom class that creates a button using an image. It extends the ImageView class. You can find the ImageButton class in the catalogclient/src/catalog/view directory. The image for the next button is in the catalogclient/src/catalog/images directory. When the mouse is clicked on the next button, it invokes a function that loads the next page of thumbnail images.
backButton
An ImageButton object that renders the back button, that is, the button with the left arrow. The image for the back button is in the catalogclient/src/catalog/images directory. When the mouse is clicked on the back button, it invokes a function that loads the previous page of thumbnail images.
closeButton
An ImageButton object that renders the close button, that is, the button with the X. The image for the close button is in the catalogclient/src/catalog/images directory. When the mouse is clicked on the close button, it ends the application.
titleText
A Text object that displays content-related text, such as a pet name, in the UI.
statusText
A Text object that displays status-related text, such as "Loading Photos...," in the UI.
thumbImageViewGroup
A Group object that contains a sequence of ThumbImageView objects. Each ThumbImageView object contains data, such as a URL, for a thumbnail image.
fullImageView
An object that displays an enlarged image. You can find the fullImageView class in the catalogclient/src/catalog/view directory. A fullImageView object is displayed when a user clicks on a thumbnail image in the UI.
 

The thumbImageViewGroup is particularly interesting. It is bound to a thumbImageViews object -- this is a sequence of ThumbImageView objects, each of which extends an ImageView object. An ImageView object is a node used for painting images that are loaded with the Image class. The following code in Main.fx shows how the thumbImageViews sequence is initialized to a grid having three columns and three rows of ThumbImageView objects:

   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
   }
 

The resulting rendered image is a rectangular window with rounded corners. The window displays a background image over which is displayed a rectangular title bar for showing content-related text or status text, a three-by-three grid of pet thumbnail images retrieved from the catalog, back and next buttons for navigation, and a close button to end the application.

Figure 6 illustrates some of the objects rendered in the pet catalog UI.

Database List
Figure 6. Some of the Objects Rendered in the Pet Catalog UI
 

If a user clicks a thumbnail image in the UI, it invokes the onMouseClicked() function in the thumbImageView class. The function sets the URL of the FullImageView object to the URL of the clicked thumbnail's larger image. It also sets the fullImageView.show variable to true, which triggers the on replace code in the FullImageView object. As a result, the window displays the larger image.

Here is part of the source code for the thumbImageView class:

   // 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;
   }
 

The FullImageView Class: The FullImageView class is a node for displaying a larger image of a pet. You can find the class in the catalogclient/src/catalog/view directory. Here is part of the source code for the FullImageView class:

   // To display enlarged image
   public class FullImageView extends ImageView {

       public var show = false on replace {
           if(useEffects) {
               fader();
           } else {
               visible = show;
           }
       }

       // Handles animation effect
       var timelineRate = 1.0;
       var timeline:Timeline = Timeline {
           rate: bind timelineRate with inverse
           keyFrames: [
               KeyFrame {
                   time: 3s
                   values: [ opacity => 1.0 tween Interpolator.LINEAR ]
               }
           ]
       };
       var timelineRunning = bind timeline.running on replace {
           if(not timelineRunning) { visible = show; }
       }

       function fader() {

           if(show) {
               timeline.time = 0s;
               timelineRate = 1.0;
               opacity = 0.0;
               visible = true;
           } else {
               timeline.time = 3s;
               timelineRate = -3.0;
               opacity = 1.0;
           }

           timeline.play();
       }

   }
 

Setting the fullImageView.show variable in the ThumbImageView class sets the visible variable in the FullImageView object to true. The true value specifies that this node and any subnodes should be rendered as part of the scene graph. Notice the fader() function. The FullImageView node's opacity variable specifies how opaque, that is, solid, the node appears.

The node also supports animation, which 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 -- this is for a single cycle of the Timeline object. The play() method plays the timeline.

Running the fader() function causes the FullImageView object to fade in or out. When a user clicks on the thumbnail image of a pet in the UI, the larger image of the pet fades in. When the user clicks the larger image, the larger image fades out and the grid of thumbnail images fades back in.

» Continue to the next page of this article

Introduction | The Application | Building the Application