Page tree
Skip to end of metadata
Go to start of metadata

This page explains how to create and configure a custom Filter. 

Please read about Filters  and request processing which explains some filters used by Magnolia. 

Implementation

To ensure your filter is properly registered using Magnolia configuration, your filter should implement  MgnlFilter  or extend another Magnolia filter which implements MgnlFilter. Extending  AbstractMgnlFilter  is usually a good starting point.

Example:

public class KlackerFilter extends AbstractMgnlFilter{
    @Override
    public void doFilter(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, 
          FilterChain filterChain) throws IOException, ServletException {
        httpServletResponse.setHeader("X-Clacks-Overhead", "GNU Terry Pratchett" );
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }
}

The example above is a dummy example inspired by GNU Terry Pratchett HTTP-Header.

Configuration and Registration of filters

Filters in a Java webapp using servlets 2.5 must be registered in the web.xml. However:

When adding a filter to Magnolia - you should not register it in web.xml but on Magnolia configuration. If the configuration is done properly - filters are registered dynamically by Magnolia.

You can configure filters implementing  MgnlFilter  as well as other filters with Magnolia configuration by using Configuration app. Compared to "classical" web.xml based configuration - you can change the configuration on the running instance. This also includes enabling and disabling a filter.

As with any other configuration data - bootstrap the configuration within your module with a bootstrap file or create an installation task to ensure configuration is set correctly when your project must be reinstalled or deployed.

Add a node to /server/filters

To configure a filter add a node to /server/filters:

Node name


 server


 filters


 klacker


 class

info.magnolia.documentation.examples.templates.KlackerFilter

  enabled

true

class

required

The fully qualified class name of your custom filter (which must implement MgnlFilter ).

enabled

optional, default is true

Setting to false disables the filter.

mappings

optional

Add mappings.


Configuring and registering a filter which does not implement info.magnolia.cms.filters.MgnlFilter

If you have a filter which can not implement  MgnlFilter  for some reason but which should be registered to Magnolia filter chain, your configuration should look like this:

Node name


 filters


 anotherFilter


 class

info.magnolia.cms.filters.FilterDecorator

 decoratedFilter


 class

info.magnolia.documentation.examples.templates.AnotherFilter

 config


 myInitParam

some value

class

required

In this case class must be info.magnolia.cms.filters.FilterDecorator.

decoratedFilter

required

class

required

The fully qualified class name of your custom filter (which does not implement AbstractMgnlFilter ).

config

optional

A map to add filter init parameters. You may add as many parameters as required. The init parameters can be read in the init method of the filter (see below).

Adding filter init parameters

javax.servlet.Filter has an #init method which is called once when the filter is initialized. 

Init parameters for filters implementing info.magnolia.cms.filters.MgnlFilter

When using filters implementing  MgnlFilter  you can use "normal" Node2Bean mechanism. Add bean properties to the filter class and configure appropriately:

 Click here to expand to see the KlackerFilter with bean properties to use for #init
public class KlackerFilter extends AbstractMgnlFilter {
	// bean properties
    private String klackerMessage;
    private int maximumKlackerNumber;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        super.init(filterConfig);
        // use bean properties - here klackerMessage, maximumKlackerNumber - 
        // to do something usefull
    }

    @Override
    public void doFilter(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
		// do something usefull here
        filterChain.doFilter(httpServletRequest, httpServletResponse);
    }


	// getter and setter methods for the bean properties
    public String getKlackerMessage() {
        return klackerMessage;
    }
    public void setKlackerMessage(String klackerMessage) {
        this.klackerMessage = klackerMessage;
    }
    public int getMaximumKlackerNumber() {
        return maximumKlackerNumber;
    }
    public void setMaximumKlackerNumber(int maximumKlackerNumber) {
        this.maximumKlackerNumber = maximumKlackerNumber;
    }
}
 Click here to expand configuration for KlackerFIlter init parameters

Node name


 filters


 klacker


 class

info.magnolia.documentation.examples.templates.KlackerFilter

  enabled

true

 klackerMessage

Klacker messages are save and reliable.

 maximumKlackerNumber

30

Init parameters for filters not implementing info.magnolia.cms.filters.MgnlFilter

If you are using FilterDecorator for custom filters not implementing  MgnlFilter , use the config node to add init parameters (see above). The parameters are set to javax.servlet.FilterConfig and can be used in the init method:

 Click here to expand to see an example how to access an init parameter in a filter using FilterDecorator
public class AnotherFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
		String initParam = filterConfig.get("myInitParam");
		// do something usefull here with the initParam
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 
      throws IOException, ServletException {
		// do something usefull here
        filterChain.doFilter(servletRequest, servletResponse);
    }
    @Override
    public void destroy() {
    }
}

Ensure position in filter chain

Filters are executed in the order they are in the chain, from top to bottom. If you do not care about execution order, you can skip this section, otherwise make sure the filter is in the right position in the chain. 

Magnolia provides task classes to adapt the order of the filter via module version handler. Use FilterOrderingTask or OrderFilterBeforeTask. The code example below is using the FilterOrderingTask.

 When installing a module, you can define the position with ModuleVersionHandler#getExtraInstallTasks.

public class MyModuleVersionHandler extends DefaultModuleVersionHandler {
    @Override
    protected List<Task> getExtraInstallTasks(InstallContext installContext) {
        List<Task> extraInstallTasks = new ArrayList<Task>(super.getExtraInstallTasks(installContext));
        extraInstallTasks.add(new FilterOrderingTask("klacker", new String[]{"contentType"}));
        return extraInstallTasks;
    }
}

The code above would ensure to have the filter "klacker" right after the filter "contentType".

4 Comments

  1. It would be great if you specify the task OrderFilterBeforeTask to order the custom filter before other filters, because the Task class name is completely different and hard to find.

    Cheers

  2. Hello David Caviedes Marquez

    I did not fully understand you. 

    The class info.magnolia.module.delta.FilterOrderingTask - which I was using on the last code example - still exists (on Magnolia 5.6.x - have not checked it on other versions).

    And yes, there is also info.magnolia.module.delta.OrderFilterBeforeTask.

    When I was writing the examples for this page, the FilterOrderingTask was working fine and doing what I was expecting.

    What is your issue? Is FilterOrderingTask not working for you? 
    Do you want me to add another example which is using OrderFilterBeforeTask?

    Kind regards, 
     Christoph


  3. Hello Christoph Meier

    Both classes works great! I only want to say that it would be great if you mention in a Note, Tip or similar in your example that if you need to order a custom filter before another filter, a possible way is to use OrderFilterBeforeTask. I suffered trying to find this class because its name is not similar to FilterOrderingTask hehehe.

    Thanks.

  4. Alright (smile) - Thanks for this clarification