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

Ensures that the enabled flag is honored in JpaExtension's observer methods #8235

Merged
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
10 changes: 5 additions & 5 deletions archetypes/helidon/src/main/archetype/common/observability.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright (c) 2022, 2023 Oracle and/or its affiliates.
Copyright (c) 2022, 2024 Oracle and/or its affiliates.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -103,14 +103,14 @@ curl -H 'Accept: application/json' -X GET http://localhost:8080/metrics
<value>io.helidon.metrics.api.MetricsFactory</value>
</list>
<list key="MainTest-other-imports">
<value>org.junit.jupiter.api.BeforeAll</value>
<value>org.junit.jupiter.api.AfterAll</value>
</list>
<list key="MainTest-static-imports">
<value>static org.junit.jupiter.api.Assertions.assertEquals</value>
</list>
<list key="MainTest-methods" order="999">
<value><![CDATA[
@BeforeAll
@AfterAll
static void clear() {
MetricsFactory.closeAll();
}
Expand Down Expand Up @@ -199,7 +199,7 @@ curl -H 'Accept: application/json' -X GET http://localhost:8080/metrics
<value>io.helidon.metrics.api.MetricsFactory</value>
</list>
<list key="MainTest-other-imports">
<value>org.junit.jupiter.api.BeforeAll</value>
<value>org.junit.jupiter.api.AfterAll</value>
</list>
<list key="MainTest-static-fields">
<value><![CDATA[
Expand All @@ -208,7 +208,7 @@ curl -H 'Accept: application/json' -X GET http://localhost:8080/metrics
</list>
<list key="MainTest-methods" order="999">
<value><![CDATA[
@BeforeAll
@AfterAll
static void clear() {
MetricsFactory.closeAll();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2023 Oracle and/or its affiliates.
* Copyright (c) 2019, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -2049,7 +2049,7 @@ private void onStartup(@Observes
Object event,
@ContainerManaged
Instance<EntityManagerFactory> emfs) {
if (!emfs.isUnsatisfied()) {
if (this.enabled && !emfs.isUnsatisfied()) {
for (EntityManagerFactory emfProxy : emfs) {
// Container-managed EntityManagerFactory instances are client proxies, so we call a business method to
// force "inflation" of the proxied instance. This, in turn, may run DDL and persistence provider
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates.
* Copyright (c) 2023, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -55,7 +55,9 @@

import jakarta.annotation.PreDestroy;
import jakarta.annotation.Priority;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.context.Initialized;
import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.event.Event;
import jakarta.enterprise.event.Observes;
Expand Down Expand Up @@ -107,6 +109,7 @@
import jakarta.xml.bind.Unmarshaller;

import static jakarta.interceptor.Interceptor.Priority.LIBRARY_AFTER;
import static jakarta.interceptor.Interceptor.Priority.LIBRARY_BEFORE;
import static jakarta.persistence.PersistenceContextType.EXTENDED;
import static jakarta.persistence.SynchronizationType.SYNCHRONIZED;
import static jakarta.persistence.SynchronizationType.UNSYNCHRONIZED;
Expand Down Expand Up @@ -620,6 +623,52 @@ private void addSyntheticBeans(@Observes @Priority(LIBRARY_AFTER) AfterBeanDisco
this.unlistedManagedClassesByUnitNames.clear();
}

// This will take some explaining.
//
// Weld 5.1.2.Final and later has a bug? interesting feature? where if a very, very particular way of acquiring a
// contextual reference is the first such way that Weld encounters, a Bean metadata bean
// (https://jakarta.ee/specifications/cdi/4.0/jakarta-cdi-spec-4.0#bean_metadata) is NOT properly created for the
// acquisition.
//
// This impacts this class because this give-me-the-Bean-metadata facility helps determine what qualifiers are in
// play for any given bean's means of production. See, for example, #produceEntityManagerFactory(Instance) above.
//
// The path to trigger this bug seems to be something like this:
//
// If the first encounter of an injection point is during the initialization of a contextual reference that must
// exist in order for an observer method to be called on it, then it *seems* that in this one case only the
// CreationalContext hierarchy that Weld uses to keep track of which thing is injecting which other thing breaks
// down, and null is returned where really it shouldn't be. See
// https://github.com/weld/core/blob/5.1.1.SP2/impl/src/main/java/org/jboss/weld/bean/builtin/BeanMetadataBean.java#L59.
//
// The following observer method, whose analog also exists in the (now-deprecated, soon to-be-removed) JpaExtension
// class, works around that problem by ensuring that the first encounter of the type (EntityManagerFactory) will
// never meet the criteria outlined above. (It will, in fact, be when emfs.next() is effectively called below.)
//
// This observer method also calls a business method
// (https://jakarta.ee/specifications/cdi/4.0/jakarta-cdi-spec-4.0#biz_method) on each EntityManagerFactory. It
// doesn't matter which one. This will cause the contextual reference's underlying contextual instance to become
// fully initialized. If the user has instructed the EntityManagerFactory to predeploy persistence units, such
// predeployment will happen here as a convenient result.
private void
workAroundWeldBeanMetadataCreationBug(@Observes
@Initialized(ApplicationScoped.class)
@Priority(LIBRARY_BEFORE + 20) // Must be later than metrics CDI extension priority
Object event,
@ContainerManaged
Instance<EntityManagerFactory> emfs) {
if (this.enabled && !emfs.isUnsatisfied()) {
for (EntityManagerFactory emfProxy : emfs) {
// Container-managed EntityManagerFactory instances are client proxies, so we call a business method (it
// doesn't matter which one, so a speedy simple one will suffice) to force "inflation" of the proxied
// instance. This, in turn, may run DDL and persistence provider validation if the persistence provider
// has been configured to do such things early (like Eclipselink with its eclipselink.deploy-on-startup
// property).
emfProxy.isOpen();
}
}
}


/*
* Other instance methods.
Expand Down Expand Up @@ -1305,7 +1354,7 @@ private void addJtaTransactionScopedEntityManagerBeans(AfterBeanDiscovery event,


private static JtaExtendedEntityManager produceJtaExtendedEntityManager(Instance<Object> instance) {
BeanAttributes<JtaExtendedEntityManager> ba = instance.select(BEAN_JTAEXTENDEDENTITYMANAGER_TYPELITERAL).get();
BeanAttributes<?> ba = instance.select(BEAN_JTAEXTENDEDENTITYMANAGER_TYPELITERAL).get();
Set<Annotation> containerManagedSelectionQualifiers = new HashSet<>();
containerManagedSelectionQualifiers.add(ContainerManaged.Literal.INSTANCE);
Set<Annotation> selectionQualifiers = new HashSet<>();
Expand Down Expand Up @@ -1376,7 +1425,7 @@ private static PersistenceUnitInfoBean producePersistenceUnitInfoBean(Instance<O
}

private static EntityManagerFactory produceEntityManagerFactory(Instance<Object> instance) {
BeanAttributes<EntityManagerFactory> ba = instance.select(BEAN_ENTITYMANAGERFACTORY_TYPELITERAL).get();
BeanAttributes<?> ba = instance.select(BEAN_ENTITYMANAGERFACTORY_TYPELITERAL).get();
Set<Annotation> selectionQualifiers = new HashSet<>();
Set<Annotation> namedSelectionQualifiers = new HashSet<>();
for (Annotation beanQualifier: ba.getQualifiers()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2023 Oracle and/or its affiliates.
* Copyright (c) 2019, 2024 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -77,7 +77,6 @@ class TestAnnotationRewriting {

@BeforeEach
void startCdiContainer() {
System.setProperty("jpaAnnotationRewritingEnabled", "true");
final SeContainerInitializer initializer = SeContainerInitializer.newInstance()
.addBeanClasses(this.getClass());
assertThat(initializer, notNullValue());
Expand Down