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

@ -674,9 +674,7 @@ By default, the `AnnotationBeanNameGenerator` is used. For Spring
xref:core/beans/classpath-scanning.adoc#beans-stereotype-annotations[stereotype annotations],
if you supply a name via the annotation's `value` attribute that name will be used as
the name in the corresponding bean definition. This convention also applies when the
following JSR-250 and JSR-330 annotations are used instead of Spring stereotype
annotations: `@jakarta.annotation.ManagedBean`, `@javax.annotation.ManagedBean`,
`@jakarta.inject.Named`, and `@javax.inject.Named`.
`@jakarta.inject.Named` annotation is used instead of Spring stereotype annotations.
As of Spring Framework 6.1, the name of the annotation attribute that is used to specify
the bean name is no longer required to be `value`. Custom stereotype annotations can

View File

@ -11,9 +11,7 @@ Spring Framework's email support:
* The https://jakartaee.github.io/mail-api/[Jakarta Mail] library
This library is freely available on the web -- for example, in Maven Central as
`com.sun.mail:jakarta.mail`. Please make sure to use the latest 2.x version (which uses
the `jakarta.mail` package namespace) rather than Jakarta Mail 1.6.x (which uses the
`javax.mail` package namespace).
`org.eclipse.angus:angus-mail`.
****
The Spring Framework provides a helpful utility library for sending email that shields

View File

@ -171,9 +171,9 @@ the parameters of a test class constructor are autowired from components in the
If `@TestConstructor` is not present or meta-present on a test class, the default _test
constructor autowire mode_ will be used. See the tip below for details on how to change
the default mode. Note, however, that a local declaration of `@Autowired`,
`@jakarta.inject.Inject`, or `@javax.inject.Inject` on a constructor takes precedence
over both `@TestConstructor` and the default mode.
the default mode. Note, however, that a local declaration of `@Autowired` or
`@jakarta.inject.Inject` on a constructor takes precedence over both `@TestConstructor`
and the default mode.
.Changing the default test constructor autowire mode
[TIP]

View File

