Hot questions for Using AspectJ in tomcat

Question:

I'm trying to get a list of all deployed applications, and specifically the name of the application mapped to tomcat root. I want to be able to do it during runtime, using a java agent that collects information on the tomcat server. I tried using this code sample:

private Iterable<String> collectAllDeployedApps() {
    try {
        final Set<String> result = new HashSet<>();
        final Set<ObjectName> instances = findServer()
                .queryNames(new ObjectName("Tomcat:j2eeType=WebModule,*"), null);
        for (ObjectName each : instances) {
            result.add(substringAfterLast(each.getKeyProperty("name"), "/")); //it will be in format like //localhost/appname 
        }
        return result;
    } catch (MalformedObjectNameException e) {
         //handle
    }
}

taken from a similar question but since I'm not logged into the manager app, I don't have the right permissions, so I get an empty list.

What I actually want - I have a java agent (based on aspectJ), and I'd like during runtime/deployment time etc. to be able to get the list of all deployed apps without actually logging in to the manager myself. How can I do this? I don't mind instrumenting tomcat's deployment code (which doesn't require any login from my side as I'm already instrumenting the code), but I'm not sure which function to instrument.

Thanks, Lin


Answer:

The question consists of 2 parts:

  • Get a list of all deployed applications - After reviewing Tomcat's API, I found several relevant deployment code parts which can be instrumented: WarWatcher.java (allows to detect changes), and we can also see the apps from - UserConfig.java which is called on startup (instrumentation can be done on setDirectory name etc.), and of course HostConfig.java that is called on stratup:

    protected void org.apache.catalina.startup.HostConfig.deployWARs(java.io.File, java.lang.String[])
    
    protected void org.apache.catalina.startup.HostConfig.deployApps()
    
    protected void org.apache.catalina.startup.HostConfig.deployWAR(org.apache.catalina.util.ContextName, java.io.File)
    

    In addition - you can check the argument for:

    protected boolean org.apache.catalina.startup.HostConfig.deploymentExists(java.lang.String)
    

    It includes the war/folder name (which usually means the application name+-).

  • Get the root application name - This can be done by using ServletContext.getRealPath() - It returns the folder name, from which the war name can be extracted (and can be used, in my case at least as the app name).

Question:

Implemented AOP using AspectJ without Spring. It works perfectly fine when running in Eclipse (Tomcat server) but not when run directly in Tomcat. Have added required dependencies in the pom but of no use. Not able to figure out the issue.

Aspect class:

@Aspect
public class FeatureAOP {
  private static final Logger LOG = LoggerFactory.getLogger(FeatureAOP.class);

  @Pointcut("execution(* x.y.z.rest.ModifiersFacadeWrapper.*(..)) && !execution(* x.y.z.rest.ModifiersFacadeWrapper.getUriInfo(..))")
  protected void pointCut() {
  }

  @Before("x.y.z.rest.aop.FeatureAOP.pointCut()  && this(mf) ")
  public void parseParams(JoinPoint jp, ModifiersFacadeWrapper mf) {
    LOG.info("Entered JoinPoint: {}", jp.getSignature());
    String feature = mf.getUriInfo().getPathParameters().get("feature").get(0);
    Feature featureEnum = Feature.get(feature);
    mf.setFeature(featureEnum);
    LOG.info("Feature set: {}", mf.getFeature());
  }
}

aop.xml:

<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
    <weaver options="-verbose -showWeaveInfo -Xset:weaveJavaxPackages=true -debug">
       	<include within="x.y.z"/>
    </weaver>
	<aspects>
		<aspect id="featureAspect" class="x.y.z.rest.aop.FeatureAOP" ></aspect>
	</aspects>
</aspectj>
  

Answer:

Found solution to this using maven. One needs to add aspectj-maven-plugin in pom.xml.

< plugin >
  < groupId > org.codehaus.mojo < /groupId>
    <artifactId>aspectj-maven-plugin</artifactId >
    < version > 1.4 < /version>
    <configuration>
        <source>1.7</source >
        <target > 1.7 < /target>
    </configuration >
  <executions >
    <execution >
      <goals>
      <goal>compile</goal >
      < /goals>
    </execution >
  < /executions>
  <dependencies>
    <dependency>
        <groupId>org.aspectj</groupId >
        < artifactId > aspectjrt < /artifactId>
        <version>${aspectj.version}</version >
    < /dependency>
    <dependency>
      <groupId>org.aspectj</groupId >
      < artifactId > aspectjtools < /artifactId>
      <version>${aspectj.version}</version >
    < /dependency>
  </dependencies >
< /plugin>

Example: https://github.com/mscharhag/blog-examples/blob/master/exception-translation/pom.xml