Tag Archives: openjpa

Enhance OpenJPA entities with Gradle


OpenJPA has a Maven plugin but doesn’t provide a gradle plugin (yet?) but build-time enhancing is still a nice solution to ensure your entities will behave correctly whatever deployment you choose (in a plain TomEE the built-in javaagent does the work well but in embedded tests it is not guaranteed).

Is that a reason to abandon Gradle? Maybe not yet ;).

Continue reading

OpenJPA and Serialization, or how to replace @AttributeConverter in JPA 2.0


JPA 2.1 introduced the @AttributeConverter annotation. The idea is to be able to implement and map programmatically the serialization of a field.
One typical example today is to use it to be able to use Java 8 new types in its entities such as LocalDateTime. This type is not handled yet by JPA specification (JPA 2.1 was too early).

OpenJPA being still JPA 2.0, you surely think it is not possible to get this feature.
However, by entering a bit in OpenJPA you will realize that it has provided this feature since years!

Of course it uses a vendor API, as all vendor API doesn’t map 1-1 the API introduced in the specification. Yet, the use of it is quite simple, and if you think in term of migration path to JPA 2.1, you’ll see that it’s easy to write a one shot tool to migrate all entities to the standard annotation/implementation (I’ll deal with that point at the end of the post).

Externalize me, Factorize me!

OpenJPA provides two specific annotations for the conversion: org.apache.openjpa.persistence.Externalizer and org.apache.openjpa.persistence.Factory.

The first one is used to convert the instance to the value to serialize in the database. The second
one is the symetric: it reads the serialized value and builds an instance used in the entity.

OpenJPA supports instance method reference as well as static method reference. In this case you can pass the “to convert” value
and StoreContext instance giving you some information on the persistence environment.

Note: to ease later migration and keep converter logic simple, sticking to String in the signature is not a bad idea.

Oops, java serialization, seriously?

At that point, you know you can write some code and wire it in your entity thanks to two annotations. Now:

  • you write your converter,
  • start to execute some JPA statements
  • and you realize that OpenJPA serializes the value you return in your externalizer.

Well, it sounds logic if you return a custom object…but it makes it even for a String.

Actually, it is not really an issue because the field is not fully considered as persistent. If you want it to be
so, then use varchar you have to decorate your column with @org.apache.openjpa.persistence.Persistent instead of storing Blob for String.

Once it is done, you get the varchar column and SQL friendly values.

One sample

Let’s take a simple entity having a long ID and a LocalDateTime field.

Converter logic can be:

public interface LocalDateTimes {
    ZoneId ZONE_ID = ZoneId.systemDefault();

    static String toString(final LocalDateTime time) {
        return time.atZone(ZONE_ID).format(DateTimeFormatter.ISO_DATE_TIME);
    }

    static LocalDateTime fromString(final String time) {
        return LocalDateTime.ofInstant(Instant.from(DateTimeFormatter.ISO_DATE_TIME.parse(time)), ZONE_ID);
    }
}

Our naked entity would be:

@Entity
public class DatedEntity { // + getters/setters
    @Id
    private long id;

    private LocalDateTime created;
}

Now let’s wire our converter:

@Entity
public class DatedEntity {
    @Id
    private long id;

    @Persistent
    @Externalizer("com.rmannibucau.java8.LocalDateTimes.toString")
    @Factory("com.rmannibucau.java8.LocalDateTimes.fromString")
    private LocalDateTime created;
}

And here we are. If you dump the SQL statement used by OpenJPA to create the table, you’ll get:

CREATE TABLE DatedEntity (id BIGINT NOT NULL, created VARCHAR(255), PRIMARY KEY (id))

Note: if you remove the @Persistent annotation you’ll get:

CREATE TABLE DatedEntity (id BIGINT NOT NULL, created BLOB, PRIMARY KEY (id))

and the values would be serialized java.

without modifying entities

OpenJPA supports XML configuration through mapping files for externalizer/factory.

Just use the extended orm schema of openjpa:

<entity-mappings xmlns="http://openjpa.apache.org/ns/orm/extendable" 	xmlns:openjpa="http://openjpa.apache.org/ns/orm" 	xmlns:orm="http://java.sun.com/xml/ns/persistence/orm" 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 	version="2.0">

<entity class="com.github.rmannibucau.domain.DatedEntity">
  <openjpa:attributes>
    <openjpa:persistent name="externalizer"       externalizer="com.rmannibucau.java8.LocalDateTimes.toString"       factory="com.rmannibucau.java8.LocalDateTimes.fromString"/>
  </openjpa:attributes>
</attributes>

</entity-mappings>

