Skip to content

Commit 5997076

Browse files
committed
fix problem where Hibernate refused to instantiate non-public UserType
also clean up some code with respect to generic typing + improve some exception reporting
1 parent 9b4502c commit 5997076

File tree

5 files changed

+88
-71
lines changed

5 files changed

+88
-71
lines changed

hibernate-core/src/main/java/org/hibernate/InstantiationException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class InstantiationException extends HibernateException {
1515
private final Class<?> clazz;
1616

1717
/**
18-
* Constructs a {@code InstantiationException}.
18+
* Constructs an {@code InstantiationException}.
1919
*
2020
* @param message A message explaining the exception condition
2121
* @param clazz The Class we are attempting to instantiate

hibernate-core/src/main/java/org/hibernate/boot/model/TypeBeanInstanceProducer.java

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@
66
*/
77
package org.hibernate.boot.model;
88

9-
import java.lang.reflect.Constructor;
10-
import java.util.Map;
11-
9+
import org.hibernate.InstantiationException;
1210
import org.hibernate.Internal;
13-
import org.hibernate.MappingException;
1411
import org.hibernate.engine.config.spi.ConfigurationService;
15-
import org.hibernate.internal.util.ReflectHelper;
1612
import org.hibernate.resource.beans.spi.BeanInstanceProducer;
1713
import org.hibernate.type.spi.TypeBootstrapContext;
1814

15+
import java.lang.reflect.Constructor;
16+
import java.util.Map;
17+
18+
import static org.hibernate.internal.util.ReflectHelper.getConstructor;
19+
1920
/**
2021
* {@link BeanInstanceProducer} implementation for building beans related to custom types.
2122
*
@@ -31,20 +32,29 @@ public TypeBeanInstanceProducer(ConfigurationService configurationService) {
3132

3233
@Override
3334
public <B> B produceBeanInstance(Class<B> beanType) {
34-
try {
35-
final Constructor<B> bootstrapContextAwareTypeConstructor = ReflectHelper.getConstructor(
36-
beanType,
37-
TypeBootstrapContext.class
38-
);
39-
if ( bootstrapContextAwareTypeConstructor != null ) {
40-
return bootstrapContextAwareTypeConstructor.newInstance( this );
35+
final Constructor<B> bootstrapContextAwareConstructor =
36+
getConstructor( beanType, TypeBootstrapContext.class );
37+
if ( bootstrapContextAwareConstructor != null ) {
38+
try {
39+
return bootstrapContextAwareConstructor.newInstance( this );
4140
}
42-
else {
43-
return beanType.newInstance();
41+
catch ( Exception e ) {
42+
throw new InstantiationException( "Could not instantiate type", beanType, e );
4443
}
4544
}
46-
catch ( Exception e ) {
47-
throw new MappingException( "Could not instantiate Type: " + beanType.getName(), e );
45+
else {
46+
final Constructor<B> constructor = getConstructor( beanType );
47+
if ( constructor != null ) {
48+
try {
49+
return constructor.newInstance();
50+
}
51+
catch ( Exception e ) {
52+
throw new InstantiationException( "Could not instantiate type", beanType, e );
53+
}
54+
}
55+
else {
56+
throw new InstantiationException( "No appropriate constructor for type", beanType );
57+
}
4858
}
4959
}
5060

hibernate-core/src/main/java/org/hibernate/boot/model/internal/AnnotationBinder.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,8 @@ private static void bindUserTypeRegistrations(
601601
private static void handleUserTypeRegistration(
602602
MetadataBuildingContext context,
603603
TypeRegistration compositeTypeRegistration) {
604+
// TODO: check that the two classes agree, i.e. that
605+
// the user type knows how to handle the type
604606
context.getMetadataCollector().registerUserType(
605607
compositeTypeRegistration.basicClass(),
606608
compositeTypeRegistration.userType()
@@ -610,6 +612,8 @@ private static void handleUserTypeRegistration(
610612
private static void handleCompositeUserTypeRegistration(
611613
MetadataBuildingContext context,
612614
CompositeTypeRegistration compositeTypeRegistration) {
615+
// TODO: check that the two classes agree, i.e. that
616+
// the user type knows how to handle the type
613617
context.getMetadataCollector().registerCompositeUserType(
614618
compositeTypeRegistration.embeddableClass(),
615619
compositeTypeRegistration.userType()

hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ public static <T> Constructor<T> getConstructor(
368368
try {
369369
constructor = clazz.getDeclaredConstructor( constructorArgs );
370370
try {
371-
ReflectHelper.ensureAccessibility( constructor );
371+
ensureAccessibility( constructor );
372372
}
373373
catch ( SecurityException e ) {
374374
constructor = null;
@@ -425,11 +425,9 @@ else if ( containerClass == Object.class ) {
425425
}
426426

427427
public static void ensureAccessibility(AccessibleObject accessibleObject) {
428-
if ( accessibleObject.isAccessible() ) {
429-
return;
428+
if ( !accessibleObject.isAccessible() ) {
429+
accessibleObject.setAccessible( true );
430430
}
431-
432-
accessibleObject.setAccessible( true );
433431
}
434432

435433
private static Field locateField(Class clazz, String propertyName) {

hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java

Lines changed: 54 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
import jakarta.persistence.TemporalType;
6868

6969
import static java.lang.Boolean.parseBoolean;
70+
import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty;
7071
import static org.hibernate.mapping.MappingHelper.injectParameters;
7172

7273
/**
@@ -803,65 +804,69 @@ public void setTypeName(String typeName) {
803804

804805
private static int COUNTER;
805806

806-
public <T extends UserType<?>> void setExplicitCustomType(Class<T> explicitCustomType) {
807+
public void setExplicitCustomType(Class<? extends UserType<?>> explicitCustomType) {
807808
if ( explicitCustomType != null ) {
808809
if ( resolution != null ) {
809810
throw new UnsupportedOperationException( "Unsupported attempt to set an explicit-custom-type when value is already resolved" );
810811
}
811812

812-
final BeanInstanceProducer instanceProducer =
813-
getBuildingContext().getBootstrapContext().getCustomTypeProducer();
814-
815-
final Properties properties = new Properties();
816-
if ( CollectionHelper.isNotEmpty( getTypeParameters() ) ) {
817-
properties.putAll( getTypeParameters() );
818-
}
819-
if ( CollectionHelper.isNotEmpty( explicitLocalTypeParams ) ) {
820-
properties.putAll( explicitLocalTypeParams );
821-
}
813+
resolution = new UserTypeResolution(
814+
new CustomType<>(
815+
getConfiguredUserTypeBean( explicitCustomType, getCustomTypeProperties() ),
816+
getTypeConfiguration()
817+
),
818+
null,
819+
getCustomTypeProperties()
820+
);
821+
}
822+
}
822823

823-
final T typeInstance;
824-
if ( getBuildingContext().getBuildingOptions().disallowExtensionsInCdi() ) {
825-
typeInstance = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( explicitCustomType );
826-
}
827-
else {
828-
final boolean hasParameters = CollectionHelper.isNotEmpty( properties );
824+
private Properties getCustomTypeProperties() {
825+
final Properties properties = new Properties();
826+
if ( isNotEmpty( getTypeParameters() ) ) {
827+
properties.putAll( getTypeParameters() );
828+
}
829+
if ( isNotEmpty( explicitLocalTypeParams ) ) {
830+
properties.putAll( explicitLocalTypeParams );
831+
}
832+
return properties;
833+
}
829834

830-
final ManagedBean<T> typeBean;
831-
if ( hasParameters ) {
832-
final String name = explicitCustomType.getName() + COUNTER++;
833-
typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class )
834-
.getBean( name, explicitCustomType, instanceProducer );
835-
}
836-
else {
837-
typeBean = getServiceRegistry().getService( ManagedBeanRegistry.class )
838-
.getBean( explicitCustomType, instanceProducer );
839-
}
840-
typeInstance = typeBean.getBeanInstance();
841-
}
835+
private <T> T getConfiguredUserTypeBean(Class<T> explicitCustomType, Properties properties) {
836+
final T typeInstance =
837+
getBuildingContext().getBuildingOptions().disallowExtensionsInCdi()
838+
? FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( explicitCustomType )
839+
: getUserTypeBean( explicitCustomType, properties ).getBeanInstance();
842840

843-
if ( typeInstance instanceof TypeConfigurationAware ) {
844-
( (TypeConfigurationAware) typeInstance ).setTypeConfiguration( getTypeConfiguration() );
845-
}
841+
if ( typeInstance instanceof TypeConfigurationAware ) {
842+
final TypeConfigurationAware configurationAware = (TypeConfigurationAware) typeInstance;
843+
configurationAware.setTypeConfiguration( getTypeConfiguration() );
844+
}
846845

847-
if ( typeInstance instanceof DynamicParameterizedType ) {
848-
if (parseBoolean(properties.getProperty(DynamicParameterizedType.IS_DYNAMIC))) {
849-
if (properties.get(DynamicParameterizedType.PARAMETER_TYPE) == null) {
850-
final DynamicParameterizedType.ParameterType parameterType = makeParameterImpl();
851-
properties.put(DynamicParameterizedType.PARAMETER_TYPE, parameterType);
852-
}
846+
if ( typeInstance instanceof DynamicParameterizedType ) {
847+
if ( parseBoolean( properties.getProperty( DynamicParameterizedType.IS_DYNAMIC ) ) ) {
848+
if ( properties.get( DynamicParameterizedType.PARAMETER_TYPE ) == null ) {
849+
properties.put( DynamicParameterizedType.PARAMETER_TYPE, makeParameterImpl() );
853850
}
854851
}
852+
}
855853

856-
injectParameters( typeInstance, properties );
857-
// envers - grr
858-
setTypeParameters( properties );
854+
injectParameters( typeInstance, properties);
855+
// envers - grr
856+
setTypeParameters( properties );
859857

860-
this.resolution = new UserTypeResolution(
861-
new CustomType<>( (UserType<?>) typeInstance, getTypeConfiguration() ),
862-
null,
863-
properties
864-
);
858+
return typeInstance;
859+
}
860+
861+
private <T> ManagedBean<T> getUserTypeBean(Class<T> explicitCustomType, Properties properties) {
862+
final BeanInstanceProducer producer = getBuildingContext().getBootstrapContext().getCustomTypeProducer();
863+
final ManagedBeanRegistry registry = getServiceRegistry().requireService( ManagedBeanRegistry.class );
864+
if ( isNotEmpty( properties ) ) {
865+
final String name = explicitCustomType.getName() + COUNTER++;
866+
return registry.getBean( name, explicitCustomType, producer );
867+
}
868+
else {
869+
return registry.getBean( explicitCustomType, producer );
865870
}
866871
}
867872

@@ -882,9 +887,9 @@ public Object accept(ValueVisitor visitor) {
882887
@Internal
883888
public boolean isDisallowedWrapperArray() {
884889
return getBuildingContext().getBuildingOptions().getWrapperArrayHandling() == WrapperArrayHandling.DISALLOW
885-
&& !isLob()
886-
&& ( explicitJavaTypeAccess == null || explicitJavaTypeAccess.apply( getTypeConfiguration() ) == null )
887-
&& isWrapperByteOrCharacterArray();
890+
&& !isLob()
891+
&& ( explicitJavaTypeAccess == null || explicitJavaTypeAccess.apply( getTypeConfiguration() ) == null )
892+
&& isWrapperByteOrCharacterArray();
888893
}
889894

890895
private boolean isWrapperByteOrCharacterArray() {

0 commit comments

Comments
 (0)