Skip to content

Commit

Permalink
HHH-12390 add hibernate-jipijapa
Browse files Browse the repository at this point in the history
  • Loading branch information
scottmarlow authored and sebersole committed Mar 26, 2018
1 parent 9cc9a68 commit 2a1a853
Show file tree
Hide file tree
Showing 85 changed files with 4,782 additions and 1 deletion.
5 changes: 4 additions & 1 deletion gradle/libraries.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ ext {
junitVersion = '4.12'
h2Version = '1.4.196'
bytemanVersion = '4.0.1' //Compatible with JDK10
infinispanVersion = '8.2.5.Final'
infinispanVersion = '9.2.0.Final'
jnpVersion = '5.0.6.CR1'

hibernateValidatorVersion = '6.0.7.Final'
Expand Down Expand Up @@ -118,6 +118,7 @@ ext {

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ infinsipan
infinispan: "org.infinispan:infinispan-core:${infinispanVersion}",
infinispan_hibernate_cache_commons: "org.infinispan:infinispan-hibernate-cache-commons:${infinispanVersion}",
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ infinispan test
infinispan_test: "org.infinispan:infinispan-core:${infinispanVersion}:tests@jar",
jboss_common_core: "org.jboss:jboss-common-core:2.2.16.GA@jar",
Expand Down Expand Up @@ -148,6 +149,8 @@ ext {
shrinkwrap_descriptors_impl_javaee: "org.jboss.shrinkwrap.descriptors:shrinkwrap-descriptors-impl-javaee:${shrinkwrapDescriptorsVersion}",

wildfly_arquillian_container_managed: "org.wildfly.arquillian:wildfly-arquillian-container-managed:${wildflyArquillianContainerVersion}",
jboss_vfs: "org.jboss:jboss-vfs:3.2.11.Final",
jipijapa_spi: "org.wildfly:jipijapa-spi:12.0.0.Final",

jboss_ejb_spec_jar : 'org.jboss.spec.javax.ejb:jboss-ejb-api_3.2_spec:1.0.0.Final',
jboss_annotation_spec_jar : 'org.jboss.spec.javax.annotation:jboss-annotations-api_1.2_spec:1.0.0.Final'
Expand Down
23 changes: 23 additions & 0 deletions hibernate-jipijapa/hibernate-jipijapa.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/

apply from: rootProject.file( 'gradle/published-java-module.gradle' )

description = 'Integrate with WildFly JipiJapa'

dependencies {
compile project( ':hibernate-core' )
compile( libraries.jipijapa_spi )
compile( libraries.jboss_vfs )
compile( libraries.infinispan_hibernate_cache_commons )

testCompile project( ':hibernate-testing' )
}

test {
forkEvery 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.jboss.as.jpa.hibernate5;

import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatformProvider;


/**
* @author Scott Marlow
*/
public class DefaultJtaPlatform implements JtaPlatformProvider {

private static volatile JBossAppServerJtaPlatform delegate;

public static JBossAppServerJtaPlatform getDelegate() {
return delegate;
}

public static void setDelegate(JBossAppServerJtaPlatform delegate) {
DefaultJtaPlatform.delegate = delegate;
}

@Override
public JtaPlatform getProvidedJtaPlatform() {
return delegate;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.jboss.as.jpa.hibernate5;


import org.hibernate.boot.archive.scan.spi.AbstractScannerImpl;
import org.hibernate.boot.archive.scan.spi.Scanner;

/**
* Annotation scanner for Hibernate. Essentially just passes along the VFS-based ArchiveDescriptorFactory
*
* @author Steve Ebersole
*/
public class HibernateArchiveScanner extends AbstractScannerImpl implements Scanner {
public HibernateArchiveScanner() {
super( VirtualFileSystemArchiveDescriptorFactory.INSTANCE );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/

package org.jboss.as.jpa.hibernate5;

import java.util.ArrayList;

import javax.enterprise.inject.spi.BeanManager;

import org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager;

/**
* HibernateExtendedBeanManager helps defer the registering of entity listeners, with the CDI BeanManager until
* after the persistence unit is available for lookup by CDI bean(s).
* This solves the WFLY-2387 issue of JPA entity listeners referencing the CDI bean, when the bean cycles back
* to the persistence unit, or a different persistence unit.
*
* @author Scott Marlow
*/
public class HibernateExtendedBeanManager implements ExtendedBeanManager {
private final ArrayList<LifecycleListener> lifecycleListeners = new ArrayList<>();
private final BeanManager beanManager;

public HibernateExtendedBeanManager(BeanManager beanManager) {
this.beanManager = beanManager;
}

/**
* Hibernate calls registerLifecycleListener to register N callbacks to be notified
* when the CDI BeanManager can safely be used. The CDI BeanManager can safely be used
* when the CDI AfterDeploymentValidation event is reached.
*
* @param lifecycleListener
*
* Note: Caller (BeanManagerAfterDeploymentValidation) is expected to synchronize calls to
* registerLifecycleListener() + beanManagerIsAvailableForUse(), which protects
* HibernateExtendedBeanManager.lifecycleListeners from being read/written from multiple concurrent threads.
* There are many writer threads (one per deployed persistence unit) and one reader/writer thread expected
* to be triggered by one AfterDeploymentValidation event per deployment.
*/
@Override
public void registerLifecycleListener(LifecycleListener lifecycleListener) {
lifecycleListeners.add(lifecycleListener);
}

public void beanManagerIsAvailableForUse() {
for (LifecycleListener hibernateCallback : lifecycleListeners) {
hibernateCallback.beanManagerInitialized(beanManager);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/

package org.jboss.as.jpa.hibernate5;

import static org.jboss.as.jpa.hibernate5.JpaLogger.JPA_LOGGER;

import java.util.Map;
import java.util.Properties;

import javax.enterprise.inject.spi.BeanManager;
import javax.persistence.SharedCacheMode;
import javax.persistence.spi.PersistenceUnitInfo;

import org.hibernate.cfg.AvailableSettings;
import org.jboss.as.jpa.hibernate5.management.HibernateManagementAdaptor;
import org.jipijapa.cache.spi.Classification;
import org.jipijapa.event.impl.internal.Notification;
import org.jipijapa.plugin.spi.EntityManagerFactoryBuilder;
import org.jipijapa.plugin.spi.JtaManager;
import org.jipijapa.plugin.spi.ManagementAdaptor;
import org.jipijapa.plugin.spi.PersistenceProviderAdaptor;
import org.jipijapa.plugin.spi.PersistenceUnitMetadata;
import org.jipijapa.plugin.spi.Platform;
import org.jipijapa.plugin.spi.TwoPhaseBootstrapCapable;

/**
* Implements the PersistenceProviderAdaptor for Hibernate
*
* @author Scott Marlow
*/
public class HibernatePersistenceProviderAdaptor implements PersistenceProviderAdaptor, TwoPhaseBootstrapCapable {

public static final String NAMING_STRATEGY_JPA_COMPLIANT_IMPL = "org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl";
private volatile JtaManager jtaManager;
private volatile Platform platform;
private static final String SHARED_CACHE_MODE = "javax.persistence.sharedCache.mode";
private static final String NONE = SharedCacheMode.NONE.name();
private static final String HIBERNATE_EXTENDED_BEANMANAGER = "org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager";

@Override
public void injectJtaManager(JtaManager jtaManager) {
if (this.jtaManager != jtaManager) {
this.jtaManager = jtaManager;
}
}

@Override
public void injectPlatform(Platform platform) {
if (this.platform != platform) {
this.platform = platform;
}
}

@SuppressWarnings("deprecation")
@Override
public void addProviderProperties(Map properties, PersistenceUnitMetadata pu) {
putPropertyIfAbsent(pu, properties, AvailableSettings.JPAQL_STRICT_COMPLIANCE, "true"); // JIPI-24 ignore jpql aliases case
putPropertyIfAbsent(pu, properties, AvailableSettings.USE_NEW_ID_GENERATOR_MAPPINGS, "true");
putPropertyIfAbsent(pu, properties, AvailableSettings.KEYWORD_AUTO_QUOTING_ENABLED,"false");
putPropertyIfAbsent(pu, properties, AvailableSettings.IMPLICIT_NAMING_STRATEGY, NAMING_STRATEGY_JPA_COMPLIANT_IMPL);
putPropertyIfAbsent(pu, properties, AvailableSettings.SCANNER, HibernateArchiveScanner.class);
properties.put(AvailableSettings.APP_CLASSLOADER, pu.getClassLoader());
putPropertyIfAbsent(pu, properties, AvailableSettings.JTA_PLATFORM, new JBossAppServerJtaPlatform(jtaManager));
putPropertyIfAbsent(pu,properties, org.hibernate.ejb.AvailableSettings.ENTITY_MANAGER_FACTORY_NAME, pu.getScopedPersistenceUnitName());
putPropertyIfAbsent(pu, properties, AvailableSettings.SESSION_FACTORY_NAME, pu.getScopedPersistenceUnitName());
if (!pu.getProperties().containsKey(AvailableSettings.SESSION_FACTORY_NAME)) {
putPropertyIfAbsent(pu, properties, AvailableSettings.SESSION_FACTORY_NAME_IS_JNDI, Boolean.FALSE);
}
}

@Override
public void addProviderDependencies(PersistenceUnitMetadata pu) {
final Properties properties = pu.getProperties();
final String sharedCacheMode = properties.getProperty(SHARED_CACHE_MODE);

if ( Classification.NONE.equals(platform.defaultCacheClassification())) {
if (!SharedCacheMode.NONE.equals(pu.getSharedCacheMode())) {
JPA_LOGGER.tracef("second level cache is not supported in platform, ignoring shared cache mode");
}
pu.setSharedCacheMode(SharedCacheMode.NONE);
}
// check if 2lc is explicitly disabled which takes precedence over other settings
boolean sharedCacheDisabled = SharedCacheMode.NONE.equals(pu.getSharedCacheMode())
||
NONE.equals(sharedCacheMode);

if (!sharedCacheDisabled &&
Boolean.parseBoolean(properties.getProperty(AvailableSettings.USE_SECOND_LEVEL_CACHE))
||
(sharedCacheMode != null && (!NONE.equals(sharedCacheMode)))
|| (!SharedCacheMode.NONE.equals(pu.getSharedCacheMode()) && (!SharedCacheMode.UNSPECIFIED.equals(pu.getSharedCacheMode())))) {
HibernateSecondLevelCache.addSecondLevelCacheDependencies(pu.getProperties(), pu.getScopedPersistenceUnitName());
JPA_LOGGER.tracef("second level cache enabled for %s", pu.getScopedPersistenceUnitName());
} else {
JPA_LOGGER.tracef("second level cache disabled for %s, pu %s property = %s, pu.getSharedCacheMode = %s",
pu.getScopedPersistenceUnitName(),
SHARED_CACHE_MODE,
sharedCacheMode,
pu.getSharedCacheMode().toString());
}
}

private void putPropertyIfAbsent(PersistenceUnitMetadata pu, Map properties, String property, Object value) {
if (!pu.getProperties().containsKey(property)) {
properties.put(property, value);
}
}

@Override
public void beforeCreateContainerEntityManagerFactory(PersistenceUnitMetadata pu) {
Notification.beforeEntityManagerFactoryCreate(Classification.INFINISPAN, pu);
}

@Override
public void afterCreateContainerEntityManagerFactory(PersistenceUnitMetadata pu) {
Notification.afterEntityManagerFactoryCreate(Classification.INFINISPAN, pu);
}

@Override
public ManagementAdaptor getManagementAdaptor() {
return HibernateManagementAdaptor.getInstance();
}

/**
* determine if management console can display the second level cache entries
*
* @param pu
* @return false if a custom AvailableSettings.CACHE_REGION_PREFIX property is specified.
* true if the scoped persistence unit name is used to prefix cache entries.
*/
@Override
public boolean doesScopedPersistenceUnitNameIdentifyCacheRegionName(PersistenceUnitMetadata pu) {
String cacheRegionPrefix = pu.getProperties().getProperty(AvailableSettings.CACHE_REGION_PREFIX);

return cacheRegionPrefix == null || cacheRegionPrefix.equals(pu.getScopedPersistenceUnitName());
}

@Override
public void cleanup(PersistenceUnitMetadata pu) {

}

@Override
public Object beanManagerLifeCycle(BeanManager beanManager) {

if( isHibernateExtendedBeanManagerSupported()) {
return new HibernateExtendedBeanManager(beanManager);
}
// for ORM 5.0, return null to indicate that the org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager extension should not be used.
return null;
}

@Override
public void markPersistenceUnitAvailable(Object wrapperBeanManagerLifeCycle) {
if(isHibernateExtendedBeanManagerSupported()) {
HibernateExtendedBeanManager hibernateExtendedBeanManager = (HibernateExtendedBeanManager) wrapperBeanManagerLifeCycle;
// notify Hibernate ORM ExtendedBeanManager extension that the entity listener(s) can now be registered.
hibernateExtendedBeanManager.beanManagerIsAvailableForUse();
}
}

/**
* org.hibernate.jpa.event.spi.jpa.ExtendedBeanManager is added to Hibernate 5.1 as an extension for delaying registration
* of entity listeners until the CDI AfterDeploymentValidation event is triggered.
* This allows entity listener classes to reference the (origin) persistence unit (WFLY-2387).
*
* return true for Hibernate ORM 5.1+, which should contain the ExtendedBeanManager contract
*/
private boolean isHibernateExtendedBeanManagerSupported() {
try {
Class.forName(HIBERNATE_EXTENDED_BEANMANAGER);
return true;
} catch (ClassNotFoundException ignore) {
return false;
} catch (NoClassDefFoundError ignore) {
return false;
}

}

/* start of TwoPhaseBootstrapCapable methods */

public EntityManagerFactoryBuilder getBootstrap(final PersistenceUnitInfo info, final Map map) {
return new TwoPhaseBootstrapImpl(info, map);
}

/* end of TwoPhaseBootstrapCapable methods */
}

Loading

0 comments on commit 2a1a853

Please sign in to comment.