October 1, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Combining JavaFX and Java Enterprise Modules

  • February 4, 2013
  • By Manoj Debnath
  • Send Email »
  • More Articles »

JavaFX is built on top of the Java platform; this creates a bonding where it can leverage all of the features of JavaSE. JavaEE is also built in top of JavaSE in much the same way. As a result applications built in both of the platforms can live in the same environment and share features, to each other's advantage. Developers can use this combined strength of application development to leverage productivity in a wide range of devices from desktops, portable devices to servers. The focus of javaFX as a tool is on the client rich interactive visualization of content; it can be a suitable candidate to interface your next enterprise application when merged with JavaEE modules. The fluidity of integration can be a decisive factor though; in coming years its ease of use with wider acceptance is presumable.

JavaEE modules and JavaFX

Java EE modules are defined by many constituent specifications standardized by Java Community Process (JCP). There are several third party organizations who implement one or more JSRs and package them in a product.  Some of these popular product families are - Spring, Guice, Tomcat, Jboss, RestEasy, Glassfish, Hibernate, etc. JavaFX can be seamlessly integrated with Hibernate: Integrate JavaFX, Hibernate and PostgreSQL with the MVC Pattern. Technically there is no restriction to combine JavaFX with the Java EE modules but fluidity of the approach to combine them may be hindered by a not so fluid merging technique. The API support for integrating JavaFX with enterprise modules is emerging. Nonetheless, the JavaSE, JavaEE and JavaFX trio establishes a wider horizon to explore and creativity to churn. JavaFX is best known for its UI support and may replace swing in near future. Developing a client user interface is the best fit for JavaFX to play around in the enterprise arena. This, however, demands a variety of robust controls and their seamless integration of data support.

JavaFX Client in JavaEE Modules

Client development is significantly different from the enterprise in its objectivity and methodology, such as:

  • Enterprise applications are now moving towards cloud, thus seamless interaction with the cloud component is essential.
  • Enterprise applications often implement different patterns such as aspects, inversion of control etc. How much JavaFX can leverage these patterns can be a decisive factor.
  • Deployment and life-cycle management of the enterprise application is more server oriented. Upgrading server-product is a tedious task and minimization of its downtime is a very crucial process.
  • Enterprise development is more about resource utilization than visual enhancement.
  • Enterprise development is primarily focused towards the performance on the server and the server is awake all the time, 24/7. Thus start up time for desktop applications may be critical but in enterprise applications it is hardly an issue.

Interestingly, whenever JavaFX lacks a certain aspect it surely can point its finger to its big brother JavaSE. This is technically true because JavaFX lacks only when it is thought of as a separate entity from JavaSE, which it actually is not, per se.

JavaFX and Web Services

Accessing components through web resources is a common phenomenon for enterprise applications. JavaFX can call remote web resources through SOAP as well as RESTful web services. As SOAP is significantly supported in Java and JavaFX, it poses no problem using the package javax.xml.soap. RESTful web services can be accessed using standard HTTP technologies. Java API has extensive support facilitating access to REST based web services through mainly – java.io and java.net packages. JAX-WS provides support for multiple protocols along with HTTP. JavaFX can leverage JAX-WS annotation support in creating web service clients that use the web services over a network.

Example

The code snippets below give a minimal sales report using JavaFX, EclipseLink 2.x JPA in the persistence layer and JAX-WS 2.0 specification, the next generation web services API replacing JAX-RPC 1.0. The code can be modified to use any other JPA framework adhering to JSR 317.

Persistence Unit

 

@Entity

@Table(name = "PRODUCT")

@XmlRootElement

@NamedQueries({

    @NamedQuery(name = "Product.findAll", query = "SELECT p FROM Product p"),

})

public class Product implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id

    private Integer productID;

    private String batchNumber;

    private String productName;

    private String productDescription;

    private float unitPrice;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "productID")

    private Collection<Sales> salesCollection;

 

   //... Getter Setter methods

    

}

 

@Entity

@Table(name = "REGION")

@XmlRootElement

@NamedQueries({

    @NamedQuery(name = "Region.findAll", query = "SELECT r FROM Region r"),

})

public class Region implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id

    private Integer regionID;

    private String regionName;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "regionID")

    private Collection<Sales> salesCollection;

 

//...Getter Setter methods

 

}

 

@Entity

@Table(name = "SALES")

@XmlRootElement

@NamedQueries({

    @NamedQuery(name = "Sales.findAll", query = "SELECT s FROM Sales s"),

})

public class Sales implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id

    private Long invoiceNumber;

    private int salesQuantity;

    @JoinColumn(name = "regionID", referencedColumnName = "regionID")

    @ManyToOne(optional = false)

    private Region regionID;

    @JoinColumn(name = "productID", referencedColumnName = "productID")

    @ManyToOne(optional = false)

    private Product productID;

 

