Skip to content

Commit 9add83e

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 0725022 commit 9add83e

File tree

12 files changed

+312
-295
lines changed

12 files changed

+312
-295
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/TypeDefinition.java

Lines changed: 49 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import java.util.Properties;
1616
import java.util.concurrent.atomic.AtomicInteger;
1717

18-
import org.hibernate.boot.model.process.internal.InferredBasicValueResolver;
1918
import org.hibernate.boot.model.process.internal.UserTypeResolution;
2019
import org.hibernate.boot.registry.StandardServiceRegistry;
2120
import org.hibernate.boot.spi.BootstrapContext;
@@ -42,6 +41,7 @@
4241
import org.hibernate.type.spi.TypeConfigurationAware;
4342
import org.hibernate.usertype.UserType;
4443

44+
import static org.hibernate.boot.model.process.internal.InferredBasicValueResolver.resolveSqlTypeIndicators;
4545
import static org.hibernate.mapping.MappingHelper.injectParameters;
4646

4747
/**
@@ -131,26 +131,28 @@ private BasicValue.Resolution<?> createResolution(
131131
);
132132
}
133133

134-
private static BasicValue.Resolution<?> createResolution(
134+
private static <T> BasicValue.Resolution<T> createResolution(
135135
String name,
136-
Class<?> typeImplementorClass,
136+
Class<T> typeImplementorClass,
137137
Map<?,?> parameters,
138138
Map<?,?> usageSiteProperties,
139139
JdbcTypeIndicators indicators,
140140
MetadataBuildingContext context) {
141141
final BootstrapContext bootstrapContext = context.getBootstrapContext();
142142
final TypeConfiguration typeConfiguration = bootstrapContext.getTypeConfiguration();
143143
final BeanInstanceProducer instanceProducer = bootstrapContext.getCustomTypeProducer();
144-
final boolean isKnownType = Type.class.isAssignableFrom( typeImplementorClass )
144+
final boolean isKnownType =
145+
Type.class.isAssignableFrom( typeImplementorClass )
145146
|| UserType.class.isAssignableFrom( typeImplementorClass );
146147

147148
// support for AttributeConverter would be nice too
148149
if ( isKnownType ) {
149-
final Object typeInstance = instantiateType( bootstrapContext.getServiceRegistry(),
150+
final T typeInstance = instantiateType( bootstrapContext.getServiceRegistry(),
150151
context.getBuildingOptions(), name, typeImplementorClass, instanceProducer );
151152

152153
if ( typeInstance instanceof TypeConfigurationAware ) {
153-
( (TypeConfigurationAware) typeInstance ).setTypeConfiguration( typeConfiguration );
154+
final TypeConfigurationAware configurationAware = (TypeConfigurationAware) typeInstance;
155+
configurationAware.setTypeConfiguration( typeConfiguration );
154156
}
155157

156158
final Properties combinedTypeParameters = new Properties();
@@ -164,22 +166,23 @@ private static BasicValue.Resolution<?> createResolution(
164166
injectParameters( typeInstance, combinedTypeParameters );
165167

166168
if ( typeInstance instanceof UserType ) {
167-
final UserType<?> userType = (UserType<?>) typeInstance;
168-
final CustomType<?> customType = new CustomType<>( userType, typeConfiguration );
169-
170-
return new UserTypeResolution( customType, null, combinedTypeParameters );
169+
@SuppressWarnings("unchecked")
170+
final UserType<T> userType = (UserType<T>) typeInstance;
171+
final CustomType<T> customType = new CustomType<>( userType, typeConfiguration );
172+
return new UserTypeResolution<>( customType, null, combinedTypeParameters );
171173
}
172174

173175
if ( typeInstance instanceof BasicType ) {
174-
final BasicType<?> resolvedBasicType = (BasicType<?>) typeInstance;
176+
@SuppressWarnings("unchecked")
177+
final BasicType<T> resolvedBasicType = (BasicType<T>) typeInstance;
175178
return new BasicValue.Resolution<>() {
176179
@Override
177180
public JdbcMapping getJdbcMapping() {
178181
return resolvedBasicType;
179182
}
180183

181-
@Override @SuppressWarnings({"rawtypes", "unchecked"})
182-
public BasicType getLegacyResolvedBasicType() {
184+
@Override
185+
public BasicType<T> getLegacyResolvedBasicType() {
183186
return resolvedBasicType;
184187
}
185188

@@ -188,8 +191,8 @@ public Properties getCombinedTypeParameters() {
188191
return combinedTypeParameters;
189192
}
190193

191-
@Override @SuppressWarnings({"rawtypes", "unchecked"})
192-
public JavaType getDomainJavaType() {
194+
@Override
195+
public JavaType<T> getDomainJavaType() {
193196
return resolvedBasicType.getMappedJavaType();
194197
}
195198

@@ -204,12 +207,12 @@ public JdbcType getJdbcType() {
204207
}
205208

206209
@Override
207-
public BasicValueConverter getValueConverter() {
210+
public BasicValueConverter<T,?> getValueConverter() {
208211
return resolvedBasicType.getValueConverter();
209212
}
210213

211-
@Override @SuppressWarnings({"rawtypes", "unchecked"})
212-
public MutabilityPlan getMutabilityPlan() {
214+
@Override
215+
public MutabilityPlan<T> getMutabilityPlan() {
213216
// a TypeDefinition does not explicitly provide a MutabilityPlan (yet?)
214217
return resolvedBasicType.isMutable()
215218
? getDomainJavaType().getMutabilityPlan()
@@ -220,37 +223,35 @@ public MutabilityPlan getMutabilityPlan() {
220223
}
221224

222225
// Series of backward compatible special cases
226+
return resolveLegacyCases( typeImplementorClass, indicators, typeConfiguration );
227+
}
223228

229+
private static <T> BasicValue.Resolution<T> resolveLegacyCases(
230+
Class<T> typeImplementorClass, JdbcTypeIndicators indicators, TypeConfiguration typeConfiguration) {
231+
final BasicType<T> legacyType;
224232
if ( Serializable.class.isAssignableFrom( typeImplementorClass ) ) {
225-
@SuppressWarnings({"rawtypes", "unchecked"})
226-
final SerializableType legacyType = new SerializableType( typeImplementorClass );
227-
return createBasicTypeResolution( legacyType, typeImplementorClass, indicators, typeConfiguration );
233+
legacyType = new SerializableType( typeImplementorClass );
228234
}
229-
230-
if ( typeImplementorClass.isInterface() ) {
231-
return createBasicTypeResolution( new JavaObjectType(), typeImplementorClass, indicators, typeConfiguration );
235+
else if ( typeImplementorClass.isInterface() ) {
236+
legacyType = (BasicType<T>) new JavaObjectType();
237+
}
238+
else {
239+
throw new IllegalArgumentException( "Named type [" + typeImplementorClass
240+
+ "] did not implement BasicType nor UserType" );
232241
}
233242

234-
throw new IllegalArgumentException(
235-
"Named type [" + typeImplementorClass + "] did not implement BasicType nor UserType"
236-
);
243+
return createBasicTypeResolution( legacyType, typeImplementorClass, indicators, typeConfiguration );
237244
}
238245

239-
private static BasicValue.Resolution<Object> createBasicTypeResolution(
240-
BasicType<?> type,
241-
Class<?> typeImplementorClass,
246+
private static <T> BasicValue.Resolution<T> createBasicTypeResolution(
247+
BasicType<T> type,
248+
Class<? extends T> typeImplementorClass,
242249
JdbcTypeIndicators indicators,
243-
TypeConfiguration typeConfiguration
244-
) {
245-
final JavaType<Serializable> jtd = typeConfiguration
246-
.getJavaTypeRegistry()
247-
.resolveDescriptor( typeImplementorClass );
250+
TypeConfiguration typeConfiguration) {
251+
final JavaType<T> jtd = typeConfiguration.getJavaTypeRegistry().resolveDescriptor( typeImplementorClass );
248252
final JdbcType jdbcType = typeConfiguration.getJdbcTypeRegistry().getDescriptor( Types.VARBINARY );
249-
final BasicType<Serializable> resolved = InferredBasicValueResolver.resolveSqlTypeIndicators(
250-
indicators,
251-
typeConfiguration.getBasicTypeRegistry().resolve( jtd, jdbcType ),
252-
jtd
253-
);
253+
final BasicType<T> basicType = typeConfiguration.getBasicTypeRegistry().resolve( jtd, jdbcType );
254+
final BasicType<T> resolved = resolveSqlTypeIndicators( indicators, basicType, jtd );
254255

255256
return new BasicValue.Resolution<>() {
256257
@Override
@@ -259,14 +260,12 @@ public JdbcMapping getJdbcMapping() {
259260
}
260261

261262
@Override
262-
@SuppressWarnings({ "rawtypes", "unchecked" })
263-
public BasicType getLegacyResolvedBasicType() {
263+
public BasicType<T> getLegacyResolvedBasicType() {
264264
return type;
265265
}
266266

267267
@Override
268-
@SuppressWarnings({ "rawtypes", "unchecked" })
269-
public JavaType getDomainJavaType() {
268+
public JavaType<T> getDomainJavaType() {
270269
return resolved.getMappedJavaType();
271270
}
272271

@@ -281,13 +280,12 @@ public JdbcType getJdbcType() {
281280
}
282281

283282
@Override
284-
public BasicValueConverter getValueConverter() {
283+
public BasicValueConverter<T,?> getValueConverter() {
285284
return resolved.getValueConverter();
286285
}
287286

288287
@Override
289-
@SuppressWarnings({ "rawtypes", "unchecked" })
290-
public MutabilityPlan getMutabilityPlan() {
288+
public MutabilityPlan<T> getMutabilityPlan() {
291289
// a TypeDefinition does not explicitly provide a MutabilityPlan (yet?)
292290
return resolved.isMutable()
293291
? getDomainJavaType().getMutabilityPlan()
@@ -296,20 +294,20 @@ public MutabilityPlan getMutabilityPlan() {
296294
};
297295
}
298296

299-
private static Object instantiateType(
297+
private static <T> T instantiateType(
300298
StandardServiceRegistry serviceRegistry,
301299
MetadataBuildingOptions buildingOptions,
302300
String name,
303-
Class<?> typeImplementorClass,
301+
Class<T> typeImplementorClass,
304302
BeanInstanceProducer instanceProducer) {
305303
if ( buildingOptions.disallowExtensionsInCdi() ) {
306304
return name != null
307305
? instanceProducer.produceBeanInstance( name, typeImplementorClass )
308306
: instanceProducer.produceBeanInstance( typeImplementorClass );
309307
}
310308
else {
311-
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
312-
final ManagedBean<?> typeBean = name != null
309+
final ManagedBeanRegistry beanRegistry = serviceRegistry.requireService( ManagedBeanRegistry.class );
310+
final ManagedBean<T> typeBean = name != null
313311
? beanRegistry.getBean( name, typeImplementorClass, instanceProducer )
314312
: beanRegistry.getBean( typeImplementorClass, instanceProducer );
315313
return typeBean.getBeanInstance();

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

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.hibernate.boot.model.convert.spi.RegisteredConversion;
4949
import org.hibernate.boot.registry.StandardServiceRegistry;
5050
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
51+
import org.hibernate.boot.spi.BootstrapContext;
5152
import org.hibernate.boot.spi.InFlightMetadataCollector;
5253
import org.hibernate.boot.spi.MetadataBuildingContext;
5354
import org.hibernate.dialect.Dialect;
@@ -601,6 +602,8 @@ private static void bindUserTypeRegistrations(
601602
private static void handleUserTypeRegistration(
602603
MetadataBuildingContext context,
603604
TypeRegistration compositeTypeRegistration) {
605+
// TODO: check that the two classes agree, i.e. that
606+
// the user type knows how to handle the type
604607
context.getMetadataCollector().registerUserType(
605608
compositeTypeRegistration.basicClass(),
606609
compositeTypeRegistration.userType()
@@ -610,6 +613,8 @@ private static void handleUserTypeRegistration(
610613
private static void handleCompositeUserTypeRegistration(
611614
MetadataBuildingContext context,
612615
CompositeTypeRegistration compositeTypeRegistration) {
616+
// TODO: check that the two classes agree, i.e. that
617+
// the user type knows how to handle the type
613618
context.getMetadataCollector().registerCompositeUserType(
614619
compositeTypeRegistration.embeddableClass(),
615620
compositeTypeRegistration.userType()
@@ -755,25 +760,21 @@ public Dialect getDialect() {
755760
}
756761

757762
private static JdbcMapping resolveUserType(Class<UserType<?>> userTypeClass, MetadataBuildingContext context) {
758-
final UserType<?> userType;
759-
if ( context.getBuildingOptions().disallowExtensionsInCdi() ) {
760-
userType = FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( userTypeClass );
761-
}
762-
else {
763-
final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry();
764-
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
765-
userType = beanRegistry.getBean( userTypeClass ).getBeanInstance();
766-
}
767-
763+
final UserType<?> userType = context.getBuildingOptions().disallowExtensionsInCdi()
764+
? FallbackBeanInstanceProducer.INSTANCE.produceBeanInstance( userTypeClass )
765+
: context.getBootstrapContext().getServiceRegistry()
766+
.requireService( ManagedBeanRegistry.class )
767+
.getBean( userTypeClass ).getBeanInstance();
768768
return new CustomType<>( userType, context.getBootstrapContext().getTypeConfiguration() );
769769
}
770770

771771
private static JdbcMapping resolveAttributeConverter(Class<AttributeConverter<?, ?>> type, MetadataBuildingContext context) {
772-
final StandardServiceRegistry serviceRegistry = context.getBootstrapContext().getServiceRegistry();
773-
final ManagedBeanRegistry beanRegistry = serviceRegistry.getService( ManagedBeanRegistry.class );
772+
final BootstrapContext bootstrapContext = context.getBootstrapContext();
773+
final ManagedBeanRegistry beanRegistry =
774+
bootstrapContext.getServiceRegistry().requireService( ManagedBeanRegistry.class );
774775
final ManagedBean<AttributeConverter<?, ?>> bean = beanRegistry.getBean( type );
775776

776-
final TypeConfiguration typeConfiguration = context.getBootstrapContext().getTypeConfiguration();
777+
final TypeConfiguration typeConfiguration = bootstrapContext.getTypeConfiguration();
777778
final JavaTypeRegistry jtdRegistry = typeConfiguration.getJavaTypeRegistry();
778779
final JavaType<? extends AttributeConverter<?,?>> converterJtd = jtdRegistry.resolveDescriptor( bean.getBeanClass() );
779780

0 commit comments

Comments
 (0)