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:
@@ -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.
|
||||
@@ -51,11 +51,8 @@ import org.springframework.util.StringUtils;
|
||||
* {@link org.springframework.stereotype.Repository @Repository}) are
|
||||
* themselves annotated with {@code @Component}.
|
||||
*
|
||||
* <p>Also supports Jakarta EE's {@link jakarta.annotation.ManagedBean} and
|
||||
* JSR-330's {@link jakarta.inject.Named} annotations (as well as their pre-Jakarta
|
||||
* {@code javax.annotation.ManagedBean} and {@code javax.inject.Named} equivalents),
|
||||
* if available. Note that Spring component annotations always override such
|
||||
* standard annotations.
|
||||
* <p>Also supports JSR-330's {@link jakarta.inject.Named} annotation if available.
|
||||
* Note that Spring component annotations always override such standard annotations.
|
||||
*
|
||||
* <p>If the annotation's value doesn't indicate a bean name, an appropriate
|
||||
* name will be built based on the short name of the class (with the first
|
||||
@@ -219,10 +216,7 @@ public class AnnotationBeanNameGenerator implements BeanNameGenerator {
|
||||
Set<String> metaAnnotationTypes, Map<String, Object> attributes) {
|
||||
|
||||
boolean isStereotype = metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME) ||
|
||||
annotationType.equals("jakarta.annotation.ManagedBean") ||
|
||||
annotationType.equals("javax.annotation.ManagedBean") ||
|
||||
annotationType.equals("jakarta.inject.Named") ||
|
||||
annotationType.equals("javax.inject.Named");
|
||||
annotationType.equals("jakarta.inject.Named");
|
||||
|
||||
return (isStereotype && attributes.containsKey("value"));
|
||||
}
|
||||
|
||||
@@ -117,9 +117,6 @@ public abstract class AnnotationConfigUtils {
|
||||
private static final boolean jakartaAnnotationsPresent =
|
||||
ClassUtils.isPresent("jakarta.annotation.PostConstruct", classLoader);
|
||||
|
||||
private static final boolean jsr250Present =
|
||||
ClassUtils.isPresent("javax.annotation.PostConstruct", classLoader);
|
||||
|
||||
private static final boolean jpaPresent =
|
||||
ClassUtils.isPresent("jakarta.persistence.EntityManagerFactory", classLoader) &&
|
||||
ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, classLoader);
|
||||
@@ -169,8 +166,7 @@ public abstract class AnnotationConfigUtils {
|
||||
}
|
||||
|
||||
// Check for Jakarta Annotations support, and if present add the CommonAnnotationBeanPostProcessor.
|
||||
if ((jakartaAnnotationsPresent || jsr250Present) &&
|
||||
!registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
|
||||
if (jakartaAnnotationsPresent && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
|
||||
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
|
||||
def.setSource(source);
|
||||
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
|
||||
|
||||
@@ -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.
|
||||
@@ -48,8 +48,7 @@ import org.springframework.util.PatternMatchUtils;
|
||||
* {@link org.springframework.stereotype.Service @Service}, or
|
||||
* {@link org.springframework.stereotype.Controller @Controller} stereotype.
|
||||
*
|
||||
* <p>Also supports Jakarta EE's {@link jakarta.annotation.ManagedBean} and
|
||||
* JSR-330's {@link jakarta.inject.Named} annotations, if available.
|
||||
* <p>Also supports JSR-330's {@link jakarta.inject.Named} annotations, if available.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
|
||||
@@ -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.
|
||||
@@ -216,31 +216,12 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
|
||||
* {@link Component @Component} meta-annotation including the
|
||||
* {@link Repository @Repository}, {@link Service @Service}, and
|
||||
* {@link Controller @Controller} stereotype annotations.
|
||||
* <p>Also supports Jakarta EE's {@link jakarta.annotation.ManagedBean} and
|
||||
* JSR-330's {@link jakarta.inject.Named} annotations (as well as their
|
||||
* pre-Jakarta {@code javax.annotation.ManagedBean} and {@code javax.inject.Named}
|
||||
* equivalents), if available.
|
||||
* <p>Also supports JSR-330's {@link jakarta.inject.Named} annotation if available.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void registerDefaultFilters() {
|
||||
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
|
||||
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
|
||||
try {
|
||||
this.includeFilters.add(new AnnotationTypeFilter(
|
||||
((Class<? extends Annotation>) ClassUtils.forName("jakarta.annotation.ManagedBean", cl)), false));
|
||||
logger.trace("JSR-250 'jakarta.annotation.ManagedBean' found and supported for component scanning");
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JSR-250 1.1 API (as included in Jakarta EE) not available - simply skip.
|
||||
}
|
||||
try {
|
||||
this.includeFilters.add(new AnnotationTypeFilter(
|
||||
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
|
||||
logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JSR-250 1.1 API not available - simply skip.
|
||||
}
|
||||
try {
|
||||
this.includeFilters.add(new AnnotationTypeFilter(
|
||||
((Class<? extends Annotation>) ClassUtils.forName("jakarta.inject.Named", cl)), false));
|
||||
@@ -249,14 +230,6 @@ public class ClassPathScanningCandidateComponentProvider implements EnvironmentC
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JSR-330 API (as included in Jakarta EE) not available - simply skip.
|
||||
}
|
||||
try {
|
||||
this.includeFilters.add(new AnnotationTypeFilter(
|
||||
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
|
||||
logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// JSR-330 API not available - simply skip.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -96,11 +96,6 @@ import org.springframework.util.StringValueResolver;
|
||||
* and default names as well. The target beans can be simple POJOs, with no special
|
||||
* requirements other than the type having to match.
|
||||
*
|
||||
* <p>Additionally, the original {@code javax.annotation} variants of the annotations
|
||||
* dating back to the JSR-250 specification (Java EE 5-8, also included in JDK 6-8)
|
||||
* are still supported as well. Note that this is primarily for a smooth upgrade path,
|
||||
* not for adoption in new applications.
|
||||
*
|
||||
* <p>This post-processor also supports the EJB {@link jakarta.ejb.EJB} annotation,
|
||||
* analogous to {@link jakarta.annotation.Resource}, with the capability to
|
||||
* specify both a local bean name and a global JNDI name for fallback retrieval.
|
||||
@@ -154,9 +149,6 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
@Nullable
|
||||
private static final Class<? extends Annotation> jakartaResourceType;
|
||||
|
||||
@Nullable
|
||||
private static final Class<? extends Annotation> javaxResourceType;
|
||||
|
||||
@Nullable
|
||||
private static final Class<? extends Annotation> ejbAnnotationType;
|
||||
|
||||
@@ -166,11 +158,6 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
resourceAnnotationTypes.add(jakartaResourceType);
|
||||
}
|
||||
|
||||
javaxResourceType = loadAnnotationType("javax.annotation.Resource");
|
||||
if (javaxResourceType != null) {
|
||||
resourceAnnotationTypes.add(javaxResourceType);
|
||||
}
|
||||
|
||||
ejbAnnotationType = loadAnnotationType("jakarta.ejb.EJB");
|
||||
if (ejbAnnotationType != null) {
|
||||
resourceAnnotationTypes.add(ejbAnnotationType);
|
||||
@@ -212,10 +199,6 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
addInitAnnotationType(loadAnnotationType("jakarta.annotation.PostConstruct"));
|
||||
addDestroyAnnotationType(loadAnnotationType("jakarta.annotation.PreDestroy"));
|
||||
|
||||
// Tolerate legacy JSR-250 annotations in javax.annotation package
|
||||
addInitAnnotationType(loadAnnotationType("javax.annotation.PostConstruct"));
|
||||
addDestroyAnnotationType(loadAnnotationType("javax.annotation.PreDestroy"));
|
||||
|
||||
// java.naming module present on JDK 9+?
|
||||
if (jndiPresent) {
|
||||
this.jndiFactory = new SimpleJndiBeanFactory();
|
||||
@@ -444,14 +427,6 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
currElements.add(new ResourceElement(field, field, null));
|
||||
}
|
||||
}
|
||||
else if (javaxResourceType != null && field.isAnnotationPresent(javaxResourceType)) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
throw new IllegalStateException("@Resource annotation is not supported on static fields");
|
||||
}
|
||||
if (!this.ignoredResourceTypes.contains(field.getType().getName())) {
|
||||
currElements.add(new LegacyResourceElement(field, field, null));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ReflectionUtils.doWithLocalMethods(targetClass, method -> {
|
||||
@@ -486,21 +461,6 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (javaxResourceType != null && bridgedMethod.isAnnotationPresent(javaxResourceType)) {
|
||||
if (method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
|
||||
if (Modifier.isStatic(method.getModifiers())) {
|
||||
throw new IllegalStateException("@Resource annotation is not supported on static methods");
|
||||
}
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
if (paramTypes.length != 1) {
|
||||
throw new IllegalStateException("@Resource annotation requires a single-arg method: " + method);
|
||||
}
|
||||
if (!this.ignoredResourceTypes.contains(paramTypes[0].getName())) {
|
||||
PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
|
||||
currElements.add(new LegacyResourceElement(method, bridgedMethod, pd));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
elements.addAll(0, currElements);
|
||||
@@ -746,57 +706,6 @@ public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBean
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class representing injection information about an annotated field
|
||||
* or setter method, supporting the @Resource annotation.
|
||||
*/
|
||||
private class LegacyResourceElement extends LookupElement {
|
||||
|
||||
private final boolean lazyLookup;
|
||||
|
||||
public LegacyResourceElement(Member member, AnnotatedElement ae, @Nullable PropertyDescriptor pd) {
|
||||
super(member, pd);
|
||||
javax.annotation.Resource resource = ae.getAnnotation(javax.annotation.Resource.class);
|
||||
String resourceName = resource.name();
|
||||
Class<?> resourceType = resource.type();
|
||||
this.isDefaultName = !StringUtils.hasLength(resourceName);
|
||||
if (this.isDefaultName) {
|
||||
resourceName = this.member.getName();
|
||||
if (this.member instanceof Method && resourceName.startsWith("set") && resourceName.length() > 3) {
|
||||
resourceName = StringUtils.uncapitalizeAsProperty(resourceName.substring(3));
|
||||
}
|
||||
}
|
||||
else if (embeddedValueResolver != null) {
|
||||
resourceName = embeddedValueResolver.resolveStringValue(resourceName);
|
||||
}
|
||||
if (Object.class != resourceType) {
|
||||
checkResourceType(resourceType);
|
||||
}
|
||||
else {
|
||||
// No resource type specified... check field/method.
|
||||
resourceType = getResourceType();
|
||||
}
|
||||
this.name = (resourceName != null ? resourceName : "");
|
||||
this.lookupType = resourceType;
|
||||
String lookupValue = resource.lookup();
|
||||
this.mappedName = (StringUtils.hasLength(lookupValue) ? lookupValue : resource.mappedName());
|
||||
Lazy lazy = ae.getAnnotation(Lazy.class);
|
||||
this.lazyLookup = (lazy != null && lazy.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getResourceToInject(Object target, @Nullable String requestingBeanName) {
|
||||
return (this.lazyLookup ? buildLazyResourceProxy(this, requestingBeanName) :
|
||||
getResource(this, requestingBeanName));
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isLazyLookup() {
|
||||
return this.lazyLookup;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class representing injection information about an annotated field
|
||||
* or setter method, supporting the @EJB annotation.
|
||||
|
||||
Reference in New Issue
Block a user