How to bootstrap JPA programmatically without the persistence.xml configuration file

(Last Updated On: January 4, 2018)


One of my Twitter followers asked me if there is any documentation for bootstrapping JPA programmatically so that we can replace the persistence.xml configuration file with a Java configuration:

Previously, I wrote an article about bootstrapping Hibernate without the persistence.xml, but that solution was based on the Hibernate-specific EntityManagerFactoryBuilderImpl.

In this article, I’m going to give you a solution that works with any JPA provider since it’s based on standard Java Persistence API.


The JPA specification PersistenceUnitInfo interface encapsulates everything is needed for bootstrapping an EntityManagerFactory. Typically, this interface is implemented by the JPA provider to store the info retrieved after parsing the persistence.xml configuration file.

Because we will no longer use a persistence.xml configuration file, we have to implement this interface ourselves. For the purpose of this test, consider the following implementation:

public class PersistenceUnitInfoImpl 
        implements PersistenceUnitInfo {

    public static final String JPA_VERSION = "2.1";

    private final String persistenceUnitName;

    private PersistenceUnitTransactionType transactionType = 

    private final List<String> managedClassNames;

    private final List<String> mappingFileNames = new ArrayList<>();

    private final Properties properties;

    private DataSource jtaDataSource;

    private DataSource nonJtaDataSource;

    public PersistenceUnitInfoImpl(
            String persistenceUnitName,
            List<String> managedClassNames,
            Properties properties) {
        this.persistenceUnitName = persistenceUnitName;
        this.managedClassNames = managedClassNames; = properties;

    public String getPersistenceUnitName() {
        return persistenceUnitName;

    public String getPersistenceProviderClassName() {
        return HibernatePersistenceProvider.class.getName();

    public PersistenceUnitTransactionType getTransactionType() {
        return transactionType;

    public DataSource getJtaDataSource() {
        return jtaDataSource;

    public PersistenceUnitInfoImpl setJtaDataSource(
            DataSource jtaDataSource) {
        this.jtaDataSource = jtaDataSource;
        this.nonJtaDataSource = null;
        transactionType = PersistenceUnitTransactionType.JTA;
        return this;

    public DataSource getNonJtaDataSource() {
        return nonJtaDataSource;

    public PersistenceUnitInfoImpl setNonJtaDataSource(
            DataSource nonJtaDataSource) {
        this.nonJtaDataSource = nonJtaDataSource;
        this.jtaDataSource = null;
        transactionType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
        return this;

    public List<String> getMappingFileNames() {
        return mappingFileNames;

    public List<URL> getJarFileUrls() {
        return Collections.emptyList();

    public URL getPersistenceUnitRootUrl() {
        return null;

    public List<String> getManagedClassNames() {
        return managedClassNames;

    public boolean excludeUnlistedClasses() {
        return false;

    public SharedCacheMode getSharedCacheMode() {
        return SharedCacheMode.UNSPECIFIED;

    public ValidationMode getValidationMode() {
        return ValidationMode.AUTO;

    public Properties getProperties() {
        return properties;

    public String getPersistenceXMLSchemaVersion() {
        return JPA_VERSION;

    public ClassLoader getClassLoader() {
        return Thread.currentThread().getContextClassLoader();

    public void addTransformer(ClassTransformer transformer) {


    public ClassLoader getNewTempClassLoader() {
        return null;

JUnit base class

To make it easier to reuse the bootstrapping logic, we can define an AbstractJPAProgrammaticBootstrapTest base class which will be extended by all our unit tests that want to bootstrap without an external persistence.xml configuration file.

The AbstractJPAProgrammaticBootstrapTest creates an EntityManagerFactory upon starting a new test and closes it after executing the unit test. This way, all tests run in isolation and each test class can be self-contained as well.

private EntityManagerFactory emf;

public EntityManagerFactory entityManagerFactory() {
    return emf;

public void init() {
    PersistenceUnitInfo persistenceUnitInfo = persistenceUnitInfo(

    Map<String, Object> configuration = new HashMap<>();

    Integrator integrator = integrator();
    if (integrator != null) {
            (IntegratorProvider) () -> 

    emf = new HibernatePersistenceProvider()

public void destroy() {

The JPA standard defines the PersistenceProvider interface defines the contract for instantiating a new EntityManagerFactory. We are going to use the HibernatePersistenceProvider which is a Hibernate-specific implementation of this interface. If you want to use a different JPA Provider, you have to check the Provider API for an implementation of the PersistenceProvider interface and use that instead.

Now, let’s see what the persistenceUnitInfo looks like:

protected PersistenceUnitInfoImpl persistenceUnitInfo(String name) {
    PersistenceUnitInfoImpl persistenceUnitInfo = new PersistenceUnitInfoImpl(
        name, entityClassNames(), properties()

    String[] resources = resources();
    if (resources != null) {

    return persistenceUnitInfo;

The entity classes and the associated XML configuration are defined by the following methods:

protected abstract Class<?>[] entities();

protected String[] resources() {
    return null;

protected List<String> entityClassNames() {
    return Arrays.asList(entities())

So, we can simply implement the entities or extend the resources method to provide the JPA mapping information programmatically.

The properties method defines some basic properties needed by all tests like auto-generating the schema or providing a JDBC DataSource to connect to the underlying database.

protected Properties properties() {
    Properties properties = new Properties();



    DataSource dataSource = newDataSource();

    if (dataSource != null) {


    return properties;

Of course, we can extend the properties base class method to provide additional properties.

The newDataSource method is defined as follows:

protected DataSource newDataSource() {
   return proxyDataSource()
        ? dataSourceProxyType().dataSource(
        : dataSourceProvider().dataSource();

protected DataSourceProxyType dataSourceProxyType() {
    return DataSourceProxyType.DATA_SOURCE_PROXY;

protected boolean proxyDataSource() {
    return true;

protected DataSourceProvider dataSourceProvider() {
    return database().dataSourceProvider();

protected Database database() {
    return Database.HSQLDB;

The dataSourceProxyType allows us to proxy the underlying JDBC DataSource so that we can use the datasource-proxy Open-Source project to log SQL statements along with their bind parameter values.

However, you are not limited to standard JPA bootstrapping only since Hibernate allows you to integrate your own bootstrapping logic via the Integrator mechanism.

By default, we don’t provide any Integrator:

protected Integrator integrator() {
    return null;

But if we provide an Integrator, this one is passed to Hibernate via the hibernate.integrator_provider configuration property.

For more details about how the Integrator mechanism works, check out this article about accessing the database table metadata using Hibernate.

And that’s pretty much it!

Specific JUnit test

Now that we have the AbstractJPAProgrammaticBootstrapTest in place, a specific test will look as follows:

public class BootstrapTest 
    extends AbstractJPAProgrammaticBootstrapTest {

    protected Class<?>[] entities() {
        return new Class[] {

    public void test() {
        doInJPA(entityManager -> {
            for (long id = 1; id <= 3; id++) {
                Post post = new Post();
                        "High-Performance Java Persistence, Part %d", id

    @Entity(name = "Post")
    @Table(name = "post")
    public static class Post {

        private Long id;

        private String title;

        //Getters and setters omitted for brevity

We just have to extend the AbstractJPAProgrammaticBootstrapTest base class and define the entities we want to use. Notice that the entities are associated to this test only so that we make sure that entity mapping changes don’t ripple to other tests.

The doInJPA is a utility method which you can see in this article I wrote before.

If you enjoyed this article, I bet you are going to love my book as well.


As you can see, bootstrapping JPA without the persistence.xml is very easy since the Java Persistence standard defines the contract to do so.

Subscribe to our Newsletter

* indicates required
10 000 readers have found this blog worth following!

If you subscribe to my newsletter, you'll get:
  • A free sample of my Video Course about running Integration tests at warp-speed using Docker and tmpfs
  • 3 chapters from my book, High-Performance Java Persistence, 
  • a 10% discount coupon for my book. 
Get the most out of your persistence layer!


2 thoughts on “How to bootstrap JPA programmatically without the persistence.xml configuration file

  1. I wonder: if i use this and only JPA stuff, nothing hibernate specific, apart from dialog and i use Wildfyl with it hibernate which changes from 4.3 to 5.0 to 5.2 and in future 6.x, 7.x and so on – do i then have no migrations at all, when i use standard JPA?
    I mean there are official migration guides for example:—5.2 , lot of questions on SO regarding migration. When i use above setup with Wildfly, only JPA then do i never have to migrate something when the underlying hibernate implementation changes?

Leave a Reply

Your email address will not be published. Required fields are marked *