HHH-16069 - Skip CDI for Hibernate extensions by default

This commit is contained in:
Steve Ebersole 2023-01-25 16:26:44 -06:00
parent 9e033c8aea
commit a742f5e988
26 changed files with 901 additions and 250 deletions

View File

@ -607,6 +607,7 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
private final String schemaCharset;
private final boolean xmlMappingEnabled;
private final boolean allowExtensionsInCdi;
public MetadataBuildingOptionsImpl(StandardServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry;
@ -763,6 +764,12 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
String.class,
null
);
allowExtensionsInCdi = configService.getSetting(
AvailableSettings.ALLOW_EXTENSIONS_IN_CDI,
StandardConverters.BOOLEAN,
false
);
}
private ArrayList<MetadataSourceType> resolveInitialSourceProcessOrdering(ConfigurationService configService) {
@ -951,6 +958,11 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
return xmlMappingEnabled;
}
@Override
public boolean disallowExtensionsInCdi() {
return allowExtensionsInCdi;
}
/**
* Yuck. This is needed because JPA lets users define "global building options"
* in {@code orm.xml} mappings. Forget that there are generally multiple

View File

@ -23,7 +23,6 @@ import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.BasicValue;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.resource.beans.internal.Helper;
import org.hibernate.resource.beans.spi.BeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBean;
@ -32,6 +31,7 @@ import org.hibernate.type.BasicType;
import org.hibernate.type.CustomType;
import org.hibernate.type.SerializableType;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.MutabilityPlan;
@ -137,6 +137,9 @@ public class TypeDefinition implements Serializable {
Map<?,?> usageSiteProperties,
JdbcTypeIndicators indicators,
MetadataBuildingContext context) {
if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
}
final BootstrapContext bootstrapContext = context.getBootstrapContext();
final TypeConfiguration typeConfiguration = bootstrapContext.getTypeConfiguration();
final BeanInstanceProducer instanceProducer = bootstrapContext.getCustomTypeProducer();
@ -282,13 +285,13 @@ public class TypeDefinition implements Serializable {
private static Object instantiateType(StandardServiceRegistry serviceRegistry,
String name, Class<?> typeImplementorClass,
BeanInstanceProducer instanceProducer) {
if ( Helper.shouldIgnoreBeanContainer( serviceRegistry ) ) {
if ( !Helper.allowExtensionsInCdi( serviceRegistry ) ) {
return name != null
? instanceProducer.produceBeanInstance( name, typeImplementorClass )
: instanceProducer.produceBeanInstance( typeImplementorClass );
}
else {
ManagedBeanRegistry beanRegistry = serviceRegistry.getService(ManagedBeanRegistry.class);
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
final ManagedBean<?> typeBean = name != null
? beanRegistry.getBean( name, typeImplementorClass, instanceProducer )
: beanRegistry.getBean( typeImplementorClass, instanceProducer );

View File

@ -12,14 +12,30 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import jakarta.persistence.*;
import jakarta.persistence.NamedNativeQueries;
import jakarta.persistence.NamedNativeQuery;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import org.hibernate.AnnotationException;
import org.hibernate.MappingException;
import org.hibernate.annotations.*;
import org.hibernate.annotations.CollectionTypeRegistration;
import org.hibernate.annotations.CollectionTypeRegistrations;
import org.hibernate.annotations.CompositeTypeRegistration;
import org.hibernate.annotations.CompositeTypeRegistrations;
import org.hibernate.annotations.ConverterRegistration;
import org.hibernate.annotations.ConverterRegistrations;
import org.hibernate.annotations.EmbeddableInstantiatorRegistration;
import org.hibernate.annotations.EmbeddableInstantiatorRegistrations;
import org.hibernate.annotations.FetchProfile;
import org.hibernate.annotations.FetchProfiles;
import org.hibernate.annotations.FilterDef;
import org.hibernate.annotations.FilterDefs;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.GenericGenerators;
import org.hibernate.annotations.Imported;
import org.hibernate.annotations.JavaTypeRegistration;
import org.hibernate.annotations.JavaTypeRegistrations;
import org.hibernate.annotations.JdbcTypeRegistration;
import org.hibernate.annotations.JdbcTypeRegistrations;
import org.hibernate.annotations.ParamDef;
import org.hibernate.annotations.TypeRegistration;
import org.hibernate.annotations.TypeRegistrations;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XAnnotatedElement;
import org.hibernate.annotations.common.reflection.XClass;
@ -37,11 +53,12 @@ import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.GenericsHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.type.descriptor.converter.internal.JpaAttributeConverterImpl;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.BasicType;
import org.hibernate.type.CustomType;
import org.hibernate.type.descriptor.converter.internal.JpaAttributeConverterImpl;
import org.hibernate.type.descriptor.java.BasicJavaType;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry;
@ -51,10 +68,28 @@ import org.hibernate.type.internal.ConvertedBasicTypeImpl;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.usertype.UserType;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Entity;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.NamedNativeQueries;
import jakarta.persistence.NamedNativeQuery;
import jakarta.persistence.NamedQueries;
import jakarta.persistence.NamedQuery;
import jakarta.persistence.NamedStoredProcedureQueries;
import jakarta.persistence.NamedStoredProcedureQuery;
import jakarta.persistence.SequenceGenerator;
import jakarta.persistence.SequenceGenerators;
import jakarta.persistence.SqlResultSetMapping;
import jakarta.persistence.SqlResultSetMappings;
import jakarta.persistence.TableGenerator;
import jakarta.persistence.TableGenerators;
import static java.util.Collections.emptyMap;
import static org.hibernate.boot.model.internal.AnnotatedClassType.ENTITY;
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
import static org.hibernate.boot.model.internal.BinderHelper.getOverridableAnnotation;
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
import static org.hibernate.boot.model.internal.InheritanceState.getInheritanceStateOfSuperEntity;
import static org.hibernate.boot.model.internal.InheritanceState.getSuperclassInheritanceState;
import static org.hibernate.internal.CoreLogging.messageLogger;
@ -459,7 +494,15 @@ public final class AnnotationBinder {
ManagedBeanRegistry managedBeanRegistry,
JdbcTypeRegistration annotation) {
final Class<? extends JdbcType> jdbcTypeClass = annotation.value();
final JdbcType jdbcType = managedBeanRegistry.getBean( jdbcTypeClass ).getBeanInstance();
final JdbcType jdbcType;
if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
jdbcType = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass );
}
else {
jdbcType = managedBeanRegistry.getBean( jdbcTypeClass ).getBeanInstance();
}
final int typeCode = annotation.registrationCode() == Integer.MIN_VALUE
? jdbcType.getDefaultSqlTypeCode()
: annotation.registrationCode();
@ -470,9 +513,16 @@ public final class AnnotationBinder {
MetadataBuildingContext context,
ManagedBeanRegistry managedBeanRegistry,
JavaTypeRegistration annotation) {
final Class<? extends BasicJavaType<?>> jtdClass = annotation.descriptorClass();
final BasicJavaType<?> jtd = managedBeanRegistry.getBean( jtdClass ).getBeanInstance();
context.getMetadataCollector().addJavaTypeRegistration( annotation.javaType(), jtd );
final Class<? extends BasicJavaType<?>> javaTypeClass = annotation.descriptorClass();
final BasicJavaType<?> javaType;
if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
javaType = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
else {
javaType = managedBeanRegistry.getBean( javaTypeClass ).getBeanInstance();
}
context.getMetadataCollector().addJavaTypeRegistration( annotation.javaType(), javaType );
}
private static void bindEmbeddableInstantiatorRegistrations(
@ -700,11 +750,18 @@ public final class AnnotationBinder {
}
}
private static JdbcMapping resolveUserType(Class<UserType<?>> type, MetadataBuildingContext context) {
final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry();
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
final ManagedBean<UserType<?>> bean = beanRegistry.getBean( type );
return new CustomType<>( bean.getBeanInstance(), context.getBootstrapContext().getTypeConfiguration() );
private static JdbcMapping resolveUserType(Class<UserType<?>> userTypeClass, MetadataBuildingContext context) {
final UserType<?> userType;
if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
userType = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( userTypeClass );
}
else {
final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry();
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
userType = beanRegistry.getBean( userTypeClass ).getBeanInstance();
}
return new CustomType<>( userType, context.getBootstrapContext().getTypeConfiguration() );
}
private static JdbcMapping resolveAttributeConverter(Class<AttributeConverter<?, ?>> type, MetadataBuildingContext context) {
@ -747,18 +804,21 @@ public final class AnnotationBinder {
}
private static JavaType<?> getJavaType(
Class<JavaType<?>> type,
Class<JavaType<?>> javaTypeClass,
MetadataBuildingContext context,
TypeConfiguration typeConfiguration) {
final JavaType<?> registeredJtd = typeConfiguration.getJavaTypeRegistry().findDescriptor( type );
final JavaType<?> registeredJtd = typeConfiguration.getJavaTypeRegistry().findDescriptor( javaTypeClass );
if ( registeredJtd != null ) {
return registeredJtd;
}
else {
final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry();
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
return beanRegistry.getBean(type).getBeanInstance();
if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry();
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
return beanRegistry.getBean(javaTypeClass).getBeanInstance();
}
public static void bindFetchProfilesForClass(XClass annotatedClass, MetadataBuildingContext context) {

View File

@ -28,7 +28,6 @@ import org.hibernate.annotations.CollectionIdJavaType;
import org.hibernate.annotations.CollectionIdJdbcType;
import org.hibernate.annotations.CollectionIdJdbcTypeCode;
import org.hibernate.annotations.CollectionIdMutability;
import org.hibernate.annotations.PartitionKey;
import org.hibernate.annotations.CollectionIdType;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.JdbcTypeCode;
@ -43,6 +42,7 @@ import org.hibernate.annotations.MapKeyType;
import org.hibernate.annotations.Mutability;
import org.hibernate.annotations.Nationalized;
import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.PartitionKey;
import org.hibernate.annotations.Target;
import org.hibernate.annotations.TimeZoneColumn;
import org.hibernate.annotations.TimeZoneStorage;
@ -57,12 +57,12 @@ import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.NationalizationSupport;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.Table;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.BasicType;
@ -430,17 +430,22 @@ public class BasicValueBinder implements JdbcTypeIndicators {
throw new MappingException( "idbag mapping missing @CollectionId" );
}
final boolean useDeferredBeanContainerAccess = buildingContext.getBuildingOptions().disallowExtensionsInCdi();
final ManagedBeanRegistry beanRegistry = getManagedBeanRegistry();
explicitBasicTypeName = null;
implicitJavaTypeAccess = (typeConfiguration) -> null;
explicitJavaTypeAccess = (typeConfiguration) -> {
final CollectionIdJavaType javaTypeAnn = findAnnotation( modelXProperty, CollectionIdJavaType.class );
if ( javaTypeAnn != null ) {
final Class<? extends BasicJavaType<?>> javaType = normalizeJavaType( javaTypeAnn.value() );
if ( javaType != null ) {
final ManagedBean<? extends BasicJavaType<?>> bean = beanRegistry.getBean( javaType );
final Class<? extends BasicJavaType<?>> javaTypeClass = normalizeJavaType( javaTypeAnn.value() );
if ( javaTypeClass != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
final ManagedBean<? extends BasicJavaType<?>> bean = beanRegistry.getBean( javaTypeClass );
return bean.getBeanInstance();
}
}
@ -451,9 +456,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJdbcTypeAccess = (typeConfiguration) -> {
final CollectionIdJdbcType jdbcTypeAnn = findAnnotation( modelXProperty, CollectionIdJdbcType.class );
if ( jdbcTypeAnn != null ) {
final Class<? extends JdbcType> jdbcType = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcType != null ) {
final ManagedBean<? extends JdbcType> managedBean = beanRegistry.getBean( jdbcType );
final Class<? extends JdbcType> jdbcTypeClass = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcTypeClass != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass );
}
final ManagedBean<? extends JdbcType> managedBean = beanRegistry.getBean( jdbcTypeClass );
return managedBean.getBeanInstance();
}
}
@ -471,9 +479,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitMutabilityAccess = (typeConfiguration) -> {
final CollectionIdMutability mutabilityAnn = findAnnotation( modelXProperty, CollectionIdMutability.class );
if ( mutabilityAnn != null ) {
final Class<? extends MutabilityPlan<?>> mutability = normalizeMutability( mutabilityAnn.value() );
if ( mutability != null ) {
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = beanRegistry.getBean( mutability );
final Class<? extends MutabilityPlan<?>> mutabilityClass = normalizeMutability( mutabilityAnn.value() );
if ( mutabilityClass != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( mutabilityClass );
}
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = beanRegistry.getBean( mutabilityClass );
return jtdBean.getBeanInstance();
}
}
@ -492,6 +503,9 @@ public class BasicValueBinder implements JdbcTypeIndicators {
if ( converterDescriptor != null ) {
final Mutability converterMutabilityAnn = converterDescriptor.getAttributeConverterClass().getAnnotation( Mutability.class );
if ( converterMutabilityAnn != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( converterMutabilityAnn.value() );
}
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = beanRegistry.getBean( converterMutabilityAnn.value() );
return jtdBean.getBeanInstance();
}
@ -537,12 +551,17 @@ public class BasicValueBinder implements JdbcTypeIndicators {
temporalPrecision = mapKeyTemporalAnn.value();
}
final boolean useDeferredBeanContainerAccess = buildingContext.getBuildingOptions().disallowExtensionsInCdi();
explicitJdbcTypeAccess = typeConfiguration -> {
final MapKeyJdbcType jdbcTypeAnn = findAnnotation( mapAttribute, MapKeyJdbcType.class );
if ( jdbcTypeAnn != null ) {
final Class<? extends JdbcType> jdbcTypeImpl = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcTypeImpl != null ) {
return getManagedBeanRegistry().getBean( jdbcTypeImpl ).getBeanInstance();
final Class<? extends JdbcType> jdbcTypeClass = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcTypeClass != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass );
}
return getManagedBeanRegistry().getBean( jdbcTypeClass ).getBeanInstance();
}
}
@ -560,9 +579,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJavaTypeAccess = typeConfiguration -> {
final MapKeyJavaType javaTypeAnn = findAnnotation( mapAttribute, MapKeyJavaType.class );
if ( javaTypeAnn != null ) {
final Class<? extends BasicJavaType<?>> jdbcTypeImpl = normalizeJavaType( javaTypeAnn.value() );
if ( jdbcTypeImpl != null ) {
return getManagedBeanRegistry().getBean( jdbcTypeImpl ).getBeanInstance();
final Class<? extends BasicJavaType<?>> javaTypeClass = normalizeJavaType( javaTypeAnn.value() );
if ( javaTypeClass != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
return getManagedBeanRegistry().getBean( javaTypeClass ).getBeanInstance();
}
}
@ -578,9 +600,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitMutabilityAccess = typeConfiguration -> {
final MapKeyMutability mutabilityAnn = findAnnotation( mapAttribute, MapKeyMutability.class );
if ( mutabilityAnn != null ) {
final Class<? extends MutabilityPlan<?>> mutability = normalizeMutability( mutabilityAnn.value() );
if ( mutability != null ) {
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = getManagedBeanRegistry().getBean( mutability );
final Class<? extends MutabilityPlan<?>> mutabilityClass = normalizeMutability( mutabilityAnn.value() );
if ( mutabilityClass != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( mutabilityClass );
}
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = getManagedBeanRegistry().getBean( mutabilityClass );
return jtdBean.getBeanInstance();
}
}
@ -599,6 +624,9 @@ public class BasicValueBinder implements JdbcTypeIndicators {
if ( converterDescriptor != null ) {
final Mutability converterMutabilityAnn = converterDescriptor.getAttributeConverterClass().getAnnotation( Mutability.class );
if ( converterMutabilityAnn != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( converterMutabilityAnn.value() );
}
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = getManagedBeanRegistry().getBean( converterMutabilityAnn.value() );
return jtdBean.getBeanInstance();
}
@ -623,6 +651,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
private void prepareListIndex(XProperty listAttribute) {
implicitJavaTypeAccess = typeConfiguration -> Integer.class;
final boolean useDeferredBeanContainerAccess = buildingContext.getBuildingOptions().disallowExtensionsInCdi();
final ManagedBeanRegistry beanRegistry = buildingContext
.getBootstrapContext()
.getServiceRegistry()
@ -631,9 +660,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJavaTypeAccess = (typeConfiguration) -> {
final ListIndexJavaType javaTypeAnn = findAnnotation( listAttribute, ListIndexJavaType.class );
if ( javaTypeAnn != null ) {
final Class<? extends BasicJavaType<?>> javaType = normalizeJavaType( javaTypeAnn.value() );
if ( javaType != null ) {
final ManagedBean<? extends BasicJavaType<?>> bean = beanRegistry.getBean( javaType );
final Class<? extends BasicJavaType<?>> javaTypeClass = normalizeJavaType( javaTypeAnn.value() );
if ( javaTypeClass != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
final ManagedBean<? extends BasicJavaType<?>> bean = beanRegistry.getBean( javaTypeClass );
return bean.getBeanInstance();
}
}
@ -644,9 +676,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJdbcTypeAccess = (typeConfiguration) -> {
final ListIndexJdbcType jdbcTypeAnn = findAnnotation( listAttribute, ListIndexJdbcType.class );
if ( jdbcTypeAnn != null ) {
final Class<? extends JdbcType> jdbcType = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcType != null ) {
final ManagedBean<? extends JdbcType> bean = beanRegistry.getBean( jdbcType );
final Class<? extends JdbcType> jdbcTypeClass = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcTypeClass != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass );
}
final ManagedBean<? extends JdbcType> bean = beanRegistry.getBean( jdbcTypeClass );
return bean.getBeanInstance();
}
}
@ -831,13 +866,18 @@ public class BasicValueBinder implements JdbcTypeIndicators {
private void prepareAnyKey(XProperty modelXProperty) {
implicitJavaTypeAccess = (typeConfiguration) -> null;
final boolean useDeferredBeanContainerAccess = buildingContext.getBuildingOptions().disallowExtensionsInCdi();
explicitJavaTypeAccess = (typeConfiguration) -> {
final AnyKeyJavaType javaTypeAnn = findAnnotation( modelXProperty, AnyKeyJavaType.class );
if ( javaTypeAnn != null ) {
final Class<? extends BasicJavaType<?>> javaType = normalizeJavaType( javaTypeAnn.value() );
final Class<? extends BasicJavaType<?>> javaTypeClass = normalizeJavaType( javaTypeAnn.value() );
if ( javaType != null ) {
return getManagedBeanRegistry().getBean( javaType ).getBeanInstance();
if ( javaTypeClass != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
return getManagedBeanRegistry().getBean( javaTypeClass ).getBeanInstance();
}
}
@ -855,9 +895,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJdbcTypeAccess = (typeConfiguration) -> {
final AnyKeyJdbcType jdbcTypeAnn = findAnnotation( modelXProperty, AnyKeyJdbcType.class );
if ( jdbcTypeAnn != null ) {
final Class<? extends JdbcType> jdbcType = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcType != null ) {
final ManagedBean<? extends JdbcType> jtdBean = getManagedBeanRegistry().getBean( jdbcType );
final Class<? extends JdbcType> jdbcTypeClass = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcTypeClass != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass );
}
final ManagedBean<? extends JdbcType> jtdBean = getManagedBeanRegistry().getBean( jdbcTypeClass );
return jtdBean.getBeanInstance();
}
}
@ -878,9 +921,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
final org.hibernate.annotations.JdbcType jdbcTypeAnn = findAnnotation( attributeXProperty, org.hibernate.annotations.JdbcType.class );
if ( jdbcTypeAnn != null ) {
final Class<? extends JdbcType> jdbcType = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcType != null ) {
return getManagedBeanRegistry().getBean( jdbcType ).getBeanInstance();
final Class<? extends JdbcType> jdbcTypeClass = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcTypeClass != null ) {
if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass );
}
return getManagedBeanRegistry().getBean( jdbcTypeClass ).getBeanInstance();
}
}
@ -903,6 +949,9 @@ public class BasicValueBinder implements JdbcTypeIndicators {
if ( mutabilityAnn != null ) {
final Class<? extends MutabilityPlan<?>> mutability = normalizeMutability( mutabilityAnn.value() );
if ( mutability != null ) {
if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( mutability );
}
return getManagedBeanRegistry().getBean( mutability ).getBeanInstance();
}
}
@ -926,6 +975,9 @@ public class BasicValueBinder implements JdbcTypeIndicators {
if ( converterDescriptor != null ) {
final Mutability converterMutabilityAnn = converterDescriptor.getAttributeConverterClass().getAnnotation( Mutability.class );
if ( converterMutabilityAnn != null ) {
if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( converterMutabilityAnn.value() );
}
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = getManagedBeanRegistry().getBean( converterMutabilityAnn.value() );
return jtdBean.getBeanInstance();
}
@ -952,10 +1004,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJavaTypeAccess = typeConfiguration -> {
final org.hibernate.annotations.JavaType javaTypeAnn = findAnnotation( attributeXProperty, org.hibernate.annotations.JavaType.class );
if ( javaTypeAnn != null ) {
final Class<? extends BasicJavaType<?>> javaType = normalizeJavaType( javaTypeAnn.value() );
if ( javaType != null ) {
final ManagedBean<? extends BasicJavaType<?>> jtdBean = getManagedBeanRegistry().getBean( javaType );
final Class<? extends BasicJavaType<?>> javaTypeClass = normalizeJavaType( javaTypeAnn.value() );
if ( javaTypeClass != null ) {
if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
final ManagedBean<? extends BasicJavaType<?>> jtdBean = getManagedBeanRegistry().getBean( javaTypeClass );
return jtdBean.getBeanInstance();
}
}

View File

@ -98,6 +98,7 @@ import org.hibernate.mapping.DependantValue;
import org.hibernate.mapping.Join;
import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.MappingHelper;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
@ -152,7 +153,6 @@ import static org.hibernate.boot.model.internal.AnnotatedColumn.buildFormulaFrom
import static org.hibernate.boot.model.internal.AnnotatedJoinColumns.buildJoinColumnsWithDefaultColumnSuffix;
import static org.hibernate.boot.model.internal.AnnotatedJoinColumns.buildJoinTableJoinColumns;
import static org.hibernate.boot.model.internal.BinderHelper.buildAnyValue;
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
import static org.hibernate.boot.model.internal.BinderHelper.createSyntheticPropertyReference;
import static org.hibernate.boot.model.internal.BinderHelper.getCascadeStrategy;
import static org.hibernate.boot.model.internal.BinderHelper.getFetchMode;
@ -163,6 +163,7 @@ import static org.hibernate.boot.model.internal.BinderHelper.isPrimitive;
import static org.hibernate.boot.model.internal.BinderHelper.toAliasEntityMap;
import static org.hibernate.boot.model.internal.BinderHelper.toAliasTableMap;
import static org.hibernate.boot.model.internal.EmbeddableBinder.fillEmbeddable;
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder;
import static org.hibernate.cfg.AvailableSettings.USE_ENTITY_WHERE_CLAUSE_FOR_COLLECTIONS;
import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.fromResultCheckStyle;
@ -845,37 +846,41 @@ public abstract class CollectionBinder {
Class<? extends UserCollectionType> implementation,
Map<String,String> parameters,
MetadataBuildingContext buildingContext) {
final boolean hasParameters = CollectionHelper.isNotEmpty( parameters );
if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
// if deferred container access is enabled, we locally create the user-type
return MappingHelper.createLocalUserCollectionTypeBean( role, implementation, hasParameters, parameters );
}
final ManagedBeanRegistry beanRegistry = buildingContext.getBuildingOptions()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class );
if ( CollectionHelper.isNotEmpty( parameters ) ) {
return beanRegistry.getBean( implementation );
}
else {
// defined parameters...
if ( ParameterizedType.class.isAssignableFrom( implementation ) ) {
// because there are config parameters and the type is configurable,
// we need a separate bean instance which means uniquely naming it
final ManagedBean<? extends UserCollectionType> typeBean = beanRegistry.getBean( role, implementation );
final UserCollectionType type = typeBean.getBeanInstance();
final Properties properties = new Properties();
properties.putAll( parameters );
( (ParameterizedType) type ).setParameterValues( properties );
return typeBean;
}
else {
// log a "warning"
BootLogging.BOOT_LOGGER.debugf(
"Custom collection-type (`%s`) assigned to attribute (`%s`) does not implement `%s`, but its `@CollectionType` defined parameters",
implementation.getName(),
role,
ParameterizedType.class.getName()
);
final ManagedBean<? extends UserCollectionType> managedBean = beanRegistry.getBean( implementation );
// but still return the bean - we can again use the no-config bean instance
return beanRegistry.getBean( implementation );
if ( hasParameters ) {
if ( ParameterizedType.class.isAssignableFrom( managedBean.getBeanClass() ) ) {
// create a copy of the parameters and create a bean wrapper to delay injecting
// the parameters, thereby delaying the need to resolve the instance from the
// wrapped bean
final Properties copy = new Properties();
copy.putAll( parameters );
return new DelayedParameterizedTypeBean<>( managedBean, copy );
}
// there were parameters, but the custom-type does not implement the interface
// used to inject them - log a "warning"
BootLogging.BOOT_LOGGER.debugf(
"`@CollectionType` (%s) specified parameters, but the" +
" implementation does not implement `%s` which is used to inject them - `%s`",
role,
ParameterizedType.class.getName(),
implementation.getName()
);
// fall through to returning `managedBean`
}
return managedBean;
}
private static CollectionBinder createBinderFromProperty(XProperty property, MetadataBuildingContext context) {
@ -902,37 +907,15 @@ public abstract class CollectionBinder {
XProperty property,
CollectionType typeAnnotation,
MetadataBuildingContext context) {
final ManagedBeanRegistry beanRegistry = context.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class );
final Class<? extends UserCollectionType> typeImpl = typeAnnotation.type();
if ( typeAnnotation.parameters().length == 0 ) {
// no parameters - we can reuse a no-config bean instance
return beanRegistry.getBean( typeImpl );
}
else {
// defined parameters...
final String attributeKey = property.getDeclaringClass().getName() + "#" + property.getName();
if ( ParameterizedType.class.isAssignableFrom( typeImpl ) ) {
// because there are config parameters and the type is configurable, we need
// a separate bean instance which means uniquely naming it
final ManagedBean<? extends UserCollectionType> typeBean = beanRegistry.getBean( attributeKey, typeImpl );
final UserCollectionType type = typeBean.getBeanInstance();
( (ParameterizedType) type ).setParameterValues( extractParameters( typeAnnotation ) );
return typeBean;
}
else {
// log a "warning"
BootLogging.BOOT_LOGGER.debugf(
"Custom collection-type (`%s`) assigned to attribute (`%s`) does not implement `%s`, but its `@CollectionType` defined parameters",
typeImpl.getName(),
attributeKey,
ParameterizedType.class.getName()
);
// but still return the bean - we can again use the no-config bean instance
return beanRegistry.getBean( typeImpl );
}
}
final Properties parameters = extractParameters( typeAnnotation );
//noinspection unchecked,rawtypes
return createCustomType(
property.getDeclaringClass().getName() + "." + property.getName(),
typeAnnotation.type(),
(Map) parameters,
context
);
}
private static Properties extractParameters(CollectionType typeAnnotation) {

View File

@ -0,0 +1,74 @@
/*
* 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.hibernate.boot.model.internal;
import java.util.Properties;
import org.hibernate.boot.BootLogging;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.usertype.ParameterizedType;
/**
* ManagedBean implementation for delayed {@link ParameterizedType}
* handling (parameter injection) for a UserCollectionType
*
* @author Steve Ebersole
*/
public class DelayedParameterizedTypeBean<T> implements ManagedBean<T> {
private final ManagedBean<T> underlyingBean;
private final Properties properties;
private T instance;
public DelayedParameterizedTypeBean(ManagedBean<T> underlyingBean, Properties properties) {
assert ParameterizedType.class.isAssignableFrom( underlyingBean.getBeanClass() );
this.underlyingBean = underlyingBean;
this.properties = properties;
}
@Override
public Class<T> getBeanClass() {
return underlyingBean.getBeanClass();
}
@Override
public T getBeanInstance() {
if ( instance == null ) {
instance = underlyingBean.getBeanInstance();
( (ParameterizedType) instance ).setParameterValues( properties );
}
return instance;
}
/**
* Create a bean wrapper which delays parameter injection
* until the bean instance is needed if there are parameters
*/
public static <T> ManagedBean<T> delayedConfigBean(
String role,
ManagedBean<T> bean,
Properties properties) {
if ( CollectionHelper.isNotEmpty( properties ) ) {
if ( ParameterizedType.class.isAssignableFrom( bean.getBeanClass() ) ) {
return new DelayedParameterizedTypeBean<>( bean, properties );
}
// there were parameters, but the custom-type does not implement the interface
// used to inject them - log a "warning"
BootLogging.BOOT_LOGGER.debugf(
"`@CollectionType` (%s) specified parameters, but the" +
" implementation does not implement `%s` which is used to inject them - `%s`",
role,
ParameterizedType.class.getName(),
bean.getBeanClass().getName()
);
}
return bean;
}
}

