diff --git a/docs/src/orchid/resources/wiki/guide/spring-integration.md b/docs/src/orchid/resources/wiki/guide/spring-integration.md
index 33b1b03d1..c47bc24a7 100644
--- a/docs/src/orchid/resources/wiki/guide/spring-integration.md
+++ b/docs/src/orchid/resources/wiki/guide/spring-integration.md
@@ -35,7 +35,7 @@ public class MvcConfig extends WebMvcConfigurerAdapter {
@Bean
public Loader templateLoader(){
- return new ServletLoader(servletContext);
+ return new ServletLoader(this.servletContext);
}
@Bean
@@ -47,7 +47,7 @@ public class MvcConfig extends WebMvcConfigurerAdapter {
public PebbleEngine pebbleEngine() {
return new PebbleEngine.Builder()
.loader(this.templateLoader())
- .extension(springExtension())
+ .extension(this.springExtension())
.build();
}
@@ -56,7 +56,7 @@ public class MvcConfig extends WebMvcConfigurerAdapter {
PebbleViewResolver viewResolver = new PebbleViewResolver();
viewResolver.setPrefix("/WEB-INF/templates/");
viewResolver.setSuffix(".html");
- viewResolver.setPebbleEngine(pebbleEngine());
+ viewResolver.setPebbleEngine(this.pebbleEngine());
return viewResolver;
}
@@ -75,7 +75,7 @@ public class ProfileController {
@RequestMapping
public ModelAndView getUserProfile(@RequestParam("id") long id) {
ModelAndView mav = new ModelAndView();
- mav.addObject("user", userService.getUser(id));
+ mav.addObject("user", this.userService.getUser(id));
mav.setViewName("profile");
return mav;
}
@@ -168,7 +168,7 @@ To output any error:
A timer in PebbleView is available to output the time taken to process a template. Just add the following config to your log4j.xml
```xml
-
+
```
diff --git a/pebble-spring/pebble-spring-boot-starter/pom.xml b/pebble-spring/pebble-spring-boot-starter/pom.xml
index 979060c00..e3282b424 100644
--- a/pebble-spring/pebble-spring-boot-starter/pom.xml
+++ b/pebble-spring/pebble-spring-boot-starter/pom.xml
@@ -24,6 +24,12 @@
${boot.version}
true
+
+ org.springframework.boot
+ spring-boot-starter-webflux
+ ${boot.version}
+ true
+
io.pebbletemplates
pebble-spring5
diff --git a/pebble-spring/pebble-spring-boot-starter/src/main/java/com/mitchellbosecke/pebble/boot/autoconfigure/PebbleAutoConfiguration.java b/pebble-spring/pebble-spring-boot-starter/src/main/java/com/mitchellbosecke/pebble/boot/autoconfigure/PebbleAutoConfiguration.java
index 57ecbbc7a..fa4bc3709 100644
--- a/pebble-spring/pebble-spring-boot-starter/src/main/java/com/mitchellbosecke/pebble/boot/autoconfigure/PebbleAutoConfiguration.java
+++ b/pebble-spring/pebble-spring-boot-starter/src/main/java/com/mitchellbosecke/pebble/boot/autoconfigure/PebbleAutoConfiguration.java
@@ -4,23 +4,27 @@
import com.mitchellbosecke.pebble.extension.Extension;
import com.mitchellbosecke.pebble.loader.ClasspathLoader;
import com.mitchellbosecke.pebble.loader.Loader;
-import com.mitchellbosecke.pebble.spring.PebbleViewResolver;
import com.mitchellbosecke.pebble.spring.extension.SpringExtension;
-import java.util.List;
-import javax.servlet.Servlet;
+import com.mitchellbosecke.pebble.spring.reactive.PebbleReactiveViewResolver;
+import com.mitchellbosecke.pebble.spring.servlet.PebbleViewResolver;
+
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
+import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import java.util.List;
+
@Configuration
@ConditionalOnClass(PebbleEngine.class)
-@AutoConfigureAfter(WebMvcAutoConfiguration.class)
+@AutoConfigureAfter({WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class})
@EnableConfigurationProperties(PebbleProperties.class)
public class PebbleAutoConfiguration {
@@ -40,7 +44,6 @@ public Loader> pebbleLoader() {
loader.setSuffix(this.properties.getSuffix());
return loader;
}
-
}
@Configuration
@@ -82,9 +85,8 @@ public PebbleEngine pebbleEngine() {
}
@Configuration
- @ConditionalOnWebApplication
- @ConditionalOnClass({Servlet.class})
- public static class PebbleViewResolverConfiguration {
+ @ConditionalOnWebApplication(type = Type.SERVLET)
+ public static class PebbleWebMvcConfiguration {
@Autowired
private PebbleProperties properties;
@@ -108,6 +110,33 @@ public PebbleViewResolver pebbleViewResolver() {
}
}
+ @Configuration
+ @ConditionalOnWebApplication(type = Type.REACTIVE)
+ public static class PebbleReactiveConfiguration {
+
+ @Autowired
+ private PebbleProperties properties;
+
+ @Autowired
+ private PebbleEngine pebbleEngine;
+
+ @Bean
+ @ConditionalOnMissingBean(name = "pebbleReactiveViewResolver")
+ public PebbleReactiveViewResolver pebbleReactiveViewResolver() {
+ String prefix = this.properties.getPrefix();
+ if (this.pebbleEngine.getLoader() instanceof ClasspathLoader) {
+ // classpathloader doesn't like leading slashes in paths
+ prefix = stripLeadingSlash(this.properties.getPrefix());
+ }
+ PebbleReactiveViewResolver resolver = new PebbleReactiveViewResolver(this.pebbleEngine);
+ resolver.setPrefix(prefix);
+ resolver.setSuffix(this.properties.getSuffix());
+ resolver.setViewNames(this.properties.getViewNames());
+ resolver.setRequestContextAttribute(this.properties.getRequestContextAttribute());
+ return resolver;
+ }
+ }
+
private static String stripLeadingSlash(String value) {
if (value == null) {
return null;
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/AppConfig.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/AppConfig.java
new file mode 100644
index 000000000..eca8f60f7
--- /dev/null
+++ b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/AppConfig.java
@@ -0,0 +1,64 @@
+package com.mitchellbosecke.pebble.boot;
+
+import com.mitchellbosecke.pebble.extension.AbstractExtension;
+import com.mitchellbosecke.pebble.extension.Extension;
+import com.mitchellbosecke.pebble.extension.Function;
+import com.mitchellbosecke.pebble.template.EvaluationContext;
+import com.mitchellbosecke.pebble.template.PebbleTemplate;
+
+import org.springframework.context.MessageSource;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.support.ResourceBundleMessageSource;
+import org.springframework.web.servlet.LocaleResolver;
+import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Configuration(proxyBeanMethods = false)
+public class AppConfig {
+ @Bean
+ public MessageSource messageSource() {
+ ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
+ messageSource.setBasename("messages");
+ messageSource.setFallbackToSystemLocale(false);
+ return messageSource;
+ }
+
+ @Bean
+ public LocaleResolver localeResolver() {
+ return new AcceptHeaderLocaleResolver();
+ }
+
+ @Bean
+ public Extension testExtension() {
+ return new TestExtension();
+ }
+
+ public static class TestExtension extends AbstractExtension {
+
+ @Override
+ public Map getFunctions() {
+ Map functions = new HashMap();
+ functions.put("testFunction", new TestFunction());
+ return functions;
+ }
+
+ public static class TestFunction implements Function {
+
+ @Override
+ public List getArgumentNames() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Object execute(Map args, PebbleTemplate self,
+ EvaluationContext context, int lineNumber) {
+ return "Tested!";
+ }
+ }
+ }
+}
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/Application.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/Application.java
index a02caf2cf..5a8c365d1 100644
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/Application.java
+++ b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/Application.java
@@ -1,62 +1,12 @@
package com.mitchellbosecke.pebble.boot;
-import com.mitchellbosecke.pebble.extension.AbstractExtension;
-import com.mitchellbosecke.pebble.extension.Extension;
-import com.mitchellbosecke.pebble.extension.Function;
-import com.mitchellbosecke.pebble.template.EvaluationContext;
-import com.mitchellbosecke.pebble.template.PebbleTemplate;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.MessageSource;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.support.ResourceBundleMessageSource;
-import org.springframework.web.servlet.LocaleResolver;
-import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
@SpringBootApplication
-@ServletComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
-
- @Bean
- public LocaleResolver localeResolver() {
- return new AcceptHeaderLocaleResolver();
- }
-
- @Bean
- public Extension testExtension() {
- return new TestExtension();
- }
-
- public static class TestExtension extends AbstractExtension {
-
- @Override
- public Map getFunctions() {
- Map functions = new HashMap();
- functions.put("testFunction", new TestFunction());
- return functions;
- }
-
- public static class TestFunction implements Function {
-
- @Override
- public List getArgumentNames() {
- return Collections.emptyList();
- }
-
- @Override
- public Object execute(Map args, PebbleTemplate self,
- EvaluationContext context, int lineNumber) {
- return "Tested!";
- }
- }
- }
-
}
\ No newline at end of file
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/Controllers.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/Controllers.java
index d99625b08..52eb0afa7 100644
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/Controllers.java
+++ b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/Controllers.java
@@ -1,7 +1,6 @@
package com.mitchellbosecke.pebble.boot;
import org.springframework.stereotype.Controller;
-import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@@ -13,17 +12,17 @@ public String hello() {
}
@RequestMapping("/index.action")
- public String index(ModelMap model) {
+ public String index() {
return "index";
}
@RequestMapping("/contextPath.action")
- public String contextPath(ModelMap model) {
+ public String contextPath() {
return "contextPath";
}
@RequestMapping("/extensions.action")
- public String extensions(ModelMap model) {
+ public String extensions() {
return "extensions";
}
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/NonWebApplication.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/NonWebApplication.java
index 6b4216d00..82268aea4 100644
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/NonWebApplication.java
+++ b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/NonWebApplication.java
@@ -4,9 +4,6 @@
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.context.MessageSource;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.support.ResourceBundleMessageSource;
@SpringBootApplication
public class NonWebApplication {
@@ -17,13 +14,4 @@ public static void main(String[] args) {
.build();
sa.run(args);
}
-
- @Bean
- public MessageSource messageSource() {
- ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
- messageSource.setBasename("messages");
- messageSource.setFallbackToSystemLocale(false);
- return messageSource;
- }
-
}
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ReactiveApplication.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ReactiveApplication.java
new file mode 100644
index 000000000..b505904cc
--- /dev/null
+++ b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ReactiveApplication.java
@@ -0,0 +1,16 @@
+package com.mitchellbosecke.pebble.boot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+import static org.springframework.boot.WebApplicationType.REACTIVE;
+
+@SpringBootApplication
+public class ReactiveApplication {
+
+ public static void main(String[] args) {
+ SpringApplication application = new SpringApplication(Application.class);
+ application.setWebApplicationType(REACTIVE);
+ application.run(args);
+ }
+}
\ No newline at end of file
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponenRegisteringPostProcessor.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponenRegisteringPostProcessor.java
deleted file mode 100644
index 3bf919dd8..000000000
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponenRegisteringPostProcessor.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.mitchellbosecke.pebble.boot;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
-import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
-import org.springframework.context.annotation.ScannedGenericBeanDefinition;
-
-class ServletComponentRegisteringPostProcessor implements BeanFactoryPostProcessor,
- ApplicationContextAware {
-
- private static final List HANDLERS;
-
- static {
- List handlers = new ArrayList();
- handlers.add(new WebServletHandler());
- handlers.add(new WebFilterHandler());
- handlers.add(new WebListenerHandler());
- HANDLERS = Collections.unmodifiableList(handlers);
- }
-
- private final Set packagesToScan;
-
- private ApplicationContext applicationContext;
-
- ServletComponentRegisteringPostProcessor(Set packagesToScan) {
- this.packagesToScan = packagesToScan;
- }
-
- @Override
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
- throws BeansException {
- if (isRunningInEmbeddedContainer()) {
- ClassPathScanningCandidateComponentProvider componentProvider = createComponentProvider();
- for (String packageToScan : this.packagesToScan) {
- scanPackage(componentProvider, packageToScan);
- }
- }
- }
-
- private void scanPackage(ClassPathScanningCandidateComponentProvider componentProvider,
- String packageToScan) {
- for (BeanDefinition candidate : componentProvider.findCandidateComponents(packageToScan)) {
- if (candidate instanceof ScannedGenericBeanDefinition) {
- for (ServletComponentHandler handler : HANDLERS) {
- handler.handle(((ScannedGenericBeanDefinition) candidate),
- (BeanDefinitionRegistry) this.applicationContext);
- }
- }
- }
- }
-
- private boolean isRunningInEmbeddedContainer() {
- return this.applicationContext instanceof ServletWebServerApplicationContext
- && ((ServletWebServerApplicationContext) this.applicationContext).getServletContext()
- == null;
- }
-
- private ClassPathScanningCandidateComponentProvider createComponentProvider() {
- ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(
- false);
- for (ServletComponentHandler handler : HANDLERS) {
- componentProvider.addIncludeFilter(handler.getTypeFilter());
- }
- return componentProvider;
- }
-
- Set getPackagesToScan() {
- return Collections.unmodifiableSet(this.packagesToScan);
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- this.applicationContext = applicationContext;
- }
-
-}
\ No newline at end of file
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponentHandler.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponentHandler.java
deleted file mode 100644
index c57882a97..000000000
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponentHandler.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.mitchellbosecke.pebble.boot;
-
-import java.lang.annotation.Annotation;
-import java.util.HashMap;
-import java.util.Map;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.context.annotation.ScannedGenericBeanDefinition;
-import org.springframework.core.annotation.AnnotationAttributes;
-import org.springframework.core.type.filter.AnnotationTypeFilter;
-import org.springframework.core.type.filter.TypeFilter;
-import org.springframework.util.Assert;
-
-abstract class ServletComponentHandler {
-
- private final Class extends Annotation> annotationType;
-
- private final TypeFilter typeFilter;
-
- protected ServletComponentHandler(Class extends Annotation> annotationType) {
- this.typeFilter = new AnnotationTypeFilter(annotationType);
- this.annotationType = annotationType;
- }
-
- TypeFilter getTypeFilter() {
- return this.typeFilter;
- }
-
- protected String[] extractUrlPatterns(String attribute, Map attributes) {
- String[] value = (String[]) attributes.get("value");
- String[] urlPatterns = (String[]) attributes.get("urlPatterns");
- if (urlPatterns.length > 0) {
- Assert
- .state(value.length == 0, "The urlPatterns and value attributes are mutually exclusive.");
- return urlPatterns;
- }
- return value;
- }
-
- protected final Map extractInitParameters(Map attributes) {
- Map initParameters = new HashMap();
- for (AnnotationAttributes initParam : (AnnotationAttributes[]) attributes.get("initParams")) {
- String name = (String) initParam.get("name");
- String value = (String) initParam.get("value");
- initParameters.put(name, value);
- }
- return initParameters;
- }
-
- void handle(ScannedGenericBeanDefinition beanDefinition, BeanDefinitionRegistry registry) {
- Map attributes = beanDefinition.getMetadata()
- .getAnnotationAttributes(this.annotationType.getName());
- if (attributes != null) {
- doHandle(attributes, beanDefinition, registry);
- }
- }
-
- protected abstract void doHandle(Map attributes, BeanDefinition beanDefinition,
- BeanDefinitionRegistry registry);
-
-}
\ No newline at end of file
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponentScan.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponentScan.java
deleted file mode 100644
index ba3bb3361..000000000
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponentScan.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.mitchellbosecke.pebble.boot;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import org.springframework.context.annotation.Import;
-
-@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-@Documented
-@Import(ServletComponentScanRegistrar.class)
-public @interface ServletComponentScan {
-
- /**
- * Alias for the {@link #basePackages()} attribute. Allows for more concise annotation
- * declarations e.g.: {@code @ServletComponentScan("org.my.pkg")} instead of {@code
- *
- * @return the base packages to scan
- * @ServletComponentScan(basePackages="org.my.pkg")}.
- */
- String[] value() default {};
-
- /**
- * Base packages to scan for annotated servlet components. {@link #value()} is an alias for (and
- * mutually exclusive with) this attribute.
- *
- * Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
- *
- * @return the base packages to scan
- */
- String[] basePackages() default {};
-
- /**
- * Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for
- * annotated servlet components. The package of each class specified will be scanned.
- *
- * @return classes from the base packages to scan
- */
- Class>[] basePackageClasses() default {};
-
-}
\ No newline at end of file
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponentScanRegistrar.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponentScanRegistrar.java
deleted file mode 100644
index b5c1dadee..000000000
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ServletComponentScanRegistrar.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.mitchellbosecke.pebble.boot;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Set;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.config.ConstructorArgumentValues.ValueHolder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.beans.factory.support.GenericBeanDefinition;
-import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
-import org.springframework.core.annotation.AnnotationAttributes;
-import org.springframework.core.type.AnnotationMetadata;
-import org.springframework.util.Assert;
-import org.springframework.util.ClassUtils;
-import org.springframework.util.ObjectUtils;
-
-class ServletComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
-
- private static final String BEAN_NAME = "servletComponentRegisteringPostProcessor";
-
- @Override
- public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
- BeanDefinitionRegistry registry) {
- Set packagesToScan = getPackagesToScan(importingClassMetadata);
- if (registry.containsBeanDefinition(BEAN_NAME)) {
- updatePostProcessor(registry, packagesToScan);
- } else {
- addPostProcessor(registry, packagesToScan);
- }
- }
-
- private void updatePostProcessor(BeanDefinitionRegistry registry, Set packagesToScan) {
- BeanDefinition definition = registry.getBeanDefinition(BEAN_NAME);
- ValueHolder constructorArguments = definition.getConstructorArgumentValues()
- .getGenericArgumentValue(Set.class);
- @SuppressWarnings("unchecked")
- Set mergedPackages = (Set) constructorArguments.getValue();
- mergedPackages.addAll(packagesToScan);
- constructorArguments.setValue(mergedPackages);
- }
-
- private void addPostProcessor(BeanDefinitionRegistry registry, Set packagesToScan) {
- GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
- beanDefinition.setBeanClass(ServletComponentRegisteringPostProcessor.class);
- beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(packagesToScan);
- beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
- registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
- }
-
- private Set getPackagesToScan(AnnotationMetadata metadata) {
- AnnotationAttributes attributes = AnnotationAttributes
- .fromMap(metadata.getAnnotationAttributes(ServletComponentScan.class.getName()));
- String[] value = attributes.getStringArray("value");
- String[] basePackages = attributes.getStringArray("basePackages");
- Class>[] basePackageClasses = attributes.getClassArray("basePackageClasses");
- if (!ObjectUtils.isEmpty(value)) {
- Assert.state(ObjectUtils.isEmpty(basePackages),
- "@ServletComponentScan basePackages and value attributes are" + " mutually exclusive");
- }
- Set packagesToScan = new LinkedHashSet();
- packagesToScan.addAll(Arrays.asList(value));
- packagesToScan.addAll(Arrays.asList(basePackages));
- for (Class> basePackageClass : basePackageClasses) {
- packagesToScan.add(ClassUtils.getPackageName(basePackageClass));
- }
- if (packagesToScan.isEmpty()) {
- return Collections.singleton(ClassUtils.getPackageName(metadata.getClassName()));
- }
- return packagesToScan;
- }
-
-}
\ No newline at end of file
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/WebFilterHandler.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/WebFilterHandler.java
deleted file mode 100644
index 3d5bd9e9e..000000000
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/WebFilterHandler.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package com.mitchellbosecke.pebble.boot;
-
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Map;
-import javax.servlet.DispatcherType;
-import javax.servlet.annotation.WebFilter;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.util.StringUtils;
-
-class WebFilterHandler extends ServletComponentHandler {
-
- WebFilterHandler() {
- super(WebFilter.class);
- }
-
- @Override
- public void doHandle(Map attributes, BeanDefinition beanDefinition,
- BeanDefinitionRegistry registry) {
- BeanDefinitionBuilder builder = BeanDefinitionBuilder
- .rootBeanDefinition(FilterRegistrationBean.class);
- builder.addPropertyValue("asyncSupported", attributes.get("asyncSupported"));
- builder.addPropertyValue("dispatcherTypes", extractDispatcherTypes(attributes));
- builder.addPropertyValue("filter", beanDefinition);
- builder.addPropertyValue("initParameters", extractInitParameters(attributes));
- String name = determineName(attributes, beanDefinition);
- builder.addPropertyValue("name", name);
- builder.addPropertyValue("servletNames", attributes.get("servletNames"));
- builder.addPropertyValue("urlPatterns", extractUrlPatterns("urlPatterns", attributes));
- registry.registerBeanDefinition(name, builder.getBeanDefinition());
- }
-
- private EnumSet extractDispatcherTypes(Map attributes) {
- DispatcherType[] dispatcherTypes = (DispatcherType[]) attributes.get("dispatcherTypes");
- if (dispatcherTypes.length == 0) {
- return EnumSet.noneOf(DispatcherType.class);
- }
- if (dispatcherTypes.length == 1) {
- return EnumSet.of(dispatcherTypes[0]);
- }
- return EnumSet
- .of(dispatcherTypes[0], Arrays.copyOfRange(dispatcherTypes, 1, dispatcherTypes.length));
- }
-
- private String determineName(Map attributes, BeanDefinition beanDefinition) {
- return (String) (StringUtils.hasText((String) attributes.get("filterName")) ? attributes
- .get("filterName")
- : beanDefinition.getBeanClassName());
- }
-
-}
\ No newline at end of file
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/WebListenerHandler.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/WebListenerHandler.java
deleted file mode 100644
index 4658858e2..000000000
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/WebListenerHandler.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.mitchellbosecke.pebble.boot;
-
-import java.util.Map;
-import javax.servlet.annotation.WebListener;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
-
-class WebListenerHandler extends ServletComponentHandler {
-
- WebListenerHandler() {
- super(WebListener.class);
- }
-
- @Override
- protected void doHandle(Map attributes, BeanDefinition beanDefinition,
- BeanDefinitionRegistry registry) {
- BeanDefinitionBuilder builder = BeanDefinitionBuilder
- .rootBeanDefinition(ServletListenerRegistrationBean.class);
- builder.addPropertyValue("listener", beanDefinition);
- registry.registerBeanDefinition(beanDefinition.getBeanClassName(), builder.getBeanDefinition());
- }
-
-}
\ No newline at end of file
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/WebServletHandler.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/WebServletHandler.java
deleted file mode 100644
index 740c83bdd..000000000
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/WebServletHandler.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.mitchellbosecke.pebble.boot;
-
-import java.util.Map;
-import javax.servlet.annotation.WebServlet;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.beans.factory.support.BeanDefinitionBuilder;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
-import org.springframework.boot.web.servlet.ServletRegistrationBean;
-import org.springframework.util.StringUtils;
-
-class WebServletHandler extends ServletComponentHandler {
-
- WebServletHandler() {
- super(WebServlet.class);
- }
-
- @Override
- public void doHandle(Map attributes, BeanDefinition beanDefinition,
- BeanDefinitionRegistry registry) {
- BeanDefinitionBuilder builder = BeanDefinitionBuilder
- .rootBeanDefinition(ServletRegistrationBean.class);
- builder.addPropertyValue("asyncSupported", attributes.get("asyncSupported"));
- builder.addPropertyValue("initParameters", extractInitParameters(attributes));
- builder.addPropertyValue("loadOnStartup", attributes.get("loadOnStartup"));
- String name = determineName(attributes, beanDefinition);
- builder.addPropertyValue("name", name);
- builder.addPropertyValue("servlet", beanDefinition);
- builder.addPropertyValue("urlMappings", extractUrlPatterns("urlPatterns", attributes));
- registry.registerBeanDefinition(name, builder.getBeanDefinition());
- }
-
- private String determineName(Map attributes, BeanDefinition beanDefinition) {
- return (String) (StringUtils.hasText((String) attributes.get("name")) ? attributes.get("name")
- : beanDefinition.getBeanClassName());
- }
-
-}
\ No newline at end of file
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/CoreTests.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/NonWebAppTests.java
similarity index 65%
rename from pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/CoreTests.java
rename to pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/NonWebAppTests.java
index 9ea36f50f..62b124a25 100644
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/CoreTests.java
+++ b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/NonWebAppTests.java
@@ -1,17 +1,20 @@
-package com.mitchellbosecke.pebble.boot;
+package com.mitchellbosecke.pebble.boot.autoconfigure;
import com.mitchellbosecke.pebble.PebbleEngine;
-import java.io.StringWriter;
+import com.mitchellbosecke.pebble.boot.NonWebApplication;
+
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import java.io.StringWriter;
-@RunWith(SpringJUnit4ClassRunner.class)
+@RunWith(SpringRunner.class)
@SpringBootTest(classes = NonWebApplication.class)
-public class CoreTests {
+public class NonWebAppTests {
@Autowired
private PebbleEngine pebbleEngine;
@@ -19,7 +22,7 @@ public class CoreTests {
@Test
public void testOk() throws Exception {
StringWriter sw = new StringWriter();
- pebbleEngine.getTemplate("hello").evaluate(sw);
+ this.pebbleEngine.getTemplate("hello").evaluate(sw);
Assert.assertTrue(sw.toString() != null && !sw.toString().isEmpty());
}
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/PebbleAutoConfigurationTest.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/PebbleAutoConfigurationTest.java
new file mode 100644
index 000000000..ab7d32ad0
--- /dev/null
+++ b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/PebbleAutoConfigurationTest.java
@@ -0,0 +1,107 @@
+package com.mitchellbosecke.pebble.boot.autoconfigure;
+
+import com.mitchellbosecke.pebble.PebbleEngine;
+import com.mitchellbosecke.pebble.loader.Loader;
+import com.mitchellbosecke.pebble.spring.extension.SpringExtension;
+import com.mitchellbosecke.pebble.spring.reactive.PebbleReactiveViewResolver;
+import com.mitchellbosecke.pebble.spring.servlet.PebbleViewResolver;
+
+import org.junit.Test;
+import org.springframework.boot.test.util.TestPropertyValues;
+import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebApplicationContext;
+import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+
+import java.util.Locale;
+
+import static java.util.Locale.CHINESE;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PebbleAutoConfigurationTest {
+
+ private static final Locale DEFAULT_LOCALE = CHINESE;
+ private AnnotationConfigServletWebApplicationContext webContext;
+
+ private AnnotationConfigReactiveWebApplicationContext reactiveWebContext;
+
+ @Test
+ public void registerBeansForServletApp() {
+ this.loadWithServlet(null);
+ assertThat(this.webContext.getBeansOfType(Loader.class)).hasSize(1);
+ assertThat(this.webContext.getBeansOfType(SpringExtension.class)).hasSize(1);
+ assertThat(this.webContext.getBeansOfType(PebbleEngine.class)).hasSize(1);
+ assertThat(this.webContext.getBeansOfType(PebbleViewResolver.class)).hasSize(1);
+ }
+
+ @Test
+ public void registerCompilerForServletApp() {
+ this.loadWithServlet(CustomCompilerConfiguration.class);
+ assertThat(this.webContext.getBeansOfType(Loader.class)).hasSize(1);
+ assertThat(this.webContext.getBeansOfType(SpringExtension.class)).isEmpty();
+ assertThat(this.webContext.getBeansOfType(PebbleEngine.class)).hasSize(1);
+ assertThat(this.webContext.getBean(PebbleEngine.class).getDefaultLocale()).isEqualTo(DEFAULT_LOCALE);
+ assertThat(this.webContext.getBeansOfType(PebbleViewResolver.class)).hasSize(1);
+ assertThat(this.webContext.getBeansOfType(PebbleReactiveViewResolver.class)).isEmpty();
+ }
+
+ @Test
+ public void registerBeansForReactiveApp() {
+ this.loadWithReactive(null);
+ assertThat(this.reactiveWebContext.getBeansOfType(Loader.class)).hasSize(1);
+ assertThat(this.reactiveWebContext.getBeansOfType(SpringExtension.class)).hasSize(1);
+ assertThat(this.reactiveWebContext.getBeansOfType(PebbleEngine.class)).hasSize(1);
+ assertThat(this.reactiveWebContext.getBeansOfType(PebbleViewResolver.class)).isEmpty();
+ assertThat(this.reactiveWebContext.getBeansOfType(PebbleReactiveViewResolver.class)).hasSize(1);
+ assertThat(this.reactiveWebContext.getBeansOfType(PebbleViewResolver.class)).isEmpty();
+ }
+
+ @Test
+ public void registerCompilerForReactiveApp() {
+ this.loadWithReactive(CustomCompilerConfiguration.class);
+ assertThat(this.reactiveWebContext.getBeansOfType(Loader.class)).hasSize(1);
+ assertThat(this.reactiveWebContext.getBeansOfType(SpringExtension.class)).isEmpty();
+ assertThat(this.reactiveWebContext.getBeansOfType(PebbleEngine.class)).hasSize(1);
+ assertThat(this.reactiveWebContext.getBean(PebbleEngine.class).getDefaultLocale()).isEqualTo(DEFAULT_LOCALE);
+ assertThat(this.reactiveWebContext.getBeansOfType(PebbleReactiveViewResolver.class)).hasSize(1);
+ assertThat(this.reactiveWebContext.getBeansOfType(PebbleViewResolver.class)).isEmpty();
+ }
+
+ private void loadWithServlet(Class> config) {
+ this.webContext = new AnnotationConfigServletWebApplicationContext();
+ TestPropertyValues.of("pebble.prefix=classpath:/templates/").applyTo(this.webContext);
+ if (config != null) {
+ this.webContext.register(config);
+ }
+ this.webContext.register(BaseConfiguration.class);
+ this.webContext.refresh();
+ }
+
+ private void loadWithReactive(Class> config) {
+ this.reactiveWebContext = new AnnotationConfigReactiveWebApplicationContext();
+ TestPropertyValues.of("pebble.prefix=classpath:/templates/").applyTo(this.reactiveWebContext);
+ if (config != null) {
+ this.reactiveWebContext.register(config);
+ }
+ this.reactiveWebContext.register(BaseConfiguration.class);
+ this.reactiveWebContext.refresh();
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ @Import(PebbleAutoConfiguration.class)
+ protected static class BaseConfiguration {
+
+ }
+
+ @Configuration(proxyBeanMethods = false)
+ protected static class CustomCompilerConfiguration {
+
+ @Bean
+ public PebbleEngine pebbleEngine() {
+ return new PebbleEngine.Builder().defaultLocale(DEFAULT_LOCALE).build();
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/ReactiveAppTest.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/ReactiveAppTest.java
new file mode 100644
index 000000000..419c7fb55
--- /dev/null
+++ b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/ReactiveAppTest.java
@@ -0,0 +1,82 @@
+package com.mitchellbosecke.pebble.boot.autoconfigure;
+
+import com.mitchellbosecke.pebble.boot.ReactiveApplication;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.web.reactive.server.WebTestClient;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ReactiveApplication.class,
+ webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
+ properties = "spring.main.web-application-type=reactive")
+public class ReactiveAppTest {
+
+ @Autowired
+ private WebTestClient client;
+
+ @Test
+ public void testOk() throws Exception {
+ String result = this.client.get().uri("/index.action").exchange()
+ .expectStatus().isOk()
+ .expectHeader().contentTypeCompatibleWith(MediaType.TEXT_HTML)
+ .expectBody(String.class)
+ .returnResult().getResponseBody();
+
+ assertThat(result).isEqualTo("Hello Pebbleworld!");
+ }
+
+ @Test
+ public void testRequestAccess() throws Exception {
+ String result = this.client.get().uri("/contextPath.action").exchange()
+ .expectStatus().isOk()
+ .expectHeader().contentTypeCompatibleWith(MediaType.TEXT_HTML)
+ .expectBody(String.class)
+ .returnResult().getResponseBody();
+
+ assertThat(result).isEqualTo("ctx path:");
+ }
+
+ @Test
+ public void testEnglishHello() throws Exception {
+ String result = this.client.get().uri("/hello.action")
+ .header("Accept-Language", "en").exchange()
+ .expectStatus().isOk()
+ .expectHeader().contentTypeCompatibleWith(MediaType.TEXT_HTML)
+ .expectBody(String.class)
+ .returnResult().getResponseBody();
+
+ assertThat(result).isEqualTo("Hello Boot!");
+ }
+
+ @Test
+ public void testSpanishHello() throws Exception {
+ String result = this.client.get().uri("/hello.action")
+ .header("Accept-Language", "es").exchange()
+ .expectStatus().isOk()
+ .expectHeader().contentTypeCompatibleWith(MediaType.TEXT_HTML)
+ .expectBody(String.class)
+ .returnResult().getResponseBody();
+
+ assertThat(result).isEqualTo("Hola Boot!");
+ }
+
+ @Test
+ public void testAdditionalExtensions() throws Exception {
+ String result = this.client.get().uri("/extensions.action")
+ .header("Accept-Language", "es").exchange()
+ .expectStatus().isOk()
+ .expectHeader().contentTypeCompatibleWith(MediaType.TEXT_HTML)
+ .expectBody(String.class)
+ .returnResult().getResponseBody();
+
+ assertThat(result).isEqualTo("Hola Boot! Tested!");
+ }
+}
+
diff --git a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ControllerTest.java b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/ServletAppTest.java
similarity index 75%
rename from pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ControllerTest.java
rename to pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/ServletAppTest.java
index 672b3782a..7ac516011 100644
--- a/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/ControllerTest.java
+++ b/pebble-spring/pebble-spring-boot-starter/src/test/java/com/mitchellbosecke/pebble/boot/autoconfigure/ServletAppTest.java
@@ -1,27 +1,30 @@
-package com.mitchellbosecke.pebble.boot;
+package com.mitchellbosecke.pebble.boot.autoconfigure;
-import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+import com.mitchellbosecke.pebble.boot.Application;
-import java.util.Locale;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
-@RunWith(SpringJUnit4ClassRunner.class)
+import java.util.Locale;
+
+import static org.junit.Assert.assertEquals;
+import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.RANDOM_PORT)
-public class ControllerTest {
+public class ServletAppTest {
@Autowired
private WebApplicationContext wac;
@@ -35,22 +38,22 @@ public void setup() {
@Test
public void testOk() throws Exception {
- mockMvc.perform(get("/index.action")).andExpect(status().isOk())
+ this.mockMvc.perform(get("/index.action")).andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(content().string("Hello Pebbleworld!"));
}
@Test
public void testRequestAccess() throws Exception {
- MvcResult result = mockMvc.perform(get("/contextPath.action")).andExpect(status().isOk())
+ MvcResult result = this.mockMvc.perform(get("/contextPath.action")).andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML)).andReturn();
- Assert.assertEquals("ctx path:" + result.getRequest().getContextPath(),
+ assertEquals("ctx path:" + result.getRequest().getContextPath(),
result.getResponse().getContentAsString());
}
@Test
public void testEnglishHello() throws Exception {
- mockMvc.perform(get("/hello.action").locale(Locale.forLanguageTag("en")))
+ this.mockMvc.perform(get("/hello.action").locale(Locale.forLanguageTag("en")))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(content().string("Hello Boot!"));
@@ -58,7 +61,7 @@ public void testEnglishHello() throws Exception {
@Test
public void testSpanishHello() throws Exception {
- mockMvc.perform(get("/hello.action").locale(Locale.forLanguageTag("es")))
+ this.mockMvc.perform(get("/hello.action").locale(Locale.forLanguageTag("es")))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(content().string("Hola Boot!"));
@@ -66,7 +69,7 @@ public void testSpanishHello() throws Exception {
@Test
public void testAdditionalExtensions() throws Exception {
- mockMvc.perform(get("/extensions.action").locale(Locale.forLanguageTag("es")))
+ this.mockMvc.perform(get("/extensions.action").locale(Locale.forLanguageTag("es")))
.andExpect(status().isOk())
.andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_HTML))
.andExpect(content().string("Hola Boot! Tested!"));
diff --git a/pebble-spring/pebble-spring5/pom.xml b/pebble-spring/pebble-spring5/pom.xml
index b917777e9..2633066cd 100644
--- a/pebble-spring/pebble-spring5/pom.xml
+++ b/pebble-spring/pebble-spring5/pom.xml
@@ -46,6 +46,11 @@
spring-webmvc
provided
+
+ org.springframework
+ spring-webflux
+ provided
+
diff --git a/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/reactive/PebbleReactiveView.java b/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/reactive/PebbleReactiveView.java
new file mode 100644
index 000000000..c0809e716
--- /dev/null
+++ b/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/reactive/PebbleReactiveView.java
@@ -0,0 +1,89 @@
+package com.mitchellbosecke.pebble.spring.reactive;
+
+import com.mitchellbosecke.pebble.PebbleEngine;
+import com.mitchellbosecke.pebble.error.PebbleException;
+import com.mitchellbosecke.pebble.template.PebbleTemplate;
+
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferUtils;
+import org.springframework.http.MediaType;
+import org.springframework.lang.Nullable;
+import org.springframework.util.MimeType;
+import org.springframework.web.reactive.result.view.AbstractUrlBasedView;
+import org.springframework.web.server.ServerWebExchange;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.Locale;
+import java.util.Map;
+
+import static java.util.Optional.ofNullable;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public class PebbleReactiveView extends AbstractUrlBasedView {
+
+ private PebbleEngine pebbleEngine;
+ private String templateName;
+
+ @Override
+ public boolean checkResourceExists(Locale locale) {
+ return this.pebbleEngine.getLoader().resourceExists(this.templateName);
+ }
+
+ @Override
+ protected Mono renderInternal(Map renderAttributes,
+ MediaType contentType,
+ ServerWebExchange exchange) {
+ DataBuffer dataBuffer = exchange.getResponse().bufferFactory().allocateBuffer();
+ if (this.logger.isDebugEnabled()) {
+ this.logger.debug(exchange.getLogPrefix() + "Rendering [" + this.getUrl() + "]");
+ }
+
+ Locale locale = LocaleContextHolder.getLocale(exchange.getLocaleContext());
+ try {
+ Charset charset = this.getCharset(contentType);
+ Writer writer = new OutputStreamWriter(dataBuffer.asOutputStream(), charset);
+ this.evaluateTemplate(renderAttributes, locale, writer);
+ } catch (Exception ex) {
+ DataBufferUtils.release(dataBuffer);
+ return Mono.error(ex);
+ }
+ return exchange.getResponse().writeWith(Flux.just(dataBuffer));
+ }
+
+ private Charset getCharset(@Nullable MediaType mediaType) {
+ return ofNullable(mediaType)
+ .map(MimeType::getCharset)
+ .orElse(this.getDefaultCharset());
+ }
+
+ private void evaluateTemplate(Map model, Locale locale, Writer writer)
+ throws IOException, PebbleException {
+ try {
+ PebbleTemplate template = this.pebbleEngine.getTemplate(this.templateName);
+ template.evaluate(writer, model, locale);
+ } finally {
+ writer.flush();
+ }
+ }
+
+ public PebbleEngine getPebbleEngine() {
+ return this.pebbleEngine;
+ }
+
+ public void setPebbleEngine(PebbleEngine pebbleEngine) {
+ this.pebbleEngine = pebbleEngine;
+ }
+
+ public String getTemplateName() {
+ return this.templateName;
+ }
+
+ public void setTemplateName(String templateName) {
+ this.templateName = templateName;
+ }
+}
diff --git a/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/reactive/PebbleReactiveViewResolver.java b/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/reactive/PebbleReactiveViewResolver.java
new file mode 100644
index 000000000..138e7ae73
--- /dev/null
+++ b/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/reactive/PebbleReactiveViewResolver.java
@@ -0,0 +1,34 @@
+package com.mitchellbosecke.pebble.spring.reactive;
+
+import com.mitchellbosecke.pebble.PebbleEngine;
+
+import org.springframework.web.reactive.result.view.AbstractUrlBasedView;
+import org.springframework.web.reactive.result.view.UrlBasedViewResolver;
+
+public class PebbleReactiveViewResolver extends UrlBasedViewResolver {
+
+ private final PebbleEngine pebbleEngine;
+
+ public PebbleReactiveViewResolver(PebbleEngine pebbleEngine) {
+ this.setViewClass(this.requiredViewClass());
+ this.pebbleEngine = pebbleEngine;
+ }
+
+ @Override
+ protected AbstractUrlBasedView createView(String viewName) {
+ PebbleReactiveView view = (PebbleReactiveView) super.createView(viewName);
+ view.setPebbleEngine(this.pebbleEngine);
+ view.setTemplateName(viewName);
+
+ return view;
+ }
+
+ @Override
+ protected Class> requiredViewClass() {
+ return PebbleReactiveView.class;
+ }
+
+ public PebbleEngine getPebbleEngine() {
+ return this.pebbleEngine;
+ }
+}
diff --git a/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/PebbleView.java b/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/servlet/PebbleView.java
similarity index 96%
rename from pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/PebbleView.java
rename to pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/servlet/PebbleView.java
index f9eb6431a..34535f76a 100644
--- a/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/PebbleView.java
+++ b/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/servlet/PebbleView.java
@@ -4,22 +4,25 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
-package com.mitchellbosecke.pebble.spring;
+package com.mitchellbosecke.pebble.spring.servlet;
import com.mitchellbosecke.pebble.PebbleEngine;
import com.mitchellbosecke.pebble.error.PebbleException;
import com.mitchellbosecke.pebble.spring.context.Beans;
import com.mitchellbosecke.pebble.template.PebbleTemplate;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.servlet.support.RequestContextUtils;
+import org.springframework.web.servlet.view.AbstractTemplateView;
+
import java.io.IOException;
import java.io.Writer;
import java.util.Locale;
import java.util.Map;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.web.servlet.support.RequestContextUtils;
-import org.springframework.web.servlet.view.AbstractTemplateView;
public class PebbleView extends AbstractTemplateView {
@@ -36,7 +39,7 @@ public class PebbleView extends AbstractTemplateView {
*
*
* The value of this constant is
- * com.mitchellbosecke.pebble.spring.PebbleView.timer. This allows
+ * com.mitchellbosecke.pebble.spring.servlet.PebbleView.timer. This allows
* you to set a specific configuration and/or appenders for timing info at your logging system
* configuration.
*
diff --git a/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/PebbleViewResolver.java b/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/servlet/PebbleViewResolver.java
similarity index 96%
rename from pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/PebbleViewResolver.java
rename to pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/servlet/PebbleViewResolver.java
index 96f3b7f12..0b7a66f44 100644
--- a/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/PebbleViewResolver.java
+++ b/pebble-spring/pebble-spring5/src/main/java/com/mitchellbosecke/pebble/spring/servlet/PebbleViewResolver.java
@@ -4,10 +4,11 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
-package com.mitchellbosecke.pebble.spring;
+package com.mitchellbosecke.pebble.spring.servlet;
import com.mitchellbosecke.pebble.PebbleEngine;
import com.mitchellbosecke.pebble.loader.Loader;
+
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.web.servlet.view.AbstractTemplateViewResolver;
diff --git a/pebble-spring/pebble-spring5/src/test/java/com/mitchellbosecke/pebble/spring/config/MVCConfig.java b/pebble-spring/pebble-spring5/src/test/java/com/mitchellbosecke/pebble/spring/config/MVCConfig.java
index e6d12f311..7d0615e63 100644
--- a/pebble-spring/pebble-spring5/src/test/java/com/mitchellbosecke/pebble/spring/config/MVCConfig.java
+++ b/pebble-spring/pebble-spring5/src/test/java/com/mitchellbosecke/pebble/spring/config/MVCConfig.java
@@ -9,9 +9,10 @@
import com.mitchellbosecke.pebble.PebbleEngine;
import com.mitchellbosecke.pebble.loader.ClasspathLoader;
import com.mitchellbosecke.pebble.loader.Loader;
-import com.mitchellbosecke.pebble.spring.PebbleViewResolver;
import com.mitchellbosecke.pebble.spring.bean.SomeBean;
import com.mitchellbosecke.pebble.spring.extension.SpringExtension;
+import com.mitchellbosecke.pebble.spring.servlet.PebbleViewResolver;
+
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/ClasspathLoader.java b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/ClasspathLoader.java
index 55021d900..91c363313 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/ClasspathLoader.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/ClasspathLoader.java
@@ -10,13 +10,15 @@
import com.mitchellbosecke.pebble.error.LoaderException;
import com.mitchellbosecke.pebble.utils.PathUtils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Uses a classloader to find templates located on the classpath.
@@ -47,7 +49,26 @@ public ClasspathLoader() {
@Override
public Reader getReader(String templateName) {
+ String location = this.getLocation(templateName);
+
+ logger.debug("Looking for template in {}.", location);
+
+ // perform the lookup
+ InputStream is = this.rcl.getResourceAsStream(location);
+ if (is == null) {
+ throw new LoaderException(null, "Could not find template \"" + location + "\"");
+ }
+
+ try {
+ return new BufferedReader(new InputStreamReader(is, this.charset));
+ } catch (UnsupportedEncodingException e) {
+ }
+
+ return null;
+ }
+
+ private String getLocation(String templateName) {
// append the prefix and make sure prefix ends with a separator character
StringBuilder path = new StringBuilder(128);
if (this.getPrefix() != null) {
@@ -64,22 +85,7 @@ public Reader getReader(String templateName) {
if (this.getSuffix() != null) {
path.append(this.getSuffix());
}
- String location = path.toString();
- logger.debug("Looking for template in {}.", location);
-
- // perform the lookup
- InputStream is = this.rcl.getResourceAsStream(location);
-
- if (is == null) {
- throw new LoaderException(null, "Could not find template \"" + location + "\"");
- }
-
- try {
- return new BufferedReader(new InputStreamReader(is, this.charset));
- } catch (UnsupportedEncodingException e) {
- }
-
- return null;
+ return path.toString();
}
public String getSuffix() {
@@ -118,4 +124,9 @@ public String resolveRelativePath(String relativePath, String anchorPath) {
public String createCacheKey(String templateName) {
return templateName;
}
+
+ @Override
+ public boolean resourceExists(String templateName) {
+ return this.rcl.getResource(this.getLocation(templateName)) != null;
+ }
}
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/DelegatingLoader.java b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/DelegatingLoader.java
index 9e225bbe7..35385c151 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/DelegatingLoader.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/DelegatingLoader.java
@@ -9,6 +9,7 @@
package com.mitchellbosecke.pebble.loader;
import com.mitchellbosecke.pebble.error.LoaderException;
+
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
@@ -89,7 +90,7 @@ public String getSuffix() {
@Override
public void setSuffix(String suffix) {
this.suffix = suffix;
- for (Loader> loader: this.loaders) {
+ for (Loader> loader : this.loaders) {
loader.setSuffix(suffix);
}
}
@@ -101,7 +102,7 @@ public String getPrefix() {
@Override
public void setPrefix(String prefix) {
this.prefix = prefix;
- for (Loader> loader: this.loaders) {
+ for (Loader> loader : this.loaders) {
loader.setPrefix(prefix);
}
}
@@ -113,7 +114,7 @@ public String getCharset() {
@Override
public void setCharset(String charset) {
this.charset = charset;
- for (Loader> loader: this.loaders) {
+ for (Loader> loader : this.loaders) {
loader.setCharset(charset);
}
}
@@ -142,4 +143,14 @@ public DelegatingLoaderCacheKey createCacheKey(String templateName) {
return new DelegatingLoaderCacheKey(keys, templateName);
}
+
+ @Override
+ public boolean resourceExists(String templateName) {
+ for (Loader> loader : this.loaders) {
+ if (loader.resourceExists(templateName)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/FileLoader.java b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/FileLoader.java
index dd784f3cd..187e23137 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/FileLoader.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/FileLoader.java
@@ -10,6 +10,10 @@
import com.mitchellbosecke.pebble.error.LoaderException;
import com.mitchellbosecke.pebble.utils.PathUtils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@@ -18,8 +22,6 @@
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* This loader searches for a file located anywhere on the filesystem. It uses java.io.File to
@@ -39,7 +41,30 @@ public class FileLoader implements Loader {
@Override
public Reader getReader(String templateName) {
+ // try to load File
+ InputStream is = null;
+ File file = this.getFile(templateName);
+ if (file.exists() && file.isFile()) {
+ try {
+ is = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ }
+ }
+
+ if (is == null) {
+ throw new LoaderException(null,
+ "Could not find template \"" + templateName + "\"");
+ }
+ try {
+ return new BufferedReader(new InputStreamReader(is, this.charset));
+ } catch (UnsupportedEncodingException e) {
+ }
+
+ return null;
+ }
+
+ private File getFile(String templateName) {
// add the prefix and ensure the prefix ends with a separator character
StringBuilder path = new StringBuilder();
if (this.getPrefix() != null) {
@@ -71,26 +96,7 @@ public Reader getReader(String templateName) {
}
// try to load File
- InputStream is = null;
- File file = new File(path.toString(), templateName);
- if (file.exists() && file.isFile()) {
- try {
- is = new FileInputStream(file);
- } catch (FileNotFoundException e) {
- }
- }
-
- if (is == null) {
- throw new LoaderException(null,
- "Could not find template \"" + path.toString() + templateName + "\"");
- }
-
- try {
- return new BufferedReader(new InputStreamReader(is, this.charset));
- } catch (UnsupportedEncodingException e) {
- }
-
- return null;
+ return new File(path.toString(), templateName);
}
public String getSuffix() {
@@ -129,4 +135,9 @@ public String resolveRelativePath(String relativePath, String anchorPath) {
public String createCacheKey(String templateName) {
return templateName;
}
+
+ @Override
+ public boolean resourceExists(String templateName) {
+ return this.getFile(templateName).exists();
+ }
}
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/Loader.java b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/Loader.java
index c8901ddd2..cc7bf0682 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/Loader.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/Loader.java
@@ -9,6 +9,7 @@
package com.mitchellbosecke.pebble.loader;
import com.mitchellbosecke.pebble.PebbleEngine;
+
import java.io.Reader;
/**
@@ -101,4 +102,5 @@ public interface Loader {
*/
T createCacheKey(String templateName);
+ boolean resourceExists(String templateName);
}
\ No newline at end of file
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/ServletLoader.java b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/ServletLoader.java
index 13e3bb00e..e6268fde4 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/ServletLoader.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/ServletLoader.java
@@ -2,14 +2,18 @@
import com.mitchellbosecke.pebble.error.LoaderException;
import com.mitchellbosecke.pebble.utils.PathUtils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+
import javax.servlet.ServletContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* Loader that uses a servlet context to find templates.
@@ -41,34 +45,18 @@ public Reader getReader(String templateName) {
Reader reader = null;
InputStream is = null;
+ String location = this.getLocation(templateName);
- // Add the prefix and make sure that it ends with a separator character
- StringBuilder path = new StringBuilder(128);
- if (getPrefix() != null) {
-
- path.append(getPrefix());
-
- // we do NOT use OS dependent separators here; getResourceAsStream
- // explicitly requires forward slashes.
- if (!getPrefix().endsWith(Character.toString(expectedSeparator))) {
- path.append(expectedSeparator);
- }
- }
- path.append(templateName);
- if (getSuffix() != null) {
- path.append(getSuffix());
- }
- String location = path.toString();
logger.debug("Looking for template in {}.", location);
- is = context.getResourceAsStream(location);
+ is = this.context.getResourceAsStream(location);
if (is == null) {
throw new LoaderException(null, "Could not find template \"" + location + "\"");
}
try {
- isr = new InputStreamReader(is, charset);
+ isr = new InputStreamReader(is, this.charset);
reader = new BufferedReader(isr);
} catch (UnsupportedEncodingException e) {
}
@@ -76,8 +64,28 @@ public Reader getReader(String templateName) {
return reader;
}
+ private String getLocation(String templateName) {
+ // Add the prefix and make sure that it ends with a separator character
+ StringBuilder path = new StringBuilder(128);
+ if (this.getPrefix() != null) {
+
+ path.append(this.getPrefix());
+
+ // we do NOT use OS dependent separators here; getResourceAsStream
+ // explicitly requires forward slashes.
+ if (!this.getPrefix().endsWith(Character.toString(this.expectedSeparator))) {
+ path.append(this.expectedSeparator);
+ }
+ }
+ path.append(templateName);
+ if (this.getSuffix() != null) {
+ path.append(this.getSuffix());
+ }
+ return path.toString();
+ }
+
public String getSuffix() {
- return suffix;
+ return this.suffix;
}
@Override
@@ -86,7 +94,7 @@ public void setSuffix(String suffix) {
}
public String getPrefix() {
- return prefix;
+ return this.prefix;
}
@Override
@@ -95,7 +103,7 @@ public void setPrefix(String prefix) {
}
public String getCharset() {
- return charset;
+ return this.charset;
}
@Override
@@ -105,7 +113,7 @@ public void setCharset(String charset) {
@Override
public String resolveRelativePath(String relativePath, String anchorPath) {
- return PathUtils.resolveRelativePath(relativePath, anchorPath, expectedSeparator);
+ return PathUtils.resolveRelativePath(relativePath, anchorPath, this.expectedSeparator);
}
@Override
@@ -113,4 +121,12 @@ public String createCacheKey(String templateName) {
return templateName;
}
+ @Override
+ public boolean resourceExists(String templateName) {
+ try {
+ return this.context.getResource(this.getLocation(templateName)) != null;
+ } catch (MalformedURLException e) {
+ return false;
+ }
+ }
}
diff --git a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/StringLoader.java b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/StringLoader.java
index a49c221da..921fb8d3a 100644
--- a/pebble/src/main/java/com/mitchellbosecke/pebble/loader/StringLoader.java
+++ b/pebble/src/main/java/com/mitchellbosecke/pebble/loader/StringLoader.java
@@ -48,4 +48,8 @@ public String createCacheKey(String templateName) {
return templateName;
}
+ @Override
+ public boolean resourceExists(String templateName) {
+ return true;
+ }
}
diff --git a/pebble/src/test/java/com/mitchellbosecke/pebble/ConcurrencyTest.java b/pebble/src/test/java/com/mitchellbosecke/pebble/ConcurrencyTest.java
index 5f597ac0a..f41c5f9b6 100644
--- a/pebble/src/test/java/com/mitchellbosecke/pebble/ConcurrencyTest.java
+++ b/pebble/src/test/java/com/mitchellbosecke/pebble/ConcurrencyTest.java
@@ -8,14 +8,14 @@
*/
package com.mitchellbosecke.pebble;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
import com.mitchellbosecke.pebble.error.LoaderException;
import com.mitchellbosecke.pebble.error.PebbleException;
import com.mitchellbosecke.pebble.loader.Loader;
import com.mitchellbosecke.pebble.loader.StringLoader;
import com.mitchellbosecke.pebble.template.PebbleTemplate;
+
+import org.junit.Test;
+
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
@@ -29,7 +29,9 @@
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
-import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
public class ConcurrencyTest {
@@ -324,6 +326,10 @@ public String createCacheKey(String templateName) {
return templateName;
}
+ @Override
+ public boolean resourceExists(String templateName) {
+ return true;
+ }
};
PebbleEngine engine = new PebbleEngine.Builder().loader(loader).strictVariables(false).build();