POJO Jenerator:  Java Code Generation for the whole MVC spectrum!  

A Free, Full-CRUD Java Code Generator for the Whole MVC Spectrum


    Because "scaffolding" and "frameworks" still leave you with lots of work to do!

POJO Jenerator White Paper

(Guest)   POJO Jenerator White Paper         
 

Brief

POJO Jenerator is a code generator that creates everything you need to get started with a new Java-based web project, or to extend an existing Java-based web project. It works like this: first, you create the data model for an entity. You give the entity an object name and a database table name, and then you provide the attributes of the object as names and SQL data types. POJO Jenerator then generates for you everything that is needed for a fully operational web-application that supports full CRUD capabilities for that entity:
  • A SQL DDL statement to create the database table. (Currently only MySQL and Oracle are supported.)
     
  • A spec-compliant JavaBean class, complete with constructors, accessors, and support for enumerations.
     
  • A JDBC Data Access Object (DAO) class with fully orthogonal CRUD methods, and support for transactions.
     
  • A series of servlets (4) and JSPs (3) that together form a basic "web-widget" for displaying records from the table, adding new records, editing records, and deleting records. This is all done with slick AJAX techniques which make it seem like the HTML table is being updated directly in the page without server interaction.
     
  • The eight XML stanzas you'll need to place in your web.xml file to declare and map the 4 servlets.
     
  • Enumerations are supported, for INT/NUMBER(10, 0) (Java int), BIGINT/NUMBER(19, 0) (Java long), and VARCHAR(n) (Java String) data types. The resulting code automatically produces a working <select> drop-list, static Lists of values and labels that can be referenced globally, and range checks to ensure posted form data matches one of the values of the enumeration.

The generated code is of course very generic - you'll want to customize it with validations, range-checks, edits, and other behavior specific to the application you are building. The resulting GUI design is also generic - a simple black & white HTML table with default buttons. You'll want to customize this with graphics, colors, fonts, styles, etc.

The intended purpose of POJO Jenerator is to give the developer a very large jump-start in developing new applications (or significant extensions to existing applications), while still producing pure, native, simple code that is easily read and understood by the largest audience of developers, and is easily deployable with a minimum of extra libraries, extensions, and configuration. The resulting code is not obfuscated into a black-box library, nor abstracted away from the developer by bundling it into a .jar file, nor created at run-time by aspect-oriented techniques. The resulting code is styled to look just like the code a developer might write from scratch, and you can step through it with any common debugger, profiler, IDE, etc. and see everything that is going on, and modify any part of it without worrying about unpredictable side-effects.