View File

@ -6,17 +6,14 @@
*/
package org.hibernate.boot.model.internal;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Embedded;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.AnnotationException;
import org.hibernate.annotations.Instantiator;
import org.hibernate.annotations.TypeBinderType;
@ -36,28 +33,33 @@ import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.property.access.internal.PropertyAccessStrategyCompositeUserTypeImpl;
import org.hibernate.property.access.internal.PropertyAccessStrategyMixedImpl;
import org.hibernate.property.access.spi.PropertyAccessStrategy;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.usertype.CompositeUserType;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Embedded;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import static org.hibernate.boot.model.internal.BinderHelper.isGlobalGeneratorNameGlobal;
import static org.hibernate.boot.model.internal.HCANNHelper.findContainingAnnotations;
import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass;
import static org.hibernate.boot.model.internal.PropertyBinder.processElementAnnotations;
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
import static org.hibernate.boot.model.internal.GeneratorBinder.generatorType;
import static org.hibernate.boot.model.internal.BinderHelper.getPath;
import static org.hibernate.boot.model.internal.BinderHelper.getPropertyOverriddenByMapperOrMapsId;
import static org.hibernate.boot.model.internal.BinderHelper.getRelativePath;
import static org.hibernate.boot.model.internal.BinderHelper.hasToOneAnnotation;
import static org.hibernate.boot.model.internal.BinderHelper.isGlobalGeneratorNameGlobal;
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
import static org.hibernate.boot.model.internal.GeneratorBinder.generatorType;
import static org.hibernate.boot.model.internal.GeneratorBinder.makeIdGenerator;
import static org.hibernate.boot.model.internal.HCANNHelper.findContainingAnnotations;
import static org.hibernate.boot.model.internal.PropertyBinder.addElementsOfClass;
import static org.hibernate.boot.model.internal.PropertyBinder.processElementAnnotations;
import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder;
import static org.hibernate.internal.CoreLogging.messageLogger;
import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY;
@ -400,7 +402,12 @@ public class EmbeddableBinder {
private static CompositeUserType<?> compositeUserType(
Class<? extends CompositeUserType<?>> compositeUserTypeClass,
MetadataBuildingContext context) {
return context.getBootstrapContext().getServiceRegistry()
if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( compositeUserTypeClass );
}
return context.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean( compositeUserTypeClass )
.getBeanInstance();

View File

@ -146,6 +146,7 @@ import org.hibernate.mapping.Table;
import org.hibernate.mapping.UnionSubclass;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.mapping.Value;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.spi.NavigablePath;
@ -2362,13 +2363,18 @@ public class ModelBinder {
try {
final Class<?> typeJavaType = classLoaderService.classForName( typeName );
final String beanName = typeName + ":" + TypeDefinition.NAME_COUNTER.getAndIncrement();
final ManagedBeanRegistry beanRegistry = bootstrapContext
.getServiceRegistry()
.getService( ManagedBeanRegistry.class );
final ManagedBean<?> bean = beanRegistry.getBean( beanName, typeJavaType );
final Object typeInstance = bean.getBeanInstance();
final Object typeInstance;
if ( metadataBuildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
typeInstance = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( typeJavaType );
}
else {
final ManagedBeanRegistry beanRegistry = bootstrapContext
.getServiceRegistry()
.getService( ManagedBeanRegistry.class );
final String beanName = typeName + ":" + TypeDefinition.NAME_COUNTER.getAndIncrement();
final ManagedBean<?> bean = beanRegistry.getBean( beanName, typeJavaType );
typeInstance = bean.getBeanInstance();
}
if ( typeInstance instanceof ParameterizedType ) {
if ( parameters != null ) {
@ -2596,15 +2602,22 @@ public class ModelBinder {
log.debugf( "Binding component [%s]", role );
if ( StringHelper.isNotEmpty( explicitComponentClassName ) ) {
try {
final Class<Object> componentClass = sourceDocument.getBootstrapContext().getClassLoaderAccess()
final Class<Object> componentClass = sourceDocument.getBootstrapContext()
.getClassLoaderAccess()
.classForName( explicitComponentClassName );
if ( CompositeUserType.class.isAssignableFrom( componentClass ) ) {
componentBinding.setTypeName( explicitComponentClassName );
CompositeUserType<?> compositeUserType = (CompositeUserType<?>) sourceDocument.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean( componentClass )
.getBeanInstance();
CompositeUserType<?> compositeUserType;
if ( sourceDocument.getBuildingOptions().disallowExtensionsInCdi() ) {
compositeUserType = (CompositeUserType<?>) FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( componentClass );
}
else {
compositeUserType = (CompositeUserType<?>) sourceDocument.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean( componentClass )
.getBeanInstance();
}
explicitComponentClassName = compositeUserType.embeddable().getName();
}
}

View File

@ -7,7 +7,7 @@
package org.hibernate.boot.spi;
import java.util.List;
import jakarta.persistence.SharedCacheMode;
import org.hibernate.HibernateException;
import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.boot.model.IdGeneratorStrategyInterpreter;
@ -21,6 +21,8 @@ import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.type.spi.TypeConfiguration;
import jakarta.persistence.SharedCacheMode;
/**
* Convenience base class for custom implementors of {@link MetadataBuildingOptions} using delegation.
*
@ -169,4 +171,8 @@ public abstract class AbstractDelegatingMetadataBuildingOptions implements Metad
return delegate.isXmlMappingEnabled();
}
@Override
public boolean disallowExtensionsInCdi() {
return delegate.disallowExtensionsInCdi();
}
}

View File

@ -8,8 +8,6 @@ package org.hibernate.boot.spi;
import java.util.List;
import jakarta.persistence.SharedCacheMode;
import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.boot.model.IdGeneratorStrategyInterpreter;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
@ -27,6 +25,8 @@ import org.hibernate.metamodel.internal.ManagedTypeRepresentationResolverStandar
import org.hibernate.metamodel.spi.ManagedTypeRepresentationResolver;
import org.hibernate.type.spi.TypeConfiguration;
import jakarta.persistence.SharedCacheMode;
/**
* Describes the options used while building the {@link org.hibernate.boot.Metadata}
* object during {@link org.hibernate.boot.MetadataBuilder#build()} processing.
@ -231,4 +231,9 @@ public interface MetadataBuildingOptions {
default boolean isXmlMappingEnabled() {
return true;
}
/**
* Check to see if extensions can be hosted in CDI
*/
boolean disallowExtensionsInCdi();
}

View File

@ -1308,6 +1308,16 @@ public interface AvailableSettings {
*/
String DELAY_CDI_ACCESS = "hibernate.delay_cdi_access";
/**
* Controls whether Hibernate can try to create beans other than converters
* and listeners using CDI. Only meaningful when a CDI {@link #BEAN_CONTAINER container}
* is used.
*
* By default, Hibernate will only attempt to create converter and listener beans using CDI.
*
* @since 6.2
*/
String ALLOW_EXTENSIONS_IN_CDI = "hibernate.cdi.extensions";
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -74,7 +74,7 @@ public class StandardIdentifierGeneratorFactory
* Constructs a new factory
*/
public StandardIdentifierGeneratorFactory(ServiceRegistry serviceRegistry) {
this( serviceRegistry, Helper.shouldIgnoreBeanContainer( serviceRegistry ) );
this( serviceRegistry, !Helper.allowExtensionsInCdi( serviceRegistry ) );
}
/**

View File

@ -38,7 +38,7 @@ import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.SelectablePath;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.BeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
@ -46,6 +46,7 @@ import org.hibernate.tool.schema.extract.spi.ColumnTypeInformation;
import org.hibernate.type.BasicType;
import org.hibernate.type.CustomType;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.type.descriptor.java.BasicJavaType;
import org.hibernate.type.descriptor.java.BasicPluralJavaType;
import org.hibernate.type.descriptor.java.JavaType;
@ -793,18 +794,25 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
properties.putAll( explicitLocalTypeParams );
}
final ManagedBean<T> typeBean;
if ( properties.isEmpty() ) {
typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class )
.getBean( explicitCustomType, instanceProducer );
final T typeInstance;
if ( getBuildingContext().getBuildingOptions().disallowExtensionsInCdi() ) {
typeInstance = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( explicitCustomType );
}
else {
final String name = explicitCustomType.getName() + COUNTER++;
typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class )
.getBean( name, explicitCustomType, instanceProducer );
}
final boolean hasParameters = CollectionHelper.isNotEmpty( properties );
final T typeInstance = typeBean.getBeanInstance();
final ManagedBean<T> typeBean;
if ( hasParameters ) {
final String name = explicitCustomType.getName() + COUNTER++;
typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class )
.getBean( name, explicitCustomType, instanceProducer );
}
else {
typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class )
.getBean( explicitCustomType, instanceProducer );
}
typeInstance = typeBean.getBeanInstance();
}
if ( typeInstance instanceof TypeConfigurationAware ) {
( (TypeConfigurationAware) typeInstance ).setTypeConfiguration( getTypeConfiguration() );

View File

@ -11,12 +11,17 @@ import java.util.Properties;
import java.util.function.Supplier;
import org.hibernate.Internal;
import org.hibernate.boot.BootLogging;
import org.hibernate.boot.model.internal.DelayedParameterizedTypeBean;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.MappingModelCreationLogger;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.resource.beans.spi.ProvidedInstanceManagedBeanImpl;
import org.hibernate.type.AnyType;
import org.hibernate.type.CollectionType;
import org.hibernate.type.CustomCollectionType;
@ -46,23 +51,55 @@ public final class MappingHelper {
String propertyRef,
MetadataImplementor metadata) {
final ClassLoaderService cls = metadata.getMetadataBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class );
final Class<? extends UserCollectionType> typeImpl = cls.classForName( typeName );
final Class<? extends UserCollectionType> userCollectionTypeClass = cls.classForName( typeName );
final ManagedBeanRegistry beanRegistry = metadata
.getMetadataBuildingOptions()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class );
final boolean hasParameters = CollectionHelper.isNotEmpty( typeParameters );
final ManagedBean<? extends UserCollectionType> userTypeBean;
final ManagedBean<? extends UserCollectionType> customTypeBean;
if ( typeParameters == null ) {
customTypeBean = beanRegistry.getBean( typeImpl );
if ( metadata.getMetadataBuildingOptions().disallowExtensionsInCdi() ) {
//noinspection unchecked,rawtypes
userTypeBean = createLocalUserCollectionTypeBean(
role,
userCollectionTypeClass,
hasParameters,
(Map) typeParameters
);
}
else {
customTypeBean = beanRegistry.getBean( role, typeImpl );
injectParameters( customTypeBean.getBeanInstance(), typeParameters );
final ManagedBeanRegistry beanRegistry = metadata
.getMetadataBuildingOptions()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class );
final ManagedBean<? extends UserCollectionType> userCollectionTypeBean = beanRegistry.getBean( userCollectionTypeClass );
if ( hasParameters ) {
if ( ParameterizedType.class.isAssignableFrom( userCollectionTypeBean.getBeanClass() ) ) {
// create a copy of the parameters and create a bean wrapper to delay injecting
// the parameters, thereby delaying the need to resolve the instance from the
// wrapped bean
final Properties copy = new Properties();
copy.putAll( typeParameters );
userTypeBean = new DelayedParameterizedTypeBean<>( userCollectionTypeBean, copy );
}
else {
// there were parameters, but the custom-type does not implement the interface
// used to inject them - log a "warning"
BootLogging.BOOT_LOGGER.debugf(
"`@CollectionType` (%s) specified parameters, but the" +
" implementation does not implement `%s` which is used to inject them - `%s`",
role,
ParameterizedType.class.getName(),
userCollectionTypeClass.getName()
);
userTypeBean = userCollectionTypeBean;
}
}
else {
userTypeBean = userCollectionTypeBean;
}
}
return new CustomCollectionType( customTypeBean, role, propertyRef );
return new CustomCollectionType( userTypeBean, role, propertyRef );
}
public static void injectParameters(Object type, Properties parameters) {
@ -166,4 +203,36 @@ public final class MappingHelper {
constrained
);
}
public static ManagedBean<UserCollectionType> createLocalUserCollectionTypeBean(
String role,
Class<? extends UserCollectionType> implementation,
boolean hasParameters,
Map<String, String> parameters) {
final UserCollectionType userCollectionType = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( implementation );
if ( hasParameters ) {
// `@CollectionType` declared parameters - inject them
if ( userCollectionType instanceof ParameterizedType ) {
final Properties properties = new Properties();
properties.putAll( parameters );
( (ParameterizedType) userCollectionType ).setParameterValues( properties );
}
else {
// there were parameters, but the custom-type does not implement the interface
// used to inject them - log a "warning"
BootLogging.BOOT_LOGGER.debugf(
"`@CollectionType` (%s) specified parameters, but the" +
" implementation does not implement `%s` which is used to inject them - `%s`",
role,
ParameterizedType.class.getName(),
implementation.getName()
);
// use the un-configured instance
}
}
return new ProvidedInstanceManagedBeanImpl<>( userCollectionType );
}
}

View File

@ -20,6 +20,7 @@ import org.hibernate.metamodel.spi.EntityRepresentationStrategy;
import org.hibernate.metamodel.spi.ManagedTypeRepresentationResolver;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.usertype.CompositeUserType;
@ -78,32 +79,42 @@ public class ManagedTypeRepresentationResolverStandard implements ManagedTypeRep
}
}
final CompositeUserType<Object> compositeUserType;
final CompositeUserType<?> compositeUserType;
if ( bootDescriptor.getTypeName() != null ) {
compositeUserType = (CompositeUserType<Object>) creationContext.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean(
creationContext.getBootstrapContext()
.getClassLoaderAccess()
.classForName( bootDescriptor.getTypeName() )
)
.getBeanInstance();
final Class<CompositeUserType<?>> userTypeClass = creationContext.getBootstrapContext()
.getClassLoaderAccess()
.classForName( bootDescriptor.getTypeName() );
if ( creationContext.getBootModel().getMetadataBuildingOptions().disallowExtensionsInCdi() ) {
compositeUserType = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( userTypeClass );
}
else {
compositeUserType = creationContext.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean( userTypeClass )
.getBeanInstance();
}
}
else {
compositeUserType = null;
}
final EmbeddableInstantiator customInstantiator;
if ( bootDescriptor.getCustomInstantiator() != null ) {
final Class<? extends EmbeddableInstantiator> customInstantiatorImpl = bootDescriptor.getCustomInstantiator();
customInstantiator = creationContext.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean( customInstantiatorImpl )
.getBeanInstance();
final Class<? extends EmbeddableInstantiator> instantiatorClass = bootDescriptor.getCustomInstantiator();
if ( creationContext.getBootModel().getMetadataBuildingOptions().disallowExtensionsInCdi() ) {
customInstantiator = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( instantiatorClass );
}
else {
customInstantiator = creationContext.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean( instantiatorClass )
.getBeanInstance();
}
}
else if ( compositeUserType != null ) {
customInstantiator = new EmbeddableCompositeUserTypeInstantiator( compositeUserType );
//noinspection unchecked,rawtypes
customInstantiator = new EmbeddableCompositeUserTypeInstantiator( (CompositeUserType) compositeUserType );
}
else if ( bootDescriptor.getComponentClassName() != null && ReflectHelper.isRecord( bootDescriptor.getComponentClass() ) ) {
if ( bootDescriptor.sortProperties() == null ) {
@ -143,11 +154,12 @@ public class ManagedTypeRepresentationResolverStandard implements ManagedTypeRep
//
// instead, resolve ReflectionOptimizer once - here - and pass along to
// StandardPojoRepresentationStrategy
//noinspection unchecked
return new EmbeddableRepresentationStrategyPojo(
bootDescriptor,
runtimeDescriptorAccess,
customInstantiator,
compositeUserType,
(CompositeUserType<Object>) compositeUserType,
creationContext
);
}

View File

@ -9,10 +9,9 @@ package org.hibernate.resource.beans.internal;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.resource.beans.container.spi.BeanLifecycleStrategy;
import org.hibernate.resource.beans.container.internal.ContainerManagedLifecycleStrategy;
import org.hibernate.resource.beans.container.internal.JpaCompliantLifecycleStrategy;
import org.hibernate.resource.beans.container.spi.ExtendedBeanManager;
import org.hibernate.resource.beans.container.spi.BeanLifecycleStrategy;
import org.hibernate.service.ServiceRegistry;
/**
@ -31,19 +30,13 @@ public final class Helper {
return beanType.getName() + ':' + name;
}
public static boolean shouldIgnoreBeanContainer(ServiceRegistry serviceRegistry) {
public static boolean allowExtensionsInCdi(ServiceRegistry serviceRegistry) {
final ConfigurationService configService = serviceRegistry.getService( ConfigurationService.class );
final Object beanManagerRef = configService.getSettings().get( AvailableSettings.JAKARTA_CDI_BEAN_MANAGER );
if ( beanManagerRef instanceof ExtendedBeanManager ) {
return true;
}
if ( configService.getSetting( AvailableSettings.DELAY_CDI_ACCESS, StandardConverters.BOOLEAN, false ) ) {
return true;
}
return false;
return configService.getSetting(
AvailableSettings.ALLOW_EXTENSIONS_IN_CDI,
StandardConverters.BOOLEAN,
false
);
}
@SuppressWarnings("unused")

View File

@ -36,6 +36,7 @@ import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.spi.CompositeTypeImplementor;
@ -96,11 +97,17 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
final ManagedBeanRegistry beanRegistry = buildingContext.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class );
final Class<Object> customTypeClass = buildingContext.getBootstrapContext()
final Class<CompositeUserType<?>> customTypeClass = buildingContext.getBootstrapContext()
.getClassLoaderAccess()
.classForName( component.getTypeName() );
//noinspection unchecked
this.compositeUserType = (CompositeUserType<Object>) beanRegistry.getBean( customTypeClass ).getBeanInstance();
if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
//noinspection unchecked,rawtypes
this.compositeUserType = (CompositeUserType) FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( customTypeClass );
}
else {
//noinspection unchecked,rawtypes
this.compositeUserType = (CompositeUserType) beanRegistry.getBean( customTypeClass ).getBeanInstance();
}
}
else {
this.compositeUserType = null;

View File

@ -52,11 +52,12 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.metamodel.model.domain.internal.ArrayTupleType;
import org.hibernate.query.internal.QueryHelper;
import org.hibernate.query.sqm.BinaryArithmeticOperator;
import org.hibernate.query.sqm.IntervalType;
import org.hibernate.query.internal.QueryHelper;
import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.service.ServiceRegistry;
@ -401,6 +402,7 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
private transient MetadataBuildingContext metadataBuildingContext;
private transient SessionFactoryImplementor sessionFactory;
private boolean allowExtensionsInCdi;
private String sessionFactoryName;
private String sessionFactoryUuid;
@ -491,6 +493,9 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
private void setMetadataBuildingContext(MetadataBuildingContext metadataBuildingContext) {
this.metadataBuildingContext = metadataBuildingContext;
if ( metadataBuildingContext != null ) {
this.allowExtensionsInCdi = metadataBuildingContext.getBuildingOptions().disallowExtensionsInCdi();
}
}
private SessionFactoryImplementor getSessionFactory() {
@ -805,8 +810,12 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
@Internal @SuppressWarnings("unchecked")
public <J> MutabilityPlan<J> createMutabilityPlan(Class<? extends MutabilityPlan<?>> planClass) {
final ManagedBean<? extends MutabilityPlan<?>> planBean =
scope.getServiceRegistry()
if ( scope.allowExtensionsInCdi ) {
//noinspection rawtypes
return (MutabilityPlan) FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( planClass );
}
final ManagedBean<? extends MutabilityPlan<?>> planBean = scope.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean( planClass );
return (MutabilityPlan<J>) planBean.getBeanInstance();

View File

@ -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.hibernate.orm.test.cdi.type;
import org.hibernate.resource.beans.container.internal.NotYetReadyException;
import org.junit.jupiter.api.Test;
import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
import jakarta.enterprise.inject.spi.AnnotatedType;
import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.enterprise.inject.spi.InjectionTarget;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Steve Ebersole
*/
public class CdiSmokeTests {
@Test
void testCdiOperations() {
final SeContainerInitializer cdiInitializer = SeContainerInitializer.newInstance()
.disableDiscovery()
.addBeanClasses( UrlType.class, OtherBean.class );
try ( final SeContainer cdiContainer = cdiInitializer.initialize() ) {
final BeanManager beanManager = cdiContainer.getBeanManager();
final AnnotatedType<UrlType> annotatedType;
try {
annotatedType = beanManager.createAnnotatedType( UrlType.class );
}
catch (Exception e) {
throw new IllegalStateException( new NotYetReadyException( e ) );
}
final InjectionTarget<UrlType> injectionTarget = beanManager
.getInjectionTargetFactory( annotatedType )
.createInjectionTarget( null );
final CreationalContext<UrlType> creationalContext = beanManager.createCreationalContext( null );
final UrlType beanInstance = injectionTarget.produce( creationalContext );
injectionTarget.inject( beanInstance, creationalContext );
injectionTarget.postConstruct( beanInstance );
assertThat( beanInstance ).isNotNull();
// assertThat( beanInstance.getOtherBean() ).isNotNull();
}
}
}

View File

@ -0,0 +1,27 @@
/*
* 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.hibernate.orm.test.cdi.type;
import org.hibernate.resource.beans.container.spi.ExtendedBeanManager;
import jakarta.enterprise.inject.spi.BeanManager;
/**
* @author Steve Ebersole
*/
public class ExtendedBeanManagerImpl implements ExtendedBeanManager {
private LifecycleListener lifecycleListener;
@Override
public void registerLifecycleListener(LifecycleListener lifecycleListener) {
this.lifecycleListener = lifecycleListener;
}
public void injectBeanManager(BeanManager beanManager) {
lifecycleListener.beanManagerInitialized( beanManager );
}
}

View File

@ -0,0 +1,13 @@
/*
* 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.hibernate.orm.test.cdi.type;
/**
* @author Steve Ebersole
*/
public class OtherBean {
}

View File

@ -0,0 +1,120 @@
/*
* 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.hibernate.orm.test.cdi.type;
import java.net.URL;
import org.hibernate.SessionFactory;
import org.hibernate.annotations.Type;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.model.process.internal.UserTypeResolution;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.tool.schema.Action;
import org.junit.jupiter.api.Test;
import jakarta.enterprise.inject.se.SeContainer;
import jakarta.enterprise.inject.se.SeContainerInitializer;
import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.persistence.Basic;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Steve Ebersole
*/
public class SimpleTests {
@Test
void testProperUsage() {
final ExtendedBeanManagerImpl extendedBeanManager = new ExtendedBeanManagerImpl();
final StandardServiceRegistryBuilder ssrbBuilder = new StandardServiceRegistryBuilder()
.applySetting( AvailableSettings.HBM2DDL_AUTO, Action.CREATE_DROP )
.applySetting( AvailableSettings.JAKARTA_CDI_BEAN_MANAGER, extendedBeanManager );
try ( final StandardServiceRegistry ssr = ssrbBuilder.build() ) {
final Metadata metadata = new MetadataSources( ssr )
.addAnnotatedClass( MappedEntity.class )
.buildMetadata();
final PersistentClass entityBinding = metadata.getEntityBinding( MappedEntity.class.getName() );
final Property property = entityBinding.getProperty( "url" );
assertThat( property ).isNotNull();
assertThat( property.getValue() ).isInstanceOf( BasicValue.class );
final BasicValue.Resolution<?> resolution = ( (BasicValue) property.getValue() ).getResolution();
assertThat( resolution ).isNotNull();
assertThat( resolution ).isInstanceOf( UserTypeResolution.class );
// assertThat( ( (UserTypeResolution) resolution ).isResolved() ).isFalse();
final SeContainerInitializer cdiInitializer = SeContainerInitializer.newInstance()
.disableDiscovery()
.addBeanClasses( UrlType.class, OtherBean.class );
try ( final SeContainer cdiContainer = cdiInitializer.initialize() ) {
final BeanManager beanManager = cdiContainer.getBeanManager();
extendedBeanManager.injectBeanManager( beanManager );
}
try ( final SessionFactory sf = metadata.buildSessionFactory() ) {
sf.inSession( (session) -> {
session.createSelectionQuery( "from MappedEntity" ).list();
} );
}
}
}
@Entity( name = "MappedEntity" )
@Table( name = "mapped_entity" )
public static class MappedEntity {
@Id
private Integer id;
@Basic
private String name;
@Basic
@Type( UrlType.class )
private URL url;
protected MappedEntity() {
// for use by Hibernate
}
public MappedEntity(Integer id, String name, URL url) {
this.id = id;
this.name = name;
this.url = url;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public URL getUrl() {
return url;
}
public void setUrl(URL url) {
this.url = url;
}
}
}

View File

@ -0,0 +1,91 @@
/*
* 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.hibernate.orm.test.cdi.type;
import java.io.Serializable;
import java.net.URL;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.SqlTypes;
import org.hibernate.usertype.UserType;
import jakarta.inject.Singleton;
import org.assertj.core.util.Objects;
/**
* @author Steve Ebersole
*/
@Singleton
public class UrlType implements UserType<URL> {
// because we cannot use CDI, injection is not available
// private final OtherBean otherBean;
//
// @Inject
// public UrlType(OtherBean otherBean) {
// if ( otherBean == null ) {
// throw new UnsupportedOperationException( "OtherBean cannot be null" );
// }
// this.otherBean = otherBean;
// }
//
// public OtherBean getOtherBean() {
// return otherBean;
// }
@Override
public int getSqlType() {
return SqlTypes.VARCHAR;
}
@Override
public Class<URL> returnedClass() {
return URL.class;
}
@Override
public boolean equals(URL x, URL y) {
return Objects.areEqual( x, y );
}
@Override
public int hashCode(URL x) {
return Objects.hashCodeFor( x );
}
@Override
public URL nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException {
throw new UnsupportedOperationException( "Not used" );
}
@Override
public void nullSafeSet(PreparedStatement st, URL value, int index, SharedSessionContractImplementor session) throws SQLException {
throw new UnsupportedOperationException( "Not used" );
}
@Override
public URL deepCopy(URL value) {
throw new UnsupportedOperationException( "Not used" );
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(URL value) {
throw new UnsupportedOperationException( "Not used" );
}
@Override
public URL assemble(Serializable cached, Object owner) {
throw new UnsupportedOperationException( "Not used" );
}
}

View File

@ -6,23 +6,9 @@
*/
package org.hibernate.orm.test.idgen.userdefined;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.times;
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
@ -39,13 +25,26 @@ import org.hibernate.resource.beans.container.spi.BeanContainer;
import org.hibernate.resource.beans.container.spi.BeanContainer.LifecycleOptions;
import org.hibernate.resource.beans.container.spi.ContainedBean;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.BaseUnitTest;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.mockito.Mockito;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.times;
/**
* @author Yanming Zhou
*/
@ -65,7 +64,8 @@ public class UserDefinedGeneratorsTests {
} );
final StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder();
ssrb.applySetting( AvailableSettings.BEAN_CONTAINER, beanContainer );
ssrb.applySetting( AvailableSettings.BEAN_CONTAINER, beanContainer )
.applySetting( AvailableSettings.ALLOW_EXTENSIONS_IN_CDI, "true" );
try (final StandardServiceRegistry ssr = ssrb.build()) {
final Metadata metadata = new MetadataSources( ssr )

View File

@ -21,6 +21,7 @@ import org.hibernate.mapping.Value;
import org.hibernate.metamodel.internal.EmbeddableCompositeUserTypeInstantiator;
import org.hibernate.metamodel.internal.EmbeddableInstantiatorPojoIndirecting;
import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.usertype.CompositeUserType;
@ -52,23 +53,33 @@ public final class ComponentMetadataGenerator extends AbstractMetadataGenerator
final Component propComponent = (Component) value;
final EmbeddableInstantiator instantiator;
if ( propComponent.getCustomInstantiator() != null ) {
instantiator = getMetadataBuildingContext().getBootstrapContext()
if ( getMetadataBuildingContext().getBuildingOptions().disallowExtensionsInCdi() ) {
instantiator = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( propComponent.getCustomInstantiator() );
}
else
instantiator = getMetadataBuildingContext().getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean( propComponent.getCustomInstantiator() )
.getBeanInstance();
}
else if ( propComponent.getTypeName() != null ) {
final CompositeUserType<Object> compositeUserType = (CompositeUserType<Object>) getMetadataBuildingContext().getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean(
getMetadataBuildingContext().getBootstrapContext()
.getClassLoaderAccess()
.classForName( propComponent.getTypeName() )
)
.getBeanInstance();
instantiator = new EmbeddableCompositeUserTypeInstantiator( compositeUserType );
final Class<CompositeUserType<?>> userTypeClass = getMetadataBuildingContext().getBootstrapContext()
.getClassLoaderAccess()
.classForName( propComponent.getTypeName() );
if ( getMetadataBuildingContext().getBuildingOptions().disallowExtensionsInCdi() ) {
final CompositeUserType<?> compositeUserType = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( userTypeClass );
//noinspection rawtypes
instantiator = new EmbeddableCompositeUserTypeInstantiator( (CompositeUserType) compositeUserType );
}
else {
final CompositeUserType<Object> compositeUserType = (CompositeUserType<Object>) getMetadataBuildingContext().getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class )
.getBean( userTypeClass )
.getBeanInstance();
instantiator = new EmbeddableCompositeUserTypeInstantiator( compositeUserType );
}
}
else if ( propComponent.getInstantiator() != null ) {
instantiator = EmbeddableInstantiatorPojoIndirecting.of(

View File

@ -15,8 +15,11 @@ import org.hibernate.envers.RevisionType;
import org.hibernate.envers.exception.AuditException;
import org.hibernate.envers.internal.synchronization.SessionCacheCleaner;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.internal.Helper;
import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.resource.beans.spi.ProvidedInstanceManagedBeanImpl;
import org.hibernate.service.ServiceRegistry;
/**
@ -107,6 +110,11 @@ public class DefaultRevisionInfoGenerator implements RevisionInfoGenerator {
Class<? extends RevisionListener> listenerClass,
ServiceRegistry serviceRegistry) {
if ( !listenerClass.equals( RevisionListener.class ) ) {
if ( Helper.allowExtensionsInCdi( serviceRegistry ) ) {
return new ProvidedInstanceManagedBeanImpl<>(
FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( listenerClass )
);
}
return serviceRegistry.getService( ManagedBeanRegistry.class ).getBean( listenerClass );
}
return null;