Skip navigation


Building a Grails Pet Catalog using Netbeans 6.5 and MySQL


This Catalog Sample app demonstrates the usage of Groovy and Grails to implement pagination of data sets for a Store Catalog.
download Catalog sample code (click on Source Code link)

Overview of the Technologies and Frameworks in the Sample Application

Grails aims to bring the "coding by convention" paradigm to Groovy. It's an open-source web application framework that leverages the Groovy language and complements Java Web development.

Groovy is an agile anddynamic language for the Java Virtual Machine, itcompiles to Java bytecode, and it combines popular features from languages such as Smalltalk, Python, and Ruby.

MySQL is the world's most popular open-source database. It offers consistently fast performance, high reliability and ease of use.

The NetBeans IDE 6.5 , in addition to full support of all Java platforms (Java SE, Java EE, Java ME, and JavaFX), has support for software development with PHP, Ajax and JavaScript, Groovy and Grails, Ruby and Ruby on Rails, and C/C++.  Netbeans 6.5 feature highlights for Groovy and Grails:

  • Develop pure Groovy apps or use Groovy in Java SE projects
  • Groovy editor with code completion, highlighting, and more
  • Grails web application framework
  • Open existing Grails applications without adding metadata

 

Grails is a Model-View-Controller based framework that simplifies the development of  web applications by reducing the need for configuration files and by generating a lot of the things needed in a database-backed Web application.

mvc.gif



The Sample Application

The sample application displays an online catalog of pets sold in a pet store. The image below shows the Catalog Listing page, which allows a user to page through a list of items in a store.

  http://weblogs.java.net/blog/caroljmcdonald/archive/itemlist.jpg


Setting Things Up:

  1. If MySQL is already not already installed, then download MySQL  and install it.

  2. Download and install Netbeans 6.5 bundled with Glassfish v3 Prelude.

  3. Download and install Grails.

  4. Start NetBeans IDE.  

  5. In the Netbeans IDE,  select Tools Options Groovy and set the location of the Grails package, which you installed using the Glassfish v3 updatetool.
    http://weblogs.java.net/blog/caroljmcdonald/archive/grailsoptions.jpg


Creating the Catalog Database Item table: 
  1. Download the sample code and extract its contents. You should now see the newly extracted directory as<sample_install_dir>/catalog, where<sample_install_dir> 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. In the Netbeans IDE,  Click Open Project in the File menu and select the catalog directory you just unzipped.
    The file  "/catalog/grails-app/conf/DataSource.groovy" is configured for  MySQL.

  3. Start the MySQL database as follows: 
    • Click the Services tab in the NetBeans IDE.
    • Expand the databases node. You should see the MySQL server database in the list of databases.       
      databaselist.jpg
    • Right-mouse click on the MySQL server database and select Start.

  4. Create the catalog database as follows: 
    • Right-mouse click on the MySQL 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<sample_install_dir>/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.

  6. Ensure that the username and password settings in thecatalog\grails-app\conf\DataSource.groovy file are the same as the corresponding property settings in NetBeans IDE 6.5 for your MySQL server database.