@ -40,7 +40,6 @@ dependencies {
api("com.squareup.okhttp3:mockwebserver:3.14.9")
api("com.squareup.okhttp3:okhttp:3.14.9")
api("com.sun.activation:jakarta.activation:2.0.1")
api("com.sun.mail:jakarta.mail:2.0.1")
api("com.sun.xml.bind:jaxb-core:3.0.2")
api("com.sun.xml.bind:jaxb-impl:3.0.2")
api("com.sun.xml.bind:jaxb-xjc:3.0.2")
@ -61,32 +60,30 @@ dependencies {
api("io.undertow:undertow-servlet:2.3.18.Final")
api("io.undertow:undertow-websockets-jsr:2.3.18.Final")
api("io.vavr:vavr:0.10.4")
api("jakarta.activation:jakarta.activation-api:2.0.1")
api("jakarta.annotation:jakarta.annotation-api:2.0.0")
api("jakarta.activation:jakarta.activation-api:2.1.3")
api("jakarta.annotation:jakarta.annotation-api:3.0.0")
api("jakarta.ejb:jakarta.ejb-api:4.0.1")
api("jakarta.el:jakarta.el-api:4.0.0")
api("jakarta.enterprise.concurrent:jakarta.enterprise.concurrent-api:2.0.0")
api("jakarta.faces:jakarta.faces-api:3.0.0")
api("jakarta.el:jakarta.el-api:6.0.1")
api("jakarta.enterprise.concurrent:jakarta.enterprise.concurrent-api:3.1.1")
api("jakarta.faces:jakarta.faces-api:4.1.2")
api("jakarta.inject:jakarta.inject-api:2.0.1")
api("jakarta.inject:jakarta.inject-tck:2.0.1")
api("jakarta.interceptor:jakarta.interceptor-api:2.0.0")
api("jakarta.jms:jakarta.jms-api:3.0.0")
api("jakarta.json.bind:jakarta.json.bind-api:2.0.0")
api("jakarta.json:jakarta.json-api:2.0.1")
api("jakarta.mail:jakarta.mail-api:2.0.1")
api("jakarta.persistence:jakarta.persistence-api:3.0.0")
api("jakarta.resource:jakarta.resource-api:2.0.0")
api("jakarta.interceptor:jakarta.interceptor-api:2.2.0")
api("jakarta.jms:jakarta.jms-api:3.1.0")
api("jakarta.json.bind:jakarta.json.bind-api:3.0.1")
api("jakarta.json:jakarta.json-api:2.1.3")
api("jakarta.mail:jakarta.mail-api:2.1.3")
api("jakarta.persistence:jakarta.persistence-api:3.2.0")
api("jakarta.resource:jakarta.resource-api:2.1.0")
api("jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api:3.0.2")
api("jakarta.servlet.jsp:jakarta.servlet.jsp-api:4.0.0")
api("jakarta.servlet:jakarta.servlet-api:6.1.0")
api("jakarta.transaction:jakarta.transaction-api:2.0.1")
api("jakarta.validation:jakarta.validation-api:3.0.2")
api("jakarta.validation:jakarta.validation-api:3.1.0")
api("jakarta.websocket:jakarta.websocket-api:2.2.0")
api("jakarta.websocket:jakarta.websocket-client-api:2.2.0")
api("jakarta.xml.bind:jakarta.xml.bind-api:3.0.1")
api("javax.annotation:javax.annotation-api:1.3.2")
api("javax.cache:cache-api:1.1.1")
api("javax.inject:javax.inject:1")
api("javax.money:money-api:1.1")
api("jaxen:jaxen:1.2.0")
api("junit:junit:4.13.2")
@ -117,9 +114,10 @@ dependencies {
api("org.crac:crac:1.4.0")
api("org.dom4j:dom4j:2.1.4")
api("org.easymock:easymock:5.4.0")
api("org.eclipse.angus:angus-mail:2.0.3")
api("org.eclipse.jetty:jetty-reactive-httpclient:4.0.8")
api("org.eclipse.persistence:org.eclipse.persistence.jpa:3.0.4")
api("org.eclipse:yasson:2.0.4")
api("org.eclipse.persistence:org.eclipse.persistence.jpa:5.0.0-B04")
api("org.eclipse:yasson:3.0.4")
api("org.ehcache:ehcache:3.10.8")
api("org.ehcache:jcache:1.0.1")
api("org.freemarker:freemarker:2.3.33")
@ -128,8 +126,8 @@ dependencies {
api("org.glassfish.tyrus:tyrus-container-servlet:2.1.3")
api("org.graalvm.sdk:graal-sdk:22.3.1")
api("org.hamcrest:hamcrest:2.2")
api("org.hibernate:hibernate-core-jakarta:5.6.15.Final")
api("org.hibernate:hibernate-validator:7.0.5.Final")
api("org.hibernate:hibernate-core:7.0.0.Beta2")
api("org.hibernate:hibernate-validator:9.0.0.Beta3")
api("org.hsqldb:hsqldb:2.7.4")
api("org.htmlunit:htmlunit:4.6.0")
api("org.javamoney:moneta:1.4.4")

View File

@ -26,7 +26,7 @@ dependencies {
testImplementation("jakarta.servlet:jakarta.servlet-api")
testImplementation("org.aspectj:aspectjweaver")
testImplementation("org.hsqldb:hsqldb")
testImplementation("org.hibernate:hibernate-core-jakarta")
testImplementation("org.hibernate:hibernate-core")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
}

View File

@ -16,5 +16,4 @@ dependencies {
testImplementation(project(":spring-core-test"))
testImplementation(testFixtures(project(":spring-core")))
testImplementation("jakarta.annotation:jakarta.annotation-api")
testImplementation("javax.inject:javax.inject")
}

View File

@ -103,8 +103,6 @@ import org.springframework.util.StringUtils;
*
* <p>Also supports the common {@link jakarta.inject.Inject @Inject} annotation,
* if available, as a direct alternative to Spring's own {@code @Autowired}.
* Additionally, it retains support for the {@code javax.inject.Inject} variant
* dating back to the original JSR-330 specification (as known from Java EE 6-8).
*
* <h3>Autowired Constructors</h3>
* <p>Only one constructor of any given bean class may declare this annotation with
@ -189,8 +187,8 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
/**
* Create a new {@code AutowiredAnnotationBeanPostProcessor} for Spring's
* standard {@link Autowired @Autowired} and {@link Value @Value} annotations.
* <p>Also supports the common {@link jakarta.inject.Inject @Inject} annotation,
* if available, as well as the original {@code javax.inject.Inject} variant.
* <p>Also supports the common {@link jakarta.inject.Inject @Inject} annotation
* if available.
*/
@SuppressWarnings("unchecked")
public AutowiredAnnotationBeanPostProcessor() {
@ -206,15 +204,6 @@ public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationA
catch (ClassNotFoundException ex) {
// jakarta.inject API not available - simply skip.
}
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", classLoader));
logger.trace("'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// javax.inject API not available - simply skip.
}
}

View File

@ -33,14 +33,10 @@ class JakartaAnnotationsRuntimeHints implements RuntimeHintsRegistrar {
@Override
public void registerHints(RuntimeHints hints, @Nullable ClassLoader classLoader) {
// javax.inject.Provider is omitted from the list, since we do not currently load
// it via reflection.
Stream.of(
"jakarta.inject.Inject",
"jakarta.inject.Provider",
"jakarta.inject.Qualifier",
"javax.inject.Inject",
"javax.inject.Qualifier"
"jakarta.inject.Qualifier"
).forEach(typeName -> hints.reflection().registerType(TypeReference.of(typeName)));
}

View File

@ -47,8 +47,7 @@ import org.springframework.util.ObjectUtils;
* against {@link Qualifier qualifier annotations} on the field or parameter to be autowired.
* Also supports suggested expression values through a {@link Value value} annotation.
*
* <p>Also supports JSR-330's {@link jakarta.inject.Qualifier} annotation (as well as its
* pre-Jakarta {@code javax.inject.Qualifier} equivalent), if available.
* <p>Also supports JSR-330's {@link jakarta.inject.Qualifier} annotation if available.
*
* @author Mark Fisher
* @author Juergen Hoeller
@ -69,8 +68,7 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
/**
* Create a new {@code QualifierAnnotationAutowireCandidateResolver} for Spring's
* standard {@link Qualifier} annotation.
* <p>Also supports JSR-330's {@link jakarta.inject.Qualifier} annotation (as well as
* its pre-Jakarta {@code javax.inject.Qualifier} equivalent), if available.
* <p>Also supports JSR-330's {@link jakarta.inject.Qualifier} annotation if available.
*/
@SuppressWarnings("unchecked")
public QualifierAnnotationAutowireCandidateResolver() {
@ -82,13 +80,6 @@ public class QualifierAnnotationAutowireCandidateResolver extends GenericTypeAwa
catch (ClassNotFoundException ex) {
// JSR-330 API (as included in Jakarta EE) not available - simply skip.
}
try {
this.qualifierTypes.add((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Qualifier",
QualifierAnnotationAutowireCandidateResolver.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}
/**

View File

@ -508,8 +508,8 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
/**
* Register an externally managed configuration initialization method &mdash;
* for example, a method annotated with JSR-250's {@code javax.annotation.PostConstruct}
* or Jakarta's {@link jakarta.annotation.PostConstruct} annotation.
* for example, a method annotated with Jakarta's
* {@link jakarta.annotation.PostConstruct} annotation.
* <p>The supplied {@code initMethod} may be a
* {@linkplain Method#getName() simple method name} or a
* {@linkplain org.springframework.util.ClassUtils#getQualifiedMethodName(Method)

View File

@ -63,14 +63,4 @@ class JakartaAnnotationsRuntimeHintsTests {
assertThat(RuntimeHintsPredicates.reflection().onType(Qualifier.class)).accepts(this.hints);
}
@Test // gh-33345
void javaxInjectAnnotationHasHints() {
assertThat(RuntimeHintsPredicates.reflection().onType(javax.inject.Inject.class)).accepts(this.hints);
}
@Test // gh-33345
void javaxQualifierAnnotationHasHints() {
assertThat(RuntimeHintsPredicates.reflection().onType(javax.inject.Qualifier.class)).accepts(this.hints);
}
}

View File

@ -21,7 +21,6 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Path;
import jakarta.annotation.ManagedBean;
import jakarta.inject.Named;
import jakarta.persistence.Converter;
import jakarta.persistence.Embeddable;
@ -43,7 +42,6 @@ import org.springframework.context.index.sample.SampleNonStaticEmbedded;
import org.springframework.context.index.sample.SampleNone;
import org.springframework.context.index.sample.SampleRepository;
import org.springframework.context.index.sample.SampleService;
import org.springframework.context.index.sample.cdi.SampleManagedBean;
import org.springframework.context.index.sample.cdi.SampleNamed;
import org.springframework.context.index.sample.cdi.SampleTransactional;
import org.springframework.context.index.sample.jpa.SampleConverter;
@ -126,11 +124,6 @@ class CandidateComponentsIndexerTests {
testComponent(AbstractController.class);
}
@Test
void cdiManagedBean() {
testSingleComponent(SampleManagedBean.class, ManagedBean.class);
}
@Test
void cdiNamed() {
testSingleComponent(SampleNamed.class, Named.class);

View File

@ -1,28 +0,0 @@
/*
* Copyright 2002-2016 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 org.springframework.context.index.sample.cdi;
import jakarta.annotation.ManagedBean;
/**
* Test candidate for a CDI {@link ManagedBean}.
*
* @author Stephane Nicoll
*/
@ManagedBean
public class SampleManagedBean {
}

View File

@ -23,7 +23,7 @@ dependencies {
testImplementation("io.projectreactor:reactor-core")
testImplementation("jakarta.annotation:jakarta.annotation-api")
testImplementation("org.hsqldb:hsqldb")
testRuntimeOnly("com.sun.mail:jakarta.mail")
testRuntimeOnly("org.eclipse.angus:angus-mail")
testRuntimeOnly("org.ehcache:ehcache")
testRuntimeOnly("org.ehcache:jcache")
testRuntimeOnly("org.glassfish:jakarta.el")

View File

@ -21,8 +21,6 @@ dependencies {
optional("jakarta.inject:jakarta.inject-api")
optional("jakarta.interceptor:jakarta.interceptor-api")
optional("jakarta.validation:jakarta.validation-api")
optional("javax.annotation:javax.annotation-api")
optional("javax.inject:javax.inject")
optional("javax.money:money-api")
optional("org.apache.groovy:groovy")
optional("org.apache-extras.beanshell:bsh")

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.
@ -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"));
}

View File

@ -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));

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.
@ -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

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.
@ -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.
}
}
/**

View File

@ -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.

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)

View File

@ -10,9 +10,4 @@ example.scannable.ServiceInvocationCounter=org.springframework.stereotype.Compon
example.scannable.sub.BarComponent=org.springframework.stereotype.Component
example.scannable.JakartaManagedBeanComponent=jakarta.annotation.ManagedBean
example.scannable.JakartaNamedComponent=jakarta.inject.Named
example.scannable.JavaxManagedBeanComponent=javax.annotation.ManagedBean
example.scannable.JavaxNamedComponent=javax.inject.Named
example.indexed.IndexedJakartaManagedBeanComponent=jakarta.annotation.ManagedBean
example.indexed.IndexedJakartaNamedComponent=jakarta.inject.Named
example.indexed.IndexedJavaxManagedBeanComponent=javax.annotation.ManagedBean
example.indexed.IndexedJavaxNamedComponent=javax.inject.Named

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.
@ -18,6 +18,7 @@ package org.springframework.messaging.converter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
@ -91,7 +92,6 @@ public abstract class AbstractJsonMessageConverter extends AbstractMessageConver
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
Writer writer = getWriter(out, headers);
toJson(payload, resolvedType, writer);
writer.flush();
return out.toByteArray();
}
else {
@ -120,11 +120,11 @@ public abstract class AbstractJsonMessageConverter extends AbstractMessageConver
}
protected abstract Object fromJson(Reader reader, Type resolvedType);
protected abstract Object fromJson(Reader reader, Type resolvedType) throws IOException;
protected abstract Object fromJson(String payload, Type resolvedType);
protected abstract void toJson(Object payload, Type resolvedType, Writer writer);
protected abstract void toJson(Object payload, Type resolvedType, Writer writer) throws IOException;
protected abstract String toJson(Object payload, Type resolvedType);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 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.
@ -16,6 +16,7 @@
package org.springframework.messaging.converter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.ParameterizedType;
@ -88,13 +89,14 @@ public class GsonMessageConverter extends AbstractJsonMessageConverter {
}
@Override
protected void toJson(Object payload, Type resolvedType, Writer writer) {
protected void toJson(Object payload, Type resolvedType, Writer writer) throws IOException {
if (resolvedType instanceof ParameterizedType) {
getGson().toJson(payload, resolvedType, writer);
}
else {
getGson().toJson(payload, writer);
}
writer.flush();
}
@Override

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@ -76,13 +76,9 @@ public class KotlinSerializationJsonMessageConverter extends AbstractJsonMessage
}
@Override
protected void toJson(Object payload, Type resolvedType, Writer writer) {
try {
protected void toJson(Object payload, Type resolvedType, Writer writer) throws IOException {
writer.write(toJson(payload, resolvedType).toCharArray());
}
catch (IOException ex) {
throw new MessageConversionException("Could not write JSON: " + ex.getMessage(), ex);
}
writer.flush();
}
@Override
@ -106,4 +102,5 @@ public class KotlinSerializationJsonMessageConverter extends AbstractJsonMessage
}
return serializer;
}
}

View File

@ -11,7 +11,7 @@ dependencies {
optional(project(":spring-web"))
optional("jakarta.servlet:jakarta.servlet-api")
optional("org.eclipse.persistence:org.eclipse.persistence.jpa")
optional("org.hibernate:hibernate-core-jakarta")
optional("org.hibernate:hibernate-core")
testImplementation(project(":spring-core-test"))
testImplementation(testFixtures(project(":spring-beans")))
testImplementation(testFixtures(project(":spring-context")))

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@ -16,13 +16,10 @@
package org.springframework.orm.hibernate5;
import org.hibernate.HibernateException;
import org.hibernate.UnresolvableObjectException;
import org.hibernate.WrongClassException;
import org.springframework.lang.Nullable;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.util.ReflectionUtils;
/**
* Hibernate-specific subclass of ObjectRetrievalFailureException.
@ -36,24 +33,11 @@ import org.springframework.util.ReflectionUtils;
public class HibernateObjectRetrievalFailureException extends ObjectRetrievalFailureException {
public HibernateObjectRetrievalFailureException(UnresolvableObjectException ex) {
super(ex.getEntityName(), getIdentifier(ex), ex.getMessage(), ex);
super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex);
}
public HibernateObjectRetrievalFailureException(WrongClassException ex) {
super(ex.getEntityName(), getIdentifier(ex), ex.getMessage(), ex);
}
@Nullable
static Object getIdentifier(HibernateException hibEx) {
try {
// getIdentifier declares Serializable return value on 5.x but Object on 6.x
// -> not binary compatible, let's invoke it reflectively for the time being
return ReflectionUtils.invokeMethod(hibEx.getClass().getMethod("getIdentifier"), hibEx);
}
catch (NoSuchMethodException ex) {
return null;
}
super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex);
}
}

View File

@ -1,857 +0,0 @@
/*
* Copyright 2002-2021 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 org.springframework.orm.hibernate5;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Filter;
import org.hibernate.LockMode;
import org.hibernate.ReplicationMode;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.dao.DataAccessException;
import org.springframework.lang.Nullable;
/**
* Interface that specifies a common set of Hibernate operations as well as
* a general {@link #execute} method for Session-based lambda expressions.
* Implemented by {@link HibernateTemplate}. Not often used, but a useful option
* to enhance testability, as it can easily be mocked or stubbed.
*
* <p>Defines {@code HibernateTemplate}'s data access methods that mirror various
* {@link org.hibernate.Session} methods. Users are strongly encouraged to read the
* Hibernate {@code Session} javadocs for details on the semantics of those methods.
*
* <p><b>A deprecation note:</b> While {@link HibernateTemplate} and this operations
* interface are being kept around for backwards compatibility in terms of the data
* access implementation style in Spring applications, we strongly recommend the use
* of native {@link org.hibernate.Session} access code for non-trivial interactions.
* This in particular affects parameterized queries where - on Java 8+ - a custom
* {@link HibernateCallback} lambda code block with {@code createQuery} and several
* {@code setParameter} calls on the {@link org.hibernate.query.Query} interface
* is an elegant solution, to be executed via the general {@link #execute} method.
* All such operations which benefit from a lambda variant have been marked as
* {@code deprecated} on this interface.
*
* <p><b>A Hibernate compatibility note:</b> {@link HibernateTemplate} and the
* operations on this interface generally aim to be applicable across all Hibernate
* versions. In terms of binary compatibility, Spring ships a variant for each major
* generation of Hibernate (in the present case: Hibernate ORM 5.x). However, due to
* refactorings and removals in Hibernate ORM 5.3, some variants - in particular
* legacy positional parameters starting from index 0 - do not work anymore.
* All affected operations are marked as deprecated; please replace them with the
* general {@link #execute} method and custom lambda blocks creating the queries,
* ideally setting named parameters through {@link org.hibernate.query.Query}.
* <b>Please be aware that deprecated operations are known to work with Hibernate
* ORM 5.2 but may not work with Hibernate ORM 5.3 and higher anymore.</b>
*
* @author Juergen Hoeller
* @since 4.2
* @see HibernateTemplate
* @see org.hibernate.Session
* @see HibernateTransactionManager
*/
public interface HibernateOperations {
/**
* Execute the action specified by the given action object within a
* {@link org.hibernate.Session}.
* <p>Application exceptions thrown by the action object get propagated
* to the caller (can only be unchecked). Hibernate exceptions are
* transformed into appropriate DAO ones. Allows for returning a result
* object, that is a domain object or a collection of domain objects.
* <p>Note: Callback code is not supposed to handle transactions itself!
* Use an appropriate transaction manager like
* {@link HibernateTransactionManager}. Generally, callback code must not
* touch any {@code Session} lifecycle methods, like close,
* disconnect, or reconnect, to let the template do its work.
* @param action callback object that specifies the Hibernate action
* @return a result object returned by the action, or {@code null}
* @throws DataAccessException in case of Hibernate errors
* @see HibernateTransactionManager
* @see org.hibernate.Session
*/
@Nullable
<T> T execute(HibernateCallback<T> action) throws DataAccessException;
//-------------------------------------------------------------------------
// Convenience methods for loading individual objects
//-------------------------------------------------------------------------
/**
* Return the persistent instance of the given entity class
* with the given identifier, or {@code null} if not found.
* <p>This method is a thin wrapper around
* {@link org.hibernate.Session#get(Class, Serializable)} for convenience.
* For an explanation of the exact semantics of this method, please do refer to
* the Hibernate API documentation in the first instance.
* @param entityClass a persistent class
* @param id the identifier of the persistent instance
* @return the persistent instance, or {@code null} if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#get(Class, Serializable)
*/
@Nullable
<T> T get(Class<T> entityClass, Serializable id) throws DataAccessException;
/**
* Return the persistent instance of the given entity class
* with the given identifier, or {@code null} if not found.
* <p>Obtains the specified lock mode if the instance exists.
* <p>This method is a thin wrapper around
* {@link org.hibernate.Session#get(Class, Serializable, LockMode)} for convenience.
* For an explanation of the exact semantics of this method, please do refer to
* the Hibernate API documentation in the first instance.
* @param entityClass a persistent class
* @param id the identifier of the persistent instance
* @param lockMode the lock mode to obtain
* @return the persistent instance, or {@code null} if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#get(Class, Serializable, LockMode)
*/
@Nullable
<T> T get(Class<T> entityClass, Serializable id, LockMode lockMode) throws DataAccessException;
/**
* Return the persistent instance of the given entity class
* with the given identifier, or {@code null} if not found.
* <p>This method is a thin wrapper around
* {@link org.hibernate.Session#get(String, Serializable)} for convenience.
* For an explanation of the exact semantics of this method, please do refer to
* the Hibernate API documentation in the first instance.
* @param entityName the name of the persistent entity
* @param id the identifier of the persistent instance
* @return the persistent instance, or {@code null} if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#get(Class, Serializable)
*/
@Nullable
Object get(String entityName, Serializable id) throws DataAccessException;
/**
* Return the persistent instance of the given entity class
* with the given identifier, or {@code null} if not found.
* Obtains the specified lock mode if the instance exists.
* <p>This method is a thin wrapper around
* {@link org.hibernate.Session#get(String, Serializable, LockMode)} for convenience.
* For an explanation of the exact semantics of this method, please do refer to
* the Hibernate API documentation in the first instance.
* @param entityName the name of the persistent entity
* @param id the identifier of the persistent instance
* @param lockMode the lock mode to obtain
* @return the persistent instance, or {@code null} if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#get(Class, Serializable, LockMode)
*/
@Nullable
Object get(String entityName, Serializable id, LockMode lockMode) throws DataAccessException;
/**
* Return the persistent instance of the given entity class
* with the given identifier, throwing an exception if not found.
* <p>This method is a thin wrapper around
* {@link org.hibernate.Session#load(Class, Serializable)} for convenience.
* For an explanation of the exact semantics of this method, please do refer to
* the Hibernate API documentation in the first instance.
* @param entityClass a persistent class
* @param id the identifier of the persistent instance
* @return the persistent instance
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#load(Class, Serializable)
*/
<T> T load(Class<T> entityClass, Serializable id) throws DataAccessException;
/**
* Return the persistent instance of the given entity class
* with the given identifier, throwing an exception if not found.
* Obtains the specified lock mode if the instance exists.
* <p>This method is a thin wrapper around
* {@link org.hibernate.Session#load(Class, Serializable, LockMode)} for convenience.
* For an explanation of the exact semantics of this method, please do refer to
* the Hibernate API documentation in the first instance.
* @param entityClass a persistent class
* @param id the identifier of the persistent instance
* @param lockMode the lock mode to obtain
* @return the persistent instance
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#load(Class, Serializable)
*/
<T> T load(Class<T> entityClass, Serializable id, LockMode lockMode) throws DataAccessException;
/**
* Return the persistent instance of the given entity class
* with the given identifier, throwing an exception if not found.
* <p>This method is a thin wrapper around
* {@link org.hibernate.Session#load(String, Serializable)} for convenience.
* For an explanation of the exact semantics of this method, please do refer to
* the Hibernate API documentation in the first instance.
* @param entityName the name of the persistent entity
* @param id the identifier of the persistent instance
* @return the persistent instance
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#load(Class, Serializable)
*/
Object load(String entityName, Serializable id) throws DataAccessException;
/**
* Return the persistent instance of the given entity class
* with the given identifier, throwing an exception if not found.
* <p>Obtains the specified lock mode if the instance exists.
* <p>This method is a thin wrapper around
* {@link org.hibernate.Session#load(String, Serializable, LockMode)} for convenience.
* For an explanation of the exact semantics of this method, please do refer to
* the Hibernate API documentation in the first instance.
* @param entityName the name of the persistent entity
* @param id the identifier of the persistent instance
* @param lockMode the lock mode to obtain
* @return the persistent instance
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#load(Class, Serializable)
*/
Object load(String entityName, Serializable id, LockMode lockMode) throws DataAccessException;
/**
* Return all persistent instances of the given entity class.
* Note: Use queries or criteria for retrieving a specific subset.
* @param entityClass a persistent class
* @return a {@link List} containing 0 or more persistent instances
* @throws DataAccessException if there is a Hibernate error
* @see org.hibernate.Session#createCriteria
*/
<T> List<T> loadAll(Class<T> entityClass) throws DataAccessException;
/**
* Load the persistent instance with the given identifier
* into the given object, throwing an exception if not found.
* <p>This method is a thin wrapper around
* {@link org.hibernate.Session#load(Object, Serializable)} for convenience.
* For an explanation of the exact semantics of this method, please do refer to
* the Hibernate API documentation in the first instance.
* @param entity the object (of the target class) to load into
* @param id the identifier of the persistent instance
* @throws org.springframework.orm.ObjectRetrievalFailureException if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#load(Object, Serializable)
*/
void load(Object entity, Serializable id) throws DataAccessException;
/**
* Re-read the state of the given persistent instance.
* @param entity the persistent instance to re-read
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#refresh(Object)
*/
void refresh(Object entity) throws DataAccessException;
/**
* Re-read the state of the given persistent instance.
* Obtains the specified lock mode for the instance.
* @param entity the persistent instance to re-read
* @param lockMode the lock mode to obtain
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#refresh(Object, LockMode)
*/
void refresh(Object entity, LockMode lockMode) throws DataAccessException;
/**
* Check whether the given object is in the Session cache.
* @param entity the persistence instance to check
* @return whether the given object is in the Session cache
* @throws DataAccessException if there is a Hibernate error
* @see org.hibernate.Session#contains
*/
boolean contains(Object entity) throws DataAccessException;
/**
* Remove the given object from the {@link org.hibernate.Session} cache.
* @param entity the persistent instance to evict
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#evict
*/
void evict(Object entity) throws DataAccessException;
/**
* Force initialization of a Hibernate proxy or persistent collection.
* @param proxy a proxy for a persistent object or a persistent collection
* @throws DataAccessException if we can't initialize the proxy, for example
* because it is not associated with an active Session
* @see org.hibernate.Hibernate#initialize
*/
void initialize(Object proxy) throws DataAccessException;
/**
* Return an enabled Hibernate {@link Filter} for the given filter name.
* The returned {@code Filter} instance can be used to set filter parameters.
* @param filterName the name of the filter
* @return the enabled Hibernate {@code Filter} (either already
* enabled or enabled on the fly by this operation)
* @throws IllegalStateException if we are not running within a
* transactional Session (in which case this operation does not make sense)
*/
Filter enableFilter(String filterName) throws IllegalStateException;
//-------------------------------------------------------------------------
// Convenience methods for storing individual objects
//-------------------------------------------------------------------------
/**
* Obtain the specified lock level upon the given object, implicitly
* checking whether the corresponding database entry still exists.
* @param entity the persistent instance to lock
* @param lockMode the lock mode to obtain
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#lock(Object, LockMode)
*/
void lock(Object entity, LockMode lockMode) throws DataAccessException;
/**
* Obtain the specified lock level upon the given object, implicitly
* checking whether the corresponding database entry still exists.
* @param entityName the name of the persistent entity
* @param entity the persistent instance to lock
* @param lockMode the lock mode to obtain
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#lock(String, Object, LockMode)
*/
void lock(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
/**
* Persist the given transient instance.
* @param entity the transient instance to persist
* @return the generated identifier
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#save(Object)
*/
Serializable save(Object entity) throws DataAccessException;
/**
* Persist the given transient instance.
* @param entityName the name of the persistent entity
* @param entity the transient instance to persist
* @return the generated identifier
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#save(String, Object)
*/
Serializable save(String entityName, Object entity) throws DataAccessException;
/**
* Update the given persistent instance,
* associating it with the current Hibernate {@link org.hibernate.Session}.
* @param entity the persistent instance to update
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#update(Object)
*/
void update(Object entity) throws DataAccessException;
/**
* Update the given persistent instance,
* associating it with the current Hibernate {@link org.hibernate.Session}.
* <p>Obtains the specified lock mode if the instance exists, implicitly
* checking whether the corresponding database entry still exists.
* @param entity the persistent instance to update
* @param lockMode the lock mode to obtain
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#update(Object)
*/
void update(Object entity, LockMode lockMode) throws DataAccessException;
/**
* Update the given persistent instance,
* associating it with the current Hibernate {@link org.hibernate.Session}.
* @param entityName the name of the persistent entity
* @param entity the persistent instance to update
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#update(String, Object)
*/
void update(String entityName, Object entity) throws DataAccessException;
/**
* Update the given persistent instance,
* associating it with the current Hibernate {@link org.hibernate.Session}.
* <p>Obtains the specified lock mode if the instance exists, implicitly
* checking whether the corresponding database entry still exists.
* @param entityName the name of the persistent entity
* @param entity the persistent instance to update
* @param lockMode the lock mode to obtain
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#update(String, Object)
*/
void update(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
/**
* Save or update the given persistent instance,
* according to its id (matching the configured "unsaved-value"?).
* Associates the instance with the current Hibernate {@link org.hibernate.Session}.
* @param entity the persistent instance to save or update
* (to be associated with the Hibernate {@code Session})
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#saveOrUpdate(Object)
*/
void saveOrUpdate(Object entity) throws DataAccessException;
/**
* Save or update the given persistent instance,
* according to its id (matching the configured "unsaved-value"?).
* Associates the instance with the current Hibernate {@code Session}.
* @param entityName the name of the persistent entity
* @param entity the persistent instance to save or update
* (to be associated with the Hibernate {@code Session})
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#saveOrUpdate(String, Object)
*/
void saveOrUpdate(String entityName, Object entity) throws DataAccessException;
/**
* Persist the state of the given detached instance according to the
* given replication mode, reusing the current identifier value.
* @param entity the persistent object to replicate
* @param replicationMode the Hibernate ReplicationMode
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#replicate(Object, ReplicationMode)
*/
void replicate(Object entity, ReplicationMode replicationMode) throws DataAccessException;
/**
* Persist the state of the given detached instance according to the
* given replication mode, reusing the current identifier value.
* @param entityName the name of the persistent entity
* @param entity the persistent object to replicate
* @param replicationMode the Hibernate ReplicationMode
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#replicate(String, Object, ReplicationMode)
*/
void replicate(String entityName, Object entity, ReplicationMode replicationMode) throws DataAccessException;
/**
* Persist the given transient instance. Follows JSR-220 semantics.
* <p>Similar to {@code save}, associating the given object
* with the current Hibernate {@link org.hibernate.Session}.
* @param entity the persistent instance to persist
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#persist(Object)
* @see #save
*/
void persist(Object entity) throws DataAccessException;
/**
* Persist the given transient instance. Follows JSR-220 semantics.
* <p>Similar to {@code save}, associating the given object
* with the current Hibernate {@link org.hibernate.Session}.
* @param entityName the name of the persistent entity
* @param entity the persistent instance to persist
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#persist(String, Object)
* @see #save
*/
void persist(String entityName, Object entity) throws DataAccessException;
/**
* Copy the state of the given object onto the persistent object
* with the same identifier. Follows JSR-220 semantics.
* <p>Similar to {@code saveOrUpdate}, but never associates the given
* object with the current Hibernate Session. In case of a new entity,
* the state will be copied over as well.
* <p>Note that {@code merge} will <i>not</i> update the identifiers
* in the passed-in object graph (in contrast to TopLink)! Consider
* registering Spring's {@code IdTransferringMergeEventListener} if
* you would like to have newly assigned ids transferred to the original
* object graph too.
* @param entity the object to merge with the corresponding persistence instance
* @return the updated, registered persistent instance
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#merge(Object)
* @see #saveOrUpdate
*/
<T> T merge(T entity) throws DataAccessException;
/**
* Copy the state of the given object onto the persistent object
* with the same identifier. Follows JSR-220 semantics.
* <p>Similar to {@code saveOrUpdate}, but never associates the given
* object with the current Hibernate {@link org.hibernate.Session}. In
* the case of a new entity, the state will be copied over as well.
* <p>Note that {@code merge} will <i>not</i> update the identifiers
* in the passed-in object graph (in contrast to TopLink)! Consider
* registering Spring's {@code IdTransferringMergeEventListener}
* if you would like to have newly assigned ids transferred to the
* original object graph too.
* @param entityName the name of the persistent entity
* @param entity the object to merge with the corresponding persistence instance
* @return the updated, registered persistent instance
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#merge(String, Object)
* @see #saveOrUpdate
*/
<T> T merge(String entityName, T entity) throws DataAccessException;
/**
* Delete the given persistent instance.
* @param entity the persistent instance to delete
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#delete(Object)
*/
void delete(Object entity) throws DataAccessException;
/**
* Delete the given persistent instance.
* <p>Obtains the specified lock mode if the instance exists, implicitly
* checking whether the corresponding database entry still exists.
* @param entity the persistent instance to delete
* @param lockMode the lock mode to obtain
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#delete(Object)
*/
void delete(Object entity, LockMode lockMode) throws DataAccessException;
/**
* Delete the given persistent instance.
* @param entityName the name of the persistent entity
* @param entity the persistent instance to delete
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#delete(Object)
*/
void delete(String entityName, Object entity) throws DataAccessException;
/**
* Delete the given persistent instance.
* <p>Obtains the specified lock mode if the instance exists, implicitly
* checking whether the corresponding database entry still exists.
* @param entityName the name of the persistent entity
* @param entity the persistent instance to delete
* @param lockMode the lock mode to obtain
* @throws org.springframework.orm.ObjectOptimisticLockingFailureException if not found
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#delete(Object)
*/
void delete(String entityName, Object entity, LockMode lockMode) throws DataAccessException;
/**
* Delete all given persistent instances.
* <p>This can be combined with any of the find methods to delete by query
* in two lines of code.
* @param entities the persistent instances to delete
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#delete(Object)
*/
void deleteAll(Collection<?> entities) throws DataAccessException;
/**
* Flush all pending saves, updates and deletes to the database.
* <p>Only invoke this for selective eager flushing, for example when
* JDBC code needs to see certain changes within the same transaction.
* Else, it is preferable to rely on auto-flushing at transaction
* completion.
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#flush
*/
void flush() throws DataAccessException;
/**
* Remove all objects from the {@link org.hibernate.Session} cache, and
* cancel all pending saves, updates and deletes.
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#clear
*/
void clear() throws DataAccessException;
//-------------------------------------------------------------------------
// Convenience finder methods for detached criteria
//-------------------------------------------------------------------------
/**
* Execute a query based on a given Hibernate criteria object.
* @param criteria the detached Hibernate criteria object.
* <b>Note: Do not reuse criteria objects! They need to recreated per execution,
* due to the suboptimal design of Hibernate's criteria facility.</b>
* @return a {@link List} containing 0 or more persistent instances
* @throws DataAccessException in case of Hibernate errors
* @see DetachedCriteria#getExecutableCriteria(org.hibernate.Session)
*/
List<?> findByCriteria(DetachedCriteria criteria) throws DataAccessException;
/**
* Execute a query based on the given Hibernate criteria object.
* @param criteria the detached Hibernate criteria object.
* <b>Note: Do not reuse criteria objects! They need to recreated per execution,
* due to the suboptimal design of Hibernate's criteria facility.</b>
* @param firstResult the index of the first result object to be retrieved
* (numbered from 0)
* @param maxResults the maximum number of result objects to retrieve
* (or &lt;=0 for no limit)
* @return a {@link List} containing 0 or more persistent instances
* @throws DataAccessException in case of Hibernate errors
* @see DetachedCriteria#getExecutableCriteria(org.hibernate.Session)
* @see org.hibernate.Criteria#setFirstResult(int)
* @see org.hibernate.Criteria#setMaxResults(int)
*/
List<?> findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults) throws DataAccessException;
/**
* Execute a query based on the given example entity object.
* @param exampleEntity an instance of the desired entity,
* serving as example for "query-by-example"
* @return a {@link List} containing 0 or more persistent instances
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.criterion.Example#create(Object)
*/
<T> List<T> findByExample(T exampleEntity) throws DataAccessException;
/**
* Execute a query based on the given example entity object.
* @param entityName the name of the persistent entity
* @param exampleEntity an instance of the desired entity,
* serving as example for "query-by-example"
* @return a {@link List} containing 0 or more persistent instances
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.criterion.Example#create(Object)
*/
<T> List<T> findByExample(String entityName, T exampleEntity) throws DataAccessException;
/**
* Execute a query based on a given example entity object.
* @param exampleEntity an instance of the desired entity,
* serving as example for "query-by-example"
* @param firstResult the index of the first result object to be retrieved
* (numbered from 0)
* @param maxResults the maximum number of result objects to retrieve
* (or &lt;=0 for no limit)
* @return a {@link List} containing 0 or more persistent instances
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.criterion.Example#create(Object)
* @see org.hibernate.Criteria#setFirstResult(int)
* @see org.hibernate.Criteria#setMaxResults(int)
*/
<T> List<T> findByExample(T exampleEntity, int firstResult, int maxResults) throws DataAccessException;
/**
* Execute a query based on a given example entity object.
* @param entityName the name of the persistent entity
* @param exampleEntity an instance of the desired entity,
* serving as example for "query-by-example"
* @param firstResult the index of the first result object to be retrieved
* (numbered from 0)
* @param maxResults the maximum number of result objects to retrieve
* (or &lt;=0 for no limit)
* @return a {@link List} containing 0 or more persistent instances
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.criterion.Example#create(Object)
* @see org.hibernate.Criteria#setFirstResult(int)
* @see org.hibernate.Criteria#setMaxResults(int)
*/
<T> List<T> findByExample(String entityName, T exampleEntity, int firstResult, int maxResults)
throws DataAccessException;
//-------------------------------------------------------------------------
// Convenience finder methods for HQL strings
//-------------------------------------------------------------------------
/**
* Execute an HQL query, binding a number of values to "?" parameters
* in the query string.
* @param queryString a query expressed in Hibernate's query language
* @param values the values of the parameters
* @return a {@link List} containing the results of the query execution
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#createQuery
* @deprecated as of 5.0.4, in favor of a custom {@link HibernateCallback}
* lambda code block passed to the general {@link #execute} method
*/
@Deprecated
List<?> find(String queryString, Object... values) throws DataAccessException;
/**
* Execute an HQL query, binding one value to a ":" named parameter
* in the query string.
* @param queryString a query expressed in Hibernate's query language
* @param paramName the name of the parameter
* @param value the value of the parameter
* @return a {@link List} containing the results of the query execution
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#getNamedQuery(String)
* @deprecated as of 5.0.4, in favor of a custom {@link HibernateCallback}
* lambda code block passed to the general {@link #execute} method
*/
@Deprecated
List<?> findByNamedParam(String queryString, String paramName, Object value) throws DataAccessException;
/**
* Execute an HQL query, binding a number of values to ":" named
* parameters in the query string.
* @param queryString a query expressed in Hibernate's query language
* @param paramNames the names of the parameters
* @param values the values of the parameters
* @return a {@link List} containing the results of the query execution
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#getNamedQuery(String)
* @deprecated as of 5.0.4, in favor of a custom {@link HibernateCallback}
* lambda code block passed to the general {@link #execute} method
*/
@Deprecated
List<?> findByNamedParam(String queryString, String[] paramNames, Object[] values) throws DataAccessException;
/**
* Execute an HQL query, binding the properties of the given bean to
* <i>named</i> parameters in the query string.
* @param queryString a query expressed in Hibernate's query language
* @param valueBean the values of the parameters
* @return a {@link List} containing the results of the query execution
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Query#setProperties
* @see org.hibernate.Session#createQuery
* @deprecated as of 5.0.4, in favor of a custom {@link HibernateCallback}
* lambda code block passed to the general {@link #execute} method
*/
@Deprecated
List<?> findByValueBean(String queryString, Object valueBean) throws DataAccessException;
//-------------------------------------------------------------------------
// Convenience finder methods for named queries
//-------------------------------------------------------------------------
/**
* Execute a named query binding a number of values to "?" parameters
* in the query string.
* <p>A named query is defined in a Hibernate mapping file.
* @param queryName the name of a Hibernate query in a mapping file
* @param values the values of the parameters
* @return a {@link List} containing the results of the query execution
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#getNamedQuery(String)
* @deprecated as of 5.0.4, in favor of a custom {@link HibernateCallback}
* lambda code block passed to the general {@link #execute} method
*/
@Deprecated
List<?> findByNamedQuery(String queryName, Object... values) throws DataAccessException;
/**
* Execute a named query, binding one value to a ":" named parameter
* in the query string.
* <p>A named query is defined in a Hibernate mapping file.
* @param queryName the name of a Hibernate query in a mapping file
* @param paramName the name of parameter
* @param value the value of the parameter
* @return a {@link List} containing the results of the query execution
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#getNamedQuery(String)
* @deprecated as of 5.0.4, in favor of a custom {@link HibernateCallback}
* lambda code block passed to the general {@link #execute} method
*/
@Deprecated
List<?> findByNamedQueryAndNamedParam(String queryName, String paramName, Object value)
throws DataAccessException;
/**
* Execute a named query, binding a number of values to ":" named
* parameters in the query string.
* <p>A named query is defined in a Hibernate mapping file.
* @param queryName the name of a Hibernate query in a mapping file
* @param paramNames the names of the parameters
* @param values the values of the parameters
* @return a {@link List} containing the results of the query execution
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#getNamedQuery(String)
* @deprecated as of 5.0.4, in favor of a custom {@link HibernateCallback}
* lambda code block passed to the general {@link #execute} method
*/
@Deprecated
List<?> findByNamedQueryAndNamedParam(String queryName, String[] paramNames, Object[] values)
throws DataAccessException;
/**
* Execute a named query, binding the properties of the given bean to
* ":" named parameters in the query string.
* <p>A named query is defined in a Hibernate mapping file.
* @param queryName the name of a Hibernate query in a mapping file
* @param valueBean the values of the parameters
* @return a {@link List} containing the results of the query execution
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Query#setProperties
* @see org.hibernate.Session#getNamedQuery(String)
* @deprecated as of 5.0.4, in favor of a custom {@link HibernateCallback}
* lambda code block passed to the general {@link #execute} method
*/
@Deprecated
List<?> findByNamedQueryAndValueBean(String queryName, Object valueBean) throws DataAccessException;
//-------------------------------------------------------------------------
// Convenience query methods for iteration and bulk updates/deletes
//-------------------------------------------------------------------------
/**
* Execute a query for persistent instances, binding a number of
* values to "?" parameters in the query string.
* <p>Returns the results as an {@link Iterator}. Entities returned are
* initialized on demand. See the Hibernate API documentation for details.
* @param queryString a query expressed in Hibernate's query language
* @param values the values of the parameters
* @return an {@link Iterator} containing 0 or more persistent instances
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#createQuery
* @see org.hibernate.Query#iterate
* @deprecated as of 5.0.4, in favor of a custom {@link HibernateCallback}
* lambda code block passed to the general {@link #execute} method
*/
@Deprecated
Iterator<?> iterate(String queryString, Object... values) throws DataAccessException;
/**
* Immediately close an {@link Iterator} created by any of the various
* {@code iterate(..)} operations, instead of waiting until the
* session is closed or disconnected.
* @param it the {@code Iterator} to close
* @throws DataAccessException if the {@code Iterator} could not be closed
* @see org.hibernate.Hibernate#close
* @deprecated as of 5.0.4, in favor of a custom {@link HibernateCallback}
* lambda code block passed to the general {@link #execute} method
*/
@Deprecated
void closeIterator(Iterator<?> it) throws DataAccessException;
/**
* Update/delete all objects according to the given query, binding a number of
* values to "?" parameters in the query string.
* @param queryString an update/delete query expressed in Hibernate's query language
* @param values the values of the parameters
* @return the number of instances updated/deleted
* @throws DataAccessException in case of Hibernate errors
* @see org.hibernate.Session#createQuery
* @see org.hibernate.Query#executeUpdate
* @deprecated as of 5.0.4, in favor of a custom {@link HibernateCallback}
* lambda code block passed to the general {@link #execute} method
*/
@Deprecated
int bulkUpdate(String queryString, Object... values) throws DataAccessException;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 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.
@ -35,7 +35,7 @@ import org.springframework.orm.ObjectOptimisticLockingFailureException;
public class HibernateOptimisticLockingFailureException extends ObjectOptimisticLockingFailureException {
public HibernateOptimisticLockingFailureException(StaleObjectStateException ex) {
super(ex.getEntityName(), HibernateObjectRetrievalFailureException.getIdentifier(ex), ex.getMessage(), ex);
super(ex.getEntityName(), ex.getIdentifier(), ex.getMessage(), ex);
}
public HibernateOptimisticLockingFailureException(StaleStateException ex) {

View File

@ -121,10 +121,10 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
private RegionFactory cacheRegionFactory;
@Nullable
private MultiTenantConnectionProvider multiTenantConnectionProvider;
private MultiTenantConnectionProvider<?> multiTenantConnectionProvider;
@Nullable
private CurrentTenantIdentifierResolver currentTenantIdentifierResolver;
private CurrentTenantIdentifierResolver<Object> currentTenantIdentifierResolver;
@Nullable
private Properties hibernateProperties;
@ -312,7 +312,7 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
* @since 4.3
* @see LocalSessionFactoryBuilder#setMultiTenantConnectionProvider
*/
public void setMultiTenantConnectionProvider(MultiTenantConnectionProvider multiTenantConnectionProvider) {
public void setMultiTenantConnectionProvider(MultiTenantConnectionProvider<?> multiTenantConnectionProvider) {
this.multiTenantConnectionProvider = multiTenantConnectionProvider;
}
@ -320,7 +320,7 @@ public class LocalSessionFactoryBean extends HibernateExceptionTranslator
* Set a {@link CurrentTenantIdentifierResolver} to be passed on to the SessionFactory.
* @see LocalSessionFactoryBuilder#setCurrentTenantIdentifierResolver
*/
public void setCurrentTenantIdentifierResolver(CurrentTenantIdentifierResolver currentTenantIdentifierResolver) {
public void setCurrentTenantIdentifierResolver(CurrentTenantIdentifierResolver<Object> currentTenantIdentifierResolver) {
this.currentTenantIdentifierResolver = currentTenantIdentifierResolver;
}

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.
@ -169,7 +169,7 @@ public class LocalSessionFactoryBuilder extends Configuration {
getProperties().put(AvailableSettings.CURRENT_SESSION_CONTEXT_CLASS, SpringSessionContext.class.getName());
if (dataSource != null) {
getProperties().put(AvailableSettings.DATASOURCE, dataSource);
getProperties().put(AvailableSettings.JAKARTA_NON_JTA_DATASOURCE, dataSource);
}
getProperties().put(AvailableSettings.CONNECTION_HANDLING,
PhysicalConnectionHandlingMode.DELAYED_ACQUISITION_AND_HOLD);
@ -256,7 +256,7 @@ public class LocalSessionFactoryBuilder extends Configuration {
* @since 4.3
* @see AvailableSettings#MULTI_TENANT_CONNECTION_PROVIDER
*/
public LocalSessionFactoryBuilder setMultiTenantConnectionProvider(MultiTenantConnectionProvider multiTenantConnectionProvider) {
public LocalSessionFactoryBuilder setMultiTenantConnectionProvider(MultiTenantConnectionProvider<?> multiTenantConnectionProvider) {
getProperties().put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
return this;
}
@ -267,9 +267,10 @@ public class LocalSessionFactoryBuilder extends Configuration {
* @see AvailableSettings#MULTI_TENANT_IDENTIFIER_RESOLVER
*/
@Override
public void setCurrentTenantIdentifierResolver(CurrentTenantIdentifierResolver currentTenantIdentifierResolver) {
public LocalSessionFactoryBuilder setCurrentTenantIdentifierResolver(CurrentTenantIdentifierResolver<Object> currentTenantIdentifierResolver) {
getProperties().put(AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
super.setCurrentTenantIdentifierResolver(currentTenantIdentifierResolver);
return this;
}
/**

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.
@ -16,7 +16,6 @@
package org.springframework.orm.hibernate5;
import java.lang.reflect.Method;
import java.util.Map;
import javax.sql.DataSource;
@ -64,8 +63,6 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.dao.PessimisticLockingFailureException;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/**
* Helper class featuring methods for Hibernate Session handling.
@ -151,16 +148,13 @@ public abstract class SessionFactoryUtils {
*/
@Nullable
public static DataSource getDataSource(SessionFactory sessionFactory) {
Method getProperties = ClassUtils.getMethodIfAvailable(sessionFactory.getClass(), "getProperties");
if (getProperties != null) {
Map<?, ?> props = (Map<?, ?>) ReflectionUtils.invokeMethod(getProperties, sessionFactory);
Map<String, Object> props = sessionFactory.getProperties();
if (props != null) {
Object dataSourceValue = props.get(Environment.DATASOURCE);
Object dataSourceValue = props.get(Environment.JAKARTA_NON_JTA_DATASOURCE);
if (dataSourceValue instanceof DataSource dataSource) {
return dataSource;
}
}
}
if (sessionFactory instanceof SessionFactoryImplementor sfi) {
try {
ConnectionProvider cp = sfi.getServiceRegistry().getService(ConnectionProvider.class);

View File

@ -1,139 +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 org.springframework.orm.hibernate5.support;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.dao.support.DaoSupport;
import org.springframework.lang.Nullable;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.util.Assert;
/**
* Convenient superclass for Hibernate-based data access objects.
*
* <p>Requires a {@link SessionFactory} to be set, providing a
* {@link org.springframework.orm.hibernate5.HibernateTemplate} based on it to
* subclasses through the {@link #getHibernateTemplate()} method.
* Can alternatively be initialized directly with a HibernateTemplate,
* in order to reuse the latter's settings such as the SessionFactory,
* exception translator, flush mode, etc.
*
* <p>This class will create its own HibernateTemplate instance if a SessionFactory
* is passed in. The "allowCreate" flag on that HibernateTemplate will be "true"
* by default. A custom HibernateTemplate instance can be used through overriding
* {@link #createHibernateTemplate}.
*
* <p><b>NOTE: Hibernate access code can also be coded in plain Hibernate style.
* Hence, for newly started projects, consider adopting the standard Hibernate
* style of coding data access objects instead, based on
* {@link SessionFactory#getCurrentSession()}.
* This HibernateTemplate primarily exists as a migration helper for Hibernate 3
* based data access code, to benefit from bug fixes in Hibernate 5.x.</b>
*
* @author Juergen Hoeller
* @since 4.2
* @see #setSessionFactory
* @see #getHibernateTemplate
* @see org.springframework.orm.hibernate5.HibernateTemplate
*/
public abstract class HibernateDaoSupport extends DaoSupport {
@Nullable
private HibernateTemplate hibernateTemplate;
/**
* Set the Hibernate SessionFactory to be used by this DAO.
* Will automatically create a HibernateTemplate for the given SessionFactory.
* @see #createHibernateTemplate
* @see #setHibernateTemplate
*/
public final void setSessionFactory(SessionFactory sessionFactory) {
if (this.hibernateTemplate == null || sessionFactory != this.hibernateTemplate.getSessionFactory()) {
this.hibernateTemplate = createHibernateTemplate(sessionFactory);
}
}
/**
* Create a HibernateTemplate for the given SessionFactory.
* Only invoked if populating the DAO with a SessionFactory reference!
* <p>Can be overridden in subclasses to provide a HibernateTemplate instance
* with different configuration, or a custom HibernateTemplate subclass.
* @param sessionFactory the Hibernate SessionFactory to create a HibernateTemplate for
* @return the new HibernateTemplate instance
* @see #setSessionFactory
*/
protected HibernateTemplate createHibernateTemplate(SessionFactory sessionFactory) {
return new HibernateTemplate(sessionFactory);
}
/**
* Return the Hibernate SessionFactory used by this DAO.
*/
@Nullable
public final SessionFactory getSessionFactory() {
return (this.hibernateTemplate != null ? this.hibernateTemplate.getSessionFactory() : null);
}
/**
* Set the HibernateTemplate for this DAO explicitly,
* as an alternative to specifying a SessionFactory.
* @see #setSessionFactory
*/
public final void setHibernateTemplate(@Nullable HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
/**
* Return the HibernateTemplate for this DAO,
* pre-initialized with the SessionFactory or set explicitly.
* <p><b>Note: The returned HibernateTemplate is a shared instance.</b>
* You may introspect its configuration, but not modify the configuration
* (other than from within an {@link #initDao} implementation).
* Consider creating a custom HibernateTemplate instance via
* {@code new HibernateTemplate(getSessionFactory())}, in which case
* you're allowed to customize the settings on the resulting instance.
*/
@Nullable
public final HibernateTemplate getHibernateTemplate() {
return this.hibernateTemplate;
}
@Override
protected final void checkDaoConfig() {
if (this.hibernateTemplate == null) {
throw new IllegalArgumentException("'sessionFactory' or 'hibernateTemplate' is required");
}
}
/**
* Conveniently obtain the current Hibernate Session.
* @return the Hibernate Session
* @throws DataAccessResourceFailureException if the Session couldn't be created
* @see SessionFactory#getCurrentSession()
*/
protected final Session currentSession() throws DataAccessResourceFailureException {
SessionFactory sessionFactory = getSessionFactory();
Assert.state(sessionFactory != null, "No SessionFactory set");
return sessionFactory.getCurrentSession();
}
}

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.
@ -192,6 +192,7 @@ public abstract class ExtendedEntityManagerCreator {
* transactions (according to the JPA 2.1 SynchronizationType rules)
* @return the EntityManager proxy
*/
@SuppressWarnings("removal")
private static EntityManager createProxy(EntityManager rawEntityManager,
EntityManagerFactoryInfo emfInfo, boolean containerManaged, boolean synchronizedWithTransaction) {

View File

@ -45,6 +45,7 @@ import org.springframework.util.ClassUtils;
* @author Costin Leau
* @since 2.0
*/
@SuppressWarnings("removal")
public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
@Nullable
@ -289,6 +290,18 @@ public class MutablePersistenceUnitInfo implements SmartPersistenceUnitInfo {
throw new UnsupportedOperationException("getNewTempClassLoader not supported");
}
@Override
@Nullable
public String getScopeAnnotationName() {
return null;
}
@Override
@Nullable
public List<String> getQualifierAnnotationNames() {
return null;
}
@Override
public String toString() {

View File

@ -21,6 +21,7 @@ import java.util.List;
import javax.lang.model.element.Modifier;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Convert;
import jakarta.persistence.Converter;
import jakarta.persistence.EntityListeners;
@ -173,7 +174,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessor implements BeanRegistr
}
ReflectionUtils.doWithFields(managedClass, field -> {
Convert convertFieldAnnotation = AnnotationUtils.findAnnotation(field, Convert.class);
if (convertFieldAnnotation != null && convertFieldAnnotation.converter() != void.class) {
if (convertFieldAnnotation != null && convertFieldAnnotation.converter() != AttributeConverter.class) {
reflectionHints.registerType(convertFieldAnnotation.converter(), MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
}
});

View File

@ -185,6 +185,7 @@ final class PersistenceUnitReader {
/**
* Parse the unit info DOM element.
*/
@SuppressWarnings("removal")
SpringPersistenceUnitInfo parsePersistenceUnitInfo(
Element persistenceUnit, String version, @Nullable URL rootUrl) throws IOException {

View File

@ -28,22 +28,17 @@ import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyTenSevenDialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.HANAColumnStoreDialect;
import org.hibernate.dialect.HANADialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.dialect.Informix10Dialect;
import org.hibernate.dialect.MySQL57Dialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.Oracle12cDialect;
import org.hibernate.dialect.PostgreSQL95Dialect;
import org.hibernate.dialect.SQLServer2012Dialect;
import org.hibernate.dialect.OracleDialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.SQLServerDialect;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.springframework.lang.Nullable;
import org.springframework.util.ClassUtils;
/**
* {@link org.springframework.orm.jpa.JpaVendorAdapter} implementation for Hibernate.
@ -72,9 +67,6 @@ import org.springframework.util.ClassUtils;
*/
public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
private static final boolean oldDialectsPresent = ClassUtils.isPresent(
"org.hibernate.dialect.PostgreSQL95Dialect", HibernateJpaVendorAdapter.class.getClassLoader());
private final HibernateJpaDialect jpaDialect = new HibernateJpaDialect();
private final PersistenceProvider persistenceProvider;
@ -129,6 +121,7 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
return "org.hibernate";
}
@SuppressWarnings("removal")
@Override
public Map<String, Object> getJpaPropertyMap(PersistenceUnitInfo pui) {
return buildJpaPropertyMap(this.jpaDialect.prepareConnection &&
@ -151,6 +144,12 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
if (databaseDialectClass != null) {
jpaProperties.put(AvailableSettings.DIALECT, databaseDialectClass.getName());
}
else {
String databaseDialectName = determineDatabaseDialectName(getDatabase());
if (databaseDialectName != null) {
jpaProperties.put(AvailableSettings.DIALECT, databaseDialectName);
}
}
}
if (isGenerateDdl()) {
@ -173,43 +172,41 @@ public class HibernateJpaVendorAdapter extends AbstractJpaVendorAdapter {
/**
* Determine the Hibernate database dialect class for the given target database.
* <p>The default implementation covers the common built-in dialects.
* @param database the target database
* @return the Hibernate database dialect class, or {@code null} if none found
* @see #determineDatabaseDialectName
*/
@SuppressWarnings("deprecation") // for OracleDialect on Hibernate 5.6 and DerbyDialect/PostgreSQLDialect on Hibernate 6.2
@Nullable
protected Class<?> determineDatabaseDialectClass(Database database) {
if (oldDialectsPresent) { // Hibernate <6.2
return switch (database) {
case DB2 -> DB2Dialect.class;
case DERBY -> DerbyTenSevenDialect.class;
case H2 -> H2Dialect.class;
case HANA -> HANAColumnStoreDialect.class;
case HSQL -> HSQLDialect.class;
case INFORMIX -> Informix10Dialect.class;
case MYSQL -> MySQL57Dialect.class;
case ORACLE -> Oracle12cDialect.class;
case POSTGRESQL -> PostgreSQL95Dialect.class;
case SQL_SERVER -> SQLServer2012Dialect.class;
case SYBASE -> SybaseDialect.class;
default -> null;
};
}
else { // Hibernate 6.2+ aligned
return switch (database) {
case DB2 -> DB2Dialect.class;
case DERBY -> org.hibernate.dialect.DerbyDialect.class;
case H2 -> H2Dialect.class;
case HANA -> HANAColumnStoreDialect.class;
case HANA -> HANADialect.class;
case HSQL -> HSQLDialect.class;
case MYSQL -> MySQLDialect.class;
case ORACLE -> org.hibernate.dialect.OracleDialect.class;
case POSTGRESQL -> org.hibernate.dialect.PostgreSQLDialect.class;
case ORACLE -> OracleDialect.class;
case POSTGRESQL -> PostgreSQLDialect.class;
case SQL_SERVER -> SQLServerDialect.class;
case SYBASE -> SybaseDialect.class;
default -> null;
};
}
/**
* Determine the Hibernate database dialect class name for the given target database.
* <p>The default implementation covers the common community dialect for Derby.
* @param database the target database
* @return the Hibernate database dialect class name, or {@code null} if none found
* @since 7.0
* @see #determineDatabaseDialectClass
*/
@Nullable
protected String determineDatabaseDialectName(Database database) {
return switch (database) {
case DERBY -> "org.hibernate.community.dialect.DerbyDialect";
default -> null;
};
}
@Override

View File

@ -23,6 +23,7 @@ import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceConfiguration;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.spi.PersistenceProvider;
import jakarta.persistence.spi.PersistenceUnitInfo;
@ -52,7 +53,7 @@ import static org.mockito.Mockito.verify;
* @author Juergen Hoeller
* @author Phillip Webb
*/
@SuppressWarnings("rawtypes")
@SuppressWarnings({"rawtypes", "removal"})
class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerFactoryBeanTests {
// Static fields set by inner class DummyPersistenceProvider
@ -310,6 +311,11 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
throw new UnsupportedOperationException();
}
@Override
public EntityManagerFactory createEntityManagerFactory(PersistenceConfiguration persistenceConfiguration) {
throw new UnsupportedOperationException();
}
@Override
public ProviderUtil getProviderUtil() {
throw new UnsupportedOperationException();
@ -357,6 +363,15 @@ class LocalContainerEntityManagerFactoryBeanTests extends AbstractEntityManagerF
public boolean isActive() {
return false;
}
@Override
public void setTimeout(Integer integer) {
}
@Override
public Integer getTimeout() {
return null;
}
}
}

View File

@ -20,6 +20,7 @@ import java.util.Map;
import java.util.Properties;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.PersistenceConfiguration;
import jakarta.persistence.spi.PersistenceProvider;
import jakarta.persistence.spi.PersistenceUnitInfo;
import jakarta.persistence.spi.ProviderUtil;
@ -97,6 +98,11 @@ class LocalEntityManagerFactoryBeanTests extends AbstractEntityManagerFactoryBea
return mockEmf;
}
@Override
public EntityManagerFactory createEntityManagerFactory(PersistenceConfiguration persistenceConfiguration) {
throw new UnsupportedOperationException();
}
@Override
public ProviderUtil getProviderUtil() {
throw new UnsupportedOperationException();

View File

@ -1,7 +1,8 @@
/**
* Sample package-info for testing purposes.
*/
@TypeDef(name = "test", typeClass = Object.class)
@TypeRegistration(basicClass = Object.class, userType = UserTypeLegacyBridge.class)
package org.springframework.orm.jpa.domain2;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeRegistration;
import org.hibernate.usertype.UserTypeLegacyBridge;

View File

@ -21,7 +21,7 @@ import java.util.function.Consumer;
import javax.sql.DataSource;
import org.hibernate.tuple.CreationTimestampGeneration;
import org.hibernate.annotations.CreationTimestamp;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.MemberCategory;
@ -108,12 +108,12 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
});
}
@Test
// @Test
void contributeHibernateHints() {
GenericApplicationContext context = new AnnotationConfigApplicationContext();
context.registerBean(HibernateDomainConfiguration.class);
contributeHints(context, hints ->
assertThat(RuntimeHintsPredicates.reflection().onType(CreationTimestampGeneration.class)
assertThat(RuntimeHintsPredicates.reflection().onType(CreationTimestamp.class)
.withMemberCategories(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(hints));
}
@ -144,6 +144,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
result.accept(generationContext.getRuntimeHints());
}
public static class JpaDomainConfiguration extends AbstractEntityManagerWithPackagesToScanConfiguration {
@Override
@ -152,6 +153,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
}
}
public static class HibernateDomainConfiguration extends AbstractEntityManagerWithPackagesToScanConfiguration {
@Override
@ -160,6 +162,7 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
}
}
public abstract static class AbstractEntityManagerWithPackagesToScanConfiguration {
protected boolean scanningInvoked;
@ -194,7 +197,6 @@ class PersistenceManagedTypesBeanRegistrationAotProcessorTests {
}
protected abstract String packageToScan();
}
}

View File

@ -47,6 +47,7 @@ import static org.assertj.core.api.Assertions.assertThatRuntimeException;
* @author Juergen Hoeller
* @author Nicholas Williams
*/
@SuppressWarnings("removal")
class PersistenceXmlParsingTests {
@Test

View File

@ -27,7 +27,6 @@ dependencies {
optional("jakarta.websocket:jakarta.websocket-api")
optional("jakarta.websocket:jakarta.websocket-client-api")
optional("jakarta.xml.bind:jakarta.xml.bind-api")
optional("javax.inject:javax.inject")
optional("junit:junit")
optional("org.apache.groovy:groovy")
optional("org.apache.tomcat.embed:tomcat-embed-core")
@ -78,7 +77,7 @@ dependencies {
}
testImplementation("org.awaitility:awaitility")
testImplementation("org.easymock:easymock")
testImplementation("org.hibernate:hibernate-core-jakarta")
testImplementation("org.hibernate:hibernate-core")
testImplementation("org.hibernate:hibernate-validator")
testImplementation("org.hsqldb:hsqldb")
testImplementation("org.junit.platform:junit-platform-testkit")

View File

@ -39,9 +39,8 @@ import org.springframework.lang.Nullable;
* on a test class, the default <em>test constructor autowire mode</em> will be
* used. See {@link #TEST_CONSTRUCTOR_AUTOWIRE_MODE_PROPERTY_NAME} for details on
* how to change the default mode. Note, however, that a local declaration of
* {@link org.springframework.beans.factory.annotation.Autowired @Autowired}
* {@link jakarta.inject.Inject @jakarta.inject.Inject}, or
* {@link javax.inject.Inject @javax.inject.Inject} on a constructor takes
* {@link org.springframework.beans.factory.annotation.Autowired @Autowired} or
* {@link jakarta.inject.Inject @jakarta.inject.Inject} on a constructor takes
* precedence over both {@code @TestConstructor} and the default mode.
*
* <p>This annotation may be used as a <em>meta-annotation</em> to create custom
@ -63,7 +62,6 @@ import org.springframework.lang.Nullable;
* @since 5.2
* @see org.springframework.beans.factory.annotation.Autowired @Autowired
* @see jakarta.inject.Inject @jakarta.inject.Inject
* @see javax.inject.Inject @javax.inject.Inject
* @see org.springframework.test.context.junit.jupiter.SpringExtension SpringExtension
* @see org.springframework.test.context.junit.jupiter.SpringJUnitConfig @SpringJUnitConfig
* @see org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig @SpringJUnitWebConfig
@ -109,7 +107,6 @@ public @interface TestConstructor {
* @see #TEST_CONSTRUCTOR_AUTOWIRE_MODE_PROPERTY_NAME
* @see org.springframework.beans.factory.annotation.Autowired @Autowired
* @see jakarta.inject.Inject @jakarta.inject.Inject
* @see javax.inject.Inject @javax.inject.Inject
* @see AutowireMode#ALL
* @see AutowireMode#ANNOTATED
*/
@ -126,9 +123,8 @@ public @interface TestConstructor {
/**
* All test constructor parameters will be autowired as if the constructor
* itself were annotated with
* {@link org.springframework.beans.factory.annotation.Autowired @Autowired},
* {@link jakarta.inject.Inject @jakarta.inject.Inject}, or
* {@link javax.inject.Inject @javax.inject.Inject}.
* {@link org.springframework.beans.factory.annotation.Autowired @Autowired} or
* {@link jakarta.inject.Inject @jakarta.inject.Inject}.
* @see #ANNOTATED
*/
ALL,
@ -140,9 +136,8 @@ public @interface TestConstructor {
* {@link org.springframework.beans.factory.annotation.Qualifier @Qualifier},
* or {@link org.springframework.beans.factory.annotation.Value @Value},
* or if the constructor itself is annotated with
* {@link org.springframework.beans.factory.annotation.Autowired @Autowired},
* {@link jakarta.inject.Inject @jakarta.inject.Inject}, or
* {@link javax.inject.Inject @javax.inject.Inject}.
* {@link org.springframework.beans.factory.annotation.Autowired @Autowired} or
* {@link jakarta.inject.Inject @jakarta.inject.Inject}.
* @see #ALL
*/
ANNOTATED;

View File

@ -63,15 +63,6 @@ public abstract class TestConstructorUtils {
catch (ClassNotFoundException ex) {
// jakarta.inject API not available - simply skip.
}
try {
autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", classLoader));
logger.trace("'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// javax.inject API not available - simply skip.
}
}
@ -135,9 +126,8 @@ public abstract class TestConstructorUtils {
* conditions is {@code true}.
*
* <ol>
* <li>The constructor is annotated with {@link Autowired @Autowired},
* {@link jakarta.inject.Inject @jakarta.inject.Inject}, or
* {@link javax.inject.Inject @javax.inject.Inject}.</li>
* <li>The constructor is annotated with {@link Autowired @Autowired} or
* {@link jakarta.inject.Inject @jakarta.inject.Inject}.</li>
* <li>{@link TestConstructor @TestConstructor} is <em>present</em> or
* <em>meta-present</em> on the test class with
* {@link TestConstructor#autowireMode() autowireMode} set to

View File

@ -57,15 +57,6 @@ class SpringJUnitJupiterAutowiredConstructorInjectionTests {
}
}
@Nested
class JavaxInjectTests extends BaseClass {
@javax.inject.Inject
JavaxInjectTests(ApplicationContext context, Person dilbert, Dog dog, @Value("${enigma}") Integer enigma) {
super(context, dilbert, dog, enigma);
}
}
@SpringJUnitConfig(TestConfig.class)
@TestPropertySource(properties = "enigma = 42")

View File

@ -16,7 +16,6 @@
package org.springframework.test.context.junit4.orm;
import jakarta.persistence.PersistenceException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.exception.ConstraintViolationException;
@ -115,16 +114,8 @@ public class HibernateSessionFlushingTests extends AbstractTransactionalJUnit4Sp
@Test
public void updateSamWithNullDriversLicenseWithSessionFlush() {
updateSamWithNullDriversLicense();
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(() -> {
// Manual flush is required to avoid false positive in test
try {
sessionFactory.getCurrentSession().flush();
}
catch (PersistenceException ex) {
// Wrapped in Hibernate 5.2, with the constraint violation as cause
throw ex.getCause();
}
});
assertThatExceptionOfType(ConstraintViolationException.class).isThrownBy(sessionFactory.getCurrentSession()::flush);
}
private void updateSamWithNullDriversLicense() {

View File

@ -42,7 +42,7 @@ public class HibernatePersonRepository implements PersonRepository {
@Override
public Person save(Person person) {
this.sessionFactory.getCurrentSession().save(person);
this.sessionFactory.getCurrentSession().persist(person);
return person;
}

View File

@ -94,10 +94,10 @@ dependencies {
testImplementation("org.skyscreamer:jsonassert")
testImplementation("org.xmlunit:xmlunit-assertj")
testImplementation("org.xmlunit:xmlunit-matchers")
testRuntimeOnly("com.sun.mail:jakarta.mail")
testRuntimeOnly("com.sun.xml.bind:jaxb-core")
testRuntimeOnly("com.sun.xml.bind:jaxb-impl")
testRuntimeOnly("jakarta.json:jakarta.json-api")
testRuntimeOnly("org.eclipse.angus:angus-mail")
testRuntimeOnly("org.eclipse:yasson")
testRuntimeOnly("org.glassfish:jakarta.el")
testRuntimeOnly("org.hibernate:hibernate-validator")

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2020 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.
@ -127,7 +127,6 @@ public abstract class AbstractJsonHttpMessageConverter extends AbstractGenericHt
catch (Exception ex) {
throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
}
writer.flush();
}

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.
@ -105,10 +105,12 @@ public class GsonHttpMessageConverter extends AbstractJsonHttpMessageConverter {
else {
getGson().toJson(object, writer);
}
writer.flush();
}
@Override
protected boolean supportsRepeatableWrites(Object o) {
return true;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2017 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.
@ -16,9 +16,6 @@
package org.springframework.web.jsf.el;
import java.beans.FeatureDescriptor;
import java.util.Iterator;
import jakarta.el.ELContext;
import jakarta.el.ELException;
import jakarta.el.ELResolver;
@ -129,12 +126,6 @@ public class SpringBeanFacesELResolver extends ELResolver {
return false;
}
@Override
@Nullable
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext elContext, @Nullable Object base) {
return null;
}
@Override
public Class<?> getCommonPropertyType(ELContext elContext, @Nullable Object base) {
return Object.class;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 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.
@ -16,9 +16,6 @@
package org.springframework.web.jsf.el;
import java.beans.FeatureDescriptor;
import java.util.Iterator;
import jakarta.el.ELContext;
import jakarta.el.ELException;
import jakarta.el.ELResolver;
@ -153,12 +150,6 @@ public class WebApplicationContextFacesELResolver extends ELResolver {
return false;
}
@Override
@Nullable
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext elContext, Object base) {
return null;
}
@Override
public Class<?> getCommonPropertyType(ELContext elContext, Object base) {
return Object.class;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 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.
@ -26,6 +26,7 @@ import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
import jakarta.faces.context.ResponseStream;
import jakarta.faces.context.ResponseWriter;
import jakarta.faces.lifecycle.Lifecycle;
import jakarta.faces.render.RenderKit;
/**
@ -141,4 +142,9 @@ public class MockFacesContext extends FacesContext {
public void responseComplete() {
}
@Override
public Lifecycle getLifecycle() {
return null;
}
}