I want to handle this exception thrown from Circle.getArea()
method using Aspectj.
Shape.java
package Shapes;
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getPerimeter(){
return 2 * Math.PI * this.radius;
}
public double getArea(){
return Math.PI * this.radius * this.radius;
}
}
Rectangle.java
package Shapes;
public class Rectangle {
private double width, height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public double getPerimeter() {
return 2 * (this.width + this.height);
}
public double getArea() {
return this.width * this.height;
}
}
Circle.java
package Shapes;
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getPerimeter() {
return 2 * Math.PI * this.radius;
}
public double getArea() {
throw new RuntimeException("Oops, I don't know how to calculate this :(");
}
}
Main.java
package Shapes;
public class Main {
public static void main(String[] args) {
try {
Shape s;
s = (Shape) new Rectangle(2, 10);
System.out.println("The area of " + s + " is " + s.getArea());
s = (Shape) new Rectangle(-2, 10);
System.out.println("The perimeter of " + s +" is " + s.getPerimeter());
s = (Shape) new Circle(-2);
System.out.println("The perimeter of " + s +" is " + s.getPerimeter());
s = (Shape) new Circle(2);
System.out.println("The area of " + s + " is " + s.getArea());
}
catch(Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Resolve.aj
package Shapes;
privileged public aspect Resolve {
declare parents: Rectangle implements Shape;
declare parents: Circle implements Shape;
public String Rectangle.getName(){
return "Rectangle";
}
public String Circle.getName(){
return "Circle";
}
public String Rectangle.toString(){
return this.getName()+"("+this.width+","+this.height+")";
}
public String Circle.toString(){
return this.getName()+"("+this.radius+")";
}
after() throwing(RuntimeException e) : execution(* Circle.*()){
handleException();
}
protected void handleException()
{
System.out.println("Error detected");
}
}
The current output is:
The area of Rectangle(2.0,10.0) is 20.0
The perimeter of Rectangle(-2.0,10.0) is 16.0
The perimeter of Circle(-2.0) is -12.566370614359172
Error detected
Error: Oops, I don't know how to calculate this :(
I want to avoid printing "Error: Oops, I don't know how to calculate this :(", and I need to get the real area of the circle object at the end. But, I cannot change any .java file. All changes should be using Resolve.aj file.
You need to use the
around
advice instead of the after:Code output:
Why are we using the around advice instead of the after?
Very informally, an
around
advice intercepts a given joinpoint, and can inject new behavior before, after, and instead of that joinpoint. Theproceed
is a special feature that allows thearound
advice to continue the execution of thejoinpoint
.From the types of advice supported by AspectJ (i.e.,
before
,after
, andaround
), thearound
advice is the only one allowed to return a value and/or use theproceed
. This makes it possible for anaround
advice to execute several times the same joinpoint, or not executed it at all. Furthermore, you can even execute the intercepted joinpoint with a different context (e.g., change the value of the method arguments).More information about how the advice and proceed works can be found on this SO Thread.
Our
around
advice will intercept all the execution joinpoint of the methods from the classCircle
, and will handle accordingly the exceptions thrown by those methods.