Running the Sample Code: 
  1. 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 the opening page of the Sample Application (at http://localhost:8080/catalog/).
http://weblogs.java.net/blog/caroljmcdonald/archive/startpage.jpg


How to Create the Catalog Sample Application with Netbeans 6.5 and MySQL

Creating the Application
  1. Run the "grails create-app" command from the IDE, by using  the IDE "Grails Application" project template to create a new Grails application as follows:

     
    • Choose File > New Project (Ctrl-Shift-N) and then select "Grails Application" from the "Groovy" category. Click Next.
    • In Project Name, type "catalog"; in Project Location, select the folder where the application will be created. Click Finish.
      http://weblogs.java.net/blog/caroljmcdonald/archive/newgrailsapp.jpg

      The IDE runs the "grails create-app" command, showing the output in the Output window. The Projects window should show you this:
      http://weblogs.java.net/blog/caroljmcdonald/archive/catalogdirectory.JPG

      Expand the folders and have a look at the source structure created by the IDE via the Grails scripts. Also look at the generated files and notice that many of them have default values filled in.

Configure Your Grails app data source for MySQL database

Configuring the data source is a simple matter of changing the values for the desired database and driver and placing the driver jar file in the <..>/lib directory.
  1. Download MySQL Connector/J 5.1.6 from here.
  2. Extract the bundle and copy the  "mysql-connector-java-5.1.6-bin.jar" to the "lib" directory of your Grails application: catalog\lib.
  3. Double click on the file "catalog\grails-app\conf\DataSource.groovy" to edit in order to change the values for MySQL configuration. The updated file looks like this (changes highlighted in red):


               
    Code Sample from: catalog\grails-app\conf\DataSource.groovy

    dataSource {
        pooled = true
        driverClassName = "com.mysql.jdbc.Driver"
        username = "root"
        password = ""   // your mysql password here
        dialect = "org.hibernate.dialect.MySQL5InnoDBDialect"
    }
    hibernate {
        cache.use_second_level_cache=true
        cache.use_query_cache=true
        cache.provider_class='com.opensymphony.oscache.hibernate.OSCacheProvider'
    }
    // environment specific settings
    environments {
        development {
            dataSource {
                dbCreate = "update"  // one of 'create', 'create-drop','update'
                url = "jdbc:mysql://localhost/petcatalog"
            }
        }
        test {
            dataSource {
                dbCreate = "update"
                url = "jdbc:mysql://localhost/petcatalog"
            }
        }
        production {
            dataSource {
                dbCreate = "update"
                url = "jdbc:mysql://localhost/petcatalog"
            }
        }
    }
       



    Being in production, it's recommended to use InnoDBtables instead of MyISAM tables. This can be easily specified by using the dialect as explained here. More details about the contents of "DataSource.groovy" can be foundhere.


Creating the Domain Class
  1. use the IDE to run the "grails create-domain-class" script as follows: 
    • Right-click on the Domain Classes node and choose New > Grails Domain Class.
      http://weblogs.java.net/blog/caroljmcdonald/archive/newgrailsdomainclass.JPG

    • Name the domain class "Item" and click Finish. The "Item.groovy" domain class is created in the Domain Classes node.
      http://weblogs.java.net/blog/caroljmcdonald/archive/newdomainclass.jpg

  2. Double click on the catalog\grails-app\domain\Item.groovy class to open it in the editor and add the attributes shown in red below to the item class.
               
    Code Sample from: catalog\grails-app\domain\Item.groovy

    class Item {
      Long id
      String name
      String description
      String imageurl
      String imagethumburl
      BigDecimal price
     
    }
       


The Model - Grails Domain Classes

The Model is your application's persistent business domain objects. A Grails domain object instance represents a row in a database table.  The command grails create-domain-class Item generates the Item.groovyclass shown below corresponding to the item database table.

After model code generation you have to add the domain object's attributes and relationships.


        
Code Sample from: domain\Item.groovy

class Item {
  Long id
  String name
  String description
  String imageurl
  String imagethumburl
  BigDecimal price
 
}
   



 

        
SQL  Sample for items table

CREATE TABLE item (
  id INT NOT NULL,
  product_id BIGINT NOT NULL,
  name VARCHAR(30) NOT NULL,
  description VARCHAR(500) NOT NULL,
  imageurl VARCHAR(55),
  imagethumburl VARCHAR(55),
  price DECIMAL(14,2) NOT NULL,
  primary key (id),
 
);
   


Groovy with Grails dynamically generates getters and setters and the dynamic methods Item.save(), Item.delete(),  Item.list(), Item.get() to retrieve/update data from/to the db table.

Grails Object Relational Mapping (GORM) is currently built on top of Hibernate but you don't have to know Hibernate to use it.

Creating the Controller and Views
  1. use the "grails generate-all" script to create a controller and views for the domain class as follows: 
    • Right-click the Controllers node and choose New > Grails Controller.
      http://weblogs.java.net/blog/caroljmcdonald/archive/generateall.JPG

    • The Item controller and Item views are generated.


The Controller

Controllers handle incoming http requests, interact with the model to get data and to process requests,  invoke the correct view, and direct domain data to the view for display.  In Grails, http requests are handled by Controller classes which are made up of one or more action methods that are executed on request and then either render a Groovy Server Page or redirect to another action. Grails routes requests to the controller action which corresponds to the URL mapping for the request. In Grails the default mapping from URL to action method follows this convention: http://host/app/controller/action/id .  For example the URL http://host/catalog/item/list calls thelist action method in the item controller class shown below.     Grails Scaffoldingprovides a series of standardized Controller action methods for listing, showing, creating, updating, and deleting objects of a class.  These standardized actions come with both controller logic and default view Groovy Server Pages. The command generate-all Item generates the Item controller and the List, Show, Create, Edit Groovy Server Pages for the Item domain object. The ItemControllerlistaction renders a view with a paginated list of item objects.

        
Code Sample from: catalog\grails-app\controllers\ItemController.groovy

class ItemController{

 
def index = { redirect(action:list,params:params) }

  def list = {
    if(!params.max) params.max = 10
    [ itemInstanceList: Item.list( params ) ]
  }
. . .


When a URL has a controller but no action (e.g. http://localhost:8080/catalog/item/  ), Grails defaults to the index action. In theItemControllercode the  indexaction method redirects to the listaction.  The ItemControllerlistaction method calls the Item.list()method which returns an ArrayList of item objects retrieved from the item database table . If there are more than params.max objects in the table, Grails creates next and previous pagination links automatically. The itemInstanceListvariable  is automatically made available to the view by the framework.

After executing code, actions usually render a GSP in the views directory corresponding to the name of the controller and action, for example the list action will render the catalog\grails-app\views\item\list.gsp .



Running the Application

The catalog Grails application is ready to run:.
  1. Right-click the application and choose "Run".

  2. When you run the project, your browser should display the opening page of the Sample Application (at http://localhost:8080/catalog/) . If the browser does not open automatically, paste the URL into a browser and then you'll see your application.

    http://weblogs.java.net/blog/caroljmcdonald/archive/grailsindex.jpg

  3. Click the "ItemController" link and you'll see this:

    http://weblogs.java.net/blog/caroljmcdonald/archive/grailslist.jpg

Modifying The View

The view layer generates a web page, using data from domain objects provided by the controller. In Grails, the view is rendered usingGroovy Server Pages

Modifying the List View GSP

  1. Copy the sub directory images from the sample application directory catalog\web-app\ to your application's catalog\web-app\  directory.
  2. Double click on the file "catalog\grails-app\views\item\ list.gsp" to edit in order to modify the item list table. Make the changes highlighted in red):
               
    Code Sample from: grails-app\views\item\list.gsp

    <table>
       <thead>
         <tr>
            <g:sortableColumnproperty="name" title="Name" />
            <g:sortableColumn property="imagethumburl" title="Photo" />
            <g:sortableColumn property="price" title="Price" />
         </tr>
       </thead>
       <tbody>
         <g:eachin="${itemInstanceList}" status="i" var="itemInstance">
            <tr class="${(i % 2) == 0 ? 'odd' : 'even'}">
               <td>
                  <g:link action="show" id="${itemInstance.id}">
                    ${fieldValue(bean:itemInstance, field:'name')}</g:link>
               </td>
               <td>
                  <img src="${itemInstance.imagethumburl}" alt="Pet" />
               </td>
               <td>
                  ${fieldValue(bean:itemInstance, field:'price')}
               </td>
            </tr>
         </g:each>
      </tbody>
     </table>

    <div class="paginateButtons">
     <g:paginatetotal="${Item.count()}" />
    </div>


    The view uses instance variables set by the controller to access the data it needs to render the GSP.

    GSP has a GroovyTagLib similar to the  JSP tag library. <g: are GroovyTags.
      

    <g:sortableColumn
           The sortableColumntag renders a sortable column to support sorting in tables.

    <g:each in="${itemInstanceList}" status="i" var="itemInstance">
     
    loops through each object in the itemInstanceListvariable, which is an ordered ArrayList of Itemmodel objects,  and assigns each Itemmodel object to the iteInstancevariable.
     
    <g:link action="show" id="${itemInstance.id}"> ${fieldValue(bean:itemInstance, field:'name')} </g:link>  
    the <g:link> GroovyTag creates an html anchor taghref based on the action,id, controller parameters specified. In this example it generates a link to the item/show/id action which when clicked will display the corresponding item details. For example this line will generate the following HTML for the variableitem
    <a href="/catalog/item/show/2">Friendly Cat</a>
    
    <img src="${itemInstance.imagethumburl}" alt="Pet" />  
    sets the HTML img tag to theitem's imagethumburl attribute. 

    ${fieldValue(bean:itemInstance, field:'price')}
     
    displays the value of the item 's price attribute .

    <g:paginate total="${Item.count()}" /> 
    The paginate tag creates next/previous buttons and a breadcrumb trail to allow pagination of results using the Item.count()domain method.

  3. Save your modifcations in the editor. Click reload current page on your browser. The Item List page should now look like the image below:
    http://weblogs.java.net/blog/caroljmcdonald/archive/itemlist1.jpg

The Show Action Method

In Grails the mapping for the URL http://host/item/show/1  ( http://host/controller/action/id )  will route to the showaction in the ItemControllerpassing 1 to the method as the id of theparamsparameter hash. The showaction of the ItemControllerclass is shown below. The ItemControllershowaction renders a view showing the details of the item object corresponding to the id parameter.

        
Code Sample from: grails-app\controllers\ItemController.groovy

 def show = {
   def itemInstance = Item.get( params.id)

   if(!itemInstance) {
      flash.message = "Item not found with id ${params.id}"
      redirect(action:list)
   }
   else { return [ itemInstance : itemInstance ] }
 }



The showaction method  calls the Item.get()method which queries the items table returning the itemInstanceinstance variable corresponding to the item with the attributeid(primary key) equal to the  idparameter. This is the equivalent of the following sql : select * from items where id='1' . The itemInstance variable is automatically made available to the Show view by the framework.

 

Modifying the Show View GSP

After executing code in the action, the showaction renders the catalog\grails-app\views\item\show.gsp.
  1. Double click on the file "catalog\grails-app\views\item\show.gsp" to edit in order to modify the item show view. Make the changes highlighted in red below:

               
    Code Sample from:catalog\grails-app\views\item\show.gsp

     <table>
         <tbody>
             <tr class="prop">
                 <td valign="top" class="name">Name:</td>
                 <td valign="top" class="value">${itemInstance.name}</td>
             </tr>
             <tr class="prop">
                 <td valign="top" class="name">Description:</td>
                 <td valign="top" class="value">${itemInstance.description}</td>
             </tr>
             <tr class="prop">
                 <td valign="top" class="name">Photo:</td>
                 <td><img src="${itemInstance.imageurl}" alt="Pet" /></td>
             </tr>
             <tr class="prop">
                 <td valign="top" class="name">Price:</td>
                 <td valign="top" class="value">${itemInstance.price}</td>
             </tr>
         </tbody>
     </table>



    ${itemInstance.description}
      
    displays the value of the item 's descriptionattribute.
    <img src="${itemInstance.imageurl}" />  
    sets the HTML image tag for theitem's imageurl attribute.
    ${itemInstance.price}
    displays the value of the item'spriceattribute.

  2. Save your modifcations in the editor. Click reload current page on your browser.
    The image below shows the resulting page for the url http://host/catalog/item/show/1, which displays the item 1's details:

     
         http://weblogs.java.net/blog/caroljmcdonald/archive/showdetail1.jpg

Layouts

Grails layouts  let you put common html on multiple views (for example page headers,  footers, sidebars).  Default layout templates are in the views layouts directory with a file name corresponding to the controller, or you can associate a view with a layout using the "layout" meta tag to your page: 
<meta name="layout" content="main">
To replace the Grails logo with a title and parrot image at the top of the Pet Catalog pages,  put this table in the catalog\grails-app\views\layouts\main.gsp  layout page:

        
Code Sample from: app/views/layouts/main.gsp

<table>
  <tr>
   <td>Pet Catalog</td>
   <td>
     <img src="${createLinkTo(dir:'images',file:'pet_logo.jpg')}"/>
   </td>
 </tr>
</table>


The image below shows the result on the show page after modifying main.gsp layout page :

http://weblogs.java.net/blog/caroljmcdonald/archive/showitem.jpg



Running you Grails app on Glassfish v2:

Netbeans does not yet support deploying grails app directly to Glassfish, but you can create a WAR file and deploy it on Glassfish as follows:
 
  1. If Jetty is running stop it: click on the IDE Services Tab, Under the Jetty server right-click on the catalog app and select Stophttp://weblogs.java.net/blog/caroljmcdonald/archive/stopjetty.JPG

  2. Right-click on the catalog project node and choose Create War File.
    http://weblogs.java.net/blog/caroljmcdonald/archive/createwar.JPG
  3. Rename the catalog-0.1.war file tocatalog.war. Copy the  catalog.warfile from your catalog directory to your Glassfish installation glassfish-v2ur2\domains\domain1\autodeploy  directory. Start Glassfish.

    Enter the URL  http://localhost:8080/catalog/  in your browser, you should see the home page of the Sample Application.

Running you Grails app on Glassfish v3:

GlassFish v3 Prelude is a lightweight Web 2.0 development and deployment platform built on a modular OSGi-based architecture. Developers can benefit from a dynamically extensible and embeddable platform with support for existing Java Web technologies, JRuby, and Groovy. GlassFish Support For Grails Framework adds the Grails framework to the GlassFish application server and allows development and easy deployment of Grails applications. Applications can be deployed in shared or standalone mode. Shared mode allows library reuse and results in much smaller war files.
  1. Install the Grails packageto Glassfish v3 using the updatetool.   Start the GlassFish Update Center by issuing the following command:GF_install\updatecenter\bin\updatetool. Check the GlassFish Support for Grails Framework checkbox in the GlassFish Update Center and click Install.
  2. Read the Glassfish Getting started with Grails.

Conclusion

This concludes the sample application which demonstrates how to work with Groovy and Grails  to page through a list of  Item Model objects which are retrieved using Item Controller action methods, and displayed using Item ViewGSPs.

References




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 blog entry and in this screencast.  This JavaFX example is a modification of theInteresting Photos : JavaFX Example Application.

catalogclient.jpg


Understanding the Code


        
Code Sample from: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 variablestitle, width and heightdefine 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 toStage, and JavaFX renders everything on a scene.
The scene instance variable has a contentvariable 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 Nodehas a  content variable which is a sequence of child Nodes that will be rendered in order whenever this Group is rendered. The Group Node has aclip variable which specifies a Rectangle which defines the the clipping shape for this GroupNode.

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.Nodeimplementations: 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: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 toScene of Stage.

The thumbImageViewGroup variable has a data binding  with thumbImageViews which is a sequence of ThumbImageView which extends ImageView.ImageViewis a Node used for painting images loaded with 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 alocation and method and start a HTTP operation with the function enqueue().  The content of the HTTP response can be accessed in theonInput 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 theupdateImages() 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:
  
 <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 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 theonEvent callback, which reports the current parse event.  The onEvent callback shown below parses the xml item elements into an instance of thePhoto class. When the itemEND_ELEMENT , </item>, is reached,  the photo
variable is inserted into thephotos 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 theHttpRequest 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 thethumbImageView Image URLs to thephoto URLs parsed from the HTTP response. 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 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 ThumbImageViewonMouseClicked 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, TheFullImageView Node's visiblevariable is set to truewhich specifies that this Node and any subnodes should be rendered as part of the scene graph. The fader() function causes the fullImageViewto fade in or out. The FullImageViewNode's  opacityvariable 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 theTimeline 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 {
           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;
           visible = true;
        } else {
            timeline.time = 3s;
            timelineRate = -3.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) {
        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 download the JavaFX SDKwithout Netbeans, but I'm going to focus on using JavaFX with Netbeans.
To start learning JavaFX  you can start off with the doc Creating Your First JavaFX Application and/or with the tutorial  Learning the JavaFX Script Programming Language. 

Running the RESTful Catalog service

  1. Download the sample code and extract its contents. You should now see the newly extracted directory as<sample_install_dir>/catalog, where<sample_install_dir> 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 thecatalog 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 databaseyou created (jndi datasource, username, password...). For example
      <resources>
        <jdbc-resource  jndi-name="catalog" />
          <property name="User" value="root"/>
          <property name="Password" value="admin"/>
          <property name="serverName" value="localhost"/>
          <property name="portNumber" value="3306"/>
          <property name="databaseName" value="petcatalog"/>
          <property name="URL" value="jdbc:mysql://localhost:3306/petcatalog"/>
      </resources> 
      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. 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 sample code and extract its contents. You should now see the newly extracted directory as<sample_install_dir>/catalog, where<sample_install_dir> 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.
  2. In NetBeans IDE, click Open Project in the File menu and select the catalogclient directory you just unzipped.
  3. 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



Filter Blog

By date: