Community
Participate
Working Groups
The following program should not print a stack trace. It does: import java.io.IOException; public aspect SoftenAdviceCall { declare soft: IOException: within(SoftenAdviceCall) && !withincode(* * (..)) && !call(* *(..)); before() : execution(* main(..)) { try { doThrow(); } catch (IOException e) { // swallow } } public static void doThrow() throws IOException { throw new IOException("test"); } public static void main(String args[]) { } } C:\devel\scratch\err>ajc SoftenAdviceCall.aj C:\devel\scratch\err>java SoftenAdviceCall org.aspectj.lang.SoftException at SoftenAdviceCall.doThrow(SoftenAdviceCall.aj:16) at SoftenAdviceCall.ajc$before$SoftenAdviceCall$1$27606269 (SoftenAdviceC all.aj:9) at SoftenAdviceCall.main(SoftenAdviceCall.aj:20) Caused by: java.io.IOException: test ... 3 more Surprisingly, if you add && !execution(* *(..)), then the program behaves as expected I have also found that excluded kinded pointcuts from declare soft seems to actually include them, at least in AJDT!!
Created attachment 28225 [details] this is a log of all the aspect/instance loading done on my startup when weaving into tomcat: showing how important it is to make those reads efficient. Obviously don't include the patch System.err
I traced this through and it seems to be working as expected to me: The declare soft statement matches the following join points: staticinitialization(SoftenAdviceCall) [CORRECT] constructor-execution(SoftenAdviceCall.new()) [CORRECT] initialization(SoftenAdviceCall.new()) [CORRECT] preinitialization(SoftenAdviceCall.new()) [CORRECT] handler(IOException) [CORRECT] adviceexecution() [CORRECT] execution(SoftenAdviceCall.doThrow()) [CORRECT] **** execution(SoftenAdviceCall.main()) [CORRECT] it is correct to soften on execution of doThrow since it is - within(SoftenAdviceCall) - !withincode(* *) (the execution join point is not withincode of anything) - !call(* *(..)) Since doThrow execution is softened, the doThrow join point leaves with a SoftException, which is not then swallowed by your before advice exception handler, and hence the program behaviour. This also explains why adding "!execution(* *(..))" gives the behaviour you expected as it would now be excluding the doThrow execution join point.
That will teach me to write everything in one type... I should have put doThrow in a helper class. But the revised test works so there's no bug.