Table of Contents

Java - HyperJaxb - From Xml (Jaxb) to database (Jpa)

About

HyperJaxb is a Jaxb plugin that creates classes that are:

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.

Prerequisites

Data

From the XML Schema Primer, download the purchase order schema example:

Project Structure

Download the basic project templates for Ant (hyperjaxb3-ejb-template-basic-0.5.6-ant-src.zip)

Steps

Directory Structure

Run the build

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

Hyperjaxb Generated Source

We got produced from the XJC schema compiler and Hyperjaxb3 plugin:

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.

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

// 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 an Unmarshaller
final Unmarshaller unmarshaller = context.createUnmarshaller();
// The Unmarshaller unmarshal
final Object object = unmarshaller.unmarshal(new File("src/test/samples/po.xml"));
// 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:

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

Hyperjaxb From Xml To Database

More

See Purchase+Order+Tutorial

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)