package gov.samhsa.consent2share.web.config;
import gov.samhsa.consent2share.web.config.di.root.PropertyPlaceholderConfig;
import gov.samhsa.consent2share.web.config.di.root.RootConfig;
import gov.samhsa.consent2share.web.config.di.servlet.ServletConfig;
import javax.servlet.HttpConstraintElement;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletSecurityElement;
import javax.servlet.annotation.ServletSecurity.TransportGuarantee;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
/**
* WebApplicationInitializer is used to replace web.xml in Servlet 3.0+
* environments like Tomcat 7.0 and above.
*
* <p>
* Only use this WebApplicationInitializer to register @Configuration classes
*
* <p>
* One application could have multiple WebApplicationInitializer implementations
* which can be used to partition configurations and as well as the old web.xml.
*
* <p>
* One application could have one root web application context which associates
* with the webapp and multiple servlet application contexts each of which
* defines the beans for one Spring servlet's app context.
*
* <p>
* The root web application context is loaded by
* org.springframework.web.context.ContextLoaderListener. <br>
* servlet application context is loaded by
* org.springframework.web.servlet.FrameworkServlet which is the parent class of
* org.springframework.web.servlet.DispatcherServlet.
*
* <p>
* All Spring MVC controllers must go in the servlet application context. <br>
* Beans in servlet application contexts can reference beans in root web
* application context, but not vice versa.
*
* <p>
* In most simple cases, the root application context is unnecessary. It
* is generally used to contain beans that are shared between all servlets and
* filters in a webapp. If you only have one servlet, then there's not really
* much point, unless you have a specific use for it.
*
* <p>
* See the detailed comments below to see how java code corresponds to elements in web.xml.
* And some set up in AbstractAnnotationConfigDispatcherServletInitializer corresponds to <servlet>
* and <servlet-mapping> elements in web.xml.
*
*/
public class AppContextDispatcherServletInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public static final String SERVLET_NAME = "consent2share";
// If returns NOT null, then means same thing as the following elements in
// web.xml:
// <context-param>
// <param-name>contextConfigLocation</param-name>
// <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
// </context-param>
// <listener>
// <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
// </listener>
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
logger.debug("getServletConfigClasses is called.");
// Here we also load PropertyPlaceholderConfig which is defined in di.root package.
// This is because PropertyPlaceholderConfigurer bean in root application context cannot be used by any servlet application context.
// See this link http://asoftwareguy.com/2010/11/19/spring-propertyplaceholderconfigurer-within-web-and-application-context/ from reference
// which quotes what Jürgen Höller said regarding PropertyPlaceholderConfigurer.
return new Class<?>[] { ServletConfig.class, PropertyPlaceholderConfig.class };
}
// <url-pattern>/</url-pattern>
@Override
protected String[] getServletMappings() {
// Map Servlet to "/"
return new String[] { "/" };
}
// <servlet-name>consent2share</servlet-name>
@Override
protected String getServletName() {
logger.debug("Servlet Name: " + SERVLET_NAME);
return SERVLET_NAME;
}
@Override
protected void customizeRegistration(
ServletRegistration.Dynamic registration) {
super.customizeRegistration(registration);
registerSecurityConstraint(registration);
}
// <security-constraint> element in web.xml but at servelet level
private void registerSecurityConstraint(
ServletRegistration.Dynamic registration) {
// HttpConstraintElement corresponds to user-data-constraint element in
// deployment descriptor web.xml.
// https is required.
HttpConstraintElement httpConstraintElement = new HttpConstraintElement(
TransportGuarantee.CONFIDENTIAL);
// ServletSecurityElement corresponds to security-constraint element in
// deployment descriptor web.xml.
ServletSecurityElement servletSecurityElement = new ServletSecurityElement(
httpConstraintElement);
// Configured at one servlet level and one servelet configuration at one
// time.
// But in web.xml, security-constraint element can be configured at
// application level
// and web-resource-collection element is used to fine control the urls
// which could be across multiple servlets
registration.setServletSecurity(servletSecurityElement);
}
// The following two elements in web.xml cannot be specified in Java
// <display-name>consent2share</display-name>
// <description>consent2share application</description>
// Same the following elements in web.xml
// <context-param>
// <param-name>spring.profiles.active</param-name>
// <param-value>profileName</param-value>
// </context-param>
//@Override
//protected WebApplicationContext createRootApplicationContext() {
// WebApplicationContext rootContext = super
// .createRootApplicationContext();
// if (rootContext != null
// && rootContext instanceof ConfigurableApplicationContext) {
// ((ConfigurableApplicationContext) rootContext).getEnvironment()
// .setActiveProfiles("profileName");
// }
// return rootContext;
//}
}