Published by Fabian on 15 May 2008 at 03:31 pm
In a current project we are about to collect XML and send them out aggregated each day. Its basically a trivial Task, but keeping it maintainable and extendable for next phase of the project possibly coming is the main requirement.
In the Past I was a regular fan of JOX, which allows you to model your XML as java classes. But at that time you had to do it by hand.
Some time later now JAXB is a really good tool (actually its an API, there is a RI from Sun that also is part of Java 6). It creates Java Classes from XSD. Then only the way to the DB would be your work.
HyperJAXB to the rescue! Originally created to support Hibernate, it now is fully compatible to EJB3/JPA standards. It invokes JAXB generator on the given schema and post processes then the generated classes, making them persistable.
The project offers a complete Maven2 package that does all the tricks for you. just put your XSD inside. fire up the maven build and enjoy these complicated technologies (Maven, XML using JAXB and Java Annotations, ORM using Hibernate and Java Annotations and JPA) doing most of the work for you. All what is left for you is to write a class that does:
//get JAXB Helper to do XML->Object conversion (unmarshalling) Unmarshaller u = JAXBContext.newInstance("demo").createUnmarshaller(); //read the object DemoObject item = (DemoObject) u.unmarshal(new File("\\tmp\\demo.xml")); //get JPA Helper to do Object->DB EntityManager em = Persistence.createEntityManagerFactory("demo").createEntityManager(); //persist the object em.persist(data);
I think this is really, really nice. I liked JAXB and JPA before I found HyperJAXB 3, but now I love them even more. You can start solving the functional issues and stop fighting the infrastructure.
Well not completely, depending on who wrote the XSD, the generated classes and Hibernate tables might look a bit messy. If that bothers you (because you might want use direct SQL from somewhere) you can tweak the XSD to make the result nicer. Either by playing with XSD mechanics (referencing elements, rather than nesting them) or customize the XSD with some HyperJAXB 3 annotations.
there is a new package: hibernate.entitymanager 3.3.2.GA that does not need the workaround below.
Make sure to update the pom.xml of your HyberJAXB project.
Unfortunately there is a small glitch in latest Hibernate packages that had cost me half a day
The hibernate.entitymanager 3.3.1.ga package depends on hibernate 3.2.4ga
But 3.2.4.ga contains a bug that prevents automatically generated PKs from working. This is in the HyberJAXB cases by default true for all objects.
To resolve the issue you need to modify your pom like this:
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-entitymanager</artifactId> <version>3.3.1.ga</version> <exclusions> <!-- Hibernate core 3.2.4.ga is buggy --> <exclusion> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> <version>3.2.4.sp1</version> </dependency>