Entity Versioning in AppFuse

Posted by Martin Homik | Posted in Java, WebApp | Posted on 26-03-2008

0

It’s time to write a few words about some things I have learned in the past week. The first thing I want to mention is versioning. So far, whenever I updated and persisted objects to the database, I calculated the modified time myself which is not that bad. But persistence layers such as Hibernate actually can do that for you. To prevent two users from writing to the database at the same time, locking techniques are provided. One such technique is called optimistic locking which is implemented by using versioning either with integers or with timestamps. If you select timestamps, the only thing you have to do is to specify which of the entity fields is supposed to be in charge of the version. Add a @Version JPA annotation to the field. Any persistence framework that is compliant to JPA will calculate the modified data for you and persist it to the database.

Find more explanations here and here.For Hibernate users the Java Persistence with Hibernate Book is the best choice.

The drawback of this approach is that once you edit an object, Hibernate creates a new revised object instead of altering the actual one. That’s a pity and does not serve my purpose in a current project. I am confused, because the book Hibernate in Action describes the versioning process differently: alterations are updates and no inserts. I am not able to resolve this issue.

Java Data Binding / Data-driven approach

Posted by Martin Homik | Posted in Java, Semantic Web, WebApp | Posted on 04-12-2007

0

I have to write this article for myself, because I am very forgetful. In a world dominated by so many technical terms and products it is not easy to find the right sources and solution. In my case, the following scenario is present: I want to have a web application including a database storage and remote services. This incorporates a set of classes, a database schema and a XML representation of my data model. In addition, the xml representation can comply to some well-known XSD standard or it can be formulated in some Semantic Web language such as OWL. Because so many components interact with each other they share a common data model but each component uses its own representation of the information.

  • The relation database uses a database schema formulated in SQL
  • The Java classes comply to a Java specification.
  • Semantic Triple stores base on RDFS and/or on OWL
  • Web Services communicate via WSDL.
  • And finally there also exist XSD definitions of a data model for interoperability.

The ultimate question is, how can I select one representation and generate all other representations? This approach is data-driven.

Hibernate Tools allow to create a set of POJOs from a database schema and vice versa a database schema from a set of JPA annotated classes. AppFuse applies HibernateTools for database creation from POJOs. POJOs also serve as sources for generation of WSDL files. Java XML Binding frameworks such as JAXB, JaxMe, or XMLBeans help to create POJOs from XSD files. POJOs created by these tools can be streamed to XML files that correspond to the origin XSD. And finally, RDFReactor can take an OWL file and create a POJO which can be used for persisting into a triple store.

So, you see the flow is not easy, as it is interrupted. While you can create POJOs with Java XML Binding tools, these POJOs are not annoted by JPAs such that an automatic generation of a database schema is not possible. In any case, if a solution exists that unifies all streams then it should be an easy-to-use approach. And this is hard to find.

Java XML Binding:

  • JAXB This is a reference implementation. There is a lot action here and the hige community.
  • JaxMe 2 In my opinion, this started as an ambitious project but lost much motivation. I do not know whether it cas been stopped, but the last news message is from 2006. A pity, because it delivered a “complete” approach tying POJOs/Beans, XML files, and (XML) databases together.
  • XMLBeans Though still one of the most active projects, I always considered this as a package monster. Good for Java/XML Binding.
  • Castor provides Java-to-XML binding, Java-to-SQL persistence, and more.
  • JibX is a fast Java XML Binding framework.

Java Database Binding:

Java RDF/OWL Binding:

  • Jastor This an open source Java code generator that emits Java Beans from Web Ontologies (OWL) enabling convenient, type safe access and eventing of RDF stored in a Jena Semantic Web Framework model. As mentioned it is programmed against Jena making an application dependent on a particular RDF Triple Store.
  • RDFReactor RDFReactor views the RDF data model through object-oriented Java proxies. It makes using RDF easy for Java developers. It is independent of a specific RDF store. It is still under development and rather a research project.

Application Frameworks

Further Reading:

AppFuse: Switching database from MySQL to PostgreSQL

Posted by Martin Homik | Posted in Java, WebApp | Posted on 04-12-2007

2

