Contents

General
    What is your suggested production environment?
    What DBAdapters are currently available?
    What database should I choose?
    Why shouldn't I store java objects in my storable objects?

Storable
    What DBAdapters are currently available?
    What database should I choose?
    Why shouldn't I store java objects in my storable objects?
    I just added a column to a storable class, what's going to happen?

Template
    What happens if I modify a template while the server is running?
    What happens if I want to store my application as a jar file?  How is the template system going to find the templates?
    What happens if I want to store my templates in a directory different then my code?
    What objects can go into a replacement table?
    What is the template load cache?
    Why when I use a DLINK or an RLINK does it fail to generate a hyperlink and returns a blank string?

Sessions
    I got some crazy serialization error when my servlet tried to reload!  Now my sessions are all toast! 


Other
    What IDE and development tools should I use?

Demo Site
    Why is the demo site so slow, shouldn't this stuff scream?

General

    What is your suggested production environment?

    I currently run Apache 1.3.14, JServ 1.1.2 on an SMP P-III Linux box.  Due to SMP problems in Sun's JDK1.3, a deadlock (reported to IBM) issue in IBM's JDK1.3, I am forced to run Sun's JDK1.2 with Inprise's JIT as the JDK environment.  As soon as IBM fixes their JVM deadlock issue I will move to the IBM JDK1.3. In my benchmarks IBM's JDK1.3 for linux outpaces all other tested JVMs, such as Sun JDK1.2 (with inprise JIT), Blackdown 1.2.2 (with inprise JIT), and Sun JDK1.3.  Depending on the test IBM's JDK1.3 runs 1.8-2.0x as fast as Sun's JDK1.3.  

     To increase speed of the JServ engine, you should turn the:

     autoreload.classes=true

     option to false in the JServ zone you are running in production.  This will increase the speed of JServ by some 20%.  However, when you recompile your production code, JServ will not automatically reload the zone.  You must touch the properties file (using the unix command touch).  If you're really worried about speed, then you need to choose the right JVM (it really makes a huge difference), and you might want to look into commercial servlet environments.  I had an eval copy of JRun , and it appeared to run significantly faster then jserv, probably because of the thread pooling which jserv currently lacks.  I didn't look too much into it though, my eval copy expired :(

    Jetty is quickly starting to earn my respect.  It's much faster then JServ.  There are a few limitations which are common to most servlet engines (reloading a Web application while users are online),  but Jetty is extremely extensible.  I suspect there may be some major advancements in Jetty over the next couple months.

    JRun now owned by Allaire is the fastest Servlet engine I've run into.  However you will pay a good amount of cash for the extra speed; JRun is not free.  JRun has limitations on restarting servlets while people are in them, and cannot reconfigure itself without restarting the entire engine (which boots everybody out).  JRun may be a little bit faster then Jetty, but Jetty's flexibility and dynamic nature probably more then make up for the difference.

Storable

    What DBAdapters are currently available?

    Currently only a MySQL DBAdapter is really available.  PostgreSQL and Interbase's adapters are either finished or nearly finished, but lack the kind of testing you would expect in a database adapter.  If anybody would like to help in this arena, it would expedite their availability.  Once additional DBAdapters are available, you should be able to simply plop in a new DBAdapter and have all your Database Object code work properly.  Moving data from one database to another is as easy* as 

Vector v = TheObject.loadVectorInstance(MT, new RawWhereQuery("")); 

Changing the DBAdapter to the destination DBAdapter

for (Enumeration e=v.elements();e.hasMoreElements()) {

    ((Storable) e.nextElement()).insert(MT);

}

* (see wasn't that easy)

    What database should I choose?

    Good news is that if you program using the Storable Object layer, you should be able to flip between underlying databases will almost no change to your application code.  Bad news is it's really up to you.  I've examined three different databases for Storable.  PostgreSQL, Interbase, and MySQL.  I would publish the specific results of these benchmarks but really they are only applicable for the application I was testing each database for.  Instead I'll give you really highlevel view of what I found. 

    If you need transactions, or you feel transactions are appropriate for your business logic, you cannot choose MySQL.  MySQL does not currently support transactions (although with BDB tables it shortly will). 

    For raw speed, insert, update, select, or joins MySQL is the clear victor over PostgreSQL and Interbase.  This may have more to do with the efficiency of the JDBC code, then the actual database.  This does not take into account concurrency (multiple requests to the database at the same time).  Apparently MySQL's limitations become quickly apparent if you have inserts/updates concurrently running with selects on the same table. 

    For complex selects using Natural joins over hundreds of thousands of records (again this was the only thing processing on the database at the time), and aggregating using a group by, MySQL is again the clear victor in speed.  Interbase comes in a far distant last, executing most of my sample complex queries approximately 5 times as slowly as MySQL.  Postgre came in somewhere in the middle of the two, sometimes running about as fast as MySQL.  Oracle ran faster then MySQL on some of these queries, on par with PostgreSQL on some, and slower on some. These queries were done using raw SQL using each database's respective tools, and not done through Storable.  The databases and SQL in all the cases were the same. 

    Why shouldn't I store java objects in my storable objects?

    Storing non-primitive (or non SQL data types) in the database rows severely limits your ability to do relational database queries, and your ability to aggregate data inside the database server.  The Python version of Storable readily stored Python objects ("pickled") in the database.  Although this made things easier at first, down the road it effectively choked off calculation optimizations.  The result was a lot of calculations and queries (which would have been faster if done in the database server) had to be done in Python.  What was really a kicker for performance was when you had to instantiate a very large set of objects, just to run the set of objects through a filter to "finish" the query because a qualifying logic was stored in some Pickled Python field.

    I've reconsidered the idea of storing anything "serialized" in the database in java for the above reason, and because java serialization is damn picky.  If you go off and store an object serialized in the database, you will -not- be able to de-serialize if you make any changes to the class file describing that object which effect any attributes.  This is because each time you change the stored attributes in a class, java goes ahead and changes the serialization ID on the class.  If the serialization IDs do not match, java does not deserialize and your data is now incompatible, and worthless.  No fear you might say, simply use a customized serialization ID, thus overriding java's natural tendency to make your serialized data bacon bits.  That will work great, (and it's probably something you should do if you store objects whose class file changes in a session), but it -won't- help you if you really do make a change which makes the serialization process incompatible.  No fear you say, you will simply write a custom serialization routine which can readily identify the different generations of the class (based the the serialization ID) and convert them to the current version.  Well great.  If you haven't noticed storing that object in the database has just become the most cumbersome, high maintenance pain the ass ever.  You can do it, and sometimes maybe you really should, but I would try to break down that object into it's components and store them using their primitive elements.  Oh, and storing a Vector might seem like a good idea since the class is likely to change any time soon; but you would certainly risk restricting yourself to a single JVM, with the same vector class.   Plus whatever is in your vector needs to be serialized too; it's probably better to create an extra table for Membership and use a foreign key to associate it to a set of objects describing what was in your vector to begin with.

    I just added a column to a storable class, what's going to happen?

    Next time a DBAdapter is attached to that Storable, the DBAdapter will check the Schema described in the Storable Class against the actual database schema.  Any missing columns are added.  Currently columns are not removed, or have their types converted automatically.

    When my application is run for the very first time, it needs to shove certain things into the database.

    You should modify your DBConnector class (the one which acctually connects the DBAdapters to the Storable classes at startup) to add the records you need.  It should use the Storable.tableExists(MT, Storable) method to check if the table for a particular class already exists in the DB.  If it doesn't, you know you need to deploy your records. 

Template

    What happens if I modify a template while the server is running?

    Apollo will automatically (based on the date) detect that the file has been updated, reparse the file, and display the new version.  Obviously if your template is stored in a jar or zip file (and was loaded by the Class Resource Loader), you won't be modifying your templates.  If somehow manage to, well, you probably have bigger problems (EG: the servlet should probably be reloaded).  If you modify an html file, and it does NOT reload, your templates were probably loaded with a Resource Loader, which is how template pages are loaded when they're stored in a JAR or WAR file.  HTML files are not reloaded when they are modified and they were loaded using a Resource Loader.  You can get apollo to not use a resource loader by fixing your apollo.properties file to properly set the PageManager.RootDir variable.

    What happens if I want to store my application as a jar/war file?  How is the template system going to find the templates?

    By default the template files will be searched for under the PageManager.RootDir directory.  If they are not found there, the template system will ask the Class Resource Loader (which probably means you need to pass in the PageHandler!) of the object loading the Template to load them.  It should be able to find them if you store them in the same directory as the .class file of the aforementioned class. 

    What happens if I want to store my templates in a directory different then my code?

    Simply point the PageManager.RootDir to a different directory.  I like having the HTML files right there with the program code, but to each his own.

    What objects can go into a replacement table?

    Anything.  The toString() object is called on whatever you shove in; unless you shove in a special Template object (such as a SelectObject).  That means if you want to do alternating background colors on rows in a table you can create a stateful object which returns alternating RGB colors to toString() calls.  

    What is the template load cache?

    Template files are parsed only once, when they are registered with the PageManager.  If you're writing a servlet, that's probably done once at startup.  Once a template file is parsed, the parsed version is stored in memory for high speed rendering.  The initial parsing isn't the fastest thing, and after you have a hundred template pages, your servlet will start to take a bit of time to initially start up.  The template load cache serializes the parsed pages before the servlet terminates.  When the servlet starts, a comparison is made to make sure the parsed template matches what is currently on disk for the template it's trying to load.  There are two comparison modes, strict and non-strict.  Strict makes sure byte-for-byte that the current template is identical to the parsed one.  Non-strict just compares the dates of the previously parsed template and the template on disk.  If there are any inconsistencies, the template is reparsed.

    Why when I use a DLINK or an RLINK does it fail to generate a hyperlink and returns a blank string?

    This happens when the template system can't figure out how to make the link.  It probably means you failed to pass in a session to the render(HashTable, WebSession) or toString(HashTable, WebSession) call, or you failed to set the ServletPath on the session using the setSevletPath(String) method.

Sessions

    I got some crazy serialization error when my servlet tried to reload!  Now my sessions are all toast! 

    You cannot place anything in your session which is not Serializable and expect it to come back from disk.  If you need to place something in a session which is not serializable by nature, you need to write a custom serialization handler for it.  See details under the "Custom Serialization" header in the Session Examples Page.

Other

   What IDE and development tools should I use?

Extremely tough call.  Good Java IDE's are far and few between, despite there being dozens of Java IDE's available (and for sale).  Apollo should work with all of them, but there are some core features you really need in an IDE when writing apollo applications.  Apollo application code forms logical tree like structure.  As a result, you really want an IDE which handles Java packages properly.  You want to be able to open up folders and close folders, where each folder is a java package.  It's also useful if when browsing the package structure in this "explorer" you can see the HTML template files.  A good debugger is important; but the debugger does not need a servlet debugging engine.  Look at the debugging servlets  pattern for a description on how to fully debug servlets in any java debugger.

Kawa

    Kawa 3.x was an excellent IDE, but is terrible for code on any application which is in CVS and new files might appear during a CVS update, because Kawa wouldn't notice new files on the  filesystem.  Also when Kawa went to Kawa 4.x, the interface got noticeably worse, and almost unusable.  I submitted half a dozen bugs for various problems, and finally gave up in disgust.

Forte

    Sun's Java IDE is extremely powerful and has lots of toys.  It's written in Java, so you should be able to use it on any platform.  Unfortunately it's marginally stable under Linux and windows, and has a few bugs.  It supports CVS integration, but (as of June 2000) really didn't work right.  It includes a debugger, and it works fairly well, even if it's slow.  It's a very CPU hungry IDE, and it's tough if you don't have an >600MHz P-III sitting on your desk (which I don't!).

JBuilder

    This is Inprise's IDE.  It's shows some true promise; it seems faster and more stable then Forte.  However there's some serious, and I mean serious limitations to making this an even remotely usable IDE.  First and foremost, it does not support auto tabbing, so hitting { [enter] does not automatically indent the next line.  Making matters astronomically worse is the fact that when you try to manually tab the next line, the tab key makes an inconsistent number of spaces.  Once hitting the tab key trying to get it to indent 4 characters, it indented 64 characters off one key press!  Also JBuilder uses the notion of classes for it's java browser.  That means although you get a nice layout of your Apollo application code, you will NOT see the html files associated with the Brokers.  JBuilder has some sort of CVS integration, however it does not function at all.  Even more of a nuisance with JBuilder, is JBuilder uses some sort of internal data structure to calculate dependencies and doesn't compile files it thinks it doesn't need to.  Sounds good, forte does something similar.  Too bad it doesn't work.  If you use JBuilder for a couple hours, you'll eventually notice it doesn't compile the file you just edited in the very same IDE.  If you do something nasty like delete a class file off the filesystem, JBuilder is done for.  It'll complain that you're accessing classes which don't exist when it tries to compile different files.  There's no real fix once you're in this jam, other then starting a new JBuilder project and starting over, or hunting down JBuilders dependency cache, and deleting it.  I submitted some bugs to Inprise, it would be considered as an "upgrade" in their next version.  Also jbuilder by default spews the complied class files to a different directory then the source code.  This doesn't work when you're trying to write servlets since the external servlet engine needs to run them, so you'll need to fix that immediately when creating a project.  JBuilder's debugger is very fast and stable; if you can ever get your code to compile in JBuilder.

JDE

    JDE is the answer for Java IDE salvation.  It's not pretty.  It's not graphical.  But it gets the job done right.  JDE is a plugin to the all powerful emacs.  Which means you get all the massive advantages of using emacs as your IDE.  Through a plugin called the SpeedBar, you will get the explorer type interface for your Apollo code.  As a bonus, Speedbar will also show you other files in these directories, so when you try to open an HTML file, you'll get emacs's built in HTML editor free of charge.  Emacs has extremely good indentation parsing (as you should expect); and you can ask Emacs to simply retab your entire file, and it will calculate the exact indent for each line of code for you.  JDE has a debugger, but in the version of the JDE I'm running (fairly old) it doesn't work so well.  I hear it's working much better in the new version.  Again, it's not graphical so it's not the most user friendly beast.  JDE is also lacking a good build system; some people use ant as the building interface for JDE.  We wrote custom build tools for compiling.  You can click on errors and it will navigate you to the line of code with the error.  JDE also allows you to do method name matching, and method name completion (like <tab> completing files in Bash), which is mad handy.  JDE is not easy to setup, but is well worth it when you are finished.  Everything possible is configurable about JDE, which is one of the reasons why it works so well.  If you need a new key bound, simply bind the key in your .emacs file.  JDE will grow on you, and aside from the Debugger being a bit difficult, is bar far the best and most usable IDE out there. 

 

Demo Site

Why is the demo site so slow, shouldn't this stuff scream?

    Two words, 90kbps uplink.  We would be eternally grateful for anybody who is willing to host the Apollo Demo application on their server.  Sourceforge does not currently provide a servlet environment for hosting.  I would suggest installing the demo site on your own machine before making any determination about the speed.