реализовать ведение журнала аспектов внутри таймера Java

У меня есть метод, который выдает IOException, который вызывается из таймера java run(). Поскольку run() не возвращает никаких проверенных исключений, и я использую AspectJ для ведения журнала, как мне зарегистрировать исключение в аспекте?

Это мой код:

timer = new Timer(); `

    timer.scheduleAtFixedRate(new TimerTask() {

        public void run() {

            for (OidTypes oidType : typesList) {

                try {
                    valueIncrementOperation(oidType);//------this method throws exception
                } catch (IOException e) {

                    System.out.println("Error occured inside Timer : "
                            + e.getMessage());

                    timer.cancel();
                    timer = null;
                }

            }

` Пока я вынужден использовать try/catch. Каковы мои варианты?


person yonikawa    schedule 13.11.2013    source источник
comment
попробуйте вызвать e.getCause()   -  person Peter Quiring    schedule 14.11.2013
comment
@PeterQuiring: я пытаюсь избавиться от блока try/catch, так откуда мне это вызывать, поскольку аспект не может перехватить run().   -  person yonikawa    schedule 14.11.2013


Ответы (2)


Сначала вам нужно упаковать IOException в непроверенное исключение, реальное исключение будет причиной исключения, которое вы поймаете в совете.

Самый простой — взять RuntimeException.

public void doTimerJob() {
    final Timer timer = new Timer();
    timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            try {
                throw new IOException("file not found");
            } catch (IOException e) {
                timer.cancel();
                throw new RuntimeException(e);
            }
        }
    }, new Date(), 2000);
}

Тогда вы можете попробовать следующее:

Создайте точечный разрез для TimerTask#run

pointcut timerTaskRun() : execution(public * java.util.TimerTask.run(..) );

и совет после создания исключения RuntimeException

after() throwing(RuntimeExceptione) : timerTaskRun() {
    System.out.println("log and rethrow " + e.getCause().getMessage());
}

Это повторно вызовет исключение после его регистрации.

Если вы хотите зарегистрировать и проглотить исключение, вы можете написать совет вокруг

Object around() : timerTaskRun() {
    Object o;
    try {
        o = proceed();   
    } catch(RuntimeException e) {
        System.out.println("log and swallow " + e.getCause().getMessage());
        o = null;
    }
    return o;
}

Обратите внимание, что у вас должен быть только один из советов, либо after throwing, либо around, а не оба.

Но вы можете не захотеть советовать все вызовы TimerTask#run вместе со всеми RuntimeException. В этом случае вы должны создать собственные типы, которые вы должны использовать в точечном разрезе и советах.

"Непроверенный" IOException

public class IOExceptionUnchecked extends RuntimeException {
    private static final long serialVersionUID = 1L;
    public IOExceptionUnchecked(IOException e) {
        super(e);
    }
}

Пользовательская задача таймера

public class MyTimerTask extends TimerTask  {
    Timer owner = null; 
    public MyTimerTask(Timer timer) {this.owner = timer;}
    @Override
    public void run() {
        try {
            throw new IOException("file not found");
        } catch (IOException e) {
            owner.cancel();
            throw new IOExceptionUnchecked(e);
        }
    }
}

Точечный разрез

pointcut timerTaskRun() : execution(public * com.example.MyTimerTask.run(..) );

после брошенного совета:

after() throwing(IOExceptionUnchecked e) : timerTaskRun() {
    System.out.println("log and rethrow " + e.getCause().getMessage());
}

Или совет

Object around() : timerTaskRun() {
    Object o;
    try {
        o = proceed();   
    } catch(IOExceptionUnchecked e) {
        System.out.println("log and swallow " + e.getCause().getMessage());
        o = null;
    }
    return o;
}
person A4L    schedule 14.11.2013
comment
большое спасибо, братан.. ценю время и усилия, которые вы приложили, чтобы опубликовать код и просмотреть все детали... я обязательно попытаюсь реализовать его... еще раз спасибо... - person yonikawa; 14.11.2013
comment
@decentguy Добро пожаловать! Надеюсь, это поможет вам найти способ решить вашу проблему! - person A4L; 14.11.2013

Вы не можете избавиться от блока try/catch, потому что IOException является проверенным исключением, а TimerTask#run объявлено, что оно не вызывает никаких проверенных исключений. Также у вас есть дополнительная логика в блоке catch для отмены таймера.

Ближайшее, что вы можете сделать, это обернуть IOException в RuntimeException и снова бросить его.

   catch(IOException){
        timer.cancel();
        throw new RuntimeException(e);
    }

Даже в этом случае исключение и трассировка стека не будут регистрироваться AspectJ. Для этого вам нужно использовать контейнер (например, Spring), чтобы создать экземпляр TimerTask и обернуть его перехватчиком AspectJ.

person Changgeng    schedule 13.11.2013
comment
спасибо за комментарий, и я использую Spring MVC. Как обернуть экземпляр TimerTask аспектом? - person yonikawa; 14.11.2013
comment
Есть несколько шагов: 1) переместить анонимный класс в класс первого уровня. 2) управлял bean-компонентом с помощью spring либо с помощью аннотации, либо помещая его в файл контекста spring, обратите внимание, что вам может потребоваться использовать область prototype. 3) применить аннотацию, связанную с аспектом - person Changgeng; 14.11.2013