JavaFX List Example
This is an example list application built using JavaFX. The app is a list of todo (to do) items. This app has functions to add, update and delete items in the list. The list data is stored in HSQLDB relational database. The app accesses the database using JDBC (Java Database Connectivity) API. The app is packaged as an executable JAR file.
JavaFX 2.2, Java SE 7 and HSQLDB 2.3.2 are used to build the app.
This article explains building the app in detail. This document’s contents:
Table Of Contents
1. Install HSQL Database
1.1. About HSQLDB
The HSQL relational database is used for storing the todo data. In this section – get and install the database.
HSQLDB (HyperSQL DataBase) is the SQL relational database software written in Java and runs in a JVM. It is a small, fast multithreaded and transactional database engine with in-memory and disk-based tables and supports embedded and server modes. This includes a JDBC driver.
1.2. Download Database
Download the database software from the download link on the website http://hsqldb.org/. In this case, the HSQLDB version 2.3.2 is downloaded. The downloaded file is a ZIP file. Extract the ZIP file into any directory of your choice. The ZIP file is extracted into a folder hsqldb-2.3.2\hsqldb
. This is the home (or install) directory.
This completes the installation. The installed database has user documentation, JDBC driver, database executables and utility programs. The install directory has /doc
and /lib
directories (in addition to others).
The /doc
directory has the user guides.
The /lib
directory has the following JAR files used commonly:
hsqldb.jar
: This has the database engine, JDBC driver and a GUI database access tool.sqltool.jar
: This has a SQL command line database access tool.
2. Create App Database and Table
2.1. Create Todos Database
The GUI database access tool is used to create and access the database. From the DOS command prompt run this:
> java -cp "X:\JCG\articles\A JavaFX List Example\hsqldb-2.3.2\hsqldb\lib\hsqldb.jar" org.hsqldb.util.DatabaseManagerSwing
NOTE: The hsqldb.jar
file is to be in the classpath.
This opens a Connect GUI dialog as shown below.
Enter the following information into the dialog:
- Recent Setting: <Do not select anything now. Next time to connect to the database select the setting created now.>
- Setting Name: <enter a name> todo db setting
- Type: <select> HSQL Database Engine Standalone
- Driver: <select> hsqldb.jdbcDriver
- URL: <enter database file path> jdbc:hsqldb:file:<<filepath – see note below for more details to specify the path>>
- User: <leave blank>
- Password: <leave blank>
Note on URL’s filepath: The filepath can be specified as a relative or an absolute path. The relative path is relative to the current directory; for example jdbc:hsqldb:file:db\TODOS_DB
in the URL creates a directory called db
and the TODOS_DB database in it. An example with absolute path is jdbc:hsqldb:file:X:\JCG\articles\A JavaFX List Example\db\TODOS_DB
.
Click Ok.
This creates a database named TODOS_DB in the specified directory. This also opens the HSQLDatabase Manager window. The window has areas showing the database structure, SQL entry and result details. The window is shown below.
2.2 Create Todo Table
The todo table has three columns: id, name and description.
- id: This is a unique integer generated by the database system. This is defined as an IDENTITY column.
An IDENTITY column is an INTEGER auto-generated by the database’s sequence generator. By default the column values start from 1 and are incremented by 1. When an insert is made into the table, the id column value is automatically populated with a new sequence number. The syntax for inserting and retrieving the id column value are shown later in this article (see section 5. Create Database Access Code).
- name: This is defined as VARCHAR (50), and not null.
- description: This is defined as VARCHAR(500).
In the HSQLDatabase Manager window enter the following SQL script and execute it.
CREATE TABLE TODO_TABLE ( id INTEGER GENERATED BY DEFAULT AS IDENTITY, name VARCHAR(50) NOT NULL, description VARCHAR(500) );
This creates the todo table. The newly created table can be viewed in the database structure area.
NOTE: This step need to be completed before going further. The app’s code assumes that the database and the table are created.
3. The Application
The todos are displayed in a list, where each todo is a list item. When a todo is selected in the list the name and description are displayed in a text box and text area respectively. This data can be edited. There are buttons to create a todo, delete and save. A status message shows the recent action performed.
The GUI is displayed in a window. The data displayed in the list and text box/area is accessed from the todo database. The database is opened on app start and closed on closing the app.
The following shows the completed app’s GUI.
3.1. Application Classes
The app comprises three Java classes.
- Todo.java: This class represents the todo item.
- TodoApp.java: This class is the main application with GUI and program execution logic.
- TodoDataAccess.java: This class has functions to access the todo database.
3.1.1 Todo.java
A todo is represented by the Todo.java
class. A todo has name and description properties. This also maintains a unique id field.
3.1.2 TodoDataAccess.java
This class has functions to access the todo database and the data. Its functions are:
- Connect to and close the database
- Insert, update, delete, query and validate data in the database
3.1.3 TodoApp.java
This class is the main application program. This has functions to start the app, close it, create the user interface and wire the GUI and the app to the data access code.
4. Build the GUI
In this step the GUI is constructed without the database access and action event handlers for the buttons. Only, the list is wired to a list selection change listener.
The app displays some predefined todo data in the list. The list todo items can be selected and the corresponding todo name and description are displayed in their respective text box/area.
The following shows the TodoApp.java class’s code followed by its description.
4.1.The Code
TodoApp.java:
import javafx.application.Application; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.scene.layout.AnchorPane; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.scene.text.Text; import javafx.scene.paint.Color; import javafx.scene.control.ListView; import javafx.scene.control.Label; import javafx.scene.control.TextField; import javafx.scene.control.TextArea; import javafx.scene.control.ScrollPane; import javafx.scene.control.ScrollPane.ScrollBarPolicy; import javafx.scene.control.Button; import javafx.scene.control.Tooltip; import javafx.scene.text.Text; import javafx.geometry.Pos; import javafx.geometry.Insets; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import java.util.List; import java.util.ArrayList; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; public class TodoApp extends Application { private ListView<Todo> listView; private ObservableList<Todo> data; private TextField nametxt; private TextArea desctxt; private Text actionstatus; public static void main(String [] args) { Application.launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Todo App - version 1"); // gridPane layout GridPane grid = new GridPane(); grid.setAlignment(Pos.CENTER); grid.setHgap(15); grid.setVgap(20); grid.setPadding(new Insets(25, 25, 25, 25)); // list view, listener and list data listView = new ListView<>(); listView.getSelectionModel().selectedIndexProperty().addListener( new ListSelectChangeListener()); data = getListData(); listView.setItems(data); grid.add(listView, 1, 1); // col = 1, row = 1 // todo name label and text fld - in a hbox Label namelbl = new Label("Todo Name:"); nametxt = new TextField(); nametxt.setMinHeight(30.0); nametxt.setPromptText("Enter todo name (required)."); nametxt.setPrefColumnCount(20); nametxt.setTooltip(new Tooltip( "Item name (5 to 50 chars length)")); HBox hbox = new HBox(); hbox.setSpacing(10); hbox.getChildren().addAll(namelbl, nametxt); // todo desc text area in a scrollpane desctxt = new TextArea(); desctxt.setPromptText("Enter description (optional)."); desctxt.setWrapText(true); ScrollPane sp = new ScrollPane(); sp.setContent(desctxt); sp.setFitToWidth(true); sp.setFitToHeight(true); sp.setPrefHeight(300); sp.setHbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); sp.setVbarPolicy(ScrollPane.ScrollBarPolicy.AS_NEEDED); // todo hbox (label + text fld), scrollpane - in a vbox VBox vbox = new VBox(); vbox.setSpacing(10); vbox.getChildren().addAll(hbox, sp); grid.add(vbox, 2, 1); // col = 2, row = 1 // new and delete buttons Button newbtn = new Button("New"); Button delbtn = new Button("Delete"); HBox hbox2 = new HBox(10); hbox2.getChildren().addAll(newbtn, delbtn); grid.add(hbox2, 1, 2); // col = 1, row = 2 // save button to the right anchor pane and grid Button savebtn = new Button("Save"); AnchorPane anchor = new AnchorPane(); AnchorPane.setRightAnchor(savebtn, 0.0); anchor.getChildren().add(savebtn); grid.add(anchor, 2, 2); // col = 2, row = 2 // action message (status) text actionstatus = new Text(); actionstatus.setFill(Color.FIREBRICK); actionstatus.setText(""); grid.add(actionstatus, 1, 3); // col = 1, row = 3 // scene Scene scene = new Scene(grid, 750, 400); // width=750, height=400 primaryStage.setScene(scene); primaryStage.show(); // initial selection; statement does nothing if no data listView.getSelectionModel().selectFirst(); } // start() private class ListSelectChangeListener implements ChangeListener<Number> { @Override public void changed(ObservableValue<? extends Number> ov, Number old_val, Number new_val) { if ((new_val.intValue() < 0) || (new_val.intValue() >= data.size())) { return; // invalid data } // set name and desc fields for the selected todo Todo todo = data.get(new_val.intValue()); nametxt.setText(todo.getName()); desctxt.setText(todo.getDesc()); actionstatus.setText(todo.getName() + " - selected"); } } private ObservableList<Todo> getListData() { List<Todo> list = new ArrayList<>(); // initial list data list.add(new Todo("Work", "Work on JCG's example article.")); list.add(new Todo("Grocery", "Get apples, milk and bread.")); list.add(new Todo("Calls", "Call kid brother.")); list.add(new Todo("Read book", "Magnificent Obcession, by Lloyd C. Douglas.")); ObservableList<Todo> data = FXCollections.observableList(list); return data; } }
4.2. Code Description
4.2.1 JavaFX Classes
The following describes the JavaFX classes used to build the GUI:
- The
Stage
class is used to construct the main window of the app. - The
GridPane
is used to layout the controls (buttons, text fields etc.) in a grid of rows and columns. - The
HBox
andVBox
lay out its child controls in a single horizontal or vertical row respectively. - The
ListView
is used to display a vertical scrollable list of todo items from which the user can select. - The
Label
andText
are used for the todo name label and text fields. - The
TextArea
is used for the todo description field. The field is placed in aScrollPane
, so that the text can be scrolled. - The
Button
control is used for the new, save and delete buttons. - The
Text
is used to display the action status.
4.2.2 Layout of Controls
The grid pane layout has 3 rows and 2 columns. The cell in which the controls are placed is as follows:
- Row 1 col 1 has the list view.
- Todo label and text field are placed in hbox.
- Row 1 col 2 has the hbox and the todo description text area – in a vbox.
- Row 2 col 1 has the new and delete buttons – in an hbox.
- Row 2 col 2 has the save button.
- Row 3 col 1 has the status text.
4.2.3 List’s Change Listener
A list selection change listener, of the type ChangeListener<Number>
is attached to the list view:
listView.getSelectionModel().selectedIndexProperty().addListener(new changeListener());
When a list item is selected, the item’s todo name and description are displayed in the text fields.
4.2.4 List’s Data
The list view is populated with data from an ObservableList<Todo>
collection – in the app’s start()
method:
data = getListData(); listView.setItems(data);
In this section, the list’s data is created within the program. The getListData() method creates todos and returns them as ObservableList<Todo> collection.
4.3 Source Code
This is the version 1 of the app. Two classes are newly created. The classes are:
- Todo.java
- TodoApp.java
NOTE: To compile the code and run the app, the jfxrt.jar
(JavaFX library) file must be in the classpath. For Java 7 this can be found at: <JRE_HOME>/lib/jfxrt.jar
.
5. Create Database Access Code
The todo list’s data is stored and accessed from a database. The TODO_TABLE in the TODO_DB database stores the todo details. The database and the table are already created earlier (see section 2. Create App Database and Table). Note the app assumes that the database is created before accessing it.
This section describes the database access code. The TodoDataAccess.java class has the code. This code uses JDBC (Java Database Connectivity) API to access the TODO_DB database.
NOTE: The app’s GUI is wired to the database access in the next section (6. Wire GUI with Database Access).
This class has methods to:
- Connect to the todo database
- Close the todo database
- Read all todo table rows into a List collection
- Insert a row into todo table
- Check if a todo name exists in the todo table
- Delete a row from the todo table
- Update a row in the todo table
The following shows the TodoDataAccess.java
class’s code and details.
5.1 Get Connection
The constructor has code to access the database and gets the Connection
object. This connection object is used to read or update database data. The connection’s properties are set as auto commit, i.e., a transaction commits at insert, update or delete without an explicit commit. The connection is of updateable type.
The DriverManager's getConnection()
static method uses a URL to connect to the database.
public TodoDataAccess() throws SQLException, ClassNotFoundException { Class.forName("org.hsqldb.jdbc.JDBCDriver" ); conn = DriverManager.getConnection( "jdbc:hsqldb:file:db/TODOS_DB;ifexists=true;shutdown=true", "", ""); conn.setAutoCommit(true); conn.setReadOnly(false); }
5.2 Get All Rows
This method retrieves all rows from todo table and returns a List
collection of Todo elements.
public List<Todo> getAllRows() throws SQLException { String sql = "SELECT * FROM " + todoTable + " ORDER BY name"; PreparedStatement pstmnt = conn.prepareStatement(sql); ResultSet rs = pstmnt.executeQuery(); List<Todo> list = new ArrayList<>(); while (rs.next()) { int i = rs.getInt("id"); String s1 = rs.getString("name"); String s2 = rs.getString("desc"); list.add(new Todo(i, s1, s2)); } pstmnt.close(); // also closes related result set return list; }
5.3 Insert a Row
This method inserts a row into the todo table. The method returns an id for the new todo row.
The id value is a sequence number generated by the database system. This is an IDENTITY column. The DEFAULT keyword (in the INSERT statement) is used for the IDENTITY column, which results in an auto-generated value for the column. See section 2.2. Create Todo Table for details on IDENTITY column creation.
The PreparedStatement's getGeneratedKeys()
method retrieves a ResultSet
with the newly generated identity column value.
public int insertRow(Todo todo) throws SQLException { String dml = "INSERT INTO " + todoTable + " VALUES (DEFAULT, ?, ?)"; PreparedStatement pstmnt = conn.prepareStatement(dml, PreparedStatement.RETURN_GENERATED_KEYS); pstmnt.setString(1, todo.getName()); pstmnt.setString(2, todo.getDesc()); pstmnt.executeUpdate(); // returns insert count // get identity column value ResultSet rs = pstmnt.getGeneratedKeys(); rs.next(); int id = rs.getInt(1); pstmnt.close(); return id; }
5.4 Check if Todo Name Exists
This method checks if a todo name already exists in the todo table. Note the app allows only unique todo names.
public boolean nameExists(Todo todo) throws SQLException { String sql = "SELECT COUNT(id) FROM " + todoTable + " WHERE name = ? AND id <> ?"; PreparedStatement pstmnt = conn.prepareStatement(sql); pstmnt.setString(1, todo.getName()); pstmnt.setInt(2, todo.getId()); ResultSet rs = pstmnt.executeQuery(); rs.next(); int count = rs.getInt(1); pstmnt.close(); if (count > 0) { return true; } return false; }
5.5 Delete a Row
This method deletes a row from the todo table for a given todo, if it exists. Note that no exception is thrown if no row is deleted.
public void deleteRow(Todo todo) throws SQLException { String dml = "DELETE FROM " + todoTable + " WHERE id = ?"; PreparedStatement pstmnt = conn.prepareStatement(dml); pstmnt.setInt(1, todo.getId()); pstmnt.executeUpdate(); // returns delete count (0 for none) pstmnt.close(); }
5.6 Update a Row
This method updates an existing row in the todo table with any changes to the todo’s properties.
public void updateRow(Todo todo) throws SQLException { String dml = "UPDATE " + todoTable + " SET name = ?, desc = ? " + " WHERE id = ?"; PreparedStatement pstmnt = conn.prepareStatement(dml); pstmnt.setString(1, todo.getName()); pstmnt.setString(2, todo.getDesc()); pstmnt.setInt(3, todo.getId()); pstmnt.executeUpdate(); // returns update count pstmnt.close(); }
5.7 Close Database
This method closes the database connection and shutdowns the database.
public void closeDb() throws SQLException { conn.close(); }
5.8 Source Code
This is the version 2 of the app. One class is newly created – TodoDataAccess.java. There are no changes to the others. The classes are:
- Todo.java
- TodoDataAccess.java
NOTE: The classes are compiled. There is no program to run.
6. Wire GUI with Database Access
This is the completed app.
The app’s GUI is wired to the database. The app is updated to have the following functions:
Add a new todo item to the list.
- Click the new button; enter todo name and description fields.
- Click the save button. This inserts the newly entered todo into the database. The new todo item is added to the list.
- The app validates that the entered todo name has 5 to 50 character length and is unique in the list.
- While entering the new todo, the entry can be cancelled by clicking the delete button.
Update a todo item in the list.
- Select a todo from the list. Edit the name and/or description fields.
- Click the save button. This saves the updated todo in the database and updates the list, after validation.
Delete a todo item in the list.
- Select a todo item from the list.
- Click the delete button. This deletes the todo from the database and the list.
App start and close.
- At the app start all the todos in the database are loaded into the list.
- At the close of the app the database is closed.
6.1 Coding
In this section the app is updated:
- The new, save and delete buttons are wired to the respective event handler.
- The handler’s code accesses the database.
- The app start and close methods access the database.
The database access code is already built in the previous section (5. Create Database Access Code).
6.1.1 About Event Handler
An event handler of type ActionEvent
is used as a button’s action event handler. The interface EventHandler
is implemented for this purpose. The button’s handler property is set as button.setOnaction(someHandler)
.
This is common for the three buttons in this app – new, delete and save.
6.2 Create a New Todo
When a user clicks the new button, a new todo item is created in the list view, and the app prompts the user to enter new todo’s name and description.
private class NewButtonListener implements EventHandler<ActionEvent> { @Override public void handle(ActionEvent e) { actionstatus.setText("New"); // creates a todo at first row with name NEW todo and // selects it Todo todo = new Todo(0, "NEW Todo", ""); // 0 = dummy id int ix = 0; data.add(ix, todo); listView.getSelectionModel().clearAndSelect(ix); nametxt.clear(); desctxt.clear(); nametxt.setText("NEW Todo"); nametxt.requestFocus(); } }
6.3 Save a Todo
When the save button is clicked, the app:
- Validates the todo name for its length (5 to 50 characters)
- Checks if the name already exists in the database
- Inserts the todo into the database
Note that this event handler is used for both the insert and update functions.
private class SaveButtonListener implements EventHandler<ActionEvent> { @Override public void handle(ActionEvent ae) { int ix = listView.getSelectionModel().getSelectedIndex(); if (ix < 0) { // no data selected or no data return; } String s1 = nametxt.getText(); String s2 = desctxt.getText(); // validate name if ((s1.length() < 5) || (s1.length() > 50)) { actionstatus.setText( "Name must be 5 to 50 characters in length"); nametxt.requestFocus(); nametxt.selectAll(); return; } // check if name is unique Todo todo = data.get(ix); todo.setName(s1); todo.setDesc(s2); if (isNameAlreadyInDb(todo)) { actionstatus.setText("Name must be unique!"); nametxt.requestFocus(); return; } if (todo.getId() == 0) { // insert in db (new todo) int id = 0; try { id = dbaccess.insertRow(todo); } catch (Exception e) { displayException(e); } todo.setId(id); data.set(ix, todo); actionstatus.setText("Saved (inserted)"); } else { // db update (existing todo) try { dbaccess.updateRow(todo); } catch (Exception e) { displayException(e); } actionstatus.setText("Saved (updated)"); } // end-if, insert or update in db // update list view with todo name, and select it data.set(ix, null); // required for refresh data.set(ix, todo); listView.getSelectionModel().clearAndSelect(ix); listView.requestFocus(); } } private boolean isNameAlreadyInDb(Todo todo) { boolean bool = false; try { bool = dbaccess.nameExists(todo); } catch (Exception e) { displayException(e); } return bool; }
6.4 Delete or Cancel a Todo
The delete button’s action serves two functions:
- Cancels a new todo that is being entered, and not yet saved.
- Deletes a selected (existing) todo item from the list and the database.
private class DeleteButtonListener implements EventHandler<ActionEvent> { @Override public void handle(ActionEvent ae) { int ix = listView.getSelectionModel().getSelectedIndex(); if (ix < 0) { // no data or none selected return; } Todo todo = data.remove(ix); try { dbaccess.deleteRow(todo); } catch (Exception e) { displayException(e); } actionstatus.setText("Deleted"); // set next todo item after delete if (data.size() == 0) { nametxt.clear(); desctxt.clear(); return; // no selection } ix = ix - 1; if (ix < 0) { ix = 0; } listView.getSelectionModel().clearAndSelect(ix); // selected ix data (not set by list listener); // requires this is set Todo itemSelected = data.get(ix); nametxt.setText(itemSelected.getName()); desctxt.setText(itemSelected.getDesc()); listView.requestFocus(); } }
6.5 App Start and Close
The JavaFX Application
class’s init()
and stop()
methods are used for app’s initialization and closing. These are overridden in the app. The init method has code to access the database at app start. The stop method has code to close the database at the closing of the app.
Also, following the app start, the todo list is populated with database data (instead of the data created within the program in the earlier version 1). This replaces the code from the version 1. The start method’s code data = getListData()
is replaced with data = getDbData()
.
@Override public void init() { try { dbaccess = new TodoDataAccess(); } catch (Exception e) { displayException(e); } } @Override public void stop() { try { dbaccess.closeDb(); } catch (Exception e) { displayException(e); } } private ObservableList<Todo> getDbData() { List<Todo> list = null; try { list = dbaccess.getAllRows(); } catch (Exception e) { displayException(e); } ObservableList<Todo> dbData = FXCollections.observableList(list); return dbData; } @Override public void start(Stage primaryStage) { ... data = getDbData(); listView.setItems(data); ...
6.6 Source Code
This is the version 3 of the app, and is the final. One class, TodoApp.java
, is modified. There are no changes to the others. The classes are:
- Todo.java
- TodoDataAccess.java
- TodoApp.java
NOTE:
- To compile the app, the
jfxrt.jar
must be in the classpath. - To run the app,
jfxrt.jar
and thehsqldb.jar
files must be in the classpath.
7. Deploy as a JAR File
7.1 Create Executable JAR File: todoapp.jar
The javafxpackager
utility program with the createjar
command option is used to create an executable JAR file for the app.
- Create a directory called:
deploy
- Create two sub-directories in the
deploy
directory:src
anddest
- Place all the app’s
class
files in thesrc
directory - Navigate to the
deploy
directory run the following command from the DOS prompt:
> javafxpackager -createjar -appclass TodoApp -srcdir src -outdir dest -outfile todoapp -v -classpath hsqldb.jar
This creates the app’s executable JAR file. Verify that the file todoapp.jar
is created in the dest
directory.
7.2 Run the App
Copy the created todoapp.jar
file into the deploy
(or any) directory. Note that the following are required before running the app:
- The
hsqldb.jar file
in the directory (or in classpath) - The app’s database and the table are pre-created (see section Create App Database and Table)
Run the app with one of the following ways:
(a) From DOS command prompt:
> java -jar todoapp.jar
(b) Double-click the todoapp.jar
file.
Hi, Compliments on the tutorial. I have a problem with setting up the DB for my project. I have done all the steps above – created a db and a table – so I can see the table in HSQLDB GUI. That part seems to be OK. The part I’m struggling with is to get it to with my IntelliJ project. When I try to Run TodoApp I get a ClassNotFoundException and the JDBCDriver string. I have tried a lot of different possible combinations of that string but without any success. I think I need to introduce my db to… Read more »
Hi Den,
Thanks for reading my article.
I have never used IntelliJ. But, I did some Google search and found these links might give some insight into the problem you mentioned:
http://nixmash.com/java/classnotfoundexception-com-mysql-jdbc-driver-fix-in-intellij-idea/
https://www.jetbrains.com/idea/help/configuring-a-db-data-source.html
Hope this helps,
Prasad.
Thank you Prasad!
For everyone else that are trying to do this in IntelliJ somewhy(I dont even know why I chose IntelliJ):
* I added the java.jdbc.Driver class module as a project dependency from Prasads link – http://nixmash.com/java/classnotfoundexception-com-mysql-jdbc-driver-fix-in-intellij-idea/
* And then because I cannot still fully understand the path logic for HSQLDB Standalone engine I ended up having this for my .getConnection path – “jdbc:hsqldb:file:~/IdeaProjects/TodoApp/out/artifacts/TodoApp/db/TODOS_DB”
If someone could explain me a little bit how this path system works, is there a difference while developing or deployed version. I would appreciate it.
Still ‘siked about how cool this tutorial is,
Den
Den,
I didn’t quite follow your question. Tell me if you are able to run the application without problems.
The following link points to the user guide for hsqldb database. It has answers for questions related to using the driver etc.: http://www.hsqldb.org/doc/2.0/
Thanks,
Prasad.
Yes, I am able to rune the application and I am really helpful for your help with these links you suggested.
The question I had was about the database file path you specify in you connection. In your tutorial you used db/TODOS_DB. I can not get it to work with such path. I can get it to work only with absoulte file paths such as:
* ~/IdeaProjects/TodoApp/out/artifacts/TodoApp/db/TODOS_DB
* or C:/bla/bla/db/TODOS_DB
Den,
There is NOTE (Note on URL’s filepath) on paths in the 2.1. Create Todos Database section above. The path can be either relative or absolute. I had not used an IDE to create, compile or run the app – that is a reason I used the relative path and absolute path also works. What is the reason you want to specify the relative path?
Prasad
Well I imagine my product being a standalone product. So I think I can not use an absolute path because it will work only on my machine. If I would to send my deployed project to someone and they try to use it on their machine – then the db path has changed. No?
So thats why I think I should use a relative path. No?
Thanks for being so patient with me ;) !
String userDir = System.getProperty(“user.dir”)
The above statement gives a directory from which you can specify the database relative directory to the userDir . This way, you can create the database in directory relative to the userDir. It will not matter what the value of userDir is – this can be C:\MyApp\Db or D:\Applications\MyApp\Db. Helps ?
That is exactly what I was looking for!
Thank you so much Prasad! This tutorial and your helpful support on the subject is just another great example of how we live on a great era of learning/teaching!
You are welcome.
Thanks, that was very helpful.
Brian
You are welcome!
A very good tutorial Prasad! Thank you very much.
Thanks for reading my article and the comments.