Kihagyás

Notifications

1. Bevezető

A különféle értesítések (notification) küldése a felhasználóknak már minden alkalmazásban alapvető követelmény. Az értesítés fajtája lehet SMS, Email, Push vagy InAPP notification.

Ezek közül a Semi Product az Email és Push értesítések küldéséhez ad beépített megoldást.

SMS esetében mivel szinte minden projekten más lesz a tényleges SMS provider, ezért a már kész keretrendszerben csak az SmsNotificationMediaTypeService.send metódust kell implementálni.

InAPP értesítéseket még a Semi nem implementálta, így ha adott projekten szükséges, akkor a keretrendszer segítségével azt is implementálni kell.

1.1 Értesítések küldése kódból

A keretrendszer lelke a NotificationService és a NotificationMediaTypeService osztályok, rajtuk keresztül történik meg általánosan az értesítések kezelése.

Fejlesztőként a NotificationService.send vagy NotificationService.schedule metódusát kell használnunk, kivéve ha Push esetén topicra akarunk (le/fel) iratkozni.

1.1.1 Email küldése

public void sajatMetodusunk() {
    EmailNotificationMessage notificationMessage = EmailNotificationMessage.builder()
    ...
    .build();

    notificationService.send(notificationMessage);
}

1.1.2 Push küldése

public void sajatMetodusunk() {
    PushNotificationMessage notificationMessage = PushNotificationMessage.builder()
    ...
    .build();

    notificationService.send(notificationMessage);
}

1.1.3 SMS küldése

public void sajatMetodusunk() {
    SmsNotificationMessage notificationMessage = SmsNotificationMessage.builder()
    ...
    .build();

    notificationService.send(notificationMessage);
}

1.1.4 InAPP küldése

public void sajatMetodusunk() {
    InAppNotificationMessage notificationMessage = InAppNotificationMessage.builder()
    ...
    .build();

    notificationService.send(notificationMessage);
}

2. Email notification

2.1 Az SMTP szerver

Ahhoz, hogy az email megérkezzen a címzettekhez egy kiszolgáló szerverre van szükség. Ehhez SMTP (Simple Mail Transfer Protocol) szervert használunk.

A használni kívánt SMTP szervert az application.yml fájlban konfigurálhatjuk a spring.mail szekcióban.

2.1.1 Konfiguráció automata teszteknél

Mivel a teszteknél GreenMail-t használunk így csak az alábbi konfiguráció szükséges az automata tesztek futtatásakor:

spring:
  ...
  mail:
    host: localhost
    port: 3025

2.1.2 Konfiguráció lokális és fejlesztői tesztkörnyezeteknél

Az alkalmazás által kiküldött levelek a maildev szolgáltatásban találhatóak meg. Ez egy lokális smtp mock, amit docker komponensként futtatunk, mint pl az adatbázist is.

Fejlesztői gépen a localhost:1080 címen érhetőek el a levelek. A menüből a relay funkcióval tovább lehet küldeni igazi levelező fiókokba is, ha erre igény lenne.

2.1.3 Címzettek maximális száma

Az SMTP szervereknek különböző limitációi lehetnek arra vonatkozólag, hogy 1 email üzenetnek hány címzettje lehet.

Ennek okán a projekten konfigurálható az 1 email üzenetben megadható maximális címzettek száma. Ezt az application.yml fájl project.notification szekció max-recipients paraméterében adhatjuk meg:

project:
  notification:
    email:
      max-recipients: 999

A gyakorlatban ez a limit annyit jelent, hogy amennyiben a konfigurált értéknél nagyobb számú címzettnek szeretnénk kiküldeni 1 email üzenetet, akkor a rendszer annyi üzenetben küldi ki az emailt hogy egyik üzenet címzettjeinek száma se haladja meg a limitet, de minden címzett megkapja az üzenetet.

Pl.: Ha 2500 címzettnek szeretnénk kiküldeni egy emailt, akkor ha a konfigurált max-recipients limit 1000 akkor 3 üzenetben küldi ki a rendszer az emailt.

2.2 Email template

