New NetBeans Plugin to Generate Getter & Setter Methods for JavaFX Properties

JavaFxPropertyHelper NetBeans Plugin Released

 

This NetBeans plugin will help to generate get/set methods for JavaFx properties that are contained within a POJO.

The standard get/set code generator creates the following get/set methods for a JavaFx property which is not ideal:

private StringProperty name;

public StringProperty getName() { 
    return name;
}
public void setName( StringProperty name ) {
    this.name = name;
}

This plugin would create the following methods:

public String getName() {
    return name.get();
}

public void setName( String value ) {
    name.set(value);
}

public StringProperty nameProperty() {
    return name;
}

It’s also possible to use variables with the suffix Property in their names which will create the following methods:

private StringProperty nameProperty;
public String getName() {
    return nameProperty.get();
}

public void setName( String value ) {
    nameProperty.set(value);
}

public StringProperty nameProperty() {
    return nameProperty;
}

Usage

Press Alt-Insert to get the “Generate” popup menu, and select “Java FX Getter and Setter…” alt tag

Methods for supported property types will automatically be generated. alt tag

Supported Property Types

  • StringProperty
  • BooleanProperty
  • DoubleProperty
  • FloatProperty
  • IntegerProperty
  • LongProperty

Unsupported Property Types

  • ListProperty
  • MapProperty
  • ObjectProperty
  • SetProperty

The plugin is current available on GitHub at:

https://github.com/rterp/JavaFxPropertyHelperNBPlugin/releases/tag/1.1.1

and will hopefully be available via the general NetBeans Plugin portal by next week.

 

Freight Tracking with JavaFX and the NetBeans Rich Client Platform

iconI am super proud of my team who this week, rolled out Version 2.0 of Lynden Navigator to more than 1,000 desktops company-wide.   Navigator allows our freight terminal managers to optimize resource planning by giving them complete visibility to freight that is scheduled to arrive and depart to/from their facility.  In addition, customer service personnel have access to a new Shipment Tracing plugin included in this version which can be used to quickly access current information about customer freight and freight history.

The initial version of the application was built on the NetBeans Rich Client Platform (RCP), utilizing Swing UI components, but version 2.0 includes new functionality implemented with JavaFX.  A screenshot of the new version of Navigator appears below.  The top portion of the application is original portion that is utilizing Swing, and specifically components developed by JideSoft.   The lower portion of the screen is new functionality that has been built utilizing JavaFX.

FMS

Enter a caption

Handy Tools for JavaFX Development

If you are building an application with JavaFx there are a few tools that will make your life a whole lot easier and save you a lot of time.


Scene Builder

The WYSIWYG drag-n-drop design tool for JavaFx will build an FXML representation of the UI which can then be loaded by a JavaFx application.  Scene Builder helps to enforce the MVC pattern, keeping business logic out of the code that describes the UI. (More on this below).

SceneBuilder1

Scene builder also has a nice “CSS Analyzer” feature which will show you the full CSS path to a component that is selected in the tool.  This has come in handy when attempting to figure out what the CSS path for a component is when attempting to determine where to apply a CSS style .  I wish I had known about this when I first began using JavaFx, as it was previously a trial-and-error process for me to get a component styled correctly.

SceneBuilder2

Gluon, Inc. has taken over the build and release of the Scene Builder installer packages which can be obtained at the following link: http://gluonhq.com/open-source/scene-builder/


NetBeans

Of course you will need a good IDE for developing the remaining, and NetBeans provides a number of features which helps out with developing with JavaFX.

The first is the autocomplete feature when working with the FXML files that are generated by Scene Builder.  The IDE will generate a list of possible values when inserting or modifying nodes.

NetbeansFx

There is also support when working with the JavaFX CSS files that will be loaded by the application.  In the example below, NetBeans generates a list of possible colors for the -fx-background-color property.

NetbeansFxCss

Finally, there is a code generator plugin which will generate getter and setter methods for JavaFX properties in a POJO class.  The normal Getter/Setter functionality would return a StringProperty object for the name variable (below), when ideally I would want the class me to return the actual String that the property represents.  A screen shot below shows the “Generate” popup menu item with the “JavaFx Props Getters & Setters”.  Once selected, the following screenshot illustrates the code that is generated.

The plugin is available at the link below.

https://github.com/rterp/JavaFxPropertyHelperNBPlugin/releases/download/1.0.0/JavaFxPropertyHelperNBPlugin-1.0.0.nbm

Ubuntu1

NetbeansFx2


Scenic View

Scenic View is another helpful tool when developing and debugging JavaFX applications.  It is a stand alone GUI application which will attach to a JavaFX application, and display all the nodes in the scene graph in a collapsable tree.  On the right side of the UI it will display various properties about the selected node.  ie min height, max height, location, css styles, etc.  In the screenshot below Scenic View is in front on the right side of the screen, and the application being debugged is behind Scenic View on the left side of the screen.  The selected button on the app is highlighted yellow, and Scenic View has selected this button in its tree view and is displaying its properties in the table on the right.

