But what if you could not only enable or disable the Filter, but also change it's behavior, on the fly at runtime without special build or deploy steps. I was pondering this idea and came up with the concept of a Servlet Filter, that by itself, does nothing.
Nothing? Well, nothing by itself.
"By itself" is the key phrase here. Instead of doing something in the Java code (getting timings, checking security, auditing calls, printing debug statements, etc.) it just instantiates a scripting engine, like BeanShell (BSH), JRuby, Groovy, etc. It starts up the scripting engine, passes the Request and/or Response objects, and runs a script that you have identified. That script does all the meat-n-potatoes work, and the Filter then calls next in chain like it normally would. And the best part is, the script could be changed at runtime, from a simple do-nothing-and-return to full blown screwing around with the Request and Response objects.
I've developed a proof-of-concept (POC) and have it running under Glassfish v2 application server. I used BeanShell for the scripting engine in the POC, but as stated above, any of the scripting engines for the JVM should work. This isn't quite ready for primetime, but it fully works.
There are actually 2 scripts called by this filter, one before the chain.doFilter() call is made, and one after. That way you have the flexibility to do operations either on the request, on the response, or both.
First, the Java code for the Filter:
Then, the 2 BSH scripts:
BSHServletFilter_PRE.bsh
import java.servlet.*;
import java.servlet.http.*;
import java.util.*;
System.out.println("This is the BSHServletFilter_PRE.bsh script!!!");
StringBuffer output = new StringBuffer();
output.append("\nRequest Attributes\n");
Enumeration attrs = request.getAttributeNames();
while (attrs.hasMoreElements()) {
String attr = (String) attrs.nextElement();
output.append(attr +" - " + request.getAttribute(attr));
output.append("\n");
}
output.append("Request Parameters\n");
Enumeration params = request.getParameterNames();
while (params.hasMoreElements()) {
String param = (String) params.nextElement();
output.append(param +" - " + request.getParameter(param));
output.append("\n");
}
System.out.println(output.toString());
System.out.println("This consludes the BSHServletFilter_PRE.bsh script!!!");
BSHServletFilter_POST.bsh
System.out.println("This is the BSHServletFilter_POST.bsh script!!!");
System.out.println("About to alter the response...");
response.getWriter().print("<h1>This response is from the BSH script</h1>");
response.getWriter().flush();
System.out.println("Done altering the response");
And the browser screenshot...
This is currently just at the POC stage. It is working as-is, running under Glassfish. But as you will immediately notice, the filenames for the scripts are hard-coded, and there is definitely some more cleanup to make this production quality code. But, you can change the behaviors of the filter, for better or worse, at runtime without any compiling, deploying, or restarting of servers. You can even "disable" the filter by writing BSH scripts that do nothing.
No comments:
Post a Comment