advisors) {
// Don't add advisors to an empty list; may indicate that proxying is just not required
if (!advisors.isEmpty()) {
boolean foundAspectJAdvice = false;
for (Advisor advisor : advisors) {
- // Be careful not to get the Advice without a guard, as
- // this might eagerly instantiate a non-singleton AspectJ aspect
+ // Be careful not to get the Advice without a guard, as this might eagerly
+ // instantiate a non-singleton AspectJ aspect...
if (isAspectJAdvice(advisor)) {
foundAspectJAdvice = true;
+ break;
}
}
if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {
diff --git a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java
index 7aac42195d..edcb08480d 100644
--- a/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java
+++ b/spring-context/src/main/java/org/springframework/context/annotation/ConfigurationClassParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
diff --git a/spring-context/src/main/java/org/springframework/context/event/AbstractApplicationEventMulticaster.java b/spring-context/src/main/java/org/springframework/context/event/AbstractApplicationEventMulticaster.java
index 6b6dcdba40..a1811030af 100644
--- a/spring-context/src/main/java/org/springframework/context/event/AbstractApplicationEventMulticaster.java
+++ b/spring-context/src/main/java/org/springframework/context/event/AbstractApplicationEventMulticaster.java
@@ -269,7 +269,7 @@ public abstract class AbstractApplicationEventMulticaster
* type before trying to instantiate it.
* If this method returns {@code true} for a given listener as a first pass,
* the listener instance will get retrieved and fully evaluated through a
- * {@link #supportsEvent(ApplicationListener, ResolvableType, Class)} call afterwards.
+ * {@link #supportsEvent(ApplicationListener, ResolvableType, Class)} call afterwards.
* @param listenerType the listener's type as determined by the BeanFactory
* @param eventType the event type to check
* @return whether the given listener should be included in the candidates
diff --git a/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java b/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java
index 6cbe6e0cd3..e81ff3633c 100644
--- a/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java
+++ b/spring-context/src/main/java/org/springframework/context/event/ApplicationListenerMethodAdapter.java
@@ -188,9 +188,9 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
/**
* Resolve the method arguments to use for the specified {@link ApplicationEvent}.
- *
These arguments will be used to invoke the method handled by this instance. Can
- * return {@code null} to indicate that no suitable arguments could be resolved and
- * therefore the method should not be invoked at all for the specified event.
+ *
These arguments will be used to invoke the method handled by this instance.
+ * Can return {@code null} to indicate that no suitable arguments could be resolved
+ * and therefore the method should not be invoked at all for the specified event.
*/
@Nullable
protected Object[] resolveArguments(ApplicationEvent event) {
@@ -201,13 +201,15 @@ public class ApplicationListenerMethodAdapter implements GenericApplicationListe
if (this.method.getParameterCount() == 0) {
return new Object[0];
}
- if (!ApplicationEvent.class.isAssignableFrom(declaredEventType.toClass()) &&
+ Class> declaredEventClass = declaredEventType.toClass();
+ if (!ApplicationEvent.class.isAssignableFrom(declaredEventClass) &&
event instanceof PayloadApplicationEvent) {
- return new Object[] {((PayloadApplicationEvent) event).getPayload()};
- }
- else {
- return new Object[] {event};
+ Object payload = ((PayloadApplicationEvent) event).getPayload();
+ if (declaredEventClass.isInstance(payload)) {
+ return new Object[] {payload};
+ }
}
+ return new Object[] {event};
}
protected void handleResult(Object result) {
diff --git a/spring-context/src/main/java/org/springframework/context/support/SimpleThreadScope.java b/spring-context/src/main/java/org/springframework/context/support/SimpleThreadScope.java
index 1ece66fc88..eb1d364f22 100644
--- a/spring-context/src/main/java/org/springframework/context/support/SimpleThreadScope.java
+++ b/spring-context/src/main/java/org/springframework/context/support/SimpleThreadScope.java
@@ -36,14 +36,13 @@ import org.springframework.lang.Nullable;
* or through a {@link org.springframework.beans.factory.config.CustomScopeConfigurer} bean.
*
*
{@code SimpleThreadScope} does not clean up any objects associated with it.
- * As such, it is typically preferable to use
- * {@link org.springframework.web.context.request.RequestScope RequestScope}
- * in web environments.
+ * It is therefore typically preferable to use a request-bound scope implementation such
+ * as {@code org.springframework.web.context.request.RequestScope} in web environments,
+ * implementing the full lifecycle for scoped attributes (including reliable destruction).
*
- *
For an implementation of a thread-based {@code Scope} with support for
- * destruction callbacks, refer to the
- *
- * Spring by Example Custom Thread Scope Module.
+ *
For an implementation of a thread-based {@code Scope} with support for destruction
+ * callbacks, refer to
+ * Spring by Example.
*
*
Thanks to Eugene Kuleshov for submitting the original prototype for a thread scope!
*
diff --git a/spring-context/src/test/java/org/springframework/context/event/PayloadApplicationEventTests.java b/spring-context/src/test/java/org/springframework/context/event/PayloadApplicationEventTests.java
new file mode 100644
index 0000000000..c9f9c17996
--- /dev/null
+++ b/spring-context/src/test/java/org/springframework/context/event/PayloadApplicationEventTests.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2002-2019 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
+ *
+ * http://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.event;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.PayloadApplicationEvent;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.stereotype.Component;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Juergen Hoeller
+ */
+public class PayloadApplicationEventTests {
+
+ @Test
+ public void testEventClassWithInterface() {
+ ApplicationContext ac = new AnnotationConfigApplicationContext(Listener.class);
+ MyEventClass event = new MyEventClass<>(this, "xyz");
+ ac.publishEvent(event);
+ assertTrue(ac.getBean(Listener.class).events.contains(event));
+ }
+
+
+ public interface Auditable {
+ }
+
+
+ public static class MyEventClass extends PayloadApplicationEvent implements Auditable {
+
+ public MyEventClass(Object source, GT payload) {
+ super(source, payload);
+ }
+
+ public String toString() {
+ return "Payload: " + getPayload();
+ }
+ }
+
+
+ @Component
+ public static class Listener {
+
+ public final List events = new ArrayList<>();
+
+ @EventListener
+ public void onEvent(Auditable event) {
+ events.add(event);
+ }
+ }
+
+}
diff --git a/spring-core/src/main/java/org/springframework/util/ClassUtils.java b/spring-core/src/main/java/org/springframework/util/ClassUtils.java
index 87db4dbc21..86ca327ca1 100644
--- a/spring-core/src/main/java/org/springframework/util/ClassUtils.java
+++ b/spring-core/src/main/java/org/springframework/util/ClassUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -43,7 +43,7 @@ import java.util.StringJoiner;
import org.springframework.lang.Nullable;
/**
- * Miscellaneous class utility methods.
+ * Miscellaneous {@code java.lang.Class} utility methods.
* Mainly for internal use within the framework.
*
* @author Juergen Hoeller
diff --git a/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java b/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java
index 9971bfc361..01b1ce9e43 100644
--- a/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java
+++ b/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -74,7 +74,8 @@ public class MappingJackson2MessageConverter implements SmartMessageConverter, B
private MessageType targetType = MessageType.BYTES;
- private String encoding = DEFAULT_ENCODING;
+ @Nullable
+ private String encoding;
@Nullable
private String encodingPropertyName;
@@ -293,13 +294,21 @@ public class MappingJackson2MessageConverter implements SmartMessageConverter, B
throws JMSException, IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
- OutputStreamWriter writer = new OutputStreamWriter(bos, this.encoding);
- objectWriter.writeValue(writer, object);
+ if (this.encoding != null) {
+ OutputStreamWriter writer = new OutputStreamWriter(bos, this.encoding);
+ objectWriter.writeValue(writer, object);
+ }
+ else {
+ // Jackson usually defaults to UTF-8 but can also go straight to bytes, e.g. for Smile.
+ // We use a direct byte array argument for the latter case to work as well.
+ objectWriter.writeValue(bos, object);
+ }
BytesMessage message = session.createBytesMessage();
message.writeBytes(bos.toByteArray());
if (this.encodingPropertyName != null) {
- message.setStringProperty(this.encodingPropertyName, this.encoding);
+ message.setStringProperty(this.encodingPropertyName,
+ (this.encoding != null ? this.encoding : DEFAULT_ENCODING));
}
return message;
}
@@ -393,12 +402,18 @@ public class MappingJackson2MessageConverter implements SmartMessageConverter, B
}
byte[] bytes = new byte[(int) message.getBodyLength()];
message.readBytes(bytes);
- try {
- String body = new String(bytes, encoding);
- return this.objectMapper.readValue(body, targetJavaType);
+ if (encoding != null) {
+ try {
+ String body = new String(bytes, encoding);
+ return this.objectMapper.readValue(body, targetJavaType);
+ }
+ catch (UnsupportedEncodingException ex) {
+ throw new MessageConversionException("Cannot convert bytes to String", ex);
+ }
}
- catch (UnsupportedEncodingException ex) {
- throw new MessageConversionException("Cannot convert bytes to String", ex);
+ else {
+ // Jackson internally performs encoding detection, falling back to UTF-8.
+ return this.objectMapper.readValue(bytes, targetJavaType);
}
}
diff --git a/spring-jms/src/test/java/org/springframework/jms/support/converter/MappingJackson2MessageConverterTests.java b/spring-jms/src/test/java/org/springframework/jms/support/converter/MappingJackson2MessageConverterTests.java
index e98fefdedd..9866935f90 100644
--- a/spring-jms/src/test/java/org/springframework/jms/support/converter/MappingJackson2MessageConverterTests.java
+++ b/spring-jms/src/test/java/org/springframework/jms/support/converter/MappingJackson2MessageConverterTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -56,7 +56,7 @@ public class MappingJackson2MessageConverterTests {
@Before
- public void setUp() throws Exception {
+ public void setup() {
sessionMock = mock(Session.class);
converter = new MappingJackson2MessageConverter();
converter.setEncodingPropertyName("__encoding__");
@@ -263,8 +263,11 @@ public class MappingJackson2MessageConverterTests {
return new MyAnotherBean();
}
+
public static class MyBean {
+ private String foo;
+
public MyBean() {
}
@@ -272,8 +275,6 @@ public class MappingJackson2MessageConverterTests {
this.foo = foo;
}
- private String foo;
-
public String getFoo() {
return foo;
}
@@ -290,13 +291,10 @@ public class MappingJackson2MessageConverterTests {
if (o == null || getClass() != o.getClass()) {
return false;
}
-
MyBean bean = (MyBean) o;
-
if (foo != null ? !foo.equals(bean.foo) : bean.foo != null) {
return false;
}
-
return true;
}
@@ -306,9 +304,12 @@ public class MappingJackson2MessageConverterTests {
}
}
+
private interface Summary {};
+
private interface Full extends Summary {};
+
private static class MyAnotherBean {
@JsonView(Summary.class)
diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompSession.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompSession.java
index 8a01b90f6c..f0906515e6 100644
--- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompSession.java
+++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompSession.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -19,8 +19,8 @@ package org.springframework.messaging.simp.stomp;
import org.springframework.lang.Nullable;
/**
- * Represents a STOMP session with operations to send messages, create
- * subscriptions and receive messages on those subscriptions.
+ * Represents a STOMP session with operations to send messages,
+ * create subscriptions and receive messages on those subscriptions.
*
* @author Rossen Stoyanchev
* @since 4.2
diff --git a/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java b/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java
index 5d59f670cf..594b4ef989 100644
--- a/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java
+++ b/spring-web/src/main/java/org/springframework/web/server/adapter/HttpWebHandlerAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -197,8 +197,7 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
/**
* Configure the {@code ApplicationContext} associated with the web application,
* if it was initialized with one via
- * {@link org.springframework.web.server.adapter.WebHttpHandlerBuilder#applicationContext
- * WebHttpHandlerBuilder#applicationContext}.
+ * {@link org.springframework.web.server.adapter.WebHttpHandlerBuilder#applicationContext(ApplicationContext)}.
* @param applicationContext the context
* @since 5.0.3
*/
@@ -232,11 +231,9 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
@Override
public Mono handle(ServerHttpRequest request, ServerHttpResponse response) {
-
if (this.forwardedHeaderTransformer != null) {
request = this.forwardedHeaderTransformer.apply(request);
}
-
ServerWebExchange exchange = createExchange(request, response);
LogFormatUtils.traceDebug(logger, traceOn ->
@@ -274,7 +271,6 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
}
private Mono handleUnresolvedError(ServerWebExchange exchange, Throwable ex) {
-
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
String logPrefix = exchange.getLogPrefix();
@@ -294,7 +290,7 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
return Mono.empty();
}
else {
- // After the response is committed, propagate errors to the server..
+ // After the response is committed, propagate errors to the server...
logger.error(logPrefix + "Error [" + ex + "] for " + formatRequest(request) +
", but ServerHttpResponse already committed (" + response.getStatusCode() + ")");
return Mono.error(ex);
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java
index a7dde23903..fea91536f0 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/config/MvcNamespaceUtils.java
@@ -82,8 +82,8 @@ public abstract class MvcNamespaceUtils {
}
parserContext.getRegistry().registerAlias(urlPathHelperRef.getBeanName(), URL_PATH_HELPER_BEAN_NAME);
}
- else if (!parserContext.getRegistry().isAlias(URL_PATH_HELPER_BEAN_NAME)
- && !parserContext.getRegistry().containsBeanDefinition(URL_PATH_HELPER_BEAN_NAME)) {
+ else if (!parserContext.getRegistry().isAlias(URL_PATH_HELPER_BEAN_NAME) &&
+ !parserContext.getRegistry().containsBeanDefinition(URL_PATH_HELPER_BEAN_NAME)) {
RootBeanDefinition urlPathHelperDef = new RootBeanDefinition(UrlPathHelper.class);
urlPathHelperDef.setSource(source);
urlPathHelperDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
@@ -107,8 +107,8 @@ public abstract class MvcNamespaceUtils {
}
parserContext.getRegistry().registerAlias(pathMatcherRef.getBeanName(), PATH_MATCHER_BEAN_NAME);
}
- else if (!parserContext.getRegistry().isAlias(PATH_MATCHER_BEAN_NAME)
- && !parserContext.getRegistry().containsBeanDefinition(PATH_MATCHER_BEAN_NAME)) {
+ else if (!parserContext.getRegistry().isAlias(PATH_MATCHER_BEAN_NAME) &&
+ !parserContext.getRegistry().containsBeanDefinition(PATH_MATCHER_BEAN_NAME)) {
RootBeanDefinition pathMatcherDef = new RootBeanDefinition(AntPathMatcher.class);
pathMatcherDef.setSource(source);
pathMatcherDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/HandlerExceptionResolverComposite.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/HandlerExceptionResolverComposite.java
index 92929d46ac..b08bd6f295 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/HandlerExceptionResolverComposite.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/HandlerExceptionResolverComposite.java
@@ -67,13 +67,12 @@ public class HandlerExceptionResolverComposite implements HandlerExceptionResolv
/**
* Resolve the exception by iterating over the list of configured exception resolvers.
- * The first one to return a {@link ModelAndView} wins. Otherwise {@code null}
- * is returned.
+ *
The first one to return a {@link ModelAndView} wins. Otherwise {@code null} is returned.
*/
@Override
@Nullable
- public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
- @Nullable Object handler, Exception ex) {
+ public ModelAndView resolveException(
+ HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex) {
if (this.resolvers != null) {
for (HandlerExceptionResolver handlerExceptionResolver : this.resolvers) {
diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ViewNameMethodReturnValueHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ViewNameMethodReturnValueHandler.java
index 41d3d02be2..d0f7780c5d 100644
--- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ViewNameMethodReturnValueHandler.java
+++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ViewNameMethodReturnValueHandler.java
@@ -33,10 +33,10 @@ import org.springframework.web.servlet.RequestToViewNameTranslator;
* as the actual return value is left as-is allowing the configured
* {@link RequestToViewNameTranslator} to select a view name by convention.
*
- *
A String return value can be interpreted in more than one ways depending
- * on the presence of annotations like {@code @ModelAttribute} or
- * {@code @ResponseBody}. Therefore this handler should be configured after
- * the handlers that support these annotations.
+ *
A String return value can be interpreted in more than one ways depending on
+ * the presence of annotations like {@code @ModelAttribute} or {@code @ResponseBody}.
+ * Therefore this handler should be configured after the handlers that support these
+ * annotations.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
@@ -49,12 +49,10 @@ public class ViewNameMethodReturnValueHandler implements HandlerMethodReturnValu
/**
- * Configure one more simple patterns (as described in
- * {@link PatternMatchUtils#simpleMatch}) to use in order to recognize
- * custom redirect prefixes in addition to "redirect:".
- *
Note that simply configuring this property will not make a custom
- * redirect prefix work. There must be a custom View that recognizes the
- * prefix as well.
+ * Configure one more simple patterns (as described in {@link PatternMatchUtils#simpleMatch})
+ * to use in order to recognize custom redirect prefixes in addition to "redirect:".
+ *
Note that simply configuring this property will not make a custom redirect prefix work.
+ * There must be a custom View that recognizes the prefix as well.
* @since 4.1
*/
public void setRedirectPatterns(@Nullable String... redirectPatterns) {