Scenic View can be downloaded at the FxExperience website.

ScenicView


MvvMFxLogo

Finally, MvvmFX is a framework for implementing the Model-View-ViewModel (MVVM) pattern in JavaFX.  This pattern allows you to separate any business logic related to the UI from the UI data and state, meaning that the business logic behind the UI can be unit tested without creating any UI components.  Since the view model doesn’t know about the view, it makes it possible to replace the view without requiring modifications to the view model.

An instance of the view model is injected into the view, which is just a JavaFx controller for a component.  An example view/controller class is shown below.

NetbeansFxMvvM

twitter: @RobTerpilowski
LinkedIn: Profile

Binding a List of Strings to a JavaFx ListView

Adding and modifying a List of Strings in a JavaFx ListView is a relatively easy task, although may not be completely intuitive at first glance.  In order to have changes to a List automatically reflected in a ListView you will need to make use of the ListProperty class, however setting items in the property is not as easy as calling the add() or addAll() methods.  This is because the underlying ObservableList class that the Property is using does not support the add() or addAll() methods.  Instead, you will need to first wrap your List in an ObservableList, and then pass that ObservableList to the ListProperty instance.

Below is an small sample application which illustrates this point.  There are two ArrayLists which contain Strings of data.  One contains the currency codes of some Asian currencies, and the other contains the currency codes of European currencies.  The list should initially be loaded with the Asian currencies, and when the user clicks on the Button, the handleButtonAction() method is invoked, which will cause the European currency list to be rendered in the ListView.

First, the FXML layout for the UI.


<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="201.0" prefWidth="131.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.40" fx:controller="com.lynden.testjavafxlistview.AppController">
<children>
<Button fx:id="button" layoutX="14.0" layoutY="160.0" onAction="#handleButtonAction" prefHeight="26.0" prefWidth="100.0" text="Click Me!" />
<ListView fx:id="myListView" layoutX="14.0" layoutY="21.0" prefHeight="109.0" prefWidth="100.0" />
</children>
</AnchorPane>

view raw

Scene.xml

hosted with ❤ by GitHub

Next, the controller class for the application


package com.lynden.testjavafxlistview;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
public class AppController implements Initializable {
@FXML
private Button button;
@FXML
private Label label;
@FXML
private ListView myListView;
protected List<String> asianCurrencyList = new ArrayList<>();
protected List<String> europeanCurrencyList = new ArrayList<>();
protected ListProperty<String> listProperty = new SimpleListProperty<>();
@FXML
private void handleButtonAction(ActionEvent event) {
listProperty.set(FXCollections.observableArrayList(europeanCurrencyList));
}
@Override
public void initialize(URL url, ResourceBundle rb) {
asianCurrencyList.add("CNH");
asianCurrencyList.add("JPY");
asianCurrencyList.add("HKD");
asianCurrencyList.add("KRW");
asianCurrencyList.add("SGD");
europeanCurrencyList.add("EUR");
europeanCurrencyList.add("GBP");
europeanCurrencyList.add("NOK");
europeanCurrencyList.add("SEK");
europeanCurrencyList.add("CHF");
europeanCurrencyList.add("HUF");
myListView.itemsProperty().bind(listProperty);
//This does not work, you can not directly add to a ListProperty
//listProperty.addAll( asianCurrencyList );
listProperty.set(FXCollections.observableArrayList(asianCurrencyList));
}
}

The two lists are populated within the initialize() method of the controller.  As you can see it is not possible simply to call the addAll() method on the ListProperty, as it will result in an “OperationNotSupportedException”.  Instead, at line 57, the FXCollections class is used to wrap the ArrayList in an ObservableArrayList instance, which is then passed into the ListProperty.

Finally, in the handleButtonAction() method, the europeanCurrencyList is wrapped in ObservableList, and passed to the ListProperty.  Since the ListProperty and the ListView are bound together (at line 53), the ListView is automatically updated with the European currency values.

Below are screenshots of the sample app both before and after the button has been clicked.

Asian Currencies

Asian currency list before clicking button.

Screen Shot 2015-09-21 at 4.48.36 PM

European currency list after clicking button.

 

 

 

 

 

 

 

 

twitter: @RobTerpilowski
LinkedIn Profile: Rob Terpilowski

 

 

Creating Custom Animated Transitions with JavaFX

