Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid class initializations more aggressively in the Hibernate ORM extension #15822

Merged
merged 15 commits into from
Apr 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
package io.quarkus.deployment.builditem;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import io.quarkus.builder.item.MultiBuildItem;

public final class AdditionalIndexedClassesBuildItem extends MultiBuildItem {

private final Set<String> classesToIndex = new HashSet<>();
private final Set<String> classesToIndex;

public AdditionalIndexedClassesBuildItem(String... classesToIndex) {
this.classesToIndex.addAll(Arrays.asList(classesToIndex));
Set<String> toIndex = new HashSet<>(classesToIndex.length);
for (String s : classesToIndex) {
toIndex.add(s);
}
this.classesToIndex = toIndex;
}

public AdditionalIndexedClassesBuildItem(String classToIndex) {
this.classesToIndex = Collections.singleton(classToIndex);
}

public Set<String> getClassesToIndex() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ CapabilityBuildItem capability() {
@BuildStep
List<AdditionalJpaModelBuildItem> addJpaModelClasses() {
return Arrays.asList(
new AdditionalJpaModelBuildItem(org.hibernate.envers.DefaultRevisionEntity.class),
new AdditionalJpaModelBuildItem(org.hibernate.envers.DefaultTrackingModifiedEntitiesRevisionEntity.class));
new AdditionalJpaModelBuildItem("org.hibernate.envers.DefaultRevisionEntity"),
yrodiere marked this conversation as resolved.
Show resolved Hide resolved
new AdditionalJpaModelBuildItem("org.hibernate.envers.DefaultTrackingModifiedEntitiesRevisionEntity"));
}

@BuildStep
Expand Down
Empty file.
2 changes: 2 additions & 0 deletions extensions/hibernate-orm/deployment/banned-signatures.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@defaultMessage Don't use the pattern MyClass.class.getName() or DotName.createSimple("org.mycompany.MyClass"). Instead, create constants using createConstant("org.mycompany.MyClass") in io.quarkus.hibernate.orm.deployment.ClassNames. That way, all class names will get checked against the classpath in ConstantsTest.
java.lang.Class#getName()
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.hibernate.orm.deployment;

import java.util.Objects;

import io.quarkus.builder.item.MultiBuildItem;

/**
Expand All @@ -11,8 +13,9 @@ public final class AdditionalJpaModelBuildItem extends MultiBuildItem {

private final String className;

public AdditionalJpaModelBuildItem(Class<?> klass) {
this.className = klass.getName();
public AdditionalJpaModelBuildItem(String className) {
Objects.requireNonNull(className);
this.className = className;
}

public String getClassName() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.quarkus.hibernate.orm.deployment;

import java.util.HashSet;
import java.util.Set;

import org.jboss.jandex.DotName;

public class ClassNames {

static final Set<DotName> CREATED_CONSTANTS = new HashSet<>();

private ClassNames() {
}

private static DotName createConstant(String fqcn) {
DotName result = DotName.createSimple(fqcn);
CREATED_CONSTANTS.add(result);
return result;
}

public static final DotName ENUM = createConstant("java.lang.Enum");

public static final DotName TENANT_CONNECTION_RESOLVER = createConstant(
"io.quarkus.hibernate.orm.runtime.tenant.TenantConnectionResolver");
public static final DotName TENANT_RESOLVER = createConstant("io.quarkus.hibernate.orm.runtime.tenant.TenantResolver");

public static final DotName STATIC_METAMODEL = createConstant("javax.persistence.metamodel.StaticMetamodel");

public static final DotName QUARKUS_PERSISTENCE_UNIT = createConstant("io.quarkus.hibernate.orm.PersistenceUnit");
public static final DotName QUARKUS_PERSISTENCE_UNIT_REPEATABLE_CONTAINER = createConstant(
"io.quarkus.hibernate.orm.PersistenceUnit$List");
public static final DotName JPA_PERSISTENCE_UNIT = createConstant("javax.persistence.PersistenceUnit");
public static final DotName JPA_PERSISTENCE_CONTEXT = createConstant("javax.persistence.PersistenceContext");

public static final DotName JPA_ENTITY = createConstant("javax.persistence.Entity");
public static final DotName MAPPED_SUPERCLASS = createConstant("javax.persistence.MappedSuperclass");
public static final DotName EMBEDDABLE = createConstant("javax.persistence.Embeddable");
public static final DotName EMBEDDED = createConstant("javax.persistence.Embedded");
public static final DotName ELEMENT_COLLECTION = createConstant("javax.persistence.ElementCollection");
public static final DotName PROXY = createConstant("org.hibernate.annotations.Proxy");
public static final DotName HIBERNATE_PROXY = createConstant("org.hibernate.proxy.HibernateProxy");
public static final DotName TYPE = createConstant("org.hibernate.annotations.Type");
public static final DotName TYPE_DEFINITION = createConstant("org.hibernate.annotations.TypeDef");
public static final DotName TYPE_DEFINITIONS = createConstant("org.hibernate.annotations.TypeDefs");

public static final DotName ENTITY_MANAGER_FACTORY = createConstant("javax.persistence.EntityManagerFactory");
public static final DotName SESSION_FACTORY = createConstant("org.hibernate.SessionFactory");
public static final DotName ENTITY_MANAGER = createConstant("javax.persistence.EntityManager");
public static final DotName SESSION = createConstant("org.hibernate.Session");

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package io.quarkus.hibernate.orm.deployment;

import java.util.Optional;

import io.quarkus.datasource.common.runtime.DatabaseKind;
import io.quarkus.deployment.configuration.ConfigurationError;

public final class Dialects {

private Dialects() {
//utility
}

public static Optional<String> guessDialect(String resolvedDbKind) {
// For now select the latest dialect from the driver
// later, we can keep doing that but also avoid DCE
// of all the dialects we want in so that people can override them
if (DatabaseKind.isDB2(resolvedDbKind)) {
return Optional.of("org.hibernate.dialect.DB297Dialect");
}
if (DatabaseKind.isPostgreSQL(resolvedDbKind)) {
return Optional.of("io.quarkus.hibernate.orm.runtime.dialect.QuarkusPostgreSQL10Dialect");
}
if (DatabaseKind.isH2(resolvedDbKind)) {
return Optional.of("io.quarkus.hibernate.orm.runtime.dialect.QuarkusH2Dialect");
}
if (DatabaseKind.isMariaDB(resolvedDbKind)) {
return Optional.of("org.hibernate.dialect.MariaDB103Dialect");
}
if (DatabaseKind.isMySQL(resolvedDbKind)) {
return Optional.of("org.hibernate.dialect.MySQL8Dialect");
}
if (DatabaseKind.isOracle(resolvedDbKind)) {
return Optional.of("org.hibernate.dialect.Oracle12cDialect");
}
if (DatabaseKind.isDerby(resolvedDbKind)) {
return Optional.of("org.hibernate.dialect.DerbyTenSevenDialect");
}
if (DatabaseKind.isMsSQL(resolvedDbKind)) {
return Optional.of("org.hibernate.dialect.SQLServer2012Dialect");
}

String error = "Hibernate extension could not guess the dialect from the database kind '" + resolvedDbKind
+ "'. Add an explicit '" + HibernateOrmProcessor.HIBERNATE_ORM_CONFIG_PREFIX + "dialect' property.";
throw new ConfigurationError(error);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,6 @@
import java.util.Collections;
import java.util.List;

import org.hibernate.annotations.AnyMetaDef;
import org.hibernate.annotations.AnyMetaDefs;
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.ListIndexBase;
import org.hibernate.annotations.NamedNativeQueries;
import org.hibernate.annotations.NamedNativeQuery;
import org.hibernate.annotations.NamedQueries;
import org.hibernate.annotations.NamedQuery;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;
import org.jboss.jandex.DotName;

public final class HibernateOrmAnnotations {
Expand All @@ -27,20 +12,20 @@ private HibernateOrmAnnotations() {
}

public static final List<DotName> PACKAGE_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(
DotName.createSimple(AnyMetaDef.class.getName()),
DotName.createSimple(AnyMetaDefs.class.getName()),
DotName.createSimple(FetchProfile.class.getName()),
DotName.createSimple(FetchProfile.FetchOverride.class.getName()),
DotName.createSimple(FetchProfiles.class.getName()),
DotName.createSimple(FilterDef.class.getName()),
DotName.createSimple(FilterDefs.class.getName()),
DotName.createSimple(GenericGenerator.class.getName()),
DotName.createSimple(GenericGenerators.class.getName()),
DotName.createSimple(ListIndexBase.class.getName()),
DotName.createSimple(NamedNativeQueries.class.getName()),
DotName.createSimple(NamedNativeQuery.class.getName()),
DotName.createSimple(NamedQueries.class.getName()),
DotName.createSimple(NamedQuery.class.getName()),
DotName.createSimple(TypeDef.class.getName()),
DotName.createSimple(TypeDefs.class.getName())));
DotName.createSimple("org.hibernate.annotations.AnyMetaDef"),
DotName.createSimple("org.hibernate.annotations.AnyMetaDefs"),
DotName.createSimple("org.hibernate.annotations.FetchProfile"),
DotName.createSimple("org.hibernate.annotations.FetchProfile$FetchOverride"),
DotName.createSimple("org.hibernate.annotations.FetchProfiles"),
DotName.createSimple("org.hibernate.annotations.FilterDef"),
DotName.createSimple("org.hibernate.annotations.FilterDefs"),
DotName.createSimple("org.hibernate.annotations.GenericGenerator"),
DotName.createSimple("org.hibernate.annotations.GenericGenerators"),
DotName.createSimple("org.hibernate.annotations.ListIndexBase"),
DotName.createSimple("org.hibernate.annotations.NamedNativeQueries"),
DotName.createSimple("org.hibernate.annotations.NamedNativeQuery"),
DotName.createSimple("org.hibernate.annotations.NamedQueries"),
DotName.createSimple("org.hibernate.annotations.NamedQuery"),
DotName.createSimple("org.hibernate.annotations.TypeDef"),
DotName.createSimple("org.hibernate.annotations.TypeDefs")));
yrodiere marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

import javax.enterprise.inject.Default;
import javax.inject.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
Expand All @@ -33,19 +31,9 @@

public class HibernateOrmCdiProcessor {

private static final List<DotName> SESSION_FACTORY_EXPOSED_TYPES = Arrays.asList(
DotName.createSimple(EntityManagerFactory.class.getName()),
DotName.createSimple(SessionFactory.class.getName()));
private static final List<DotName> SESSION_EXPOSED_TYPES = Arrays.asList(
DotName.createSimple(EntityManager.class.getName()),
DotName.createSimple(Session.class.getName()));

private static final DotName PERSISTENCE_UNIT_QUALIFIER = DotName.createSimple(PersistenceUnit.class.getName());

private static final DotName JPA_PERSISTENCE_UNIT = DotName.createSimple(javax.persistence.PersistenceUnit.class.getName());

private static final DotName JPA_PERSISTENCE_CONTEXT = DotName
.createSimple(javax.persistence.PersistenceContext.class.getName());
private static final List<DotName> SESSION_FACTORY_EXPOSED_TYPES = Arrays.asList(ClassNames.ENTITY_MANAGER_FACTORY,
ClassNames.SESSION_FACTORY);
private static final List<DotName> SESSION_EXPOSED_TYPES = Arrays.asList(ClassNames.ENTITY_MANAGER, ClassNames.SESSION);

@BuildStep
AnnotationsTransformerBuildItem convertJpaResourceAnnotationsToQualifier(
Expand All @@ -71,10 +59,10 @@ public void transform(TransformationContext transformationContext) {
}

DotName jpaAnnotation;
if (field.hasAnnotation(JPA_PERSISTENCE_UNIT)) {
jpaAnnotation = JPA_PERSISTENCE_UNIT;
} else if (field.hasAnnotation(JPA_PERSISTENCE_CONTEXT)) {
jpaAnnotation = JPA_PERSISTENCE_CONTEXT;
if (field.hasAnnotation(ClassNames.JPA_PERSISTENCE_UNIT)) {
jpaAnnotation = ClassNames.JPA_PERSISTENCE_UNIT;
} else if (field.hasAnnotation(ClassNames.JPA_PERSISTENCE_CONTEXT)) {
jpaAnnotation = ClassNames.JPA_PERSISTENCE_CONTEXT;
} else {
return;
}
Expand All @@ -93,7 +81,7 @@ public void transform(TransformationContext transformationContext) {
// in this case, we consider it the default too if the name matches
transformation.add(DotNames.DEFAULT);
} else {
transformation.add(PERSISTENCE_UNIT_QUALIFIER,
transformation.add(ClassNames.QUARKUS_PERSISTENCE_UNIT,
AnnotationValue.createStringValue("value", persistenceUnitNameAnnotationValue.asString()));
}
transformation.done();
Expand Down
Loading