Obsługa wyjątków na produkcji

0

Cześć wszystkim ! Zawsze wyrzucałem swoje wyjątki przez zapis throw new KnowledgeNotFoundException.
Natomiast gdy użyłem JavaMailSender -musiałbyś obsłużyć wyjątek MessagingException, zrobiłem jak zawsze, przez throw. natomiast to trafiło do dużej ilości serwisów i kontrolerów i team lead kazał mi to zamienić. Zrobiłem przez try-catch i e.printStackTrace(), lecz nie jestem pewien czy jest to akceptowane na realnych projektach w prod branch.

Co sądzicie, Czy musiałbym zmienić obsługę MessagingException, albo zostawić tak?

JavaMailConfig.class

    @Bean
    public JavaMailSender getJavaMailSender() {
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost(host);
        mailSender.setPort(port);

        mailSender.setUsername(username);
        mailSender.setPassword(password);
        mailSender.setDefaultEncoding("ISO-8859-2");

        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.transport.protocol", protocol);
        props.put("mail.smtp.auth", isAuth);
        props.put("mail.smtp.starttls.enable", isStartTlsEnable);

        return mailSender;
    }

MailSenderIml.class

    @Override
    public void sendMail(String to, String subject, String context) {
        MimeMessage message = javaMailSender.createMimeMessage();
        MimeMessageHelper helper;
        try {
            helper = new MimeMessageHelper(message, true);
            helper.setFrom(sentFrom);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(context, true);
        } catch (MessagingException e) {
            e.printStackTrace();
        }

        javaMailSender.send(message);
    }
5

Oczywiście że nie jest akceptowalne.Polecam poczytać o logowaniu, np. z użyciem SLF4J, w skrócie logowanie to mechanizm zapisu informacji np. o błędach i to zazwyczaj do plików. Dzięki temu jak błąd się pojawi to możesz znaleźć informacje że się pojawił. A jakaś dodatkowa obsługa zalezy od przypadku, np. przy błędzie wysłania emaili można nakazać ponowną próbkę wysyłki po jakimś czasie.

2

natomiast to trafiło do dużej ilości serwisów i kontrolerów

I dobrze, jak był błąd to musi być hałas.

Generalnie wygląda to jakby kontrakt pomiędzy usługą/komponentem odpowiedzialnym za wysyłanie email'i nie był dobrze zdefiniowany.
Przykładowy kontrakt mógłby wyglądać tak:

  1. Usługa przyjmuje zlecenie wysyłki email'a w trybie fire and forget
  2. Jeżeli email nie można wysłać to nastąpi ponowienie próby wysyłki po 1h, 4h i 1d
  3. Jeżeli email nadal nie może być wysłany to trafi do "deadlettera" oraz powiadomiony zostanie zespół odpowiedzialny za usługę (aka manualna interwencja)
  4. Gdy email zostanie wysłany usługa zlecająca wysłanie przesyłki może dostać powiadomienie zwrotne w postaci eventu EmailSent{key=abc...}. Powiadomienie zwrotne jest wysyłane tylko gdy zleceniodawna tego zażąda ustawiając odpowiednie pole w żądaniu.

Dla komponentu w kodzie, jest prostej i tam rzucenie wyjątku jest akceptowalną sytuacją - ale dużo gorzej będzie obsługiwać retry'ie. Generalnie wysyłkę email najlepiej robić async korzystając po drodze z kolejki nawet jak to jest monolit. Wtedy możesz mieć np. bieda kolejkę w bazie danych i job'a spring'owego który co 5s skanuje tą kolejkę i próbuje nadawać wiadomości.

Generalnie radzę pogadać i ustalić co ta wysłka ma robić i jak ma się integrować z resztą aplikacji bo z opisu który podajesz niewiele wynika.

1

Natomiast gdy użyłem JavaMailSender -musiałbyś obsłużyć wyjątek MessagingException, zrobiłem jak zawsze, przez throw. natomiast to trafiło do dużej ilości serwisów i kontrolerów i team lead kazał mi to zamienić.

No dobra, ale to jest pytanie biznesowe - co się ma stać jeśli wysłanie maila się nie powiedzie? Bo rzucanie wyjątków to generalnie żadne rozwiązanie. Czy np. te maile powinny trafiać na jakąś kolejkę i co jakiś czas próbujesz wysłać te które się nie powiodły? Czy może gdzieś to powinno być sygnalizowane?

Zrobiłem przez try-catch i e.printStackTrace(), lecz nie jestem pewien czy jest to akceptowane na realnych projektach w prod branch.

xD to teraz wyjaśnij mi jak chcesz potem dostać się do tych błędów, skoro printStackTrace pisze na konsole a 99% aplikacji jest odpalana jako serwis i nie ma żadnej konsoli. Równie dobrze mogłeś zrobić pusty catch, bo efekt byłby ten sam. Wyjątki loguje się loggerem, żeby leciały do jakiegoś pliku czy docelowo do ELKa.

0
Shalom napisał(a):

No dobra, ale to jest pytanie biznesowe - co się ma stać jeśli wysłanie maila się nie powiedzie?

Patrząc na kod, to ten try/catch jest tylko dla budowania wiadomości - nawet jak poleci exception i wpadnie w catch, to później i tak spróbuje wysłać xd

0

Crashlytics.

1 użytkowników online, w tym zalogowanych: 0, gości: 1