Test it!

If you reuse OpenJPARule I talked about in a previous post, you can write a test like:

public class DatedEntityTest {
    @Rule
    public final OpenJPARule $ = new OpenJPARule()
            .types(DatedEntity.class)
            .configure("openjpa.Log", "SQL=TRACE")
            .configure(
                "openjpa.ConnectionFactoryProperties",
                "PrintParameters=true, PrettyPrint=true, PrettyPrintLineLength=80");

    @Test
    public void checkDate() {
        final LocalDateTime now = LocalDateTime.now();

        final DatedEntity de = new DatedEntity();
        de.setId(1);
        de.setCreated(now);

        $.transaction((em) -> {
            em.persist(de);
            return null;
        });
        $.run(EntityManager::clear);

        DatedEntity loaded = $.transaction((em) -> em.find(DatedEntity.class, 1L));
        assertNotNull(loaded);
        assertEquals(now, loaded.getCreated());

        $.transaction((em) -> {
            final DatedEntity entity = em.find(DatedEntity.class, 1L);
            em.remove(entity);
            return entity;
        });
    }
}

The log output looks like:

27  INFO   [main] openjpa.Runtime - Starting OpenJPA 2.4.0
144  INFO   [main] openjpa.jdbc.JDBC - Using dictionary class "org.apache.openjpa.jdbc.sql.HSQLDictionary".
919  INFO   [main] openjpa.jdbc.JDBC - Connected to HSQL Database Engine version 2.2 using JDBC driver HSQL Database Engine Driver version 2.3.2.
1271  TRACE  [main] openjpa.jdbc.SQL - <t 896644936, conn 1050065615> executing prepstmnt 265321659
SELECT SEQUENCE_SCHEMA, SEQUENCE_NAME
    FROM INFORMATION_SCHEMA.SYSTEM_SEQUENCES

1272  TRACE  [main] openjpa.jdbc.SQL - <t 896644936, conn 1050065615> [0 ms] spent
1283  TRACE  [main] openjpa.jdbc.SQL - <t 896644936, conn 270056930> executing stmnt 794075965
CREATE TABLE DatedEntity (id BIGINT NOT NULL, created VARCHAR(255), PRIMARY KEY
        (id))
1284  TRACE  [main] openjpa.jdbc.SQL - <t 896644936, conn 270056930> [1 ms] spent
1554  INFO   [main] openjpa.Enhance - Creating subclass and redefining methods for "[class com.github.rmannibucau.openjpa.java8.DatedEntity]". This means that your application will be less efficient than it would if you ran the OpenJPA enhancer.
1698  INFO   [main] openjpa.Runtime - OpenJPA dynamically loaded the class enhancer. Any classes that were not enhanced at build time will be enhanced when they are loaded by the JVM.
1831  TRACE  [main] openjpa.jdbc.SQL - <t 896644936, conn 633240419> executing prepstmnt 1916575798
INSERT INTO DatedEntity (id, created)
    VALUES (?, ?)
[params=(long) 1, (String) 2015-05-24T09:36:20.229+02:00[Europe/Paris]]
1832  TRACE  [main] openjpa.jdbc.SQL - <t 896644936, conn 633240419> [0 ms] spent
1873  TRACE  [main] openjpa.jdbc.SQL - <t 896644936, conn 1222768327> executing prepstmnt 1193471756
SELECT t0.created
    FROM DatedEntity t0
    WHERE t0.id = ?
[params=(long) 1]
1874  TRACE  [main] openjpa.jdbc.SQL - <t 896644936, conn 1222768327> [0 ms] spent
1938  TRACE  [main] openjpa.jdbc.SQL - <t 896644936, conn 76659128> executing prepstmnt 2032169857
DELETE FROM DatedEntity
    WHERE id = ?
[params=(long) 1]
1941  TRACE  [main] openjpa.jdbc.SQL - <t 896644936, conn 76659128> [2 ms] spent

You can identify the serialized date is correctly bound to the prepared statement:

[params=(long) 1, (String) 2015-05-24T09:36:20.229+02:00[Europe/Paris]]

Preparing to JPA 2.1

This post is already too long to detail the implementation but I’ll try to give the overall idea to easily migrate entities to JPA 2.1 converters if needed.

If you don’t have much entities, don’t waste your time writing any tool. Instead, directly do the migration manually.
I know it may sound obvious, but any tool has an investment in terms of time, and here in particular as you need to write it. Personally, if the migration takes less than 20 minutes by hand, I would go for the manual solution.

