Introduction
The application displays the content of EMPLOYEE table from DB2 sample database. But what is worth personal data without keeping some additional data like: documents, images, scans etc ? So I decided to extend the application by this feature.
Database
Data like that can be kept in database as blob column. Because more than one document related to a single employee can be stored I decided to create additional table to implement this one-to-many relationship.
create table empattach (id INTEGER GENERATED ALWAYS AS IDENTITY, empno char(6) NOT NULL, filename varchar2(100) NOT NULL, comment varchar2(100), adddate DATE DEFAULT CURRENT DATE, attach BLOB)
alter table empattach FOREIGN KEY FOREIGN_EMPNO (EMPNO) REFERENCES EMPLOYEE ON DELETE NO ACTION
Defining foreign key (the second statement) is not necessary from the application point of view. But by introducing this constraint we are sure that we would not have "dangling" attachment in our database, it is enforced by the database engine.
Because it is one-to-many relationship the "empno" column is not a primary key for empattach table, additional identity column (generated automatically) is defined.
Client application
Additional column "Att" was added. This column displays number of attachments related to the employee and also - after clicking at this cell - additional window pop-ups enabling some actions on attachments.
In order to activate this additional window GWT ActionCell extended as Button was used. The code is something like:
private class AttachClass implements ActionCell.DelegateThis column cell behaves like a normal button and activates an action after clicking at it.{ @Override public void execute(OneRecord object) { AttachmentDialog a = new AttachmentDialog(object, rInfo); PopupDraw p = new PopupDraw(a, false); p.draw(100, 100); } } private class ActionNumberCell extends ActionCell { private final RowFieldInfo f; ActionNumberCell(RowFieldInfo f) { super("", new AttachClass()); this.f = f; } @Override public void render(Cell.Context context, OneRecord value, SafeHtmlBuilder sb) { FieldValue numb = GetField.getValue(f, value); sb.appendHtmlConstant(""); sb.append(numb.getiField()); sb.appendHtmlConstant(""); } } private Column constructAction(RowFieldInfo f) { ActionNumberCell ce = new ActionNumberCell(f); return new ButtonColumn(ce); }
Sending attachments to and fro
Uploading and downloading attachments is done by a traditional servlet, it does not make any sense to do it via RPC call.
So web.xml file keeps additional definitions for servlets implementing GET and POST method.
In GWT code uploading (sending attachment from client to the server) is done via FormPanel and triggering "SUBMIT" action.
Downloading (sending attachment from server to the client) is implemented via enabling Anchor (link) to click on.
Because together with attachment also content-type is sent (based on file name extension) the web browser will try to apply the proper action for the file sent - for instance: to display an image. It is very nice part of it, not trivial action affordable for a song.
Server side
There is a standard definition of two servlets on the server side, one for uploading and the second for downloading. Storing and extracting blob column to and from the database is done via Spring LobHandler class. In order to send a valid content-type very nice feature of Java EE is used :
MimetypesFileTypeMap (starting from Java 1.6 it comes also with JRE).
Refactoring
Unfortunately, by adding this feature the code size doubled. On the other by refactoring the code responsible for displaying a table on the screen (RecordPresentation.java) I was able to reuse this code twicely: to display the rows from the employee table and also for displaying the list of attachments (empattach table).
Brak komentarzy:
Prześlij komentarz