Using Byteman To Do Advanced Debugging

At my work we develop web application using Java EE with Spring framework. One of our biggest applications has a proxy part to it. Meaning that the request goes into it. Goes through the normal filter chain, through Spring Session, through Spring Security, through a lot of custom interceptors, etc.. At one point this application decides if the current request should be handled by this application it self or proxied to a CMS page rendering micro service. 

This is nice in theory until you try to do this with POST request that has a body. Than you figure out that due to how tomcat is implementing it's request code you can loose the request body when something on the chain asks this request for it's parameters. Tomcat stores this info in a input stream and when for example getParameter is called content of this input stream can be lost.

It's not easy to figure out what piece of code is calling these requests methods. There is not natural place to add break-point to. (If you know of something please let me know I would love to know).

This is where Byteman comes to play. With the help of Byteman I was able to log all the lines of code that were reading request parameters. 

Here is my step by step guide.

1) Login to your server

sudo su tomcat
cd /home/tomcat/
# Use latest if from here http://byteman.jboss.org/downloads.html
wget http://downloads.jboss.org/byteman/4.0.1/byteman-download-4.0.1-bin.zip
unzip byteman-download-4.0.1-bin
mv byteman-download-4.0.1-bin byteman
cd byteman
mkdir rules
# Add rules for each method
vi rules.txt

2) Rules

RULE check getParameterMap
INTERFACE javax.servlet.http.HttpServletRequest
METHOD getParameterMap()
AT ENTRY
IF TRUE
DO traceStack("XXX attempting to read param map ")
ENDRULE
 
RULE check testController
CLASS com.idc.sage.web.controller.getdoc.GetDocOldUrlController
METHOD getDoc(HttpServletRequest)
AT ENTRY
IF TRUE
DO traceStack("XXX attempting to read ")
ENDRULE
 
RULE check getParameter
INTERFACE javax.servlet.http.HttpServletRequest
METHOD getParameter(String)
AT ENTRY
IF TRUE
DO traceStack("XXX attempting to read param value ")
ENDRULE
 
RULE check getParameterValues
INTERFACE javax.servlet.http.HttpServletRequest
METHOD getParameterValues(String)
AT ENTRY
IF TRUE
DO traceStack("XXX attempting to read param values )
ENDRULE
 
RULE check getParameterNames
INTERFACE javax.servlet.http.HttpServletRequest
METHOD getParameterNames(String)
AT ENTRY
IF TRUE
DO traceStack("XXX attempting to read param names ")
ENDRULE
 
RULE check getReader
INTERFACE javax.servlet.http.HttpServletRequest
METHOD getReader()
AT ENTRY
IF TRUE
DO traceStack("XXX attempting to read reader ")
ENDRULE

3) Edit your tomcat settings

vi /usr/local/tomcat/app/bin/setenv.sh
### byteman -  add this line to the start of the file
CATALINA_OPTS="$CATALINA_OPTS -javaagent:/home/tomcat/byteman/lib/byteman.jar=script:/home/tomcat/byteman/rules/rules.txt,sys:/home/tomcat/byteman/lib/byteman.jar"

Restart your server and tail cataliona.out