Manapság egy email üzenetnek nem csak tartalmilag, de formailag is meg kell felelnie az aktuális trendeknek.

Ez a gyakorlatban úgy valósul meg, hogy a mai modern email kliensek képesek a HTML template-et használó email üzeneteket is megjeleníteni. A HTML lehetőséget ad arra, hogy az email üzeneteket igény szerint formázzuk és különféle stíluselemekkel lássuk el.

Ebből következően a projekten is HTML formátumban tároljuk az emailek template-jeit.

A template-ek előállításának megkönnyítésére az MJML Responsive Email Framework-öt használjuk.

A template-ből a HTML-t ezután egy generátor script-tel állítjuk elő.

Az email template-eket az adatbázisban a noti_templates táblában tároljuk és onnan használja az alkalmazás is.

A template beszúrásához szükséges SQL scriptet nem kézzel, hanem generálva állítjuk elő.

2.2.1 Template létrehozása és SQL script generálása

Az email template-ek forrás MJML fájljai a backend-service/websrc/src/notifications/templates/email mappa alatt találhatóak.

Ebbe a mappába kell létrehozni az új MJML template-et. A dinamikus paramétereket az alábbi formátumban kell megadni: ${notification.parameterName}

notification.-el prefixelt paraméternevek

Fontos, hogy az email templatekben a dinamikusan feloldandó paraméterek neveit prefixelni kell a notification. kulcsszóval.

Ennek oka, hogy a template-eket SQL scriptekkel beszúrjuk a noti_templates táblába is. Azonban az SQL scripteket nem kézzel, hanem Liquibase-el futtatjuk, ami bizonyos kulcsszavakat automatikusan felold az SQL scriptek végrehajtásakor. Azért, hogy a Liquibase kulcsszavakkal történő esetleges egyezéseket elkerüljük a saját paramétereinket notification.-el prefixeljük.

A Liquibase projekten történő használatáról részletesebben olvashatsz itt.

Ha feltesszük, hogy az általunk létrehozott template neve: template-name, a feature mappa neve: featureDir akkor az alábbi lépésekkel tudjuk legenerálni az email template adatbázisba történő beszúrásához szükséges scriptet:

  1. Az src könyvtárban lévő notifications/templates/email mappába kell létrehozni az email template-et az emailhez kapcsolódó feature package alá. template-name.mjml néven. Pl.: src/notifications/templates/email/newfeature/template-name.mjml

  2. Miután a template elkészült az src könyvtárban található package.json-ba fel kell venni az új template-hez tartozó build script-et:

    "build-mjml:template-name": "node ./generate-html.js --folder featureDir --filename template-name && node ./generate-sql.js template-name"
    

    Template generálása

    Ezt a scriptet futtatva tudjuk majd legenerálni az új template-hez tartozó HTML-t és SQL scriptet. A scriptet az intelliJ felületét használva is lefuttathatjuk, ha a „play“ ikonra kattintunk: GenerateTemplateFromSQL

    Generált template elérési útvonala

    A generált template-ek a következő elérési útvonalon lesznek elérhetőek: SourceOfGenerateTemplateFromSQL

  3. Ezt követően a package.json fájlban hozzá kell adni a fő build script-hez a előbbi pontban felvett script-et:

    "build-mjml": "npm run build-mjml:client_email_verification && npm run build-mjml:admin_email_verification && npm run build-mjml:auth_user_reset_password && npm run build-mjml:template-name"
    

    Template generálása

    Ezt a scriptet futtatva tudjuk majd legenerálni az összes template-hez tartozó SQL scriptet.

  4. Végül a generate-sql.js fájlba kell felvenni az új template adatait a resources tömbbe:

        {
            fileName: "template-name",
            featureDir: "newfeature",    
            notification_key: "email.notification_key",
            title: "email title",
        }
    
    • A fileName mezőben kell megadni a template fájl nevét.
    • A featureDir mezőben kell megadni a templatehez tartozó feature package nevét.
    • A notification_key mezőben kell megadni, hogy milyen kulccsal kerüljön be a template az adatbázisba.
    • A title mezőben kell megadni, hogy mi legyen a kiküldött email tárgya. (Itt is használhatóak a dinamikus paraméterek az email törzséhez hasonlóan.)

    Az email template-ek valid_from értéke mindig az aktuális dátum lesz. Ha a generálás során kézzel szeretnénk megadni egy specifikus, akár jövőbeli dátumot, akkor a generálás idejére kitölthetjük a resources tömbben a valid_from mezőt is:

        {
            fileName: "template-name",
            featureDir: "newfeature",
            notification_key: "email.notification_key",
            title: "email title",
            valid_from: "2020-02-02 12:00:00 +01:00",
        }
    

    Mikor kell specifikus valid_from értéket definiálni?

    A valid_from mezőben egy olyan dátumot lehet megadni amely dátumtól kezdve szeretnénk, hogy a rendszer az általunk generált template-et használja.

    Ez egy új template esetén nyilván az aktuális dátum kell hogy legyen és ilyenkor a valid_from megadása nem szükséges.

    Azonban amennyiben egy létező template-et módosítunk előfordulhat, hogy az új template-et csak egy bizonyos dátumtól kezdve szeretnénk használni. Ez a dátum a valid_from mezőben adható meg.

    Fontos

    Ha specifikus valid_from értékkel generáljuk a template SQL script-jét, akkor se commitoljuk fel a kitöltött valid_from mezőt. Az alapértelmezetten mindig maradjon üresen a generate-sql.js fájlban.

  5. Ezután lépjünk be a webscr mappába, és installáljuk a node package manager-t.

  6. Főkönyvtárból: cd .\backend-service\websrc\
  7. npm ci

  8. Az npm run build-mjml:template-name parancs futtatása után kapjuk meg a generált SQL scriptet mely az alábbi útvonalon lesz elérhető:
    backend-service/src/main/resources/db/insert_template_name_generated.sql

  9. Az insert_template_name_generated.sql fájl egy ideiglenes fájl amit a repositoryba sem kommitolunk. Ebből következően a Liquibase changeSet-be nem ezt a fájlt kell bekötni. A tartalmát másoljuk át az aktuális feature-höz tartozó SQL fájlunkba.

