Servlet Filter in OSGi enabled web application

Servlet filters are an important component of web application and it can be used in different scenarios, e.g.:

1) Authenticating requests (ServletRequest) before delegating them to your actual business class (Servlet/Controller).
2) Formatting request (ServletRequest) and response data (ServletResponse)
3) Global/Application level Error handling

There are many more uses cases where we can use Servlet filters.
A traditional web application is composed of couple of Business classes & data (model), JSP (views), controllers/servlets and few other resources like css, images etc. All these components are packaged as a WAR file and we deploy it on a web/application server. To add/configure a servlet filter in traditional web application we user web.xml configuration file and tag as:
  1. <filter>  
  2.  <filter-name>springSecurityFilterChain</filter-name>  
  3.  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>  
  4. </filter>  
  5.   
  6. <filter-mapping>  
  7.     <filter-name>springSecurityFilterChain</filter-name>  
  8.     <url-pattern>/*</url-pattern>  
  9.     <dispatcher>REQUEST</dispatcher>  
  10.     <dispatcher>ERROR</dispatcher>  
  11. </filter-mapping>  
  12.         


An OSGi web application is different as compared to traditional web applications. Below are few major differences:

1) Traditional web applications are deployed on web/application server and run under a servlet container whereas OSGi web application are deployed in an OSGi container that has servlet container as an OSGi HTTP service.
2) In traditional web application required libraries/jars are part of WAR file whereas in OSGi web application jar files are installed as OSGi bundles in OSGi container.
3) In traditional web application Filter are configured using web application whereas in OSGi web application Filter are configured/registered using OSGi HTTP service.

As I mentioned, in OSGi web application we don’t configure filters in web.xml file rather we need to register it through OSGi HTTP service, there are two different ways to do this:

1) Create a Filter and register it as an OSGi service in to OSGi HTTP service (ExtHttpService)
2) Create a Filter and make it as an OSGi component (Whiteboard method)
In this post we are going to create a simple filter to encode all request parameters using UTF-8 encoding before passing that request to a servlet/controller. We have used this concept in Adobe/Day CQ5 that uses Apache Felix as OSGi framework for managing OSGi components and services.

1) Create a Filter and register it to OSGi HTTP service
a) Create a class that implements javax.servlet.Filter and add you logic to doFilter() method. Also, if required implement the init() and destroy() to do some initialization and cleanup activities.
  1. public class CharacterEncodingFilter implements Filter {  
  2.  private String encoding = "UTF-8";  
  3.  private Boolean forceEncoding = true;  
  4.  public void init(FilterConfig filterConfig) throws ServletException {  
  5.   try {  
  6.    String encoding = filterConfig.getInitParameter("init.charencoding.filter.encoding");  
  7.    if(encoding != null && encoding.trim().length() >0) {  
  8.     this.encoding = encoding;  
  9.   
  10.    }  
  11.   
  12.    if(filterConfig.getInitParameter("init.charencoding.filter.forceencoding") != null) {  
  13.     Boolean forceEncoding = Boolean.parseBoolean(  
  14.       filterConfig.getInitParameter("init.charencoding.filter.forceencoding"));  
  15.     this.forceEncoding = forceEncoding;  
  16.   
  17.    }  
  18.   } catch (Exception ex) {  
  19.    ex.printStackTrace();  
  20.   }  
  21.  }  
  22.   
  23.  public void doFilter(ServletRequest request, ServletResponse response,   
  24.    FilterChain chain) throws IOException, ServletException {  
  25.   ExtraParamWrappedRequest reqwrapper = new ExtraParamWrappedRequest((HttpServletRequest) request, null);  
  26.   
  27.   if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {  
  28.    Map additionalParams = new HashMap();  
  29.    additionalParams.put("_charset_", new String[]{encoding});  
  30.    reqwrapper = new ExtraParamWrappedRequest((HttpServletRequest) request, additionalParams);  
  31.    reqwrapper.setCharacterEncoding(this.encoding);  
  32.   
  33.    if (this.forceEncoding) {  
  34.     response.setCharacterEncoding(this.encoding);  
  35.    }  
  36.   
  37.   }  
  38.   
  39.   chain.doFilter(reqwrapper, response);  
  40.  }  
  41.   
  42.  public void destroy() {  
  43.   // TODO Auto-generated method stub  
  44.  }  
  45.   
  46.  class ExtraParamWrappedRequest extends HttpServletRequestWrapper {  
  47.   private final Map modifiableParameters;  
  48.   private Map allParameters = null;  
  49.   
  50.   public ExtraParamWrappedRequest(final HttpServletRequest request, final Map additionalParams) {  
  51.    super(request);  
  52.    modifiableParameters = new TreeMap();  
  53.   
  54.    if(additionalParams != null) {  
  55.     modifiableParameters.putAll(additionalParams);  
  56.    }  
  57.   
  58.   }  
  59.   
  60.   @Override  
  61.   public String getParameter(final String name) {  
  62.    String strings = getRequest().getParameter(name);  
  63.   
  64.    if (strings != null)  {  
  65.     return strings;  
  66.    }  
  67.    return null;  
  68.   }  
  69.   
  70.   @SuppressWarnings("unchecked")  
  71.   @Override  
  72.   public Map getParameterMap() {  
  73.    if (allParameters == null) {  
  74.     allParameters = new TreeMap();  
  75.     allParameters.putAll(super.getParameterMap());  
  76.     allParameters.putAll(modifiableParameters);  
  77.    }  
  78.    return Collections.unmodifiableMap(allParameters);  
  79.   }  
  80.   
  81.   @Override  
  82.   public Enumeration getParameterNames() {  
  83.    return Collections.enumeration(getParameterMap().keySet());  
  84.   
  85.   }  
  86.   
  87.   @Override  
  88.   public String[] getParameterValues(final String name) {  
  89.    return getParameterMap().get(name);  
  90.   }  
  91.   
  92.  }  
  93.   
  94. }  

b) Every OSGi bundle has an Activator class, we need to register the filter that we have created in step (a) to OSGi HTTP service in our Activator class by getting the reference of HTTP service (ExtHttpService).

  1. public class Activator implements BundleActivator {  
  2.  private static final Logger log = LoggerFactory.getLogger(Activator.class);  
  3.   
  4.  public void start(BundleContext context) throws Exception {  
  5.   ServiceReference sRef = context.getServiceReference(ExtHttpService.class.getName());  
  6.   
  7.   if (sRef != null) {  
  8.    Dictionary properties = new Hashtable();  
  9.    properties.put("service.pid", CharacterEncodingFilter.class.getName());  
  10.    properties.put("init.charencoding.filter.encoding", "UTF-8");  
  11.    properties.put("init.charencoding.filter.forceencoding", "true");  
  12.    ExtHttpService service = (ExtHttpService) context.getService(sRef);  
  13.    service.registerFilter(new CharacterEncodingFilter(), "/.*", properties, 0, null);  
  14.   }  
  15.  }  
  16.   
  17.  public void stop(BundleContext context) throws Exception {  
  18.   System.out.println(context.getBundle().getSymbolicName() + " stopped");  
  19.  }  
  20.   
  21. }  


2) Create a Filter and make it as an OSGi component

Second method of registering a filter to OSGi container is, creating it as a OSGi component/service. Below are the steps that we need to follow:

a) Create a class that implements javax.servlet.Filter and add you logic to doFilter() method. Also, if required implement the init() and destroy() to do some initialization and cleanup activities. Basically, we can use the same class (CharacterEncodingFilter) that we have created above, the only difference we have in this method is the way of registering a filter.

b) Get hold of OSGi bundle context and register filter as a service as shown below:
  1. public class Activator implements BundleActivator {  
  2.  private ServiceRegistration registration;  
  3.  public void start(BundleContext context) throws Exception {  
  4.   Hashtable props = new Hashtable();  
  5.   props.put("pattern", /.*");  
  6.     props.put("init.message", "Character encoding filter!");  
  7.   props.put("service.ranking", "1");  
  8.   this.registration = context.registerService(Filter.class.getName(), new CharacterEncodingFilter (), props);  
  9.  }  
  10.   
  11.  public void stop(BundleContext context) throws Exception {  
  12.   this.registration.unregister();  
  13.  }  
  14.   
  15. }  

We have seen two different ways of registering filter for a web application that is running under OSGi container so, what’s the difference between these two methods?

An OSGi container may contain multiple OSGi web application and each web application runs under its own bundle context. HTTP service is the service that manages HTTP request/response for all web application deployed under an OSGi container. First method registers filter at HTTP service level (global) and is applied to all request/response across all web application deployed in an OSGi container whereas second method registers a filter at bundle (individual web application) level and gets only executed only when a request is for that particular application/bundle. When we have multiple filters, they can be positioned based on need (which one to execute first and after that and so on) at HTTP service (fourth argument of service.registerFilter method) and individual application bundle level (service.ranking property).
I hope this will help you to understand how Servlets filters works in OSGi enabled web applications.

References:
http://felix.apache.org/site/apache-felix-http-service.html
http://www.eclipse.org/equinox/server/


Thanks
-- Surya
Posted by Suryakand at 4:20 PM

转载于:https://my.oschina.net/yygh/blog/536567

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值