JavaFX comes with a number of animated transitions out of the box which are very easy to integrate into an application without too much effort. There are times though when the existing animations don’t cover a desired transition between UI states. Fortunately, implementing a custom animation is as easy as subclassing the javafx.animation.Transition class and providing an implementation of the interpolate() method. As an example, I had a JavaFX Parent component which I wanted to “grow” to a larger height if a large component was placed inside it. Rather than having the Parent component just jump to its new larger height, I wanted the transition to the new height to be animated over a specified amount of time. I was able to accomplish this effect by creating the ResizeHeightTranslation below.


import javafx.animation.Transition;
import javafx.scene.layout.Region;
import javafx.util.Duration;
public class ResizeHeightTranslation extends Transition {
protected Region region;
protected double startHeight;
protected double newHeight;
protected double heightDiff;
public ResizeHeightTranslation( Duration duration, Region region, double newHeight ) {
setCycleDuration(duration);
this.region = region;
this.newHeight = newHeight;
this.startHeight = region.getHeight();
this.heightDiff = newHeightstartHeight;
}
@Override
protected void interpolate(double fraction) {
region.setMinHeight( startHeight + ( heightDiff * fraction ) );
}
}

In the constructor the duration of the animation is passed to the parent class, and the amount of space the component will need to grow is calculated.


public ResizeHeightTranslation( Duration duration, Region region, double newHeight ) {
setCycleDuration(duration);
this.region = region;
this.newHeight = newHeight;
this.startHeight = region.getHeight();
this.heightDiff = newHeightstartHeight;
}

All that remains to do in the interpolate() method is to calculate the new height based on how far along the animation is. The interpolate() method will be called by the JavaFX runtime with values starting from 0.0 and going to 1.0 as the animation progresses.


@Override
protected void interpolate(double fraction) {
region.setMinHeight( startHeight + ( heightDiff * fraction ) );
}


Example Usage

In the example below I have a JavaFX Pane (salmon color), and a Button. When the Button is clicked I would like to add a TableView to the Pane. The TableView however is taller than the Pane is so I would like the Pane to increase in height so the table fits completely within the Pane. To give this state transition a polished effect, I would like the resizing of the Pane to be animated and then I would like the TableView to fade into view once the resizing is complete. Below is a screenshot of the UI, containing the Pane and the Button components.

screen-shot-2015-09-01-at-1-26-24-pm

The FXML for the UI is below


<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="346.0" prefWidth="498.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.40" fx:controller="com.lynden.resizetest.FXMLController">
<children>
<Button fx:id="clickMeButton" layoutX="394.0" layoutY="294.0" onAction="#handleButtonAction" text="Click Me!" />
<Pane fx:id="contentPane" layoutX="25.0" layoutY="22.0" prefHeight="158.0" prefWidth="243.0" style="-fx-background-color: salmon;" />
</children>
</AnchorPane>

view raw

Scene.xml

hosted with ❤ by GitHub

In the controller class for the UI I have implemented and ActionListener method for the Button. When the Button is clicked a new TableView is created, along with a new ResizeHeightTranslation animation and a FadeTransition. Both of these animations are set to execute one right after the other by putting them in a SequentialTransition.


import com.lynden.glitter.animation.ResizeHeightTranslation;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.animation.FadeTransition;
import javafx.animation.SequentialTransition;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TableView;
import javafx.scene.layout.Pane;
import javafx.util.Duration;
public class FXMLController implements Initializable {
@FXML
private Button clickMeButton;
@FXML
private Pane contentPane;
@FXML
private void handleButtonAction(ActionEvent event) {
TableView tableView = new TableView();
tableView.setMaxHeight(250);
tableView.setMinHeight(250);
ResizeHeightTranslation rht = new ResizeHeightTranslation(Duration.millis(1000), contentPane, tableView.getMinHeight() );
FadeTransition ft = new FadeTransition(Duration.millis(1000), tableView);
ft.setFromValue(0);
ft.setToValue(1);
SequentialTransition pt = new SequentialTransition(rht, ft);
pt.play();
contentPane.getChildren().add(tableView);
}
@Override
public void initialize(URL url, ResourceBundle rb) {
}
}

Finally, a short clip illustrating the animated transition in action.

twitter: @RobTerpilowski

MVC tutorial with the NetBeans Rich Client Platform (RCP) and JavaFX

This tutorial illustrates the creation of a small application based on the NetBeans Rich Client Platform (RCP), and JavaFx, which will monitor the prices of a few stocks and update the UI in real time as prices are updated.  The application will make use of SceneBuilder to create an main UI, and JavaFX property bindings in order to keep the UI up to date as the prices are updated.


The Model

First, lets start with the model, a Stock class which will simply consist of a ticker symbol and a name.

public class Stock {
    
    protected String symbol;
    protected String name;

    public Stock(String symbol, String name) {
        this.symbol = symbol;
        this.name = name;
    }

    public String getSymbol() {
        return symbol;
    }

    public String getName() {
        return name;
    }    
}

