Friday, 9 August 2013

JavaFX Clients and JDBC Servers: Are JavaFX Bean-style objects required on the server side?

JavaFX Clients and JDBC Servers: Are JavaFX Bean-style objects required on
the server side?

I have a JDBC application that is built around a single-server database
(the RDBMS is HSQLDB -- which I love so far). In my first draft of the
application, I have used the following tiered approach:
+-------------------------------+
| DATA STORE (appx 20 tables) | HSQLDB; highly normalized tables
+-------------------------------+
|
v
+-------------------------------+
| DOMAIN OBJECT LAYER (1:1) | A Java class for each table in DB
+-------------------------------+
|
v
+-------------------------------+ Abstraction for the objects that the app
| CLIENT OBJECT LAYER / DAO's | logic actually uses (denormalized)
+-------------------------------+
|
V
+-------------------------------+ Adapts ObservableArrayList() instances
| PRESENTATION LAYER (JAVAFX) | of objects to the GUI
+-------------------------------+
In the Domain Object Layer I presently do all JDBC queries with a generic
static method:
static <E> ObservableList<E> doGenericQuery(SQLParametersList pars,
String sql, Callback<RowSet,E> factory) {
// factory is a Function Object. For now I use Callback<P,R> as the
// "strategy" ... P is a RowSet, R is the object return type. The factory
// simply invokes the constructor for the desired return object type.
RowSet jrs = null;
ObservableList<E> queryList = FXCollections.<E>observableArrayList();
try {
jrs = SQLConnection.getRowSetInstance();
if (jrs == null) {
System.err.println(Census.MSG_ERR_JDBCFAIL);
return queryList; }
jrs.setCommand(sql);
for(int i=0; i < pars.size(); i++) {
// datum().col() method returns an enum representing the
// database column; setJdbcParamByType is an enum
// constant-specific method that invokes the correct
// setXXX method on the PreparedStatement
pars.datum(i).col().setJdbcParamByType(jrs, pars.datum(i)));
}
jrs.execute();
while (jrs.next()) {
queryList.add(factory.<RowSet,E>call(jrs));
}
} catch (SQLException e) {
Logger.getLogger(DB.class.getName()).log(Level.SEVERE, null, e);
} finally {
if (jrs != null) try { jrs.close(); } catch (SQLException e) { }
}
return queryList;
}
What I would like to do is use this method in the data access abstraction
for my whole application, but I'm wondering if I can. As written, this
method returns an ObservableList because it is used by a JavaFX
application. The ObservableList holds instances of SimpleXXXProperty
objects (JavaFX Bean-style, i.e. mutable, objects). I don't think I can
use this code as presently written because I don't want to take JavaFX
Bean-style objects to the server-side.
Eventually, the data access layers are going to be executed in a
server-side environment and the presentation-layer stuff is going to
happen on the client.
I really don't want to have my server-side code using JavaFX Bean-style
objects. Ideally, I want the queries to form a list of immutable objects
and I think I could accomplish that except for the necessity to deal with
JavaFX which seems to mandate that I make everything public and mutable.
The solution that I am thinking of now is to have the server code create
immutable objects from the query result that get wrapped in an
unmodifiableList which then gets transmitted to the client. The client
then has to transmogrify the read-only list into an ObservableList of
JavaFX Bean-style objects so that they may be used in the GUI. BUT .. this
approach requires that I write different version of my Domain Object Layer
(client and server).
Am I on the right track here?

No comments:

Post a Comment