Yesterday, I tried to run my AppFuse application with PostgreSQL instead of MySQL. I ran into a CLEAN_INSERT problem which was a result of an earlier mistake. In MySQL I used a longtext type for a description field. This type corresponds to a column JPA annotation having a length attribute with the value ‘2147483647′. Obviously, this value is too high. Note, the storage required for a ‘longtext’ is L + 4 bytes, where L < 2^32. According to PostgreSQL documentation “the longest possible character string that can be stored is about 1 GB”.

In a first solution, I removed the length attribute from the JPA annotation. PostgreSQL creates per default a “character varying(255)” data type with a fixed limit of 255 characters. On the database level, it is possible to omit the limit value, the system takes then the maximum value. But, I do not know how to specify this in a JPA annotation. Anyway, now, my AppFuse runs with PostgreSQL, too.

This was quite a bit of ’small-steps’ work.

Funny Exception

Posted by Martin Homik | Posted in Java, WebApp | Posted on 12-10-2007

0

This one made me laughing!!!


Sapperlott Exception

AppFuse: JPA Entity Inheritance

Posted by Martin Homik | Posted in Java, WebApp | Posted on 27-07-2007

0

Motivation. Originnaly, I picked up an approach from Semantic Web and RDF(s) where everything is a Thing and everthing else derives from that base class. In my current application, I wanted to have a base pojo class and other classes were supposed to extend that class. Since I am still new to this AppFuse and application frameworks, I had to get familiar with persistency and AppFuse in the context of entity inheritance following the try-and-error style. Here are my results.

Reading. Using google and folling discussions in AppFuse forums I collected a bunch of links. The most valuable are listed below:

Strategies. There are three strategies for entity inheritance: Single Table per Class Hierarchy, Table per Concrete Class, and Joined Subclass.

