As mentioned in the introductory post, in order to minimize the risk, the first phase of the ATG Retirement project was to replace all ATG Dynamo data layer components. New data layer was implemented using the Hibernate JPA implementation.
Loading Spring Context
Since, during the first phase, we had a mixed mode (ATG Dynamo application with JPA data layer implemented using Hibernate and Spring) the first task was to enable ATG application to access new data layer beans.
For this purpose, a new class SpringLoader was created. This was a typical Dynamo service component, which loaded the Spring context during initialization. All Spring beans were exposed by the SpringLoader with simple getter methods. This enabled us to inject Spring beans into the Dynamo components using the following pattern:
In order to load the Spring context a ContextSingletonBeanFactoryLocator class was used with the pattern “classpath*:**/beanRefFactory.xml”.
ATG Dynamo ORM
ATG Dynamo contains two ORM frameworks: Repository Items and Relational Views.
Relational Views use *.rvw configuration files, that contain mappings between database and Java beans and named queries and functions defined using Dynamo specific query language RQL. Beside other features Dynamo relational views support complex properties containing other relational views.
Dynamo Repository Items, on the other side, are not Java beans. Dynamo uses a Map implementation for repository item and data mappings is defined in *.xml configuration files. Beside other features Dynamo repository items support complex properties containing other Repository Item, inheritance and default values for properties.
Porting Dynamo Relational Views to JPA
The first step was to annotate existing relational view beans with JPA annotations. After that, named queries defined in the relation view files were moved to the entity classes as named queries using JPQL. In most cases, this was a straight forward task, however, careful consideration had to be made when Relational View mapped several tables together into one bean, using join operations, or when some property was of complex type, containing another relational view.
Depending on the type of join a simple JPA @SecondaryTable annotation was used, alone or accompanied with Hibernate annotations that supported optional secondary tables (used in left join scenarios). Other case was when a property of a Relational View was of Relational View type, so depending on the context one of the JPA relational annotations were used: @ManyToOne, @OneToMany, etc.
Porting Dynamo Repository Items to JPA
For Dynamo repository items, conversion to JPA was similar to previous case. Main difference was that JPA entity class was to be created from scratch based on the repository XML mapping files. Some additional JPA annotations were also used, mainly for inheritance, and @PrePersist annotation for injecting default values.
Testing New JPA Data Manager Classes
After converting Dynamo data layer to the new JPA implementation, a thorough testing was performed for each data manager. In order to ensure identical behavior of the old Dynamo data manager components and new Spring/JPA data manager beans, a comparison of the results of the two managers was made for a given set of input arguments.
The first step was to determine the representative values for the input arguments of each data manager method. Special emphasis was put on the boundary cases. Once this set was determined, a JUnit test was created to produce an XML describing those values and results of the execution of the old Dynamo data managers.
The last step was to create a JUnit test which invokes the new data manager beans based on the argument values from the XML and then compares the results of the execution with the ones stored in the XML.
This enabled automated JUnit testing of the new data manger beans and ensured that the results of the new managers were the same as earlier.