MTI TEK
  • Home
  • About
  • LLMs
  • Docker
  • Kubernetes
  • Java
  • All Resources
Java Servlet | Wrapper Classes
  1. Understanding Servlet Wrapper Classes
  2. Available Wrapper Classes
  3. Practical Implementation Example
  4. Common Use Cases and Best Practices

  1. Understanding Servlet Wrapper Classes
    Servlet wrapper classes are decorator pattern implementations that allow you to extend, modify, or restrict the functionality of servlet request and response objects without altering their original implementation. They act as intermediaries between your application code and the actual servlet container objects.

    Wrapper classes are particularly useful in filters and other components where you need to intercept, modify, or enhance the behavior of HTTP requests and responses. They provide a clean way to add functionality such as request parameter validation, response content modification, logging, or security enhancements.

    The wrapper pattern allows you to override specific methods while delegating all other method calls to the wrapped object, maintaining the original contract while adding your custom behavior.
  2. Available Wrapper Classes
    The Servlet API provides four predefined wrapper classes organized in a hierarchical structure. These classes implement the decorator pattern and provide default implementations that delegate to the wrapped object.

    Request Wrapper Classes:
    • jakarta.servlet.ServletRequestWrapper - Base wrapper for ServletRequest
      jakarta.servlet.http.HttpServletRequestWrapper - HTTP-specific request wrapper
      [jakarta.servlet.ServletRequestWrapper] -- implements -- [jakarta.servlet.ServletRequest]
      | extends
      |-- [jakarta.servlet.http.HttpServletRequestWrapper] -- implements -- [jakarta.servlet.http.HttpServletRequest]

    Response Wrapper Classes:
    • jakarta.servlet.ServletResponseWrapper - Base wrapper for ServletResponse
      jakarta.servlet.http.HttpServletResponseWrapper - HTTP-specific response wrapper
      [jakarta.servlet.ServletResponseWrapper] -- implements -- [jakarta.servlet.ServletResponse]
      | extends
      |-- [jakarta.servlet.http.HttpServletResponseWrapper] -- implements -- [jakarta.servlet.http.HttpServletResponse]

    Each wrapper class provides constructors that accept the corresponding request or response object to be wrapped. All method calls are delegated to the wrapped object by default, allowing you to override only the methods you need to customize.
  3. Practical Implementation Example
    The following example demonstrates how to use HttpServletResponseWrapper in a filter to modify response content. This filter appends additional HTML content to the response:
    package com.mtitek.filters.test1;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import jakarta.servlet.Filter;
    import jakarta.servlet.FilterChain;
    import jakarta.servlet.FilterConfig;
    import jakarta.servlet.ServletException;
    import jakarta.servlet.ServletRequest;
    import jakarta.servlet.ServletResponse;
    import jakarta.servlet.http.HttpServletResponse;
    import jakarta.servlet.http.HttpServletResponseWrapper;
    
    public class MyFilter2 implements Filter {
        FilterConfig filterConfig;
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            this.filterConfig = filterConfig;
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            HttpServletResponseWrapper httpServletResponseWrapper = new HttpServletResponseWrapper((HttpServletResponse) servletResponse) {
                private PrintWriter out;
    
                {
                    out = new PrintWriter(((HttpServletResponse) getResponse()).getWriter()) {
                        @Override
                        public void close() {
                            // Override close to prevent premature closure
                        }
    
                        @Override
                        public void flush() {
                            // Override flush to control when content is sent
                        }
                    };
                }
    
                @Override
                public PrintWriter getWriter() throws IOException {
                    return out;
                }
            };
    
            filterChain.doFilter(servletRequest, httpServletResponseWrapper);
    
            PrintWriter out = httpServletResponseWrapper.getWriter();
            out.println("<br /><hr /><br />Add HTML code to the filter ...");
            out.close();
        }
    
        @Override
        public void destroy() {
            // Cleanup resources if needed
        }
    }
    This example creates a custom response wrapper that overrides the getWriter() method to provide a controlled PrintWriter. The wrapper prevents the writer from being closed or flushed prematurely, allowing the filter to append content after the servlet has finished processing.
  4. Common Use Cases and Best Practices
    Servlet wrapper classes are versatile tools that can be applied in various scenarios.

    Common Use Cases:
    • Modifying response content, adding headers, footers, or transforming data before sending it to the client.
    • Validating, sanitizing, or transforming request parameters before they reach the servlet.
    • Implementing security measures such as input validation, XSS protection, or content filtering.
    • Capturing request/response data for auditing, debugging, or performance monitoring purposes.
    • Implementing response compression, character encoding conversion, or content transformation.

    Best Practices:
    • Only override the methods you need to customize. Let the wrapper delegate other calls to maintain the original behavior.
    • When working with streams or writers, ensure proper resource management to avoid memory leaks or connection issues.
    • If your wrapper maintains state, ensure it's thread-safe since servlets handle multiple concurrent requests.
    • Be mindful of performance impact, especially when wrapping frequently called methods or processing large amounts of data.
    • Implement proper error handling to ensure your wrapper doesn't introduce new failure points in the request processing chain.
© 2025 mtitek