Support Spring Mobile for all template engines

Previously, Spring Mobile was only supported for Thymeleaf and JSPs. This
commit improves the auto-configuration to also provide device delegating
support for Freemarker, Groovy Templates and Mustache.

Closes gh-5140
This commit is contained in:
Stephane Nicoll 2016-06-28 16:16:34 +02:00
parent 6dd8e71d06
commit c024dc836a
3 changed files with 252 additions and 208 deletions

View File

@ -16,27 +16,27 @@
package org.springframework.boot.autoconfigure.mobile; package org.springframework.boot.autoconfigure.mobile;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.thymeleaf.spring4.view.ThymeleafViewResolver; import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration;
import org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration;
import org.springframework.boot.autoconfigure.mustache.web.MustacheViewResolver;
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration; import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.mobile.device.view.LiteDeviceDelegatingViewResolver; import org.springframework.mobile.device.view.LiteDeviceDelegatingViewResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import org.springframework.web.servlet.view.groovy.GroovyMarkupViewResolver;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Mobile's * {@link EnableAutoConfiguration Auto-configuration} for Spring Mobile's
@ -45,102 +45,96 @@ import org.springframework.web.servlet.view.InternalResourceViewResolver;
* {@link InternalResourceViewResolver} is used as a fallback. * {@link InternalResourceViewResolver} is used as a fallback.
* *
* @author Roy Clarkson * @author Roy Clarkson
* @author Stephane Nicoll
* @since 1.1.0 * @since 1.1.0
*/ */
@Configuration @Configuration
@ConditionalOnWebApplication @ConditionalOnWebApplication
@ConditionalOnClass(LiteDeviceDelegatingViewResolver.class) @ConditionalOnClass(LiteDeviceDelegatingViewResolver.class)
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, ThymeleafAutoConfiguration.class }) @ConditionalOnProperty(prefix = "spring.mobile.devicedelegatingviewresolver", name = "enabled", havingValue = "true")
@EnableConfigurationProperties(DeviceDelegatingViewResolverProperties.class)
@AutoConfigureAfter({WebMvcAutoConfiguration.class, FreeMarkerAutoConfiguration.class,
GroovyTemplateAutoConfiguration.class, MustacheAutoConfiguration.class,
ThymeleafAutoConfiguration.class})
public class DeviceDelegatingViewResolverAutoConfiguration { public class DeviceDelegatingViewResolverAutoConfiguration {
private static final Log logger = LogFactory
.getLog(DeviceDelegatingViewResolverAutoConfiguration.class);
private static abstract class AbstractDelegateConfiguration {
@Autowired
private DeviceDelegatingViewResolverProperties viewResolverProperties;
protected LiteDeviceDelegatingViewResolver getConfiguredViewResolver(
ViewResolver delegate, int delegateOrder) {
LiteDeviceDelegatingViewResolver resolver = new LiteDeviceDelegatingViewResolver(
delegate);
resolver.setEnableFallback(this.viewResolverProperties.isEnableFallback());
resolver.setNormalPrefix(this.viewResolverProperties.getNormalPrefix());
resolver.setNormalSuffix(this.viewResolverProperties.getNormalSuffix());
resolver.setMobilePrefix(this.viewResolverProperties.getMobilePrefix());
resolver.setMobileSuffix(this.viewResolverProperties.getMobileSuffix());
resolver.setTabletPrefix(this.viewResolverProperties.getTabletPrefix());
resolver.setTabletSuffix(this.viewResolverProperties.getTabletSuffix());
resolver.setOrder(getAdjustedOrder(delegateOrder));
return resolver;
}
private int getAdjustedOrder(int order) {
if (order == Ordered.HIGHEST_PRECEDENCE) {
return Ordered.HIGHEST_PRECEDENCE;
}
// The view resolver must be ordered higher than the delegate view
// resolver, otherwise the view names will not be adjusted
return order - 1;
}
}
@Configuration @Configuration
@EnableConfigurationProperties(DeviceDelegatingViewResolverProperties.class) protected static class LiteDeviceDelegatingViewResolverFactoryConfiguration {
@ConditionalOnMissingBean(name = "deviceDelegatingViewResolver")
@ConditionalOnProperty(prefix = "spring.mobile.devicedelegatingviewresolver", name = "enabled", havingValue = "true", matchIfMissing = false)
protected static class DeviceDelegatingViewResolverConfiguration {
@Configuration
@ConditionalOnBean(name = "thymeleafViewResolver")
protected static class ThymeleafViewResolverViewResolverDelegateConfiguration
extends AbstractDelegateConfiguration {
private final ThymeleafViewResolver viewResolver;
protected ThymeleafViewResolverViewResolverDelegateConfiguration(
ThymeleafViewResolver viewResolver) {
this.viewResolver = viewResolver;
}
@Bean @Bean
public LiteDeviceDelegatingViewResolver deviceDelegatingViewResolver() { public DeviceDelegatingViewResolverFactory deviceDelegatingViewResolverFactory(
if (logger.isDebugEnabled()) { DeviceDelegatingViewResolverProperties properties) {
logger.debug("LiteDeviceDelegatingViewResolver delegates to " return new DeviceDelegatingViewResolverFactory(properties);
+ "ThymeleafViewResolver");
}
return getConfiguredViewResolver(this.viewResolver,
this.viewResolver.getOrder());
} }
} }
@Configuration @Configuration
@EnableConfigurationProperties(DeviceDelegatingViewResolverProperties.class) @ConditionalOnClass(FreeMarkerViewResolver.class)
@ConditionalOnMissingBean(name = "thymeleafViewResolver") protected static class DeviceDelegatingFreemarkerViewResolverConfiguration {
@Bean
@ConditionalOnBean(FreeMarkerViewResolver.class)
public LiteDeviceDelegatingViewResolver deviceDelegatingFreemarkerViewResolver(
DeviceDelegatingViewResolverFactory factory,
FreeMarkerViewResolver viewResolver) {
return factory.createViewResolver(viewResolver);
}
}
@Configuration
@ConditionalOnClass(GroovyMarkupViewResolver.class)
protected static class DeviceDelegatingGroovyMarkupViewResolverConfiguration {
@Bean
@ConditionalOnBean(GroovyMarkupViewResolver.class)
public LiteDeviceDelegatingViewResolver deviceDelegatingGroovyMarkupViewResolver(
DeviceDelegatingViewResolverFactory factory,
GroovyMarkupViewResolver viewResolver) {
return factory.createViewResolver(viewResolver);
}
}
@Configuration
@ConditionalOnClass(InternalResourceViewResolver.class)
protected static class DeviceDelegatingJspViewResolverConfiguration {
@Bean
@ConditionalOnBean(InternalResourceViewResolver.class) @ConditionalOnBean(InternalResourceViewResolver.class)
protected static class InternalResourceViewResolverDelegateConfiguration public LiteDeviceDelegatingViewResolver deviceDelegatingJspViewResolver(
extends AbstractDelegateConfiguration { DeviceDelegatingViewResolverFactory factory,
private final InternalResourceViewResolver viewResolver;
protected InternalResourceViewResolverDelegateConfiguration(
InternalResourceViewResolver viewResolver) { InternalResourceViewResolver viewResolver) {
this.viewResolver = viewResolver; return factory.createViewResolver(viewResolver);
} }
}
@Configuration
@ConditionalOnClass(MustacheViewResolver.class)
protected static class DeviceDelegatingMustacheViewResolverConfiguration {
@Bean @Bean
public LiteDeviceDelegatingViewResolver deviceDelegatingViewResolver() { @ConditionalOnBean(MustacheViewResolver.class)
if (logger.isDebugEnabled()) { public LiteDeviceDelegatingViewResolver deviceDelegatingMustacheViewResolver(
logger.debug("LiteDeviceDelegatingViewResolver delegates to " DeviceDelegatingViewResolverFactory factory,
+ "InternalResourceViewResolver"); MustacheViewResolver viewResolver) {
return factory.createViewResolver(viewResolver);
} }
return getConfiguredViewResolver(this.viewResolver,
this.viewResolver.getOrder()); }
}
@Configuration
@ConditionalOnClass(ThymeleafViewResolver.class)
protected static class DeviceDelegatingThymeleafViewResolverConfiguration {
@Bean
@ConditionalOnBean(ThymeleafViewResolver.class)
public LiteDeviceDelegatingViewResolver deviceDelegatingThymeleafViewResolver(
DeviceDelegatingViewResolverFactory factory,
ThymeleafViewResolver viewResolver) {
return factory.createViewResolver(viewResolver);
} }
} }

View File

@ -0,0 +1,85 @@
/*
* Copyright 2012-2016 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.boot.autoconfigure.mobile;
import org.springframework.core.Ordered;
import org.springframework.mobile.device.view.LiteDeviceDelegatingViewResolver;
import org.springframework.web.servlet.ViewResolver;
/**
* A factory for {@link LiteDeviceDelegatingViewResolver} that applies customizations
* of {@link DeviceDelegatingViewResolverProperties}.
*
* @author Stephane Nicoll
* @since 1.4.0
*/
public class DeviceDelegatingViewResolverFactory {
private final DeviceDelegatingViewResolverProperties properties;
public DeviceDelegatingViewResolverFactory(DeviceDelegatingViewResolverProperties properties) {
this.properties = properties;
}
/**
* Create a {@link LiteDeviceDelegatingViewResolver} delegating to the specified
* {@link ViewResolver}.
* @param delegate the view resolver to delegate to
* @param delegatingOrder the order of the {@link LiteDeviceDelegatingViewResolver}
* @return a {@link LiteDeviceDelegatingViewResolver} handling the specified resolver
*/
public LiteDeviceDelegatingViewResolver createViewResolver(
ViewResolver delegate, int delegatingOrder) {
LiteDeviceDelegatingViewResolver resolver = new LiteDeviceDelegatingViewResolver(
delegate);
resolver.setEnableFallback(this.properties.isEnableFallback());
resolver.setNormalPrefix(this.properties.getNormalPrefix());
resolver.setNormalSuffix(this.properties.getNormalSuffix());
resolver.setMobilePrefix(this.properties.getMobilePrefix());
resolver.setMobileSuffix(this.properties.getMobileSuffix());
resolver.setTabletPrefix(this.properties.getTabletPrefix());
resolver.setTabletSuffix(this.properties.getTabletSuffix());
resolver.setOrder(delegatingOrder);
return resolver;
}
/**
* Create a {@link LiteDeviceDelegatingViewResolver} delegating to the specified
* {@link ViewResolver} and computing a sensible order for it. The specified
* {@link ViewResolver} should implement {@link Ordered}, consider using
* {@link #createViewResolver(ViewResolver, int)} if that's not the case.
* @param delegate the view resolver to delegate to
* @return a {@link LiteDeviceDelegatingViewResolver} handling the specified resolver
*/
public LiteDeviceDelegatingViewResolver createViewResolver(ViewResolver delegate) {
if (!(delegate instanceof Ordered)) {
throw new IllegalStateException("ViewResolver " + delegate + "should implement " + Ordered.class.getName());
}
int delegateOrder = ((Ordered) delegate).getOrder();
return createViewResolver(delegate, adjustOrder(delegateOrder));
}
private int adjustOrder(int order) {
if (order == Ordered.HIGHEST_PRECEDENCE) {
return Ordered.HIGHEST_PRECEDENCE;
}
// The view resolver must be ordered higher than the delegate view
// resolver, otherwise the view names will not be adjusted
return order - 1;
}
}

View File

@ -16,28 +16,36 @@
package org.springframework.boot.autoconfigure.mobile; package org.springframework.boot.autoconfigure.mobile;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.After; import org.junit.After;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.thymeleaf.spring4.view.ThymeleafViewResolver; import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.PropertyAccessor; import org.springframework.beans.PropertyAccessor;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration.DeviceDelegatingViewResolverConfiguration; import org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration;
import org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration;
import org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration;
import org.springframework.boot.autoconfigure.mustache.web.MustacheViewResolver;
import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration; import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration;
import org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration; import org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration; import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.MockEmbeddedServletContainerFactory;
import org.springframework.boot.test.util.EnvironmentTestUtils; import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.Bean; import org.springframework.core.Ordered;
import org.springframework.context.annotation.Configuration;
import org.springframework.mobile.device.view.AbstractDeviceDelegatingViewResolver;
import org.springframework.mobile.device.view.LiteDeviceDelegatingViewResolver; import org.springframework.mobile.device.view.LiteDeviceDelegatingViewResolver;
import org.springframework.mock.web.MockServletContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import org.springframework.web.servlet.view.groovy.GroovyMarkupViewResolver;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -49,9 +57,10 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class DeviceDelegatingViewResolverAutoConfigurationTests { public class DeviceDelegatingViewResolverAutoConfigurationTests {
private static final MockEmbeddedServletContainerFactory containerFactory = new MockEmbeddedServletContainerFactory(); @Rule
public final ExpectedException thrown = ExpectedException.none();
private AnnotationConfigEmbeddedWebApplicationContext context; private AnnotationConfigWebApplicationContext context;
@After @After
public void close() { public void close() {
@ -60,123 +69,82 @@ public class DeviceDelegatingViewResolverAutoConfigurationTests {
} }
} }
@Test(expected = NoSuchBeanDefinitionException.class) @Test
public void deviceDelegatingViewResolverDefaultDisabled() throws Exception { public void deviceDelegatingViewResolverDefaultDisabled() throws Exception {
this.context = new AnnotationConfigEmbeddedWebApplicationContext(); load();
this.context.register(Config.class, this.thrown.expect(NoSuchBeanDefinitionException.class);
DeviceDelegatingViewResolverConfiguration.class); this.context.getBean(LiteDeviceDelegatingViewResolver.class);
this.context.refresh();
this.context.getBean("deviceDelegatingViewResolver",
AbstractDeviceDelegatingViewResolver.class);
} }
@Test @Test
public void deviceDelegatingInternalResourceViewResolverEnabled() throws Exception { public void deviceDelegatingJspResourceViewResolver() throws Exception {
this.context = new AnnotationConfigEmbeddedWebApplicationContext(); load("spring.mobile.devicedelegatingviewresolver.enabled:true");
EnvironmentTestUtils.addEnvironment(this.context, assertThat(this.context.getBeansOfType(LiteDeviceDelegatingViewResolver.class)).hasSize(1);
"spring.mobile.devicedelegatingviewresolver.enabled:true");
this.context.register(Config.class, WebMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
DeviceDelegatingViewResolverConfiguration.class);
this.context.refresh();
InternalResourceViewResolver internalResourceViewResolver = this.context InternalResourceViewResolver internalResourceViewResolver = this.context
.getBean(InternalResourceViewResolver.class); .getBean(InternalResourceViewResolver.class);
AbstractDeviceDelegatingViewResolver deviceDelegatingViewResolver = this.context assertLiteDeviceDelegatingViewResolver(internalResourceViewResolver,
.getBean("deviceDelegatingViewResolver", "deviceDelegatingJspViewResolver");
AbstractDeviceDelegatingViewResolver.class);
assertThat(internalResourceViewResolver).isNotNull();
assertThat(deviceDelegatingViewResolver).isNotNull();
assertThat(deviceDelegatingViewResolver.getViewResolver())
.isInstanceOf(InternalResourceViewResolver.class);
try {
this.context.getBean(ThymeleafViewResolver.class);
}
catch (NoSuchBeanDefinitionException ex) {
// expected. ThymeleafViewResolver shouldn't be defined.
}
assertThat(deviceDelegatingViewResolver.getOrder())
.isEqualTo(internalResourceViewResolver.getOrder() - 1);
}
@Test(expected = NoSuchBeanDefinitionException.class)
public void deviceDelegatingInternalResourceViewResolverDisabled() throws Exception {
this.context = new AnnotationConfigEmbeddedWebApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"spring.mobile.devicedelegatingviewresolver.enabled:false");
this.context.register(Config.class, WebMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
DeviceDelegatingViewResolverConfiguration.class);
this.context.refresh();
assertThat(this.context.getBean(InternalResourceViewResolver.class)).isNotNull();
try {
this.context.getBean(ThymeleafViewResolver.class);
}
catch (NoSuchBeanDefinitionException ex) {
// expected. ThymeleafViewResolver shouldn't be defined.
}
this.context.getBean("deviceDelegatingViewResolver",
AbstractDeviceDelegatingViewResolver.class);
} }
@Test @Test
public void deviceDelegatingThymeleafViewResolverEnabled() throws Exception { public void deviceDelegatingFreemarkerViewResolver() throws Exception {
this.context = new AnnotationConfigEmbeddedWebApplicationContext(); load(Collections.<Class<?>>singletonList(FreeMarkerAutoConfiguration.class),
EnvironmentTestUtils.addEnvironment(this.context,
"spring.mobile.devicedelegatingviewresolver.enabled:true"); "spring.mobile.devicedelegatingviewresolver.enabled:true");
this.context.register(Config.class, WebMvcAutoConfiguration.class, assertThat(this.context.getBeansOfType(LiteDeviceDelegatingViewResolver.class)).hasSize(2);
ThymeleafAutoConfiguration.class, assertLiteDeviceDelegatingViewResolver(this.context.getBean(FreeMarkerViewResolver.class),
HttpMessageConvertersAutoConfiguration.class, "deviceDelegatingFreemarkerViewResolver");
PropertyPlaceholderAutoConfiguration.class,
DeviceDelegatingViewResolverConfiguration.class);
this.context.refresh();
ThymeleafViewResolver thymeleafViewResolver = this.context
.getBean(ThymeleafViewResolver.class);
AbstractDeviceDelegatingViewResolver deviceDelegatingViewResolver = this.context
.getBean("deviceDelegatingViewResolver",
AbstractDeviceDelegatingViewResolver.class);
assertThat(thymeleafViewResolver).isNotNull();
assertThat(deviceDelegatingViewResolver).isNotNull();
assertThat(deviceDelegatingViewResolver.getViewResolver())
.isInstanceOf(ThymeleafViewResolver.class);
assertThat(this.context.getBean(InternalResourceViewResolver.class)).isNotNull();
assertThat(this.context.getBean(ThymeleafViewResolver.class)).isNotNull();
assertThat(deviceDelegatingViewResolver.getOrder())
.isEqualTo(thymeleafViewResolver.getOrder() - 1);
} }
@Test(expected = NoSuchBeanDefinitionException.class) @Test
public void deviceDelegatingThymeleafViewResolverDisabled() throws Exception { public void deviceDelegatingGroovyMarkupViewResolver() throws Exception {
this.context = new AnnotationConfigEmbeddedWebApplicationContext(); load(Collections.<Class<?>>singletonList(GroovyTemplateAutoConfiguration.class),
EnvironmentTestUtils.addEnvironment(this.context, "spring.mobile.devicedelegatingviewresolver.enabled:true");
assertThat(this.context.getBeansOfType(LiteDeviceDelegatingViewResolver.class)).hasSize(2);
assertLiteDeviceDelegatingViewResolver(this.context.getBean(GroovyMarkupViewResolver.class),
"deviceDelegatingGroovyMarkupViewResolver");
}
@Test
public void deviceDelegatingMustacheViewResolver() throws Exception {
load(Collections.<Class<?>>singletonList(MustacheAutoConfiguration.class),
"spring.mobile.devicedelegatingviewresolver.enabled:true");
assertThat(this.context.getBeansOfType(LiteDeviceDelegatingViewResolver.class)).hasSize(2);
assertLiteDeviceDelegatingViewResolver(this.context.getBean(MustacheViewResolver.class),
"deviceDelegatingMustacheViewResolver");
}
@Test
public void deviceDelegatingThymeleafViewResolver() throws Exception {
load(Collections.<Class<?>>singletonList(ThymeleafAutoConfiguration.class),
"spring.mobile.devicedelegatingviewresolver.enabled:true");
assertThat(this.context.getBeansOfType(LiteDeviceDelegatingViewResolver.class)).hasSize(2);
assertLiteDeviceDelegatingViewResolver(this.context.getBean(ThymeleafViewResolver.class),
"deviceDelegatingThymeleafViewResolver");
}
public void assertLiteDeviceDelegatingViewResolver(ViewResolver delegate, String delegatingBeanName) {
LiteDeviceDelegatingViewResolver deviceDelegatingViewResolver = this.context
.getBean(delegatingBeanName, LiteDeviceDelegatingViewResolver.class);
assertThat(deviceDelegatingViewResolver.getViewResolver())
.isSameAs(delegate);
assertThat(deviceDelegatingViewResolver.getOrder())
.isEqualTo(((Ordered) delegate).getOrder() - 1);
}
@Test
public void deviceDelegatingViewResolverDisabled() throws Exception {
load(Arrays.asList(FreeMarkerAutoConfiguration.class, GroovyTemplateAutoConfiguration.class,
MustacheAutoConfiguration.class, ThymeleafAutoConfiguration.class),
"spring.mobile.devicedelegatingviewresolver.enabled:false"); "spring.mobile.devicedelegatingviewresolver.enabled:false");
this.context.register(Config.class, WebMvcAutoConfiguration.class, assertThat(this.context.getBeansOfType(LiteDeviceDelegatingViewResolver.class)).hasSize(0);
ThymeleafAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
DeviceDelegatingViewResolverConfiguration.class);
this.context.refresh();
assertThat(this.context.getBean(InternalResourceViewResolver.class)).isNotNull();
assertThat(this.context.getBean(ThymeleafViewResolver.class)).isNotNull();
this.context.getBean("deviceDelegatingViewResolver",
AbstractDeviceDelegatingViewResolver.class);
} }
@Test @Test
public void defaultPropertyValues() throws Exception { public void defaultPropertyValues() throws Exception {
this.context = new AnnotationConfigEmbeddedWebApplicationContext(); load("spring.mobile.devicedelegatingviewresolver.enabled:true");
EnvironmentTestUtils.addEnvironment(this.context,
"spring.mobile.devicedelegatingviewresolver.enabled:true");
this.context.register(Config.class, WebMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
DeviceDelegatingViewResolverConfiguration.class);
this.context.refresh();
LiteDeviceDelegatingViewResolver liteDeviceDelegatingViewResolver = this.context LiteDeviceDelegatingViewResolver liteDeviceDelegatingViewResolver = this.context
.getBean("deviceDelegatingViewResolver", .getBean("deviceDelegatingJspViewResolver",
LiteDeviceDelegatingViewResolver.class); LiteDeviceDelegatingViewResolver.class);
DirectFieldAccessor accessor = new DirectFieldAccessor( DirectFieldAccessor accessor = new DirectFieldAccessor(
liteDeviceDelegatingViewResolver); liteDeviceDelegatingViewResolver);
assertThat(accessor.getPropertyValue("enableFallback")).isEqualTo(Boolean.FALSE); assertThat(accessor.getPropertyValue("enableFallback")).isEqualTo(Boolean.FALSE);
@ -246,32 +214,29 @@ public class DeviceDelegatingViewResolverAutoConfigurationTests {
private PropertyAccessor getLiteDeviceDelegatingViewResolverAccessor( private PropertyAccessor getLiteDeviceDelegatingViewResolverAccessor(
String... configuration) { String... configuration) {
this.context = new AnnotationConfigEmbeddedWebApplicationContext(); load(configuration);
EnvironmentTestUtils.addEnvironment(this.context, configuration);
this.context.register(Config.class, WebMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
DeviceDelegatingViewResolverConfiguration.class);
this.context.refresh();
LiteDeviceDelegatingViewResolver liteDeviceDelegatingViewResolver = this.context LiteDeviceDelegatingViewResolver liteDeviceDelegatingViewResolver = this.context
.getBean("deviceDelegatingViewResolver", .getBean("deviceDelegatingJspViewResolver",
LiteDeviceDelegatingViewResolver.class); LiteDeviceDelegatingViewResolver.class);
return new DirectFieldAccessor(liteDeviceDelegatingViewResolver); return new DirectFieldAccessor(liteDeviceDelegatingViewResolver);
} }
@Configuration public void load(String... environment) {
protected static class Config { load(null, environment);
@Bean
public EmbeddedServletContainerFactory containerFactory() {
return containerFactory;
}
@Bean
public EmbeddedServletContainerCustomizerBeanPostProcessor embeddedServletContainerCustomizerBeanPostProcessor() {
return new EmbeddedServletContainerCustomizerBeanPostProcessor();
} }
public void load(List<Class<?>> config, String... environment) {
this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext());
if (config != null) {
this.context.register(config.toArray(new Class[config.size()]));
}
this.context.register(WebMvcAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
DeviceDelegatingViewResolverAutoConfiguration.class);
EnvironmentTestUtils.addEnvironment(this.context, environment);
this.context.refresh();
} }
} }