//...Getter and Setter methods

 

}

Web Service

@WebService(serviceName = "ProductSalesService")

public class ProductSalesService {

    @PersistenceUnit

    EntityManagerFactory emf;

      

   

    @WebMethod(operationName = "getProducts")

    public List getProducts() {

        return emf.createEntityManager().createNamedQuery("Product.findAll").getResultList();                

    }

    @WebMethod(operationName = "getRegions")

    public List getRegions() {

        return emf.createEntityManager().createNamedQuery("Region.findAll").getResultList();                        

    }

    @WebMethod(operationName = "getAllSales")

    public List getAllSales() {

        return emf.createEntityManager().createNamedQuery("Sales.findAll").getResultList();        

    }  

}

JavaFX Client

public class ProductSalesClient extends Application {

    private GridPane grid = new GridPane();

    private List<Object> sales = new ArrayList<>();

    ObservableList<ProdSalesQty> list = FXCollections.observableArrayList();

    private BorderPane borderPane = new BorderPane();

    private final int columWidth = 200;

    

    @Override

    public void start(Stage primaryStage) {        

        sales = getAllSales();

        borderPane.setTop(grid);

        Scene scene = new Scene(borderPane, 300, 250);

        tabularData();

        grid.addRow(0, barChart("Product", "Product Quantity Sales", "Product Name", "Sales Quantity", list), pieChart("Zonewise Sales", list), barChart("Product", "Product Quantity Sales", "Product Name", "Sales Quantity", list));

        primaryStage.setTitle("Product Sales");

        primaryStage.setScene(scene);

        primaryStage.show();

    }

    private void tabularData() {

        TableView<ProdSalesQty> table = new TableView<>();

        TableColumn<ProdSalesQty, String> prodCol = new TableColumn<>("Product");

        prodCol.setCellValueFactory(new Callback<TableColumn.CellDataFeatures<ProdSalesQty, String>, ObservableValue<String>>() {

            @Override

            public ObservableValue<String> call(CellDataFeatures<ProdSalesQty, String> p) {

                ProdSalesQty pq = p.getValue();

                return new SimpleStringProperty(pq.getProdName());

            }

        });

        prodCol.setPrefWidth(columWidth);

        TableColumn<ProdSalesQty, String> qtyCol = new TableColumn<>("Quantity");

        qtyCol.setCellValueFactory(new Callback<CellDataFeatures<ProdSalesQty, String>, ObservableValue<String>>() {

            @Override

            public ObservableValue<String> call(CellDataFeatures<ProdSalesQty, String> p) {

                ProdSalesQty pq = p.getValue();

                return new SimpleStringProperty(String.valueOf(pq.getSaleQty()));

            }

        });

        qtyCol.setPrefWidth(columWidth);

        TableColumn<ProdSalesQty, String> regCol = new TableColumn<>("Region");

        regCol.setCellValueFactory(new Callback<CellDataFeatures<ProdSalesQty, String>, ObservableValue<String>>() {

            @Override

            public ObservableValue<String> call(CellDataFeatures<ProdSalesQty, String> p) {

                ProdSalesQty pq = p.getValue();

                return new SimpleStringProperty(pq.getRegName());

            }

        });

        regCol.setPrefWidth(columWidth);

        TableColumn<ProdSalesQty, String> costCol = new TableColumn<>("Cost");

        costCol.setCellValueFactory(new Callback<CellDataFeatures<ProdSalesQty, String>, ObservableValue<String>>() {

            @Override

            public ObservableValue<String> call(CellDataFeatures<ProdSalesQty, String> p) {

                ProdSalesQty pq = p.getValue();

                return new SimpleStringProperty(String.valueOf(pq.getCost()));

            }

        });

        costCol.setPrefWidth(columWidth);

        table.getColumns().addAll(prodCol, qtyCol, regCol, costCol);

 

        for (Object salesObject : sales) {

            Sales s = (Sales) salesObject;

            ProdSalesQty psq = new ProdSalesQty();

            psq.setProdName(s.getProductID().getProductName());

            psq.setSaleQty(s.getSalesQuantity());

            psq.setRegName(s.getRegionID().getRegionName());

            psq.setCost((s.getSalesQuantity() * s.getProductID().getUnitPrice()));

            System.out.println(psq.toString());

            list.add(psq);

        }

        table.setItems(list);

        borderPane.setCenter(table);

    }

 

