10

I just started playing with AspectJ (1.6.11). I'm sending emails via commons-email libary and I'd like to know how long it takes to send a message. So this is my email sending code:

import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;

public class EmailTest
{
    public static void main(String[] args) throws EmailException
    {
        Email e = new SimpleEmail();
        e.setHostName("localhost");
        e.setFrom("foo@localhost");
        e.addTo("batto@localhost");
        e.setSubject("Test " + System.currentTimeMillis());
        e.setMsg("Message");
        e.send();
    }
}

and this is my aspect:

public aspect EmailAspect
{
    private long start;

    pointcut conn() : call(* javax.mail.Transport.send(..));

    void around() : conn() {
        start = System.currentTimeMillis();
        Throwable t = null;
        try {
            proceed();
        }
        catch(Throwable _t) {
            t = _t;
        }
        long spent = System.currentTimeMillis() - start;
        System.out.println("Send time: " + spent);
        if (t != null) {
            throw new RuntimeException(t);
        }
    }
}

However when I compile it with:

java -jar ../lib/aspectjtools-1.6.11.jar -cp "$CLASSPATH" -source 6 Email*{java,aj}

I get following warning:

/home/batto/work/ajtest/test/EmailAspect.aj:8 [warning] advice defined in EmailAspect has not been applied [Xlint:adviceDidNotMatch]


1 warning

And of course aspect doesn't work. I tried before()/after() advices, different patterns in call(), but it all ended up with same warning.

I debugged the the program in Eclipse (with commons-email sources) and I know that Transport.send() gets executed.

What is the problem?

Thank you.

UPDATE

So I've just figured out that I need source code of javax.mail.Transport for the method of weaving I used (source weaving). So I used binary weaving and it worked. However I changed my mind and now I want to measure time of java.net.Socket.connect(..) (org.apache.commons.mail.Email.send(..) calls javax.mail.Transport.send(..) which calls java.net.Socket.connect(..), I verified it by debugging in Eclipse). But I don't want to include whole JDK in my compiled code. So I tried load-time weaving. This is my modified aspect:

public aspect EmailAspect {
    // Some day I'll learn what's the difference between call() and execution()
    pointcut conn() :
        call(* java.net.Socket.connect(..)) ||
        execution(* java.net.Socket.connect(..));

    before() : conn() {
        System.out.println("It works");
    }
}

And this steps I did to compile & run program:

$ mkdir META-INF
$ cat >META-INF/aop.xml
<aspectj>
  <aspects>
    <aspect name="EmailAspect"/>
    <!-- I think this is not neccessary -->
    <include within="java..*"/>
    <include within="javax..*"/>
  </aspects>
  <weaver>
    <include within="java..*"/>
    <include within="javax..*"/>
  </weaver>
</aspectj>
$ # add jars from ../lib to CLASSPATH
$ javac -source 6 EmailTest.java
$ java -jar ../lib/aspectjtools-1.6.11.jar -cp ".:$CLASSPATH" -source 6 EmailAspect.aj
$ java -cp ".:$CLASSPATH" -javaagent:../lib/aspectjweaver-1.6.11.jar EmailTest

But it doesn't work :(.

batto
  • 171
  • 1
  • 2
  • 10

2 Answers2

3

So I've just sovled the problem with load-time weaving. I changed aop.xml to:

<aspectj>
  <aspects>
    <aspect name="EmailAspect"/>
  </aspects>
  <weaver options="-verbose -Xset:weaveJavaxPackages=true -Xset:weaveJavaPackages=true">
  </weaver>
</aspectj>

I found answer here https://bugs.eclipse.org/bugs/show_bug.cgi?id=149261#c11 (and also AspectJ runtime was reporting that I need to supply -Xset:weaveJavaxPackages=true option all the time, I was just too dumb :().

batto
  • 171
  • 1
  • 2
  • 10
0

A quick check on the apache documentation seems to show that neither Email nor SimpleEmail are instances of Transport. Change the pointcut to:

pointcut conn() : call(* SimpleEmail.send(..));
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
anjosc
  • 923
  • 7
  • 13
  • Yeah, but Email.send() calls Transport.send(..). Anyway I got it working (I updated the question) with binary weaving. Now problem changed to not working load-time weaving. – batto Jun 07 '11 at 11:29
  • Also I added execution() "predicate" with same pattern to pointcut (I don't know what's the difference yet but it doesn't matter right now). – batto Jun 07 '11 at 11:42
  • @batto there is no way to achieve this through compile time weaving (CTW) ? – manocha_ak Nov 28 '14 at 09:11