Tuesday, September 3, 2013

PerfSpy 9 -- AspectJ How To Weave JSP



My daily job is to maintain a hugely-complex-and-wonderfully-interesting legacy application. It was written more than 15 years ago. It structure looks like below:


The big house is JBoss 4.0. For some reason, JBoss 4.0 was tweaked in some mysterious ways, which makes it hard to upgrade to JBoss. So already, the house was not built very strongly (hence it is raining). The two small houses are two web applications deployed onto JBoss – the system is one single web application, and yet there are two WARs. One house is much smaller, and serves a small purpose. Every single page has to be served by two houses. Among other things, this adds complexity to “Jar hell”: some jars have to be placed in A.war, some in B.war, some have to be placed onto the top of the Jboss roof. Not to mention the complex interactions between A.war and B.war. 

There is also an engine house provided by JBoss 4.0: jbossweb-tomcat55.sar which powers A.war and B.war. Tomcat is Jboss’ web application server. 

A.war uses JSP and Struts technologies. B.war is much smaller and uses Servlet technology to handle page requests.

Now we want to monitor JSPs. We all know JSP are eventually turned into Servlet. In Tomcat, the class that does the honor of transforming a JSP into a Servlet is org.apache.jasper.runtime.HttpJspBase, more specifically, your jsp is compiled into a class which inherits from org.apache.jasper.runtime.HttpJspBase, and the content of your jsp is stuffed into _jspService method.




Notice the jsp is compiled into a Servlet class, which has a different name. 

com.myPkg1.myPkg2.myPkg3.myJsp.jsp

becomes
org.apache.jsp.web.com.myPkg1.myPkg2.myPkg3.myJsp_jsp.class 

Use PerfSpy to capture JSP, the JSPPerfspyAspect looks like this:

  • cflow pointcut aims at the superclass:
@Pointcut("cflow (execution(* org.apache.jasper.runtime.HttpJspBase._jspService(..)))")
        public void cflowOps() {
}
  •        during this code flow, captures all application’s method invocations:

  @Pointcut("execution(* com.myPk1..*(..)) ||
execution(*org.apache.jsp.web.myPkg1.._jspService(..))")
        public void withinCflowOps() {
        }
Because JSP is now put into a different package, make sure its method invocations are also included execution(* org.apache.jsp.web.myPkg1.._jspService(..).

Now JSPPerfspyAspect is implemented, where to put this JSPPerfspyAspect? Since A.war uses JSP technology to handle page request, should this JSPAspect be put into A.war/META-INFO/aop.xml? 

No! 


JSP classes are loaded by JasperLoader, while A.war is loaded by WebAppClassLoader. JasperLoader resides in jbossweb-tomcat55.sar, not in A.war. So you should put JSPPerfspyAspect into an aop.xml, and put this aop.xml into jbossweb-tomcat55.sar/WEB-INFO.
 


In AOP.xml, make sure you are weaving the compiled jsp classes:

<include within="org.apache.jsp.web.myPkg1..*"/>

 


 

No comments:

Post a Comment