The current version is 1.0.29 (requires JDK 8 and above). Amazon corretto is recommended for the JDK (this, IMO, is the true successor to the Sun and the OpenJDK). (Changelog)
There is also a JDK 6 version available, which is exactly the same as JDK 8, except is missing some misc/minor JDBC methods (missing in JDK6 since added in JDK 7+) (Changelog)

Due to increasing divergence between JDK 6/8, this will be the last version that will be available for JDK 6.

The download comes with full source, javadoc and compiled classes. You can also recompile all classes from scratch (there are no external dependencies).


Molly can be used for standalone java programs or in a web-server/servlet environment. After downloading the molly package, you just have to make sure that either molly.jar or the compiled classes (unjar'ed) are in your classpath. There are several possibilites (unix examples shown):

For Standalone programs:
You can install molly in a location outside of your webserver.
    unix> export CLASSSPATH=$CLASSPATH:/path/to/molly.jar
Then run this as your first program
    unix> java fc.util.Version
If you see a welcome message, you are up and running successfully!

Alternately, you can specify the classpath to the java interpreter:

    unix> java -cp $CLASSPATH:/path/to/molly.jar java fc.util.Version 

Next, try generating some O/R classes and connecting to the database. The following will print out usage information to the console.
unix> java fc.jdbc.dbo.Generate
You can get some sample configuration files (edit those to your environment) from the O/R examples. The cookbook is also worth checking out.
For Web Applications:
You can also install molly.jar directly in your web server's WEB-INF/lib directory. (See this for more details).

The webserver will automatically add this to it's java classpath. To run programs from the command line, you would say:

    unix> export  CLASSSPATH=$CLASSPATH:/my/website/WEB-INF/lib/molly.jar
    unix> java
Alternately, you can specify the classpath to the java interpreter:
    unix> java -cp CLASSSPATH=$CLASSPATH:/my/website/WEB-INF/lib/molly.jar java


  1. Changed the PageParser to generate code that keeps String literals less than 64K bytes. Pages lines are output using something similar to
  2. in the PageServlet. Each line in the source document is converted into these out statements. However, if the entire source document is one large line (with no newlines) and that line size is massive (> 64K), the the generated code will fail because Java string literals are limited by the classfile constant pool limitations (this limitation may go away in future java variants but is true as of now).
    This sort of thing can happen with machine generated XML files for example (uncommon but can happen).
    We break such long lines into smaller chunks internally (without adding any spurious linebreaks) so what you put in is exactly what you get out (and no compilation errors!)
  1. Added a BitUtil class for misc. Bit operations.
  2. Slight cleanup to BasicArgcheckFailHandler class to have less noisy output
  1. The include-file pages tag is improved and previous limitations (of not being able to contain directives, declarations, etc) are removed.
  2. Internal refactoring and improvements to the molly pages parser and reader.
  3. JSON/JSONB data types are supported and returned as Objects by the DBO frameworks. These are can be converted into Java JSON objects locally on the Java side (by passing these as Strings to your JSON framework - whichever framework you are using).
  4. DBO framework prevents a edge case - an internal variable count would clash with a column name "count" if used. Internal names start with __ now and that should be a hopefully separate namespace. If your table column name happens to be (2 underscores) "__count", you are still in trouble though!
  5. Although mysql testing has fallen by the wayside, a round of mysql testing for this release, just to ensure the framewok is database independent. Both postgres and mysql work great.
  1. DBO Framework: added a deleteUsing variation that takes an optional WHERE clause
  2. Various misc. cleanups and tweaks
  1. Created a JDK 8 compatible version that compiles under JDK 8. JDK 6 is still supported but will be dropped afer this version.
  1. In addition to the WebApp that is created per servlet context/webapp, multiple WebApps can be manually instantiated and added (under different names) in the same servlet context/webapp. This is useful when there are multiple servlets running in the same context, each of which need seperate connection pools, loggers, etc; these servlets can use the existing WebApp functionality that reads a config file and creates all this specific for each servlet (independent of the shared context wide WebApp).

    In particular, this is useful for servlets that support REST API versions, /rest/v1/*, rest/v2/*, etc, and one can configure different connection pool sizes and resources for each particular version of the API, as opposed to using context wide shared resources for all the different servlets in common.

  1. The DBO Generate warns & exits early if a table or column name is a Java Reserved Keyword because the generated code wouldn't compile in that case anyway.
  2. Added a MiscUtil class.
  3. Added a few more utility methods to CalendarUtil
  1. Small tweaks and fixes throughout the framework.
  1. DBO Framework: added the ability to save primitive fields as null if they are nullable in the database. Primitive fields such as integer cannot be null in Java yet the corresponding SQL fields can be null in the database. So, for a field "x", there is now a method called "setNull_x()" (or similar), which if called sends null for x to the database.
  2. Misc cleanups
  1. Changed WebApp to be more sane (you now create a different WebApp instance per tomcat webapp. Prior WebApp usage (when molly classes were loaded via the system classpath) was 1 instance shared across all tomcat webapps, which meant each webapp would overwrite the prior webapps configuration. The recommended way to install the molly classes in each tomcat webapps separate jar directory (such that it wasn't in the system classpath at all) was proving to be too much of a hassle in practice.
  2. Misc cleanups
  1. Bug fix: IOUtil.sha1hash was missing a leading "0" in the hex value for bytes less than 16 (so "A" rather than "0A").
    Thanks to Menelaos Perdikeas of Semantix Information Technologies, for the patch.
  1. Misc. tweaks and improvements to the DBO framework.
  2. Bug fix: When creating a new DBO object and saving it as a forced update (via the update method), the primary key parameters specified to the update method are used, rather than using the original primary key(s) (which are now only used internally for updates of objects retrieved from the database).
  1. Added a NamedParamStatement class. This makes it easier to work with JDBC PreparedStatements, instead of using ? and integer indexes, one can use named parameters instead. For example:
    String query = "select * from foo where bar = @bar and baz = @baz";
    NamedParamStatement ps = NamedParamStatement.get(con, query);
    ps.setString("bar", "hello");
    ps.setInt("baz", 42);
    This is quite useful for larger, complicated queries with lots of parameters.

  2. Misc. improvements in in the DBO generate code that make it easier to use when using table aliases (using the SQL "AS" keyword).

    For example, see columns(String) and getFromRS(ResultSet, prefix)

  1. Fixed a bug in the DBO generate code that would cause an error when updating a row after modifying it's primary key(s). For example, consider the following table:
    create table users (username varchar(255) primary key, age integer);
    Now, we use DBO, generate our java objects and say:
    users u = usersMgr.getByKey("molly");
    u.set_age(22);, u);
    This would internally create & use a SQL update statement that would look something like:
    UPDATE users set username = 'case', age = '22' where username = 'case';
    We update a row using the primary key but we are changing the primary key itself, which means we can no longer find the original row to update.

    This problem is fixed now, by having the generated DBO object internally save the original values of all primary keys. These original values are then used when updating the row. In this example, that would now look like:

    UPDATE users set username = 'case', age = '22' where username = 'molly';

    Dunno how this elementary bug managed to slip through, undetected for so many years. Primary keys are not changed that often, I guess. Just goes to show that no complex piece of software is ever completely bug free.

  2. Fixed another bug in DBO. If setters were generated for SERIAL/auto-increment types, and values were manually entered for those types, then those fields were not saved to the database.
  1. Added a CommentedFileReader class that helps read files, ignoring any comments and whitespace.

    With the existence of CommentedFileReader, FilePropertyMgr, IOUtil, StringUtil and Template, using property & configuration files is easy.

  1. Added a QueryReader class that helps organize your queries in a text file, external to your program. This makes maintainence a lot easier.
  2. Note: We skipped version 1.0.13 for good luck
  1. Previously, when saving a new DBO object, if a particular field was not-nullable in the database, it had to be set in the DBO object before the object could be successfully saved/updated. Now, it does not have to be set in the object, if the database also defines a default column value for that non-nullable column.
  2. Many misc. tweaks & changes
  1. Fixed a bug in the DBO-generated manager class, where if an autoincrement/serial column was not the first column in a table, then saving a corresponding object would fail (when retrieving the new auto increment value).
  1. Various little documentation fixes.
  2. The problem with the command java fc.jdbc.dbo.Generate not printing its usage/help file has been solved. It wasn't a bug with the Java classloader as previously thought. It was the fact that the help file was missing from the published jar file (yeah, I know !)
  3. JDBCSession has been improved to not use static methods. I like using static utility classes (as opposed to singletons) because they are simple. But if the utility class needs to be initialized (once) before being used, then, we have to remember to call the static initializer, which is easy to forget. So instead of saying:
    we now say:
    JDBCSession session = JDBCSession.getInstance(); //does init if needed
  4. Added a cookbook link on the website, concurrently with this release.
  5. A special thanks to Menelaos Perdikeas of Semantix Information Technologies, for helping report and diagnose various issues.
  1. This version compiles and runs under JDK 1.6. The only change from the previous version was some additional JDBC4 specific method signatures, required for JDK 1.6 were added. Consequently, this version will not run under JDK 1.5 and requires JDK 1.6 or greater.
  1. The configuration file for the DBO Generator accepts both prefix and suffix * wildcards for table names to exclude. (previously, a wildcard could only be applied to the include tables). Added Clarifications to the include/exclude functionality in the configuration file.

    There is a problem with the command java fc.jdbc.dbo.Generate not printing its usage/help file (due to a java bug with the classloader not being able to load a resource from within a .jar). These usage/help instructions have now been added to the javadoc as well to get around this problem.

    I recently pointed the DBO Generator towards a real 400+ table enterprise production database with all sorts of columns, tables and relationships. The generator ran flawlessly and took about 30 seconds to generate and write 800+ classes (2 per table). So the Generator itself is super fast (perhaps the fastest O/R in Java) and does work very nicely.

  2. The fc.util.Watch class can now return elapsed time in seconds (in addition to milliseconds) which makes for more user friendly output.
  1. Added the ability to use a thread local java.util.Random to WebApp
  1. Modified GzipFileServlet so the paths of included files are relative to the document root (as opposed to web app context as earlier). It is more intuitive for absolute paths to be relative to the document root.
  2. Added more methods to the Page interface and improved the javadocs for both Page and PageImpl.
  3. Added a new Table class.
  1. Fixed a major bug in the PageMgr page reloading algorithm. This bug caused the page class to be discarded and reloaded as if the page had been modified, even when it hadn't. This caused the static fields in the page to be reinitialized at every page access, instead of when the page source was modified.

    All molly page users should immediately upgrade to this release.

  1. Fixed a minor bug which caused the PageMgr to throw an exception when the webapp was restarted.
  1. The configuration file for the DBO Generator accepts both prefix and suffix * wildcards for table names to include. (previously, a wildcard could only be either a suffix or a prefix but not both).
  1. Page forwards can now contain expressions. (Earlier, only Page includes could contain expressions)
  2. Misc. javadoc clarifications.
  1. Added GzipFileServlet. This allows serving of compressed html/js; this speeds things up considerably when downloading javascript libraries
  1. Initial public release.