diff --git a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java index 254377e2f3..134bc2f3e0 100644 --- a/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java +++ b/spring-aop/src/main/java/org/springframework/aop/interceptor/AsyncExecutionAspectSupport.java @@ -36,7 +36,6 @@ import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.core.task.AsyncTaskExecutor; import org.springframework.core.task.support.TaskExecutorAdapter; import org.springframework.lang.UsesJava8; -import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; @@ -137,8 +136,10 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware { Executor executorToUse = this.defaultExecutor; String qualifier = getExecutorQualifier(method); if (StringUtils.hasLength(qualifier)) { - Assert.notNull(this.beanFactory, "BeanFactory must be set on " + getClass().getSimpleName() + - " to access qualified executor '" + qualifier + "'"); + if (this.beanFactory == null) { + throw new IllegalStateException("BeanFactory must be set on " + getClass().getSimpleName() + + " to access qualified executor '" + qualifier + "'"); + } executorToUse = BeanFactoryAnnotationUtils.qualifiedBeanOfType( this.beanFactory, Executor.class, qualifier); } diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java index a3fc160fe3..3b505b5fc9 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractAutowireCapableBeanFactory.java @@ -685,7 +685,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac if (Modifier.isStatic(factoryMethod.getModifiers()) == isStatic && factoryMethod.getName().equals(mbd.getFactoryMethodName()) && factoryMethod.getParameterTypes().length >= minNrOfArgs) { - // No declared type variables to inspect, so just process the standard return type. + // Declared type variables to inspect? if (factoryMethod.getTypeParameters().length > 0) { try { // Fully resolve parameter names and argument values. diff --git a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java index b3881e0793..3b996ddb3b 100644 --- a/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java +++ b/spring-context/src/test/java/org/springframework/scheduling/annotation/EnableAsyncTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -67,17 +67,6 @@ public class EnableAsyncTests { asyncBean.work(); } - - @Configuration - @EnableAsync - static class AsyncConfig { - @Bean - public AsyncBean asyncBean() { - return new AsyncBean(); - } - } - - @Test public void withAsyncBeanWithExecutorQualifiedByName() throws ExecutionException, InterruptedException { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); @@ -95,8 +84,80 @@ public class EnableAsyncTests { assertThat(workerThread3.get().getName(), startsWith("otherExecutor-")); } + @Test + public void asyncProcessorIsOrderedLowestPrecedenceByDefault() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(AsyncConfig.class); + ctx.refresh(); + + AsyncAnnotationBeanPostProcessor bpp = ctx.getBean(AsyncAnnotationBeanPostProcessor.class); + assertThat(bpp.getOrder(), is(Ordered.LOWEST_PRECEDENCE)); + } + + @Test + public void orderAttributeIsPropagated() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(OrderedAsyncConfig.class); + ctx.refresh(); + + AsyncAnnotationBeanPostProcessor bpp = ctx.getBean(AsyncAnnotationBeanPostProcessor.class); + assertThat(bpp.getOrder(), is(Ordered.HIGHEST_PRECEDENCE)); + } + + @Test + public void customAsyncAnnotationIsPropagated() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(CustomAsyncAnnotationConfig.class); + ctx.refresh(); + + Object bean = ctx.getBean(CustomAsyncBean.class); + assertTrue(AopUtils.isAopProxy(bean)); + boolean isAsyncAdvised = false; + for (Advisor advisor : ((Advised)bean).getAdvisors()) { + if (advisor instanceof AsyncAnnotationAdvisor) { + isAsyncAdvised = true; + break; + } + } + assertTrue("bean was not async advised as expected", isAsyncAdvised); + } + + /** + * Fails with classpath errors on trying to classload AnnotationAsyncExecutionAspect + */ + @Test(expected = BeanDefinitionStoreException.class) + public void aspectModeAspectJAttemptsToRegisterAsyncAspect() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(AspectJAsyncAnnotationConfig.class); + ctx.refresh(); + } + + @Test + public void customExecutorIsPropagated() throws InterruptedException { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(CustomExecutorAsyncConfig.class); + ctx.refresh(); + + AsyncBean asyncBean = ctx.getBean(AsyncBean.class); + asyncBean.work(); + Thread.sleep(500); + assertThat(asyncBean.getThreadOfExecution().getName(), startsWith("Custom-")); + + TestableAsyncUncaughtExceptionHandler exceptionHandler = (TestableAsyncUncaughtExceptionHandler) + ctx.getBean("exceptionHandler"); + assertFalse("handler should not have been called yet", exceptionHandler.isCalled()); + + asyncBean.fail(); + Thread.sleep(500); + Method m = ReflectionUtils.findMethod(AsyncBean.class, "fail"); + exceptionHandler.assertCalledWith(m, UnsupportedOperationException.class); + + ctx.close(); + } + static class AsyncBeanWithExecutorQualifiedByName { + @Async public Future work0() { return new AsyncResult(Thread.currentThread()); @@ -120,6 +181,7 @@ public class EnableAsyncTests { static class AsyncBean { + private Thread threadOfExecution; @Async @@ -138,60 +200,10 @@ public class EnableAsyncTests { } - @Test - public void asyncProcessorIsOrderedLowestPrecedenceByDefault() { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.register(AsyncConfig.class); - ctx.refresh(); - - AsyncAnnotationBeanPostProcessor bpp = ctx.getBean(AsyncAnnotationBeanPostProcessor.class); - assertThat(bpp.getOrder(), is(Ordered.LOWEST_PRECEDENCE)); - } - - - @Test - public void orderAttributeIsPropagated() { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.register(OrderedAsyncConfig.class); - ctx.refresh(); - - AsyncAnnotationBeanPostProcessor bpp = ctx.getBean(AsyncAnnotationBeanPostProcessor.class); - assertThat(bpp.getOrder(), is(Ordered.HIGHEST_PRECEDENCE)); - } - - - @Configuration - @EnableAsync(order=Ordered.HIGHEST_PRECEDENCE) - static class OrderedAsyncConfig { - @Bean - public AsyncBean asyncBean() { - return new AsyncBean(); - } - } - - - @Test - public void customAsyncAnnotationIsPropagated() { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.register(CustomAsyncAnnotationConfig.class); - ctx.refresh(); - - Object bean = ctx.getBean(CustomAsyncBean.class); - assertTrue(AopUtils.isAopProxy(bean)); - boolean isAsyncAdvised = false; - for (Advisor advisor : ((Advised)bean).getAdvisors()) { - if (advisor instanceof AsyncAnnotationAdvisor) { - isAsyncAdvised = true; - break; - } - } - assertTrue("bean was not async advised as expected", isAsyncAdvised); - } - - @Configuration - @EnableAsync(annotation=CustomAsync.class) + @EnableAsync(annotation = CustomAsync.class) static class CustomAsyncAnnotationConfig { + @Bean public CustomAsyncBean asyncBean() { return new CustomAsyncBean(); @@ -206,25 +218,26 @@ public class EnableAsyncTests { static class CustomAsyncBean { + @CustomAsync public void work() { } } - /** - * Fails with classpath errors on trying to classload AnnotationAsyncExecutionAspect - */ - @Test(expected=BeanDefinitionStoreException.class) - public void aspectModeAspectJAttemptsToRegisterAsyncAspect() { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.register(AspectJAsyncAnnotationConfig.class); - ctx.refresh(); + @Configuration + @EnableAsync(order = Ordered.HIGHEST_PRECEDENCE) + static class OrderedAsyncConfig { + + @Bean + public AsyncBean asyncBean() { + return new AsyncBean(); + } } @Configuration - @EnableAsync(mode=AdviceMode.ASPECTJ) + @EnableAsync(mode = AdviceMode.ASPECTJ) static class AspectJAsyncAnnotationConfig { @Bean public AsyncBean asyncBean() { @@ -233,33 +246,21 @@ public class EnableAsyncTests { } - @Test - public void customExecutorIsPropagated() throws InterruptedException { - AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); - ctx.register(CustomExecutorAsyncConfig.class); - ctx.refresh(); - - AsyncBean asyncBean = ctx.getBean(AsyncBean.class); - asyncBean.work(); - Thread.sleep(500); - assertThat(asyncBean.getThreadOfExecution().getName(), startsWith("Custom-")); - - TestableAsyncUncaughtExceptionHandler exceptionHandler = (TestableAsyncUncaughtExceptionHandler) - ctx.getBean("exceptionHandler"); - assertFalse("handler should not have been called yet", exceptionHandler.isCalled()); - - asyncBean.fail(); - Thread.sleep(500); - Method m = ReflectionUtils.findMethod(AsyncBean.class, "fail"); - exceptionHandler.assertCalledWith(m, UnsupportedOperationException.class); + @Configuration + @EnableAsync + static class AsyncConfig { - ctx.close(); + @Bean + public AsyncBean asyncBean() { + return new AsyncBean(); + } } @Configuration @EnableAsync static class CustomExecutorAsyncConfig implements AsyncConfigurer { + @Bean public AsyncBean asyncBean() { return new AsyncBean(); @@ -288,6 +289,7 @@ public class EnableAsyncTests { @Configuration @EnableAsync static class AsyncWithExecutorQualifiedByNameConfig { + @Bean public AsyncBeanWithExecutorQualifiedByName asyncBean() { return new AsyncBeanWithExecutorQualifiedByName(); @@ -295,15 +297,14 @@ public class EnableAsyncTests { @Bean public Executor e1() { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - return executor; + return new ThreadPoolTaskExecutor(); } @Bean @Qualifier("e2") public Executor otherExecutor() { - ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - return executor; + return new ThreadPoolTaskExecutor(); } } + } diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/config/InitializeDatabaseIntegrationTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/config/InitializeDatabaseIntegrationTests.java index 286a897f2e..723707add1 100644 --- a/spring-jdbc/src/test/java/org/springframework/jdbc/config/InitializeDatabaseIntegrationTests.java +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/config/InitializeDatabaseIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -37,8 +37,10 @@ import static org.junit.Assert.*; public class InitializeDatabaseIntegrationTests { private String enabled; + private ClassPathXmlApplicationContext context; + @Before public void init() { enabled = System.setProperty("ENABLED", "true"); @@ -48,7 +50,8 @@ public class InitializeDatabaseIntegrationTests { public void after() { if (enabled != null) { System.setProperty("ENABLED", enabled); - } else { + } + else { System.clearProperty("ENABLED"); } if (context != null) { @@ -56,6 +59,7 @@ public class InitializeDatabaseIntegrationTests { } } + @Test public void testCreateEmbeddedDatabase() throws Exception { context = new ClassPathXmlApplicationContext("org/springframework/jdbc/config/jdbc-initialize-config.xml"); @@ -107,13 +111,15 @@ public class InitializeDatabaseIntegrationTests { } private void assertCorrectSetup(DataSource dataSource) { - JdbcTemplate t = new JdbcTemplate(dataSource); - assertEquals(1, t.queryForObject("select count(*) from T_TEST", Integer.class).intValue()); + JdbcTemplate jt = new JdbcTemplate(dataSource); + assertEquals(1, jt.queryForObject("select count(*) from T_TEST", Integer.class).intValue()); } + public static class CacheData implements InitializingBean { private JdbcTemplate jdbcTemplate; + private List> cache; public void setDataSource(DataSource dataSource) { @@ -128,7 +134,6 @@ public class InitializeDatabaseIntegrationTests { public void afterPropertiesSet() throws Exception { cache = jdbcTemplate.queryForList("SELECT * FROM T_TEST"); } - } } diff --git a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java index 47f7b681c1..d298341675 100644 --- a/spring-web/src/main/java/org/springframework/http/HttpHeaders.java +++ b/spring-web/src/main/java/org/springframework/http/HttpHeaders.java @@ -954,7 +954,7 @@ public class HttpHeaders implements MultiValueMap, Serializable try { return simpleDateFormat.parse(headerValue).getTime(); } - catch (ParseException e) { + catch (ParseException ex) { // ignore } } @@ -980,8 +980,8 @@ public class HttpHeaders implements MultiValueMap, Serializable */ @Override public String getFirst(String headerName) { - List headerValues = headers.get(headerName); - return headerValues != null ? headerValues.get(0) : null; + List headerValues = this.headers.get(headerName); + return (headerValues != null ? headerValues.get(0) : null); } /** @@ -994,7 +994,7 @@ public class HttpHeaders implements MultiValueMap, Serializable */ @Override public void add(String headerName, String headerValue) { - List headerValues = headers.get(headerName); + List headerValues = this.headers.get(headerName); if (headerValues == null) { headerValues = new LinkedList(); this.headers.put(headerName, headerValues); @@ -1014,7 +1014,7 @@ public class HttpHeaders implements MultiValueMap, Serializable public void set(String headerName, String headerValue) { List headerValues = new LinkedList(); headerValues.add(headerValue); - headers.put(headerName, headerValues); + this.headers.put(headerName, headerValues); } @Override @@ -1027,7 +1027,7 @@ public class HttpHeaders implements MultiValueMap, Serializable @Override public Map toSingleValueMap() { LinkedHashMap singleValueMap = new LinkedHashMap(this.headers.size()); - for (Entry> entry : headers.entrySet()) { + for (Entry> entry : this.headers.entrySet()) { singleValueMap.put(entry.getKey(), entry.getValue().get(0)); } return singleValueMap;