diff --git a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java index dcffc2c2ed..f553b215a5 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/configuration/ScopingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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. @@ -24,11 +24,8 @@ import java.util.HashMap; import java.util.Map; import org.junit.After; -import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; -import org.springframework.tests.sample.beans.ITestBean; -import org.springframework.tests.sample.beans.TestBean; import org.springframework.aop.scope.ScopedObject; import org.springframework.beans.factory.ObjectFactory; @@ -40,6 +37,10 @@ import org.springframework.context.annotation.ConfigurationClassPostProcessor; import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.ScopedProxyMode; import org.springframework.context.support.GenericApplicationContext; +import org.springframework.tests.sample.beans.ITestBean; +import org.springframework.tests.sample.beans.TestBean; + +import static org.junit.Assert.*; /** * Tests that scopes are properly supported by using a custom Scope implementations @@ -58,10 +59,11 @@ public class ScopingTests { private GenericApplicationContext ctx; + @Before public void setUp() throws Exception { customScope = new CustomScope(); - ctx = createContext(customScope, ScopedConfigurationClass.class); + ctx = createContext(ScopedConfigurationClass.class); } @After @@ -69,11 +71,9 @@ public class ScopingTests { if (ctx != null) { ctx.close(); } - ctx = null; - customScope = null; } - private GenericApplicationContext createContext(org.springframework.beans.factory.config.Scope customScope, Class configClass) { + private GenericApplicationContext createContext(Class configClass) { DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); if (customScope != null) { beanFactory.registerScope(SCOPE, customScope); @@ -85,6 +85,7 @@ public class ScopingTests { return ctx; } + @Test public void testScopeOnClasses() throws Exception { genericTestScope("scopedClass"); @@ -95,6 +96,40 @@ public class ScopingTests { genericTestScope("scopedInterface"); } + private void genericTestScope(String beanName) throws Exception { + String message = "scope is ignored"; + Object bean1 = ctx.getBean(beanName); + Object bean2 = ctx.getBean(beanName); + + assertSame(message, bean1, bean2); + + Object bean3 = ctx.getBean(beanName); + + assertSame(message, bean1, bean3); + + // make the scope create a new object + customScope.createNewScope = true; + + Object newBean1 = ctx.getBean(beanName); + assertNotSame(message, bean1, newBean1); + + Object sameBean1 = ctx.getBean(beanName); + + assertSame(message, newBean1, sameBean1); + + // make the scope create a new object + customScope.createNewScope = true; + + Object newBean2 = ctx.getBean(beanName); + assertNotSame(message, newBean1, newBean2); + + // make the scope create a new object .. again + customScope.createNewScope = true; + + Object newBean3 = ctx.getBean(beanName); + assertNotSame(message, newBean2, newBean3); + } + @Test public void testSameScopeOnDifferentBeans() throws Exception { Object beanAInScope = ctx.getBean("scopedClass"); @@ -154,10 +189,8 @@ public class ScopingTests { assertSame(spouse.getName(), spouseFromBF.getName()); } - @Test public void testScopedProxyConfigurationWithClasses() throws Exception { - TestBean singleton = (TestBean) ctx.getBean("singletonWithScopedClassDep"); ITestBean spouse = singleton.getSpouse(); assertTrue("scoped bean is not wrapped by the scoped-proxy", spouse instanceof ScopedObject); @@ -189,7 +222,6 @@ public class ScopingTests { assertSame(spouse.getName(), spouseFromBF.getName()); } - @Test public void testScopedConfigurationBeanDefinitionCount() throws Exception { // count the beans @@ -197,112 +229,41 @@ public class ScopingTests { assertEquals(11, ctx.getBeanDefinitionCount()); } -// /** -// * SJC-254 caught a regression in handling scoped proxies starting in 1.0 m4. -// * The ScopedProxyFactoryBean object was having its scope set to that of its delegate -// * whereas it should have remained singleton. -// */ -// @Test -// public void sjc254() { -// JavaConfigWebApplicationContext ctx = new JavaConfigWebApplicationContext(); -// ctx.setConfigLocations(new String[] { ScopeTestConfiguration.class.getName() }); -// ctx.refresh(); -// -// // should be fine -// ctx.getBean(Bar.class); -// -// boolean threw = false; -// try { -// ctx.getBean(Foo.class); -// } catch (BeanCreationException ex) { -// if(ex.getCause() instanceof IllegalStateException) { -// threw = true; -// } -// } -// assertTrue(threw); -// } - - @Configuration - static class ScopeTestConfiguration { - - @Bean - @Scope(value="session", proxyMode=ScopedProxyMode.INTERFACES) - public Foo foo() { - return new Foo(); - } - - @Bean - public Bar bar() { - return new Bar(foo()); - } - } static class Foo { + public Foo() { - //System.out.println("created foo: " + this.getClass().getName()); } public void doSomething() { - //System.out.println("interesting: " + this); } } + static class Bar { private final Foo foo; public Bar(Foo foo) { this.foo = foo; - //System.out.println("created bar: " + this); } public Foo getFoo() { return foo; } - } - private void genericTestScope(String beanName) throws Exception { - String message = "scope is ignored"; - Object bean1 = ctx.getBean(beanName); - Object bean2 = ctx.getBean(beanName); - - assertSame(message, bean1, bean2); - - Object bean3 = ctx.getBean(beanName); - - assertSame(message, bean1, bean3); - - // make the scope create a new object - customScope.createNewScope = true; - - Object newBean1 = ctx.getBean(beanName); - assertNotSame(message, bean1, newBean1); - - Object sameBean1 = ctx.getBean(beanName); - - assertSame(message, newBean1, sameBean1); - - // make the scope create a new object - customScope.createNewScope = true; - - Object newBean2 = ctx.getBean(beanName); - assertNotSame(message, newBean1, newBean2); - - // make the scope create a new object .. again - customScope.createNewScope = true; - - Object newBean3 = ctx.getBean(beanName); - assertNotSame(message, newBean2, newBean3); - } @Configuration public static class InvalidProxyOnPredefinedScopesConfiguration { @Bean @Scope(proxyMode=ScopedProxyMode.INTERFACES) - public Object invalidProxyOnPredefinedScopes() { return new Object(); } + public Object invalidProxyOnPredefinedScopes() { + return new Object(); + } } + @Configuration public static class ScopedConfigurationClass { diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SimpAnnotationMethodMessageHandler.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SimpAnnotationMethodMessageHandler.java index 5beb830252..1994c7b475 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SimpAnnotationMethodMessageHandler.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/annotation/support/SimpAnnotationMethodMessageHandler.java @@ -17,7 +17,13 @@ package org.springframework.messaging.simp.annotation.support; import java.lang.reflect.Method; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.ConfigurableApplicationContext; @@ -33,21 +39,25 @@ import org.springframework.messaging.converter.CompositeMessageConverter; import org.springframework.messaging.converter.MessageConverter; import org.springframework.messaging.converter.StringMessageConverter; import org.springframework.messaging.core.AbstractMessageSendingTemplate; +import org.springframework.messaging.handler.DestinationPatternsMessageCondition; import org.springframework.messaging.handler.HandlerMethod; import org.springframework.messaging.handler.annotation.MessageMapping; -import org.springframework.messaging.handler.annotation.support.*; +import org.springframework.messaging.handler.annotation.support.AnnotationExceptionHandlerMethodResolver; import org.springframework.messaging.handler.annotation.support.DestinationVariableMethodArgumentResolver; +import org.springframework.messaging.handler.annotation.support.HeaderMethodArgumentResolver; +import org.springframework.messaging.handler.annotation.support.HeadersMethodArgumentResolver; +import org.springframework.messaging.handler.annotation.support.MessageMethodArgumentResolver; +import org.springframework.messaging.handler.annotation.support.PayloadArgumentResolver; import org.springframework.messaging.handler.invocation.AbstractExceptionHandlerMethodResolver; import org.springframework.messaging.handler.invocation.AbstractMethodMessageHandler; -import org.springframework.messaging.handler.DestinationPatternsMessageCondition; import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver; import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler; import org.springframework.messaging.simp.SimpMessageHeaderAccessor; +import org.springframework.messaging.simp.SimpMessageMappingInfo; import org.springframework.messaging.simp.SimpMessageSendingOperations; +import org.springframework.messaging.simp.SimpMessageTypeMessageCondition; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.messaging.simp.annotation.SubscribeMapping; -import org.springframework.messaging.simp.SimpMessageMappingInfo; -import org.springframework.messaging.simp.SimpMessageTypeMessageCondition; import org.springframework.messaging.support.MessageBuilder; import org.springframework.stereotype.Controller; import org.springframework.util.AntPathMatcher; @@ -58,11 +68,10 @@ import org.springframework.validation.Errors; import org.springframework.validation.Validator; /** - * A handler for messages delegating to - * {@link org.springframework.messaging.simp.annotation.SubscribeMapping @SubscribeMapping} and - * {@link MessageMapping @MessageMapping} annotated methods. - *

