Welcome!

Machine Learning Authors: Pat Romanski, Liz McMillan, Yeshim Deniz, Elizabeth White, Corey Roth

Related Topics: Agile Computing, Machine Learning

Agile Computing: Blog Feed Post

Three Steps to Build a Killer WebSocket App with JavaFX

The app I wanted to build consumes the same data source as the lightning fast Kaazing portfolio demo


Here’s the source for my Sample.fxml file:

 

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

<?import fxmltableview.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.collections.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.control.cell.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.text.*?>
<?import javafxapplication4.*?>

<AnchorPane id="AnchorPane" prefHeight="443.999755859375" prefWidth="656.9998779296875" xmlns:fx="http://javafx.com/fxml" fx:controller="javafxapplication4.SampleController">
  <children>
    <BorderPane prefHeight="706.0" prefWidth="717.0" snapToPixel="false" AnchorPane.bottomAnchor="14.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="14.0" AnchorPane.topAnchor="0.0">
      <right>
        <TableView fx:id="tableView" editable="true" prefHeight="393.999755859375" prefWidth="555.9998779296875">
          <columns>
            <TableColumn prefWidth="240.0" text="Company" fx:id="company">
              <cellValueFactory>
                <PropertyValueFactory property="company" />
              </cellValueFactory>
            </TableColumn>
            <TableColumn prefWidth="100.0" text="Ticker" fx:id="ticker">
              <cellValueFactory>
                <PropertyValueFactory property="ticker" />
              </cellValueFactory>
            </TableColumn>
            <TableColumn prefWidth="100.0" text="Price" fx:id="price">
              <cellValueFactory>
                <PropertyValueFactory property="price" />
              </cellValueFactory>
            </TableColumn>
            <TableColumn prefWidth="100.0" text="Change" fx:id="change">
              <cellValueFactory>
                <PropertyValueFactory property="change" />
              </cellValueFactory>
            </TableColumn>
          </columns>
          <BorderPane.margin>
            <Insets bottom="50.0" left="50.0" right="50.0" top="50.0" />
          </BorderPane.margin>
        </TableView>
      </right>
      <top>
        <Pane prefHeight="32.0" prefWidth="745.0">
          <children>
            <Label alignment="CENTER" contentDisplay="CENTER" layoutX="14.0" layoutY="5.0" prefWidth="614.9998779296875" text="WebSocket Portfolio Demo" textAlignment="CENTER" textFill="#cc6200">
              <font>
                <Font name="System Bold" size="24.0" />
              </font>
            </Label>
          </children>
        </Pane>
      </top>
    </BorderPane>
  </children>
</AnchorPane>

 

Then, I defined the data model driving my TableView. I created a JavaBean, called Stock, with four private variables. The first three: company, ticker, and price, represent the first three columns of my TableView. The fourth one is a computed value, displaying the change of the price of a stock.

 

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javafxapplication4;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/**
 *
 * @author pmoskovi
 */
public class Stock {

    private SimpleStringProperty company;
    private SimpleStringProperty ticker;
    private SimpleStringProperty price;
    private SimpleStringProperty change;

    public Stock () {
        setCompany("");
        setTicker("");
        setPrice("");
    }

    public Stock(String company, String ticker, String price, String shares, String value) {
        setCompany(company);
        setTicker (ticker);
        setPrice (price);
    }

    public String getCompany() {
        return companyProperty().get();
    }

    public void setCompany(String company) {
        companyProperty().set(company);
    }

    public StringProperty companyProperty() {
        if (company == null) {
            company = new SimpleStringProperty(this, "company");
        }
         return company;
    }

    public String getTicker() {
        return tickerProperty().get();
    }

    public void setTicker(String ticker) {
        tickerProperty().set(ticker);
    }

    public StringProperty tickerProperty() {
        if (ticker == null) {
            ticker = new SimpleStringProperty(this, "ticker");
        }
         return ticker;
    }

    public String getPrice() {
        return priceProperty().get();
    }

    public void setPrice(String price) {
        priceProperty().set(price);
    }

    public StringProperty priceProperty() {
        if (price == null) {
            price = new SimpleStringProperty(this, "price");
        }
         return price;
    }

    public String getChange() {
        return changeProperty().get();
    }

    public void setChange(String change) {
        changeProperty().set(change);
    }

