Trap The Spark…

December 28, 2008

Persistence Layer

Gregari’s persistence layer consists of the following:

  • Database schema 
  • Value objects written as EJB3 Entity objects (mapped to the database via Java Persistence/Hibernate 3 annotations)
  • DAO (Data Access Objects) written as EJB3 SSB (Stateless Session Beans)

Value Objects - The value objects are generated using the Castor XML open source project and XML Schemas.  This was done as its relatively quick to model objects using a single file (XML Schema) and generate the following:

  • classes
  • attributes
  • attribute getters/setters
  • XML  marshal/unmarshal code
  • simple field validation
  • etc.    

Castor XML – Using Castor XML and XSD’s (XML Schema files) XML elements are mapped to Java classes, XML attributes are mapped to Java properties, XML element relationships (with other XML elements) are mapped to collections of objects (1:1 or 1:n depending the design).  So if your familiar with XML Schemas… Gregari is taking full advantage of the XSD specifications.  Castor XML is merely taking the XSD’s and generating Java classes.  The normal Castor XML configuration is leveraged, i.e.

  • Mapping XML namespaces to Java packages
  • configuring which type of collections to be used
  • create a “hashcode” method (true)
  • create an “equals” method (true)
  • inherit from a common base class
  • etc.

All of this can be seen in the castorbuilder.properties file specification from Castor XML

Components - From a modeling perspective … there’s components (logical groupings of objects).  In Gregari a single XML Schema is mapped 1:1 with a component.  Within the XSD file are the component’s objects as well as relationships to each object (where applicable).  Furthermore by using XDoclet2 tags within the XSD description element, the XDoclet annotations will be generated in the class, attribute and/or method JavaDoc comment sections.  XDoclet annotations that are used include those for Hibernate as well as some Gregari-custom XDoclet tags.  By adding the XDoclet tags… a post processor (custom written leveraging XDoclet’s parsing capabilities) will transform the Castor generated JavaBeans (POJO’s) into EJB3 Entity Beans complete with annotations (both EJB, Java Persistence, Hibernate ORM, Hibernate Search, Hibernate Validations, JBoss Seam, as well as some Gregari specific Java5 Annotations).  In addition to the Gregari XDoclet post-processor (that transforms the POJO’s into EJB3 Entities), Hibernate Tools is used to generate Hibernate configuration/mapping files as well as generate database specific DDL SQL.

Build Process -  To generate value objects… the build process has the following steps:

  • From XSD files generate Java POJO’s using Castor XML Code Generator
  • From POJO’s transform into EJB3 Entities using a Gregari custom XDoclet plugin
  • From EJB3 Entities generate Hibernate configuration/mapping files (to generate DB specific DDL SQL) using Hibernate Tools
  • From Hibernate configuration/mapping files generate DB specific DDL SQL using Hibernate Tools

Gregari Schema component – All of this can be found in the Gregari Schema component.  Child components include the following (their individual mapping to databases is explained below while the database strategy is explained in the Database Strategy blog entry).

  • Common – Contains common XSD files used to generate common POJO’s.
  • Activity – Contains XSD’s specific to the user interface, i.e. metadata signifying what’s present as well as what can/cannot be customized by an application tenant.  These objects are associated with the Metadata database.
  • Audit – Contains XSD’s specific to any objects used to track system usage, i.e. user sessions, user request, user authentication/authorization attempts, data accesses, debug statements, scheduled job audits, etc. These objects are associated with the Audit database.
  • Database – Contains any DDL SQL as well as DbUnit files used to create test data for any unit tests. There are no POJO objects within this component.
  • Etc – Contains XSD’s that specific XML document root elements, i.e. placed in a common place.  Not all root elements are here.
  • Instance – Contains XSD’s specific to any objects used to create multi-tenant data, i.e. notes, addresses, UDF’s, etc.  Presumably this could be placed in a single tenant shard or kept together in a multi-tenant shard. These objects are associated with the Instance database.
  • Metadata – Contains XSD’s specific to signifying what’s present in the system as well as what can/cannot be customized by an application tenant.  Also keeps track of any customizations. These objects are associated with the Metadata database as explained in the Database Strategy blog entry.
  • Reporting – Contains XSD’s specific to the reporting component, i.e. metadata signifying what report categories, reports and report parameters are present. These objects are associated with the Metadata database.
  • Scheduler – Contains XSD’s specific to the scheduler component, i.e. metadata signifying what job categories, jobs, scheduled jobs are present. These objects are associated with the Metadata database.

