JavaBeat

  • Home
  • Java
    • Java 7
    • Java 8
    • Java EE
    • Servlets
  • Spring Framework
    • Spring Tutorials
    • Spring 4 Tutorials
    • Spring Boot
  • JSF Tutorials
  • Most Popular
    • Binary Search Tree Traversal
    • Spring Batch Tutorial
    • AngularJS + Spring MVC
    • Spring Data JPA Tutorial
    • Packaging and Deploying Node.js
  • About Us
    • Join Us (JBC)
  • Privacy

Use of Virtual Extension methods in the Java 8 APIs

May 18, 2012 by Mohamed Sanaulla Leave a Comment

In wrote a bit about Virtual extension methods here and here. I thought of going over this implementation in the JDK, so that it will give us an idea of how these can be applied.

also read:

  • Java 8.0 Tutorials
  • Java 7.0 Tutorials
  • New Features in Java 7.0
  • G1 Garbage Collector in Java 7.0

As I told earlier, the main intention of adding the virtual extension methods was to provide an option to extend the existing interfaces (by adding new methods) without breaking the existing usages. Consequently the main contender for this is the Collection interface in java.util package. All the collection classes in Java implement this interface. Few methods were added to the Collection interface to provide support for the new collections API.

Lets consider the retainAll method as defined below (copied as is from the source distributed with the JDK):

[code lang=”java”]
/**
* Retains all of the elements of this collection which
* match the provided predicate.
*
* @param filter a predicate which returns {@code true}
* for elements to beretained.
* @return {@code true} if any elements were retained.
*/
// XXX potential source incompatibility with retainAll(null)
// now being ambiguous
boolean retainAll(Predicate<? super E> filter) default {
return CollectionHelpers.retainAll(this, filter);
}
[/code]

New CollectionHelpers class is introduced which contains the implementation of various methods used as virtual extension methods. Also notice that the method in the Collection interface doesn’t have any code/implementation details, instead they refer to methods from another class (CollectionHelpers in this case).

The CollectionHelpers.retainApp is defined as (From the source for CollectionHelpers):

[code lang=”java”]
public static <E> boolean retainAll(Collection<E> collection,
Predicate<? super E> filter ) {
boolean retained = false;
Iterator<E> each = collection.iterator();
while(each.hasNext()) {
if(!filter.test(each.next())) {
each.remove();
} else {
retained = true;
}
}
return retained;
}
[/code]

There are numerous such examples in the JDK 8, and one can explore different options from the source for the Java APIs.

Filed Under: Java Tagged With: Java 8, JavaFX, Project Lambda

Developing a Simple Todo Application using JavaFX, Java and MongoDB- Part-3

May 13, 2012 by Mohamed Sanaulla Leave a Comment

In the previous post we created the UI for adding a new Todo where in we used a Tab, TabPane and added the required controls- TextField and a Button to the Tab.

also read:

  • Java FX Tutorials
  • Developing a Simple Todo Application using JavaFX, Java and MongoDB
  • Using JavaFX Chart API to add charts to Swing applications

Going forward, in this post we will create the UI for listing the Open Todos i.e the Todos which have not been marked as Closed. We intend to implement the following features in the UI:

  • Ability to load the Todos when the Tab is selected.
  • Obtain a list view for the Todos with a scroll bar if the list takes more vertical space than required.
  • For each Todo, provide a button to mark the todo as completed.

Before going further, lets have a look at the possible UI we wish to generate at the end:

Loading the Todo on Tab selection:

We add an EventHandler (class TodoLoader) which is added to the Tab#onSelectionChanged event, which loads the Todos from the repository and creates a GridPane with the task name, date when it was added and the button to mark the Todo as completed. This button, which marks the Todo as closed, uses the CloseTodoHandler.

TodoLoader and CloseTodoHandler implement EventHandler and the handle method is overridden to add the required functionality.

Constructing the Handler for loading the Open Todos:

In the TodoLoader#handle(Event event) method we:

Get all the open todos from the database:
[code lang=”java”]
openTodos = TodoDAO.getOpenTodos();
[/code]

For each Todo we have fetched, create a Label for task text and date added and a button for marking the todo as completed. Also for the button we set its actionEvent handler which is an instance of CloseTodoHandler.
[code lang=”java”]
for(Todo aTodo : openTodos)
{
GridPane todoPane = new GridPane();
Label taskLabel = new Label(aTodo.getTask());
Label dateAdded = new Label(aTodo.getAdded().toString());

CloseTodoHandler closeHandler =
new CloseTodoHandler(todoBox,
todoPane,
aTodo);
Button closeButton = ButtonBuilder.create()
.graphic(new ImageView(
new Image(getClass().getResourceAsStream(‘check.png’))))
.onAction(closeHandler)
.build();

todoPane.add(taskLabel,1,1,5,1);
todoPane.add(dateAdded,1,2,4,1);
todoPane.add(closeButton, 5, 2, 1, 1);
todoBox.getChildren().add(todoPane);
}
[/code]

