2017-02-19 3 views
1

Я пытаюсь понять, как обрабатывать обработку исключений здесь. У меня есть мой ниже Singleton класс, который подключается к cassandra, инициализирует все метаданные при первом вызове, а затем запускает периодический фоновый поток, который обновляет все наши метаданные каждые 15 минут.Как справиться с обработкой исключений в одноэлементном шаблоне?

public class CassUtils { 
    private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); 
    private final CassSession cassSession; 

    private static class Holder { 
    private static final CassUtils INSTANCE = new CassUtils(); 
    } 

    public static CassUtils getInstance() { 
    return Holder.INSTANCE; 
    } 

    private CassUtils() { 
    CassConfig config = Utils.getConfig(); 
    try { 
     this.cassSession = new CassSession(config); 
     initializeMetadata(); // initializes metadata on the very first call 
    } catch (Exception ex) { 
     // log error 
     throw new IllegalStateException("cannot initialize metadata: " + ex.getMessage()); 
    } 
    } 

    private void startScheduleTask() { 
    scheduler.scheduleAtFixedRate(new Runnable() { 
     public void run() { 
     try { 
      List<ProcessMetadata> processMetadata = getProcessMeta(); 
      List<ClientMetadata> clientMetadata = getClientMeta(); 
      List<ProcMetadata> procMetadata = getProcMeta(); 
      if (!processMetadata.isEmpty() && !clientMetadata.isEmpty()) 
      MetadataManager.setMetadata(processMetadata, clientMetadata, procMetadata); 
     } catch (Exception ex) { 
      // log error 
     } 
     } 
    }, 30, 15, TimeUnit.MINUTES); 
    } 

    private void initializeMetadata() { 
    List<ProcessMetadata> processMetadata = getProcessMeta(true); 
    List<ClientMetadata> clientMetadata = getClientMeta(); 
    List<ProcMetadata> procMetadata = getProcMeta(); 
    if (processMetadata.isEmpty() || clientMetadata.isEmpty() || procMetadata.isEmpty()) { 
     throw new IllegalStateException(); // is it ok to throw exception without any message here? 
    } 
    MetadataManager.setMetadata(processMetadata, clientMetadata, procMetadata); 
    startScheduleTask(); 
    } 

Мне нужно уведомить вызывающего абонента, который вызывает этот синглтон, если есть какие-либо проблемы.

  • Теперь по какой-либо причине, если CassSession кидает исключение, потому что это класс соединяется с Кассандрой и по какой-то причине не в состоянии подключиться к Кассандре (в основном это никогда не произойдет), то я поймать исключение в catch блоке в классе CassUtils и бросить IllegalStateException пользователям с сообщением в нем.
  • Также скажем, если мы сможем подключиться к cassandra через CassSession (который мы всегда будем), но в методе initializeMetadata, все наши метаданные пустые, то я не хочу продолжать дальше, поэтому я бросаю IllegalStateException без каких-либо сообщение в нем. Это нормально? Потому что в конечном итоге он будет пойман catch блоком класса CassUtils, который бросает исключение на вызывающих пользователей.

Как обрабатывать обработку исключений в однотонных случаях, чтобы мы могли уведомить вызывающего человека, кто звонит в этот синглтон. И правильное исключение: IllegalStateException? Эти вышеприведенные случаи будут выполняться во время первого вызова во время инициализации. Есть ли лучший способ сделать это?

ответ

1

Вы используете статическую/инициализацию класса для создания экземпляра ClassUtils. Как общее правило:

  • Все отмеченные исключения, которые выбрасываются при инициализации класса должны быть пойманным. Компилятор настаивает.
  • Любые незаметные исключения, которые распространяются из статической инициализации классов, в конечном итоге вызовут Error. Даже в тех контекстах, где вы можете поймать эту ошибку, вы столкнетесь с классом, инициализация которого завершилась неудачей. JVM никогда не будет повторять инициализацию, и класс ... и любой другой класс, который зависит от него, будет непригодным.

Так что, если вы должны были иметь дело с этим, вам нужно будет поймать и (соответственно) обработать исключение во время статической инициализации.

Следующая проблема заключается в том, что если вы хотите, чтобы сообщить о неспособности пользователей CassUtils одноточечного, то getInstance() должен возвращать экземпляр CassUtils (или, возможно, подкласс), который способен:

  1. Вспоминая исключение или что-либо другое, сообщившее об ошибке, и
  2. переучивание его вызывающим методам экземпляра в API CassUtils.

Это возможно, но сложный.

И ИМО нежелательно. Я думаю, вам будет лучше не пытаться восстановиться.Не разрешайте инициализировать сеанс Casandra как фатальную ошибку. Если вы не можете этого сделать, то метод getInstance() должен быть методом, который генерирует/отменяет исключение, которое говорит «мы сломаны». По крайней мере, это позволяет избежать необходимости потенциального вызова любого метода CassUtils, чтобы иметь дело с исключением «мы сломаны».


Вы когда-нибудь упоминали о том, что синглеты - плохая идея? Вместо этого подумайте об использовании инъекции зависимостей.

+0

Спасибо за ваше предложение. Как «инъекция зависимостей» поможет мне здесь? Просто пытаясь понять выгоду, я получу с этим. Если вы можете привести пример, почему DI будет лучше подходит здесь с моим примером, тогда я должен подумать об удалении всех синглов, которые у меня есть в моей библиотеке. – user1950349

+0

Ну, для начала он избегает такого беспорядка. Во-вторых, он упрощает тестирование вашей кодовой базы и проще использовать ее повторно. Google "singleton versus dependency injection" –

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