2016-05-08 3 views
0

В моем текущем проекте я потребляю много строк JSON. Из-за этого я создал метод утилиты для обработки JSONExceptions, созданных инструментами «org.json». Вот мой текущий подход:Изящно обрабатывать ошибки в Java с AspectJ

Мой обработчик JSON

public static <R> R handleJSONException(String operation, String params, String jsonString, FunctionWithJSONString<R> function) { 

    try { 
     return function.process(jsonString); 
    } catch(JSONException jsonEx) { 
     throw new myRunTimeException(
      StatusCode.ERROR_PARSING_JSON, 
      "Error occurred while attempting to parse json: \"" + jsonString + "\"", 
      "JSON parsing error occurred during operation, " + operation ", with params: " + params); 
    } 
} 

Мой пользовательский функциональный интерфейс:

@FunctionalInterface 
public interface FunctionWithJSONString<R> { 
    public R process(String jsonString) throws JSONException; 
} 

Вот пример его использования:

public Object getObjectFromJSONString(final String json) { 

    String operation = "Get an Object from some source"; 
    String params = ""; 

    return handleJSONException(operation, params, json, (jsonString) -> { 
     JSONObject body = new JSONObject(jsonString); 
     return body.getObject("object"); 
    }) 
} 

(Конечно, этот код очень упрощен.Это обычно разделяли на под-методы, а "handleJSONException" ome проверка на json, прежде чем передать его, но это дает его смысл)

Проблема в том, что я не люблю либо иметь эти лямбды каждый раз, когда обрабатываю JSON, либо должен иметь метод processAndHandleJSON, который просто проходит ссылка на метод sub methodJSON каждый раз, когда я общаюсь с JSONExceptions (хотя я предпочитаю этот подход ко всему, что я видел).

Я подумал, что, возможно, я мог бы использовать некоторые ориентированные на аспекты программирования. Итак, я пришел с этим проектом (за исключением класса конфигурации):

аннотацию к сигнализировать объединение точка:

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
public @interface JSONHandler { 
} 

Рекомендация используется в точках соединения:

@Aspect 
public class JSONExceptionAdvice { 

    @Around(@annotation(JSONHandler)) 
    public Object wrapJSONHandlingMethod(ProceedingJoinPoint joinPoint) throws throwable { 
     try { 
      return joinPoint.proceed(joinPoint.getArgs); 
     } catch (JSONException jsonEx) { 
      //Some method that throws the "myRunTimeException" with necessary parameters 
     } 
      return null; 
    } 
} 

Вот бы является примером его использования:

@JSONHandler 
public Object getObjectFromJSON(final String json) { 
    JSONObject body = new JSONObject(json); 
    return body.getObject("object"); 
} 

Однако это не скомпилировано. Чтобы заставить его скомпилировать и угадать этот аспект, ошибка «метод getObjectFromJSON» в сигнатуре «бросает исключение JSONException». Это означало бы, что мне все равно понадобится попробовать/поймать где-нибудь по лестнице. И чтобы усугубить ситуацию, это была бы пустая попытка/уловка, которая выглядит уродливой, или кому-то, кто не знает, что ее обрабатывают ниже, ленивы.

Я бы хотел, чтобы моя аннотация могла подавлять предупреждения «Unhandled JSONException» в компиляторе, но это нелегко сделать из того, что я понимаю. Любые другие идеи, о которых я думал, вернулись к тому, что у меня было раньше, но более подробные и тяжелые.

Есть ли у кого-нибудь идеи о том, как AspectJ можно использовать для достижения желаемой цели в чистом виде? Четко ли сформулирована цель? Может ли кто-нибудь рекомендовать другой подход, который лучше, чем любой из них?

Я рассмотрел другие проблемы в StackOverflow, например Exception handling through spring AOP + Aspectj, но либо они используют пустой try/catch, либо вообще игнорируют проблему необработанного исключения.

P.S. Хотя это специфично для обработки json, я хотел бы применить это к нескольким другим распространенным ошибкам. Поэтому, хотя ответы org.json приветствуются, я, скорее всего, приму наиболее общий ответ.

ответ

0

Не уверен, если я понимаю ваши требования правильно, но если вам нужно, чтобы устранить необходимость поймать отмеченные org.json.JSONException -s (заставить его вести себя, как это было бы RuntimeException), то, что вам нужно, это утверждение AspectJ declare soft. Объявите мягкое оберните ваш проверочный org.json.JSONException с непроверенным org.aspectj.lang.SoftException. Это доступно только с использованием собственного синтаксиса AspectJ, и вам нужно будет переключиться на компилятор AspectJ для компиляции вашего проекта (так что вы не получите ошибки компиляции, чтобы не поймать проверенное исключение или не объявить их размножаться с помощью ключевого слова throws в клиенте методы).

public aspect JSONExceptionAdvice { 

    declare soft: org.json.JSONException: @annotation(JSONHandler); 

    after() throwing(org.json.JSONException e): @annotation(JSONHandler) { 
     System.out.println(e); 
    } 

} 

Обратите внимание, что с after throwing советами вы не подавляете org.json.JSONException, он все равно будет распространяться через стек (хотя это будет размягчается), так что в основном хорошо для целей регистрации. Если вам нужно подавить исключение или выполнить какую-либо другую компенсацию, вам необходимо использовать совет around вместо after throwing.

Смежные вопросы