The code for the complete class which loads the Todos and constructs the required UI is:
[code lang=”java”]
class TodoLoader implements EventHandler&lt;Event&gt;{

List&lt;Todo&gt; openTodos;
VBox todoBox;

TodoLoader(VBox todoBox){
this.todoBox = todoBox;
}
@Override
public void handle(Event event) {
//Clear the existing Todos, for adding new Todos
todoBox.getChildren().clear();
try {
openTodos = TodoDAO.getOpenTodos();
for(Todo aTodo : openTodos)
{
//A component that displays the information for each todo
GridPane todoPane = new GridPane();
Label taskLabel = new Label(aTodo.getTask());
Label dateAdded = new Label(aTodo.getAdded().toString());

//Event handler for handling close operations
CloseTodoHandler closeHandler =
new CloseTodoHandler(todoBox,
todoPane,
aTodo);
Button closeButton = ButtonBuilder.create()
.graphic(new ImageView(
new Image(getClass().
getResourceAsStream(‘check.png’))))
.onAction(closeHandler)
.build();

/*
* Add the task label,
* date added, and the
* close button to the
* gridpane component
*/
todoPane.add(taskLabel,1,1,5,1);
todoPane.add(dateAdded,1,2,4,1);
todoPane.add(closeButton, 5, 2, 1, 1);
todoBox.getChildren().add(todoPane);
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
[/code]

Now, lets look at some aspects of the CloseTodoHandler.

Constructing the handler for closing the Todos:

Each button which handles closing of todo should be aware of:

  • which Todo to close i.e have a reference to the Todo instance
  • which GridPane to remove from the VBox, should have a reference to GridPane instance
  • which VBox to remove from i.e reference to the VBox instance.

When we are creating the instance of the CloseTodoHandler, we pass in these information as shown
[code lang=”java”]
CloseTodoHandler closeHandler =
new CloseTodoHandler(todoBox,
todoPane,
aTodo);
[/code]

In the handling of this event: we just have to invoke the corresponding DAO method to close the Todo and also remove it from the VBox as shown below:
[code lang=”java”]
@Override
public void handle(ActionEvent actionEvent) {
try {
TodoDAO.setTodoAsCompleted(todo);
todoBox.getChildren().remove(todoPane);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
[/code]

The complete code for the CloseTodoHandler is:

[code lang=”java”]
class CloseTodoHandler implements EventHandler&lt;ActionEvent&gt;{

VBox todoBox;
GridPane todoPane;
Todo todo;

CloseTodoHandler(VBox todoBox,
GridPane todoPane,
Todo todo){
this.todo = todo;
this.todoBox = todoBox;
this.todoPane = todoPane;
}

@Override
public void handle(ActionEvent actionEvent) {
try {
TodoDAO.setTodoAsCompleted(todo);
todoBox.getChildren().remove(todoPane);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
[/code]

Now we have to build the Tab which uses all the above classes, event handlers to generate the UI as shown in the screen shot above. An instance of VBox is created to add all the Todos on the UI and this instance is passed to the TodoLoader class so that it can use it to populate the UI as shown above in the TodoLoader class definition.
[code lang=”java”]
final VBox todoBox = new VBox();
todoBox.setTranslateX(10);
todoBox.setSpacing(10);

[/code]

As the items can occupy more than the given height of the application, we use ScrollPane to add the Veritcal scroll bars:
[code lang=”java”]
final ScrollPane todoListScroll = ScrollPaneBuilder.create()
.hbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED)
.prefHeight(APP_HEIGHT – 90)
.maxWidth(APP_WIDTH)
.build();
todoListScroll.setContent(todoBox);
[/code]

And finally build the Tab as:
[code lang=”java”]
Tab allTodosTab = TabBuilder.create()
.text(‘All todos’)
.content(todoListScroll)
.closable(false)
.onSelectionChanged(new TodoLoader(todoBox))
.build();
[/code]

We refactor this code into a method and this method is invoked from the TodoAppRunner defined in the previous post.
[code lang=”java”]
private Tab buildShowAllTodoUi(){
final ScrollPane todoListScroll = ScrollPaneBuilder.create()
.hbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED)
.prefHeight(APP_HEIGHT – 90)
.maxWidth(APP_WIDTH)
.build();

final VBox todoBox = new VBox();
todoBox.setTranslateX(10);
todoBox.setSpacing(10);
todoListScroll.setContent(todoBox);

Tab allTodosTab = TabBuilder.create()
.text(‘All todos’)
.content(todoListScroll)
.closable(false)
.onSelectionChanged(new TodoLoader(todoBox))
.build();

return allTodosTab;
}
[/code]

The complete source code can be downloaded from here. I know its been a long series of posts and if you are stuck at any point just let us know via the comments here and we would try to clear out the confusion.

Filed Under: Java FX Tagged With: JavaFX, MongoDB

Developing a Simple Todo Application using JavaFX, Java and MongoDB- Part-2

May 12, 2012 by Mohamed Sanaulla Leave a Comment

In my previous post:

  • I setup the objective of our sample application and named it as TodoFX (I know lot of you would have missed the naming part, lack of creativity in naming drives me create portmanteau of technology and usage of app)
  • Created the back end for our sample application, in the process we played around with MongoDB (not much though).

also read:

  • Java FX Tutorials
  • Developing a Simple Todo Application using JavaFX, Java and MongoDB
  • Using JavaFX Chart API to add charts to Swing applications

Continuing with the application, I would like to:

  • Add a few updates to the model and backend APIs we had created earlier
  • Develop the UI for our application. This would include 2 parts- Developing the UI for Adding new task and Developing the UI to list all uncompleted tasks.

Updates to the model and the backend APIs:

I thought of introduing “id” field, and this would help us in identifying a particular Todo and mark it as completed. The updated Todo class would be:

[code lang=”java”]
public class Todo{
//Among other fields
private String id;
public String getId(){
return id;
}
public void setId (String id){
this.id = id;
}
}
[/code]

Lets also update the TodoDAO, to add a method to get incomplete Todos:

[code lang=”java”]
public class TodoDAO{
//Other methods defined in previous post
public static List getOpenTodos()
throws UnknownHostException{
DB db = DbManager.getDb(DBNAME);
DBCollection collection = db.getCollection(COLLECTION_NAME);
DBObject filterObject = BasicDBObjectBuilder.start()
.add("completed",false)
.get();
DBCursor dbCursor = collection.find(filterObject);
List openTodos = new ArrayList();
while ( dbCursor.hasNext()){
DBObject dbObject = dbCursor.next();
String task = String.valueOf(dbObject.get("task"));
Date added = (Date)dbObject.get("added");
boolean completed = (Boolean)dbObject.get("completed");
Todo todo = new Todo(task,
completed,
added,
dbObject.get("_id").toString());
openTodos.add(todo);
}
return openTodos;
}
}
[/code]
One important take away in the above example is the use of a JSON object in the DBCollection#find(), the JSON object which was passed is the query used for fetching the data. And how do you create the JSON object? Using BasicDBObject or DBObject.
We might have to come back and update the DAO to add a method to set a selected task as completed. ( I am working on the UI to get it working well). Ok, I just went back, tried out the API and here it is how we would update the Todo to set it as completed. We need a JSON object to identify what to update and then a JSON object to set the updated value for the attribute/key we want (and this is the reason why we added the “id” attribute in the Todo Model class). We will add the below method to the TodoDAO class (here I would independently give the method, but its a part of the TodoDAO class)

[code lang=”java”]
public static void setTodoAsCompleted(Todo todoRef)
throws UnknownHostException{
DB db = DbManager.getDb(DBNAME);
DBCollection collection = db.getCollection(COLLECTION_NAME);
DBObject queryObject = BasicDBObjectBuilder.start()
.add("_id", new ObjectId(todoRef.getId()))
.get();
DBObject updateValue = BasicDBObjectBuilder.start()
.add("completed",true)
.get();

collection.update(queryObject,updateValue);
}
[/code]

We make use of DBCollection#update(query,newValue) to update the DB row/JSON object identified by the query.

That’s pretty much I had to add about back end, yeah I know you are more excited to see about JavaFX and the UI, so lets now create a simple UI. I am thinking splitting this UI into one more post and in this post I would explain about the UI for adding new task.

Developing the UI for TodoFX – Add new Task UI:

Once completed, the UI would look like:

For the Add New Todo UI we would use: Tab, TabPane, TextField and Button.

Creating and adding to a Tab:

The components in the Tab for adding a new Todo are:

Field for adding the task name/title:

[code lang=”java”]
TextField tNameField = TextFieldBuilder.create()
.build();
final StringProperty todoTitle = tNameField.textProperty();
[/code]
We use properties to bind the values on the components, with binding the value/text in the component is automatically reflected in the property to which it is bound to. In this case the text of the TextField(tNameField) is bound to the a SringProperty called todoTitle. Read this if you want to get familiar with properties.
Button for saving the todo:

[code lang=”java”]
Button addNewButton = ButtonBuilder.create()
.text("Add")
.onAction(new EventHandler() {
@Override
public void handle(ActionEvent actionEvent) {
Todo todo = new Todo(todoTitle.get());
todoTitle.set("");
try {
TodoDAO.saveTodo(todo);
labelMsg.set("Successfully added the task");
labelVisibility.set(true);
} catch (UnknownHostException ex) {
ex.printStackTrace();
}
}
}
)
.build();
[/code]
Interesting to see here is the use of Builder Pattern for creating the components, this gives a great flexibility in terms of chaining the calls on the same instance. We also added the action for the button, obvious action is to save the Todo. People familiar with Swing applications would be aware of adding action listeners by creating an anonymous inner class. In JavaFX components we create an instance of EventHandler and override EventHandler#handle(ActionEvent) method. With Java 8, these can be replaced by using Lambda expressions/closures.
The components created above should be added to the Tab, and we make use of GridPane to align these components. GridPane is a layout component which allows placing of components into different grids. Aligning the components in GridPane we have,

[code lang=”java”]
GridPane addNewPane = GridPaneBuilder.create()
.hgap(5)
.vgap(5)
.build();

addNewPane.add(msgLabel,1,2,2,1);
addNewPane.add(tNameLabel,1,3);
addNewPane.add(tNameField,2,3);
addNewPane.add(addNewButton,2,5);

Tab addNewTab = TabBuilder.create()
.content(addNewPane)
.text("Add Task")
.closable(false)
.build();
[/code]

Looks like we have completed building the Add New task UI. Let me put together all these creation code:

[code lang=”java”]
import javafx.application.Application;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.ImageViewBuilder;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import net.javabeat.db.Todo;
import net.javabeat.db.TodoDAO;

import java.net.UnknownHostException;
import java.util.List;
import java.util.Set;

public class TodoAppRunner extends Application{

public static final int APP_WIDTH = 200;
public static final int APP_HEIGHT = 300;

public static void main(String[] args)
throws UnknownHostException{
Application.launch(args);
}

@Override
public void start(Stage stage) throws Exception {
BorderPane root = new BorderPane();
Scene scene = new Scene(root, APP_WIDTH,APP_HEIGHT);
Tab addNewTab = buildAddNewTodoUi();
TabPane tabPane = TabPaneBuilder.create()
.tabs(addNewTab)
.build();

root.setCenter(tabPane);
stage.setScene(scene);
stage.setTitle("My Todo’s!");
stage.show();
}

private Tab buildAddNewTodoUi(){
Label msgLabel = LabelBuilder.create()
.text("")
.visible(false)
.build();

TextField tNameField = new TextField();

final StringProperty todoTitle = tNameField.textProperty();
final StringProperty labelMsg = msgLabel.textProperty();
final BooleanProperty lblVisibility = msgLabel.visibleProperty();

Label tNameLabel = new Label("Task");
Button addNewButton = ButtonBuilder.create()
.text("Add")
.onAction(new EventHandler() {
@Override
public void handle(ActionEvent actionEvent) {
Todo todo = new Todo(todoTitle.get());
try {
TodoDAO.saveTodo(todo);
labelMsg.set("Successfully added the task");
lblVisibility.set(true);
todoTitle.set("");
} catch (UnknownHostException ex) {
ex.printStackTrace();
}
}
})
.build();
GridPane addNewPane = GridPaneBuilder.create()
.hgap(5)
.vgap(5)
.build();

addNewPane.add(msgLabel,1,2,2,1);
addNewPane.add(tNameLabel,1,3);
addNewPane.add(tNameField,2,3);
addNewPane.add(addNewButton,2,5);

Tab addNewTab = TabBuilder.create()
.content(addNewPane)
.text("Add Task")
.closable(false)
.build();

return addNewTab;

}
}
[/code]

The source code can be downloaded from here.

In my next post, I will show how to create a UI for listing all the unfinished Todos, and set the Todos as completed from the UI.

Filed Under: Java FX Tagged With: JavaFX, MongoDB

Developing a Simple Todo Application using JavaFX, Java and MongoDB- Part-1

May 9, 2012 by Mohamed Sanaulla Leave a Comment

Over a series of 2 posts or so, I would try and show how to develop a simple Todo Desktop application using JavaFX as the Frontend, and the well known NoSQL database MongoDB as the Backend and using Java as the glue between both of them. The main aim of developing this application is to understand how we can use MongoDB and its Java driver to communicate with Java applications.

also read:

  • Java FX Tutorials
  • Developing a Simple Todo Application using JavaFX, Java and MongoDB
  • Using JavaFX Chart API to add charts to Swing applications

A brief about MongoDB: It is a document oriented NoSQL database, which stores the data in the form of JSON-like document structure. I can go one and write more, but we can explore as we go along.

In this post, I would cover:

  • Installing MongoDB
  • Trying out MongoDB using the command line.
  • Downloading the Java driver for MongoDB
  • Developing the backend for our application.

Installing MongoDB

Download the required MongoDB package from their download site.

Unzip the contents into a directory and lets name it as MONGO_HOME. Update the PATH variable to add the MONGO_HOME/bin. This is useful if you want to run mongo, mongod and other command from any location in your command line.

On your command prompt try $: mongod -version and it should print the version of MongoDB you are using.

Trying out MongoDB using the command line

You have to create a \data\db directory in your C: if you are using Windows or a /data/db directory on Unix, which mongo would use for storing the data.

Start the mongodb database server by running:

[shell]
C:\Users\sanaulla>mongod
mongod –help for help and startup options
Wed May 09 22:28:11 [initandlisten]
MongoDB starting : pid=4992 port=27017 dbpath=/data/db/ 32-bit

[initandlisten] db version v1.8.1, pdfile version 4.5
[initandlisten] waiting for connections on port 27017
[websvr] web admin interface listening on port 28017
[/shell]

Lets connect to this database using the mogndb client.

[shell]
C:\Users\sanaulla>mongo
MongoDB shell version: 1.8.1
connecting to: test
[/shell]

We try out a few simple commands, you can find

[shell]
> use test
switched to db test
> show collections
> book = {"name":"Book1", "publisher":"publisher1"}
{ "name" : "Book1", "publisher" : "publisher1" }
> db.books.save(book)
> db.books.find()
{ "_id" : ObjectId("4faaa578f65827304120d54b"),
"name" : "Book1",
"publisher" : "publisher1"
}
[/shell]

  • use command is used to switch the database whose name is provided after the use. If the db doesn’t exist a new one is created.
  • show collections shows the collections created in the db. A collection can be considered equivalent to a table in RDBMS, but with a flexible schema.
  • book = {} creates a JSON object which represents a JSON like document and is equivalent to a row in the RDBMS table. And the attributes within the JSON object represent the columns of an RDBMS table.
  • db.books.save(book) saves the given JSON object into the collection name which is “books” in this case.
  • db.books.find() is used to get all the JSON Objects/rows in the given collections, something similar to SELECT * FROM table_name in SQL.

Downloading the Java driver for MongoDB

Download the Java driver for MongoDB from their Java Language Center page, its a jar which has to be added to your applications classpath.

There are a few basics explained here to get you started with the Java Driver. Dont worry, I will go through few of those as we develop the application further.

Developing the backend for our application

Ah, finally! Lets start with building the backend for our Todo application, lets call it TodoFX and also test the backend via the command line.

Starting with the model class for our application, A Todo would have the task name, status i.e whether it is completed or not, date of adding, and date when it was finished.

[code lang=”java”]
//Todo.java
import java.util.Date;

public class Todo {
public Todo(String task,
boolean completed,
Date added){
this.task = task;
this.completed = completed;
this.added = added;
}

public Todo(String task){
this.task = task;
this.added = new Date();
this.completed = false;
}

@Override
public String toString(){
return added+": "+this.getTask();
}

private String task;
private boolean completed;
private Date added;
private Date finished;

public String getTask() {
return task;
}

public void setTask(String task) {
this.task = task;
}

public boolean isCompleted() {
return completed;
}

public void setCompleted(boolean completed) {
this.completed = completed;
}

public Date getAdded() {
return added;
}

public Date getFinished() {
return finished;
}

public void setFinished(Date finished) {
this.finished = finished;
}
}
[/code]

To start persisting the data, we need a database connection to the MongoDB. The Java Driver provides Mongo class which can be used to obtain the database connection. If we use the default constructor then it returns the database connection to the local database. In this example we would do that. I will try to see if I can connect to a cloud database and show the same.

[code lang=”java”]
Mongo mongo = new Mongo();
[/code]

and then use Mongo#getDB(dbName) to return the database where we would like to store our collections and objects. The database object is of type DB.

[code lang=”java”]
DB db = mongo.getDB(name);
[/code]

I extracted these into a different class called DbManager

[code lang=”java”]
//DbManager.java
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import java.net.UnknownHostException;

public class DbManager {

private static DB db;
public static DB getDb (String name)
throws UnknownHostException {
Mongo mongo = new Mongo();
if ( db == null){
db = mongo.getDB(name);
}
return db;
}
}
[/code]

Ok, so its time to see how we can SAVE and FIND all the todos added. Before that, our database name is: “todoapp” and the collection name is: “todo”

Saving the Todo instance to the database:

Create a DBObject from the data present in the Todo instance. I prefer to use the BasicDBObjectBuilder to create an instance of DBObject.

[code lang=”java”]
DBObject dbObject = BasicDBObjectBuilder.start()
.add("task",todo.getTask())
.add("completed",todo.isCompleted())
.add("added",todo.getAdded())
.get();
[/code]

the BasicDBObjectBuilder#add(), takes in a key, value pair where the key represents the column name and the value represents the item in the column. The advantage with NoSQL is that there is no requirement of a rigid schema. I could have one row with 3 keys, another row with 4 keys and so on.

After creating the DBObject, it has to be added to the collection and then persisted to the database.

[code lang=”java”]
DB db = DbManager.getDb("todoapp");
DBCollection dbCollection = db.getCollection("todo");
dbCollection.save(dbObject);
[/code]

Pretty straight forward right? And here you are done with persisting your data to the database. How simple can this get? I just removed the fear of PreparedStatments, Connections, SQLExceptions and what not.
Note: In all the cases the DbManager is the class which we have created somewhere near the starting of this example.

Retrieving all the Todos from the database:

– Get the database and fetch the collection from it.
– Iterate through the collection and get each of the values for the available keys(or columns)
– Create instance of Todo from these retrieved values.

Let me show the code:

[code lang=”java”]
DB db = DbManager.getDb(DBNAME);
DBCollection dbCollection = db.getCollection(COLLECTION_NAME);
DBCursor dbCursor = dbCollection.find();
List allTodos = new ArrayList();
while ( dbCursor.hasNext()){
DBObject dbObject = dbCursor.next();
String task = String.valueOf(dbObject.get("task"));
Date added = (Date)dbObject.get("added");
boolean completed = (Boolean)dbObject.get("completed");
Todo todo = new Todo(task,completed, added);
allTodos.add(todo);
}
return allTodos;
[/code]

One new thing is the use of DBCursor, which is an iterator over the database results (think ResultSet).

Let me call this class which provides save() and find() as TodoDAO

[code lang=”java”]
//TodoDAO.java
import com.mongodb.*;
import java.net.UnknownHostException;
import java.util.*;

public class TodoDAO {

private static final String DBNAME = "todoapp";
private static final String COLLECTION_NAME = "todo";
public static void saveTodo(Todo todo)
throws UnknownHostException{
DBObject dbObject = BasicDBObjectBuilder.start()
.add("task",todo.getTask())
.add("completed",todo.isCompleted())
.add("added",todo.getAdded())
.get();
DB db = DbManager.getDb(DBNAME);
DBCollection dbCollection = db.getCollection(COLLECTION_NAME);
dbCollection.save(dbObject);
}

public static List getAllTodos()
throws UnknownHostException{
DB db = DbManager.getDb(DBNAME);
DBCollection dbCollection = db.getCollection(COLLECTION_NAME);
DBCursor dbCursor = dbCollection.find();
List allTodos = new ArrayList();

while ( dbCursor.hasNext()){
DBObject dbObject = dbCursor.next();
String task = String.valueOf(dbObject.get("task"));
Date added = (Date)dbObject.get("added");
boolean completed = (Boolean)dbObject.get("completed");
Todo todo = new Todo(task,completed, added);
allTodos.add(todo);
}

return allTodos;
}
}
[/code]

I think with this we have pretty much the required backend to build further. There are lot of aspects of query, like providing the WHERE clauses, then we can do indexing. I havent explored all those, and I would surely write about it as and when I explore.

Let me try and run this via command line:

[code lang=”java”]
//TodoAppRunner.java
public class TodoAppRunner{
public static void main(String[] args)
throws UnknownHostException{
Todo todo = new Todo("Task 1 from Command Line");
TodoDAO.saveTodo(todo);

todo = new Todo("Task 2 from Command Line");
TodoDAO.saveTodo(todo);

todo = new Todo("Task 3 from Command Line");
TodoDAO.saveTodo(todo);

List allTodos = TodoDAO.getAllTodos();
for ( Todo aTodo : allTodos){
System.out.println(aTodo);
}
}
}
[/code]

Output:

[shell]
Wed May 09 23:42:07 IST 2012: Task 1 from Command Line
Wed May 09 23:42:09 IST 2012: Task 2 from Command Line
Wed May 09 23:42:09 IST 2012: Task 3 from Command Line
[/shell]

I have used IntelliJ Idea IDE for this sample application.

Next: Building the Add New Todo UI using JavaFX.

Filed Under: Java FX Tagged With: JavaFX, MongoDB

Using JavaFX Chart API to add charts to Swing applications

May 6, 2012 by Mohamed Sanaulla Leave a Comment

In our previous post we looked at how we can embed JavaFX components into Swing applications. As Java Swing lacks Charting API, we can make use of the JavaFX Chart API and not depend on other 3rd party libraries like JFreeChart and others. The javafx.scene.chart is the package which contains all the charting related classes. In this example we will look at creating Scatter Charts and Bar Charts which are categorized as XYCharts which is nothing but these charts are plotted on a X and Y axis. The classes for the charts to be used are javafx.scene.chart.ScatterChart and javafx.scene.chart.BarChart. If you happen to look at the declaration of these classes, they accept generic types where X indicates the type on the X Axis and Y indicates the type on the Y axis. These charts require a set of axis to be defined before they are used. If the axis is of type Number, then one can use NumberAxis and for String values one can make use of CategoryAxis. For each of the Number axis or category axis we can define the range of of values to be plotted on the axis. Let me show some code on how it can be achieved:

[code lang=”java”]
NumberAxis yAxis =
new NumberAxis(0.0,5.0,1.0);
NumberAxis xAxis =
new NumberAxis(0.0,5.0,1.0);
//Scatter chart with 2 axis defined. Both are number axis
ScatterChart scatterChart =
new ScatterChart<>(xAxis,yAxis);
[/code]

also read:

  • Java FX Tutorials
  • Developing a Simple Todo Application using JavaFX, Java and MongoDB
  • Using JavaFX Chart API to add charts to Swing applications

For a Chart with a Category and Number axis, we can have something like:

[code lang=”java”]
NumberAxis lineYAxis =
new NumberAxis(0,100_000,10_000);
CategoryAxis lineXAxis =
new CategoryAxis();
//One can set the label for axis as well.
lineYAxis.setLabel("Sales");
lineXAxis.setLabel("Products");

// A bar chart with X and Y axis representing
// string and numbers.
BarChart barChart =
new BarChart<>(lineXAxis,lineYAxis);
[/code]

Moving ahead, our next task is to add some data to these charts. As you already have seen, the scatter chart accepts data while the bar chart accepts data. The charts being demonstrated in our example here are XY charts which means that they are plotted against X Axis and Y Axis, so  we use XYChart at all places. Lets populate some data to our scatter chart

[code lang=”java”]
XYChart.Series series = new XYChart.Series<>();
series.setName("Value 1");
series.getData().add(getData(1.2,3.4));
series.getData().add(getData(3.4,4.5));
series.getData().add(getData(1.5,1.2));
series.getData().add(getData(4.5, 1.6));
[/code]

where our function getData is defined as

[code lang=”java”]
private XYChart.Data getData(double x, double y){
XYChart.Data data = new XYChart.Data<>();
data.setXValue(x);
data.setYValue(y);
return data;
}
[/code]

To populate the data for bar chart we write something like:

[code lang=”java”]
// First Series
XYChart.Series bar1 = new XYChart.Series<>();
bar1.setName("Computing Devices");
bar1.getData().add(getData(40000,"Desktop"));
bar1.getData().add(getData(30_000,"Netbooks"));
bar1.getData().add(getData(70_000,"Tablets"));
bar1.getData().add(getData(90_000,"Smartphones"));

//Second series
XYChart.Series bar2 = new XYChart.Series<>();
bar2.setName("Consumer Goods");
bar2.getData().add(getData(60_000,"Washing Machines"));
bar2.getData().add(getData(70_000,"Telivision"));
bar2.getData().add(getData(50_000,"Microwave Ovens"));

// Add both the series to the bar chart
// Notice the use of addAll() method here
// and only add() for scatter chart
barChart.getData().addAll(bar1,bar2);
[/code]

Once the program is working, the above 2 graphs would be represented as:

Now that we have touched upon the basics of adding chart, the other things which are to be taken care are the layout of the JavaFX components and then adding the JFXPanel into a JFrame. If you dont know what a JFXPanel is please read this post for some information on the same.

The complete code for this sample is:

[code lang=”java”]
import javafx.application.Platform;
import javafx.beans.property.SimpleListProperty;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.chart.*;
import javafx.scene.layout.GridPane;

import javax.swing.*;
import java.awt.*;

public class JavaChartDemo {

public static void main ( String[] args){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
ChartFrame mainFrame = new ChartFrame();
mainFrame.setVisible(true);
}
});
}
}

class ChartFrame extends JFrame {

JFXPanel fxPanel;
public ChartFrame(){
initSwingComponents();

initFxComponents();
}

private void initSwingComponents(){
JPanel mainPanel = new JPanel(new BorderLayout());
fxPanel = new JFXPanel();
mainPanel.add(fxPanel, BorderLayout.CENTER);

JLabel titleLabel = new JLabel("Charts in Swing applications");
mainPanel.add(titleLabel, BorderLayout.NORTH);

this.add(mainPanel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(800,400);
}

private void initFxComponents(){

Platform.runLater(new Runnable() {
@Override
public void run() {
GridPane grid = new GridPane();
Scene scene = new Scene(grid, 800, 400);

/**
* Construct and populate Scatter chart
*/
NumberAxis yAxis = new NumberAxis(0.0,5.0,1.0);
NumberAxis xAxis = new NumberAxis(0.0,5.0,1.0);
ScatterChart scatterChart =
new ScatterChart<>(xAxis,yAxis);
XYChart.Series series =
new XYChart.Series<>();
series.setName("Value 1");
series.getData().add(getData(1.2,3.4));
series.getData().add(getData(3.4,4.5));
series.getData().add(getData(1.5,1.2));
series.getData().add(getData(4.5, 1.6));
scatterChart.getData().addAll(series);
grid.add(scatterChart,0,0);

/**
* Construct and populate Bar chart.
* It uses 2 series of data.
*/
NumberAxis lineYAxis =
new NumberAxis(0,100_000,10_000);
lineYAxis.setLabel("Sales");
CategoryAxis lineXAxis = new CategoryAxis();
lineXAxis.setLabel("Products");
BarChart barChart =
new BarChart<>(lineXAxis,lineYAxis);
XYChart.Series bar1 =
new XYChart.Series<>();
bar1.setName("Computing Devices");
bar1.getData().add(getData(40000,"Desktop"));
bar1.getData().add(getData(30_000,"Netbooks"));
bar1.getData().add(getData(70_000,"Tablets"));
bar1.getData().add(getData(90_000,"Smartphones"));

XYChart.Series bar2 = new XYChart.Series<>();
bar2.setName("Consumer Goods");
bar2.getData().add(getData(60_000,"Washing Machines"));
bar2.getData().add(getData(70_000,"Telivision"));
bar2.getData().add(getData(50_000,"Microwave Ovens"));

barChart.getData().addAll(bar1,bar2);
grid.setVgap(20);
grid.setHgap(20);
grid.add(barChart,2,0);
fxPanel.setScene(scene);
}
});

}

private XYChart.Data getData(double x, double y){
XYChart.Data data = new XYChart.Data<>();
data.setXValue(x);
data.setYValue(y);
return data;
}

private XYChart.Data getData(double x, String y){
XYChart.Data data = new XYChart.Data<>();
data.setYValue(x);
data.setXValue(y);
return data;
}
}

[/code]

We will try to update and posts JavaFX chart specific examples. Please do subscribe to the posts to keep a track of the new updates.

Filed Under: Java FX Tagged With: JavaFX

Embedding HTML into Java Swing Applications

May 6, 2012 by Mohamed Sanaulla Leave a Comment

HTML in Swing applications? Yes, you have read it right. Swing doesn’t provide components to embed HTML and I have seen lot of people asking how can we add html content in Swing applications. Your concerns have been addressed by the latest release of JavaFX which is JavaFX 2.0. You might wonder what this JavaFX is, so let me just touch upon that as well.

also read:

  • Java Tutorials
  • Java EE Tutorials
  • Design Patterns Tutorials
  • Java File IO Tutorials

JavaFX is the RIA platform envisaged by Sun Microsystems as the next UI toolkit for Java, as Swing has been around for a long time and has started to age. The initiative was good, but was not rightly implemented. The JavaFX 1, 1.2, 1.3 or in general anything before 2.0 is no longer supported. Pre JavaFX 2.0 one had to use JavaFX Script to create the applications and these could invoke the Java API. But learning a new language altogether was not appealing for a Java developer as one couldn’t easily use with existing Java code base. In 2.0 the JavaFX Script was totally removed to make way for the Java based api for creating JavaFX components. Once you have setup the JavaFX SDK, you get to use the JavaFX specific API in the javafx.* packages. There are lot of cool things underneath the JavaFX platform, but that’s out of the scope of this article.

Coming back to our main focus, JavaFX provides a component called WebView which with the help of WebEngine can be used to load web pages along with constructing the DOM and running the required JavaScript. But that’s a JavaFX component. How is it going to help us in our Swing application? Exactly, JavaFX provides another component called JFXPanel which can be used to embed JavaFX components into Swing applications and in turn the JFXPanel is added to our JFrame or other Swing containers.

[code lang=”java”]
JFrame myFrame = new JFrame();
JFXPanel myFXPanel = new JFXPanel():
myFrame.add(myFXPanel);
[/code]

Now the required JavaFX components would be added to the JFXPanel. The JavaFX components are to be created only in the JavaFX Application thread and not in the main thread or the thread created using SwingUtilities.invokeLater. Before that lets just get familiar with a few JavaFX components which we would be using in this example:

  • javafx.scene.Scene: All components in the JavaFX application are represented as a scene graph – a collection of parent and child components. The Scene component is the container for the scene graph or the components, and we define the root for all these containers when we instantiate the Scene component.
  • javafx.scene.layout.BorderPane: Its the JavaFX’s version of all familiar Swing BorderLayout.

So lets try to add a WebView component to the JFXPanel.

[code lang=”java”]
Platform.runLater(new Runnable() {
@Override
public void run() {

BorderPane borderPane = new BorderPane();
WebView webComponent = new WebView();

webComponent.getEngine().load("http://google.com/");

borderPane.setCenter(webComponent);
Scene scene = new Scene(borderPane,450,450);
myFXPanel.setScene(scene);

}
});
[/code]
The Platform.runLater creates a JavaFX application thread, and this thread has to be used for all the JavaFX based operations (we can create multiple such threads, but yes, for any of the JavaFX related operation is carried out as part of this thread).

In the above snippet, we create an instance of BorderPane, set it as the root of scene when we create a Scene object and then add the WebView to the BorderPane. We also ask the WebEngine of the WebView to load the URL: www.google.com. The scene object is then added to the JFXPanel. Remember, that JFXPanel is alread added to the JFrame or some Swing components. So you have a Swing application loading your web pages.

Below is the complete code for loading web pages in Swing applications.

[code lang=”java”]
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebView;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class SwingHtmlDemo {
public static void main(String [] args){

SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
ApplicationFrame mainFrame = new ApplicationFrame();
mainFrame.setVisible(true);
}
});

}

}

/**
* Main window used to display some HTML content.
*/
class ApplicationFrame extends JFrame{

JFXPanel javafxPanel;
WebView webComponent;
JPanel mainPanel;

JTextField urlField;
JButton goButton;

public ApplicationFrame(){

javafxPanel = new JFXPanel();

initSwingComponents();

loadJavaFXScene();
}

/**
* Instantiate the Swing compoents to be used
*/
private void initSwingComponents(){
mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
mainPanel.add(javafxPanel, BorderLayout.CENTER);

JPanel urlPanel = new JPanel(new FlowLayout());
urlField = new JTextField();
urlField.setColumns(50);
urlPanel.add(urlField);
goButton = new JButton("Go");

/**
* Handling the loading of new URL, when the user
* enters the URL and clicks on Go button.
*/
goButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Platform.runLater(new Runnable() {
@Override
public void run() {
String url = urlField.getText();
if ( url != null && url.length() > 0){
webComponent.getEngine().load(url);
}
}
});

}
});

urlPanel.add(goButton);
mainPanel.add(urlPanel, BorderLayout.NORTH);

this.add(mainPanel);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(700,600);
}

/**
* Instantiate the JavaFX Components in
* the JavaFX Application Thread.
*/
private void loadJavaFXScene(){
Platform.runLater(new Runnable() {
@Override
public void run() {

BorderPane borderPane = new BorderPane();
webComponent = new WebView();

webComponent.getEngine().load("http://google.com/");

borderPane.setCenter(webComponent);
Scene scene = new Scene(borderPane,450,450);
javafxPanel.setScene(scene);

}
});
}
}
[/code]

I used JavaFX SDK for Linux on Ubuntu and IntelliJ to develop this sample application. One can download the JavaFX SDK from here.

Filed Under: Java Tagged With: Java, JavaFX, webview

Follow Us

  • Facebook
  • Pinterest

As a participant in the Amazon Services LLC Associates Program, this site may earn from qualifying purchases. We may also earn commissions on purchases from other retail websites.

JavaBeat

FEATURED TUTORIALS

Answered: Using Java to Convert Int to String

What is new in Java 6.0 Collections API?

The Java 6.0 Compiler API

Copyright © by JavaBeat · All rights reserved