Next, the listener interface that we will need to implement in order to get updates on the prices.  The priceUpdated() method will be invoked whenever a new price arrives for a stock.


public interface StockPriceUpdatedListener {

    public void priceUpdated( Stock stock, double price );
    
}

The model will consist of a collection of stocks, each of which will be mapped to a StringProperty.  When a new stock is added to the model, a new StringProperty will be created and mapped to the specified stock.  The model implements the StockPriceUpdatedListener interface.  When a new price is received, the StringProperty for that Stock will be looked up and updated.

Note that in the model below that you need to be on the main JavaFx thread when you update a property!  For the purposes of this application the stock prices are arriving from a non-ui thread, so updating the property needs to be wrapped in a Platform.runLater() call which will put the update on to the ui-thread.


import com.mvc.stock.price.Stock;
import com.mvc.stock.price.StockPriceUpdatedListener;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

public class StockModel implements StockPriceUpdatedListener {
    
    protected Map<Stock, StringProperty> stocks = new HashMap<>();
    DecimalFormat df = new DecimalFormat("$##0.00");
    
    public StringProperty addStock( Stock stock ) {
        StringProperty property = stocks.get(stock);
        if( property == null ) {
            property = new SimpleStringProperty("");
            stocks.put(stock, property);
        }
        
        return property;
    }
    
    @Override
    public void priceUpdated(Stock stock, double price) {
        //Don't update the properties from a non-JavaFx-UI thread!
        Platform.runLater( () -> stocks.get(stock).setValue(df.format(price)));
    }    
}


The View

Next, the view for this application was designed with SceneBuilder.  The layout consists of a GridPane containing information about a few stocks, as well as a subscribe button which will trigger the monitoring of price information.

Screen Shot 2015-06-12 at 1.06.11 PM

SceneBuilder generated the following FXML code below, with the UI controller set to:

com.mvc.stock.ui.StockPriceController

Also note that the button has its onAction event defined to call the subscribeButtonClicked() method which will need to be implemented in the StockPriceController class.


<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>


<AnchorPane id="AnchorPane" prefHeight="197.0" prefWidth="233.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="com.mvc.stock.ui.StockPricePanelController">
    <children>
        <GridPane alignment="CENTER" gridLinesVisible="true" layoutX="14.0" layoutY="14.0">
            <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
            </columnConstraints>
            <rowConstraints>
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            </rowConstraints>
            <children>
                <Label text="MSFT" GridPane.halignment="RIGHT" GridPane.rowIndex="1">
                    <padding>
                        <Insets right="10.0" />
                    </padding>
                </Label>
                <Label alignment="CENTER" text="Stock" textAlignment="CENTER" GridPane.halignment="CENTER">
                    <padding>
                        <Insets right="10.0" />
                    </padding>
                    <font>
                        <Font name="System Bold" size="13.0" />
                    </font>
                </Label>
                <Label text="Last Price" GridPane.columnIndex="1" GridPane.halignment="CENTER">
                    <font>
                        <Font name="System Bold" size="13.0" />
                    </font>
                </Label>
                <Label text="EBAY" GridPane.halignment="RIGHT" GridPane.rowIndex="3">
                    <padding>
                        <Insets right="10.0" />
                    </padding>
                </Label>
                <Label text="AMZN" GridPane.halignment="RIGHT" GridPane.rowIndex="2">
                    <padding>
                        <Insets right="10.0" />
                    </padding>
                </Label>
                <Label fx:id="msftPriceLabel" GridPane.columnIndex="1" GridPane.rowIndex="1">
                    <padding>
                        <Insets left="10.0" />
                    </padding>
                </Label>
                <Label fx:id="amznPriceLabel" GridPane.columnIndex="1" GridPane.rowIndex="2">
                    <padding>
                        <Insets left="10.0" />
                    </padding>
                </Label>
                <Label fx:id="ebayPriceLabel" GridPane.columnIndex="1" GridPane.rowIndex="3">
                    <padding>
                        <Insets left="10.0" />
                    </padding>
                </Label>
            </children>
        </GridPane>
        <Button fx:id="subscribeButton" layoutX="136.0" layoutY="153.0" mnemonicParsing="false" onAction="#subscribeButtonClicked" text="Subscribe" />
    </children>
</AnchorPane>



The Controller

As mentioned above, the FXML file references StockPricePanelController as the UI’s controller.  The controller has 3 labels and a button defined which will be injected into the controller by annotating those fields with the @FXML annotation.  When the controller is first initialized it creates a new stock object for each stock and then binds the StringProperty of the StockModel to the StringProperty of its corresponding label.

Also, as previously stated, the controller will need to implement a method called subscribeButtonClicked() which was defined in the FXML above.  This method needs to be annotated with the @FXML annotation in order to be invoked when the subscribeButton is clicked.  When this action is invoked, the controller will subscribe to price data for the specified stocks.


