Polishing
This commit is contained in:
@@ -125,8 +125,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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -679,7 +679,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.
|
||||
@@ -833,8 +833,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
|
||||
/**
|
||||
* Obtain a "shortcut" singleton FactoryBean instance to use for a
|
||||
* {@code getObjectType()} call, without full initialization
|
||||
* of the FactoryBean.
|
||||
* {@code getObjectType()} call, without full initialization of the FactoryBean.
|
||||
* @param beanName the name of the bean
|
||||
* @param mbd the bean definition for the bean
|
||||
* @return the FactoryBean instance, or {@code null} to indicate
|
||||
@@ -875,8 +874,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
|
||||
/**
|
||||
* Obtain a "shortcut" non-singleton FactoryBean instance to use for a
|
||||
* {@code getObjectType()} call, without full initialization
|
||||
* of the FactoryBean.
|
||||
* {@code getObjectType()} call, without full initialization of the FactoryBean.
|
||||
* @param beanName the name of the bean
|
||||
* @param mbd the bean definition for the bean
|
||||
* @return the FactoryBean instance, or {@code null} to indicate
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -25,10 +25,10 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link ScopeMetadataResolver} implementation that by default checks for
|
||||
* the presence of Spring's {@link Scope} annotation on the bean class.
|
||||
* the presence of Spring's {@link Scope @Scope} annotation on the bean class.
|
||||
*
|
||||
* <p>The exact type of annotation that is checked for is configurable via the
|
||||
* {@link #setScopeAnnotationType(Class)} property.
|
||||
* <p>The exact type of annotation that is checked for is configurable via
|
||||
* {@link #setScopeAnnotationType(Class)}.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
@@ -43,7 +43,7 @@ public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance of the {@code AnnotationScopeMetadataResolver} class.
|
||||
* Construct a new {@code AnnotationScopeMetadataResolver}.
|
||||
* @see #AnnotationScopeMetadataResolver(ScopedProxyMode)
|
||||
* @see ScopedProxyMode#NO
|
||||
*/
|
||||
@@ -52,8 +52,9 @@ public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the {@code AnnotationScopeMetadataResolver} class.
|
||||
* @param defaultProxyMode the desired scoped-proxy mode
|
||||
* Construct a new {@code AnnotationScopeMetadataResolver} using the
|
||||
* supplied default {@link ScopedProxyMode}.
|
||||
* @param defaultProxyMode the default scoped-proxy mode
|
||||
*/
|
||||
public AnnotationScopeMetadataResolver(ScopedProxyMode defaultProxyMode) {
|
||||
Assert.notNull(defaultProxyMode, "'defaultProxyMode' must not be null");
|
||||
@@ -63,7 +64,7 @@ public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
|
||||
|
||||
/**
|
||||
* Set the type of annotation that is checked for by this
|
||||
* {@link AnnotationScopeMetadataResolver}.
|
||||
* {@code AnnotationScopeMetadataResolver}.
|
||||
* @param scopeAnnotationType the target annotation type
|
||||
*/
|
||||
public void setScopeAnnotationType(Class<? extends Annotation> scopeAnnotationType) {
|
||||
|
||||
@@ -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.
|
||||
@@ -138,11 +138,11 @@ import org.springframework.core.Ordered;
|
||||
public @interface EnableAsync {
|
||||
|
||||
/**
|
||||
* Indicate the 'async' annotation type to be detected at either class
|
||||
* or method level. By default, both the {@link Async} annotation and
|
||||
* the EJB 3.1 {@code javax.ejb.Asynchronous} annotation will be
|
||||
* detected. <p>This setter property exists so that developers can provide
|
||||
* their own (non-Spring-specific) annotation type to indicate that a method
|
||||
* Indicate the 'async' annotation type to be detected at either class or
|
||||
* method level. By default, both the {@link Async} annotation and the
|
||||
* EJB 3.1 {@code javax.ejb.Asynchronous} annotation will be detected.
|
||||
* <p>This setter property exists so that developers can provide their
|
||||
* own (non-Spring-specific) annotation type to indicate that a method
|
||||
* (or all methods of a given class) should be invoked asynchronously.
|
||||
*/
|
||||
Class<? extends Annotation> annotation() default Annotation.class;
|
||||
@@ -151,7 +151,6 @@ public @interface EnableAsync {
|
||||
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
|
||||
* to standard Java interface-based proxies. The default is {@code false}. <strong>
|
||||
* Applicable only if {@link #mode()} is set to {@link AdviceMode#PROXY}</strong>.
|
||||
*
|
||||
* <p>Note that setting this attribute to {@code true} will affect <em>all</em>
|
||||
* Spring-managed beans requiring proxying, not just those marked with {@code @Async}.
|
||||
* For example, other beans marked with Spring's {@code @Transactional} annotation
|
||||
@@ -176,4 +175,5 @@ public @interface EnableAsync {
|
||||
* existing proxies rather than double-proxy.
|
||||
*/
|
||||
int order() default Ordered.LOWEST_PRECEDENCE;
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -23,13 +23,12 @@ import org.springframework.context.annotation.Role;
|
||||
import org.springframework.scheduling.config.TaskManagementConfigUtils;
|
||||
|
||||
/**
|
||||
* {@code @Configuration} class that registers a {@link
|
||||
* ScheduledAnnotationBeanPostProcessor} bean capable of processing Spring's @{@link
|
||||
* Scheduled} annotation.
|
||||
* {@code @Configuration} class that registers a {@link ScheduledAnnotationBeanPostProcessor}
|
||||
* bean capable of processing Spring's @{@link Scheduled} annotation.
|
||||
*
|
||||
* <p>This configuration class is automatically imported when using the @{@link
|
||||
* EnableScheduling} annotation. See {@code @EnableScheduling} Javadoc for complete usage
|
||||
* details.
|
||||
* <p>This configuration class is automatically imported when using the
|
||||
* @{@link EnableScheduling} annotation. See {@code @EnableScheduling}'s javadoc
|
||||
* for complete usage details.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
|
||||
@@ -543,7 +543,7 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||
* Return the primary Validator to apply after each binding step, if any.
|
||||
*/
|
||||
public Validator getValidator() {
|
||||
return this.validators.size() > 0 ? this.validators.get(0) : null;
|
||||
return (this.validators.size() > 0 ? this.validators.get(0) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,49 +84,6 @@ public class EnableAsyncTests {
|
||||
assertThat(workerThread3.get().getName(), startsWith("otherExecutor-"));
|
||||
}
|
||||
|
||||
|
||||
static class AsyncBeanWithExecutorQualifiedByName {
|
||||
@Async
|
||||
public Future<Thread> work0() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
}
|
||||
|
||||
@Async("e1")
|
||||
public Future<Thread> work() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
}
|
||||
|
||||
@Async("otherExecutor")
|
||||
public Future<Thread> work2() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
}
|
||||
|
||||
@Async("e2")
|
||||
public Future<Thread> work3() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class AsyncBean {
|
||||
private Thread threadOfExecution;
|
||||
|
||||
@Async
|
||||
public void work() {
|
||||
this.threadOfExecution = Thread.currentThread();
|
||||
}
|
||||
|
||||
@Async
|
||||
public void fail() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Thread getThreadOfExecution() {
|
||||
return threadOfExecution;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void asyncProcessorIsOrderedLowestPrecedenceByDefault() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
@@ -148,7 +94,6 @@ public class EnableAsyncTests {
|
||||
assertThat(bpp.getOrder(), is(Ordered.LOWEST_PRECEDENCE));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void orderAttributeIsPropagated() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
@@ -159,17 +104,6 @@ public class EnableAsyncTests {
|
||||
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();
|
||||
@@ -188,51 +122,16 @@ public class EnableAsyncTests {
|
||||
assertTrue("bean was not async advised as expected", isAsyncAdvised);
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAsync(annotation=CustomAsync.class)
|
||||
static class CustomAsyncAnnotationConfig {
|
||||
@Bean
|
||||
public CustomAsyncBean asyncBean() {
|
||||
return new CustomAsyncBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface CustomAsync {
|
||||
}
|
||||
|
||||
|
||||
static class CustomAsyncBean {
|
||||
@CustomAsync
|
||||
public void work() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fails with classpath errors on trying to classload AnnotationAsyncExecutionAspect
|
||||
*/
|
||||
@Test(expected=BeanDefinitionStoreException.class)
|
||||
@Test(expected = BeanDefinitionStoreException.class)
|
||||
public void aspectModeAspectJAttemptsToRegisterAsyncAspect() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(AspectJAsyncAnnotationConfig.class);
|
||||
ctx.refresh();
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAsync(mode=AdviceMode.ASPECTJ)
|
||||
static class AspectJAsyncAnnotationConfig {
|
||||
@Bean
|
||||
public AsyncBean asyncBean() {
|
||||
return new AsyncBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void customExecutorIsPropagated() throws InterruptedException {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
@@ -257,9 +156,112 @@ public class EnableAsyncTests {
|
||||
}
|
||||
|
||||
|
||||
static class AsyncBeanWithExecutorQualifiedByName {
|
||||
|
||||
@Async
|
||||
public Future<Thread> work0() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
}
|
||||
|
||||
@Async("e1")
|
||||
public Future<Thread> work() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
}
|
||||
|
||||
@Async("otherExecutor")
|
||||
public Future<Thread> work2() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
}
|
||||
|
||||
@Async("e2")
|
||||
public Future<Thread> work3() {
|
||||
return new AsyncResult<Thread>(Thread.currentThread());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class AsyncBean {
|
||||
|
||||
private Thread threadOfExecution;
|
||||
|
||||
@Async
|
||||
public void work() {
|
||||
this.threadOfExecution = Thread.currentThread();
|
||||
}
|
||||
|
||||
@Async
|
||||
public void fail() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Thread getThreadOfExecution() {
|
||||
return threadOfExecution;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAsync(annotation = CustomAsync.class)
|
||||
static class CustomAsyncAnnotationConfig {
|
||||
|
||||
@Bean
|
||||
public CustomAsyncBean asyncBean() {
|
||||
return new CustomAsyncBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@interface CustomAsync {
|
||||
}
|
||||
|
||||
|
||||
static class CustomAsyncBean {
|
||||
|
||||
@CustomAsync
|
||||
public void work() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAsync(order = Ordered.HIGHEST_PRECEDENCE)
|
||||
static class OrderedAsyncConfig {
|
||||
|
||||
@Bean
|
||||
public AsyncBean asyncBean() {
|
||||
return new AsyncBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAsync(mode = AdviceMode.ASPECTJ)
|
||||
static class AspectJAsyncAnnotationConfig {
|
||||
|
||||
@Bean
|
||||
public AsyncBean asyncBean() {
|
||||
return new AsyncBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
static class AsyncConfig {
|
||||
|
||||
@Bean
|
||||
public AsyncBean asyncBean() {
|
||||
return new AsyncBean();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
static class CustomExecutorAsyncConfig implements AsyncConfigurer {
|
||||
|
||||
@Bean
|
||||
public AsyncBean asyncBean() {
|
||||
return new AsyncBean();
|
||||
@@ -275,7 +277,7 @@ public class EnableAsyncTests {
|
||||
|
||||
@Override
|
||||
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||
return exceptionHandler();
|
||||
return exceptionHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@@ -288,6 +290,7 @@ public class EnableAsyncTests {
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
static class AsyncWithExecutorQualifiedByNameConfig {
|
||||
|
||||
@Bean
|
||||
public AsyncBeanWithExecutorQualifiedByName asyncBean() {
|
||||
return new AsyncBeanWithExecutorQualifiedByName();
|
||||
@@ -295,15 +298,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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 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.
|
||||
@@ -41,6 +41,7 @@ import static org.junit.Assert.*;
|
||||
* Tests use of @EnableScheduling on @Configuration classes.
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @author Sam Brannen
|
||||
* @since 3.1
|
||||
*/
|
||||
public class EnableSchedulingTests {
|
||||
@@ -50,6 +51,7 @@ public class EnableSchedulingTests {
|
||||
Assume.group(TestGroup.PERFORMANCE);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void withFixedRateTask() throws InterruptedException {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
@@ -138,12 +140,17 @@ public class EnableSchedulingTests {
|
||||
ctx.register(AmbiguousExplicitSchedulerConfig.class);
|
||||
try {
|
||||
ctx.refresh();
|
||||
} catch (IllegalStateException ex) {
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertThat(ex.getMessage(), startsWith("More than one TaskScheduler"));
|
||||
throw ex;
|
||||
}
|
||||
finally {
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EnableScheduling @Configuration
|
||||
static class AmbiguousExplicitSchedulerConfig {
|
||||
|
||||
@@ -236,6 +243,7 @@ public class EnableSchedulingTests {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(SchedulingEnabled_withAmbiguousTaskSchedulers_butNoActualTasks.class);
|
||||
ctx.refresh();
|
||||
ctx.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -265,10 +273,14 @@ public class EnableSchedulingTests {
|
||||
ctx.register(SchedulingEnabled_withAmbiguousTaskSchedulers_andSingleTask.class);
|
||||
try {
|
||||
ctx.refresh();
|
||||
} catch (IllegalStateException ex) {
|
||||
assertThat(ex.getMessage(), startsWith("More than one TaskScheduler and/or"));
|
||||
}
|
||||
catch (IllegalStateException ex) {
|
||||
assertThat(ex.getMessage(), startsWith("More than one TaskScheduler"));
|
||||
throw ex;
|
||||
}
|
||||
finally {
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -295,6 +307,7 @@ public class EnableSchedulingTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void withAmbiguousTaskSchedulers_andSingleTask_disambiguatedByScheduledTaskRegistrarBean() throws InterruptedException {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
@@ -476,6 +489,7 @@ public class EnableSchedulingTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void withInitiallyDelayedFixedRateTask() throws InterruptedException {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
@@ -486,8 +500,8 @@ public class EnableSchedulingTests {
|
||||
AtomicInteger counter = ctx.getBean(AtomicInteger.class);
|
||||
ctx.close();
|
||||
|
||||
assertThat(counter.get(), greaterThan(0)); // the @Scheduled method was called
|
||||
assertThat(counter.get(), lessThanOrEqualTo(10)); // but not more than times the delay allows
|
||||
assertThat(counter.get(), greaterThan(0)); // the @Scheduled method was called
|
||||
assertThat(counter.get(), lessThanOrEqualTo(10)); // but not more than times the delay allows
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,8 +30,9 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Helper class that encapsulates the specification of a method parameter, i.e.
|
||||
* a Method or Constructor plus a parameter index and a nested type index for
|
||||
* a declared generic type. Useful as a specification object to pass along.
|
||||
* a {@link Method} or {@link Constructor} plus a parameter index and a nested
|
||||
* type index for a declared generic type. Useful as a specification object to
|
||||
* pass along.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
@@ -66,20 +67,22 @@ public class MethodParameter {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new MethodParameter for the given method, with nesting level 1.
|
||||
* Create a new {@code MethodParameter} for the given method, with nesting level 1.
|
||||
* @param method the Method to specify a parameter for
|
||||
* @param parameterIndex the index of the parameter
|
||||
* @param parameterIndex the index of the parameter: -1 for the method
|
||||
* return type; 0 for the first method parameter; 1 for the second method
|
||||
* parameter, etc.
|
||||
*/
|
||||
public MethodParameter(Method method, int parameterIndex) {
|
||||
this(method, parameterIndex, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MethodParameter for the given method.
|
||||
* Create a new {@code MethodParameter} for the given method.
|
||||
* @param method the Method to specify a parameter for
|
||||
* @param parameterIndex the index of the parameter
|
||||
* (-1 for the method return type; 0 for the first method parameter,
|
||||
* 1 for the second method parameter, etc)
|
||||
* @param parameterIndex the index of the parameter: -1 for the method
|
||||
* return type; 0 for the first method parameter; 1 for the second method
|
||||
* parameter, etc.
|
||||
* @param nestingLevel the nesting level of the target type
|
||||
* (typically 1; e.g. in case of a List of Lists, 1 would indicate the
|
||||
* nested List, whereas 2 would indicate the element of the nested List)
|
||||
@@ -197,7 +200,7 @@ public class MethodParameter {
|
||||
|
||||
/**
|
||||
* Return the index of the method/constructor parameter.
|
||||
* @return the parameter index (never negative)
|
||||
* @return the parameter index (-1 in case of the return type)
|
||||
*/
|
||||
public int getParameterIndex() {
|
||||
return this.parameterIndex;
|
||||
|
||||
@@ -129,6 +129,7 @@ public class AntPathMatcher implements PathMatcher {
|
||||
* turn it off when encountering too many patterns to cache at runtime
|
||||
* (the threshold is 65536), assuming that arbitrary permutations of patterns
|
||||
* are coming in, with little chance for encountering a recurring pattern.
|
||||
* @since 4.0.1
|
||||
* @see #getStringMatcher(String)
|
||||
*/
|
||||
public void setCachePatterns(boolean cachePatterns) {
|
||||
@@ -413,18 +414,18 @@ public class AntPathMatcher implements PathMatcher {
|
||||
public Map<String, String> extractUriTemplateVariables(String pattern, String path) {
|
||||
Map<String, String> variables = new LinkedHashMap<String, String>();
|
||||
boolean result = doMatch(pattern, path, true, variables);
|
||||
Assert.state(result, "Pattern \"" + pattern + "\" is not a match for \"" + path + "\"");
|
||||
if (!result) {
|
||||
throw new IllegalStateException("Pattern \"" + pattern + "\" is not a match for \"" + path + "\"");
|
||||
}
|
||||
return variables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine two patterns into a new pattern.
|
||||
*
|
||||
* <p>This implementation simply concatenates the two patterns, unless
|
||||
* the first pattern contains a file extension match (e.g., {@code *.html}).
|
||||
* In that case, the second pattern will be merged into the first. Otherwise,
|
||||
* an {@code IllegalArgumentException} will be thrown.
|
||||
*
|
||||
* <h3>Examples</h3>
|
||||
* <table border="1">
|
||||
* <tr><th>Pattern 1</th><th>Pattern 2</th><th>Result</th></tr>
|
||||
@@ -442,7 +443,6 @@ public class AntPathMatcher implements PathMatcher {
|
||||
* <tr><td>/*.html</td><td>/hotels</td><td>/hotels.html</td></tr>
|
||||
* <tr><td>/*.html</td><td>/*.txt</td><td>{@code IllegalArgumentException}</td></tr>
|
||||
* </table>
|
||||
*
|
||||
* @param pattern1 the first pattern
|
||||
* @param pattern2 the second pattern
|
||||
* @return the combination of the two patterns
|
||||
@@ -484,6 +484,7 @@ public class AntPathMatcher implements PathMatcher {
|
||||
// simply concatenate the two patterns
|
||||
return concat(pattern1, pattern2);
|
||||
}
|
||||
|
||||
String extension1 = pattern1.substring(starDotPos1 + 1);
|
||||
int dotPos2 = pattern2.indexOf('.');
|
||||
String fileName2 = (dotPos2 == -1 ? pattern2 : pattern2.substring(0, dotPos2));
|
||||
@@ -508,14 +509,18 @@ public class AntPathMatcher implements PathMatcher {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a full path, returns a {@link Comparator} suitable for sorting patterns in order of explicitness.
|
||||
* <p>The returned {@code Comparator} will {@linkplain java.util.Collections#sort(java.util.List,
|
||||
* java.util.Comparator) sort} a list so that more specific patterns (without uri templates or wild cards) come before
|
||||
* generic patterns. So given a list with the following patterns: <ol> <li>{@code /hotels/new}</li>
|
||||
* <li>{@code /hotels/{hotel}}</li> <li>{@code /hotels/*}</li> </ol> the returned comparator will sort this
|
||||
* list so that the order will be as indicated.
|
||||
* <p>The full path given as parameter is used to test for exact matches. So when the given path is {@code /hotels/2},
|
||||
* the pattern {@code /hotels/2} will be sorted before {@code /hotels/1}.
|
||||
* Given a full path, returns a {@link Comparator} suitable for sorting patterns in order of
|
||||
* explicitness.
|
||||
* <p>This{@code Comparator} will {@linkplain java.util.Collections#sort(List, Comparator) sort}
|
||||
* a list so that more specific patterns (without uri templates or wild cards) come before
|
||||
* generic patterns. So given a list with the following patterns:
|
||||
* <ol>
|
||||
* <li>{@code /hotels/new}</li>
|
||||
* <li>{@code /hotels/{hotel}}</li> <li>{@code /hotels/*}</li>
|
||||
* </ol>
|
||||
* the returned comparator will sort this list so that the order will be as indicated.
|
||||
* <p>The full path given as parameter is used to test for exact matches. So when the given path
|
||||
* is {@code /hotels/2}, the pattern {@code /hotels/2} will be sorted before {@code /hotels/1}.
|
||||
* @param path the full path to use for comparison
|
||||
* @return a comparator capable of sorting patterns in order of explicitness
|
||||
*/
|
||||
@@ -542,11 +547,11 @@ public class AntPathMatcher implements PathMatcher {
|
||||
|
||||
public AntPathStringMatcher(String pattern) {
|
||||
StringBuilder patternBuilder = new StringBuilder();
|
||||
Matcher m = GLOB_PATTERN.matcher(pattern);
|
||||
Matcher matcher = GLOB_PATTERN.matcher(pattern);
|
||||
int end = 0;
|
||||
while (m.find()) {
|
||||
patternBuilder.append(quote(pattern, end, m.start()));
|
||||
String match = m.group();
|
||||
while (matcher.find()) {
|
||||
patternBuilder.append(quote(pattern, end, matcher.start()));
|
||||
String match = matcher.group();
|
||||
if ("?".equals(match)) {
|
||||
patternBuilder.append('.');
|
||||
}
|
||||
@@ -557,7 +562,7 @@ public class AntPathMatcher implements PathMatcher {
|
||||
int colonIdx = match.indexOf(':');
|
||||
if (colonIdx == -1) {
|
||||
patternBuilder.append(DEFAULT_VARIABLE_PATTERN);
|
||||
this.variableNames.add(m.group(1));
|
||||
this.variableNames.add(matcher.group(1));
|
||||
}
|
||||
else {
|
||||
String variablePattern = match.substring(colonIdx + 1, match.length() - 1);
|
||||
@@ -568,7 +573,7 @@ public class AntPathMatcher implements PathMatcher {
|
||||
this.variableNames.add(variableName);
|
||||
}
|
||||
}
|
||||
end = m.end();
|
||||
end = matcher.end();
|
||||
}
|
||||
patternBuilder.append(quote(pattern, end, pattern.length()));
|
||||
this.pattern = Pattern.compile(patternBuilder.toString());
|
||||
@@ -590,10 +595,12 @@ public class AntPathMatcher implements PathMatcher {
|
||||
if (matcher.matches()) {
|
||||
if (uriTemplateVariables != null) {
|
||||
// SPR-8455
|
||||
Assert.isTrue(this.variableNames.size() == matcher.groupCount(),
|
||||
"The number of capturing groups in the pattern segment " + this.pattern +
|
||||
" does not match the number of URI template variables it defines, which can occur if " +
|
||||
" capturing groups are used in a URI template regex. Use non-capturing groups instead.");
|
||||
if (this.variableNames.size() != matcher.groupCount()) {
|
||||
throw new IllegalArgumentException("The number of capturing groups in the pattern segment " +
|
||||
this.pattern + " does not match the number of URI template variables it defines, " +
|
||||
"which can occur if capturing groups are used in a URI template regex. " +
|
||||
"Use non-capturing groups instead.");
|
||||
}
|
||||
for (int i = 1; i <= matcher.groupCount(); i++) {
|
||||
String name = this.variableNames.get(i - 1);
|
||||
String value = matcher.group(i);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.springframework.expression;
|
||||
|
||||
/**
|
||||
* Super class for exceptions that can occur whilst processing expressions
|
||||
* Super class for exceptions that can occur whilst processing expressions.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @since 3.0
|
||||
@@ -27,11 +27,11 @@ public class ExpressionException extends RuntimeException {
|
||||
|
||||
protected String expressionString;
|
||||
|
||||
protected int position; // -1 if not known - but should be known in all reasonable cases
|
||||
protected int position; // -1 if not known - but should be known in all reasonable cases
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
* Construct a new expression exception.
|
||||
* @param expressionString the expression string
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
@@ -42,7 +42,7 @@ public class ExpressionException extends RuntimeException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
* Construct a new expression exception.
|
||||
* @param expressionString the expression string
|
||||
* @param position the position in the expression string where the problem occurred
|
||||
* @param message a descriptive message
|
||||
@@ -54,7 +54,7 @@ public class ExpressionException extends RuntimeException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
* Construct a new expression exception.
|
||||
* @param position the position in the expression string where the problem occurred
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
@@ -64,7 +64,7 @@ public class ExpressionException extends RuntimeException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
* Construct a new expression exception.
|
||||
* @param position the position in the expression string where the problem occurred
|
||||
* @param message a descriptive message
|
||||
* @param cause the underlying cause of this exception
|
||||
@@ -75,21 +75,40 @@ public class ExpressionException extends RuntimeException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new expression exception.
|
||||
* Construct a new expression exception.
|
||||
* @param message a descriptive message
|
||||
*/
|
||||
public ExpressionException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new expression exception.
|
||||
* @param message a descriptive message
|
||||
* @param cause the underlying cause of this exception
|
||||
*/
|
||||
public ExpressionException(String message, Throwable cause) {
|
||||
super(message,cause);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the exception message. Since Spring 4.0 this method returns the same
|
||||
* result as {@link #toDetailedString()}.
|
||||
* Return the expression string.
|
||||
*/
|
||||
public final String getExpressionString() {
|
||||
return this.expressionString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the position in the expression string where the problem occurred.
|
||||
*/
|
||||
public final int getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the exception message. Since Spring 4.0 this method returns the
|
||||
* same result as {@link #toDetailedString()}.
|
||||
* @see java.lang.Throwable#getMessage()
|
||||
*/
|
||||
@Override
|
||||
@@ -98,35 +117,34 @@ public class ExpressionException extends RuntimeException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the exception simple message without including the expression that caused
|
||||
* the failure.
|
||||
* Return a detailed description of this exception, including the expression
|
||||
* String and position (if available) as well as the actual exception message.
|
||||
*/
|
||||
public String toDetailedString() {
|
||||
if (this.expressionString != null) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
output.append("Expression '");
|
||||
output.append(this.expressionString);
|
||||
output.append("'");
|
||||
if (this.position != -1) {
|
||||
output.append(" @ ");
|
||||
output.append(this.position);
|
||||
}
|
||||
output.append(": ");
|
||||
output.append(getSimpleMessage());
|
||||
return output.toString();
|
||||
}
|
||||
else {
|
||||
return getSimpleMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the exception simple message without including the expression
|
||||
* that caused the failure.
|
||||
*/
|
||||
public String getSimpleMessage() {
|
||||
return super.getMessage();
|
||||
}
|
||||
|
||||
public String toDetailedString() {
|
||||
StringBuilder output = new StringBuilder();
|
||||
if (this.expressionString!=null) {
|
||||
output.append("Expression '");
|
||||
output.append(this.expressionString);
|
||||
output.append("'");
|
||||
if (this.position!=-1) {
|
||||
output.append(" @ ");
|
||||
output.append(this.position);
|
||||
}
|
||||
output.append(": ");
|
||||
}
|
||||
output.append(getSimpleMessage());
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
public final String getExpressionString() {
|
||||
return this.expressionString;
|
||||
}
|
||||
|
||||
public final int getPosition() {
|
||||
return this.position;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -56,7 +56,7 @@ public class CodeFlow implements Opcodes {
|
||||
* will be called after the main evaluation function has finished being generated.
|
||||
*/
|
||||
private List<FieldAdder> fieldAdders = null;
|
||||
|
||||
|
||||
/**
|
||||
* As SpEL ast nodes are called to generate code for the main evaluation method
|
||||
* they can register to add code to a static initializer in the class. Any
|
||||
@@ -64,19 +64,19 @@ public class CodeFlow implements Opcodes {
|
||||
* has finished being generated.
|
||||
*/
|
||||
private List<ClinitAdder> clinitAdders = null;
|
||||
|
||||
|
||||
/**
|
||||
* Name of the class being generated. Typically used when generating code
|
||||
* that accesses freshly generated fields on the generated type.
|
||||
*/
|
||||
private String clazzName;
|
||||
|
||||
|
||||
/**
|
||||
* When code generation requires holding a value in a class level field, this
|
||||
* is used to track the next available field id (used as a name suffix).
|
||||
*/
|
||||
private int nextFieldId = 1;
|
||||
|
||||
|
||||
/**
|
||||
* When code generation requires an intermediate variable within a method,
|
||||
* this method records the next available variable (variable 0 is 'this').
|
||||
@@ -211,7 +211,7 @@ public class CodeFlow implements Opcodes {
|
||||
|
||||
/**
|
||||
* Create the JVM signature descriptor for a method. This consists of the descriptors
|
||||
* for the constructor parameters surrounded with parentheses, followed by the
|
||||
* for the method parameters surrounded with parentheses, followed by the
|
||||
* descriptor for the return type. Note the descriptors here are JVM descriptors,
|
||||
* unlike the other descriptor forms the compiler is using which do not include the
|
||||
* trailing semicolon.
|
||||
@@ -232,11 +232,12 @@ public class CodeFlow implements Opcodes {
|
||||
|
||||
/**
|
||||
* Create the JVM signature descriptor for a constructor. This consists of the
|
||||
* descriptors for the constructor parameters surrounded with parentheses. Note the
|
||||
* descriptors for the constructor parameters surrounded with parentheses, followed by
|
||||
* the descriptor for the return type, which is always "V". Note the
|
||||
* descriptors here are JVM descriptors, unlike the other descriptor forms the
|
||||
* compiler is using which do not include the trailing semicolon.
|
||||
* @param ctor the constructor
|
||||
* @return a String signature descriptor (e.g. "(ILjava/lang/String;)")
|
||||
* @return a String signature descriptor (e.g. "(ILjava/lang/String;)V")
|
||||
*/
|
||||
public static String createSignatureDescriptor(Constructor<?> ctor) {
|
||||
Class<?>[] params = ctor.getParameterTypes();
|
||||
@@ -657,7 +658,7 @@ public class CodeFlow implements Opcodes {
|
||||
}
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called after the main expression evaluation method has been generated, this
|
||||
* method will callback any registered FieldAdders or ClinitAdders to add any
|
||||
@@ -695,7 +696,7 @@ public class CodeFlow implements Opcodes {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a ClinitAdder which will add code to the static
|
||||
* Register a ClinitAdder which will add code to the static
|
||||
* initializer in the generated class to support the code
|
||||
* produced by an ast nodes primary generateCode() method.
|
||||
*/
|
||||
@@ -717,11 +718,11 @@ public class CodeFlow implements Opcodes {
|
||||
public String getClassname() {
|
||||
return clazzName;
|
||||
}
|
||||
|
||||
|
||||
public interface FieldAdder {
|
||||
public void generateField(ClassWriter cw, CodeFlow codeflow);
|
||||
}
|
||||
|
||||
|
||||
public interface ClinitAdder {
|
||||
public void generateCode(MethodVisitor mv, CodeFlow codeflow);
|
||||
}
|
||||
@@ -743,11 +744,11 @@ public class CodeFlow implements Opcodes {
|
||||
}
|
||||
else {
|
||||
mv.visitLdcInsn(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce appropriate bytecode to store a stack item in an array. The
|
||||
* Produce appropriate bytecode to store a stack item in an array. The
|
||||
* instruction to use varies depending on whether the type
|
||||
* is a primitive or reference type.
|
||||
* @param mv where to insert the bytecode
|
||||
@@ -781,7 +782,7 @@ public class CodeFlow implements Opcodes {
|
||||
public static int arrayCodeFor(String arraytype) {
|
||||
switch (arraytype.charAt(0)) {
|
||||
case 'I': return T_INT;
|
||||
case 'J': return T_LONG;
|
||||
case 'J': return T_LONG;
|
||||
case 'F': return T_FLOAT;
|
||||
case 'D': return T_DOUBLE;
|
||||
case 'B': return T_BYTE;
|
||||
@@ -805,9 +806,9 @@ public class CodeFlow implements Opcodes {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Produce the correct bytecode to build an array. The opcode to use and the
|
||||
* Produce the correct bytecode to build an array. The opcode to use and the
|
||||
* signature to pass along with the opcode can vary depending on the signature
|
||||
* of the array type.
|
||||
* @param mv the methodvisitor into which code should be inserted
|
||||
@@ -825,7 +826,8 @@ public class CodeFlow implements Opcodes {
|
||||
// is [[I then we want [I and not [I;
|
||||
if (CodeFlow.isReferenceTypeArray(arraytype)) {
|
||||
mv.visitTypeInsn(ANEWARRAY, arraytype+";");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
mv.visitTypeInsn(ANEWARRAY, arraytype);
|
||||
}
|
||||
}
|
||||
@@ -835,5 +837,4 @@ public class CodeFlow implements Opcodes {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Map<String,Object>> 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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -120,7 +120,7 @@ public class JmsMessagingTemplate extends AbstractMessagingTemplate<Destination>
|
||||
* to convert the payload of the message.
|
||||
* <p>Consider configuring a {@link MessagingMessageConverter} with a different
|
||||
* {@link MessagingMessageConverter#setPayloadConverter(MessageConverter) payload converter}
|
||||
* for more advanced scenario.
|
||||
* for more advanced scenarios.
|
||||
* @see org.springframework.jms.support.converter.MessagingMessageConverter
|
||||
*/
|
||||
public void setJmsMessageConverter(MessageConverter jmsMessageConverter) {
|
||||
|
||||
@@ -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.
|
||||
@@ -40,8 +40,8 @@ import org.springframework.jms.support.destination.DynamicDestinationResolver;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* An abstract {@link MessageListener} adapter providing the necessary infrastructure
|
||||
* to extract the payload of a {@link Message}
|
||||
* An abstract JMS {@link MessageListener} adapter providing the necessary
|
||||
* infrastructure to extract the payload of a JMS {@link Message}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Stephane Nicoll
|
||||
@@ -217,7 +217,7 @@ public abstract class AbstractAdaptableMessageListener
|
||||
return message;
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new MessageConversionException("Could not unmarshal message", ex);
|
||||
throw new MessageConversionException("Could not convert JMS message", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,10 +246,12 @@ public abstract class AbstractAdaptableMessageListener
|
||||
sendResponse(session, destination, response);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ReplyFailureException("Failed to send reply with payload '" + result + "'", ex);
|
||||
throw new ReplyFailureException("Failed to send reply with payload [" + result + "]", ex);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
// No JMS Session available
|
||||
if (logger.isWarnEnabled()) {
|
||||
logger.warn("Listener method returned result [" + result +
|
||||
"]: not generating response message for it because of no JMS Session given");
|
||||
|
||||
@@ -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.
|
||||
@@ -77,7 +77,7 @@ public class MessagingMessageListenerAdapter extends AbstractAdaptableMessageLis
|
||||
return (Message<?>) getMessagingMessageConverter().fromMessage(jmsMessage);
|
||||
}
|
||||
catch (JMSException ex) {
|
||||
throw new MessageConversionException("Could not unmarshal message", ex);
|
||||
throw new MessageConversionException("Could not convert JMS message", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,8 +90,8 @@ public class MessagingMessageListenerAdapter extends AbstractAdaptableMessageLis
|
||||
return this.handlerMethod.invoke(message, jmsMessage, session);
|
||||
}
|
||||
catch (MessagingException ex) {
|
||||
throw new ListenerExecutionFailedException(createMessagingErrorMessage("Listener method could not " +
|
||||
"be invoked with the incoming message"), ex);
|
||||
throw new ListenerExecutionFailedException(
|
||||
createMessagingErrorMessage("Listener method could not be invoked with incoming message"), ex);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new ListenerExecutionFailedException("Listener method '" +
|
||||
|
||||
@@ -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.
|
||||
@@ -31,11 +31,11 @@ import org.springframework.messaging.MessageHeaders;
|
||||
public interface MessageConverter {
|
||||
|
||||
/**
|
||||
* Convert the payload of a {@link Message} from serialized form to a typed Object of
|
||||
* the specified target class. The {@link MessageHeaders#CONTENT_TYPE} header should
|
||||
* indicate the MIME type to convert from.
|
||||
* <p>If the converter does not support the specified media type or cannot perform the
|
||||
* conversion, it should return {@code null}.
|
||||
* Convert the payload of a {@link Message} from a serialized form to a typed Object
|
||||
* of the specified target class. The {@link MessageHeaders#CONTENT_TYPE} header
|
||||
* should indicate the MIME type to convert from.
|
||||
* <p>If the converter does not support the specified media type or cannot perform
|
||||
* the conversion, it should return {@code null}.
|
||||
* @param message the input message
|
||||
* @param targetClass the target class for the conversion
|
||||
* @return the result of the conversion, or {@code null} if the converter cannot
|
||||
@@ -47,15 +47,15 @@ public interface MessageConverter {
|
||||
* Create a {@link Message} whose payload is the result of converting the given
|
||||
* payload Object to serialized form. The optional {@link MessageHeaders} parameter
|
||||
* may contain a {@link MessageHeaders#CONTENT_TYPE} header to specify the target
|
||||
* media type for the conversion and it may contain additional headers to be added to
|
||||
* the message.
|
||||
* <p>If the converter does not support the specified media type or cannot perform the
|
||||
* conversion, it should return {@code null}.
|
||||
* media type for the conversion and it may contain additional headers to be added
|
||||
* to the message.
|
||||
* <p>If the converter does not support the specified media type or cannot perform
|
||||
* the conversion, it should return {@code null}.
|
||||
* @param payload the Object to convert
|
||||
* @param header optional headers for the message, may be {@code null}
|
||||
* @return the new message or {@code null} if the converter does not support the
|
||||
* @param headers optional headers for the message (may be {@code null})
|
||||
* @return the new message, or {@code null} if the converter does not support the
|
||||
* Object type or the target media type
|
||||
*/
|
||||
Message<?> toMessage(Object payload, MessageHeaders header);
|
||||
Message<?> toMessage(Object payload, MessageHeaders headers);
|
||||
|
||||
}
|
||||
|
||||
@@ -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,8 @@ import org.springframework.validation.Validator;
|
||||
* The default {@link MessageHandlerMethodFactory} implementation creating an
|
||||
* {@link InvocableHandlerMethod} with the necessary
|
||||
* {@link HandlerMethodArgumentResolver} instances to detect and process
|
||||
* most of the use cases defined by
|
||||
* {@link org.springframework.messaging.handler.annotation.MessageMapping MessageMapping}
|
||||
* most of the use cases defined by
|
||||
* {@link org.springframework.messaging.handler.annotation.MessageMapping MessageMapping}.
|
||||
*
|
||||
* <p>Extra method argument resolvers can be added to customize the method
|
||||
* signature that can be handled.
|
||||
|
||||
@@ -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.
|
||||
@@ -22,10 +22,11 @@ import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* A {@link HandlerMethodArgumentResolver} for {@link Message} parameters. Validates
|
||||
* that the generic type of the payload matches with the message value.
|
||||
* A {@link HandlerMethodArgumentResolver} for {@link Message} parameters.
|
||||
* Validates that the generic type of the payload matches with the message value.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Stephane Nicoll
|
||||
@@ -33,7 +34,6 @@ import org.springframework.messaging.handler.invocation.HandlerMethodArgumentRes
|
||||
*/
|
||||
public class MessageMethodArgumentResolver implements HandlerMethodArgumentResolver {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return Message.class.isAssignableFrom(parameter.getParameterType());
|
||||
@@ -41,22 +41,19 @@ public class MessageMethodArgumentResolver implements HandlerMethodArgumentResol
|
||||
|
||||
@Override
|
||||
public Object resolveArgument(MethodParameter parameter, Message<?> message) throws Exception {
|
||||
|
||||
Class<?> paramType = parameter.getParameterType();
|
||||
|
||||
if (!paramType.isAssignableFrom(message.getClass())) {
|
||||
throw new MethodArgumentTypeMismatchException(message, parameter,
|
||||
"The actual message type [" + message.getClass().getName() + "] " +
|
||||
"does not match the expected type [" + paramType.getName() + "]");
|
||||
"The actual message type [" + ClassUtils.getQualifiedName(message.getClass()) + "] " +
|
||||
"does not match the expected type [" + ClassUtils.getQualifiedName(paramType) + "]");
|
||||
}
|
||||
|
||||
Class<?> expectedPayloadType = getPayloadType(parameter);
|
||||
Object payload = message.getPayload();
|
||||
|
||||
if (expectedPayloadType != null && !expectedPayloadType.isInstance(payload)) {
|
||||
if (payload != null && expectedPayloadType != null && !expectedPayloadType.isInstance(payload)) {
|
||||
throw new MethodArgumentTypeMismatchException(message, parameter,
|
||||
"The expected Message<?> payload type [" + expectedPayloadType.getName() +
|
||||
"] does not match the actual payload type [" + payload.getClass().getName() + "]");
|
||||
"The expected Message<?> payload type [" + ClassUtils.getQualifiedName(expectedPayloadType) +
|
||||
"] does not match the actual payload type [" + ClassUtils.getQualifiedName(payload.getClass()) + "]");
|
||||
}
|
||||
|
||||
return message;
|
||||
|
||||
@@ -455,7 +455,9 @@ public abstract class AbstractMethodMessageHandler<T>
|
||||
processHandlerMethodException(handlerMethod, ex, message);
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.error("Error while processing message " + message, ex);
|
||||
if (logger.isErrorEnabled()) {
|
||||
logger.error("Error while processing message " + message, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,9 +497,7 @@ public abstract class AbstractMethodMessageHandler<T>
|
||||
protected abstract AbstractExceptionHandlerMethodResolver createExceptionHandlerMethodResolverFor(Class<?> beanType);
|
||||
|
||||
protected void handleNoMatch(Set<T> ts, String lookupDestination, Message<?> message) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("No matching methods.");
|
||||
}
|
||||
logger.debug("No matching methods.");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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.
|
||||
@@ -46,7 +46,6 @@ public interface SimpMessageSendingOperations extends MessageSendingOperations<S
|
||||
|
||||
/**
|
||||
* Send a message to the given user.
|
||||
*
|
||||
* @param user the user that should receive the message.
|
||||
* @param destination the destination to send the message to.
|
||||
* @param payload the payload to send
|
||||
@@ -55,13 +54,11 @@ public interface SimpMessageSendingOperations extends MessageSendingOperations<S
|
||||
|
||||
/**
|
||||
* Send a message to the given user.
|
||||
*
|
||||
* <p>By default headers are interpreted as native headers (e.g. STOMP) and
|
||||
* are saved under a special key in the resulting Spring
|
||||
* {@link org.springframework.messaging.Message Message}. In effect when the
|
||||
* message leaves the application, the provided headers are included with it
|
||||
* and delivered to the destination (e.g. the STOMP client or broker).
|
||||
*
|
||||
* <p>If the map already contains the key
|
||||
* {@link org.springframework.messaging.support.NativeMessageHeaderAccessor#NATIVE_HEADERS "nativeHeaders"}
|
||||
* or was prepared with
|
||||
@@ -69,36 +66,31 @@ public interface SimpMessageSendingOperations extends MessageSendingOperations<S
|
||||
* then the headers are used directly. A common expected case is providing a
|
||||
* content type (to influence the message conversion) and native headers.
|
||||
* This may be done as follows:
|
||||
*
|
||||
* <pre class="code">
|
||||
* SimpMessageHeaderAccessor accessor = SimpMessageHeaderAccessor.create();
|
||||
* accessor.setContentType(MimeTypeUtils.TEXT_PLAIN);
|
||||
* accessor.setNativeHeader("foo", "bar");
|
||||
* accessor.setLeaveMutable(true);
|
||||
* MessageHeaders headers = accessor.getMessageHeaders();
|
||||
*
|
||||
* messagingTemplate.convertAndSendToUser(user, destination, payload, headers);
|
||||
* </pre>
|
||||
*
|
||||
* <p><strong>Note:</strong> if the {@code MessageHeaders} are mutable as in
|
||||
* the above example, implementations of this interface should take notice and
|
||||
* update the headers in the same instance (rather than copy or re-create it)
|
||||
* and then set it immutable before sending the final message.
|
||||
*
|
||||
* @param user the user that should receive the message, must not be {@code null}
|
||||
* @param destination the destination to send the message to, must not be {@code null}
|
||||
* @param payload the payload to send, may be {@code null}
|
||||
* @param headers the message headers, may be {@code null}
|
||||
* @param user the user that should receive the message (must not be {@code null})
|
||||
* @param destination the destination to send the message to (must not be {@code null})
|
||||
* @param payload the payload to send (may be {@code null})
|
||||
* @param headers the message headers (may be {@code null})
|
||||
*/
|
||||
void convertAndSendToUser(String user, String destination, Object payload, Map<String, Object> headers)
|
||||
throws MessagingException;
|
||||
|
||||
/**
|
||||
* Send a message to the given user.
|
||||
*
|
||||
* @param user the user that should receive the message, must not be {@code null}
|
||||
* @param destination the destination to send the message to, must not be {@code null}
|
||||
* @param payload the payload to send, may be {@code null}
|
||||
* @param user the user that should receive the message (must not be {@code null})
|
||||
* @param destination the destination to send the message to (must not be {@code null})
|
||||
* @param payload the payload to send (may be {@code null})
|
||||
* @param postProcessor a postProcessor to post-process or modify the created message
|
||||
*/
|
||||
void convertAndSendToUser(String user, String destination, Object payload,
|
||||
@@ -106,12 +98,10 @@ public interface SimpMessageSendingOperations extends MessageSendingOperations<S
|
||||
|
||||
/**
|
||||
* Send a message to the given user.
|
||||
*
|
||||
* <p>See {@link #convertAndSend(Object, Object, java.util.Map)} for important
|
||||
* notes regarding the input headers.
|
||||
*
|
||||
* @param user the user that should receive the message.
|
||||
* @param destination the destination to send the message to.
|
||||
* @param user the user that should receive the message
|
||||
* @param destination the destination to send the message to
|
||||
* @param payload the payload to send
|
||||
* @param headers the message headers
|
||||
* @param postProcessor a postProcessor to post-process or modify the created message
|
||||
|
||||
@@ -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.
|
||||
@@ -35,16 +35,16 @@ import org.springframework.messaging.simp.user.DestinationUserNameProvider;
|
||||
import org.springframework.messaging.support.MessageHeaderInitializer;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A {@link HandlerMethodReturnValueHandler} for sending to destinations specified in a
|
||||
* {@link SendTo} or {@link SendToUser} method-level annotations.
|
||||
*
|
||||
* <p>The value returned from the method is converted, and turned to a {@link Message} and
|
||||
* sent through the provided {@link MessageChannel}. The
|
||||
* message is then enriched with the sessionId of the input message as well as the
|
||||
* destination from the annotation(s). If multiple destinations are specified, a copy of
|
||||
* the message is sent to each destination.
|
||||
* sent through the provided {@link MessageChannel}. The message is then enriched with the
|
||||
* session id of the input message as well as the destination from the annotation(s).
|
||||
* If multiple destinations are specified, a copy of the message is sent to each destination.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.0
|
||||
@@ -108,7 +108,6 @@ public class SendToMethodReturnValueHandler implements HandlerMethodReturnValueH
|
||||
/**
|
||||
* Configure a {@link MessageHeaderInitializer} to apply to the headers of all
|
||||
* messages sent to the client outbound channel.
|
||||
*
|
||||
* <p>By default this property is not set.
|
||||
*/
|
||||
public void setHeaderInitializer(MessageHeaderInitializer headerInitializer) {
|
||||
@@ -125,8 +124,8 @@ public class SendToMethodReturnValueHandler implements HandlerMethodReturnValueH
|
||||
|
||||
@Override
|
||||
public boolean supportsReturnType(MethodParameter returnType) {
|
||||
if ((returnType.getMethodAnnotation(SendTo.class) != null) ||
|
||||
(returnType.getMethodAnnotation(SendToUser.class) != null)) {
|
||||
if (returnType.getMethodAnnotation(SendTo.class) != null ||
|
||||
returnType.getMethodAnnotation(SendToUser.class) != null) {
|
||||
return true;
|
||||
}
|
||||
return (!this.annotationRequired);
|
||||
@@ -137,10 +136,11 @@ public class SendToMethodReturnValueHandler implements HandlerMethodReturnValueH
|
||||
if (returnValue == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
MessageHeaders headers = message.getHeaders();
|
||||
String sessionId = SimpMessageHeaderAccessor.getSessionId(headers);
|
||||
|
||||
SendToUser sendToUser = returnType.getMethodAnnotation(SendToUser.class);
|
||||
|
||||
if (sendToUser != null) {
|
||||
boolean broadcast = sendToUser.broadcast();
|
||||
String user = getUserName(message, headers);
|
||||
@@ -188,7 +188,9 @@ public class SendToMethodReturnValueHandler implements HandlerMethodReturnValueH
|
||||
}
|
||||
String name = DestinationPatternsMessageCondition.LOOKUP_DESTINATION_HEADER;
|
||||
String destination = (String) message.getHeaders().get(name);
|
||||
Assert.hasText(destination, "No lookup destination header in " + message);
|
||||
if (!StringUtils.hasText(destination)) {
|
||||
throw new IllegalStateException("No lookup destination header in " + message);
|
||||
}
|
||||
|
||||
return (destination.startsWith("/") ?
|
||||
new String[] {defaultPrefix + destination} : new String[] {defaultPrefix + "/" + destination});
|
||||
|
||||
@@ -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.
|
||||
@@ -102,13 +102,14 @@ public class SubscriptionMethodReturnValueHandler implements HandlerMethodReturn
|
||||
String sessionId = SimpMessageHeaderAccessor.getSessionId(headers);
|
||||
String subscriptionId = SimpMessageHeaderAccessor.getSubscriptionId(headers);
|
||||
|
||||
Assert.state(subscriptionId != null,
|
||||
"No subscriptionId in message=" + message + ", method=" + returnType.getMethod());
|
||||
if (subscriptionId == null) {
|
||||
throw new IllegalStateException(
|
||||
"No subscriptionId in " + message + " returned by: " + returnType.getMethod());
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Reply to @SubscribeMapping: " + returnValue);
|
||||
}
|
||||
|
||||
this.messagingTemplate.convertAndSend(destination, returnValue, createHeaders(sessionId, subscriptionId));
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -145,6 +145,7 @@ public class MessageMethodArgumentResolverTests {
|
||||
assertSame(message, this.resolver.resolveArgument(parameter, message));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void handleMessage(
|
||||
Message<?> wildcardPayload,
|
||||
|
||||
@@ -88,8 +88,8 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
private static final Method withRulesMethod;
|
||||
|
||||
static {
|
||||
withRulesMethod = ReflectionUtils.findMethod(SpringJUnit4ClassRunner.class, "withRules", FrameworkMethod.class,
|
||||
Object.class, Statement.class);
|
||||
withRulesMethod = ReflectionUtils.findMethod(SpringJUnit4ClassRunner.class, "withRules",
|
||||
FrameworkMethod.class, Object.class, Statement.class);
|
||||
if (withRulesMethod == null) {
|
||||
throw new IllegalStateException(
|
||||
"Failed to find withRules() method: SpringJUnit4ClassRunner requires JUnit 4.9 or higher.");
|
||||
@@ -101,7 +101,7 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new {@code SpringJUnit4ClassRunner} and initializes a
|
||||
* Construct a new {@code SpringJUnit4ClassRunner} and initialize a
|
||||
* {@link TestContextManager} to provide Spring testing functionality to
|
||||
* standard JUnit tests.
|
||||
* @param clazz the test class to be run
|
||||
@@ -110,13 +110,13 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
public SpringJUnit4ClassRunner(Class<?> clazz) throws InitializationError {
|
||||
super(clazz);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("SpringJUnit4ClassRunner constructor called with [" + clazz + "].");
|
||||
logger.debug("SpringJUnit4ClassRunner constructor called with [" + clazz + "]");
|
||||
}
|
||||
this.testContextManager = createTestContextManager(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link TestContextManager} for the supplied test class.
|
||||
* Create a new {@link TestContextManager} for the supplied test class.
|
||||
* <p>Can be overridden by subclasses.
|
||||
* @param clazz the test class to be managed
|
||||
*/
|
||||
@@ -132,9 +132,9 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a description suitable for an ignored test class if the test is
|
||||
* Return a description suitable for an ignored test class if the test is
|
||||
* disabled via {@code @IfProfileValue} at the class-level, and
|
||||
* otherwise delegates to the parent implementation.
|
||||
* otherwise delegate to the parent implementation.
|
||||
* @see ProfileValueUtils#isTestEnabledInThisEnvironment(Class)
|
||||
*/
|
||||
@Override
|
||||
@@ -146,10 +146,10 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the test is enabled in the first place. This prevents
|
||||
* classes with a non-matching {@code @IfProfileValue} annotation from
|
||||
* running altogether, even skipping the execution of
|
||||
* {@code prepareTestInstance()} {@code TestExecutionListener} methods.
|
||||
* Check whether the test is enabled in the current execution environment.
|
||||
* <p>This prevents classes with a non-matching {@code @IfProfileValue}
|
||||
* annotation from running altogether, even skipping the execution of
|
||||
* {@code prepareTestInstance()} methods in {@code TestExecutionListeners}.
|
||||
* @see ProfileValueUtils#isTestEnabledInThisEnvironment(Class)
|
||||
* @see org.springframework.test.annotation.IfProfileValue
|
||||
* @see org.springframework.test.context.TestExecutionListener
|
||||
@@ -164,9 +164,9 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the {@link Statement} returned by the parent implementation with a
|
||||
* {@link RunBeforeTestClassCallbacks} statement, thus preserving the
|
||||
* default functionality but adding support for the Spring TestContext
|
||||
* Wrap the {@link Statement} returned by the parent implementation with a
|
||||
* {@code RunBeforeTestClassCallbacks} statement, thus preserving the
|
||||
* default JUnit functionality while adding support for the Spring TestContext
|
||||
* Framework.
|
||||
* @see RunBeforeTestClassCallbacks
|
||||
*/
|
||||
@@ -177,9 +177,9 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the {@link Statement} returned by the parent implementation with a
|
||||
* {@link RunAfterTestClassCallbacks} statement, thus preserving the default
|
||||
* functionality but adding support for the Spring TestContext Framework.
|
||||
* Wrap the {@link Statement} returned by the parent implementation with a
|
||||
* {@code RunAfterTestClassCallbacks} statement, thus preserving the default
|
||||
* JUnit functionality while adding support for the Spring TestContext Framework.
|
||||
* @see RunAfterTestClassCallbacks
|
||||
*/
|
||||
@Override
|
||||
@@ -189,10 +189,10 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to the parent implementation for creating the test instance and
|
||||
* then allows the {@link #getTestContextManager() TestContextManager} to
|
||||
* Delegate to the parent implementation for creating the test instance and
|
||||
* then allow the {@link #getTestContextManager() TestContextManager} to
|
||||
* prepare the test instance before returning it.
|
||||
* @see TestContextManager#prepareTestInstance(Object)
|
||||
* @see TestContextManager#prepareTestInstance
|
||||
*/
|
||||
@Override
|
||||
protected Object createTest() throws Exception {
|
||||
@@ -202,7 +202,7 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the same logic as
|
||||
* Perform the same logic as
|
||||
* {@link BlockJUnit4ClassRunner#runChild(FrameworkMethod, RunNotifier)},
|
||||
* except that tests are determined to be <em>ignored</em> by
|
||||
* {@link #isTestMethodIgnored(FrameworkMethod)}.
|
||||
@@ -226,25 +226,26 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Augments the default JUnit behavior
|
||||
* {@link #withPotentialRepeat(FrameworkMethod, Object, Statement) with
|
||||
* potential repeats} of the entire execution chain.
|
||||
* <p>Furthermore, support for timeouts has been moved down the execution chain
|
||||
* in order to include execution of {@link org.junit.Before @Before}
|
||||
* and {@link org.junit.After @After} methods within the timed
|
||||
* execution. Note that this differs from the default JUnit behavior of
|
||||
* executing {@code @Before} and {@code @After} methods
|
||||
* in the main thread while executing the actual test method in a separate
|
||||
* thread. Thus, the end effect is that {@code @Before} and
|
||||
* {@code @After} methods will be executed in the same thread as
|
||||
* the test method. As a consequence, JUnit-specified timeouts will work
|
||||
* fine in combination with Spring transactions. Note that JUnit-specific
|
||||
* timeouts still differ from Spring-specific timeouts in that the former
|
||||
* execute in a separate thread while the latter simply execute in the main
|
||||
* thread (like regular tests).
|
||||
* Augment the default JUnit behavior
|
||||
* {@linkplain #withPotentialRepeat with potential repeats} of the entire
|
||||
* execution chain.
|
||||
* <p>Furthermore, support for timeouts has been moved down the execution
|
||||
* chain in order to include execution of {@link org.junit.Before @Before}
|
||||
* and {@link org.junit.After @After} methods within the timed execution.
|
||||
* Note that this differs from the default JUnit behavior of executing
|
||||
* {@code @Before} and {@code @After} methods in the main thread while
|
||||
* executing the actual test method in a separate thread. Thus, the net
|
||||
* effect is that {@code @Before} and {@code @After} methods will be
|
||||
* executed in the same thread as the test method. As a consequence,
|
||||
* JUnit-specified timeouts will work fine in combination with Spring
|
||||
* transactions. However, JUnit-specific timeouts still differ from
|
||||
* Spring-specific timeouts in that the former execute in a separate
|
||||
* thread while the latter simply execute in the main thread (like regular
|
||||
* tests).
|
||||
* @see #possiblyExpectingExceptions(FrameworkMethod, Object, Statement)
|
||||
* @see #withBefores(FrameworkMethod, Object, Statement)
|
||||
* @see #withAfters(FrameworkMethod, Object, Statement)
|
||||
* @see #withRulesReflectively(FrameworkMethod, Object, Statement)
|
||||
* @see #withPotentialRepeat(FrameworkMethod, Object, Statement)
|
||||
* @see #withPotentialTimeout(FrameworkMethod, Object, Statement)
|
||||
*/
|
||||
@@ -253,7 +254,6 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
Object testInstance;
|
||||
try {
|
||||
testInstance = new ReflectiveCallable() {
|
||||
|
||||
@Override
|
||||
protected Object runReflectiveCall() throws Throwable {
|
||||
return createTest();
|
||||
@@ -271,7 +271,6 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
statement = withRulesReflectively(frameworkMethod, testInstance, statement);
|
||||
statement = withPotentialRepeat(frameworkMethod, testInstance, statement);
|
||||
statement = withPotentialTimeout(frameworkMethod, testInstance, statement);
|
||||
|
||||
return statement;
|
||||
}
|
||||
|
||||
@@ -283,19 +282,19 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if {@link Ignore @Ignore} is present for the supplied
|
||||
* {@link FrameworkMethod test method} or if the test method is disabled via
|
||||
* {@code @IfProfileValue}.
|
||||
* Return {@code true} if {@link Ignore @Ignore} is present for the supplied
|
||||
* {@linkplain FrameworkMethod test method} or if the test method is disabled
|
||||
* via {@code @IfProfileValue}.
|
||||
* @see ProfileValueUtils#isTestEnabledInThisEnvironment(Method, Class)
|
||||
*/
|
||||
protected boolean isTestMethodIgnored(FrameworkMethod frameworkMethod) {
|
||||
Method method = frameworkMethod.getMethod();
|
||||
return (method.isAnnotationPresent(Ignore.class) || !ProfileValueUtils.isTestEnabledInThisEnvironment(method,
|
||||
getTestClass().getJavaClass()));
|
||||
return (method.isAnnotationPresent(Ignore.class) ||
|
||||
!ProfileValueUtils.isTestEnabledInThisEnvironment(method, getTestClass().getJavaClass()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the same logic as
|
||||
* Perform the same logic as
|
||||
* {@link BlockJUnit4ClassRunner#possiblyExpectingExceptions(FrameworkMethod, Object, Statement)}
|
||||
* except that the <em>expected exception</em> is retrieved using
|
||||
* {@link #getExpectedException(FrameworkMethod)}.
|
||||
@@ -303,29 +302,30 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
@Override
|
||||
protected Statement possiblyExpectingExceptions(FrameworkMethod frameworkMethod, Object testInstance, Statement next) {
|
||||
Class<? extends Throwable> expectedException = getExpectedException(frameworkMethod);
|
||||
return expectedException != null ? new ExpectException(next, expectedException) : next;
|
||||
return (expectedException != null ? new ExpectException(next, expectedException) : next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@code exception} that the supplied {@link FrameworkMethod
|
||||
* Get the {@code exception} that the supplied {@linkplain FrameworkMethod
|
||||
* test method} is expected to throw.
|
||||
* <p>Supports JUnit's {@link Test#expected() @Test(expected=...)} annotation.
|
||||
* <p>Can be overridden by subclasses.
|
||||
* @return the expected exception, or {@code null} if none was specified
|
||||
*/
|
||||
protected Class<? extends Throwable> getExpectedException(FrameworkMethod frameworkMethod) {
|
||||
Test testAnnotation = frameworkMethod.getAnnotation(Test.class);
|
||||
Class<? extends Throwable> junitExpectedException = (testAnnotation != null
|
||||
&& testAnnotation.expected() != Test.None.class ? testAnnotation.expected() : null);
|
||||
|
||||
return junitExpectedException;
|
||||
Test test = frameworkMethod.getAnnotation(Test.class);
|
||||
return (test != null && test.expected() != Test.None.class ? test.expected() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supports both Spring's {@link Timed @Timed} and JUnit's
|
||||
* {@link Test#timeout() @Test(timeout=...)} annotations, but not both
|
||||
* simultaneously. Returns either a {@link SpringFailOnTimeout}, a
|
||||
* {@link FailOnTimeout}, or the unmodified, supplied {@link Statement} as
|
||||
* appropriate.
|
||||
* Perform the same logic as
|
||||
* {@link BlockJUnit4ClassRunner#withPotentialTimeout(FrameworkMethod, Object, Statement)}
|
||||
* but with additional support for Spring's {@code @Timed} annotation.
|
||||
* <p>Supports both Spring's {@link org.springframework.test.annotation.Timed @Timed}
|
||||
* and JUnit's {@link Test#timeout() @Test(timeout=...)} annotations, but not both
|
||||
* simultaneously.
|
||||
* @return either a {@link SpringFailOnTimeout}, a {@link FailOnTimeout},
|
||||
* or the supplied {@link Statement} as appropriate
|
||||
* @see #getSpringTimeout(FrameworkMethod)
|
||||
* @see #getJUnitTimeout(FrameworkMethod)
|
||||
*/
|
||||
@@ -335,10 +335,9 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
long springTimeout = getSpringTimeout(frameworkMethod);
|
||||
long junitTimeout = getJUnitTimeout(frameworkMethod);
|
||||
if (springTimeout > 0 && junitTimeout > 0) {
|
||||
String msg = "Test method [" + frameworkMethod.getMethod()
|
||||
+ "] has been configured with Spring's @Timed(millis=" + springTimeout
|
||||
+ ") and JUnit's @Test(timeout=" + junitTimeout
|
||||
+ ") annotations. Only one declaration of a 'timeout' is permitted per test method.";
|
||||
String msg = String.format("Test method [%s] has been configured with Spring's @Timed(millis=%s) and " +
|
||||
"JUnit's @Test(timeout=%s) annotations, but only one declaration of a 'timeout' is " +
|
||||
"permitted per test method.", frameworkMethod.getMethod(), springTimeout, junitTimeout);
|
||||
logger.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
@@ -356,37 +355,37 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the configured JUnit {@code timeout} from the {@link Test @Test}
|
||||
* annotation on the supplied {@link FrameworkMethod test method}.
|
||||
* @return the timeout, or {@code 0} if none was specified.
|
||||
* Retrieve the configured JUnit {@code timeout} from the {@link Test @Test}
|
||||
* annotation on the supplied {@linkplain FrameworkMethod test method}.
|
||||
* @return the timeout, or {@code 0} if none was specified
|
||||
*/
|
||||
protected long getJUnitTimeout(FrameworkMethod frameworkMethod) {
|
||||
Test testAnnotation = frameworkMethod.getAnnotation(Test.class);
|
||||
return (testAnnotation != null && testAnnotation.timeout() > 0 ? testAnnotation.timeout() : 0);
|
||||
Test test = frameworkMethod.getAnnotation(Test.class);
|
||||
return (test != null && test.timeout() > 0 ? test.timeout() : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the configured Spring-specific {@code timeout} from the
|
||||
* {@link Timed @Timed} annotation on the supplied
|
||||
* {@link FrameworkMethod test method}.
|
||||
* @return the timeout, or {@code 0} if none was specified.
|
||||
* Retrieve the configured Spring-specific {@code timeout} from the
|
||||
* {@link org.springframework.test.annotation.Timed @Timed} annotation
|
||||
* on the supplied {@linkplain FrameworkMethod test method}.
|
||||
* @return the timeout, or {@code 0} if none was specified
|
||||
*/
|
||||
protected long getSpringTimeout(FrameworkMethod frameworkMethod) {
|
||||
AnnotationAttributes annAttrs = AnnotatedElementUtils.getAnnotationAttributes(frameworkMethod.getMethod(),
|
||||
Timed.class.getName());
|
||||
AnnotationAttributes annAttrs = AnnotatedElementUtils.getAnnotationAttributes(
|
||||
frameworkMethod.getMethod(), Timed.class.getName());
|
||||
if (annAttrs == null) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
long millis = annAttrs.<Long> getNumber("millis").longValue();
|
||||
return millis > 0 ? millis : 0;
|
||||
return (millis > 0 ? millis : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the {@link Statement} returned by the parent implementation with a
|
||||
* {@link RunBeforeTestMethodCallbacks} statement, thus preserving the
|
||||
* default functionality but adding support for the Spring TestContext
|
||||
* Wrap the {@link Statement} returned by the parent implementation with a
|
||||
* {@code RunBeforeTestMethodCallbacks} statement, thus preserving the
|
||||
* default functionality while adding support for the Spring TestContext
|
||||
* Framework.
|
||||
* @see RunBeforeTestMethodCallbacks
|
||||
*/
|
||||
@@ -394,13 +393,13 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
protected Statement withBefores(FrameworkMethod frameworkMethod, Object testInstance, Statement statement) {
|
||||
Statement junitBefores = super.withBefores(frameworkMethod, testInstance, statement);
|
||||
return new RunBeforeTestMethodCallbacks(junitBefores, testInstance, frameworkMethod.getMethod(),
|
||||
getTestContextManager());
|
||||
getTestContextManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the {@link Statement} returned by the parent implementation with a
|
||||
* {@link RunAfterTestMethodCallbacks} statement, thus preserving the
|
||||
* default functionality but adding support for the Spring TestContext
|
||||
* Wrap the {@link Statement} returned by the parent implementation with a
|
||||
* {@code RunAfterTestMethodCallbacks} statement, thus preserving the
|
||||
* default functionality while adding support for the Spring TestContext
|
||||
* Framework.
|
||||
* @see RunAfterTestMethodCallbacks
|
||||
*/
|
||||
@@ -408,13 +407,13 @@ public class SpringJUnit4ClassRunner extends BlockJUnit4ClassRunner {
|
||||
protected Statement withAfters(FrameworkMethod frameworkMethod, Object testInstance, Statement statement) {
|
||||
Statement junitAfters = super.withAfters(frameworkMethod, testInstance, statement);
|
||||
return new RunAfterTestMethodCallbacks(junitAfters, testInstance, frameworkMethod.getMethod(),
|
||||
getTestContextManager());
|
||||
getTestContextManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Supports Spring's {@link Repeat @Repeat} annotation by returning a
|
||||
* {@link SpringRepeat} statement initialized with the configured repeat
|
||||
* count or {@code 1} if no repeat count is configured.
|
||||
* Wrap the supplied {@link Statement} with a {@code SpringRepeat} statement.
|
||||
* <p>Supports Spring's {@link org.springframework.test.annotation.Repeat @Repeat}
|
||||
* annotation.
|
||||
* @see SpringRepeat
|
||||
*/
|
||||
protected Statement withPotentialRepeat(FrameworkMethod frameworkMethod, Object testInstance, Statement next) {
|
||||
|
||||
@@ -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.
|
||||
@@ -511,7 +511,7 @@ public abstract class AbstractPlatformTransactionManager implements PlatformTran
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a rae TransactionStatus instance for the given arguments.
|
||||
* Create a TransactionStatus instance for the given arguments.
|
||||
*/
|
||||
protected DefaultTransactionStatus newTransactionStatus(
|
||||
TransactionDefinition definition, Object transaction, boolean newTransaction,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* 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,
|
||||
@@ -785,7 +785,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
||||
try {
|
||||
return simpleDateFormat.parse(headerValue).getTime();
|
||||
}
|
||||
catch (ParseException e) {
|
||||
catch (ParseException ex) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
@@ -811,8 +811,8 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
||||
*/
|
||||
@Override
|
||||
public String getFirst(String headerName) {
|
||||
List<String> headerValues = headers.get(headerName);
|
||||
return headerValues != null ? headerValues.get(0) : null;
|
||||
List<String> headerValues = this.headers.get(headerName);
|
||||
return (headerValues != null ? headerValues.get(0) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -825,7 +825,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
||||
*/
|
||||
@Override
|
||||
public void add(String headerName, String headerValue) {
|
||||
List<String> headerValues = headers.get(headerName);
|
||||
List<String> headerValues = this.headers.get(headerName);
|
||||
if (headerValues == null) {
|
||||
headerValues = new LinkedList<String>();
|
||||
this.headers.put(headerName, headerValues);
|
||||
@@ -845,7 +845,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
||||
public void set(String headerName, String headerValue) {
|
||||
List<String> headerValues = new LinkedList<String>();
|
||||
headerValues.add(headerValue);
|
||||
headers.put(headerName, headerValues);
|
||||
this.headers.put(headerName, headerValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -858,7 +858,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
|
||||
@Override
|
||||
public Map<String, String> toSingleValueMap() {
|
||||
LinkedHashMap<String, String> singleValueMap = new LinkedHashMap<String,String>(this.headers.size());
|
||||
for (Entry<String, List<String>> entry : headers.entrySet()) {
|
||||
for (Entry<String, List<String>> entry : this.headers.entrySet()) {
|
||||
singleValueMap.put(entry.getKey(), entry.getValue().get(0));
|
||||
}
|
||||
return singleValueMap;
|
||||
|
||||
@@ -153,12 +153,14 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||
this.messageConverters.add(new AtomFeedHttpMessageConverter());
|
||||
this.messageConverters.add(new RssChannelHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jackson2XmlPresent) {
|
||||
messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
|
||||
this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
|
||||
}
|
||||
else if (jaxb2Present) {
|
||||
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jackson2Present) {
|
||||
this.messageConverters.add(new MappingJackson2HttpMessageConverter());
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -26,7 +26,6 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.support.WebDataBinderFactory;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
|
||||
@@ -61,7 +60,7 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu
|
||||
*/
|
||||
@Override
|
||||
public boolean supportsParameter(MethodParameter parameter) {
|
||||
return getArgumentResolver(parameter) != null;
|
||||
return (getArgumentResolver(parameter) != null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +72,9 @@ public class HandlerMethodArgumentResolverComposite implements HandlerMethodArgu
|
||||
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
|
||||
|
||||
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
|
||||
Assert.notNull(resolver, "Unknown parameter type [" + parameter.getParameterType().getName() + "]");
|
||||
if (resolver == null) {
|
||||
throw new IllegalArgumentException("Unknown parameter type [" + parameter.getParameterType().getName() + "]");
|
||||
}
|
||||
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 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.
|
||||
@@ -23,39 +23,36 @@ import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
/**
|
||||
* SPI for resolving custom return values from a specific handler method. Typically implemented to detect special return
|
||||
* types, resolving well-known result values for them.
|
||||
* SPI for resolving custom return values from a specific handler method.
|
||||
* Typically implemented to detect special return types, resolving
|
||||
* well-known result values for them.
|
||||
*
|
||||
* <p>A typical implementation could look like as follows:
|
||||
*
|
||||
* <pre class="code">
|
||||
* public class MyModelAndViewResolver implements ModelAndViewResolver {
|
||||
*
|
||||
* public ModelAndView resolveModelAndView(Method handlerMethod,
|
||||
* Class handlerType,
|
||||
* Object returnValue,
|
||||
* ExtendedModelMap implicitModel,
|
||||
* NativeWebRequest webRequest) {
|
||||
* if (returnValue instanceof MySpecialRetVal.class)) {
|
||||
* return new MySpecialRetVal(returnValue);
|
||||
* public ModelAndView resolveModelAndView(Method handlerMethod, Class handlerType,
|
||||
* Object returnValue, ExtendedModelMap implicitModel, NativeWebRequest webRequest) {
|
||||
* if (returnValue instanceof MySpecialRetVal.class)) {
|
||||
* return new MySpecialRetVal(returnValue);
|
||||
* }
|
||||
* return UNRESOLVED;
|
||||
* }
|
||||
* return UNRESOLVED;
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#setCustomModelAndViewResolvers
|
||||
* @see org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter#setCustomModelAndViewResolvers
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface ModelAndViewResolver {
|
||||
|
||||
/** Marker to be returned when the resolver does not know how to handle the given method parameter. */
|
||||
/**
|
||||
* Marker to be returned when the resolver does not know how to handle the given method parameter.
|
||||
*/
|
||||
ModelAndView UNRESOLVED = new ModelAndView();
|
||||
|
||||
ModelAndView resolveModelAndView(Method handlerMethod,
|
||||
Class<?> handlerType,
|
||||
Object returnValue,
|
||||
ExtendedModelMap implicitModel,
|
||||
NativeWebRequest webRequest);
|
||||
|
||||
ModelAndView resolveModelAndView(Method handlerMethod, Class<?> handlerType, Object returnValue,
|
||||
ExtendedModelMap implicitModel, NativeWebRequest webRequest);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 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.
|
||||
@@ -29,10 +29,13 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link org.springframework.web.servlet.HandlerExceptionResolver HandlerExceptionResolver}
|
||||
* interface that uses the {@link ResponseStatus @ResponseStatus} annotation to map exceptions to HTTP status codes.
|
||||
* A {@link org.springframework.web.servlet.HandlerExceptionResolver
|
||||
* HandlerExceptionResolver} that uses the {@link ResponseStatus @ResponseStatus}
|
||||
* annotation to map exceptions to HTTP status codes.
|
||||
*
|
||||
* <p>This exception resolver is enabled by default in the {@link org.springframework.web.servlet.DispatcherServlet}.
|
||||
* <p>This exception resolver is enabled by default in the
|
||||
* {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlet}
|
||||
* and the MVC Java config and the MVC namespace.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Rossen Stoyanchev
|
||||
@@ -48,6 +51,7 @@ public class ResponseStatusExceptionResolver extends AbstractHandlerExceptionRes
|
||||
this.messageSource = messageSource;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected ModelAndView doResolveException(HttpServletRequest request, HttpServletResponse response,
|
||||
Object handler, Exception ex) {
|
||||
@@ -65,16 +69,20 @@ public class ResponseStatusExceptionResolver extends AbstractHandlerExceptionRes
|
||||
}
|
||||
|
||||
/**
|
||||
* Template method that handles {@link ResponseStatus @ResponseStatus} annotation. <p>Default implementation send a
|
||||
* response error using {@link HttpServletResponse#sendError(int)}, or {@link HttpServletResponse#sendError(int,
|
||||
* String)} if the annotation has a {@linkplain ResponseStatus#reason() reason}. Returns an empty ModelAndView.
|
||||
* Template method that handles {@link ResponseStatus @ResponseStatus} annotation.
|
||||
* <p>The default implementation sends a response error using
|
||||
* {@link HttpServletResponse#sendError(int)} or
|
||||
* {@link HttpServletResponse#sendError(int, String)} if the annotation has a
|
||||
* {@linkplain ResponseStatus#reason() reason} and then returns an empty ModelAndView.
|
||||
* @param responseStatus the annotation
|
||||
* @param request current HTTP request
|
||||
* @param response current HTTP response
|
||||
* @param handler the executed handler, or {@code null} if none chosen at the time of the exception
|
||||
* (for example, if multipart resolution failed)
|
||||
* @param ex the exception that got thrown during handler execution
|
||||
* @return a corresponding ModelAndView to forward to, or {@code null} for default processing
|
||||
* @param handler the executed handler, or {@code null} if none chosen at the
|
||||
* time of the exception (for example, if multipart resolution failed)
|
||||
* @param ex the exception that got thrown during handler execution or the
|
||||
* exception that has the ResponseStatus annotation if found on the cause.
|
||||
* @return a corresponding ModelAndView to forward to, or {@code null}
|
||||
* for default processing
|
||||
*/
|
||||
protected ModelAndView resolveResponseStatus(ResponseStatus responseStatus, HttpServletRequest request,
|
||||
HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
||||
|
||||
@@ -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.
|
||||
@@ -103,8 +103,8 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
||||
List<String> fileExtensions) {
|
||||
|
||||
this.patterns = Collections.unmodifiableSet(prependLeadingSlash(patterns));
|
||||
this.pathHelper = urlPathHelper != null ? urlPathHelper : new UrlPathHelper();
|
||||
this.pathMatcher = pathMatcher != null ? pathMatcher : new AntPathMatcher();
|
||||
this.pathHelper = (urlPathHelper != null ? urlPathHelper : new UrlPathHelper());
|
||||
this.pathMatcher = (pathMatcher != null ? pathMatcher : new AntPathMatcher());
|
||||
this.useSuffixPatternMatch = useSuffixPatternMatch;
|
||||
this.useTrailingSlashMatch = useTrailingSlashMatch;
|
||||
if (fileExtensions != null) {
|
||||
@@ -220,7 +220,6 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
|
||||
* {@link #getMatchingCondition(javax.servlet.http.HttpServletRequest)}.
|
||||
* This method is provided as an alternative to be used if no request is available
|
||||
* (e.g. introspection, tooling, etc).
|
||||
*
|
||||
* @param lookupPath the lookup path to match to existing patterns
|
||||
* @return a collection of matching patterns sorted with the closest match at the top
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
@@ -31,13 +31,13 @@ import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondit
|
||||
/**
|
||||
* Encapsulates the following request mapping conditions:
|
||||
* <ol>
|
||||
* <li>{@link PatternsRequestCondition}
|
||||
* <li>{@link RequestMethodsRequestCondition}
|
||||
* <li>{@link ParamsRequestCondition}
|
||||
* <li>{@link HeadersRequestCondition}
|
||||
* <li>{@link ConsumesRequestCondition}
|
||||
* <li>{@link ProducesRequestCondition}
|
||||
* <li>{@code RequestCondition} (optional, custom request condition)
|
||||
* <li>{@link PatternsRequestCondition}
|
||||
* <li>{@link RequestMethodsRequestCondition}
|
||||
* <li>{@link ParamsRequestCondition}
|
||||
* <li>{@link HeadersRequestCondition}
|
||||
* <li>{@link ConsumesRequestCondition}
|
||||
* <li>{@link ProducesRequestCondition}
|
||||
* <li>{@code RequestCondition} (optional, custom request condition)
|
||||
* </ol>
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
@@ -266,21 +266,21 @@ public final class RequestMappingInfo implements RequestCondition<RequestMapping
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof RequestMappingInfo) {
|
||||
RequestMappingInfo other = (RequestMappingInfo) obj;
|
||||
return (this.patternsCondition.equals(other.patternsCondition) &&
|
||||
this.methodsCondition.equals(other.methodsCondition) &&
|
||||
this.paramsCondition.equals(other.paramsCondition) &&
|
||||
this.headersCondition.equals(other.headersCondition) &&
|
||||
this.consumesCondition.equals(other.consumesCondition) &&
|
||||
this.producesCondition.equals(other.producesCondition) &&
|
||||
this.customConditionHolder.equals(other.customConditionHolder));
|
||||
if (!(other instanceof RequestMappingInfo)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
RequestMappingInfo otherInfo = (RequestMappingInfo) other;
|
||||
return (this.patternsCondition.equals(otherInfo.patternsCondition) &&
|
||||
this.methodsCondition.equals(otherInfo.methodsCondition) &&
|
||||
this.paramsCondition.equals(otherInfo.paramsCondition) &&
|
||||
this.headersCondition.equals(otherInfo.headersCondition) &&
|
||||
this.consumesCondition.equals(otherInfo.consumesCondition) &&
|
||||
this.producesCondition.equals(otherInfo.producesCondition) &&
|
||||
this.customConditionHolder.equals(otherInfo.customConditionHolder));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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.
|
||||
@@ -26,13 +26,13 @@ import org.springframework.http.server.ServerHttpRequest;
|
||||
import org.springframework.http.server.ServerHttpResponse;
|
||||
|
||||
/**
|
||||
* A {@code ResponseBodyAdvice} implementation that adds support for
|
||||
* Jackson's {@code @JsonView} annotation declared on a Spring MVC
|
||||
* {@code @RequestMapping} or {@code @ExceptionHandler} method.
|
||||
* A {@link ResponseBodyAdvice} implementation that adds support for Jackson's
|
||||
* {@code @JsonView} annotation declared on a Spring MVC {@code @RequestMapping}
|
||||
* or {@code @ExceptionHandler} method.
|
||||
*
|
||||
* <p>The serialization view specified in the annotation will be passed in to
|
||||
* the {@code MappingJackson2HttpMessageConverter} which will then use it to
|
||||
* serialize the response body with.
|
||||
* <p>The serialization view specified in the annotation will be passed in to the
|
||||
* {@link org.springframework.http.converter.json.MappingJackson2HttpMessageConverter}
|
||||
* which will then use it to serialize the response body with.
|
||||
*
|
||||
* <p>Note that despite {@code @JsonView} allowing for more than one class to
|
||||
* be specified, the use for a response body advice is only supported with
|
||||
@@ -40,6 +40,7 @@ import org.springframework.http.server.ServerHttpResponse;
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.1
|
||||
* @see com.fasterxml.jackson.annotation.JsonView
|
||||
* @see com.fasterxml.jackson.databind.ObjectMapper#writerWithView(Class)
|
||||
*/
|
||||
public class JsonViewResponseBodyAdvice extends AbstractMappingJacksonResponseBodyAdvice {
|
||||
|
||||
@@ -99,13 +99,13 @@ import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* An {@link AbstractHandlerMethodAdapter} that supports {@link HandlerMethod}s
|
||||
* with the signature -- method argument and return types, defined in
|
||||
* with their method argument and return type signature, as defined via
|
||||
* {@code @RequestMapping}.
|
||||
*
|
||||
* <p>Support for custom argument and return value types can be added via
|
||||
* {@link #setCustomArgumentResolvers} and {@link #setCustomReturnValueHandlers}.
|
||||
* Or alternatively to re-configure all argument and return value types use
|
||||
* {@link #setArgumentResolvers} and {@link #setReturnValueHandlers(List)}.
|
||||
* Or alternatively, to re-configure all argument and return value types,
|
||||
* use {@link #setArgumentResolvers} and {@link #setReturnValueHandlers}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 3.1
|
||||
@@ -697,12 +697,12 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
if (session != null) {
|
||||
Object mutex = WebUtils.getSessionMutex(session);
|
||||
synchronized (mutex) {
|
||||
return invokeHandleMethod(request, response, handlerMethod);
|
||||
return invokeHandlerMethod(request, response, handlerMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return invokeHandleMethod(request, response, handlerMethod);
|
||||
return invokeHandlerMethod(request, response, handlerMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -739,8 +739,8 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
* Invoke the {@link RequestMapping} handler method preparing a {@link ModelAndView}
|
||||
* if view resolution is required.
|
||||
*/
|
||||
private ModelAndView invokeHandleMethod(HttpServletRequest request,
|
||||
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
|
||||
private ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response,
|
||||
HandlerMethod handlerMethod) throws Exception {
|
||||
|
||||
ServletWebRequest webRequest = new ServletWebRequest(request, response);
|
||||
|
||||
@@ -756,7 +756,7 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
|
||||
asyncWebRequest.setTimeout(this.asyncRequestTimeout);
|
||||
|
||||
final WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
|
||||
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
|
||||
asyncManager.setTaskExecutor(this.taskExecutor);
|
||||
asyncManager.setAsyncWebRequest(asyncWebRequest);
|
||||
asyncManager.registerCallableInterceptors(this.callableInterceptors);
|
||||
@@ -766,7 +766,6 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
Object result = asyncManager.getConcurrentResult();
|
||||
mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
|
||||
asyncManager.clearConcurrentResult();
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found concurrent result value [" + result + "]");
|
||||
}
|
||||
@@ -774,7 +773,6 @@ public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter
|
||||
}
|
||||
|
||||
requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
|
||||
|
||||
if (asyncManager.isConcurrentHandlingStarted()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -127,7 +127,6 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Whether to use suffix pattern matching.
|
||||
*/
|
||||
@@ -229,7 +228,8 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
||||
}
|
||||
|
||||
/**
|
||||
* Created a RequestMappingInfo from a RequestMapping annotation.
|
||||
* Create a {@link RequestMappingInfo} from the supplied
|
||||
* {@link RequestMapping @RequestMapping} annotation.
|
||||
*/
|
||||
protected RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, RequestCondition<?> customCondition) {
|
||||
String[] patterns = resolveEmbeddedValuesInPatterns(annotation.value());
|
||||
|
||||
@@ -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.
|
||||
@@ -19,9 +19,9 @@ package org.springframework.web.servlet.view.groovy;
|
||||
import groovy.text.markup.MarkupTemplateEngine;
|
||||
|
||||
/**
|
||||
* Interface to be implemented by objects that configure and manage a
|
||||
* Groovy MarkupTemplateEngine for automatic lookup in a web environment.
|
||||
* Detected and used by GroovyMarkupView.
|
||||
* Interface to be implemented by objects that configure and manage a Groovy
|
||||
* {@link MarkupTemplateEngine} for automatic lookup in a web environment.
|
||||
* Detected and used by {@link GroovyMarkupView}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @since 4.1
|
||||
|
||||
@@ -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.
|
||||
@@ -46,7 +46,6 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @Bean
|
||||
* public GroovyMarkupConfig groovyMarkupConfigurer() {
|
||||
*
|
||||
* GroovyMarkupConfigurer configurer = new GroovyMarkupConfigurer();
|
||||
* configurer.setResourceLoaderPath("classpath:/WEB-INF/groovymarkup/");
|
||||
* return configurer;
|
||||
@@ -79,7 +78,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.1
|
||||
* @see GroovyMarkupView
|
||||
* @see <a href="http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html">
|
||||
* @see <a href="http://groovy-lang.org/templating.html#_the_markuptemplateengine">
|
||||
* Groovy Markup Template engine documentation</a>
|
||||
*/
|
||||
public class GroovyMarkupConfigurer extends TemplateConfiguration
|
||||
|
||||
@@ -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.
|
||||
@@ -35,8 +35,7 @@ import org.springframework.web.servlet.view.AbstractTemplateView;
|
||||
import org.springframework.web.util.NestedServletException;
|
||||
|
||||
/**
|
||||
* An {@link org.springframework.web.servlet.view.AbstractTemplateView AbstractTemplateView}
|
||||
* based on Groovy XML/XHTML markup templates.
|
||||
* An {@link AbstractTemplateView} subclass based on Groovy XML/XHTML markup templates.
|
||||
*
|
||||
* <p>Spring's Groovy Markup Template support requires Groovy 2.3.1 and higher.
|
||||
*
|
||||
@@ -45,7 +44,7 @@ import org.springframework.web.util.NestedServletException;
|
||||
* @since 4.1
|
||||
* @see GroovyMarkupViewResolver
|
||||
* @see GroovyMarkupConfigurer
|
||||
* @see <a href="http://beta.groovy-lang.org/docs/groovy-2.3.2/html/documentation/markup-template-engine.html">
|
||||
* @see <a href="http://groovy-lang.org/templating.html#_the_markuptemplateengine">
|
||||
* Groovy Markup Template engine documentation</a>
|
||||
*/
|
||||
public class GroovyMarkupView extends AbstractTemplateView {
|
||||
|
||||
@@ -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.
|
||||
@@ -21,10 +21,9 @@ import java.util.Locale;
|
||||
import org.springframework.web.servlet.view.AbstractTemplateViewResolver;
|
||||
|
||||
/**
|
||||
* Convenience subclass of
|
||||
* {@link org.springframework.web.servlet.view.AbstractTemplateViewResolver}
|
||||
* that supports {@link GroovyMarkupView} (i.e. Groovy XML/XHTML markup templates)
|
||||
* and custom subclasses of it.
|
||||
* Convenience subclass of @link AbstractTemplateViewResolver} that supports
|
||||
* {@link GroovyMarkupView} (i.e. Groovy XML/XHTML markup templates) and
|
||||
* custom subclasses of it.
|
||||
*
|
||||
* <p>The view class for all views created by this resolver can be specified
|
||||
* via the {@link #setViewClass(Class)} property.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Support classes for the integration of
|
||||
* <a href="http://beta.groovy-lang.org/docs/groovy-2.3.0/html/documentation/markup-template-engine.html">
|
||||
* <a href="http://docs.groovy-lang.org/docs/next/html/documentation/template-engines.html#_the_markuptemplateengine">
|
||||
* Groovy Templates</a> as Spring web view technology.
|
||||
* Contains a View implementation for Groovy templates.
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.web.socket.sockjs.client;
|
||||
|
||||
import java.net.URI;
|
||||
@@ -15,10 +31,9 @@ public interface InfoReceiver {
|
||||
/**
|
||||
* Perform an HTTP request to the SockJS "Info" URL.
|
||||
* and return the resulting JSON response content, or raise an exception.
|
||||
*
|
||||
* @param infoUrl the URL to obtain SockJS server information from
|
||||
* @return the body of the response
|
||||
*/
|
||||
String executeInfoRequest(URI infoUrl);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -13,8 +13,8 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.web.socket.sockjs.client;
|
||||
|
||||
package org.springframework.web.socket.sockjs.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -40,7 +40,6 @@ public interface Transport {
|
||||
|
||||
/**
|
||||
* Connect the transport.
|
||||
*
|
||||
* @param request the transport request.
|
||||
* @param webSocketHandler the application handler to delegate lifecycle events to.
|
||||
* @return a future to indicate success or failure to connect.
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.web.socket.sockjs.client;
|
||||
|
||||
import java.net.URI;
|
||||
@@ -8,8 +24,7 @@ import org.springframework.web.socket.TextMessage;
|
||||
* A SockJS {@link Transport} that uses HTTP requests to simulate a WebSocket
|
||||
* interaction. The {@code connect} method of the base {@code Transport} interface
|
||||
* is used to receive messages from the server while the
|
||||
* {@link #executeSendRequest(java.net.URI, org.springframework.web.socket.TextMessage)
|
||||
* executeSendRequest(URI, TextMessage)} method here is used to send messages.
|
||||
* {@link #executeSendRequest} method here is used to send messages.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 4.1
|
||||
@@ -20,7 +35,6 @@ public interface XhrTransport extends Transport, InfoReceiver {
|
||||
* An {@code XhrTransport} supports both the "xhr_streaming" and "xhr" SockJS
|
||||
* server transports. From a client perspective there is no implementation
|
||||
* difference.
|
||||
*
|
||||
* <p>By default an {@code XhrTransport} will be used with "xhr_streaming"
|
||||
* first and then with "xhr", if the streaming fails to connect. In some
|
||||
* cases it may be useful to suppress streaming so that only "xhr" is used.
|
||||
|
||||
@@ -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.
|
||||
@@ -83,13 +83,12 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedConfigClasses() {
|
||||
return new Class<?>[] { TestMessageBrokerConfiguration.class, TestMessageBrokerConfigurer.class };
|
||||
return new Class<?>[] {TestMessageBrokerConfiguration.class, TestMessageBrokerConfigurer.class};
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void sendMessageToController() throws Exception {
|
||||
|
||||
TextMessage message = create(StompCommand.SEND).headers("destination:/app/simple").build();
|
||||
WebSocketSession session = doHandshake(new TestClientWebSocketHandler(0, message), "/ws").get();
|
||||
|
||||
@@ -104,10 +103,8 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
|
||||
@Test
|
||||
public void sendMessageToControllerAndReceiveReplyViaTopic() throws Exception {
|
||||
|
||||
TextMessage message1 = create(StompCommand.SUBSCRIBE)
|
||||
.headers("id:subs1", "destination:/topic/increment").build();
|
||||
|
||||
TextMessage message2 = create(StompCommand.SEND)
|
||||
.headers("destination:/app/increment").body("5").build();
|
||||
|
||||
@@ -126,7 +123,6 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
|
||||
@Test
|
||||
public void sendMessageToBrokerAndReceiveReplyViaTopic() throws Exception {
|
||||
|
||||
TextMessage m1 = create(StompCommand.SUBSCRIBE).headers("id:subs1", "destination:/topic/foo").build();
|
||||
TextMessage m2 = create(StompCommand.SEND).headers("destination:/topic/foo").body("5").build();
|
||||
|
||||
@@ -148,7 +144,6 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
|
||||
@Test
|
||||
public void sendSubscribeToControllerAndReceiveReply() throws Exception {
|
||||
|
||||
String destHeader = "destination:/app/number";
|
||||
TextMessage message = create(StompCommand.SUBSCRIBE).headers("id:subs1", destHeader).build();
|
||||
|
||||
@@ -168,7 +163,6 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
|
||||
@Test
|
||||
public void handleExceptionAndSendToUser() throws Exception {
|
||||
|
||||
String destHeader = "destination:/user/queue/error";
|
||||
TextMessage m1 = create(StompCommand.SUBSCRIBE).headers("id:subs1", destHeader).build();
|
||||
TextMessage m2 = create(StompCommand.SEND).headers("destination:/app/exception").build();
|
||||
@@ -178,7 +172,6 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
|
||||
try {
|
||||
assertTrue(clientHandler.latch.await(2, TimeUnit.SECONDS));
|
||||
|
||||
String payload = clientHandler.actual.get(0).getPayload();
|
||||
assertTrue(payload.startsWith("MESSAGE\n"));
|
||||
assertTrue(payload.contains("destination:/user/queue/error\n"));
|
||||
@@ -191,10 +184,8 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
|
||||
@Test
|
||||
public void webSocketScope() throws Exception {
|
||||
|
||||
TextMessage message1 = create(StompCommand.SUBSCRIBE)
|
||||
.headers("id:subs1", "destination:/topic/scopedBeanValue").build();
|
||||
|
||||
TextMessage message2 = create(StompCommand.SEND)
|
||||
.headers("destination:/app/scopedBeanValue").build();
|
||||
|
||||
@@ -203,7 +194,6 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
|
||||
try {
|
||||
assertTrue(clientHandler.latch.await(2, TimeUnit.SECONDS));
|
||||
|
||||
String payload = clientHandler.actual.get(0).getPayload();
|
||||
assertTrue(payload.startsWith("MESSAGE\n"));
|
||||
assertTrue(payload.contains("destination:/topic/scopedBeanValue\n"));
|
||||
@@ -221,6 +211,7 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
private @interface IntegrationTestController {
|
||||
}
|
||||
|
||||
|
||||
@IntegrationTestController
|
||||
static class SimpleController {
|
||||
|
||||
@@ -243,6 +234,7 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IntegrationTestController
|
||||
static class IncrementController {
|
||||
|
||||
@@ -257,6 +249,7 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IntegrationTestController
|
||||
static class ScopedBeanController {
|
||||
|
||||
@@ -279,6 +272,7 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
String getValue();
|
||||
}
|
||||
|
||||
|
||||
static class ScopedBeanImpl implements ScopedBean {
|
||||
|
||||
private final String value;
|
||||
@@ -304,7 +298,6 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
|
||||
private final CountDownLatch latch;
|
||||
|
||||
|
||||
public TestClientWebSocketHandler(int expectedNumberOfMessages, TextMessage... messagesToSend) {
|
||||
this.messagesToSend = messagesToSend;
|
||||
this.expected = expectedNumberOfMessages;
|
||||
@@ -325,6 +318,7 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@ComponentScan(
|
||||
basePackageClasses=StompWebSocketIntegrationTests.class,
|
||||
@@ -333,7 +327,7 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
static class TestMessageBrokerConfigurer extends AbstractWebSocketMessageBrokerConfigurer {
|
||||
|
||||
@Autowired
|
||||
private HandshakeHandler handshakeHandler; // can't rely on classpath for server detection
|
||||
private HandshakeHandler handshakeHandler; // can't rely on classpath for server detection
|
||||
|
||||
@Override
|
||||
public void registerStompEndpoints(StompEndpointRegistry registry) {
|
||||
@@ -353,19 +347,20 @@ public class StompWebSocketIntegrationTests extends AbstractWebSocketIntegration
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class TestMessageBrokerConfiguration extends DelegatingWebSocketMessageBrokerConfiguration {
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public AbstractSubscribableChannel clientInboundChannel() {
|
||||
return new ExecutorSubscribableChannel(); // synchronous
|
||||
return new ExecutorSubscribableChannel(); // synchronous
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean
|
||||
public AbstractSubscribableChannel clientOutboundChannel() {
|
||||
return new ExecutorSubscribableChannel(); // synchronous
|
||||
return new ExecutorSubscribableChannel(); // synchronous
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user