If you think it would be longer, or if you are in a big company and you want to provide an out-of-the-box tool for all projects, here are few points to succeed in writing such a tool:

  • wrap the conversion in an easy-to-run tool. Since that’s a one-shot migration, I would write a simple main(String[]) which would integrate with maven and gradle easily. In fact, many developers will rely on it, through maven-exec-plugin for maven for instance.
    Though, the packaging can be a all-in-one bundle making it easy to run without integrating to any tooling as well. Once again that’s a one shot
    tool, so no need to update its project pom in absolute.
  • finding entities. Two choices here: either you rely on bytecode parsing or on source code parsing. Bytecode parsing implies sources to be compiled to an annotation processor. This can be a good choice but bytecode parsing is not a big hypothesis. Thus, using any class finder like xbean-finder is an easy option as well.
  • finding converters: once you’ve found entities (see previous step) you need to find converters. It is not that hard: simply check for
    @Externalizer and @Factory in your entities. If you used xbean-finder in the previous step you can skip entities finding and directly find these annotations on fields and methods. Side note: if you configured them through xml, be sure to find persistence.xml files and read mapping, you can reuse OpenJPA implementation parser to get them.
  • parse @Externalizer and @Factory to get the “converter” implementation. Here is the tip: once you get the converter, the idea is to simply generate a JPA 2.1 converter delegating to the old one. OpenJPA supports several signatures for the externalizers/factories. In practice, the most common use is to have a static method thus a plain delegation is enough.
  • once you’ve generated all converters (if they are reused accross the code, no need to generate them twice), add to all entities
    the @AttributeConverter annotation to take them into account and remove openjpa specific imports and decoration on he field/method.

This can look a bit complicated but it actually takes less than 1h of hacking.

Want more content ? Keep up-to-date on my new blog

Or stay in touch on twitter @rmannibucau

Simple Java 8 JPA JUnit rule


When you have JPA specific logic or a complex object graph, you surely want to test JPA without worrying of testing your whole application (i.e you just need a plain entity manager and no container).

To do so, you can of course create your entity manager factory, then you create an entity manager and play with it. But it can be nice, in particular with Java 8, to write a small JUnit rule to simply this kind of testing.

This rule would take in charge:

– a default configuration
– the ability to configure the persistent unit
– the ability to run a task in a transaction
– the ability to use the entitymanager without worrying of its creation

Create a JUnit rule

To create a JUnit rule you need to implement `org.junit.rules.TestRule`.

public class OpenJPARule implements TestRule {
  @Override
  public Statement apply(Statement base, Description description) {
      return new Statement() {
        @Override
        public void evaluate() throws Throwable {
            base.evaluate();
        }
    };
}

This implementation does nothing, it simply delegates to the original execution. Yet, we now see that we can wrap `base.evaluate()` in a try/finally block and add some code before and after the execution.

That’s what we’ll do.

Instead of using standard `Persistence` factory class to create the `EntityManagedFactory`, we’ll use OpenJPA on (`org.apache.openjpa.persistence.OpenJPAPersistence`) because it doesn’t need a persistence.xml to exist.

Our implementation will then look like:

OpenJPAEntityManagerFactory emf = OpenJPAPersistence.createEntityManagerFactory("test", null, config);
OpenJPAEntityManager em = emf.createEntityManager();
try {
    base.evaluate();
} finally {
    em.close();
    emf.close();
}

This is great but we can’t do much with this `EntityManager` while it is not accessible to the application.

To keep the ability to run tests in parallel, we’ll store it in a thread local in the rule:

package com.github.rmannibucau.openjpa.java8.junit;

import org.apache.openjpa.persistence.OpenJPAEntityManager;
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
import org.apache.openjpa.persistence.OpenJPAPersistence;
import org.hsqldb.jdbcDriver;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;

import static java.util.Arrays.asList;

public class OpenJPARule implements TestRule {
    private final ThreadLocal<EntityManager> em = new ThreadLocal<>();

    @Override
    public Statement apply(Statement base, Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                OpenJPAEntityManagerFactory emf = OpenJPAPersistence.createEntityManagerFactory("test", null, config);
                OpenJPAEntityManager em = emf.createEntityManager();
                OpenJPARule.this.em.set(em);
                try {
                    base.evaluate();
                } finally {
                    em.close();
                    emf.close();
                    OpenJPARule.this.em.remove();
                }
            }
        };
    }
}

By making the thread local accessible, we’ll be able to use it in the application. But before we’ll need
an entity manager which can be created. That’s to say we need some configuration.

For the testing purpose we’ll use hsqldb as testing database (h2 would be perfect as well) and we’ll use a default
configuration already wiring a datasource, forcing to create the schema and supporting unenhanced classes.

