JMS asynchrones Mailversenden

JavaExpInc

Mitglied
Hallo zusammen,

ich baue gerade eine kleine Anwendung für mich und diese beinhaltet einen Login. Beim Login wird eine Begrüßungsmail an die User mailadresse (womit sich der User registriert hat) versandt. Dies passiert in einer separaten EJB mit JMS.

Nun möchte ich gerne die "Passwort vergessen" Funktion einbauen und auch eine Mail versenden mit einem zufälligen String der dann das neue Passwort ist. Soweit so gut mein Problem ist nun jedoch das die onMessage() nur einen Übergabeparameter erwartet und ich hatte gedacht das ich noch einen boolean mitgebe (boolean newPw = false -> Willkommensmail, boolean newPw = true -> Mail mit neuem Passwort).

Jetzt frage ich mich ob ich eine komplett neue EJB bauen muss, nur zum Mailversand bei dem neuen Pw oder ob es da nicht eine elegantere Möglichkeit gibt?

z.B. irgendwie etwas in die message bei onMessage(Message message) mitzugeben, in der ich dann auslese ob es sich um ein Pw oder Registrierung handelt. Hat da jemand eine Idee?

Viele Grüße
 

mrBrown

Super-Moderator
Mitarbeiter
Trenn die Logik, das generieren der Mail und das Senden, das sind ja drei unabhängige Aufgaben.

Das Passwort zurücksetzte, eine Nachricht dazu generieren und diese dann versenden kann man wunderbar trennen ;)
 

JavaExpInc

Mitglied
Die Logik habe ich schon getrennt. Ich habe 2 EJB-Module. In Modul A wird der Auftrag erzeugt und zur asynchronen Versendung nach Modul B versandt. Dort wird nun die onMessage methode aufgerufen und die Mailversandt. Modul B beinhaltet auch den Textinhalt der Mail.

In Modul A habe ich die beiden Methoden registrieren und passwort vergessen. Diese rufen dann meine Mail Bean zum produzieren der Mail auf und diese leitet die Anfrage dann ja sozusagen an Modul B weiter (damit dies auch asynchron geschieht).

Nun möchte ich aus der Bean in Modul A wo die Mail erzeugt wird ja etwas anderes mitgeben, sodass Modul B mitbekommt "Hey es geht nun um passwort Vergessen da nehme ich diesen Inhalt der Mail und nicht den fürs Registrieren".

Meiner Meinung nach ist die Logik hier doch schon getrennt oder habe ich etwas übersehen bzw. dich nicht richtig verstanden? :)
 

mrBrown

Super-Moderator
Mitarbeiter
Das was ich meinte:

MailSender* - bekommt fertige Mail (irgendein passendes Objekt) und kümmert sich NUR um das versenden. (entspricht zT deinem B)
Registration* - kümmert sich nur um das Registrieren, nutzt dafür andere Services zum speichern in der DB etc, formatiert die Mail (wofür dann wahrscheinlich irgendein Template-Service genutzt wird) - Mischung aus deine A und B
PasswordReset* - kümmert sich nur um den Reset, analog zu Registration



Für alles gibt es nur eine Zuständigkeit, jedes braucht nur minimale Kenntnisse über alles, etc...
 

JavaExpInc

Mitglied
Aber genauso habe ich es meines Erachtens schon.

Registration*: erstellt den User in der DB (dafür nutzt er einen anderen Service) und spricht wieder eine andere Bean an damit die Mail erstellt wird.
PasswordReset*: resettet das Passwort in der DB (mit anderen Methoden von anderen services) und spricht wieder dieselbe Bean an wie in Registration* damit die Mail erstellt wird. Die Bean die die Mail erstellt spricht dann den anderen EJB Container an wo letztendlich die Mail versandt wird.

Was ich natürlich machen könnte wäre eine zweite Bean die eine Mail erzeugt für PasswortReset* . Sodass ich zwei Beans habe die Mails produzieren. Einmal für PasswortReset* und einmal für Registration*. Wäre das dann charmant gelöst bzw. auch das was du meintest? :)
 

mrBrown

Super-Moderator
Mitarbeiter
Ja, die natürlich gehört das Mail erstellen für beide Fälle getrennt, das war doch mein Punkt? das sind ja völlig unterschiedliche Dinge.

Die Bean, die die Mail versendet, muss überhaupt keine Ahnung vom Inhalt haben, da kann völlig egal sein, zu welchem UseCase die gehört.
 

