Welcome!

AJAX & REA Authors: Sebastian Kruk, RealWire News Distribution, Harald Zeitlhofer

Related Topics: Web 2.0, AJAX & REA

Web 2.0: 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 Jonas Jacobi

Jonas has 21 years of experience leading the development of innovative technology products and services. Together with Kaazing’s Co-Founder & CTO John Fallows, he pioneered and championed the groundbreaking HTML5 WebSocket standard. Prior to co-founding Kaazing he served as VP of Product Management for Brane Corporation, a Silicon Valley startup dedicated to developing a market-leading enterprise platform for building model-driven apps. Before Brane, he spent 8+ years at Oracle where he served as a Java EE and open source Evangelist, and was Product Manager in the Oracle Application Server division for JavaServer Faces, Oracle ADF Faces, and Oracle ADF Faces Rich Client. He is a frequent speaker at international conferences on accelerating and scaling secure enterprise-grade WebComms (Web Communications).

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.


Cloud Expo Latest Stories
14th International Cloud Expo, held on June 10–12, 2014 at the Javits Center in New York City, featured three content-packed days with a rich array of sessions about the business and technical value of cloud computing, Internet of Things, Big Data, and DevOps led by exceptional speakers from every sector of the IT ecosystem. The Cloud Expo series is the fastest-growing Enterprise IT event in the past 10 years, devoted to every aspect of delivering massively scalable enterprise IT as a service.
Hardware will never be more valuable than on the day it hits your loading dock. Each day new servers are not deployed to production the business is losing money. While Moore’s Law is typically cited to explain the exponential density growth of chips, a critical consequence of this is rapid depreciation of servers. The hardware for clustered systems (e.g., Hadoop, OpenStack) tends to be significant capital expenses. In his session at 15th Cloud Expo, Mason Katz, CTO and co-founder of StackIQ, to discuss how infrastructure teams should be aware of the capitalization and depreciation model of these expenses to fully understand when and where automation is critical.
Over the last few years the healthcare ecosystem has revolved around innovations in Electronic Health Record (HER) based systems. This evolution has helped us achieve much desired interoperability. Now the focus is shifting to other equally important aspects – scalability and performance. While applying cloud computing environments to the EHR systems, a special consideration needs to be given to the cloud enablement of Veterans Health Information Systems and Technology Architecture (VistA), i.e., the largest single medical system in the United States.
In his session at 15th Cloud Expo, Mark Hinkle, Senior Director, Open Source Solutions at Citrix Systems Inc., will provide overview of the open source software that can be used to deploy and manage a cloud computing environment. He will include information on storage, networking(e.g., OpenDaylight) and compute virtualization (Xen, KVM, LXC) and the orchestration(Apache CloudStack, OpenStack) of the three to build their own cloud services. Speaker Bio: Mark Hinkle is the Senior Director, Open Source Solutions, at Citrix Systems Inc. He joined Citrix as a result of their July 2011 acquisition of Cloud.com where he was their Vice President of Community. He is currently responsible for Citrix open source efforts around the open source cloud computing platform, Apache CloudStack and the Xen Hypervisor. Previously he was the VP of Community at Zenoss Inc., a producer of the open source application, server, and network management software, where he grew the Zenoss Core project to over 10...
Most of today’s hardware manufacturers are building servers with at least one SATA Port, but not every systems engineer utilizes them. This is considered a loss in the game of maximizing potential storage space in a fixed unit. The SATADOM Series was created by Innodisk as a high-performance, small form factor boot drive with low power consumption to be plugged into the unused SATA port on your server board as an alternative to hard drive or USB boot-up. Built for 1U systems, this powerful device is smaller than a one dollar coin, and frees up otherwise dead space on your motherboard. To meet the requirements of tomorrow’s cloud hardware, Innodisk invested internal R&D resources to develop our SATA III series of products. The SATA III SATADOM boasts 500/180MBs R/W Speeds respectively, or double R/W Speed of SATA II products.
As more applications and services move "to the cloud" (public or on-premise) cloud environments are increasingly adopting and building out traditional enterprise features. This in turn is enabling and encouraging cloud adoption from enterprise users. In many ways the definition is blurring as features like continuous operation, geo-distribution or on-demand capacity become the norm. NuoDB is involved in both building enterprise software and using enterprise cloud capabilities. In his session at 15th Cloud Expo, Seth Proctor, CTO at NuoDB, Inc., will discuss the experiences from building, deploying and using enterprise services and suggest some ways to approach moving enterprise applications into a cloud model.
Until recently, many organizations required specialized departments to perform mapping and geospatial analysis, and they used Esri on-premise solutions for that work. In his session at 15th Cloud Expo, Dave Peters, author of the Esri Press book Building a GIS, System Architecture Design Strategies for Managers, will discuss how Esri has successfully included the cloud as a fully integrated SaaS expansion of the ArcGIS mapping platform. Organizations that have incorporated Esri cloud-based applications and content within their business models are reaping huge benefits by directly leveraging cloud-based mapping and analysis capabilities within their existing enterprise investments. The ArcGIS mapping platform includes cloud-based content management and information resources to more widely, efficiently, and affordably deliver real-time actionable information and analysis capabilities to your organization.
Almost everyone sees the potential of Internet of Things but how can businesses truly unlock that potential. The key will be in the ability to discover business insight in the midst of an ocean of Big Data generated from billions of embedded devices via Systems of Discover. Businesses will also need to ensure that they can sustain that insight by leveraging the cloud for global reach, scale and elasticity. In his session at Internet of @ThingsExpo, Mac Devine, Distinguished Engineer at IBM, will discuss bringing these three elements together via Systems of Discover.
Cloud and Big Data present unique dilemmas: embracing the benefits of these new technologies while maintaining the security of your organization’s assets. When an outside party owns, controls and manages your infrastructure and computational resources, how can you be assured that sensitive data remains private and secure? How do you best protect data in mixed use cloud and big data infrastructure sets? Can you still satisfy the full range of reporting, compliance and regulatory requirements? In his session at 15th Cloud Expo, Derek Tumulak, Vice President of Product Management at Vormetric, will discuss how to address data security in cloud and Big Data environments so that your organization isn’t next week’s data breach headline.
The cloud is everywhere and growing, and with it SaaS has become an accepted means for software delivery. SaaS is more than just a technology, it is a thriving business model estimated to be worth around $53 billion dollars by 2015, according to IDC. The question is – how do you build and scale a profitable SaaS business model? In his session at 15th Cloud Expo, Jason Cumberland, Vice President, SaaS Solutions at Dimension Data, will give the audience an understanding of common mistakes businesses make when transitioning to SaaS; how to avoid them; and how to build a profitable and scalable SaaS business.
SYS-CON Events announced today that Gridstore™, the leader in software-defined storage (SDS) purpose-built for Windows Servers and Hyper-V, will exhibit at SYS-CON's 15th International Cloud Expo®, which will take place on November 4–6, 2014, at the Santa Clara Convention Center in Santa Clara, CA. Gridstore™ is the leader in software-defined storage purpose built for virtualization that is designed to accelerate applications in virtualized environments. Using its patented Server-Side Virtual Controller™ Technology (SVCT) to eliminate the I/O blender effect and accelerate applications Gridstore delivers vmOptimized™ Storage that self-optimizes to each application or VM across both virtual and physical environments. Leveraging a grid architecture, Gridstore delivers the first end-to-end storage QoS to ensure the most important App or VM performance is never compromised. The storage grid, that uses Gridstore’s performance optimized nodes or capacity optimized nodes, starts with as few a...
SYS-CON Events announced today that Solgenia, the global market leader in Cloud Collaboration and Cloud Infrastructure software solutions, will exhibit at SYS-CON's 15th International Cloud Expo®, which will take place on November 4–6, 2014, at the Santa Clara Convention Center in Santa Clara, CA. Solgenia is the global market leader in Cloud Collaboration and Cloud Infrastructure software solutions. Designed to “Bridge the Gap” between personal and professional social, mobile and cloud user experiences, our solutions help large and medium-sized organizations dramatically improve productivity, reduce collaboration costs, and increase the overall enterprise value by bringing collaboration and infrastructure solutions to the cloud.
Cloud computing started a technology revolution; now DevOps is driving that revolution forward. By enabling new approaches to service delivery, cloud and DevOps together are delivering even greater speed, agility, and efficiency. No wonder leading innovators are adopting DevOps and cloud together! In his session at DevOps Summit, Andi Mann, Vice President of Strategic Solutions at CA Technologies, will explore the synergies in these two approaches, with practical tips, techniques, research data, war stories, case studies, and recommendations.
Enterprises require the performance, agility and on-demand access of the public cloud, and the management, security and compatibility of the private cloud. The solution? In his session at 15th Cloud Expo, Simone Brunozzi, VP and Chief Technologist(global role) for VMware, will explore how to unlock the power of the hybrid cloud and the steps to get there. He'll discuss the challenges that conventional approaches to both public and private cloud computing, and outline the tough decisions that must be made to accelerate the journey to the hybrid cloud. As part of the transition, an Infrastructure-as-a-Service model will enable enterprise IT to build services beyond their data center while owning what gets moved, when to move it, and for how long. IT can then move forward on what matters most to the organization that it supports – availability, agility and efficiency.
Every healthy ecosystem is diverse. This is especially true in cloud ecosystems, where portability and interoperability are more important than old enterprise models of proprietary ownership. In his session at 15th Cloud Expo, Mark Baker, Server Product Manager at Canonical/Ubuntu, will discuss how single vendors used to take the lead in creating and delivering technology, but in a cloud economy, where users want tools of their preference, when and where they need them, it makes no sense.