Oscar is 3 years old ; it works and probably some effort and experience is behind this.
Although it is supposed to use Struts, it is mainly a clever , homegrown jsp framework.
Here's some background:
jsp stands for java server pages , or java scripting pages. Oscar is a great example how
jsp is used in the latter sense ; special tags <@page import ... /> allow java packages to be accessed
in the script. From then on, the script can be written like the body of a main method, accessing anything
the import gives access to. For instance , if one wants to access a database, importing java.sql.*; would
be enough , as long as a suitable driver jar is in the WEB-INF/lib directory of the application, or the common/lib
directory of the tomcat server. (e.g. postgresql.jar) .
The advantage of using java in jsp like a scripting language, is that there is no compilation step. Merely
press reload on the browser after modifying the jsp page, and see what happens. Suitably small increments
in writing the script , makes it much like writing in an interpreted language e.g. BASIC, and usually not much
debugging constructs are needed to figure out what's happening ; the simple out.println("I'm here 1"); and
out.println("I'm after here 1"); is enough to isolate where the bug occurs. Other tricks include wrapping
it in a try statement , and use "try { ... } catch(Exception e) { out.println(e); }"
"out" is the the response output stream, which will appear on the web page.
- oscar works, and much of its logic is in the jsp page, so there's no jumping between jsp page and
java class file, to figure out what 's going on.
- because oscar doesn't use the WEB-INF/struts-config.xml file for configuration of web page connections,
you can figure out the navigation mainly by just looking at where navigation details are stored in the
jsp page. They are either literal - stored as forward directives, or hyperlink addresses, or html form action attributes.
They are also stored in special javascript functions, like PageOpen(..) which invoke a javascript window.open() and create
new popup browser windows without toolbars or menu.
- the dynamic part of the navigation is stored as string arrays, where a string key is paired with a jsp file path ,
and forwarded using a lookup using appointmentMainBean.!whereTo(key)
e.g. in provider/providercontrol.jsp
apptMainBean.doCommand(request); //store request to a help class object Dict - function¶ms
if(true) {
out.clear();
pageContext.forward(apptMainBean.whereTo());
}
Here, request is the
HttpRequest object , as defined in the java servlet api. What the doCommand() method
is actually doing, is extracting the request parameters "dboperation" and "displaymode" which specify
what the sql to run is , and displaymode is what is the string key to the next page.
You may say this is very bad object orientation, because it is an obfuscatiion of a very simple operation,
and maybe that is so.
e.g . it would have been a lot clearer if it had been
apptMainBean.setNextSQL( request.getParameter("dboperation"));
String url = apptMainBean.getPageForward( request.getParameter("displaymode"));
pageContext.forward(url);
But to be fair, if one looks at the the j2ee tutorial bookstore6 example to understand what the
fuss is about the latest "dynamic html framework" from Mr
McClahan , java server faces,
it also is a masterful piece of obfuscation, with convenience implementation methods put
on the
AbstractBean class, and making all the bean classes inherit from it, so they can access
the convenience methods .
Better start making notes about what's been gleaned about the structure of oscar.
The application is rooted in the ./web directory,
and it looks like it has been moved from the base directory at some stage.
struts-config.xml is in web/WEB-INF
the java class source files are in web/WEB-INF/classes/src,
the jsp files have the base directory web/
struts-config.xml lists the welcome files which will be the first page when accessing the url
http://:/oscar , e.g. index.jsp,
redirection is then to login.jsp, which displays the login form. This is processed by
the java class, LoginAction , which looks up the password, and the role associated with
the login user, and the rolename is used to forward on , within the struts-config.xml
e.g. "provider", "receptionist", "admin" have forward directives from the struts action "login"
; however the receptionist looks to be deliberately changed to provider , and hard coded in LoginAction ,
this can be changed, but doesn't fully work, because there seems to be other problems , once
one tries to proceed past the day appointment's screen.
The "provider" path goes to provider/providercontrol.jsp with null parameters, and this is
detected and default parameters are set and redirection occurs to providerappointmentadminday.jsp ,
which is still in the provider directory.
Providerappointmentday displays the appointments screen. It has a request parameter "viewall" which if
is = "1" , will find an array of providers in a group. Each column of the each provider is a separate table,
but evenly spaced according to the 15 minute interval. The outer loop is the number of providers.
The inner loop iterates the time in a for loop. A special while loop iterates the appointments for the
provider. A first time flag means the while loop will iterate the appointment; this flag is set to false,
whenever the time interval in the loop does not contain the start time of the current appointment,
and when it is set to false, the while loop will not iterate the appointment, but default executes.
also , if the time interval is before the current start time as above, the while loop is broken out of, to continue
the time interval interation. If the time interval is after the current appointment's endtime,
then the first time flag is set to true, and the while loop continued, which means the current appointment
is discarded in the while loop rs.next() , and the next appointment chosen.
This is quite an interesting and not very straight forward way of constructing the appointment
table for a provider ; a conventional way, might be to cache a model of appointment table cells, but
then this makes it more difficult to show double bookings etc...
when an appointment cell is being constructed,
the special cases hyperlinks for encounter, billing, master detail, straight forwardly pass the demographic number
and / or the appointment number.
the add appointments case occurs when the time is clicked, and this is forwarded to appointment/addappointment
which in turn forwards to a demographic during search, and returns to an "originalpage" parameter, in order
simulate a procedural call / child dialog display .
The search demographic is also the same for edit appointment, which is hyperlinked to the
names in the day appointment's display.
interception of search can be done to an alternate database by using an analogous demographic view,
but some further post processing interception needs to be done, in order to add the
external demographic into the internal demographic table, so that other use cases , billing have
a chance to work minimally modified.
The encounter display is more "struts" oriented, as it uses the convention of calling "action.do" as a
an action url for a form or hyperlink, and in the incomingEncounter action an encounter bean
for the demographic is added to the session parameters, and the saveEncounter action, straight
forward transfers the the encounter beans field values to an sql encounter table.
these are pure java classes in WEB-INF/classes/src/oscar/oscarEncounter/pageutil/ectSave..java and ectIncoming...java
The navigation is dictated in the struts-config.xml, as well as the page that display the encounter
case,
DesignComparison
-- SyanTan - 13 Jul 2006