Note: this last point is used for small tests but it is not recommanded to count on it in a real application (with relationships).

Here is our default configuration:

Map config = new HashMap() {{
    put("javax.persistence.jdbc.driver", jdbcDriver.class.getName());
    put("javax.persistence.jdbc.url", "jdbc:hsqldb:mem:test");
    put("javax.persistence.jdbc.user", "sa");
    put("javax.persistence.jdbc.password", "");

    put("openjpa.RuntimeUnenhancedClasses", "supported");

    put("openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=true)");

    put("openjpa.InitializeEagerly", "true");
}};

We’ll store this configuration in our rule, allowing us to customize it through a configure method. We’ll also add a particular
method that enables to specify which types are taken into account (entities). This is done by setting `openjpa.MetaDataFactory`
property giving a value to `types` key:

public class OpenJPARule implements TestRule {
    private final ThreadLocal<EntityManager> em = new ThreadLocal<>();
    private final Map config = new HashMap() {{
        put("javax.persistence.jdbc.driver", jdbcDriver.class.getName());
        put("javax.persistence.jdbc.url", "jdbc:hsqldb:mem:test");
        put("javax.persistence.jdbc.user", "sa");
        put("javax.persistence.jdbc.password", "");

        put("openjpa.RuntimeUnenhancedClasses", "supported");

        put("openjpa.jdbc.SynchronizeMappings", "buildSchema(ForeignKeys=true)");

        put("openjpa.InitializeEagerly", "true");
    }};

    public OpenJPARule configure(final String key, final String value) {
        config.put(key, value);
        return this;
    }

    public OpenJPARule types(final Class<?>... classes) {
        configure("openjpa.MetaDataFactory", "types=" + asList(classes).stream().map(Class::getName).collect(Collectors.joining(",")));
        return this;
    }

    @Override
    public Statement apply(Statement base, Description description) {
      // ...
    }
}

Now, to miss a way to use the rule and `EntityManager`, we’ll provide two methods:

– run: execute a task getting the entity manager as parameter. `java.util.function.Consumer` is a perfect parameter for that
– transaction: execute a task in a transaction. Here, returning some values (persisted entity?) is nice, so we’ll use `java.util.function.Function` as parameter

Finally these methods will look like:

public void run(Consumer<EntityManager> task) {
    task.accept(em.get());
}

public <T> T transaction(Function<EntityManager, T> task) {
    EntityManager entityManager = em.get();
    EntityTransaction tx = entityManager.getTransaction();
    tx.begin();
    boolean cancelled = false;
    try {
        return task.apply(entityManager);
    } catch (RuntimeException e) {
        cancelled = true;
        tx.rollback();
        throw e;
    } finally {
        if (!cancelled) {
            tx.commit();
        }
    }
}

What is nice in using `Function` and `Consumer` is that it is lambda friendly.

Use the OpenJPA JUnit rule

Now we have all the code, we can use our rule in test class:

public class JPATest {
    @Rule
    public final OpenJPARule $ = new OpenJPARule()
            .types(DatedEntity.class)
            .configure("openjpa.Log", "SQL=TRACE");

    @Test
    public void doPersist() {
        final AnEntity de = new AnEntity();
        $.transaction((em) -> {
            em.persist(de);
            return de;
        });
        $.run(EntityManager::clear);
    }
}

OpenJPA and Date JSON serialization


Following the trends, you can try to push your entities to the front layer of your application without any in between conversion. A common sample is to return an entity in a JAX-RS bean.

For instance:

Continue reading

Efficient SQL Insert with MySQL and OpenJPA


Some applications need a high INSERT throughput. I got this issue and found an interesting way to enhance without effort this parameter using OpenJPA (can be adapted with other providers) and MySQL (not sure about other databases).

Continue reading

Generate OpenJPA metamodel classes with maven, maven compiler alternative


It is often better to enhance your entities at build times and it generally simply needs to add -Aopenjpa.metamodel=true  to maven compiler compilerArguments and openjpa to the classpath of the plugin but it has two main drawbacks:

  1. if you need to use other processors you can’t manage it correctly
  2. it simply doesn’t work with maven compiler plugin 3.0

Of course there is an interesting alternative.

Continue reading

Avoiding OpenJPA annotations in the code


OpenJPA, as a lot of JPA providers, supports some custom configuration through specific annotations. That’s great but it makes your code not portable.

It is often not known but OpenJPA comes with the ability to replace these annotations (at least a lot of these annotations) by a simple XML configuration.

Continue reading

TomEE and OpenEJB JPA deploy time enhancement


TomEE and OpenEJB got recently some deploy time enhancement features.

Continue reading