Skip to content

Commit

Permalink
HIbernate plugin now supports org.springframework.orm.jpa.vendor.Spri…
Browse files Browse the repository at this point in the history
…ngHibernateJpaPersistenceProvider (e.g. configuration via spring without persistence.xml file)
  • Loading branch information
Jiri Bubnik committed Feb 15, 2016
1 parent 8c63e09 commit e203abc
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ public class HibernatePersistenceHelper {
* @param original entity manager factory
* @return proxy of entity manager
*/
public static EntityManagerFactory createContainerEntityManagerFactoryProxy(PersistenceUnitInfo info, Map properties,
public static EntityManagerFactory createContainerEntityManagerFactoryProxy(Object builder, PersistenceUnitInfo info, Map properties,
EntityManagerFactory original) {
// ensure only once
if (wrappedPersistenceUnitNames.contains(info.getPersistenceUnitName()))
return original;
wrappedPersistenceUnitNames.add(info.getPersistenceUnitName());

EntityManagerFactoryProxy wrapper = EntityManagerFactoryProxy.getWrapper(info.getPersistenceUnitName());
EntityManagerFactory proxy = wrapper.proxy(original, info.getPersistenceUnitName(), info, properties);
EntityManagerFactory proxy = wrapper.proxy(builder, original, info.getPersistenceUnitName(), info, properties);

initPlugin(original);

Expand All @@ -52,15 +52,15 @@ public static EntityManagerFactory createContainerEntityManagerFactoryProxy(Pers
* @param original entity manager factory
* @return proxy of entity manager
*/
public static EntityManagerFactory createEntityManagerFactoryProxy(String persistenceUnitName, Map properties,
public static EntityManagerFactory createEntityManagerFactoryProxy(Object builder, String persistenceUnitName, Map properties,
EntityManagerFactory original) {
// ensure only once
if (wrappedPersistenceUnitNames.contains(persistenceUnitName))
return original;
wrappedPersistenceUnitNames.add(persistenceUnitName);

EntityManagerFactoryProxy wrapper = EntityManagerFactoryProxy.getWrapper(persistenceUnitName);
EntityManagerFactory proxy = wrapper.proxy(original, persistenceUnitName, null, properties);
EntityManagerFactory proxy = wrapper.proxy(builder, original, persistenceUnitName, null, properties);

initPlugin(original);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package org.hotswap.agent.plugin.hibernate;

import org.hotswap.agent.annotation.OnClassLoadEvent;
import org.hotswap.agent.javassist.CannotCompileException;
import org.hotswap.agent.javassist.ClassPool;
import org.hotswap.agent.javassist.CtClass;
import org.hotswap.agent.javassist.CtConstructor;
import org.hotswap.agent.javassist.CtMethod;
import org.hotswap.agent.javassist.CtNewMethod;
import org.hotswap.agent.javassist.*;
import org.hotswap.agent.javassist.bytecode.AccessFlag;
import org.hotswap.agent.logging.AgentLogger;
import org.hotswap.agent.plugin.hibernate.proxy.SessionFactoryProxy;
Expand All @@ -27,7 +22,7 @@ public class HibernateTransformers {
* <p/>
* After the entity manager factory and it's proxy are instantiated, plugin init method is invoked.
*/
@OnClassLoadEvent(classNameRegexp = "(org.hibernate.ejb.HibernatePersistence)|(org.hibernate.jpa.HibernatePersistenceProvider)")
@OnClassLoadEvent(classNameRegexp = "(org.hibernate.ejb.HibernatePersistence)|(org.hibernate.jpa.HibernatePersistenceProvider)|(org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider)")
public static void proxyHibernatePersistence(CtClass clazz) throws Exception {
LOGGER.debug("Override org.hibernate.ejb.HibernatePersistence#createContainerEntityManagerFactory and createEntityManagerFactory to create a EntityManagerFactoryProxy proxy.");

Expand All @@ -36,21 +31,26 @@ public static void proxyHibernatePersistence(CtClass clazz) throws Exception {
CtMethod newMethod = CtNewMethod.make(
"public javax.persistence.EntityManagerFactory createContainerEntityManagerFactory(" +
" javax.persistence.spi.PersistenceUnitInfo info, java.util.Map properties) {" +
" properties.put(\"PERSISTENCE_CLASS_NAME\", \"" + clazz.getName() + "\");" +
" return " + HibernatePersistenceHelper.class.getName() + ".createContainerEntityManagerFactoryProxy(" +
" info, properties, _createContainerEntityManagerFactory" + clazz.getSimpleName() + "(info, properties)); " +
" this, info, properties, _createContainerEntityManagerFactory" + clazz.getSimpleName() + "(info, properties)); " +
"}", clazz);
clazz.addMethod(newMethod);

oldMethod = clazz.getDeclaredMethod("createEntityManagerFactory");
oldMethod.setName("_createEntityManagerFactory" + clazz.getSimpleName());

newMethod = CtNewMethod.make(
"public javax.persistence.EntityManagerFactory createEntityManagerFactory(" +
" String persistenceUnitName, java.util.Map properties) {" +
" return " + HibernatePersistenceHelper.class.getName() + ".createEntityManagerFactoryProxy(" +
" persistenceUnitName, properties, _createEntityManagerFactory" + clazz.getSimpleName() + "(persistenceUnitName, properties)); " +
"}", clazz);
clazz.addMethod(newMethod);
try {
oldMethod = clazz.getDeclaredMethod("createEntityManagerFactory");
oldMethod.setName("_createEntityManagerFactory" + clazz.getSimpleName());

newMethod = CtNewMethod.make(
"public javax.persistence.EntityManagerFactory createEntityManagerFactory(" +
" String persistenceUnitName, java.util.Map properties) {" +
" return " + HibernatePersistenceHelper.class.getName() + ".createEntityManagerFactoryProxy(" +
" this, persistenceUnitName, properties, _createEntityManagerFactory" + clazz.getSimpleName() + "(persistenceUnitName, properties)); " +
"}", clazz);
clazz.addMethod(newMethod);
} catch (NotFoundException e) {
LOGGER.trace("Method createEntityManagerFactory not found on " + clazz.getName() + ". Is Ok for Spring implementation...", e);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ public class EntityManagerFactoryProxy {
PersistenceUnitInfo info;
Map properties;

// builder object to create properties
Object builder;

/**
* Create new wrapper for persistenceUnitName and hold it's instance for future use.
*
Expand All @@ -61,11 +64,16 @@ public static void refreshProxiedFactories() {
LOGGER.warning("Unable to resolve hibernate version '{}'", version);
}

for (EntityManagerFactoryProxy wrapper : proxiedFactories.values())
for (EntityManagerFactoryProxy wrapper : proxiedFactories.values()) {
String persistenceClassName = wrapper.properties == null ? null :
(String) wrapper.properties.get("PERSISTENCE_CLASS_NAME");

try {
// lock proxy execution during reload
synchronized (wrapper.reloadLock) {
if (version43OrGreater) {
if ("org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider".equals(persistenceClassName)) {
wrapper.refreshProxiedFactorySpring();
} else if (version43OrGreater) {
wrapper.refreshProxiedFactoryVersion43OrGreater();
} else {
wrapper.refreshProxiedFactory();
Expand All @@ -74,6 +82,18 @@ public static void refreshProxiedFactories() {
} catch (Exception e) {
e.printStackTrace();
}
}
}

private void refreshProxiedFactorySpring() {
try {
currentInstance = (EntityManagerFactory) ReflectionHelper.invoke(builder, builder.getClass(),
"createContainerEntityManagerFactory",
new Class[]{PersistenceUnitInfo.class, Map.class}, info, properties);
} catch (Exception e) {
e.printStackTrace();
LOGGER.error("Unable to reload persistence unit {}", info, e);
}
}

public void refreshProxiedFactoryVersion43OrGreater() {
Expand Down Expand Up @@ -151,8 +171,9 @@ private void buildFreshEntityManagerFactory() {
* @param properties properties to cache for factory reload
* @return the proxy
*/
public EntityManagerFactory proxy(EntityManagerFactory factory, String persistenceUnitName,
public EntityManagerFactory proxy(Object builder, EntityManagerFactory factory, String persistenceUnitName,
PersistenceUnitInfo info, Map properties) {
this.builder = builder;
this.currentInstance = factory;
this.persistenceUnitName = persistenceUnitName;
this.info = info;
Expand Down

0 comments on commit e203abc

Please sign in to comment.