You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pluto-scm@portals.apache.org by as...@apache.org on 2019/03/25 22:54:00 UTC

[portals-pluto] branch master updated: PLUTO-750 Develop the thymeleaf-mvc-portlet-spring module

This is an automated email from the ASF dual-hosted git repository.

asfgriff pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/portals-pluto.git


The following commit(s) were added to refs/heads/master by this push:
     new 31913e0  PLUTO-750 Develop the thymeleaf-mvc-portlet-spring module
31913e0 is described below

commit 31913e041ce54c7331384246d5b2fa443b4c5895
Author: Neil Griffin <ne...@gmail.com>
AuthorDate: Mon Mar 25 18:53:40 2019 -0400

    PLUTO-750 Develop the thymeleaf-mvc-portlet-spring module
---
 portlet-templating/pom.xml                         |   1 +
 .../thymeleaf-mvc-portlet-spring/pom.xml           | 101 ++++++++++++++
 .../portlet/spring/SpringVariableValidator.java    | 147 +++++++++++++++++++++
 .../spring/TemplateEngineSupplierProducer.java     |  83 ++++++++++++
 .../portlet/spring/VariableValidatorProducer.java  |  43 ++++++
 .../mvc/portlet/spring/ViewEngineProducer.java     |  59 +++++++++
 .../mvc/portlet/spring/WebContextProducer.java     | 142 ++++++++++++++++++++
 7 files changed, 576 insertions(+)

diff --git a/portlet-templating/pom.xml b/portlet-templating/pom.xml
index 8ded1ef..394d9aa 100644
--- a/portlet-templating/pom.xml
+++ b/portlet-templating/pom.xml
@@ -26,6 +26,7 @@
 		<module>thymeleaf-portlet-api</module>
 		<module>thymeleaf-mvc-portlet-api</module>
 		<module>thymeleaf-mvc-portlet-cdi</module>
+		<module>thymeleaf-mvc-portlet-spring</module>
 	</modules>
 
 </project>
