General upgrade to Jakarta EE 11 APIs

Includes removal of ManagedBean and javax.annotation legacy support.
Includes AbstractJson(Http)MessageConverter revision for Yasson 3.0.
Includes initial Hibernate ORM 7.0 upgrade.

Closes gh-34011
Closes gh-33750
This commit is contained in:
Juergen Hoeller
2024-12-03 13:30:25 +01:00
parent 15c6d3449b
commit 949432ce8b
65 changed files with 200 additions and 2995 deletions

View File

@@ -1,24 +0,0 @@
/*
* Copyright 2002-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.indexed;
/**
* @author Sam Brannen
*/
@jakarta.annotation.ManagedBean
public class IndexedJakartaManagedBeanComponent {
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.indexed;
/**
* @author Sam Brannen
*/
@javax.annotation.ManagedBean
public class IndexedJavaxManagedBeanComponent {
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.indexed;
/**
* @author Sam Brannen
*/
@javax.inject.Named("myIndexedJavaxNamedComponent")
public class IndexedJavaxNamedComponent {
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.scannable;
/**
* @author Sam Brannen
*/
@jakarta.annotation.ManagedBean("myJakartaManagedBeanComponent")
public class JakartaManagedBeanComponent {
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.scannable;
/**
* @author Sam Brannen
*/
@javax.annotation.ManagedBean("myJavaxManagedBeanComponent")
public class JavaxManagedBeanComponent {
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.scannable;
/**
* @author Sam Brannen
*/
@javax.inject.Named("myJavaxNamedComponent")
public class JavaxNamedComponent {
}

View File

@@ -40,8 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Integration tests for handling JSR-330 {@link jakarta.inject.Qualifier} and
* {@link javax.inject.Qualifier} annotations.
* Integration tests for handling {@link jakarta.inject.Qualifier} annotations.
*
* @author Juergen Hoeller
* @author Sam Brannen
@@ -317,16 +316,6 @@ class InjectAnnotationAutowireContextTests {
assertThat(bean.getAnimal2().getName()).isEqualTo("Jakarta Fido");
}
@Test // gh-33345
void autowiredConstructorArgumentResolvesJavaxNamedCandidate() {
Class<JavaxNamedConstructorArgumentTestBean> testBeanClass = JavaxNamedConstructorArgumentTestBean.class;
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(testBeanClass, JavaxCat.class, JavaxDog.class);
JavaxNamedConstructorArgumentTestBean bean = context.getBean(testBeanClass);
assertThat(bean.getAnimal1().getName()).isEqualTo("Javax Tiger");
assertThat(bean.getAnimal2().getName()).isEqualTo("Javax Fido");
}
@Test
void autowiredFieldResolvesQualifiedCandidateWithDefaultValueAndNoValueOnBeanDefinition() {
GenericApplicationContext context = new GenericApplicationContext();
@@ -587,29 +576,6 @@ class InjectAnnotationAutowireContextTests {
}
static class JavaxNamedConstructorArgumentTestBean {
private final Animal animal1;
private final Animal animal2;
@javax.inject.Inject
public JavaxNamedConstructorArgumentTestBean(@javax.inject.Named("Cat") Animal animal1,
@javax.inject.Named("Dog") Animal animal2) {
this.animal1 = animal1;
this.animal2 = animal2;
}
public Animal getAnimal1() {
return this.animal1;
}
public Animal getAnimal2() {
return this.animal2;
}
}
public static class QualifiedFieldWithDefaultValueTestBean {
@Inject
@@ -705,16 +671,6 @@ class InjectAnnotationAutowireContextTests {
}
@javax.inject.Named("Cat")
static class JavaxCat implements Animal {
@Override
public String getName() {
return "Javax Tiger";
}
}
@jakarta.inject.Named("Dog")
static class JakartaDog implements Animal {
@@ -725,16 +681,6 @@ class InjectAnnotationAutowireContextTests {
}
@javax.inject.Named("Dog")
static class JavaxDog implements Animal {
@Override
public String getName() {
return "Javax Fido";
}
}
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier

View File

@@ -23,10 +23,7 @@ import java.lang.annotation.Target;
import java.util.List;
import example.scannable.DefaultNamedComponent;
import example.scannable.JakartaManagedBeanComponent;
import example.scannable.JakartaNamedComponent;
import example.scannable.JavaxManagedBeanComponent;
import example.scannable.JavaxNamedComponent;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
@@ -108,21 +105,6 @@ class AnnotationBeanNameGeneratorTests {
assertGeneratedName(JakartaNamedComponent.class, "myJakartaNamedComponent");
}
@Test
void generateBeanNameWithJavaxNamedComponent() {
assertGeneratedName(JavaxNamedComponent.class, "myJavaxNamedComponent");
}
@Test
void generateBeanNameWithJakartaManagedBeanComponent() {
assertGeneratedName(JakartaManagedBeanComponent.class, "myJakartaManagedBeanComponent");
}
@Test
void generateBeanNameWithJavaxManagedBeanComponent() {
assertGeneratedName(JavaxManagedBeanComponent.class, "myJavaxManagedBeanComponent");
}
@Test
void generateBeanNameWithCustomStereotypeComponent() {
assertGeneratedName(DefaultNamedComponent.class, "thoreau");

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2023 the original author or authors.
* Copyright 2002-2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,10 +27,7 @@ import java.util.regex.Pattern;
import java.util.stream.Stream;
import example.gh24375.AnnotatedComponent;
import example.indexed.IndexedJakartaManagedBeanComponent;
import example.indexed.IndexedJakartaNamedComponent;
import example.indexed.IndexedJavaxManagedBeanComponent;
import example.indexed.IndexedJavaxNamedComponent;
import example.profilescan.DevComponent;
import example.profilescan.ProfileAnnotatedComponent;
import example.profilescan.ProfileMetaAnnotatedComponent;
@@ -40,10 +37,7 @@ import example.scannable.DefaultNamedComponent;
import example.scannable.FooDao;
import example.scannable.FooService;
import example.scannable.FooServiceImpl;
import example.scannable.JakartaManagedBeanComponent;
import example.scannable.JakartaNamedComponent;
import example.scannable.JavaxManagedBeanComponent;
import example.scannable.JavaxNamedComponent;
import example.scannable.MessageBean;
import example.scannable.NamedComponent;
import example.scannable.NamedStubDao;
@@ -99,51 +93,31 @@ class ClassPathScanningCandidateComponentProviderTests {
BarComponent.class
);
private static final Set<Class<?>> scannedJakartaComponents = Set.of(
JakartaNamedComponent.class,
JakartaManagedBeanComponent.class
);
private static final Set<Class<?>> scannedJavaxComponents = Set.of(
JavaxNamedComponent.class,
JavaxManagedBeanComponent.class
);
private static final Set<Class<?>> indexedComponents = Set.of(
IndexedJakartaNamedComponent.class,
IndexedJakartaManagedBeanComponent.class,
IndexedJavaxNamedComponent.class,
IndexedJavaxManagedBeanComponent.class
);
@Test
void defaultsWithScan() {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
provider.setResourceLoader(new DefaultResourceLoader(
CandidateComponentsTestClassLoader.disableIndex(getClass().getClassLoader())));
testDefault(provider, TEST_BASE_PACKAGE, true, true, false);
testDefault(provider, TEST_BASE_PACKAGE, true, false);
}
@Test
void defaultsWithIndex() {
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);
provider.setResourceLoader(new DefaultResourceLoader(TEST_BASE_CLASSLOADER));
testDefault(provider, "example", true, true, true);
testDefault(provider, "example", true, true);
}
private void testDefault(ClassPathScanningCandidateComponentProvider provider, String basePackage,
boolean includeScannedJakartaComponents, boolean includeScannedJavaxComponents, boolean includeIndexedComponents) {
boolean includeScannedJakartaComponents, boolean includeIndexedComponents) {
Set<Class<?>> expectedTypes = new HashSet<>(springComponents);
if (includeScannedJakartaComponents) {
expectedTypes.addAll(scannedJakartaComponents);
}
if (includeScannedJavaxComponents) {
expectedTypes.addAll(scannedJavaxComponents);
expectedTypes.add(JakartaNamedComponent.class);
}
if (includeIndexedComponents) {
expectedTypes.addAll(indexedComponents);
expectedTypes.add(IndexedJakartaNamedComponent.class);
}
Set<BeanDefinition> candidates = provider.findCandidateComponents(basePackage);
@@ -216,7 +190,7 @@ class ClassPathScanningCandidateComponentProviderTests {
private void testCustomAnnotationTypeIncludeFilter(ClassPathScanningCandidateComponentProvider provider) {
provider.addIncludeFilter(new AnnotationTypeFilter(Component.class));
testDefault(provider, TEST_BASE_PACKAGE, false, false, false);
testDefault(provider, TEST_BASE_PACKAGE, false, false);
}
@Test
@@ -309,7 +283,7 @@ class ClassPathScanningCandidateComponentProviderTests {
Set<BeanDefinition> candidates = provider.findCandidateComponents(TEST_BASE_PACKAGE);
assertScannedBeanDefinitions(candidates);
assertBeanTypes(candidates, FooServiceImpl.class, StubFooDao.class, ServiceInvocationCounter.class,
BarComponent.class, JakartaManagedBeanComponent.class, JavaxManagedBeanComponent.class);
BarComponent.class);
}
@Test

View File

@@ -116,16 +116,6 @@ class CommonAnnotationBeanPostProcessorTests {
assertThat(bean.destroyCalled).isTrue();
}
@Test
void postConstructAndPreDestroyWithLegacyAnnotations() {
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(LegacyAnnotatedInitDestroyBean.class));
LegacyAnnotatedInitDestroyBean bean = (LegacyAnnotatedInitDestroyBean) bf.getBean("annotatedBean");
assertThat(bean.initCalled).isTrue();
bf.destroySingletons();
assertThat(bean.destroyCalled).isTrue();
}
@Test
void postConstructAndPreDestroyWithManualConfiguration() {
InitDestroyAnnotationBeanPostProcessor bpp = new InitDestroyAnnotationBeanPostProcessor();
@@ -223,26 +213,6 @@ class CommonAnnotationBeanPostProcessorTests {
assertThat(bean.destroy3Called).isTrue();
}
@Test
void resourceInjectionWithLegacyAnnotations() {
bf.registerBeanDefinition("annotatedBean", new RootBeanDefinition(LegacyResourceInjectionBean.class));
TestBean tb = new TestBean();
bf.registerSingleton("testBean", tb);
TestBean tb2 = new TestBean();
bf.registerSingleton("testBean2", tb2);
LegacyResourceInjectionBean bean = (LegacyResourceInjectionBean) bf.getBean("annotatedBean");
assertThat(bean.initCalled).isTrue();
assertThat(bean.init2Called).isTrue();
assertThat(bean.init3Called).isTrue();
assertThat(bean.getTestBean()).isSameAs(tb);
assertThat(bean.getTestBean2()).isSameAs(tb2);
bf.destroySingletons();
assertThat(bean.destroyCalled).isTrue();
assertThat(bean.destroy2Called).isTrue();
assertThat(bean.destroy3Called).isTrue();
}
@Test
void resourceInjectionWithResolvableDependencyType() {
bpp.setBeanFactory(bf);
@@ -558,30 +528,6 @@ class CommonAnnotationBeanPostProcessorTests {
}
public static class LegacyAnnotatedInitDestroyBean {
public boolean initCalled = false;
public boolean destroyCalled = false;
@javax.annotation.PostConstruct
private void init() {
if (this.initCalled) {
throw new IllegalStateException("Already called");
}
this.initCalled = true;
}
@javax.annotation.PreDestroy
private void destroy() {
if (this.destroyCalled) {
throw new IllegalStateException("Already called");
}
this.destroyCalled = true;
}
}
public static class InitDestroyBeanPostProcessor implements DestructionAwareBeanPostProcessor {
@Override
@@ -691,83 +637,6 @@ class CommonAnnotationBeanPostProcessorTests {
}
public static class LegacyResourceInjectionBean extends LegacyAnnotatedInitDestroyBean {
public boolean init2Called = false;
public boolean init3Called = false;
public boolean destroy2Called = false;
public boolean destroy3Called = false;
@javax.annotation.Resource
private TestBean testBean;
private TestBean testBean2;
@javax.annotation.PostConstruct
protected void init2() {
if (this.testBean == null || this.testBean2 == null) {
throw new IllegalStateException("Resources not injected");
}
if (!this.initCalled) {
throw new IllegalStateException("Superclass init method not called yet");
}
if (this.init2Called) {
throw new IllegalStateException("Already called");
}
this.init2Called = true;
}
@javax.annotation.PostConstruct
private void init() {
if (this.init3Called) {
throw new IllegalStateException("Already called");
}
this.init3Called = true;
}
@javax.annotation.PreDestroy
protected void destroy2() {
if (this.destroyCalled) {
throw new IllegalStateException("Superclass destroy called too soon");
}
if (this.destroy2Called) {
throw new IllegalStateException("Already called");
}
this.destroy2Called = true;
}
@javax.annotation.PreDestroy
private void destroy() {
if (this.destroyCalled) {
throw new IllegalStateException("Superclass destroy called too soon");
}
if (this.destroy3Called) {
throw new IllegalStateException("Already called");
}
this.destroy3Called = true;
}
@javax.annotation.Resource
public void setTestBean2(TestBean testBean2) {
if (this.testBean2 != null) {
throw new IllegalStateException("Already called");
}
this.testBean2 = testBean2;
}
public TestBean getTestBean() {
return testBean;
}
public TestBean getTestBean2() {
return testBean2;
}
}
static class NonPublicResourceInjectionBean<B> extends ResourceInjectionBean {
@Resource(name="testBean4", type=TestBean.class)