    public BarChart barChart(String seriesName, String title, String xLabel, String yLabel, ObservableList<ProdSalesQty> list) {

        CategoryAxis xAxis = new CategoryAxis();

        NumberAxis yAxis = new NumberAxis();

        BarChart bc = new BarChart(xAxis, yAxis);

        bc.getData().clear();

        bc.setAnimated(true);

        bc.setTitle(title);

        xAxis.setLabel(xLabel);

        yAxis.setLabel(yLabel);

        XYChart.Series series1 = new XYChart.Series();

        series1.setName(seriesName);

 

        ObservableList products = FXCollections.observableList(getProducts());

        for (Object productObject : products) {

            Product p = (Product) productObject;

            int sum = 0;

            boolean found = false;

            for (ProdSalesQty psq : list) {

                if (p.getProductName().equals(psq.getProdName())) {

                    sum = sum + psq.getSaleQty();

                    found = true;

                }

            }

            if (found) {

                series1.getData().add(new XYChart.Data(p.getProductName(), sum));

            }

        }

        bc.setAnimated(true);

        bc.getData().add(series1);

        return bc;

    }

 

    public PieChart pieChart(String title, ObservableList<ProdSalesQty> list) {

        PieChart pie = new PieChart();

        pie.getData().clear();

        ObservableList pieChartData = FXCollections.observableArrayList();

        ObservableList regions = FXCollections.observableList(getRegions());

        for (Object regionObject : regions) {

            Region r = (Region) regionObject;

            int sum = 0;

            boolean found = false;

            for (ProdSalesQty p : list) {

                if (r.getRegionName().equals(p.getRegName())) {

                    sum = sum + p.getSaleQty();

                    found = true;

                }

            }

            if (found) {

                pieChartData.add(new PieChart.Data(r.getRegionName(), sum));

            }

        }        

        pie.setData(pieChartData);

        pie.setAnimated(true);

        pie.setTitle(title);

        return pie;

    }

 

    public static void main(String[] args) {

        launch(args);

    }

 

    public class ProdSalesQty {

                private String prodName;

                private int saleQty;

                private String regName;

                private float cost;

                //...Getter and Setter methods

    }

 

private static java.util.List<java.lang.Object> getAllSales() {

        productsalesclient.ProductSalesService_Service service = new productsalesclient.ProductSalesService_Service();

        productsalesclient.ProductSalesService port = service.getProductSalesServicePort();

        return port.getAllSales();

    }

 

    private static java.util.List<java.lang.Object> getRegions() {

        productsalesclient.ProductSalesService_Service service = new productsalesclient.ProductSalesService_Service();

        productsalesclient.ProductSalesService port = service.getProductSalesServicePort();

        return port.getRegions();

    }

 

    private static java.util.List<java.lang.Object> getProducts() {

        productsalesclient.ProductSalesService_Service service = new productsalesclient.ProductSalesService_Service();

        productsalesclient.ProductSalesService port = service.getProductSalesServicePort();

        return port.getProducts();

    }

}

Minimal Sales Report

JavaFX client accessing JPA model from the Server through Web-services (JAX-WS) to generate the report.

JavaFX client
JavaFX client

JavaFX and Spring

Spring framework has revolutionized enterprise application development by introducing the POJO model. Spring framework does not impose any particular programming model, rather it provides an environment where programmers may use the features of the framework according to the requirement. This is quite different from the old caged EJB model of programming. The boilerplate code and constraints of programming are never felt in Spring, though a lot has been simplified recently in the EJB world. Spring gradually became quite popular with the Java community as an alternative to EJB.  Spring has extensive support for Inversion of Control, MVC, database access, security authorization control and many more under the same hood. In a sense, Spring provided features for a one stop solution for the enterprise development needs. Perhaps, for this reason Spring is one of the most sought after technologies in the enterprise arena. So when we speak of enterprise development with JavaFX, how far can Spring be left behind? Stephen Chin gave an excellent introduction in matchmaking the two technologies in the articles: Application Initialization, Configuration and FXML and  Authentication and Authorization. With the release of the 2.x version, JavaFX has now become closeer to the stable Java APIs; as a result integrating external libraries such as Spring is just a matter of choice.

Conclusion

Practically, there are various ways to integrate JavaEE modules, moreover JavaFX can leverage JavaSE APIs, so there are a number of possibilities and options available in JavaEE modules to work with. The current list of Java EE 6 JSR is voluminous. Merging each of them in JavaFX is possible with a little or more effort. James L. Weaver demonstrated a way to integrate the external web services of Tweeter API in the article: Best Practices for JavaFX 2.0 Enterprise Applications. However, JavaFX does not have a very fluid integration technique as an enterprise java bean client. The UI controls in the JavaFX framework still need more options to play in the enterprise arena. Nonetheless, efforts are on among the Java community. Till then merging JavaFX with Java EE modules will only be an experiment among the technological enthusiasts.


Tags: JavaFX, Enterprise




Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel