HHH-16096 Passing an ExtendedBeanManager which is notified too late leads to initialization error

This commit is contained in:
Vedran Prišćan 2023-01-25 12:00:14 +01:00 committed by Steve Ebersole
parent 94b20bafc8
commit d18cdbec35
2 changed files with 167 additions and 0 deletions

View File

@ -223,6 +223,20 @@ public class JpaCompliantLifecycleStrategy implements BeanLifecycleStrategy {
return;
}
if ( beanManager == null ) {
try {
beanInstance = fallbackProducer.produceBeanInstance( beanType );
return;
}
catch (Exception e) {
// the CDI BeanManager is not know to be ready for use and the
// fallback-producer was unable to create the bean...
throw new IllegalStateException(
"CDI BeanManager is not known to be ready for use and the fallback-producer was unable to create the bean",
new NotYetReadyException( e )
);
}
}
try {
this.creationalContext = beanManager.createCreationalContext( null );

View File

@ -0,0 +1,153 @@
/*
* 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.lifecycle;
import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.HibernateException;
import org.hibernate.annotations.Type;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.resource.beans.container.spi.ExtendedBeanManager;
import org.hibernate.testing.TestForIssue;
import org.hibernate.usertype.DynamicParameterizedType;
import org.hibernate.usertype.UserType;
import org.junit.jupiter.api.Test;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;
@TestForIssue(jiraKey = "HHH-16096")
public class ExtendedBeanManagerNotAvailableDuringCustomUserTypeInitTest {
@Test
public void tryIt() {
// pass ExtendedBeanManager but never initialize it
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
.applySetting( AvailableSettings.JAKARTA_CDI_BEAN_MANAGER, new ExtendedBeanManagerImpl() )
.build();
// this will trigger initialization of dynamic parameterized user type bean
//noinspection EmptyTryBlock
try (var ignored = new MetadataSources(ssr)
.addAnnotatedClass(TheEntity.class)
.buildMetadata()
.buildSessionFactory()) {
}
finally {
StandardServiceRegistryBuilder.destroy(ssr);
}
}
@SuppressWarnings("JpaDataSourceORMInspection")
@Entity(name = "TheEntity")
@Table(name = "TheEntity")
public static class TheEntity {
@Id
private Integer id;
private String name;
@Type(CustomDynamicParameterizedUserType.class)
private String custom;
}
public static class CustomDynamicParameterizedUserType implements UserType<Object>, DynamicParameterizedType {
@Override
public int getSqlType() {
return Types.VARCHAR;
}
@Override
public Class<Object> returnedClass() {
return Object.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if (x == null) {
return y == null;
} else {
return x.equals(y);
}
}
@Override
public int hashCode(Object x) throws HibernateException {
return x == null ? 0 : x.hashCode();
}
@Override
public Object nullSafeGet(ResultSet rs, int i, SharedSessionContractImplementor sharedSessionContractImplementor, Object o) throws SQLException {
String xmldoc = rs.getString(i);
return rs.wasNull() ? null : xmldoc;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.OTHER);
} else {
st.setObject(index, value, Types.OTHER);
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (String) value;
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return cached;
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
@Override
public void setParameterValues(Properties parameters) {
// nothing
}
}
public static class ExtendedBeanManagerImpl implements ExtendedBeanManager {
private LifecycleListener lifecycleListener;
@Override
public void registerLifecycleListener(LifecycleListener lifecycleListener) {
assert this.lifecycleListener == null;
this.lifecycleListener = lifecycleListener;
}
// not called
public void notify(BeanManager ready) {
lifecycleListener.beanManagerInitialized( ready );
}
}
}