I have been using Hibernate JPA, with a Java Generics based data access layer for some time now. But each time I go to a new project, I find that I have to do quite a bit of rework just to integrate this component. So what I wanted to do, is find a way to create a separate component, that was fully tested, but could be included into a project specific component for each new project, with minimal duplication and hassle.
Required Configuration files:
The required configuration files where:
- META-INF/persistence.xml: JPA Configuration
- applicationContext-common-data-services.xml: common DAO declarations
- application-jpa.xml: Spring, JPA and Hibernate declarations
- hibernate.cfg.xml: Hibernate properties
I wanted to include all the configuration files that where required into the common-data-services jar, but found that persistence.xml was required to build and test, so I had to exclude it from the final jar in my pom.xml :
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <configuration> <strong><excludes> <exclude>**/persistence.xml</exclude> </excludes></strong> </configuration> </plugin>
I did this, because if I left this in the common-data-services jar, then any project specific jar would not be able to add inherited domain objects. The other 3 configuration files could be included in this jar
Required Java Files:
The required Java files where:
- src/main/java/com.**.dao.*: Generics based Data Access Object
- src/main/java/com.**.domain.*: Annotated
- src/test/java/com.**.dao.jpa.*: DAO specific test cases
- src/test/java/com.**.domain.*: Domain specific test cases
I did this, because if I left this in the common-data-services jar, then any project specific jar would not be able to add inherited domain objects. Such as, I wanted all users of this component to have:
- IdentifiedObject: Base Class for all domain Objects
- IdentifiedObjectListener: Listener for IdentifiedObject class.
- StringIdentifiedObject: Base Class for all String Identified domain Objects
- StringIdentifiedObjectListener: Listener for StringIdentifiedObject class.
I was trying to have something that was reusable to where projects did not have to re-create the wheel each time they wanted to implement data services.
Now, when I create a project specific data-services component, I can then just add the common-data-services as a dependency:
<dependency> <groupId>com.baselogic.services</groupId> <<strong>artifactId>common-data-services</artifactId></strong> <version>3.0-SNAPSHOT</version> <scope>compile</scope> </dependency>
When I create the component, can see her, that I only need the META-INF/persistence.xml
In the project specific persistence.xml, I had to add the classes from my common-data-services jar, so those tables would get created by Hibernate
<persistence-unit name="ApplicationEntityManager" transaction-type="RESOURCE_LOCAL"> <!-- It appears that in order to create additional tables from other JAR's, we need to declare them here. --> <strong><class>com.baselogic.domain.User</class></strong> <class>com.baselogic.domain.security.Authority</class> <class>com.baselogic.domain.security.UserDetails</class>
I did include an src/main/resources/import.xml in this module. This way, after the common-data-services classes are included, and my project data services TABLES where create by hibernate, I can add reference data here to seed my database for testing purposes.
It is easy to include all common data service code into a reusable component(jar), then leverage that in a project specific data services implementation. The only duplication is to add a persistence.xml into teh common-data-services component, but exclude it from the final package.