JavaExpInc

Mitglied
So habe mir das nochmal angeschaut jedoch funktioniert das so nicht wie du und ich uns das gerade gedacht haben. Da ich in der Bean nicht den Mailtext erzeuge sondern nur mit jms TextMessage.createMessage(); und messagte.setText(mail) und mail ist hier nur meine Mailadresse
 

mrBrown

Super-Moderator
Mitarbeiter
So habe mir das nochmal angeschaut jedoch funktioniert das so nicht wie du und ich uns das gerade gedacht haben. Da ich in der Bean nicht den Mailtext erzeuge sondern nur mit jms TextMessage.createMessage(); und messagte.setText(mail) und mail ist hier nur meine Mailadresse
Häh?

So wie das bei dir bisher ist, funktioniert das natürlich nicht auf magische Weise plötzlich anders - du musst das schon entsprechend anpassen, zB nicht TextMessage sondern etwas geeigneteres
 

JavaExpInc

Mitglied
Was meinst du mit etwas geeigneterem?

Momentan sieht es so aus
Java:
      public void sendWelcomeMail(String mail) {
        try (JMSContext context = jmsFactory.createContext(JMSContext.AUTO_ACKNOWLEDGE)){
            TextMessage message = context.createTextMessage();
            message.setStringProperty("DocType", "Letter");
            message.setText(mail);
            context.createProducer().send(outputQueue, message);
        }

und mein Modul B welches die Mail versendet hat die onMessage Methode so
Code:
@Override
    public void onMessage(Message message) {      
            TextMessage msg = (TextMessage) message;
            MultiPartEmail email = new MultiPartEmail();
           email.setHostName("Hostname");
            email.setSmtpPort(XX);
            try {
                email.setFrom("XXX);
                email.addTo(YYYY);
                //email.addTo(msg.getText());
                email.setSubject("Willkommen");
                email.setMsg("hier steht die mail nachricht");
                email.send();
Und es funktioniert soweit nur den Inhalt und Betreff meiner Mail gebe ich erst in meinem Modul B an und sowie du es sagtest müsste ich dies ja auch hier in Modul A machen, was ich aber bislang auch nicht mache und auch gar nicht geht oder?
 
Zuletzt bearbeitet:

mrBrown

Super-Moderator
Mitarbeiter
Benutz doch beim nächsten Mal bitte Code-Tags ([code=java][/code]) ;)




Und es funktioniert soweit nur den Inhalt und Betreff meiner Mail gebe ich erst in meinem Modul B an und sowie du es sagtest müsste ich dies ja auch hier in Modul A machen, was ich aber bislang auch nicht mache und auch gar nicht geht oder?
Was ist denn Modul A und Modul B? Ich hoffe, die heißen nicht wirklich so...
 

mrBrown

Super-Moderator
Mitarbeiter
Ausgehend von dem Oben: Warum bestimmt denn die Bean, die Mails versendet, über den Inhalt, und nicht einfach die Bean, die das Mail versenden anstößt?

Du gehst ja auch nicht zum Briefträger, und sagst dem, du möchtest einen Brief schreiben, sondern gibst dem den geschriebenen Brief...
 

JavaExpInc

Mitglied
Nein Sie heißen natürlich nicht so, habe es zur Vereinheitlich nur so genannt gehabt. Es gibt bei mir zwei EJBs - EJB A beinhaltet eine userBean in der die Methode forgotPW() und registrieren() sind und eine mailBean in der die Methode sendWelcomeMail() steht. Dann gibt es noch EJB B in der meine mailSendBean drin ist mit der Methode onMessage(). Hier wieder nur EJB A und B als vereinfachung so benannt.
 

JavaExpInc

Mitglied
Ausgehend von dem Oben: Warum bestimmt denn die Bean, die Mails versendet, über den Inhalt, und nicht einfach die Bean, die das Mail versenden anstößt?

Du gehst ja auch nicht zum Briefträger, und sagst dem, du möchtest einen Brief schreiben, sondern gibst dem den geschriebenen Brief...
Ja wenn ich wüsste wie ich das änder genauso wie du es sagtest, wäre die Sache klar. Habe ich schon probiert aber ich weiß nicht wie ich das machen soll.
 

mrBrown

Super-Moderator
Mitarbeiter
MailSender* - bekommt fertige Mail (irgendein passendes Objekt) und kümmert sich NUR um das versenden. (entspricht zT deinem B)
Registration* - kümmert sich nur um das Registrieren, nutzt dafür andere Services zum speichern in der DB etc, formatiert die Mail (wofür dann wahrscheinlich irgendein Template-Service genutzt wird) - Mischung aus deine A und B
PasswordReset* - kümmert sich nur um den Reset, analog zu Registration
Naja, viel mehr als das kann man kaum schreiben, ohne fertigen Code zu liefern...


Statt TextMessage musst du etwas anderes, passenderes nehmen (so viel gibts ja da nicht zu Auswahl), was *alle* nötigen Information für die Mail enthält - insbesondere Empfänger und Inhalt.

Die nötigen Daten kommen eben aus den Methoden, die das Registrieren bzw zurücksetzen des Passworts anstoßen.


Das Konzept dahinter ist ja auch völlig unabhängig von EJBs, das lässt sich auch mit einfachen POJOs modellieren.
 

JavaExpInc

Mitglied
Den Code sowie ich ihn habe, habe ich bereits gepostet. Mehr habe ich da ja nicht.

Meinst du ObjectMessage? Wobei dann müsste ich ja ein Objekt haben was ich senden möchte, was ich nicht habe.
 

JavaExpInc

Mitglied
Aber MultiPartEmail erstelle ich mir ja erst bei der onMessage Methode. Ich müsste es ja bei sendWelcomeMail() Methode das Objekt erstellen oder? Ich kann mir das irgendwie noch nicht so richtig vorstellen...
 

mrBrown

Super-Moderator
Mitarbeiter
Aus meiner zweiten Antwort:
MailSender* - bekommt fertige Mail (irgendein passendes Objekt) und kümmert sich NUR um das versenden. (entspricht zT deinem B)
Das ist der Teil mit onMessage, das bekommt *die fertige Mail*, ob das bereits MultiPartEmail ist, oder ein eigenes Mail-Objekt oder eine Map ist egal - es müssen nur *alle* Informationen bereits fertig sein.

Registration* - kümmert sich nur um das [...und] formatiert die Mail [...]
Die Mail wird z.B. in sendWelcomeMail erstellt (bzw dies von dieser an eine entsprechende Methode delegiert).
*Nur* der Teil, der sich um das Registriere (und analog das Zurücksetzen des Passworts kümmert), hat überhaupt die nötigen Informationen, die Mail zu erstellen (zB Kontext, Nutzername, Passwort, ...).


Wo siehst du da irgendwelche Probleme oder Schwierigkeiten?


Code:
[sendWelcomeMail]                      [onMessage]
        |                                 |
Trägt Nutzer in die DB ein                |
        |                                 |
erstellt passende _Mail                   |
        |                                 |
gibt Mail-Objekt weiter -----------> bekommt Mail, gekapselt in sinnvollem Objekt
                                          |
                                      sendet Mail
 

JavaExpInc

Mitglied
Mein Problem ist nicht das verstehen - so hatte ich mir das auch vorgestellt sondern das Objekt erstellen mit dem nötigen password + usermailadresse. Ich habe keine Ahnung wie die MapMessage oder ObjectMessage diese Daten beinhalten kann also wie ich diese setten und getten kann
 

JavaExpInc

Mitglied
Naja, bei ObjectMessage mit setObject und getObject, bei MapMessage mit setTYPE und getTYPE...
Du meinst bei MapMessage.setJMSType()? Weil da kann ich ja nur einen String reinsetzen. Ich muss ja mehr speichern als nur einen String...

entweder das neue PW + Mailadresse oder halt noch mehr also den Header der Mail und den Inhalt der Mail den ich bislang noch in der onMessage() reinschreibe
 

mrBrown

Super-Moderator
Mitarbeiter
Du meinst bei MapMessage.setJMSType()? Weil da kann ich ja nur einen String reinsetzen. Ich muss ja mehr speichern als nur einen String...
Nein, ich meine setString, setByte, setBoolean, ...

entweder das neue PW + Mailadresse oder halt noch mehr also den Header der Mail und den Inhalt der Mail den ich bislang noch in der onMessage() reinschreibe
Joa, eine Map kann beliebig viele Keys fassen, hättest dann halt einen Key "Empfänger" mit dem Empfänger als Value, einen "Betreff" mit dem Betreff, einen "Inhalt" mit dem Inhalt usw...
 

Neue Themen


Oben