2.3 Az email küldés tesztelése

Az automata tesztek futtatásakor az email küldés teszteléséhez GreenMail-t használunk.

Ha olyan funkciót fejlesztünk ami email kiküldéssel is jár, akkor azt, hogy a megfelelő címzetteknek kiküldjük-e a megfelelő emaileket az assertThatEmailsWasDeliveredToCorrectTargetEmails metódussal tudjuk ellenőrizni.

Az assertThatEmailsWasDeliveredToCorrectTargetEmails metódus egy EmailCheckDTO-t vár paraméterül, melyben megadható:

  • notificationKey: Az elvárt email értesítés template-jének azonosítója.
  • targetEmails: Az elvárt email címzettjének/címzettjeinek email címe.

2.4 A noti_history tábla

Amikor egy értesítést kiküld a rendszer a hozzá tartozó metaadatokat és magát az email üzenetet is letárolja a noti_history táblában. Így visszakereshetővé válik az email üzenetek kiküldése.

Az hogy a konkrét notification mentésre kerüljön, az application.yml-ben konfigurálható, notification típusonként külön, pl SMS esetében

project:
  notification:
    sms:
      save-to-db: true

2.5 Időzített üzenetek kiküldése

A rendszer támogatja, hogy előre lehessen ütemezni időzített üzeneteket, ehhez a NotificationService.schedule metódusát kell meghívni, majd a rendszer automatán kiküldi adott időpontban az értesítéseket.

Ha a projekt nem szeretné menteni az értesítéseket, akkor az időzített üzenetek csak addig kerülnek tárolásra, ameddig a tényleges kiküldés nem történik meg.

2.6 Push notificationök konfigurálása

Android és iOS esetén Firebase alapon történik meg a push notificationok kiküldése.

Ha a projekten szükséges, akkor konfiguráljuk be a Firebase tutorialok alapján az alkalmazásokat, és az application.yml fájlban beállíthatjuk a firebase-ről letöltött json fájlt a push szekció alatt.