Skip to content

Commit 99e7543

Browse files
committed
Merge branch '7.0.x'
2 parents 82a9d66 + f0f447a commit 99e7543

7 files changed

Lines changed: 60 additions & 49 deletions

File tree

framework-platform/framework-platform.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ javaPlatform {
99
dependencies {
1010
api(platform("com.fasterxml.jackson:jackson-bom:2.20.2"))
1111
api(platform("io.micrometer:micrometer-bom:1.16.4"))
12-
api(platform("io.netty:netty-bom:4.2.10.Final"))
12+
api(platform("io.netty:netty-bom:4.2.12.Final"))
1313
api(platform("io.projectreactor:reactor-bom:2025.0.4"))
1414
api(platform("io.rsocket:rsocket-bom:1.1.5"))
1515
api(platform("org.apache.groovy:groovy-bom:5.0.4"))

spring-context/src/main/java/org/springframework/cache/annotation/Cacheable.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,18 @@
193193
* This is effectively a hint and the chosen cache provider might not actually
194194
* support it in a synchronized fashion. Check your provider documentation for
195195
* more details on the actual semantics.
196+
* <p>Note that `sync=true` leads to a combined callback operation against the
197+
* cache provider. If this combined operation fails on initial cache access,
198+
* there is no separate put operation to attempt anymore. Whereas for a default
199+
* `sync=false` setup, there are independent get and put steps: If the get step
200+
* fails but its error is suppressed in the {@code CacheErrorHandler} setup,
201+
* there will still be a put attempt after calling the underlying method.
196202
* @since 4.3
197203
* @see org.springframework.cache.Cache#get(Object, Callable)
204+
* @see org.springframework.cache.Cache#get(Object)
205+
* @see org.springframework.cache.Cache#put(Object, Object)
206+
* @see org.springframework.cache.interceptor.CacheErrorHandler#handleCacheGetError
207+
* @see org.springframework.cache.interceptor.CacheErrorHandler#handleCachePutError
198208
*/
199209
boolean sync() default false;
200210

spring-context/src/main/java/org/springframework/cache/interceptor/CacheErrorHandler.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.cache.interceptor;
1818

19+
import java.util.concurrent.Callable;
20+
1921
import org.jspecify.annotations.Nullable;
2022

2123
import org.springframework.cache.Cache;
@@ -39,10 +41,17 @@ public interface CacheErrorHandler {
3941
* Handle the given runtime exception thrown by the cache provider when
4042
* retrieving an item with the specified {@code key}, possibly
4143
* rethrowing it as a fatal exception.
44+
* <p>Note that for a default {@code @Cacheable} setup, this will be called
45+
* after an initial cache access failure, whereas the subsequent put step may
46+
* independently fail and be handled in {@link #handleCachePutError} still.
47+
* However, for {@code @Cacheable(sync=true)}, there is only a combined get step
48+
* with {@code handleCacheGetError} being called in case of failure; there won't
49+
* be a separate put attempt after initial cache access failure anymore.
4250
* @param exception the exception thrown by the cache provider
4351
* @param cache the cache
4452
* @param key the key used to get the item
4553
* @see Cache#get(Object)
54+
* @see Cache#get(Object, Callable)
4655
*/
4756
void handleCacheGetError(RuntimeException exception, Cache cache, Object key);
4857

spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,10 @@ public ApplicationListenerMethodAdapter(String beanName, Class<?> targetClass, M
126126
}
127127

128128
private static List<ResolvableType> resolveDeclaredEventTypes(Method method, @Nullable EventListener ann) {
129-
int count = (KotlinDetector.isSuspendingFunction(method) ? method.getParameterCount() - 1 : method.getParameterCount());
129+
int count = (KotlinDetector.isSuspendingFunction(method) ? method.getParameterCount() - 1 :
130+
method.getParameterCount());
130131
if (count > 1) {
131-
throw new IllegalStateException(
132-
"Maximum one parameter is allowed for event listener method: " + method);
132+
throw new IllegalStateException("Maximum one parameter is allowed for event listener method: " + method);
133133
}
134134

135135
if (ann != null) {
@@ -156,6 +156,35 @@ private static int resolveOrder(Method method) {
156156
}
157157

158158

159+
/**
160+
* Return the target listener method.
161+
* @since 7.0.7 in public form (with protected visibility since 5.3)
162+
*/
163+
public final Method getTargetMethod() {
164+
return this.targetMethod;
165+
}
166+
167+
/**
168+
* Return the condition to use.
169+
* <p>Matches the {@code condition} attribute of the {@link EventListener}
170+
* annotation or any matching attribute on a composed annotation that
171+
* is meta-annotated with {@code @EventListener}.
172+
*/
173+
protected final @Nullable String getCondition() {
174+
return this.condition;
175+
}
176+
177+
/**
178+
* Return whether default execution is applicable for the target listener.
179+
* @since 6.2
180+
* @see #onApplicationEvent
181+
* @see EventListener#defaultExecution()
182+
*/
183+
protected final boolean isDefaultExecution() {
184+
return this.defaultExecution;
185+
}
186+
187+
159188
/**
160189
* Initialize this instance.
161190
*/
@@ -167,7 +196,7 @@ void init(ApplicationContext applicationContext, @Nullable EventExpressionEvalua
167196

168197
@Override
169198
public void onApplicationEvent(ApplicationEvent event) {
170-
if (isDefaultExecution()) {
199+
if (this.defaultExecution) {
171200
processEvent(event);
172201
}
173202
}
@@ -222,22 +251,11 @@ public String getListenerId() {
222251
* @see #getListenerId()
223252
*/
224253
protected String getDefaultListenerId() {
225-
Method method = getTargetMethod();
226254
StringJoiner sj = new StringJoiner(",", "(", ")");
227-
for (Class<?> paramType : method.getParameterTypes()) {
255+
for (Class<?> paramType : this.targetMethod.getParameterTypes()) {
228256
sj.add(paramType.getName());
229257
}
230-
return ClassUtils.getQualifiedMethodName(method) + sj;
231-
}
232-
233-
/**
234-
* Return whether default execution is applicable for the target listener.
235-
* @since 6.2
236-
* @see #onApplicationEvent
237-
* @see EventListener#defaultExecution()
238-
*/
239-
protected boolean isDefaultExecution() {
240-
return this.defaultExecution;
258+
return ClassUtils.getQualifiedMethodName(this.targetMethod) + sj;
241259
}
242260

243261

@@ -274,11 +292,10 @@ private boolean shouldHandle(ApplicationEvent event, @Nullable Object @Nullable
274292
if (args == null) {
275293
return false;
276294
}
277-
String condition = getCondition();
278-
if (StringUtils.hasText(condition)) {
295+
if (StringUtils.hasText(this.condition)) {
279296
Assert.notNull(this.evaluator, "EventExpressionEvaluator must not be null");
280297
return this.evaluator.condition(
281-
condition, event, this.targetMethod, this.methodKey, args);
298+
this.condition, event, this.targetMethod, this.methodKey, args);
282299
}
283300
return true;
284301
}
@@ -402,32 +419,14 @@ protected Object getTargetBean() {
402419
return this.applicationContext.getBean(this.beanName);
403420
}
404421

405-
/**
406-
* Return the target listener method.
407-
* @since 5.3
408-
*/
409-
protected Method getTargetMethod() {
410-
return this.targetMethod;
411-
}
412-
413-
/**
414-
* Return the condition to use.
415-
* <p>Matches the {@code condition} attribute of the {@link EventListener}
416-
* annotation or any matching attribute on a composed annotation that
417-
* is meta-annotated with {@code @EventListener}.
418-
*/
419-
protected @Nullable String getCondition() {
420-
return this.condition;
421-
}
422-
423422
/**
424423
* Add additional details such as the bean type and method signature to
425424
* the given error message.
426425
* @param message error message to append the HandlerMethod details to
427426
*/
428427
protected String getDetailedErrorMessage(Object bean, @Nullable String message) {
429428
StringBuilder sb = (StringUtils.hasLength(message) ? new StringBuilder(message).append('\n') : new StringBuilder());
430-
sb.append("HandlerMethod details: \n");
429+
sb.append("ApplicationListenerMethodAdapter details: \n");
431430
sb.append("Bean [").append(bean.getClass().getName()).append("]\n");
432431
sb.append("Method [").append(this.method.toGenericString()).append("]\n");
433432
return sb.toString();

spring-core/src/main/java/org/springframework/core/task/SimpleAsyncTaskExecutor.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,7 @@ public void execute(Runnable task, long startTimeout) {
324324
catch (Throwable ex) {
325325
// Release concurrency permit if thread creation fails
326326
this.concurrencyThrottle.afterAccess();
327-
throw new TaskRejectedException(
328-
"Failed to start execution thread for task: " + task, ex);
327+
throw new TaskRejectedException("Failed to start execution thread for task: " + task, ex);
329328
}
330329
}
331330
else if (this.activeThreads != null) {

spring-core/src/main/java/org/springframework/core/task/support/TaskExecutorAdapter.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
* @see java.util.concurrent.ExecutorService
4343
* @see java.util.concurrent.Executors
4444
*/
45-
@SuppressWarnings("deprecation")
4645
public class TaskExecutorAdapter implements AsyncTaskExecutor {
4746

4847
private final Executor concurrentExecutor;

spring-webmvc/src/main/java/org/springframework/web/servlet/function/SseServerResponse.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,6 @@ private static final class DefaultSseBuilder implements SseBuilder {
105105

106106
private static final byte[] NL_NL = new byte[]{'\n', '\n'};
107107

108-
109108
private final ServerHttpResponse outputMessage;
110109

111110
private final DeferredResult<?> deferredResult;
@@ -118,7 +117,6 @@ private static final class DefaultSseBuilder implements SseBuilder {
118117

119118
private boolean sendFailed;
120119

121-
122120
public DefaultSseBuilder(HttpServletResponse response, Context context, DeferredResult<?> deferredResult,
123121
HttpHeaders httpHeaders) {
124122
this.outputMessage = new ServletServerHttpResponse(response);
@@ -184,7 +182,6 @@ private SseBuilder field(String name, String value) {
184182
@Override
185183
public void data(Object object) throws IOException {
186184
Assert.notNull(object, "Object must not be null");
187-
188185
if (object instanceof String text) {
189186
writeString(text);
190187
}
@@ -206,7 +203,6 @@ private void writeObject(Object data) throws IOException {
206203
this.builder.append("data:");
207204
try {
208205
this.outputMessage.getBody().write(builderBytes());
209-
210206
Class<?> dataClass = data.getClass();
211207
for (HttpMessageConverter<?> converter : this.messageConverters) {
212208
if (converter.canWrite(dataClass, MediaType.APPLICATION_JSON)) {
@@ -291,8 +287,7 @@ public MutableHeadersServerHttpResponse(ServerHttpResponse delegate, HttpHeaders
291287
public HttpHeaders getHeaders() {
292288
return this.mutableHeaders;
293289
}
294-
295290
}
296-
297291
}
292+
298293
}

0 commit comments

Comments
 (0)