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 FilterChain 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 can stay the same per environment with our environment.properties file containing an entry to tell us if XPM is enabled.

First we created a FilterChain class

 public class FilterChainImpl implements FilterChain {
    private Iterator<Filter> filters;
 
    public FilterChainImpl(Filter... filters) {
        this.filters = Arrays.asList(filters).iterator();
    }
 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        if (filters.hasNext()) {
            Filter filter = filters.next();
            filter.doFilter(request, response, this);
        }
    }
}

We then created a custom filter to instantiate the FilterChain via conditional logic

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

	public void init(FilterConfig config) throws ServletException {	
	}
	
	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException 
	{
		logger.info("in SdlXpmWrapperFilter doFilter()");
		
		//replace this with your own method of getting environment specific variables
		String isXpmEnabled = applicationProperties.getMessage("is.xpm.enabled");

		if(("true").equalsIgnoreCase(isXpmEnabled))
		{
			logger.info("SDL XPM is enabled on this environment.");

			FilterChain filterChain = new FilterChainImpl(
				new ClientBinaryContentFilter(), 
				new ClientPageContentFilter());
			filterChain.doFilter(req, resp);
		}       
		//carry on all other filters in the deployment descriptor (aka web.xml)
	    chain.doFilter(req, resp);
	}
	
	@Override
	public void destroy() {}
}

Our custom filter was added to our 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>
</filter>
<filter-mapping>
    <filter-name>SdlXpmWrapperFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

All that was left was to add the following to our environment.properties files

is.xpm.enabled=false

Notice that has only one filter in our web.xml which runs for 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

Thanks for subscribing to our newsletter!