import com.mvc.stock.price.Stock;
import com.mvc.stock.price.provider.IStockPriceProvider;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;

/**
 * FXML Controller class
 *
 */
public class StockPricePanelController implements Initializable {

    
    @FXML
    protected Label msftPriceLabel;
    
    @FXML
    protected Label amznPriceLabel;
    
    @FXML
    protected Label ebayPriceLabel;
    
    @FXML
    protected Button subscribeButton;
    
    protected StockModel stockModel;
    
    protected IStockPriceProvider provider;
    protected Stock msft = new Stock("MSFT", "Microsoft");
    protected Stock amzn = new Stock("AMZN", "Amazon");
    protected Stock ebay = new Stock("EBAY", "eBay");
    
    
    /**
     * Initializes the controller class.
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        stockModel = new StockModel();
        //bind the string property from the model to the labels.
        msftPriceLabel.textProperty().bindBidirectional( stockModel.addStock(msft) );
        amznPriceLabel.textProperty().bindBidirectional( stockModel.addStock(amzn) );
        ebayPriceLabel.textProperty().bindBidirectional( stockModel.addStock(ebay) );
    }    

    public IStockPriceProvider getProvider() {
        return provider;
    }

    public void setProvider(IStockPriceProvider provider) {
        this.provider = provider;
    }

    @FXML
    public void subscribeButtonClicked( ActionEvent event ) {
        if( provider != null ) {
            provider.subscribeToPriceData(msft, stockModel);
            provider.subscribeToPriceData(amzn, stockModel);
            provider.subscribeToPriceData(ebay, stockModel);
        }
    }
    
}

The final piece is to tie JavaFX UI into the NetBeans module which this component is a part of.  In order to do this you will need to have a TopComponent defined for your module like in the example below.  Basically a TopComponent is a top level panel that is usually within a TabbedPane in the main UI.  The TopComponent class below uses the Lookup API to find an implementation of an IStockPriceProvider interface.  Next a JFXPanel is created, which is a Swing JPanel that can hold a JavaFX Scene.

Within the Platform.runLater() method, a new FXMLLoader is created which points to the location of the FXML file from above.  Once the loader has loaded the file, we can obtain a reference to the StockPricePanelController, and pass in the instance of the stockPriceProvider that was previously just looked up.

Finally, a new Scene is created,  added to the JFXPanel, and the JFXPanel is added to the Center position of the TopComponent.


public final class StockPriceTopComponent extends TopComponent {

    public StockPriceTopComponent() {
        initComponents();
        setName(Bundle.CTL_StockPriceTopComponent());
        setToolTipText(Bundle.HINT_StockPriceTopComponent());
        putClientProperty(TopComponent.PROP_CLOSING_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_DRAGGING_DISABLED, Boolean.TRUE);
        putClientProperty(TopComponent.PROP_UNDOCKING_DISABLED, Boolean.TRUE);
        
        
        IStockPriceProvider stockPriceProvider = Lookup.getDefault().lookup(IStockPriceProvider.class);
        if( stockPriceProvider == null ) {
            throw new IllegalStateException( "Provider is null");
        }        
        
        JFXPanel jfxPanel = new JFXPanel();

        //This needs to be set to make sure the JavaFx thread doesn't exit if the tab is closed.
        Platform.setImplicitExit(false);
        
        // create JavaFX scene
        Platform.runLater(() -> {
            Parent root;
            try {
                FXMLLoader loader = new FXMLLoader(getClass().getResource("/com/mvc/stock/ui/StockPricePanel.fxml"));
                root = loader.load();
                StockPricePanelController controller = loader.getController();
                controller.setProvider(stockPriceProvider);
                
                Scene scene = new Scene(root);
                
                jfxPanel.setScene(scene);
            } catch (IOException ex) {
                Exceptions.printStackTrace(ex);
            }
        });
        add( jfxPanel, BorderLayout.CENTER );
    }

The resulting NetBeans application is shown below.

Screen Shot 2015-06-12 at 1.43.45 PM

twitter: @RobTerpilowski
t
witter: @LimitUpTrading

Using Dependency Injection in a Java SE Application

It would be nice to decouple components in client applications the way that we have become accustom to doing in server side applications and providing a way to use mock implementations for unit testing.

Fortunately it is fairly straightforward to configure a Java SE client application to use a dependency injection framework such as Weld.

The first step is to include the weld-se jar as a dependency in your project. The weld-se jar is basically the Weld framework repackaged along with its other dependencies as a single jar file which is about 4MB.

    <dependency>
        <groupId>org.jboss.weld.se</groupId>
        <artifactId>weld-se</artifactId>
        <version>2.2.11.Final</version>
    </dependency>

 

Implement a singleton which will create and initialize the Weld container and provide a method to access a bean from the container.

import org.jboss.weld.environment.se.Weld;
import org.jboss.weld.environment.se.WeldContainer;


public class CdiContext {

    public static final CdiContext INSTANCE = new CdiContext();

    private final Weld weld;
    private final WeldContainer container;

    private CdiContext() {
        this.weld = new Weld();
        this.container = weld.initialize();
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                weld.shutdown();
            }
        });
    }

    public <T> T getBean(Class<T> type) {
        return container.instance().select(type).get();
    }
}

 

Once you have the context you can then use it to instantiate a bean which in turn will inject any dependencies into the bean.

import java.util.HashMap;
import java.util.Map;


public class MainClass {
    protected String baseDir;
    protected String wldFileLocation;
    protected String dataFileDir;
    protected int timeInterval = 15;
    protected String outputFileDir;

    public void run() throws Exception {
        CdiContext context = CdiContext.INSTANCE;

        //Get an isntance of the bean from the context
        IMatcher matcher = context.getBean(IMatcher.class);

        matcher.setCommodityTradeTimeMap( getDateTranslations(1, "6:30:00 AM", "6:35:00 AM", "6:45:00 AM") );

        matcher.matchTrades(wldFileLocation, dataFileDir, timeInterval, outputFileDir);

    }

What is great is that there are no annotations required on the interfaces or their implementing classes. Weld will automatically find the implementation and inject it in the class where defined. ie. there were no annotations required on the IDataFileReader interface or its implementing classes in order to @Inject it into the Matcher class. Likewise neither the IMatcher interface nor the Matcher class require annotations in order to be instantiated by the CdiContext above.

public class Matcher implements IMatcher {

    //Framework will automatically find and inject
    //an implementation of IDataFileReader

    @Inject
    protected IDataFileReader dataFileReader;

twitter: @RobTerpilowski
@LimitUpTrading

Automatically Sorting a JavaFX TableView

With the SortedList implementation of ObservableList, automatically sorting a JavaFX TableView nearly works out of the box. In fact, it does work out of the box as long as you are adding or removing items from the list. In these circumstances, the list and the accompanying TableView will automatically resort the data. The case where the data isn’t automatically resorted is if the data in the existing rows change, but no rows are added or removed from the list.

For example, I have a TableView displaying various price information about a list of stocks including the last price, and the percent change from yesterday’s closing price. I would like to sort the list based on percent change, from lowest to highest as the prices change in real-time.  However since the app just loads the stocks into the list once and then never adds or removes items from the list, the TableView only auto sorted on the initial load, but did not automatically sort as the prices were updated.

Fortunately the fix proved to be fairly minor and easy to implement.

To start with, the application uses a Stock POJO which contains the following properties to represent the data. An ObservableList of these POJOs will be the basis of the data that the TableView will render.

public class Stock implements Level1QuoteListener {

protected StockTicker ticker;

protected SimpleStringProperty symbol = new SimpleStringProperty("");

protected SimpleDoubleProperty bid = new SimpleDoubleProperty(0);

protected SimpleDoubleProperty ask = new SimpleDoubleProperty(0);

protected SimpleDoubleProperty last = new SimpleDoubleProperty(0);

protected SimpleDoubleProperty percentChange = new SimpleDoubleProperty(0);

protected SimpleIntegerProperty volume = new SimpleIntegerProperty(0);

protected SimpleDoubleProperty previousClose = new SimpleDoubleProperty(0);

protected SimpleDoubleProperty open = new SimpleDoubleProperty(0);

 

The first step is to implement a new Callback, tying it to the property we wish to sort in the table. When this property is updated it will trigger the table to resort itself automatically.

      Callback<Stock,Observable[]> cb =(Stock stock) -> new Observable[]{
        stock.percentChangeProperty(),
    };

 

The next step is to create a new ObservableList using the Callback above.

      ObservableList<Stock> observableList = FXCollections.observableArrayList(cb);
      observableList.addAll(stocks);

Finally the last step is to create a new SortedList using the ObservableList previously created and also passing in an implementation of a Comparator which will be used to determine how to sort the data.

      SortedList<Stock> sortedList = new SortedList<>( observableList, 
      (Stock stock1, Stock stock2) -> {
        if( stock1.getPercentChange() < stock2.getPercentChange() ) {
            return -1;
        } else if( stock1.getPercentChange() > stock2.getPercentChange() ) {
            return 1;
        } else {
            return 0;
        }
    });


    tickerTableView.setItems(sortedList);
}

That’s it. The video below illustrates the auto-sorting in action as the price of the stocks are updated in real-time.


twitter: @RobTerpilowski

JPA java.lang.IllegalArgumentException: No query defined for that name (Solved)

I’ve recently been working with the [Camel JPA] (http://camel.apache.org/jpa.html) component for moving data from one of our SQL servers to our messaging system.

We have a number of Entity POJOs defined that contain a named query which the JPA component uses in order to query the database to select the appropriate records that need to be processed. Everything was working great and I decided to move these beans to a separate library that could be shared with other applications. However, once I did this the original application started encountering the following error.

java.lang.IllegalArgumentException: No query defined for that name [AllinboundMessagesSqlBean.findByProcessed]

I checked the classpath and the beans were in fact being found, but the named queries on the beans were not being found. It took some research, but the solution to the problem ended up proving to be very simple.

The change was to explicitly add the entity classes to the application’s persistance.xml

com.lynden.json.beans.AllinboundLoopBean
com.lynden.json.beans.AllinboundMessagesSqlBean

Once the classes were defined in the file, the app was then able to find these entity beans that were in a separate .jar. Hopefully this will help others out there who may have run into a similar issue.

twitter: @RobTerpilowski

Formatting Rows in a JavaFX TableView Using CSS Pseudo Classes

One strategy for formatting cells in a JavaFX TableView is to utilize CSS Pseudo classes and a TableRowFactory to select the appropriate class to style the row. Below is a screenshot of an applcation that is configured to monitor real time stock quotes. Each row displays price information for a single stock. I would like the rows to be colored based on the price change of the particular stock, with a red row representing a stock that is trading lower since the previous day, and a green row to represent a stock whose current price is higher than the previous day.

enter image description here

First the domain object which represents the Stock is below. Notice that the class uses JavaFX properties to represent the various values that are displayed in each column.

public class Stock implements Level1QuoteListener {

protected StockTicker ticker;
protected SimpleStringProperty symbol = new SimpleStringProperty();
protected SimpleDoubleProperty bid = new SimpleDoubleProperty();
protected SimpleDoubleProperty ask= new SimpleDoubleProperty();
protected SimpleDoubleProperty last = new SimpleDoubleProperty();
protected SimpleDoubleProperty percentChange = new SimpleDoubleProperty();
protected SimpleIntegerProperty volume = new SimpleIntegerProperty();
protected SimpleDoubleProperty previousClose = new SimpleDoubleProperty();
protected SimpleDoubleProperty open = new SimpleDoubleProperty();


public Stock( StockTicker ticker ) {
    this.ticker = ticker;
    setSymbol( ticker.getSymbol() );
}

public void setSymbol( String symbol ) {
    this.symbol.set(symbol);
}

public String getSymbol() {
    return symbol.get();
}

public StringProperty symbol() {
    return symbol;
}

public void setBid( double bid ) {
    this.bid.set(bid);
}

public double getBid() {
    return bid.get();
}

public SimpleDoubleProperty bid() {
    return bid;
}

public void setAsk( double ask ) {
    this.ask.set(ask);
}

public double getAsk() {
    return ask.get();
}

public DoubleProperty ask() {
    return ask;
}

public void setLast( double last ) {
    this.last.set(last);
    double change = ((last-closeProperty().get() ) / closeProperty().get() ) * 100.0;
    setPercentChange(change);

}

public double getLast() {
    return last.get();
}

public DoubleProperty last() {
    return last;
}

public void setPercentChange( double percentChange ) {
    this.percentChange.set(percentChange);
}

public double getPercentChange() {
    return percentChange.get();
}

public void setVolume( int volume ) {
    this.volume.set(volume);
}

public int getVolume() {
    return volume.get();
}

public void setPreviousClose( double close ) {
    this.previousClose.set(close);
    double change = ((last.get()-close ) / close ) * 100.0;
    setPercentChange(change);
}


public double getPreviousClose() {
    return previousClose.get();
}

public DoubleProperty previousClose() {
    return previousClose;
}

public void setOpen( double open ) {
    this.open.set(open);
}

public double getOpen() {
    return open.get();
}

public DoubleProperty openProperty() {
    return open;
}

public DoubleProperty closeProperty() {
    return previousClose;
}

public DoubleProperty percentChangeProperty() {
    return percentChange;
}

public StockTicker getTicker() {
    return ticker;
}



@Override
public void quoteRecieved(ILevel1Quote quote) {
    if( quote.getTicker().equals(ticker)) {
        BigDecimal quoteValue = quote.getValue();
        switch( quote.getType() ) {
            case ASK:
                setAsk(quoteValue.doubleValue());
                break;
            case BID:
                setBid(quoteValue.doubleValue());
                break;
            case LAST:
                setLast(quoteValue.doubleValue());
                break;
            case CLOSE:                  
                setPreviousClose(quoteValue.doubleValue());
                break;
            case OPEN:
                setOpen(quoteValue.doubleValue());
                break;
            case VOLUME:
                setVolume(quoteValue.intValue());
                break;
            default:
                break;

        }
    }
}

The first step in creating a custom format is to define the styles in the CSS stylesheet that is associated with the TableView. The CSS file below shows how the table row will be formatted. Comments below describe each item including the ‘up’ and ‘down’ Pseudo classes that are defined for the .table-row-cell class.

/* Default row background is black */
.table-row-cell {
    -fx-background-color: black;
}

/* Text in the rows will be white */
.table-row-cell .text {
       -fx-fill: white ;
}

/*
Pseudo class 'up' will change the row background
 color to green when activated 
 */
.table-row-cell:up 
{
    -fx-background-color: #007054; 
}

/*
Pseudo class 'down' will change the row background 
color to red when activated
*/
.table-row-cell:down {
    -fx-background-color: #A30029;
}

Ok, so far this seems easy enough. Now the tricky part is to activate the proper Pseudo class when the % change of the stock price is positive or negative. This can be done using a TableRowFactory in the controller class which is managing the TableView.

Below is an example controller which has a reference to a TableView object called tickerTableView. The setup() method contains logic for selecting the appropriate pseudo class based on the stock data.

public class FXMLController implements Initializable {


@FXML
private TableView tickerTableView;


