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

> Procedural Languages > Java

1 - 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.

3 - Prerequisites

3.1 - Data

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

Advertising

3.2 - Project Structure

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

4 - Steps

4.1 - 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.

4.2 - 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

4.3 - 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.

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>
Advertising

5 - Source Script

5.1 - 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).

5.2 - 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);
Advertising

5.3 - persistence.properties

persistence.properties are database and JPA provider specific. See: JPA - Persistence Properties

5.4 - 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);
 
    }
 
}

5.5 - Resultaat

5.5.1 - Script output

Purchase Order Comment Hurry, my lawn is going wild!
Url jdbc:oracle:thin:@//localhost:1521/orcl.HotITem.local
Purchase Order Id 1

5.5.2 - Database

6 - More

7 - Documentation / Reference

8 - Support

8.1 - 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)
lang/java/hyperjaxb.txt · Last modified: 2017/09/06 09:16 by gerardnico