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 String schemaCharset;
private final boolean xmlMappingEnabled; private final boolean xmlMappingEnabled;
private final boolean allowExtensionsInCdi;
public MetadataBuildingOptionsImpl(StandardServiceRegistry serviceRegistry) { public MetadataBuildingOptionsImpl(StandardServiceRegistry serviceRegistry) {
this.serviceRegistry = serviceRegistry; this.serviceRegistry = serviceRegistry;
@ -763,6 +764,12 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
String.class, String.class,
null null
); );
allowExtensionsInCdi = configService.getSetting(
AvailableSettings.ALLOW_EXTENSIONS_IN_CDI,
StandardConverters.BOOLEAN,
false
);
} }
private ArrayList<MetadataSourceType> resolveInitialSourceProcessOrdering(ConfigurationService configService) { private ArrayList<MetadataSourceType> resolveInitialSourceProcessOrdering(ConfigurationService configService) {
@ -951,6 +958,11 @@ public class MetadataBuilderImpl implements MetadataBuilderImplementor, TypeCont
return xmlMappingEnabled; return xmlMappingEnabled;
} }
@Override
public boolean disallowExtensionsInCdi() {
return allowExtensionsInCdi;
}
/** /**
* Yuck. This is needed because JPA lets users define "global building options" * Yuck. This is needed because JPA lets users define "global building options"
* in {@code orm.xml} mappings. Forget that there are generally multiple * 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.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.BasicValue; import org.hibernate.mapping.BasicValue;
import org.hibernate.metamodel.mapping.JdbcMapping; 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.internal.Helper;
import org.hibernate.resource.beans.spi.BeanInstanceProducer; import org.hibernate.resource.beans.spi.BeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBean; 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.CustomType;
import org.hibernate.type.SerializableType; import org.hibernate.type.SerializableType;
import org.hibernate.type.Type; 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.ImmutableMutabilityPlan;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.MutabilityPlan; import org.hibernate.type.descriptor.java.MutabilityPlan;
@ -137,6 +137,9 @@ public class TypeDefinition implements Serializable {
Map<?,?> usageSiteProperties, Map<?,?> usageSiteProperties,
JdbcTypeIndicators indicators, JdbcTypeIndicators indicators,
MetadataBuildingContext context) { MetadataBuildingContext context) {
if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
}
final BootstrapContext bootstrapContext = context.getBootstrapContext(); final BootstrapContext bootstrapContext = context.getBootstrapContext();
final TypeConfiguration typeConfiguration = bootstrapContext.getTypeConfiguration(); final TypeConfiguration typeConfiguration = bootstrapContext.getTypeConfiguration();
final BeanInstanceProducer instanceProducer = bootstrapContext.getCustomTypeProducer(); final BeanInstanceProducer instanceProducer = bootstrapContext.getCustomTypeProducer();
@ -282,13 +285,13 @@ public class TypeDefinition implements Serializable {
private static Object instantiateType(StandardServiceRegistry serviceRegistry, private static Object instantiateType(StandardServiceRegistry serviceRegistry,
String name, Class<?> typeImplementorClass, String name, Class<?> typeImplementorClass,
BeanInstanceProducer instanceProducer) { BeanInstanceProducer instanceProducer) {
if ( Helper.shouldIgnoreBeanContainer( serviceRegistry ) ) { if ( !Helper.allowExtensionsInCdi( serviceRegistry ) ) {
return name != null return name != null
? instanceProducer.produceBeanInstance( name, typeImplementorClass ) ? instanceProducer.produceBeanInstance( name, typeImplementorClass )
: instanceProducer.produceBeanInstance( typeImplementorClass ); : instanceProducer.produceBeanInstance( typeImplementorClass );
} }
else { else {
ManagedBeanRegistry beanRegistry = serviceRegistry.getService(ManagedBeanRegistry.class); final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
final ManagedBean<?> typeBean = name != null final ManagedBean<?> typeBean = name != null
? beanRegistry.getBean( name, typeImplementorClass, instanceProducer ) ? beanRegistry.getBean( name, typeImplementorClass, instanceProducer )
: beanRegistry.getBean( typeImplementorClass, instanceProducer ); : beanRegistry.getBean( typeImplementorClass, instanceProducer );

View File

@ -12,14 +12,30 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; 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.AnnotationException;
import org.hibernate.MappingException; 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.ReflectionManager;
import org.hibernate.annotations.common.reflection.XAnnotatedElement; import org.hibernate.annotations.common.reflection.XAnnotatedElement;
import org.hibernate.annotations.common.reflection.XClass; 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.GenericsHelper;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.metamodel.mapping.JdbcMapping; 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.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
import org.hibernate.type.CustomType; 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.BasicJavaType;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.spi.JavaTypeRegistry; 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.type.spi.TypeConfiguration;
import org.hibernate.usertype.UserType; 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 java.util.Collections.emptyMap;
import static org.hibernate.boot.model.internal.AnnotatedClassType.ENTITY; 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.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.getInheritanceStateOfSuperEntity;
import static org.hibernate.boot.model.internal.InheritanceState.getSuperclassInheritanceState; import static org.hibernate.boot.model.internal.InheritanceState.getSuperclassInheritanceState;
import static org.hibernate.internal.CoreLogging.messageLogger; import static org.hibernate.internal.CoreLogging.messageLogger;
@ -459,7 +494,15 @@ public final class AnnotationBinder {
ManagedBeanRegistry managedBeanRegistry, ManagedBeanRegistry managedBeanRegistry,
JdbcTypeRegistration annotation) { JdbcTypeRegistration annotation) {
final Class<? extends JdbcType> jdbcTypeClass = annotation.value(); 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 final int typeCode = annotation.registrationCode() == Integer.MIN_VALUE
? jdbcType.getDefaultSqlTypeCode() ? jdbcType.getDefaultSqlTypeCode()
: annotation.registrationCode(); : annotation.registrationCode();
@ -470,9 +513,16 @@ public final class AnnotationBinder {
MetadataBuildingContext context, MetadataBuildingContext context,
ManagedBeanRegistry managedBeanRegistry, ManagedBeanRegistry managedBeanRegistry,
JavaTypeRegistration annotation) { JavaTypeRegistration annotation) {
final Class<? extends BasicJavaType<?>> jtdClass = annotation.descriptorClass(); final Class<? extends BasicJavaType<?>> javaTypeClass = annotation.descriptorClass();
final BasicJavaType<?> jtd = managedBeanRegistry.getBean( jtdClass ).getBeanInstance();
context.getMetadataCollector().addJavaTypeRegistration( annotation.javaType(), jtd ); 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( private static void bindEmbeddableInstantiatorRegistrations(
@ -700,11 +750,18 @@ public final class AnnotationBinder {
} }
} }
private static JdbcMapping resolveUserType(Class<UserType<?>> type, MetadataBuildingContext context) { 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 StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry();
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class ); final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
final ManagedBean<UserType<?>> bean = beanRegistry.getBean( type ); userType = beanRegistry.getBean( userTypeClass ).getBeanInstance();
return new CustomType<>( bean.getBeanInstance(), context.getBootstrapContext().getTypeConfiguration() ); }
return new CustomType<>( userType, context.getBootstrapContext().getTypeConfiguration() );
} }
private static JdbcMapping resolveAttributeConverter(Class<AttributeConverter<?, ?>> type, MetadataBuildingContext context) { private static JdbcMapping resolveAttributeConverter(Class<AttributeConverter<?, ?>> type, MetadataBuildingContext context) {
@ -747,18 +804,21 @@ public final class AnnotationBinder {
} }
private static JavaType<?> getJavaType( private static JavaType<?> getJavaType(
Class<JavaType<?>> type, Class<JavaType<?>> javaTypeClass,
MetadataBuildingContext context, MetadataBuildingContext context,
TypeConfiguration typeConfiguration) { TypeConfiguration typeConfiguration) {
final JavaType<?> registeredJtd = typeConfiguration.getJavaTypeRegistry().findDescriptor( type ); final JavaType<?> registeredJtd = typeConfiguration.getJavaTypeRegistry().findDescriptor( javaTypeClass );
if ( registeredJtd != null ) { if ( registeredJtd != null ) {
return registeredJtd; return registeredJtd;
} }
else {
if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry(); final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry();
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class ); final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
return beanRegistry.getBean(type).getBeanInstance(); return beanRegistry.getBean(javaTypeClass).getBeanInstance();
}
} }
public static void bindFetchProfilesForClass(XClass annotatedClass, MetadataBuildingContext context) { 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.CollectionIdJdbcType;
import org.hibernate.annotations.CollectionIdJdbcTypeCode; import org.hibernate.annotations.CollectionIdJdbcTypeCode;
import org.hibernate.annotations.CollectionIdMutability; import org.hibernate.annotations.CollectionIdMutability;
import org.hibernate.annotations.PartitionKey;
import org.hibernate.annotations.CollectionIdType; import org.hibernate.annotations.CollectionIdType;
import org.hibernate.annotations.Immutable; import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.JdbcTypeCode; import org.hibernate.annotations.JdbcTypeCode;
@ -43,6 +42,7 @@ import org.hibernate.annotations.MapKeyType;
import org.hibernate.annotations.Mutability; import org.hibernate.annotations.Mutability;
import org.hibernate.annotations.Nationalized; import org.hibernate.annotations.Nationalized;
import org.hibernate.annotations.Parameter; import org.hibernate.annotations.Parameter;
import org.hibernate.annotations.PartitionKey;
import org.hibernate.annotations.Target; import org.hibernate.annotations.Target;
import org.hibernate.annotations.TimeZoneColumn; import org.hibernate.annotations.TimeZoneColumn;
import org.hibernate.annotations.TimeZoneStorage; import org.hibernate.annotations.TimeZoneStorage;
@ -57,12 +57,12 @@ import org.hibernate.boot.spi.InFlightMetadataCollector;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.NationalizationSupport; import org.hibernate.dialect.NationalizationSupport;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.mapping.BasicValue; import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Component; import org.hibernate.mapping.Component;
import org.hibernate.mapping.Table; 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.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
@ -430,17 +430,22 @@ public class BasicValueBinder implements JdbcTypeIndicators {
throw new MappingException( "idbag mapping missing @CollectionId" ); throw new MappingException( "idbag mapping missing @CollectionId" );
} }
final boolean useDeferredBeanContainerAccess = buildingContext.getBuildingOptions().disallowExtensionsInCdi();
final ManagedBeanRegistry beanRegistry = getManagedBeanRegistry(); final ManagedBeanRegistry beanRegistry = getManagedBeanRegistry();
explicitBasicTypeName = null; explicitBasicTypeName = null;
implicitJavaTypeAccess = (typeConfiguration) -> null; implicitJavaTypeAccess = (typeConfiguration) -> null;
explicitJavaTypeAccess = (typeConfiguration) -> { explicitJavaTypeAccess = (typeConfiguration) -> {
final CollectionIdJavaType javaTypeAnn = findAnnotation( modelXProperty, CollectionIdJavaType.class ); final CollectionIdJavaType javaTypeAnn = findAnnotation( modelXProperty, CollectionIdJavaType.class );
if ( javaTypeAnn != null ) { if ( javaTypeAnn != null ) {
final Class<? extends BasicJavaType<?>> javaType = normalizeJavaType( javaTypeAnn.value() ); final Class<? extends BasicJavaType<?>> javaTypeClass = normalizeJavaType( javaTypeAnn.value() );
if ( javaType != null ) { if ( javaTypeClass != null ) {
final ManagedBean<? extends BasicJavaType<?>> bean = beanRegistry.getBean( javaType ); if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
final ManagedBean<? extends BasicJavaType<?>> bean = beanRegistry.getBean( javaTypeClass );
return bean.getBeanInstance(); return bean.getBeanInstance();
} }
} }
@ -451,9 +456,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJdbcTypeAccess = (typeConfiguration) -> { explicitJdbcTypeAccess = (typeConfiguration) -> {
final CollectionIdJdbcType jdbcTypeAnn = findAnnotation( modelXProperty, CollectionIdJdbcType.class ); final CollectionIdJdbcType jdbcTypeAnn = findAnnotation( modelXProperty, CollectionIdJdbcType.class );
if ( jdbcTypeAnn != null ) { if ( jdbcTypeAnn != null ) {
final Class<? extends JdbcType> jdbcType = normalizeJdbcType( jdbcTypeAnn.value() ); final Class<? extends JdbcType> jdbcTypeClass = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcType != null ) { if ( jdbcTypeClass != null ) {
final ManagedBean<? extends JdbcType> managedBean = beanRegistry.getBean( jdbcType ); if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass );
}
final ManagedBean<? extends JdbcType> managedBean = beanRegistry.getBean( jdbcTypeClass );
return managedBean.getBeanInstance(); return managedBean.getBeanInstance();
} }
} }
@ -471,9 +479,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitMutabilityAccess = (typeConfiguration) -> { explicitMutabilityAccess = (typeConfiguration) -> {
final CollectionIdMutability mutabilityAnn = findAnnotation( modelXProperty, CollectionIdMutability.class ); final CollectionIdMutability mutabilityAnn = findAnnotation( modelXProperty, CollectionIdMutability.class );
if ( mutabilityAnn != null ) { if ( mutabilityAnn != null ) {
final Class<? extends MutabilityPlan<?>> mutability = normalizeMutability( mutabilityAnn.value() ); final Class<? extends MutabilityPlan<?>> mutabilityClass = normalizeMutability( mutabilityAnn.value() );
if ( mutability != null ) { if ( mutabilityClass != null ) {
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = beanRegistry.getBean( mutability ); if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( mutabilityClass );
}
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = beanRegistry.getBean( mutabilityClass );
return jtdBean.getBeanInstance(); return jtdBean.getBeanInstance();
} }
} }
@ -492,6 +503,9 @@ public class BasicValueBinder implements JdbcTypeIndicators {
if ( converterDescriptor != null ) { if ( converterDescriptor != null ) {
final Mutability converterMutabilityAnn = converterDescriptor.getAttributeConverterClass().getAnnotation( Mutability.class ); final Mutability converterMutabilityAnn = converterDescriptor.getAttributeConverterClass().getAnnotation( Mutability.class );
if ( converterMutabilityAnn != null ) { if ( converterMutabilityAnn != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( converterMutabilityAnn.value() );
}
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = beanRegistry.getBean( converterMutabilityAnn.value() ); final ManagedBean<? extends MutabilityPlan<?>> jtdBean = beanRegistry.getBean( converterMutabilityAnn.value() );
return jtdBean.getBeanInstance(); return jtdBean.getBeanInstance();
} }
@ -537,12 +551,17 @@ public class BasicValueBinder implements JdbcTypeIndicators {
temporalPrecision = mapKeyTemporalAnn.value(); temporalPrecision = mapKeyTemporalAnn.value();
} }
final boolean useDeferredBeanContainerAccess = buildingContext.getBuildingOptions().disallowExtensionsInCdi();
explicitJdbcTypeAccess = typeConfiguration -> { explicitJdbcTypeAccess = typeConfiguration -> {
final MapKeyJdbcType jdbcTypeAnn = findAnnotation( mapAttribute, MapKeyJdbcType.class ); final MapKeyJdbcType jdbcTypeAnn = findAnnotation( mapAttribute, MapKeyJdbcType.class );
if ( jdbcTypeAnn != null ) { if ( jdbcTypeAnn != null ) {
final Class<? extends JdbcType> jdbcTypeImpl = normalizeJdbcType( jdbcTypeAnn.value() ); final Class<? extends JdbcType> jdbcTypeClass = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcTypeImpl != null ) { if ( jdbcTypeClass != null ) {
return getManagedBeanRegistry().getBean( jdbcTypeImpl ).getBeanInstance(); if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass );
}
return getManagedBeanRegistry().getBean( jdbcTypeClass ).getBeanInstance();
} }
} }
@ -560,9 +579,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJavaTypeAccess = typeConfiguration -> { explicitJavaTypeAccess = typeConfiguration -> {
final MapKeyJavaType javaTypeAnn = findAnnotation( mapAttribute, MapKeyJavaType.class ); final MapKeyJavaType javaTypeAnn = findAnnotation( mapAttribute, MapKeyJavaType.class );
if ( javaTypeAnn != null ) { if ( javaTypeAnn != null ) {
final Class<? extends BasicJavaType<?>> jdbcTypeImpl = normalizeJavaType( javaTypeAnn.value() ); final Class<? extends BasicJavaType<?>> javaTypeClass = normalizeJavaType( javaTypeAnn.value() );
if ( jdbcTypeImpl != null ) { if ( javaTypeClass != null ) {
return getManagedBeanRegistry().getBean( jdbcTypeImpl ).getBeanInstance(); if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
return getManagedBeanRegistry().getBean( javaTypeClass ).getBeanInstance();
} }
} }
@ -578,9 +600,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitMutabilityAccess = typeConfiguration -> { explicitMutabilityAccess = typeConfiguration -> {
final MapKeyMutability mutabilityAnn = findAnnotation( mapAttribute, MapKeyMutability.class ); final MapKeyMutability mutabilityAnn = findAnnotation( mapAttribute, MapKeyMutability.class );
if ( mutabilityAnn != null ) { if ( mutabilityAnn != null ) {
final Class<? extends MutabilityPlan<?>> mutability = normalizeMutability( mutabilityAnn.value() ); final Class<? extends MutabilityPlan<?>> mutabilityClass = normalizeMutability( mutabilityAnn.value() );
if ( mutability != null ) { if ( mutabilityClass != null ) {
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = getManagedBeanRegistry().getBean( mutability ); if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( mutabilityClass );
}
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = getManagedBeanRegistry().getBean( mutabilityClass );
return jtdBean.getBeanInstance(); return jtdBean.getBeanInstance();
} }
} }
@ -599,6 +624,9 @@ public class BasicValueBinder implements JdbcTypeIndicators {
if ( converterDescriptor != null ) { if ( converterDescriptor != null ) {
final Mutability converterMutabilityAnn = converterDescriptor.getAttributeConverterClass().getAnnotation( Mutability.class ); final Mutability converterMutabilityAnn = converterDescriptor.getAttributeConverterClass().getAnnotation( Mutability.class );
if ( converterMutabilityAnn != null ) { if ( converterMutabilityAnn != null ) {
if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( converterMutabilityAnn.value() );
}
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = getManagedBeanRegistry().getBean( converterMutabilityAnn.value() ); final ManagedBean<? extends MutabilityPlan<?>> jtdBean = getManagedBeanRegistry().getBean( converterMutabilityAnn.value() );
return jtdBean.getBeanInstance(); return jtdBean.getBeanInstance();
} }
@ -623,6 +651,7 @@ public class BasicValueBinder implements JdbcTypeIndicators {
private void prepareListIndex(XProperty listAttribute) { private void prepareListIndex(XProperty listAttribute) {
implicitJavaTypeAccess = typeConfiguration -> Integer.class; implicitJavaTypeAccess = typeConfiguration -> Integer.class;
final boolean useDeferredBeanContainerAccess = buildingContext.getBuildingOptions().disallowExtensionsInCdi();
final ManagedBeanRegistry beanRegistry = buildingContext final ManagedBeanRegistry beanRegistry = buildingContext
.getBootstrapContext() .getBootstrapContext()
.getServiceRegistry() .getServiceRegistry()
@ -631,9 +660,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJavaTypeAccess = (typeConfiguration) -> { explicitJavaTypeAccess = (typeConfiguration) -> {
final ListIndexJavaType javaTypeAnn = findAnnotation( listAttribute, ListIndexJavaType.class ); final ListIndexJavaType javaTypeAnn = findAnnotation( listAttribute, ListIndexJavaType.class );
if ( javaTypeAnn != null ) { if ( javaTypeAnn != null ) {
final Class<? extends BasicJavaType<?>> javaType = normalizeJavaType( javaTypeAnn.value() ); final Class<? extends BasicJavaType<?>> javaTypeClass = normalizeJavaType( javaTypeAnn.value() );
if ( javaType != null ) { if ( javaTypeClass != null ) {
final ManagedBean<? extends BasicJavaType<?>> bean = beanRegistry.getBean( javaType ); if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
final ManagedBean<? extends BasicJavaType<?>> bean = beanRegistry.getBean( javaTypeClass );
return bean.getBeanInstance(); return bean.getBeanInstance();
} }
} }
@ -644,9 +676,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJdbcTypeAccess = (typeConfiguration) -> { explicitJdbcTypeAccess = (typeConfiguration) -> {
final ListIndexJdbcType jdbcTypeAnn = findAnnotation( listAttribute, ListIndexJdbcType.class ); final ListIndexJdbcType jdbcTypeAnn = findAnnotation( listAttribute, ListIndexJdbcType.class );
if ( jdbcTypeAnn != null ) { if ( jdbcTypeAnn != null ) {
final Class<? extends JdbcType> jdbcType = normalizeJdbcType( jdbcTypeAnn.value() ); final Class<? extends JdbcType> jdbcTypeClass = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcType != null ) { if ( jdbcTypeClass != null ) {
final ManagedBean<? extends JdbcType> bean = beanRegistry.getBean( jdbcType ); if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass );
}
final ManagedBean<? extends JdbcType> bean = beanRegistry.getBean( jdbcTypeClass );
return bean.getBeanInstance(); return bean.getBeanInstance();
} }
} }
@ -831,13 +866,18 @@ public class BasicValueBinder implements JdbcTypeIndicators {
private void prepareAnyKey(XProperty modelXProperty) { private void prepareAnyKey(XProperty modelXProperty) {
implicitJavaTypeAccess = (typeConfiguration) -> null; implicitJavaTypeAccess = (typeConfiguration) -> null;
final boolean useDeferredBeanContainerAccess = buildingContext.getBuildingOptions().disallowExtensionsInCdi();
explicitJavaTypeAccess = (typeConfiguration) -> { explicitJavaTypeAccess = (typeConfiguration) -> {
final AnyKeyJavaType javaTypeAnn = findAnnotation( modelXProperty, AnyKeyJavaType.class ); final AnyKeyJavaType javaTypeAnn = findAnnotation( modelXProperty, AnyKeyJavaType.class );
if ( javaTypeAnn != null ) { if ( javaTypeAnn != null ) {
final Class<? extends BasicJavaType<?>> javaType = normalizeJavaType( javaTypeAnn.value() ); final Class<? extends BasicJavaType<?>> javaTypeClass = normalizeJavaType( javaTypeAnn.value() );
if ( javaType != null ) { if ( javaTypeClass != null ) {
return getManagedBeanRegistry().getBean( javaType ).getBeanInstance(); if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
return getManagedBeanRegistry().getBean( javaTypeClass ).getBeanInstance();
} }
} }
@ -855,9 +895,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJdbcTypeAccess = (typeConfiguration) -> { explicitJdbcTypeAccess = (typeConfiguration) -> {
final AnyKeyJdbcType jdbcTypeAnn = findAnnotation( modelXProperty, AnyKeyJdbcType.class ); final AnyKeyJdbcType jdbcTypeAnn = findAnnotation( modelXProperty, AnyKeyJdbcType.class );
if ( jdbcTypeAnn != null ) { if ( jdbcTypeAnn != null ) {
final Class<? extends JdbcType> jdbcType = normalizeJdbcType( jdbcTypeAnn.value() ); final Class<? extends JdbcType> jdbcTypeClass = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcType != null ) { if ( jdbcTypeClass != null ) {
final ManagedBean<? extends JdbcType> jtdBean = getManagedBeanRegistry().getBean( jdbcType ); if ( useDeferredBeanContainerAccess ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( jdbcTypeClass );
}
final ManagedBean<? extends JdbcType> jtdBean = getManagedBeanRegistry().getBean( jdbcTypeClass );
return jtdBean.getBeanInstance(); 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 ); final org.hibernate.annotations.JdbcType jdbcTypeAnn = findAnnotation( attributeXProperty, org.hibernate.annotations.JdbcType.class );
if ( jdbcTypeAnn != null ) { if ( jdbcTypeAnn != null ) {
final Class<? extends JdbcType> jdbcType = normalizeJdbcType( jdbcTypeAnn.value() ); final Class<? extends JdbcType> jdbcTypeClass = normalizeJdbcType( jdbcTypeAnn.value() );
if ( jdbcType != null ) { if ( jdbcTypeClass != null ) {
return getManagedBeanRegistry().getBean( jdbcType ).getBeanInstance(); 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 ) { if ( mutabilityAnn != null ) {
final Class<? extends MutabilityPlan<?>> mutability = normalizeMutability( mutabilityAnn.value() ); final Class<? extends MutabilityPlan<?>> mutability = normalizeMutability( mutabilityAnn.value() );
if ( mutability != null ) { if ( mutability != null ) {
if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( mutability );
}
return getManagedBeanRegistry().getBean( mutability ).getBeanInstance(); return getManagedBeanRegistry().getBean( mutability ).getBeanInstance();
} }
} }
@ -926,6 +975,9 @@ public class BasicValueBinder implements JdbcTypeIndicators {
if ( converterDescriptor != null ) { if ( converterDescriptor != null ) {
final Mutability converterMutabilityAnn = converterDescriptor.getAttributeConverterClass().getAnnotation( Mutability.class ); final Mutability converterMutabilityAnn = converterDescriptor.getAttributeConverterClass().getAnnotation( Mutability.class );
if ( converterMutabilityAnn != null ) { if ( converterMutabilityAnn != null ) {
if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( converterMutabilityAnn.value() );
}
final ManagedBean<? extends MutabilityPlan<?>> jtdBean = getManagedBeanRegistry().getBean( converterMutabilityAnn.value() ); final ManagedBean<? extends MutabilityPlan<?>> jtdBean = getManagedBeanRegistry().getBean( converterMutabilityAnn.value() );
return jtdBean.getBeanInstance(); return jtdBean.getBeanInstance();
} }
@ -952,10 +1004,12 @@ public class BasicValueBinder implements JdbcTypeIndicators {
explicitJavaTypeAccess = typeConfiguration -> { explicitJavaTypeAccess = typeConfiguration -> {
final org.hibernate.annotations.JavaType javaTypeAnn = findAnnotation( attributeXProperty, org.hibernate.annotations.JavaType.class ); final org.hibernate.annotations.JavaType javaTypeAnn = findAnnotation( attributeXProperty, org.hibernate.annotations.JavaType.class );
if ( javaTypeAnn != null ) { if ( javaTypeAnn != null ) {
final Class<? extends BasicJavaType<?>> javaType = normalizeJavaType( javaTypeAnn.value() ); final Class<? extends BasicJavaType<?>> javaTypeClass = normalizeJavaType( javaTypeAnn.value() );
if ( javaTypeClass != null ) {
if ( javaType != null ) { if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
final ManagedBean<? extends BasicJavaType<?>> jtdBean = getManagedBeanRegistry().getBean( javaType ); return FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( javaTypeClass );
}
final ManagedBean<? extends BasicJavaType<?>> jtdBean = getManagedBeanRegistry().getBean( javaTypeClass );
return jtdBean.getBeanInstance(); return jtdBean.getBeanInstance();
} }
} }

View File

@ -98,6 +98,7 @@ import org.hibernate.mapping.DependantValue;
import org.hibernate.mapping.Join; import org.hibernate.mapping.Join;
import org.hibernate.mapping.KeyValue; import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.ManyToOne; import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.MappingHelper;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property; import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable; 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.buildJoinColumnsWithDefaultColumnSuffix;
import static org.hibernate.boot.model.internal.AnnotatedJoinColumns.buildJoinTableJoinColumns; 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.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.createSyntheticPropertyReference;
import static org.hibernate.boot.model.internal.BinderHelper.getCascadeStrategy; import static org.hibernate.boot.model.internal.BinderHelper.getCascadeStrategy;
import static org.hibernate.boot.model.internal.BinderHelper.getFetchMode; 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.toAliasEntityMap;
import static org.hibernate.boot.model.internal.BinderHelper.toAliasTableMap; 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.EmbeddableBinder.fillEmbeddable;
import static org.hibernate.boot.model.internal.GeneratorBinder.buildGenerators;
import static org.hibernate.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder; 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.cfg.AvailableSettings.USE_ENTITY_WHERE_CLAUSE_FOR_COLLECTIONS;
import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.fromResultCheckStyle; import static org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle.fromResultCheckStyle;
@ -845,37 +846,41 @@ public abstract class CollectionBinder {
Class<? extends UserCollectionType> implementation, Class<? extends UserCollectionType> implementation,
Map<String,String> parameters, Map<String,String> parameters,
MetadataBuildingContext buildingContext) { 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() final ManagedBeanRegistry beanRegistry = buildingContext.getBuildingOptions()
.getServiceRegistry() .getServiceRegistry()
.getService( ManagedBeanRegistry.class ); .getService( ManagedBeanRegistry.class );
if ( CollectionHelper.isNotEmpty( parameters ) ) { final ManagedBean<? extends UserCollectionType> managedBean = beanRegistry.getBean( implementation );
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 );
} }
else {
// defined parameters... // there were parameters, but the custom-type does not implement the interface
if ( ParameterizedType.class.isAssignableFrom( implementation ) ) { // used to inject them - log a "warning"
// 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( BootLogging.BOOT_LOGGER.debugf(
"Custom collection-type (`%s`) assigned to attribute (`%s`) does not implement `%s`, but its `@CollectionType` defined parameters", "`@CollectionType` (%s) specified parameters, but the" +
implementation.getName(), " implementation does not implement `%s` which is used to inject them - `%s`",
role, role,
ParameterizedType.class.getName() ParameterizedType.class.getName(),
implementation.getName()
); );
// but still return the bean - we can again use the no-config bean instance // fall through to returning `managedBean`
return beanRegistry.getBean( implementation );
}
} }
return managedBean;
} }
private static CollectionBinder createBinderFromProperty(XProperty property, MetadataBuildingContext context) { private static CollectionBinder createBinderFromProperty(XProperty property, MetadataBuildingContext context) {
@ -902,37 +907,15 @@ public abstract class CollectionBinder {
XProperty property, XProperty property,
CollectionType typeAnnotation, CollectionType typeAnnotation,
MetadataBuildingContext context) { MetadataBuildingContext context) {
final ManagedBeanRegistry beanRegistry = context.getBootstrapContext() final Properties parameters = extractParameters( typeAnnotation );
.getServiceRegistry()
.getService( ManagedBeanRegistry.class ); //noinspection unchecked,rawtypes
final Class<? extends UserCollectionType> typeImpl = typeAnnotation.type(); return createCustomType(
if ( typeAnnotation.parameters().length == 0 ) { property.getDeclaringClass().getName() + "." + property.getName(),
// no parameters - we can reuse a no-config bean instance typeAnnotation.type(),
return beanRegistry.getBean( typeImpl ); (Map) parameters,
} context
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 );
}
}
} }
private static Properties extractParameters(CollectionType typeAnnotation) { 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; package org.hibernate.boot.model.internal;
import jakarta.persistence.Column; import java.lang.annotation.Annotation;
import jakarta.persistence.Embeddable; import java.lang.reflect.Constructor;
import jakarta.persistence.Embedded; import java.lang.reflect.Type;
import jakarta.persistence.EmbeddedId; import java.util.ArrayList;
import jakarta.persistence.GeneratedValue; import java.util.HashMap;
import jakarta.persistence.Id; import java.util.List;
import jakarta.persistence.ManyToMany; import java.util.Map;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import org.hibernate.AnnotationException; import org.hibernate.AnnotationException;
import org.hibernate.annotations.Instantiator; import org.hibernate.annotations.Instantiator;
import org.hibernate.annotations.TypeBinderType; 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.PropertyAccessStrategyCompositeUserTypeImpl;
import org.hibernate.property.access.internal.PropertyAccessStrategyMixedImpl; import org.hibernate.property.access.internal.PropertyAccessStrategyMixedImpl;
import org.hibernate.property.access.spi.PropertyAccessStrategy; import org.hibernate.property.access.spi.PropertyAccessStrategy;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.usertype.CompositeUserType; import org.hibernate.usertype.CompositeUserType;
import java.lang.annotation.Annotation; import jakarta.persistence.Column;
import java.lang.reflect.Constructor; import jakarta.persistence.Embeddable;
import java.lang.reflect.Type; import jakarta.persistence.Embedded;
import java.util.ArrayList; import jakarta.persistence.EmbeddedId;
import java.util.HashMap; import jakarta.persistence.GeneratedValue;
import java.util.List; import jakarta.persistence.Id;
import java.util.Map; 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.getPath;
import static org.hibernate.boot.model.internal.BinderHelper.getPropertyOverriddenByMapperOrMapsId; 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.getRelativePath;
import static org.hibernate.boot.model.internal.BinderHelper.hasToOneAnnotation; 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.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.boot.model.internal.PropertyHolderBuilder.buildPropertyHolder;
import static org.hibernate.internal.CoreLogging.messageLogger; import static org.hibernate.internal.CoreLogging.messageLogger;
import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY; import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY;
@ -400,7 +402,12 @@ public class EmbeddableBinder {
private static CompositeUserType<?> compositeUserType( private static CompositeUserType<?> compositeUserType(
Class<? extends CompositeUserType<?>> compositeUserTypeClass, Class<? extends CompositeUserType<?>> compositeUserTypeClass,
MetadataBuildingContext context) { MetadataBuildingContext context) {
return context.getBootstrapContext().getServiceRegistry() if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( compositeUserTypeClass );
}
return context.getBootstrapContext()
.getServiceRegistry()
.getService( ManagedBeanRegistry.class ) .getService( ManagedBeanRegistry.class )
.getBean( compositeUserTypeClass ) .getBean( compositeUserTypeClass )
.getBeanInstance(); .getBeanInstance();

View File

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

View File

@ -7,7 +7,7 @@
package org.hibernate.boot.spi; package org.hibernate.boot.spi;
import java.util.List; import java.util.List;
import jakarta.persistence.SharedCacheMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.TimeZoneStorageStrategy; import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.boot.model.IdGeneratorStrategyInterpreter; import org.hibernate.boot.model.IdGeneratorStrategyInterpreter;
@ -21,6 +21,8 @@ import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.id.factory.IdentifierGeneratorFactory; import org.hibernate.id.factory.IdentifierGeneratorFactory;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import jakarta.persistence.SharedCacheMode;
/** /**
* Convenience base class for custom implementors of {@link MetadataBuildingOptions} using delegation. * Convenience base class for custom implementors of {@link MetadataBuildingOptions} using delegation.
* *
@ -169,4 +171,8 @@ public abstract class AbstractDelegatingMetadataBuildingOptions implements Metad
return delegate.isXmlMappingEnabled(); 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 java.util.List;
import jakarta.persistence.SharedCacheMode;
import org.hibernate.TimeZoneStorageStrategy; import org.hibernate.TimeZoneStorageStrategy;
import org.hibernate.boot.model.IdGeneratorStrategyInterpreter; import org.hibernate.boot.model.IdGeneratorStrategyInterpreter;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy; 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.metamodel.spi.ManagedTypeRepresentationResolver;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import jakarta.persistence.SharedCacheMode;
/** /**
* Describes the options used while building the {@link org.hibernate.boot.Metadata} * Describes the options used while building the {@link org.hibernate.boot.Metadata}
* object during {@link org.hibernate.boot.MetadataBuilder#build()} processing. * object during {@link org.hibernate.boot.MetadataBuilder#build()} processing.
@ -231,4 +231,9 @@ public interface MetadataBuildingOptions {
default boolean isXmlMappingEnabled() { default boolean isXmlMappingEnabled() {
return true; 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"; 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 * Constructs a new factory
*/ */
public StandardIdentifierGeneratorFactory(ServiceRegistry serviceRegistry) { 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.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.SelectablePath; 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.BeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBean; import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; 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.BasicType;
import org.hibernate.type.CustomType; import org.hibernate.type.CustomType;
import org.hibernate.type.Type; 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.BasicJavaType;
import org.hibernate.type.descriptor.java.BasicPluralJavaType; import org.hibernate.type.descriptor.java.BasicPluralJavaType;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
@ -793,18 +794,25 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol
properties.putAll( explicitLocalTypeParams ); properties.putAll( explicitLocalTypeParams );
} }
final ManagedBean<T> typeBean; final T typeInstance;
if ( properties.isEmpty() ) { if ( getBuildingContext().getBuildingOptions().disallowExtensionsInCdi() ) {
typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class ) typeInstance = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( explicitCustomType );
.getBean( explicitCustomType, instanceProducer );
} }
else { else {
final boolean hasParameters = CollectionHelper.isNotEmpty( properties );
final ManagedBean<T> typeBean;
if ( hasParameters ) {
final String name = explicitCustomType.getName() + COUNTER++; final String name = explicitCustomType.getName() + COUNTER++;
typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class ) typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class )
.getBean( name, explicitCustomType, instanceProducer ); .getBean( name, explicitCustomType, instanceProducer );
} }
else {
final T typeInstance = typeBean.getBeanInstance(); typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class )
.getBean( explicitCustomType, instanceProducer );
}
typeInstance = typeBean.getBeanInstance();
}
if ( typeInstance instanceof TypeConfigurationAware ) { if ( typeInstance instanceof TypeConfigurationAware ) {
( (TypeConfigurationAware) typeInstance ).setTypeConfiguration( getTypeConfiguration() ); ( (TypeConfigurationAware) typeInstance ).setTypeConfiguration( getTypeConfiguration() );

View File

@ -11,12 +11,17 @@ import java.util.Properties;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.hibernate.Internal; 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.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.MetadataBuildingContext; import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.MappingModelCreationLogger; 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.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.resource.beans.spi.ProvidedInstanceManagedBeanImpl;
import org.hibernate.type.AnyType; import org.hibernate.type.AnyType;
import org.hibernate.type.CollectionType; import org.hibernate.type.CollectionType;
import org.hibernate.type.CustomCollectionType; import org.hibernate.type.CustomCollectionType;
@ -46,23 +51,55 @@ public final class MappingHelper {
String propertyRef, String propertyRef,
MetadataImplementor metadata) { MetadataImplementor metadata) {
final ClassLoaderService cls = metadata.getMetadataBuildingOptions().getServiceRegistry().getService( ClassLoaderService.class ); 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 boolean hasParameters = CollectionHelper.isNotEmpty( typeParameters );
final ManagedBean<? extends UserCollectionType> userTypeBean;
if ( metadata.getMetadataBuildingOptions().disallowExtensionsInCdi() ) {
//noinspection unchecked,rawtypes
userTypeBean = createLocalUserCollectionTypeBean(
role,
userCollectionTypeClass,
hasParameters,
(Map) typeParameters
);
}
else {
final ManagedBeanRegistry beanRegistry = metadata final ManagedBeanRegistry beanRegistry = metadata
.getMetadataBuildingOptions() .getMetadataBuildingOptions()
.getServiceRegistry() .getServiceRegistry()
.getService( ManagedBeanRegistry.class ); .getService( ManagedBeanRegistry.class );
final ManagedBean<? extends UserCollectionType> userCollectionTypeBean = beanRegistry.getBean( userCollectionTypeClass );
final ManagedBean<? extends UserCollectionType> customTypeBean; if ( hasParameters ) {
if ( typeParameters == null ) { if ( ParameterizedType.class.isAssignableFrom( userCollectionTypeBean.getBeanClass() ) ) {
customTypeBean = beanRegistry.getBean( typeImpl ); // 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 { else {
customTypeBean = beanRegistry.getBean( role, typeImpl ); // there were parameters, but the custom-type does not implement the interface
injectParameters( customTypeBean.getBeanInstance(), typeParameters ); // 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) { public static void injectParameters(Object type, Properties parameters) {
@ -166,4 +203,36 @@ public final class MappingHelper {
constrained 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.ManagedTypeRepresentationResolver;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.usertype.CompositeUserType; 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 ) { if ( bootDescriptor.getTypeName() != null ) {
compositeUserType = (CompositeUserType<Object>) creationContext.getBootstrapContext() 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() .getServiceRegistry()
.getService( ManagedBeanRegistry.class ) .getService( ManagedBeanRegistry.class )
.getBean( .getBean( userTypeClass )
creationContext.getBootstrapContext()
.getClassLoaderAccess()
.classForName( bootDescriptor.getTypeName() )
)
.getBeanInstance(); .getBeanInstance();
} }
}
else { else {
compositeUserType = null; compositeUserType = null;
} }
final EmbeddableInstantiator customInstantiator; final EmbeddableInstantiator customInstantiator;
if ( bootDescriptor.getCustomInstantiator() != null ) { if ( bootDescriptor.getCustomInstantiator() != null ) {
final Class<? extends EmbeddableInstantiator> customInstantiatorImpl = bootDescriptor.getCustomInstantiator(); final Class<? extends EmbeddableInstantiator> instantiatorClass = bootDescriptor.getCustomInstantiator();
if ( creationContext.getBootModel().getMetadataBuildingOptions().disallowExtensionsInCdi() ) {
customInstantiator = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( instantiatorClass );
}
else {
customInstantiator = creationContext.getBootstrapContext() customInstantiator = creationContext.getBootstrapContext()
.getServiceRegistry() .getServiceRegistry()
.getService( ManagedBeanRegistry.class ) .getService( ManagedBeanRegistry.class )
.getBean( customInstantiatorImpl ) .getBean( instantiatorClass )
.getBeanInstance(); .getBeanInstance();
} }
}
else if ( compositeUserType != null ) { 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() ) ) { else if ( bootDescriptor.getComponentClassName() != null && ReflectHelper.isRecord( bootDescriptor.getComponentClass() ) ) {
if ( bootDescriptor.sortProperties() == null ) { if ( bootDescriptor.sortProperties() == null ) {
@ -143,11 +154,12 @@ public class ManagedTypeRepresentationResolverStandard implements ManagedTypeRep
// //
// instead, resolve ReflectionOptimizer once - here - and pass along to // instead, resolve ReflectionOptimizer once - here - and pass along to
// StandardPojoRepresentationStrategy // StandardPojoRepresentationStrategy
//noinspection unchecked
return new EmbeddableRepresentationStrategyPojo( return new EmbeddableRepresentationStrategyPojo(
bootDescriptor, bootDescriptor,
runtimeDescriptorAccess, runtimeDescriptorAccess,
customInstantiator, customInstantiator,
compositeUserType, (CompositeUserType<Object>) compositeUserType,
creationContext creationContext
); );
} }

View File

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

View File

@ -36,6 +36,7 @@ import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.property.access.spi.PropertyAccess; import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.spi.CompositeTypeImplementor; import org.hibernate.type.spi.CompositeTypeImplementor;
@ -96,11 +97,17 @@ public class ComponentType extends AbstractType implements CompositeTypeImplemen
final ManagedBeanRegistry beanRegistry = buildingContext.getBootstrapContext() final ManagedBeanRegistry beanRegistry = buildingContext.getBootstrapContext()
.getServiceRegistry() .getServiceRegistry()
.getService( ManagedBeanRegistry.class ); .getService( ManagedBeanRegistry.class );
final Class<Object> customTypeClass = buildingContext.getBootstrapContext() final Class<CompositeUserType<?>> customTypeClass = buildingContext.getBootstrapContext()
.getClassLoaderAccess() .getClassLoaderAccess()
.classForName( component.getTypeName() ); .classForName( component.getTypeName() );
//noinspection unchecked if ( buildingContext.getBuildingOptions().disallowExtensionsInCdi() ) {
this.compositeUserType = (CompositeUserType<Object>) beanRegistry.getBean( customTypeClass ).getBeanInstance(); //noinspection unchecked,rawtypes
this.compositeUserType = (CompositeUserType) FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( customTypeClass );
}
else {
//noinspection unchecked,rawtypes
this.compositeUserType = (CompositeUserType) beanRegistry.getBean( customTypeClass ).getBeanInstance();
}
} }
else { else {
this.compositeUserType = null; 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.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.MappingModelExpressible; import org.hibernate.metamodel.mapping.MappingModelExpressible;
import org.hibernate.metamodel.model.domain.internal.ArrayTupleType; 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.BinaryArithmeticOperator;
import org.hibernate.query.sqm.IntervalType; import org.hibernate.query.sqm.IntervalType;
import org.hibernate.query.internal.QueryHelper;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.tree.SqmTypedNode; 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.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistry;
@ -401,6 +402,7 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
private transient MetadataBuildingContext metadataBuildingContext; private transient MetadataBuildingContext metadataBuildingContext;
private transient SessionFactoryImplementor sessionFactory; private transient SessionFactoryImplementor sessionFactory;
private boolean allowExtensionsInCdi;
private String sessionFactoryName; private String sessionFactoryName;
private String sessionFactoryUuid; private String sessionFactoryUuid;
@ -491,6 +493,9 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
private void setMetadataBuildingContext(MetadataBuildingContext metadataBuildingContext) { private void setMetadataBuildingContext(MetadataBuildingContext metadataBuildingContext) {
this.metadataBuildingContext = metadataBuildingContext; this.metadataBuildingContext = metadataBuildingContext;
if ( metadataBuildingContext != null ) {
this.allowExtensionsInCdi = metadataBuildingContext.getBuildingOptions().disallowExtensionsInCdi();
}
} }
private SessionFactoryImplementor getSessionFactory() { private SessionFactoryImplementor getSessionFactory() {
@ -805,8 +810,12 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
@Internal @SuppressWarnings("unchecked") @Internal @SuppressWarnings("unchecked")
public <J> MutabilityPlan<J> createMutabilityPlan(Class<? extends MutabilityPlan<?>> planClass) { public <J> MutabilityPlan<J> createMutabilityPlan(Class<? extends MutabilityPlan<?>> planClass) {
final ManagedBean<? extends MutabilityPlan<?>> planBean = if ( scope.allowExtensionsInCdi ) {
scope.getServiceRegistry() //noinspection rawtypes
return (MutabilityPlan) FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( planClass );
}
final ManagedBean<? extends MutabilityPlan<?>> planBean = scope.getServiceRegistry()
.getService( ManagedBeanRegistry.class ) .getService( ManagedBeanRegistry.class )
.getBean( planClass ); .getBean( planClass );
return (MutabilityPlan<J>) planBean.getBeanInstance(); 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; 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.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger; 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.annotations.GenericGenerator;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources; 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.BeanContainer.LifecycleOptions;
import org.hibernate.resource.beans.container.spi.ContainedBean; import org.hibernate.resource.beans.container.spi.ContainedBean;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer; import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.BaseUnitTest; import org.hibernate.testing.orm.junit.BaseUnitTest;
import org.junit.jupiter.api.Test; 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 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 * @author Yanming Zhou
*/ */
@ -65,7 +64,8 @@ public class UserDefinedGeneratorsTests {
} ); } );
final StandardServiceRegistryBuilder ssrb = new StandardServiceRegistryBuilder(); 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()) { try (final StandardServiceRegistry ssr = ssrb.build()) {
final Metadata metadata = new MetadataSources( ssr ) 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.EmbeddableCompositeUserTypeInstantiator;
import org.hibernate.metamodel.internal.EmbeddableInstantiatorPojoIndirecting; import org.hibernate.metamodel.internal.EmbeddableInstantiatorPojoIndirecting;
import org.hibernate.metamodel.spi.EmbeddableInstantiator; import org.hibernate.metamodel.spi.EmbeddableInstantiator;
import org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry; import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.usertype.CompositeUserType; import org.hibernate.usertype.CompositeUserType;
@ -52,6 +53,10 @@ public final class ComponentMetadataGenerator extends AbstractMetadataGenerator
final Component propComponent = (Component) value; final Component propComponent = (Component) value;
final EmbeddableInstantiator instantiator; final EmbeddableInstantiator instantiator;
if ( propComponent.getCustomInstantiator() != null ) { if ( propComponent.getCustomInstantiator() != null ) {
if ( getMetadataBuildingContext().getBuildingOptions().disallowExtensionsInCdi() ) {
instantiator = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( propComponent.getCustomInstantiator() );
}
else
instantiator = getMetadataBuildingContext().getBootstrapContext() instantiator = getMetadataBuildingContext().getBootstrapContext()
.getServiceRegistry() .getServiceRegistry()
.getService( ManagedBeanRegistry.class ) .getService( ManagedBeanRegistry.class )
@ -59,17 +64,23 @@ public final class ComponentMetadataGenerator extends AbstractMetadataGenerator
.getBeanInstance(); .getBeanInstance();
} }
else if ( propComponent.getTypeName() != null ) { else if ( propComponent.getTypeName() != null ) {
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() final CompositeUserType<Object> compositeUserType = (CompositeUserType<Object>) getMetadataBuildingContext().getBootstrapContext()
.getServiceRegistry() .getServiceRegistry()
.getService( ManagedBeanRegistry.class ) .getService( ManagedBeanRegistry.class )
.getBean( .getBean( userTypeClass )
getMetadataBuildingContext().getBootstrapContext()
.getClassLoaderAccess()
.classForName( propComponent.getTypeName() )
)
.getBeanInstance(); .getBeanInstance();
instantiator = new EmbeddableCompositeUserTypeInstantiator( compositeUserType ); instantiator = new EmbeddableCompositeUserTypeInstantiator( compositeUserType );
} }
}
else if ( propComponent.getInstantiator() != null ) { else if ( propComponent.getInstantiator() != null ) {
instantiator = EmbeddableInstantiatorPojoIndirecting.of( instantiator = EmbeddableInstantiatorPojoIndirecting.of(
propComponent.getPropertyNames(), propComponent.getPropertyNames(),

View File

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