About
HyperJaxb is a Jaxb plugin that creates classes that are:
- JAXB-enabled (thanks to the JAXB schema compiler)
- and JPA-enabled (thanks to the Hyperjaxb3 Jaxb plugin)
HyperJaxb permits then to have Jaxb + Jpa in one API.
JAXB vs. JPA - JAXB is not 100% compatible with JPA
Hyperjaxb3 is a code generator. It provides a JAXB 2 plugin which participates in JAXB's code generation - and produces all necessary JPA annotations as well as the supporting code to make the class JAXB and JPA compatible.
Articles Related
Prerequisites
Data
From the XML Schema Primer, download the purchase order schema example:
- the sample data XML file: po.xml
Project Structure
Download the basic project templates for Ant (hyperjaxb3-ejb-template-basic-0.5.6-ant-src.zip)
Steps
Directory Structure
- Unpack the basic project templates and import it into an Eclipse Java project
- Add the content of the lib directory in your class path
- Put your schema (*.xsd) and binding files (*.xjb) into src/main/resources.
- Put your XML samples (*.xml) into src/test/samples.
Run the build
- Run mvn clean install for Maven or ant clean install for Ant.
ant clean install
Buildfile: D:\workspace\HyperJaxb2\build.xml
clean:
generate-sources:
[mkdir] Created dir: D:\workspace\HyperJaxb2\target\generated-sources\xjc
[xjc] Consider using <depends>/<produces> so that XJC won't do unnecessary compilation
[xjc] Compiling file:/D:/workspace/HyperJaxb2/src/main/resources/po.xsd
[xjc] Writing output to D:\workspace\HyperJaxb2\target\generated-sources\xjc
compile:
[mkdir] Created dir: D:\workspace\HyperJaxb2\target\classes
[javac] D:\workspace\HyperJaxb2\build.xml:142: warning: 'includeantruntime' was not set, default
ing to build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 5 source files to D:\workspace\HyperJaxb2\target\classes
[copy] Copying 3 files to D:\workspace\HyperJaxb2\target\classes
test-compile:
[mkdir] Created dir: D:\workspace\HyperJaxb2\target\test-classes
[javac] D:\workspace\HyperJaxb2\build.xml:158: warning: 'includeantruntime' was not set, default
ing to build.sysclasspath=last; set to false for repeatable builds
[javac] Compiling 5 source files to D:\workspace\HyperJaxb2\target\test-classes
[copy] Copying 3 files to D:\workspace\HyperJaxb2\target\test-classes
test:
[mkdir] Created dir: D:\workspace\HyperJaxb2\target\junit-reports
[junit] Running RoundtripTest
[junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 1.372 sec
package:
[jar] Building jar: D:\workspace\HyperJaxb2\target\hyperjaxb3-ejb-template-basic-ant-0.5.6.jar
install:
BUILD SUCCESSFUL
Total time: 9 seconds
Check generated content
We got produced from the XJC schema compiler and Hyperjaxb3 plugin:
- a set of Java files containing both JAXB and JPA annotations.
The class contains @Entity, @Table, @ManyToOne and few other annotations generated by the Hyperjaxb3 plugin. These annotations turn this class into an entity which can be persisted with JPA.
- a JPA persistence unit description in META-INF/persistence.xml in target/generated-sources/xjc which contains the generated entities.
Persistence.xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence version="1.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd
http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<persistence-unit name="generated">
<class>generated.Items</class>
<class>generated.Items$Item</class>
<class>generated.PurchaseOrderType</class>
<class>generated.USAddress</class>
</persistence-unit>
</persistence>
Source Script
Jaxb
- Creation of an instance of JAXB context with a JAXBContext.newInstance(…) call passing the context path. The context path is typically the package name of the generated classes.
// Context with the package name of the generated class as parameter
context = JAXBContext.newInstance("generated");
// A context with the class name of the root element is also possible
context = JAXBContext.newInstance(PurchaseOrderType.class);
- Creation of the Unmarshaller which call an unmarshall action
// Creation of an Unmarshaller
final Unmarshaller unmarshaller = context.createUnmarshaller();
// The Unmarshaller unmarshal
final Object object = unmarshaller.unmarshal(new File("src/test/samples/po.xml"));
- Cast of the object to retrieve the good type and test
// With a cast, we retrieve the final object (data type)
@SuppressWarnings("unchecked")
final PurchaseOrderType purchaseOrder = ((JAXBElement<PurchaseOrderType>) object).getValue();
// Test
System.out.println("Purchase Order Comment "+purchaseOrder.getComment());
An instance of the generated ObjectFactory is only needed to create objects (to marshall).Jpa
Creation of an entity manager factory by passing:
- the name of persistence unit (see META-INF/persistence.xml above)
- a properties file (in the resource persistence.properties) to define the database-specific properties
You can define the database connection in the persistence unit itself but to keep ORM mappings should be generic, case-specific. They are be kept separately.
final Properties persistenceProperties = new Properties();
InputStream is = null;
try {
is = getClass().getClassLoader().getResourceAsStream("persistence.properties");
persistenceProperties.load(is);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ignored) {
}
}
}
entityManagerFactory = Persistence.createEntityManagerFactory(
"generated", persistenceProperties);
persistence.properties
persistence.properties are database and JPA provider specific. See: JPA - Persistence Properties
Code
/**
*
*/
package main.java;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import generated.ObjectFactory;
import generated.PurchaseOrderType;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
/**
* @author gerard
*
*/
public class Main {
private static JAXBContext context;
private static EntityManagerFactory entityManagerFactory;
/**
* @param args
* @throws JAXBException
* @throws IOException
*/
public static void main(String[] args) throws JAXBException, IOException {
context = JAXBContext.newInstance("generated");
new ObjectFactory();
// Unmarshaller
final Unmarshaller unmarshaller = context.createUnmarshaller();
// Unmarshal
final Object object = unmarshaller.unmarshal(new File("src/test/samples/po.xml"));
// Cast
@SuppressWarnings("unchecked")
final PurchaseOrderType purchaseOrder = ((JAXBElement<PurchaseOrderType>) object).getValue();
System.out.println("Purchase Order Comment "+purchaseOrder.getComment());
final Properties persistenceProperties = new Properties();
InputStream is = null;
try {
is = new FileInputStream("src/resources/persistence.properties");
persistenceProperties.load(is);
} finally {
if (is != null) {
is.close();
}
}
System.out.println("Url "+persistenceProperties.getProperty("hibernate.connection.url"));
entityManagerFactory = Persistence.createEntityManagerFactory(
"generated", persistenceProperties);
final EntityManager saveManager = entityManagerFactory
.createEntityManager();
saveManager.getTransaction().begin();
saveManager.persist(purchaseOrder);
saveManager.getTransaction().commit();
saveManager.close();
final Long id = purchaseOrder.getHjid();
System.out.println("Purchase Order Id "+id);
}
}
Resultaat
Script output
Purchase Order Comment Hurry, my lawn is going wild!
Url jdbc:oracle:thin:@//localhost:1521/orcl.HotITem.local
Purchase Order Id 1
Database
More
Documentation / Reference
Support
javax.xml.bind.UnmarshalException: unexpected element (uri…
The fact that it doesn't unmarshal, is clear in the error message: it expects a no-namespace element <{}Repository> as opposed to <{uri:“http://www.oracle.com/obis/repository”}Repository>.
Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.oracle.com/obis/repository", local:"BusinessModel"). Expected elements are <{}Repository>
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:662)