Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[aspectj-users] LTW does not work for some classes under Tomcat

Hello to everyone
I have discovered two problems while using AspectJ in my web application for logging and performance metering. Please, let me know if they are relevant to that mailing list or I should create a bug report or point me to the solution.
My web application uses Spring but I do not use their weaving helpers except for one class because I need to weave not just beans but servlets and and other non-bean classes.
My configuration is simple and straightforward:
aop.xml:
<aspectj>
  <weaver options="-verbose -showWeaveInfo">
     <!-- only weave classes in our application-specific packages -->
     <include within="net.mansion..*"/>
  </weaver>

  <aspects>
     <!-- weave in just this aspect -->
     <aspect name="net.mansion.logging.LoggingAspect"/>
  </aspects>
 </aspectj>


context.xml.default:
 <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
  useSystemClassLoaderAsParent="false" />
code snippet of my LoggingAspect class with annotation:
@Around(... + // a lot of other pointcuts
              " || execution(public void net.mansion.redirect.impl.engine.web.RedirectProcessorServlet.doGet(javax.servlet.http.HttpServletRequest,                                  javax.servlet.http.HttpServletResponse))"  )
  public Object debugMethodLogging(ProceedingJoinPoint joinPoint) throws Throwable {
      return debugMethodLogging(Level.DEBUG, joinPoint);
  }
logging.properties:
handlers= java.util.logging.FileHandler

.level= TRACE

java.util.logging.FileHandler.pattern = D:/logs/aspectj.log
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.FileHandler.level = FINER

org.aspectj.level = FINER

Problem 1: What I have found is that aspect is not applied to my servlet classes. While debugging the AspectJ I discovered that there are racing conditions in Aj.java when I run application under Tomcat. WeavingAdaptor initialization has not been complete yet (see line 254) when Tomcat loads servlet classes using TomcatInstrumentableClassLoader. Thought there are synchronized section but it only ensures that only one instance per classloader will be created. While WeavingAdaptor is not initialized yet and  ClassLoaderWeavingAdaptor's field enabled is false that prevents class from being weaved:
WeavingAdaptor.java (line 294):
if (!enabled) {
  if (trace.isTraceEnabled()) {
  trace.exit("weaveClass", false);
  }
  return bytes;
  }

23.06.2010 18:45:16 org.aspectj.weaver.loadtime.Aj preProcess
FINER: EVENT
23.06.2010 18:45:16 org.aspectj.weaver.tools.WeavingAdaptor weaveClass
FINER: ENTRY org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor@1d0740e
23.06.2010 18:45:16 org.aspectj.weaver.tools.WeavingAdaptor weaveClass
FINER: ENTRY net/mansion/redirect/impl/engine/web/RedirectProcessorServlet/class byte[12079]
23.06.2010 18:45:16 org.aspectj.weaver.tools.WeavingAdaptor weaveClass
FINER: RETURN false
In AspectJ output to stdout there is no messages like "weaving [class name]" or "not weaving [class name]" that could said that class is processed with weaver (no servlet classes mentioned at all).
When initialize method of ClassLoaderWeavingAdaptor is complete, I see that messages but for other classes of my application.
Has any one run into this issue before?
Problem 2: I have tons of ClassNotFoundException in aspectj log for all the classes that are weaved (1-40 exceptions for the single class):
SEVERE: Unable to find class 'java.lang.net.mansion.redirect.impl.engine.web.RedirectProcessorServlet' in repository
java.lang.ClassNotFoundException: java.lang.net.mansion.redirect.impl.engine.web.RedirectProcessorServlet not found - unable to determine URL
 at org.aspectj.apache.bcel.util.ClassLoaderRepository.loadClass(ClassLoaderRepository.java:292)
 at org.aspectj.weaver.bcel.BcelWorld.lookupJavaClass(BcelWorld.java:390)
 at org.aspectj.weaver.bcel.BcelWorld.resolveDelegate(BcelWorld.java:373)
 at org.aspectj.weaver.ltw.LTWWorld.resolveDelegate(LTWWorld.java:111)
 at org.aspectj.weaver.World.resolveToReferenceType(World.java:440)
 at org.aspectj.weaver.World.resolve(World.java:296)
 at org.aspectj.weaver.patterns.SimpleScope.lookupType(SimpleScope.java:59)
 at org.aspectj.weaver.BindingScope.lookupType(BindingScope.java:55)
 at org.aspectj.weaver.patterns.WildTypePattern.lookupTypeInScope(WildTypePattern


Classes are under classpath and loaded with correct classloader. I know that I am not the first one who saw that messages. The problem as I think resides in org.aspectj.weaver.patterns.WildTypePattern and org.aspectj.weaver.patterns.SimpleScope classes. More pecisely in method lookupType:
 public UnresolvedType lookupType(String name, IHasPosition location) {
  for (int i = 0; i < importedNames.length; i++) {
     String importedName = importedNames[i];
     // // make sure we're matching against the
     // // type name rather than part of it
     // if (importedName.endsWith("." + name)) {
     if (importedName.endsWith(name)) {
        return world.resolve(importedName);
     }
  }

  for (int i = 0; i < importedPrefixes.length; i++) {
     String importedPrefix = importedPrefixes[i];
     ResolvedType tryType = world.resolve(UnresolvedType.forName(importedPrefix + name), true);
     if (!tryType.isMissing()) {
        return tryType;
     }
  }

  return world.resolve(UnresolvedType.forName(name), true); // my comment name here is "net.mansion.redirect.impl.engine.web.RedirectProcessorServlet"
 }


I not know why it was decided that imported types has priority over specifyied in annotations (like net.mansion.redirect.impl.engine.web.RedirectProcessorServlet), but this methods tries first to find in scope classes with java.lang prefix and a bunch of other prefixes specific for application. In my case importedPrefixes array was of size 40 and looks like:
importedPrefixes[0] = 'java.lang'
importedPrefixes[1] = 'net.mansion.logging'
importedPrefixes[2] = 'net.mansion.logging'
...
importedPrefixes[39] = 'net.mansion.logging'
Note that in my case there were 39 of completely identical entries in the array. Of course there is no classes in java.lang.net.mansion.redirect package and net.mansion.logging.net.mansion.redirect package as well. It spends significant time while trying to load non-existing classes (I have 22 MB log file consisting mostly from ClassNotFoundException errors).
Actual type is correctly resolved at the return statement: world.resolve(UnresolvedType.forName(name), true).
Turning off the bcel caching does not solve the problem.
Has anyone an idea how to fix that all? I have aready spent 3 days on that stuff :-(
P.S. How to download latest build? It says "access denied" when I try to get the archive:
http://www.eclipse.org/downloads/download.php?file=/tools/aspectj/aspectj-1.6.9.RC1.jar&mirror_id=999&url="">
regards,
Peter

Back to the top