06.18.19

Conditional SDL Experience Manager (XPM) Filters Per Environment

By Jonathan Primmer

Have you ever wanted to deploy the same Java WAR to multiple SDL environments but couldn’t because your WAR contains a web.xml file containing SDL’s XPM filters?

Typically it’s possible to configure your build process to generate the WAR per environment but we didn’t have that luxury.

Instead, we used a CompositeFilter to chain the XPM Page and Binary filters together with conditional logic to check an environment.properties file to decide if the chain should be triggered. This way our web.xml stays the same per environment with our environment.properties file containing an entry to tell us if XPM is enabled.

First we create a custom filter to instantiate the CompositeFilter via conditional logic

@Component("SdlXpmWrapperFilter")
public class SdlXpmWrapperFilter implements Filter {
			
	@Autowired
	@Qualifier("applicationProperties")
	protected ApplicationProperties applicationProperties;
	
    static LoggerUtil logger = LoggerUtil.getInstance(SdlXpmWrapperFilter.class);

    private CompositeFilter compositeFilter;
    private String isXpmEnabled;

	public void init(FilterConfig config) throws ServletException {
		
		logger.debug("in SdlXpmWrapperFilter init()");

		//replace this with your own method of getting environment specific variables
		this.isXpmEnabled = applicationProperties.getMessage("is.xpm.enabled");

		if(("true").equalsIgnoreCase(this.isXpmEnabled))
		{
			this.compositeFilter = new CompositeFilter();
 
			List<Filter> filters = new ArrayList<>();
			filters.add(new ClientPageContentFilter());
			filters.add(new ClientBinaryContentFilter());
		 
			compositeFilter.setFilters(filters);
			
			compositeFilter.init(config);
		}
	}
	
	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException 
	{
		logger.debug("in SdlXpmWrapperFilter doFilter()");
		if(("true").equalsIgnoreCase(this.isXpmEnabled))
		{		
			logger.debug("SDL XPM is enabled on this environment.");
		    this.compositeFilter.doFilter(req, resp, chain);
		}
		else {
			chain.doFilter(req, resp);
		}
	}
	
	@Override
	public void destroy() {
	    this.compositeFilter.destroy();
	}
}

Add the custom filter to the web.xml instead of directly adding com.sdl.web.preview.client.filter.ClientPageContentFilter and com.sdl.web.preview.client.filter.ClientPageContentFilter

<filter>
   <filter-name>SdlXpmWrapperFilter</filter-name>
   <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
   <init-param>
      <param-name>targetFilterLifecycle</param-name>
      <param-value>true</param-value>
   </init-param>
</filter>
<filter-mapping>
   <filter-name>SdlXpmWrapperFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

Finally add the following to the environment.properties files

is.xpm.enabled=false

Notice that we have only one filter in our web.xml which conditionally executes both the Page and Binary filters, meaning that they run on the same filter-mapping. In reality, you may wish to create two custom filters if your Page and Binary filters are on different filter-mappings.

You can find the source files here https://bitbucket.org/jonathanprimmer/sdl-8.5-conditional-xpm-filters-java

CATEGORIES |
Java, SDL, Tridion