EJB3 Entity Final Notes - As noted earlier the EJB3 Entities are just basically POJO’s with getter/setter methods, XML marshal/unmarshal methods, and simple field validation.  There is no complex validation nor business logic within these objects as they are generated.  However, they are heavily annotated with Java5 Annotations to trigger behavior via Interceptors, etc.  Furthermore the value objects have no understanding of an underlying persistence mechanism, i.e. they could be mapped against a database or marshaled into XML and sent to an ESB.  Any persistence via a database or an ESB would need to be handled in other objects, i.e. DAO’s, etc.

DAO (Data Access Objects) - DAOs wrap the interaction between the value object and the persistence mechanism’s (in this case Hibernate).  Normally you create a well defined interface and then whatever concrete implementations.  So you could swap out implementations as needed (i.e. talk to the database, or LDAP, or an ESB).  That’s the theory at least.  So in these DAO’s an javax.persistence.EntityManager is injected. This EntityManager is tied with a javax.persistence.PersistenceContext. The PersistenceContext in turn is tied with an underlying database. For Gregari only one EntityManager/PersistenceContext is injected per DAO (this helps as there are multiple databases and want to make sure the right object goes into the right database. The layer above (i.e. BO or Business Object layer) handles the orchestration of multiple DAO’s in a given unit of work.  The BO object is not tied to a specific database, rather it can work with multiple DAO/EntityManager/PersistenceContext tuples.

The DAO’s typically have the following methods:

  • get a list of objects (given any parent ID’s as well as a QBE (query by example) search pattern)
  • get a specific object based on its ID
  • get a specific object based on its business key (code, tenant ID, etc)
  • insert an object
  • update a specific object (for UI’s that drill down into the object details and potentially update its contents)
  • update a set of objects (for UI’s, etc. that support bulk updates)
  • delete a set of objects (for UI’s, etc. that allow multiple deletes)

Generally speaking this is set up for your normal QBE Search (Query By Example) as well as CRUD operations (Create, Read, Update, Delete).  Very specific searches (get this object’s children that are active) can be placed in the BO (with the QBE parameters hardcoded) thus reusing the “get a list of objects” DAO method.  Where reuse doesn’t make sense then create new BO/DAO methods to handle the query.  But ideally the BO objects have far more methods to handle specific business logic than the DAO’s.  If the DAO’s have a lot of methods then… you may need to reconsider your model.  In addition the DAO’s should be reusable across BO’s (sure there might be a BO 1:1 mapping with DAO’s to do CRUD type business logic.  But for more complex business logic… the BO might need multiple DAO’s.

Annotations – The DAO objects don’t have a lot of Java 5 annotations, currently just EJB3 Stateless Session annotations, JBoss Seam annotations and some Azzura Gregari specific annotations for checking that the right tenant’s users are seeing the right data.  The annotations take into account the following concepts, i.e.

  • Provider data – Data that only the SAAS provider should see.
  • Global data – Data that any tenant can see, i.e. metadata regarding the system (entities, attributes/methods/relationships on the entities, etc)
  • GlobalLocal data – Data that normally is global but can be overridden by a particular tenant.  Overridden data should only be visible to the tenant whereas global data should be available to all tenants.  Essentially there could be a mixture of global and local data within the same result set (typically metadata).  An example might be for a status attribute enumeration, i.e. global values would be “active” or “inactive”.  But a tenant might have added “deleted” to satisfy one of their internal needs.
  • Local data – Data that should only be visible to the tenant.

In subsequent blogs I’ll describe the service layer, add some diagrams and code snippets.


December 14, 2008

Java5 Annotations

In building Gregari I’ve tried to leverage two basic concepts

  • Generate as much as I can via Xdoclet (or Castor) at build time, ideally any boilerplate code.
  • Write the rest but leverage abstract classes or Java5 Annotations/Interceptors.

Assuming one is familiar with Java Annotations… prior to the Java 5 release if you wanted to use the annotation concept you could do the following, i.e.

  • at build time use Xdoclet tags @blah.blah-blah my-attribute=”hi” within the JavaDoc section
  • at runtime use Spring AOP Annotations (amongst others) by @@MyAnnotation( my-attribute=”hi”)

But then came Java 5 with built-in annotation support and so I converted all of my Spring annotations over to the Java 5 standard.  But I still had a lot of ugly Xdoclet tags remaining in my code.   After reading Manning’s “Seam In Action”, i.e. http://www.manning.com/dallen/… I was struck on how JBOSS Seam leveraged Java5 Annotations.  So I basically got rid of my mixture of XDoclet tags (for code generation) and Java5 Annotations (for runtime)… and instead went to exclusively Java5 Annotations.  It even sped up XDOCLET2 code generation by approximately a factor of 10.  The downside is perhaps I went overboard… but not sure what else to do…

So I use Java5 Annotations for the following major concepts:

  • Taxonomies – I have two major taxonomies, i.e. to distinguish one type of objects from another (i.e. business objects from data access objects, mainly done for code generation purposes).  The other major taxonomy is for what capabilities the object supports so that any cross cutting Interceptors can act accordingly.  Essentially these taxonomy annotations are “marker interfaces”.  These taxonomy annotations are both at the class and method levels… where appropriate.
  • Metadata – In order to customize/configure/personalize enterprise applications (such as in a SAAS model where you can configure the application… you first need to know what’s possible.  By embedding the code with annotations… it should centralize code/metadata in one place.  As a part of a build process (or other) the code can be parsed and the metadata stored in configuration files, databases, etc.
  •  JEE specific annotations (EJB’s, Transactions, Entities)
  • Hibernate (ORM, Validation and Search)
  • JBOSS Seam specific annotations
  • System management – One of the issues for 24/7 Operations (DFO-Design For Operations) is that developers write the code but operations supports it (yet there’s little hand off between the two groups).  What if development annotated their code to create health models, instrumentation models, task models, etc. so that a management system could be generated to support the code being developed.  Perhaps just another way to support Extreme Programming, i.e. your code is self documenting.  Normally this is just for other developers… but operation/development engineering (i.e. developers who create software to optimize system management) is another audience.
  • Interface generation – A Java best practice is to have all concrete objects implement an interface.  Other objects reference the interface instead of the concrete object.  This allows many cool things, i.e. mock objects, etc.  Normally the interface is hand written but… if the concrete interface were the master… you could generate its supporting interface (assuming this is the first implementation of that interface).  Interface generation would be optional based on if the marker annotations were present or not.  So… this is done at the class level to signify an interface as well as the method level to signify what methods should be included in the interface.
  • Method level behavior, i.e. should encryption/decryption be implemented, caching, user-defined-fields (UDF’s), history, notes, addresses, list of values (enumerated values), security, etc.  JEE Interceptors will detect this and act accordingly.
  • Page level behavior, i.e. by leveraging the Java5 concept of package-info.java’s at the package level, I can implement component level annotations.  All sub-packages presumably are of the same “component”.  And thus my leverage component component level behavior (where applicable).  I use this at the system management level to create statistics by component.

In subsequent blog postings (to this one) I’ll give specific examples of what this looks like.

Theme: Silver is the New Black. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.