    public StringProperty changeProperty() {
        if (change == null) {
            change = new SimpleStringProperty(this, "change");
        }
         return change;
    }
}

 

Step 3 – Feeding the application with data through WebSockets

Lastly, by simply following the How to Build Java Client Using Kaazing WebSocket Gateway I created the WebSocket connection, subscribed to the stock data feed, and updated my model which in turn refreshed the TableView in the screen.

The app uses the JMS Edition of Kaazing WebSocket Gateway, allowing you to invoke JMS APIs directly in the JavaFX application code.

 

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javafxapplication4;

import java.net.URL;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.naming.Context;
import javax.naming.InitialContext;

/**
 *
 * @author pmoskovi
 */
public class SampleController implements Initializable {

    private ObservableList data;
    @FXML
    private Label label;
    @FXML
    private TableView tableView;
    @FXML
    private TableColumn<Stock, String> change;
    ListIterator it;

    public void startRendering() {

        addStock("3mCo", "MMM", "", "", "");
        addStock("AT&T Inc", "T", "", "", "");
        addStock("Boeing Co", "BA", "", "", "");
        addStock("Citigroup", "C", "", "", "");
        addStock("Hewlett-Packard Co", "HPQ", "", "", "");
        addStock("Intel Corporation", "INTC", "", "", "");
        addStock("International Business Machines", "IBM", "", "", "");
        addStock("McDonald's Cororation", "MCD", "", "", "");
        addStock("Microsoft Corporation", "MSFT", "", "", "");
        addStock("Verizon Communications", "VZ", "", "", "");
        addStock("Wal-Mart Stores Inc", "WMT", "", "", "");

        doConnect();
    }

    protected void addStock(String company, String ticker, String price, String shares, String value) {
        ObservableList data = tableView.getItems();
        data.add(new Stock(company, ticker, price, shares, value));
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        startRendering();
    }

