Detect Reactive web applications
This commit improves `@ConditionalOnWebApplication` to specify the requested web application type. By default, any web application will match but it can also match only if a recactive (or servlet) web application is present. Closes gh-8118
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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,12 @@ import java.lang.annotation.Target;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
|
||||
/**
|
||||
* {@link Conditional} that only matches when the application context is a web application
|
||||
* context.
|
||||
* {@link Conditional} that matches when the application is a web application. By default,
|
||||
* any web application will match but it can be narrowed using the {@link #type()}
|
||||
* attribute.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Target({ ElementType.TYPE, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@@ -36,4 +38,32 @@ import org.springframework.context.annotation.Conditional;
|
||||
@Conditional(OnWebApplicationCondition.class)
|
||||
public @interface ConditionalOnWebApplication {
|
||||
|
||||
/**
|
||||
* The required type of the web application.
|
||||
* @return the required web application type
|
||||
*/
|
||||
Type type() default Type.ANY;
|
||||
|
||||
/**
|
||||
* Available application types.
|
||||
*/
|
||||
enum Type {
|
||||
|
||||
/**
|
||||
* Any web application will match.
|
||||
*/
|
||||
ANY,
|
||||
|
||||
/**
|
||||
* Only servlet-based web application will match.
|
||||
*/
|
||||
SERVLET,
|
||||
|
||||
/**
|
||||
* Only reactive-based web application will match.
|
||||
*/
|
||||
REACTIVE
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.condition;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.context.embedded.ReactiveWebApplicationContext;
|
||||
import org.springframework.context.annotation.Condition;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.core.Ordered;
|
||||
@@ -59,6 +63,35 @@ class OnWebApplicationCondition extends SpringBootCondition {
|
||||
AnnotatedTypeMetadata metadata, boolean required) {
|
||||
ConditionMessage.Builder message = ConditionMessage.forCondition(
|
||||
ConditionalOnWebApplication.class, required ? "(required)" : "");
|
||||
Type type = deduceType(metadata);
|
||||
if (Type.SERVLET == type) {
|
||||
return isServletWebApplication(context);
|
||||
}
|
||||
else if (Type.REACTIVE == type) {
|
||||
return isReactiveWebApplication(context);
|
||||
}
|
||||
else {
|
||||
ConditionOutcome servletOutcome = isServletWebApplication(context);
|
||||
if (servletOutcome.isMatch() && required) {
|
||||
return new ConditionOutcome(servletOutcome.isMatch(),
|
||||
message.because(servletOutcome.getMessage()));
|
||||
}
|
||||
ConditionOutcome reactiveOutcome = isReactiveWebApplication(context);
|
||||
if (reactiveOutcome.isMatch() && required) {
|
||||
return new ConditionOutcome(reactiveOutcome.isMatch(),
|
||||
message.because(reactiveOutcome.getMessage()));
|
||||
}
|
||||
boolean finalOutcome = (required ?
|
||||
servletOutcome.isMatch() && reactiveOutcome.isMatch() :
|
||||
servletOutcome.isMatch() || reactiveOutcome.isMatch());
|
||||
return new ConditionOutcome(finalOutcome, message.because(
|
||||
servletOutcome.getMessage()).append("and").append(
|
||||
reactiveOutcome.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
private ConditionOutcome isServletWebApplication(ConditionContext context) {
|
||||
ConditionMessage.Builder message = ConditionMessage.forCondition("");
|
||||
if (!ClassUtils.isPresent(WEB_CONTEXT_CLASS, context.getClassLoader())) {
|
||||
return ConditionOutcome
|
||||
.noMatch(message.didNotFind("web application classes").atAll());
|
||||
@@ -76,7 +109,26 @@ class OnWebApplicationCondition extends SpringBootCondition {
|
||||
if (context.getResourceLoader() instanceof WebApplicationContext) {
|
||||
return ConditionOutcome.match(message.foundExactly("WebApplicationContext"));
|
||||
}
|
||||
return ConditionOutcome.noMatch(message.because("not a web application"));
|
||||
return ConditionOutcome.noMatch(message.because("not a servlet web application"));
|
||||
}
|
||||
|
||||
private ConditionOutcome isReactiveWebApplication(ConditionContext context) {
|
||||
ConditionMessage.Builder message = ConditionMessage.forCondition("");
|
||||
if (context.getResourceLoader() instanceof ReactiveWebApplicationContext) {
|
||||
return ConditionOutcome.match(
|
||||
message.foundExactly("ReactiveWebApplicationContext"));
|
||||
}
|
||||
return ConditionOutcome.noMatch(message.because(
|
||||
"not a reactive web application"));
|
||||
}
|
||||
|
||||
private Type deduceType(AnnotatedTypeMetadata metadata) {
|
||||
Map<String, Object> attributes = metadata.getAnnotationAttributes(
|
||||
ConditionalOnWebApplication.class.getName());
|
||||
if (attributes != null) {
|
||||
return (Type) attributes.get("type");
|
||||
}
|
||||
return Type.ANY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -16,56 +16,76 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.condition;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.context.embedded.ReactiveWebApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConditionalOnNotWebApplication}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Dave Syer$
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class ConditionalOnNotWebApplicationTests {
|
||||
|
||||
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@After
|
||||
public void closeContext() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWebApplication() {
|
||||
this.context.register(BasicConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.containsBean("foo")).isTrue();
|
||||
assertThat(this.context.getBean("foo")).isEqualTo("foo");
|
||||
public void testNotWebApplicationWithServletContext() {
|
||||
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
|
||||
ctx.register(NotWebApplicationConfiguration.class);
|
||||
ctx.setServletContext(new MockServletContext());
|
||||
ctx.refresh();
|
||||
|
||||
this.context = ctx;
|
||||
assertThat(this.context.getBeansOfType(String.class)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotWebApplicationWithReactiveContext() {
|
||||
ReactiveWebApplicationContext ctx = new ReactiveWebApplicationContext();
|
||||
ctx.register(NotWebApplicationConfiguration.class);
|
||||
ctx.refresh();
|
||||
|
||||
this.context = ctx;
|
||||
assertThat(this.context.getBeansOfType(String.class)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotWebApplication() {
|
||||
this.context.register(MissingConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.containsBean("foo")).isFalse();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnWebApplication
|
||||
protected static class MissingConfiguration {
|
||||
|
||||
@Bean
|
||||
public String bar() {
|
||||
return "bar";
|
||||
}
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(NotWebApplicationConfiguration.class);
|
||||
ctx.refresh();
|
||||
|
||||
this.context = ctx;
|
||||
assertThat(this.context.getBeansOfType(String.class)).containsExactly(
|
||||
entry("none", "none"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnNotWebApplication
|
||||
protected static class BasicConfiguration {
|
||||
protected static class NotWebApplicationConfiguration {
|
||||
|
||||
@Bean
|
||||
public String foo() {
|
||||
return "foo";
|
||||
public String none() {
|
||||
return "none";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
* Copyright 2012-2017 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.
|
||||
@@ -16,59 +16,106 @@
|
||||
|
||||
package org.springframework.boot.autoconfigure.condition;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
|
||||
import org.springframework.boot.context.embedded.ReactiveWebApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
|
||||
/**
|
||||
* Tests for {@link ConditionalOnWebApplication}.
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
public class ConditionalOnWebApplicationTests {
|
||||
|
||||
private final AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
private ConfigurableApplicationContext context;
|
||||
|
||||
@Test
|
||||
public void testWebApplication() {
|
||||
this.context.register(BasicConfiguration.class);
|
||||
this.context.setServletContext(new MockServletContext());
|
||||
this.context.refresh();
|
||||
assertThat(this.context.containsBean("foo")).isTrue();
|
||||
assertThat(this.context.getBean("foo")).isEqualTo("foo");
|
||||
@After
|
||||
public void closeContext() {
|
||||
if (this.context != null) {
|
||||
this.context.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotWebApplication() {
|
||||
this.context.register(MissingConfiguration.class);
|
||||
this.context.setServletContext(new MockServletContext());
|
||||
this.context.refresh();
|
||||
assertThat(this.context.containsBean("foo")).isFalse();
|
||||
public void testWebApplicationWithServletContext() {
|
||||
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
|
||||
ctx.register(AnyWebApplicationConfiguration.class,
|
||||
ServletWebApplicationConfiguration.class,
|
||||
ReactiveWebApplicationConfiguration.class);
|
||||
ctx.setServletContext(new MockServletContext());
|
||||
ctx.refresh();
|
||||
|
||||
this.context = ctx;
|
||||
assertThat(this.context.getBeansOfType(String.class)).containsExactly(
|
||||
entry("any", "any"), entry("servlet", "servlet"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWebApplicationWithReactiveContext() {
|
||||
ReactiveWebApplicationContext ctx = new ReactiveWebApplicationContext();
|
||||
ctx.register(AnyWebApplicationConfiguration.class,
|
||||
ServletWebApplicationConfiguration.class,
|
||||
ReactiveWebApplicationConfiguration.class);
|
||||
ctx.refresh();
|
||||
|
||||
this.context = ctx;
|
||||
assertThat(this.context.getBeansOfType(String.class)).containsExactly(
|
||||
entry("any", "any"), entry("reactive", "reactive"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonWebApplication() {
|
||||
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.register(AnyWebApplicationConfiguration.class,
|
||||
ServletWebApplicationConfiguration.class,
|
||||
ReactiveWebApplicationConfiguration.class);
|
||||
ctx.refresh();
|
||||
|
||||
this.context = ctx;
|
||||
assertThat(this.context.getBeansOfType(String.class)).isEmpty();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnNotWebApplication
|
||||
protected static class MissingConfiguration {
|
||||
@ConditionalOnWebApplication
|
||||
protected static class AnyWebApplicationConfiguration {
|
||||
|
||||
@Bean
|
||||
public String bar() {
|
||||
return "bar";
|
||||
public String any() {
|
||||
return "any";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnWebApplication
|
||||
protected static class BasicConfiguration {
|
||||
@ConditionalOnWebApplication(type = Type.SERVLET)
|
||||
protected static class ServletWebApplicationConfiguration {
|
||||
|
||||
@Bean
|
||||
public String foo() {
|
||||
return "foo";
|
||||
public String servlet() {
|
||||
return "servlet";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnWebApplication(type = Type.REACTIVE)
|
||||
protected static class ReactiveWebApplicationConfiguration {
|
||||
|
||||
@Bean
|
||||
public String reactive() {
|
||||
return "reactive";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -171,7 +171,8 @@ public class AutoConfigurationReportLoggingInitializerTests {
|
||||
}
|
||||
// Just basic sanity check, test is for visual inspection
|
||||
String l = this.debugLog.get(0);
|
||||
assertThat(l).contains("not a web application (OnWebApplicationCondition)");
|
||||
assertThat(l).contains(
|
||||
"not a servlet web application (OnWebApplicationCondition)");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user