Single Table per Class Hirarchy. This is the default strategy. All classes in the hirerarchy are mapped to a single table in the database. If you have a deep hierarchy, you might end up having a table with many columns. With respect to memory resources this might be not the best choice, but it is runtime efficient and quite easy to program. To use this strategy, you have to apply the inheritance annotation in the root class. You might also want to stick to the default discriminator name (“DTYPE”) and discriminator type (String). Otherwise change it. Every class in the hierarchy should define a discriminator value which identifies the class in the table row. Here is how you code it.

  1.  
  2.    @Entity
  3.    @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
  4.    @DiscriminatorValue("base")
  5.    @Table(name = "single_table")
  6.    public class BaseInheritEntitySingleTable extends BaseObject {
  7.  
  8.     private Long id;
  9.     private String baseText;
  10.  
  11.    …
  1.  
  2.    @Entity
  3.    @DiscriminatorValue("extend")
  4.    public class ExtendInheritEntitySingleTable extends BaseInheritEntitySingleTable {
  5.  
  6.     private String extendedText;
  7.  
  8.    …

To test whether the database schema has been set up properly type ‘mvn hibernate3:hbm2ddl’. If you want to insert values using dbunit, modify your sample-data.xml, like follows:

  1.  
  2. <!–BaseInheritEntitySingleTable-START–>
  3. table name="single_table"><column>id</column>
  4.       <column>base_text</column>
  5.       <column>DTYPE</column>
  6.    <row>
  7.       <value description="id">1</value>
  8.       <value description="base_text">Base text 1</value>
  9.       <value description="DTYPE">base</value>
  10.    </row>
  11.    <row>
  12.       <value description="id">2</value>
  13.       <value description="base_text">Base text 2</value>
  14.       <value description="DTYPE">base</value>
  15.    </row>
  16.    <row>
  17.       <value description="id">3</value>
  18.       <value description="base_text">Base text 3</value>
  19.       <value description="DTYPE">base</value>
  20.    </row>
  21.  
  22. <!–BaseInheritEntitySingleTable-END–>
  23.  
  24. <!–ExtendInheritEntitySingleTable-START–>
  25. <table name="single_table"><column>id</column>
  26.       <column>base_text</column>
  27.       <column>extended_text</column>
  28.       <column>DTYPE</column>
  29.    <row>
  30.       <value description="id">4</value>
  31.       <value description="base_text">E-Base text 1</value>
  32.       <value description="extended_text">Extended text 1</value>
  33.       <value description="DTYPE">extended</value>
  34.    </row>
  35.    <row>
  36.       <value description="id">5</value>
  37.       <value description="base_text">E-Base text 2</value>
  38.       <value description="extended_text">Extended text 2</value>
  39.       <value description="DTYPE">extended</value>
  40.    </row>
  41.    <row>
  42.       <value description="id">6</value>
  43.       <value description="base_text">E-Base text 3</value>
  44.       <value description="extended_text">Extended text 3</value>
  45.       <value description="DTYPE">extended</value>
  46.    </row></table>
  47. <!–BaseInheritEntitySingleTable-START–>

Run ‘mvn test-compile’ to fill the tables with values from your sample-data.xml.

 

Table per Class. Using this strategy means that each class in the hierarchy is mapped to its own table in the database. It provides poor support for polymorphic relationships and usually requires SQL UNION queries. Hence, it is not recommended. However, here are the JPA annotations:

  1.  
  2.    @Entity
  3.    @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
  4.    @Table(name = "base_table_per_class")
  5.    public class BaseInheritEntityTablePerClass extends BaseObject {
  6.  
  7.     private Long id;
  8.     private String baseText;
  9.  
  10.    …
  1.  
  2.    @Entity
  3.    @Table(name = "extend_table_per_class")
  4.    public class ExtendInheritEntityTablePerClass extends BaseInheritEntityTablePerClass {
  5.  
  6.     private String extendedText;
  7.  
  8.    …

Run ‘mvn hibernate3:hbm2ddl’ to create the database schema.

  1.  
  2. <!–BaseInheritEntityTablePerClass-START–>
  3. <table name="base_table_per_class"><column>id</column>
  4.         <column>base_text</column>>
  5.     <row>
  6.         <value description="id">1</value>
  7.         <value description="base_text">Base Text 1</value>
  8.     </row>
  9.     <row>
  10.         <value description="id">2</value>
  11.         <value description="base_text">Base Text 2</value>
  12.     </row>
  13.     <row>
  14.         <value description="id">3</value>
  15.         <value description="base_text">Base Text 3</value>
  16.     </row></table>
  17. <!–BaseInheritEntityTablePerClass-END–>
  18. <!–ExtendedInheritEntityTablePerClass-START–>
  19. <table name="extend_table_per_class"><column>id</column>
  20.         <column>base_text</column>
  21.         <column>extended_text</column>
  22.     <row>
  23.         <value description="id">1</value>
  24.         <value description="base_text">E-Base Text 1</value>
  25.         <value description="extended_text">Extended Text 1</value>
  26.     </row>
  27.     <row>
  28.         <value description="id">2</value>
  29.         <value description="base_text">E-Base Text 2</value>
  30.         <value description="extended_text">Extended Text 2</value>
  31.     </row>
  32.     <row>
  33.         <value description="id">3</value>
  34.         <value description="base_text">E-Base Text 3</value>
  35.         <value description="extended_text">Extended Text 3</value>
  36.     </row></table>
  37. <!–ExtendedInheritEntityTablePerClass-END–>

Run ‘mvn test-compile’ to populate your database schema with data from your sample-data.xml.

 

Joined Subclass Strategy. The root of the class hierarchy is represented by a single table, and each subclass has a separate table that only contains those fields specific to that subclass. The tables are joined using the same primary key names but the primary key of the extended class is also a foreign key to its superclass. In our case, it is ‘id’. This strategy provides good support for polymorphic relationships , but requires join operations to be performed when instantiating entity subclasses. This may result in poor performance for extensive class hierarchies.

  1.  
  2.    @Entity
  3.    @Inheritance(strategy=InheritanceType.JOINED)
  4.    @Table(name = "base_joined_table")
  5.    public class BaseInheritEntityJoined extends BaseObject {
  6.  
  7.        private Long id;
  8.        private String baseText;
  9.  
  10.        …
  1.  
  2.    @Entity
  3.    @Table(name = "extended_joined_table")
  4.    public class ExtendInheritEntityJoined extends BaseInheritEntityJoined {
  5.  
  6.        private String extendedText;
  7.  
  8.    …

Create the database schema using ‘mvn hibernate3:hbm2ddl’. To populate the database with data add to your sample-data.xml:

  1.  
  2. <!–BaseInheritEntityJoined-START–>
  3. <table name="base_joined_table"><column>id</column>
  4.         <column>base_text</column>
  5.     <row>
  6.         <value description="id">1</value>
  7.         <value description="base_text">Base text 1</value>
  8.     </row>
  9.     <row>
  10.         <value description="id">2</value>
  11.         <value description="base_text">Base text 2</value>
  12.     </row>
  13.     <row>
  14.         <value description="id">3</value>
  15.         <value description="base_text">Base text 3</value>
  16.     </row>
  17.     <row>
  18.         <value description="id">4</value>
  19.         <value description="base_text">E-Base text 1</value>
  20.     </row>
  21.     <row>
  22.         <value description="id">5</value>
  23.         <value description="base_text">E-Base text 2</value>
  24.     </row>
  25.     <row>
  26.         <value description="id">6</value>
  27.         <value description="base_text">E-Base text 3</value>
  28.     </row></table>
  29. <!–BaseInheritEntityJoined-START–>
  30. <!–ExtendInheritJoined-START–>
  31. <table name="extended_joined_table"><column>id</column>
  32.         <column>extended_text</column>
  33.     <row>
  34.         <value description="id">4</value>
  35.         <value description="extended_text">Extended text 1</value>
  36.     </row>
  37.     <row>
  38.         <value description="id">5</value>
  39.         <value description="extended_text">Extended text 2</value>
  40.     </row>
  41.     <row>
  42.         <value description="id">6</value>
  43.         <value description="extended_text">Extended text 3</value>
  44.     </row></table>
  45. <!–BaseInheritEntityJoined-START–>

Type ‘mvn test-compile’.

 

Tips.

  • Delete the database schema whenever you are in a prototype try-and-error programming process. You’ll avoid a bunch of errors you might not be able to explain, because your changed code has not be propagated to the database schema or whatever. Starting with a clean database filters unnecessary discractions.
  • Turn off foreign key validation as dbunit causes errors. It’s not the best step, but you will be able to compile and run your application. See here.
  • Be aware that fields in sub classes are by default nullable. Otherwise, you have to define a default value. I am not sure whether this is the best solution, but I usually assign a default value right after declaration of the field.

Open questions.

  • AppFuse seems to complain about a missing primary key when you derive an abstract class from BaseObject and and extend the abstract class by a concrete class. So far I have no explanation for this.
  • Is it possible to overwrite the primary key entity?
  • What about compund primary keys?
  • So far, I have been working only at the maven-dbunit level. That is, I have not tested anything with DAOs and Managers. This could be the next step.
  • I have not tested hierarchies deeper than one level.

 

Conclusion. In the process of going through this brief tutorial I relaised that Entity Inheritance might not be the best approach. I guess, I will stick to relationships as they provide me with more flexibility. There will be still a base class ‘Thing’, but other classes won’t derive from it. Saying this, the alternative would be to establish a OneToOne relationship between a class and its assumed “super” ‘Thing’ class. I wonder if this is different from the Joined Subclass Strategy?

AppFuse: removing auto-generated classes

Posted by Martin Homik | Posted in WebApp | Posted on 12-07-2007

0

AppFuse is an application-framework based on the latest software developments. One extremely useful feature is automatic generation of code (snippets) from POJO classes. Unfortunately, there is no auto-deinstall function. So once, you have generated and installed code automatically, you have to remove the code snippets by hand.Here is a short description how to proceed. Let’s assume, you did not go through the full “Person” tutorial. Instead you implemented a POJO class including annotations and ran ‘mvn appfuse:gen|install -Dentity=Person’. To remove “Person” from project you have to delete:

  • src/main/java/**/model/Person.java
  • src/main/java/**/model/webapp/action/PersonAction.java
  • src/test/java/**/model/webapp/action/PersonActionTest.java
  • src/main/resources/**/model/Person-validation.xml
  • src/main/resources/**/webapp/action/PersonAction-validation.xml
  • src/main/webapp/WEB-INF/pages/personForm.jsp
  • src/main/webapp/WEB-INF/pages/personList.jsp

Remove “Person” related entries from the following files:

  • src/main/resources/hibernate.cfg.xml Delete mapping to Person modell class.
  • src/main/resources/struts.xml Delete all Person actions.
  • src/main/resources/ApplicationResources.properties Delete properties related to Person. Also delete properties inside other languages.
  • src/main/webapp/common/menu.jsp Delete entry for Person
  • src/main/webapp/WEB-INF/applicationContext.xml Delete Person related beans.
  • src/main/webapp/WEB-INF/menu-config.xml Delete Person section.
  • src/test/resources/sample-data.xml Delete Person mockup data.
  • src/test/resources/web-tests.xml Delete Person Canoo web test data. Don’t forget to delete PersonTests in the top target.