diff --git a/portlet-templating/thymeleaf-mvc-portlet-spring/pom.xml b/portlet-templating/thymeleaf-mvc-portlet-spring/pom.xml
new file mode 100644
index 0000000..7a840cb
--- /dev/null
+++ b/portlet-templating/thymeleaf-mvc-portlet-spring/pom.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor 
+   license agreements. See the NOTICE file distributed with this work for additional 
+   information regarding copyright ownership. The ASF licenses this file to 
+   you 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.apache.portals.pluto</groupId>
+		<artifactId>portlet-templating</artifactId>
+		<version>3.0.2-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+	<artifactId>thymeleaf-mvc-portlet-spring</artifactId>
+	<name>Thymeleaf MVC Portlet Spring</name>
+	<description>Spring implementation of the Thymeleaf MVC Portlet API</description>
+
+	<properties>
+		<spring.version>5.1.4.RELEASE</spring.version>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>javax.mvc</groupId>
+			<artifactId>javax.mvc-api</artifactId>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>javax.portlet</groupId>
+			<artifactId>portlet-api</artifactId>
+			<scope>provided</scope>
+			<exclusions>
+				<exclusion>
+					<groupId>javax.enterprise</groupId>
+					<artifactId>cdi-api</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>javax.servlet-api</artifactId>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>javax.ws.rs</groupId>
+			<artifactId>javax.ws.rs-api</artifactId>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>ognl</groupId>
+			<artifactId>ognl</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.portals.pluto</groupId>
+			<artifactId>portlet-servlet-adapter</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.portals.pluto</groupId>
+			<artifactId>thymeleaf-mvc-portlet-api</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-beans</artifactId>
+			<version>${spring.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-context</artifactId>
+			<version>${spring.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework</groupId>
+			<artifactId>spring-core</artifactId>
+			<version>${spring.version}</version>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>
diff --git a/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/SpringVariableValidator.java b/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/SpringVariableValidator.java
new file mode 100644
index 0000000..074e60e
--- /dev/null
+++ b/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/SpringVariableValidator.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.pluto.thymeleaf.mvc.portlet.spring;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletContext;
+
+import org.apache.pluto.thymeleaf.portlet.VariableValidator;
+import org.apache.pluto.thymeleaf.portlet.VariableValidatorBase;
+
+
+/**
+ * This class provides a Spring implementation of the {@link org.apache.pluto.thymeleaf.portlet.VariableValidator}
+ * interface.
+ *
+ * @author  Neil Griffin
+ */
+public class SpringVariableValidator extends VariableValidatorBase {
+
+	private static final Set<String> literalBeanNames;
+
+	static {
+		literalBeanNames = new HashSet<>();
+		literalBeanNames.add("beanMethodDecorator");
+		literalBeanNames.add("bindingResultImpl");
+		literalBeanNames.add("configurationImpl");
+		literalBeanNames.add("encodersImpl");
+		literalBeanNames.add("getBooleanParam");
+		literalBeanNames.add("getDateParam");
+		literalBeanNames.add("getDoubleParam");
+		literalBeanNames.add("getFloatParam");
+		literalBeanNames.add("getIntegerParam");
+		literalBeanNames.add("getLongParam");
+		literalBeanNames.add("getMessageInterpolator");
+		literalBeanNames.add("getParamConverterProviders");
+		literalBeanNames.add("getStringParam");
+		literalBeanNames.add("getTemplateEngineSupplier");
+		literalBeanNames.add("getViewEngine");
+		literalBeanNames.add("getWebContext");
+		literalBeanNames.add("getValidator");
+		literalBeanNames.add("localeResolverImpl");
+		literalBeanNames.add("messageSource");
+		literalBeanNames.add("paramConverterProviderImpl");
+		literalBeanNames.add("springBeanPortletFilter");
+		literalBeanNames.add("springPostProcessor");
+		literalBeanNames.add("variableValidator");
+		literalBeanNames.add("viewEngineContextInjectableImpl");
+		literalBeanNames.add("viewEngineJspImpl");
+		literalBeanNames.add("viewRenderer");
+	}
+
+	// Instance field must be declared volatile in order for the double-check idiom to work (requires JRE 1.5+)
+	private volatile Boolean includeStandardBeans;
+
+	private PortletConfig portletConfig;
+	private PortletContext portletContext;
+
+	public SpringVariableValidator(PortletConfig portletConfig, PortletContext portletContext) {
+		this.portletConfig = portletConfig;
+		this.portletContext = portletContext;
+	}
+
+	public PortletConfig getPortletConfig() {
+		return portletConfig;
+	}
+
+	public PortletContext getPortletContext() {
+		return portletContext;
+	}
+
+	@Override
+	public boolean isIncludeStandardBeans() {
+
+		Boolean include = this.includeStandardBeans;
+
+		// First check without locking (not yet thread-safe)
+		if (include == null) {
+
+			synchronized (this) {
+				include = this.includeStandardBeans;
+
+				// Second check with locking (thread-safe)
+				if (include == null) {
+
+					PortletConfig portletConfig = getPortletConfig();
+					String initParameterValue = portletConfig.getInitParameter(
+							VariableValidator.INCLUDE_STANDARD_BEANS);
+
+					boolean initParameterFlag = false;
+
+					if (initParameterValue != null) {
+						initParameterFlag = Boolean.valueOf(initParameterValue.toString());
+					}
+
+					PortletContext portletContext = getPortletContext();
+					initParameterValue = portletContext.getInitParameter(VariableValidator.INCLUDE_STANDARD_BEANS);
+
+					if (initParameterValue != null) {
+						initParameterFlag = Boolean.valueOf(initParameterValue.toString());
+					}
+
+					include = this.includeStandardBeans = initParameterFlag;
+				}
+			}
+		}
+
+		return include;
+	}
+
+	@Override
+	public boolean isValidName(String name, boolean headerPhase, boolean renderPhase, boolean resourcePhase) {
+
+		boolean valid = super.isValidName(name, headerPhase, renderPhase, resourcePhase);
+
+		if (!valid) {
+			return false;
+		}
+
+		if (literalBeanNames.contains(name)) {
+			return false;
+		}
+
+		if (name.endsWith("ConverterProvider") || name.startsWith("org.springframework") || name.endsWith("Producer") ||
+				name.startsWith("scopedTarget.") || name.endsWith("VariableValidator")) {
+			return false;
+		}
+
+		return true;
+	}
+}
diff --git a/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/TemplateEngineSupplierProducer.java b/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/TemplateEngineSupplierProducer.java
new file mode 100644
index 0000000..11d942c
--- /dev/null
+++ b/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/TemplateEngineSupplierProducer.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.pluto.thymeleaf.mvc.portlet.spring;
+
+import javax.mvc.MvcContext;
+import javax.mvc.engine.ViewEngine;
+import javax.portlet.PortletConfig;
+import javax.servlet.ServletContext;
+
+import org.apache.pluto.thymeleaf.portlet.DefaultTemplateEngineSupplier;
+import org.apache.pluto.thymeleaf.portlet.PortletMessageResolver;
+import org.apache.pluto.thymeleaf.portlet.PortletTemplateResolver;
+import org.apache.pluto.thymeleaf.portlet.TemplateEngineSupplier;
+import org.apache.pluto.thymeleaf.portlet.TemplateLocationSupplier;
+
+import org.springframework.beans.factory.BeanFactory;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+
+import org.thymeleaf.TemplateEngine;
+
+
+/**
+ * This class is a Spring producer that provides the ability to generate an instance of {@link TemplateEngineSupplier}.
+ *
+ * @author  Neil Griffin
+ */
+@Configuration
+public class TemplateEngineSupplierProducer {
+
+	@Bean
+	@Scope(proxyMode = ScopedProxyMode.INTERFACES)
+	public TemplateEngineSupplier getTemplateEngineSupplier(PortletConfig portletConfig, ServletContext servletContext,
+		BeanFactory beanFactory) {
+		TemplateEngine templateEngine = new TemplateEngine();
+		templateEngine.setMessageResolver(new PortletMessageResolver(portletConfig));
+		templateEngine.setTemplateResolver(new PortletTemplateResolver(servletContext,
+				new SpringConfigurationSupplier(beanFactory)));
+
+		return new DefaultTemplateEngineSupplier(templateEngine);
+	}
+
+	private static class SpringConfigurationSupplier implements TemplateLocationSupplier {
+
+		private BeanFactory beanFactory;
+
+		public SpringConfigurationSupplier(BeanFactory beanFactory) {
+			this.beanFactory = beanFactory;
+		}
+
+		@Override
+		public String get() {
+			MvcContext mvcContext = beanFactory.getBean(MvcContext.class);
+
+			javax.ws.rs.core.Configuration configuration = mvcContext.getConfig();
+
+			String templateLocation = (String) configuration.getProperty(ViewEngine.VIEW_FOLDER);
+
+			if (templateLocation == null) {
+				templateLocation = ViewEngine.DEFAULT_VIEW_FOLDER;
+			}
+
+			return templateLocation;
+		}
+	}
+}
diff --git a/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/VariableValidatorProducer.java b/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/VariableValidatorProducer.java
new file mode 100644
index 0000000..cd5a0a9
--- /dev/null
+++ b/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/VariableValidatorProducer.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.pluto.thymeleaf.mvc.portlet.spring;
+
+import javax.portlet.PortletConfig;
+import javax.portlet.PortletContext;
+
+import org.apache.pluto.thymeleaf.portlet.VariableValidator;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+/**
+ * This class is a Spring producer that provides the ability to generate an instance of {@link VariableValidator}.
+ *
+ * @author  Neil Griffin
+ */
+@Configuration
+public class VariableValidatorProducer {
+
+	@Bean
+	public VariableValidator getVariableValidator(PortletConfig portletConfig, PortletContext portletContext) {
+
+		SpringVariableValidator springVariableValidator = new SpringVariableValidator(portletConfig, portletContext);
+
+		return springVariableValidator;
+	}
+}
diff --git a/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/ViewEngineProducer.java b/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/ViewEngineProducer.java
new file mode 100644
index 0000000..32bcc73
--- /dev/null
+++ b/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/ViewEngineProducer.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.pluto.thymeleaf.mvc.portlet.spring;
+
+import java.io.IOException;
+
+import javax.mvc.engine.ViewEngine;
+import javax.mvc.engine.ViewEngineException;
+import javax.portlet.MimeResponse;
+
+import org.apache.pluto.thymeleaf.mvc.portlet.ThymeleafViewEngine;
+import org.apache.pluto.thymeleaf.portlet.TemplateEngineSupplier;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+
+import org.thymeleaf.context.IWebContext;
+
+
+/**
+ * This class is a Spring producer that provides the ability to generate instances of {@link ViewEngine}.
+ *
+ * @author  Neil Griffin
+ */
+@Configuration
+public class ViewEngineProducer {
+
+	@Bean
+	@Scope(proxyMode = ScopedProxyMode.INTERFACES, value = "portletRequest")
+	public ViewEngine getViewEngine(TemplateEngineSupplier templateEngineSupplier, IWebContext webContext) {
+		return new ThymeleafViewEngine(templateEngineSupplier.get(), webContext,
+				viewEngineContext -> {
+					MimeResponse mimeResponse = viewEngineContext.getResponse(MimeResponse.class);
+
+					try {
+						return mimeResponse.getWriter();
+					}
+					catch (IOException e) {
+						throw new ViewEngineException(e);
+					}
+				});
+	}
+}
diff --git a/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/WebContextProducer.java b/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/WebContextProducer.java
new file mode 100644
index 0000000..bb48e4c
--- /dev/null
+++ b/portlet-templating/thymeleaf-mvc-portlet-spring/src/main/java/org/apache/pluto/thymeleaf/mvc/portlet/spring/WebContextProducer.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.pluto.thymeleaf.mvc.portlet.spring;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.mvc.Models;
+import javax.mvc.MvcContext;
+import javax.portlet.MimeResponse;
+import javax.portlet.PortletRequest;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.pluto.portlet.servlet.adapter.HttpServletRequestAdapter;
+import org.apache.pluto.portlet.servlet.adapter.HttpServletResponseAdapter;
+import org.apache.pluto.thymeleaf.portlet.VariableValidator;
+import org.apache.pluto.thymeleaf.portlet.WebContextBase;
+
+import org.springframework.beans.BeansException;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+import org.springframework.context.annotation.ScopedProxyMode;
+
+import org.thymeleaf.context.IWebContext;
+
+
+/**
+ * This class is a Spring producer that provides the ability to generate instances of {@link IWebContext}.
+ *
+ * @author  Neil Griffin
+ */
+@Configuration
+public class WebContextProducer implements ApplicationContextAware {
+
+	private ApplicationContext applicationContext;
+
+	@Scope(proxyMode = ScopedProxyMode.INTERFACES, value = "portletRequest")
+	@Bean
+	public IWebContext getWebContext(MvcContext mvcContext, Models models, PortletRequest portletRequest,
+		MimeResponse mimeResponse, ServletContext servletContext) {
+
+		return new SpringPortletWebContext(applicationContext, models,
+				(String) portletRequest.getAttribute(PortletRequest.LIFECYCLE_PHASE),
+				new HttpServletRequestAdapter(portletRequest), new HttpServletResponseAdapter(mimeResponse),
+				servletContext, mvcContext.getLocale(), mvcContext.getConfig());
+	}
+
+	@Override
+	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+		this.applicationContext = applicationContext;
+	}
+
+	private static class SpringPortletWebContext extends WebContextBase {
+
+		private ApplicationContext applicationContext;
+		private Set<String> beanNames;
+		private Models models;
+
+		public SpringPortletWebContext(ApplicationContext applicationContext, Models models, String lifecyclePhase,
+			HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
+			ServletContext servletContext, Locale locale, javax.ws.rs.core.Configuration configuration) {
+
+			super(httpServletRequest, httpServletResponse, servletContext, locale);
+			this.applicationContext = applicationContext;
+			this.models = models;
+			this.beanNames = new HashSet<>();
+
+			boolean portletSpecBeans = false;
+
+			VariableValidator variableValidator = applicationContext.getBean(VariableValidator.class);
+
+			boolean headerPhase = lifecyclePhase.equals(PortletRequest.HEADER_PHASE);
+			boolean renderPhase = lifecyclePhase.equals(PortletRequest.RENDER_PHASE);
+			boolean resourcePhase = lifecyclePhase.equals(PortletRequest.RESOURCE_PHASE);
+
+			for (String beanName : applicationContext.getBeanDefinitionNames()) {
+
+				if ((beanName != null) &&
+						variableValidator.isValidName(beanName, headerPhase, renderPhase, resourcePhase)) {
+					this.beanNames.add(beanName);
+				}
+			}
+		}
+
+		@Override
+		public boolean containsVariable(String name) {
+
+			Map<String, Object> modelsMap = models.asMap();
+
+			if (modelsMap.containsKey(name)) {
+				return true;
+			}
+
+			return beanNames.contains(name);
+		}
+
+		@Override
+		public Object getVariable(String name) {
+
+			Object value = models.get(name);
+
+			if (value == null) {
+				value = applicationContext.getBean(name);
+			}
+
+			return value;
+		}
+
+		@Override
+		public Set<String> getVariableNames() {
+
+			Map<String, Object> modelsMap = models.asMap();
+			Set<String> variableNames = new HashSet<>(modelsMap.keySet());
+			variableNames.addAll(beanNames);
+
+			return variableNames;
+		}
+
+	}
+}