POJO Jenerator is among the first (if not the first) code generator to provide CRUD code generation that goes beyond the model/persistence layer, and into the presentation and controller layers of the venerated MVC framework. All the software plumbing that is required for fetching the data from the database table, placing it into the session and forwarding to the appropriate JSP, iterating over the list of objects and rendering them into a table, displaying a form for adding new records and editing existing records (and AJAXing these into and out of the page when needed), processing the posted form data, and round-tripping the data into & out of the database - is generated automatically. All you need to do is modify the resulting Java code and HTML to match the look & feel of the application you're building, and to provide custom behavior where needed (usually in the form of data edits, range-checks, validations, etc.) What might take days or even weeks of effort if done by hand, takes only a few minutes using POJO Jenerator, freeing the developer to spend valuable time on the less mundane work of customizing the design and behavior of the software.

 
Limitations

  1. POJO Jenerator supports only the following SQL column types, and maps them to these Java types:

    MySQL Oracle Java
      INT NOT NULL   NUMBER(10, 0) NOT NULL   int
      BIGINT NOT NULL   NUMBER(19, 0) NOT NULL   long
      VARCHAR(n)   VARCHAR(n)   String
      DATETIME   DATE   Date (java.util.Date)
      DECIMAL(x,y)   FLOAT(24)   BigDecimal

  2. Your bean attribute names must exactly match your database column names. (You're already doing this, right?)
     
  3. Your table (and value object) must have an attribute called "id", of either INT or BIGINT type for MySQL, or NUMBER(10, 0) or NUMBER(19,0) for Oracle, which is the primary key of the database table, and you must set this primary key so that the database auto-populates the values. (Again, you're already doing this, right?)
     
  4. As mentioned above, enumerations are currently only supported for INT/NUMBER(10, 0) (Java int), BIGINT/NUMBER(19, 0) (Java long), and VARCHAR(n) (Java String) data types.

 
The Generated Bean Class

The generated bean class has all private attributes, with public accessor methods. It also implements java.io.Serializable, and has a default, no-arguments constructor. These features keep the class compliant with the JavaBean specification.

The generated bean class also has a more useful constructor, which takes arguments and makes assignments.

When enumerations are specified, a static List of the allowed values, and a static HashMap of value-label pairs is generated for lookups. A method for presenting the label for the current value of the bean instance is provided, and a singleton pattern is created for populating the enumeration components. It also produces a method that renders an HTML <select> list with the current value selected, and another method that determines if a supplied value is a valid enumeration. These are all used in the generated code.

 
Naked Value Objects
At some point I got tired of using getters and setters for all my beans, because the vast majority of the time, they do not do anything other than directly get or directly set the attribute value. This means a lot of wasted code, wasted CPU cycles, and wasted memory, and also makes coding with the beans more tedious.

So I made an option called "Naked Value Object". When you check this, the generated code will result in a "naked" bean: the attributes are all public, there are no accessor methods, and this is reflected in the DAO class and GUI components. You can try generating the code both ways and see for yourself which version is easier to code with, consumes less memory, runs faster, and results in less lines of code.

 
Anatomy of a POJO DAO class
The DAO class that is generated by POJO Jenerator is intended to be a "starter" DAO class. It provides sample methods for retrieving data, inserting data, updating data, and deleting data. Most of the modifier methods can be used as-is without modification for the life of your software. The retriever methods also work as-is, but are intended to be examples that you copy and modify for specific data fetching needs.

Each method in the DAO class has two versions: one that is "atomic", and one that supports transactions. The atomic version is the one you will likely use most often, and all it does is fetch a database connection, pass this in a call to the transacted version, and then return the results and close the connection. The transacted version of each method has the same name as the atomic version, but with "Trans" appended to the end. It requires a connection to be passed in, and it is also declared to throw an exception, so it must be wrapped in a try-catch block when calling. This is what you will do when you need to perform database operations within a transaction.

  • Retrievers: There are two retriever methods generated. One fetches a single row by the primary key, and this method returns a single bean of the generated type. The second retriever is a multi-row fetcher, and returns a java.util.List of beans of the generated type. It simply fetches all rows in the database table. The idea is that you will be copying one of these two methods, giving it a new name, and changing the SQL to a more specific and useful select statement. If what you need to do involves multiple records, copy from the multi-row retriever. If you need a single row, you can copy from the single-row retriever.
     
  • JDBC Binder: A simple method that takes a ResultSet object as an argument, and builds and returns a bean of the generated type. Some people might call this a "factory" that makes a bean from a JDBC ResultSet. It is used by the retrievers, and if you are using the retrievers as examples to copy & paste from, then you will always only have to go to one place to make changes to the bindings for all of your retriever methods.
     
  • Inserters: There are three types of insert methods. One takes a single bean and inserts it. The next takes a single bean and inserts it, but also returns the newly-generated primary key, for those cases where you need to know that. (Think of inserting a parent record, and then using the new primary key of that parent as a foreign key for the child records to be inserted next.) The third insert method takes a java.util.List of beans and inserts them in batch, taking advantage of the PreparedStatement's performance.
     
  • Updaters: There are two update methods: one that updates a single bean, and one that takes a java.util.List of beans and updates them all, taking advantage of the PreparedStatement's performance.
     
  • Deleters: There are two delete methods: one that deletes a single bean, and one that takes a java.util.List of beans and deletes them all, taking advantage of the PreparedStatement's performance.

Each generated DAO class extends the PojoDAO base class. The PojoDAO class contains constants for various security and failover parameters, and supporting methods for obtaining database connections from the pool, parsing currency, converting between java.sql.Timestamp and java.util.Date objects, and other general-purpose tasks used in the generated DAOs. The jndi name of your DataSource is populated in this PojoDAO class (in the getConnection() method) from the value you supply when entering the object information. You typically only need to generate the PojoDAO class once for a project, and then you don't really need to re-generate this for every DAO you make, because they all extend this same class.

 
Anatomy of the POJO GUI Code
The GUI code consists of four Servlet classes, three JSPs, and the eight XML stanzas you need to place in your web.xml file to declare and map the four Servlets. All Servlets and JSPs are named with the name of the object, followed by a description that suits the file:
  • <ObjectName>DisplayRecords.java: This servlet simply invokes the method on the generated DAO class to retrieve all records from the table, and places this List of objects into the session. Session tokens are of the format "<NameOfClassSettingThisToken>.<variableName>", which makes it very easy to debug and trace where to go to make corrections or changes. For example, the List of all records is set to a variable name of <objectName>Beans, and it gets placed in the session under the token "<ObjectName>DisplayRecords.<objectName>Beans".

    The Servlet then forwards to the <ObjectName>DisplayRecords.jsp file.

  • <ObjectName>DisplayRecords.jsp: This JSP contains all the Javascript code needed to manipulate the web page using AJAX calls to support adding, editing, and deleting records. It uses a <jsp: include> to include the <ObjectName>DisplayRecordsTable.jsp file.
     
  • <ObjectName>DisplayRecordsTable.jsp: This JSP is what does the work of rendering the HTML table to display the records from the database table. It first renders a row for column headers, then it retrieves the List of objects from the session using the token "<ObjectName>DisplayRecords.<objectName>Beans", and iterates over this list, pulling out each bean and rendering a row in the table. All attributes of the table (except for the primary key) are displayed by default, and the last column of each row gets "Edit" and "Delete" buttons. These buttons invoke the Javascript functions defined in the <ObjectName>DisplayRecords.jsp file.

    Lastly, it renders a final row with an "Add" button in it, for adding new records.

    You can think of this JSP as a modular component that can potentially be re-used elsewhere in your application. The contract is simply that it needs a List of beans of the generated type in the session under the token "<ObjectName>DisplayRecords.<objectName>Beans", and you can <jsp: include> (or AJAX in) this JSP file wherever you need it.
     

  • <ObjectName>Form.jsp: This JSP is what renders the HTML form representing an editable row in the table. This JSP behaves slightly differently depending on whether it is in "Edit" mode or "AddNew" mode. Text fields are limited in maxlength by the size of the VARCHAR definition (for String fields). Dates are displayed with a simple default format that is easily changed. Enumerations are automatically rendered as a <select> drop-list.
     
  • <ObjectName>Submit.java: This servlet is what gets called when the "Save" buttons are clicked. It receives the POSTed form data and processes each incoming field into the bean class. Size limits are checked for VARCHAR fields, and automatically truncated as a default. Comments are inserted to suggest to the programmer to consider what kinds of validations, edits, range-checks, etc. ought to be performed for each incoming attribute. Enumerated attributes are automatically checked for valid values. Decimals are treated as currency amounts as a default, and Dates are parsed in the same default as they are displayed. Again, these are meant as simple defaults in order to produce a working prototype, but they are easily changed.

    Each attribute is grouped together in the servlet code with a comment-header to easily identify it. Lastly, the servlet performs an update or insert, depending on whether this is an "Edit" or "AddNew" context. It then forwards to the <ObjectName>DisplayRecords servlet, which will re-fetch the records from the database, update the List of beans in the session, and ultimately forward to the <ObjectName>DisplayRecordsTable.jsp to re-render the table.
     

  • <ObjectName>Edit.java: When an "Edit" button is clicked, this servlet is called with a parameter indicating which index the particular record is located in the List of beans. It uses this parameter to retrieve the specific bean from the List of beans in the session, and then places this bean as a separate object in the session under the token "<ObjectName>Edit.<objectName>Bean", and then forwards to the <ObjectName>Form.jsp with a parameter to tell the form JSP that this is an Edit operation.
     
  • <ObjectName>Delete.java: When a "Delete" button is clicked, this servlet is called with a parameter indicating which index the particular record is located in the List of beans. It uses this parameter to retrieve the specific bean from the List of beans in the session, and then makes the DAO call to delete it from the database. It then forwards to the <ObjectName>DisplayRecords servlet, which will re-fetch the records from the database, update the List of beans in the session, and ultimately forward to the <ObjectName>DisplayRecordsTable.jsp to re-render the table.
     
 
Summary
The generated components are the result of years of lessons learned and best-practices, and by using it as a starting point for your development, you will establish a solid, well-architected, working prototype from which you can easily override and/or extend behavior and design, while at the same time avoiding many pitfalls and potential bugs.

For example, each row in the rendered table is really a single <td> element that has a nested table in it, and this table is wrapped in a <span> element. This is necessary because standard HTML does not permit modifying the .innerHTML property of <tr> elements (a very common mistake made by web programmers). Another example: once an Edit button has been clicked to open up a row in the table for editing, the rest of the buttons on the page are disabled to prevent the user from clicking something that could result in confusing the state of the page, or an awkward presentation for the user. Javascript functions, HTML buttons, <span> tags, etc. are all named logically and concisely so as to prevent naming conflicts in the event that this code is merged in with other components or included in other JSPs. Try-catch blocks are used in all Servlets and JSPs, and the default error reporting can be easily overwritten with whatever logging solution you prefer.

Care has been taken to produce simple, transparent, and explicit code that makes as few assumptions as possible about the skill-sets of the developers who will be reading and manipulating it, and also requires no exotic or expensive plug-ins, .jar files, or third-party tools. As such, the resulting code from POJO Jenerator adheres to the POJO principle, and can even be used as a teaching device for new developers. Yet the code is very efficient, occupies a small footprint, and executes very quickly - all of which amounts to very high scalability. The generated architecture and code from POJO Jenerator has been tested in environments with thousands of concurrent users, and performed exceptionally well.

POJO Jenerator is not meant to be a panacea solution. Like most toolsets, this generator simply provides a starting point from which to customize and extend to accommodate your specific development needs. By following the patterns and software architecture of the generated code, you will produce web-applications that are well-formed, high-performance, efficient, usable, and scalable, yet also plainly readable, understandable, and maintainable by any Java developer with even a moderate level of experience.

 


© Copyright 2007-2024 TimeChannels. All rights reserved.
Site Map