 public void setup() {
 //The pseudo classes 'up' and 'down' that were defined in the css file.
    PseudoClass up = PseudoClass.getPseudoClass("up");
    PseudoClass down = PseudoClass.getPseudoClass("down");



//Set a rowFactory for the table view.
tickerTableView.setRowFactory(tableView -> {
        TableRow<Stock> row = new TableRow<>();
        ChangeListener<Number> changeListener = (obs, oldPrice, newPrice) -> {
            row.pseudoClassStateChanged(up, newPrice.doubleValue() > 0);
            row.pseudoClassStateChanged(down, newPrice.doubleValue() <= 0);
        };

        row.itemProperty().addListener((obs, previousStock, currentStock) -> {
            if (previousStock != null) {
                previousStock.percentChangeProperty().removeListener(changeListener);
            }
            if (currentStock != null) {
                currentStock.percentChangeProperty().addListener(changeListener);
                row.pseudoClassStateChanged(up, currentStock.getPercentChange() > 0);
                row.pseudoClassStateChanged(down, currentStock.getPercentChange() <= 0);
            } else {
                row.pseudoClassStateChanged(up, false);
                row.pseudoClassStateChanged(down, false);
            }
        });
        return row;
    });
}

The first step is to create 2 new PseudoClass object which will map to the Pseudo classes that were defined in the css file.

PseudoClass up = PseudoClass.getPseudoClass("up");
PseudoClass down = PseudoClass.getPseudoClass("down");

Next a RowFactory needs to be defined which knows how to select the proper PseudoClass. The setRowFactory() method on the TableView class takes a Callback object which in turn takes a TableView as an argument and returns a TableRow.

The first thing to do in the row factory is to create a new change listener. This listener will monitor the stock for a particular row. The oldPrice and newPrice are passed into the change listener. The pseudo class of the row can then be activated or deactivated by invoking the pseudoClassStateChanged() method on the TableRow and passing the appropriate PseudoClass and boolean value to indicate whether or not the class should be active.

tickerTableView.setRowFactory(tableView -> {
   TableRow<Stock> row = new TableRow<>();
   ChangeListener<Number> changeListener = (obs, oldPrice, newPrice) -> {
     row.pseudoClassStateChanged(up, newPrice.doubleValue() > 0);
     row.pseudoClassStateChanged(down, newPrice.doubleValue() <= 0);
   };

The final piece is to tie the change listener to the item in the TableRow. This is done by adding a listener on the ItemProperty of the row. Once a Stock item is added to the TableRow, the ChangeListener defined above can be bound to the Stock’s percentChangeProperty. The initial state of the classes are also set when the new item is added. If a Stock item is being removed from the TableRow, the previousStock variable will be populate with the Stock object that is being removed. At this point the change listener can be removed from the row for the old Stock before the new one is added.

row.itemProperty().addListener((obs, previousStock, currentStock) -> {
            if (previousStock != null) {
                previousStock.percentChangeProperty().removeListener(changeListener);
            }
            if (currentStock != null) {
                currentStock.percentChangeProperty().addListener(changeListener);
                //Set the initial state of the pseudo classes
                row.pseudoClassStateChanged(up, currentStock.getPercentChange() > 0);
                row.pseudoClassStateChanged(down, currentStock.getPercentChange() <= 0);
            } else {
                row.pseudoClassStateChanged(up, false);
                row.pseudoClassStateChanged(down, false);
            }
        });
        return row;
    });

The final result is displayed in the table below Rows will change between red and green automatically in real time as the price of the stock fluctuates throughout the trading day.

enter image description here

twitter: @RobTerpilowski