From e203abc0210c926695fc26f609b2be7c7a4189ee Mon Sep 17 00:00:00 2001 From: Jiri Bubnik Date: Mon, 15 Feb 2016 16:50:21 +0100 Subject: [PATCH] HIbernate plugin now supports org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider (e.g. configuration via spring without persistence.xml file) --- .../hibernate/HibernatePersistenceHelper.java | 8 ++--- .../hibernate/HibernateTransformers.java | 36 +++++++++---------- .../proxy/EntityManagerFactoryProxy.java | 27 ++++++++++++-- 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/HibernatePersistenceHelper.java b/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/HibernatePersistenceHelper.java index 8dcb22999..422b59075 100644 --- a/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/HibernatePersistenceHelper.java +++ b/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/HibernatePersistenceHelper.java @@ -30,7 +30,7 @@ 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())) @@ -38,7 +38,7 @@ public static EntityManagerFactory createContainerEntityManagerFactoryProxy(Pers 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); @@ -52,7 +52,7 @@ 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)) @@ -60,7 +60,7 @@ public static EntityManagerFactory createEntityManagerFactoryProxy(String persis 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); diff --git a/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/HibernateTransformers.java b/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/HibernateTransformers.java index 7912e3b88..aed112424 100644 --- a/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/HibernateTransformers.java +++ b/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/HibernateTransformers.java @@ -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; @@ -27,7 +22,7 @@ public class HibernateTransformers { *

* 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."); @@ -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); + } } /** diff --git a/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/proxy/EntityManagerFactoryProxy.java b/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/proxy/EntityManagerFactoryProxy.java index 1b592dad4..ac36412ee 100644 --- a/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/proxy/EntityManagerFactoryProxy.java +++ b/plugin/hotswap-agent-hibernate-plugin/src/main/java/org/hotswap/agent/plugin/hibernate/proxy/EntityManagerFactoryProxy.java @@ -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. * @@ -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(); @@ -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() { @@ -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;