- * Supports Ant-style path patterns with template variables. + * A handler for messages delegating to {@link MessageMapping @MessageMapping} + * and {@link SubscribeMapping @SubscribeMapping} annotated methods. + * + *

Supports Ant-style path patterns with template variables. * * @author Rossen Stoyanchev * @author Brian Clozel @@ -93,7 +102,6 @@ public class SimpAnnotationMethodMessageHandler extends AbstractMethodMessageHan /** * Create an instance of SimpAnnotationMethodMessageHandler with the given * message channels and broker messaging template. - * * @param clientInboundChannel the channel for receiving messages from clients (e.g. WebSocket clients) * @param clientOutboundChannel the channel for messages to clients (e.g. WebSocket clients) * @param brokerTemplate a messaging template to send application messages to the broker @@ -185,6 +193,7 @@ public class SimpAnnotationMethodMessageHandler extends AbstractMethodMessageHan this.validator = validator; } + @Override public boolean isAutoStartup() { return true; @@ -226,8 +235,8 @@ public class SimpAnnotationMethodMessageHandler extends AbstractMethodMessageHan } } - protected List initArgumentResolvers() { + protected List initArgumentResolvers() { ConfigurableBeanFactory beanFactory = (ClassUtils.isAssignableValue(ConfigurableApplicationContext.class, getApplicationContext())) ? ((ConfigurableApplicationContext) getApplicationContext()).getBeanFactory() : null; @@ -245,14 +254,13 @@ public class SimpAnnotationMethodMessageHandler extends AbstractMethodMessageHan resolvers.addAll(getCustomArgumentResolvers()); resolvers.add(new PayloadArgumentResolver(this.messageConverter, - this.validator != null ? this.validator : new NoopValidator())); + (this.validator != null ? this.validator : new NoopValidator()))); return resolvers; } @Override protected List initReturnValueHandlers() { - List handlers = new ArrayList(); // Annotation-based return value types @@ -276,7 +284,6 @@ public class SimpAnnotationMethodMessageHandler extends AbstractMethodMessageHan @Override protected SimpMessageMappingInfo getMappingForMethod(Method method, Class handlerType) { - MessageMapping typeAnnot = AnnotationUtils.findAnnotation(handlerType, MessageMapping.class); MessageMapping messageAnnot = AnnotationUtils.findAnnotation(method, MessageMapping.class); if (messageAnnot != null) { @@ -312,9 +319,9 @@ public class SimpAnnotationMethodMessageHandler extends AbstractMethodMessageHan @Override protected Set getDirectLookupDestinations(SimpMessageMappingInfo mapping) { Set result = new LinkedHashSet(); - for (String s : mapping.getDestinationConditions().getPatterns()) { - if (!this.pathMatcher.isPattern(s)) { - result.add(s); + for (String pattern : mapping.getDestinationConditions().getPatterns()) { + if (!this.pathMatcher.isPattern(pattern)) { + result.add(pattern); } } return result; @@ -362,14 +369,17 @@ public class SimpAnnotationMethodMessageHandler extends AbstractMethodMessageHan return new AnnotationExceptionHandlerMethodResolver(beanType); } + private static final class NoopValidator implements Validator { + @Override public boolean supports(Class clazz) { return false; } + @Override public void validate(Object target, Errors errors) { } - }; + } } diff --git a/spring-web/src/main/java/org/springframework/web/filter/ShallowEtagHeaderFilter.java b/spring-web/src/main/java/org/springframework/web/filter/ShallowEtagHeaderFilter.java index 6b5e688848..2414c1989e 100644 --- a/spring-web/src/main/java/org/springframework/web/filter/ShallowEtagHeaderFilter.java +++ b/spring-web/src/main/java/org/springframework/web/filter/ShallowEtagHeaderFilter.java @@ -35,12 +35,14 @@ import org.springframework.util.StreamUtils; import org.springframework.web.util.WebUtils; /** - * {@link javax.servlet.Filter} that generates an {@code ETag} value based on the content on the response. - * This ETag is compared to the {@code If-None-Match} header of the request. If these headers are equal, - * the response content is not sent, but rather a {@code 304 "Not Modified"} status instead. + * {@link javax.servlet.Filter} that generates an {@code ETag} value based on the + * content on the response. This ETag is compared to the {@code If-None-Match} + * header of the request. If these headers are equal, the response content is + * not sent, but rather a {@code 304 "Not Modified"} status instead. * - *

Since the ETag is based on the response content, the response (or {@link org.springframework.web.servlet.View}) - * is still rendered. As such, this filter only saves bandwidth, not server performance. + *

Since the ETag is based on the response content, the response + * (e.g. a {@link org.springframework.web.servlet.View}) is still rendered. + * As such, this filter only saves bandwidth, not server performance. * * @author Arjen Poutsma * @author Rossen Stoyanchev @@ -82,12 +84,11 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter { } private void updateResponse(HttpServletRequest request, HttpServletResponse response) throws IOException { - - ShallowEtagResponseWrapper responseWrapper = WebUtils.getNativeResponse(response, ShallowEtagResponseWrapper.class); + ShallowEtagResponseWrapper responseWrapper = + WebUtils.getNativeResponse(response, ShallowEtagResponseWrapper.class); Assert.notNull(responseWrapper, "ShallowEtagResponseWrapper not found"); response = (HttpServletResponse) responseWrapper.getResponse(); - byte[] body = responseWrapper.toByteArray(); int statusCode = responseWrapper.getStatusCode(); @@ -131,9 +132,8 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter { *

- * * @param request the HTTP request * @param response the HTTP response * @param responseStatusCode the HTTP response status code @@ -143,10 +143,14 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter { protected boolean isEligibleForEtag(HttpServletRequest request, HttpServletResponse response, int responseStatusCode, byte[] responseBody) { - return (responseStatusCode >= 200 && responseStatusCode < 300) - && HttpMethod.GET.name().equals(request.getMethod()) - && (response.getHeader(HEADER_CACHE_CONTROL) == null - || !response.getHeader(HEADER_CACHE_CONTROL).contains(DIRECTIVE_NO_STORE)); + if (responseStatusCode >= 200 && responseStatusCode < 300 && + HttpMethod.GET.name().equals(request.getMethod())) { + String cacheControl = response.getHeader(HEADER_CACHE_CONTROL); + if (cacheControl == null || !cacheControl.contains(DIRECTIVE_NO_STORE)) { + return true; + } + } + return false; } /** @@ -239,7 +243,7 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter { } private int getStatusCode() { - return statusCode; + return this.statusCode; } private byte[] toByteArray() { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles2/SpringWildcardServletTilesApplicationContext.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles2/SpringWildcardServletTilesApplicationContext.java index b9c6db99ad..f3240374a3 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles2/SpringWildcardServletTilesApplicationContext.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/tiles2/SpringWildcardServletTilesApplicationContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2014 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. @@ -29,7 +29,7 @@ import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.web.context.support.ServletContextResourcePatternResolver; /** - * Spring-specific subclass of the ServletTilesApplicationContext. + * Spring-specific subclass of the Tiles ServletTilesApplicationContext. * * @author Juergen Hoeller * @since 4.0.1 @@ -67,4 +67,5 @@ public class SpringWildcardServletTilesApplicationContext extends ServletTilesAp } return urlSet; } + }