    protected void doConnect() {
        Properties props = new Properties();
        props.put(InitialContext.INITIAL_CONTEXT_FACTORY,
                "com.kaazing.gateway.jms.client.stomp.StompInitialContextFactory");

        //WebSocket end-point
        props.put(Context.PROVIDER_URL, "ws://demo.kaazing.com/jms");
        InitialContext ctx;
        final ObservableList data = tableView.getItems();

        try {
            ctx = new InitialContext(props);
            ConnectionFactory connectionFactory;
            connectionFactory = (ConnectionFactory) ctx.lookup("ConnectionFactory");

            //Creating WebSocket connection
            Connection connection = connectionFactory.createConnection(null, null);
            connection.setExceptionListener(new ExceptionListener() {
                @Override
                public void onException(JMSException jmse) {
                    jmse.printStackTrace();
                }
            });

            //Creating JMS session
            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

            //Creating JMS topic
            Topic topic = (Topic) ctx.lookup("/topic/portfolioStock");

            //Creating JMS consumer
            MessageConsumer consumer = session.createConsumer(topic);
            consumer.setMessageListener(new MessageListener() {
                @Override
                public void onMessage(Message msg) {
                    it = data.listIterator();

                    try {
                        // Creating a String array out of the incoming message: ticker, company, price
                        String[] stockMsgArr = parseList(((TextMessage) msg).getText(), ":");

//                        System.out.println(stockMsgArr[0] + ":" + stockMsgArr[1] + ":" + stockMsgArr[2]);
                        // Loop through all the elements of the viewTable model
                        while (it.hasNext()) {
                            // st holds the current row of tableView
                            Stock st = (Stock)it.next();
//                            System.out.println("st.getTicker() " + st.getTicker() + " | " + "stockMsgArr[1] " + stockMsgArr[1]);

                            if (st.getTicker().equals(stockMsgArr[1])) {
                                Float oldValue, newValue;
                                newValue = Float.parseFloat(stockMsgArr[2]);
                                oldValue = Float.parseFloat((st.getPrice().equals("")) ? "0" : st.getPrice());
//                                System.out.println ("oldValue: " + oldValue + " | newValue: " + newValue);
                                ((Stock)(it.previous())).setChange(new DecimalFormat("#.##").format((newValue-oldValue)));
                                st.setPrice (newValue.toString());
                                break;
                            }
                        }
                    } catch (JMSException e) {
                        e.printStackTrace();
                    }
                }
            });
            connection.start();
        } catch (Exception ex) {
            Logger.getLogger(SampleController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static String[] parseList(String list, String delim) {
        List result = new ArrayList();
        StringTokenizer tokenizer = new StringTokenizer(list, delim);
        while (tokenizer.hasMoreTokens()) {
            result.add(tokenizer.nextToken());
        }
        return (String[]) result.toArray(new String[0]);
    }

}

 

If you’re attending JavaOne this year, come to our session for goodies and cool demos on WebSockets.

To learn more about the JMS APIs exposed to Web clients, or if you want to see step-by-step instructions on building a true HTML5 WebSocket app using the JavaScript API, check out these Kaazing tutorials.


Read the original blog entry...

More Stories By Kaazing Blog

Kaazing is helping define the future of the event-driven enterprise by accelerating the Web for the Internet of Things.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.


@CloudExpo Stories
For organizations that have amassed large sums of software complexity, taking a microservices approach is the first step toward DevOps and continuous improvement / development. Integrating system-level analysis with microservices makes it easier to change and add functionality to applications at any time without the increase of risk. Before you start big transformation projects or a cloud migration, make sure these changes won’t take down your entire organization.
It is ironic, but perhaps not unexpected, that many organizations who want the benefits of using an Agile approach to deliver software use a waterfall approach to adopting Agile practices: they form plans, they set milestones, and they measure progress by how many teams they have engaged. Old habits die hard, but like most waterfall software projects, most waterfall-style Agile adoption efforts fail to produce the results desired. The problem is that to get the results they want, they have to ch...
Organizations planning enterprise data center consolidation and modernization projects are faced with a challenging, costly reality. Requirements to deploy modern, cloud-native applications simultaneously with traditional client/server applications are almost impossible to achieve with hardware-centric enterprise infrastructure. Compute and network infrastructure are fast moving down a software-defined path, but storage has been a laggard. Until now.
Without a clear strategy for cost control and an architecture designed with cloud services in mind, costs and operational performance can quickly get out of control. To avoid multiple architectural redesigns requires extensive thought and planning. Boundary (now part of BMC) launched a new public-facing multi-tenant high resolution monitoring service on Amazon AWS two years ago, facing challenges and learning best practices in the early days of the new service.
Digital Transformation is much more than a buzzword. The radical shift to digital mechanisms for almost every process is evident across all industries and verticals. This is often especially true in financial services, where the legacy environment is many times unable to keep up with the rapidly shifting demands of the consumer. The constant pressure to provide complete, omnichannel delivery of customer-facing solutions to meet both regulatory and customer demands is putting enormous pressure on...
The best way to leverage your CloudEXPO | DXWorldEXPO presence as a sponsor and exhibitor is to plan your news announcements around our events. The press covering CloudEXPO | DXWorldEXPO will have access to these releases and will amplify your news announcements. More than two dozen Cloud companies either set deals at our shows or have announced their mergers and acquisitions at CloudEXPO. Product announcements during our show provide your company with the most reach through our targeted audienc...
With 10 simultaneous tracks, keynotes, general sessions and targeted breakout classes, @CloudEXPO and DXWorldEXPO are two of the most important technology events of the year. Since its launch over eight years ago, @CloudEXPO and DXWorldEXPO have presented a rock star faculty as well as showcased hundreds of sponsors and exhibitors!
DXWorldEXPO LLC announced today that All in Mobile, a mobile app development company from Poland, will exhibit at the 22nd International CloudEXPO | DXWorldEXPO. All In Mobile is a mobile app development company from Poland. Since 2014, they maintain passion for developing mobile applications for enterprises and startups worldwide.
JETRO showcased Japan Digital Transformation Pavilion at SYS-CON's 21st International Cloud Expo® at the Santa Clara Convention Center in Santa Clara, CA. The Japan External Trade Organization (JETRO) is a non-profit organization that provides business support services to companies expanding to Japan. With the support of JETRO's dedicated staff, clients can incorporate their business; receive visa, immigration, and HR support; find dedicated office space; identify local government subsidies; get...
Both SaaS vendors and SaaS buyers are going “all-in” to hyperscale IaaS platforms such as AWS, which is disrupting the SaaS value proposition. Why should the enterprise SaaS consumer pay for the SaaS service if their data is resident in adjacent AWS S3 buckets? If both SaaS sellers and buyers are using the same cloud tools, automation and pay-per-transaction model offered by IaaS platforms, then why not host the “shrink-wrapped” software in the customers’ cloud? Further, serverless computing, cl...
"We view the cloud not as a specific technology but as a way of doing business and that way of doing business is transforming the way software, infrastructure and services are being delivered to business," explained Matthew Rosen, CEO and Director at Fusion, in this SYS-CON.tv interview at 18th Cloud Expo (http://www.CloudComputingExpo.com), held June 7-9 at the Javits Center in New York City, NY.
DXWorldEXPO LLC announced today that the upcoming DXWorldEXPO | CloudEXPO New York event will feature 10 companies from Poland to participate at the "Poland Digital Transformation Pavilion" on November 12-13, 2018.
The current age of digital transformation means that IT organizations must adapt their toolset to cover all digital experiences, beyond just the end users’. Today’s businesses can no longer focus solely on the digital interactions they manage with employees or customers; they must now contend with non-traditional factors. Whether it's the power of brand to make or break a company, the need to monitor across all locations 24/7, or the ability to proactively resolve issues, companies must adapt to...
In his Opening Keynote at 21st Cloud Expo, John Considine, General Manager of IBM Cloud Infrastructure, led attendees through the exciting evolution of the cloud. He looked at this major disruption from the perspective of technology, business models, and what this means for enterprises of all sizes. John Considine is General Manager of Cloud Infrastructure Services at IBM. In that role he is responsible for leading IBM’s public cloud infrastructure including strategy, development, and offering m...
As data explodes in quantity, importance and from new sources, the need for managing and protecting data residing across physical, virtual, and cloud environments grow with it. Managing data includes protecting it, indexing and classifying it for true, long-term management, compliance and E-Discovery. Commvault can ensure this with a single pane of glass solution – whether in a private cloud, a Service Provider delivered public cloud or a hybrid cloud environment – across the heterogeneous enter...
We all know that end users experience the internet primarily with mobile devices. From an app development perspective, we know that successfully responding to the needs of mobile customers depends on rapid DevOps – failing fast, in short, until the right solution evolves in your customers' relationship to your business. Whether you’re decomposing an SOA monolith, or developing a new application cloud natively, it’s not a question of using microservices - not doing so will be a path to eventual ...
"DivvyCloud as a company set out to help customers automate solutions to the most common cloud problems," noted Jeremy Snyder, VP of Business Development at DivvyCloud, in this SYS-CON.tv interview at 20th Cloud Expo, held June 6-8, 2017, at the Javits Center in New York City, NY.
More and more brands have jumped on the IoT bandwagon. We have an excess of wearables – activity trackers, smartwatches, smart glasses and sneakers, and more that track seemingly endless datapoints. However, most consumers have no idea what “IoT” means. Creating more wearables that track data shouldn't be the aim of brands; delivering meaningful, tangible relevance to their users should be. We're in a period in which the IoT pendulum is still swinging. Initially, it swung toward "smart for smart...
DXWorldEXPO LLC announced today that ICC-USA, a computer systems integrator and server manufacturing company focused on developing products and product appliances, will exhibit at the 22nd International CloudEXPO | DXWorldEXPO. DXWordEXPO New York 2018, colocated with CloudEXPO New York 2018 will be held November 11-13, 2018, in New York City. ICC is a computer systems integrator and server manufacturing company focused on developing products and product appliances to meet a wide range of ...
We all know that end users experience the Internet primarily with mobile devices. From an app development perspective, we know that successfully responding to the needs of mobile customers depends on rapid DevOps – failing fast, in short, until the right solution evolves in your customers' relationship to your business. Whether you’re decomposing an SOA monolith, or developing a new application cloud natively, it’s not a question of using microservices – not doing so will be a path to eventual b...
Major trends and emerging technologies – from virtual reality and IoT, to Big Data and algorithms – are helping organizations innovate in the digital era. However, to create real business value, IT must think beyond the ‘what’ of digital transformation to the ‘how’ to harness emerging trends, innovation and disruption. Architecture is the key that underpins and ties all these efforts together. In the digital age, it’s important to invest in architecture, extend the enterprise footprint to the cl...