5 Replies Latest reply on Feb 10, 2013 6:35 PM by mariusz bogucki

    Async e-mail on registration

    Marcos Maia Newbie

      I am having a hard time trying to make seam send an async e-mail on a registration routine. The code works perfectly if I take out the annotation @Asynchronous from the following code:



      //code to call mail template
      @Name("emailRenderer")
      @AutoCreate
      public class EmailRenderer {
           @Logger
           Log log;
           
           @In
           private Renderer renderer;
           
           @Asynchronous
           public void enviaEmailAtivacao()
           {
                log.debug("Entrou no EmailRenderer.enviaEmailAtivacao");
                renderer.render("/emailAtivacao.xhtml");
           }
           
      }



      I have also set the mail session in components.xml



      <mail:mail-session host="smtp...." username="username_here" password="*******"/>



      and xhtml template:



      <m:from name="Anototudo">anototudo@maweb.com.br</m:from>
        <m:to name="#{user.nome}" address="#{user.email}"/>
       <m:subject>Email de confirmação de cadastro do Anototudo!</m:subject>
      ....
      



      Well as I mentioned it is all working fine, sending the e-mail but ONLY using a normal sync call. Whenever I try to send it in an asynchronous way it throws the following exception: 



      22:07:56,879 ERROR [AsynchronousExceptionHandler] Exeception thrown whilst executing asynchronous call
      java.lang.NullPointerException
           at javax.mail.internet.InternetAddress.checkAddress(InternetAddress.java:873)
           at javax.mail.internet.InternetAddress.validate(InternetAddress.java:856)
           at org.jboss.seam.mail.ui.AddressComponent.getInternetAddress(AddressComponent.java:39)
      




      The strange about that is that IT DOES WORK when the @Asynchronous is taken out from the code.


      I have also tryied an approach using Quartz(registering in components.xml, etc) as mentioned in the documentation but server throws the same error.



      Actually I am more used to JMS approach and I am trying to work in a JMS queue solution for this and will get back on it soon. Untill there any help on this will be greatly appreciated.


      :)







        • 1. Re: Async e-mail on registration
          Shervin Asgari Master

          I wrote this a while back.
          Maybe it can help you out.


          My guess is that your user object is null.
          When you are making Asynchronous calls you have to set it in the asynchronous context.
          Thus you should set the user in your enviaEmailAtivacao() method like this:




          public void enviaEmailAtivacao() {
              Contexts.getConversationContext().set("user",user);
          }
          
          



          • 2. Re: Async e-mail on registration
            Shervin Asgari Master

            I saved too fast. Correct code would be:



                 


              @Asynchronous
                 public void enviaEmailAtivacao()
                 {
                            Contexts.getConversationContext().set("user",user);
                      log.debug("Entrou no EmailRenderer.enviaEmailAtivacao");
                      renderer.render("/emailAtivacao.xhtml");
                 }




            • 3. Re: Async e-mail on registration
              Nikolay Elenkov Master

              There is no such thing as a conversation (or session for that matter) inside your asynchronous call. While the above code may work, it is misleading. Use event context instead. Cf, the Seam mail example application:


              @Name("asynchronousMailProcessor")
              @AutoCreate
              public class AsynchronousMailProcessor
              {
                  private static final LogProvider log = Logging.getLogProvider(AsynchronousMailProcessor.class); 
              
                  @Asynchronous
                  public void scheduleSend(@Duration long delay, Person person) {
                   try {
                       Contexts.getEventContext().set("person", person);
                       Renderer.instance().render("/simple.xhtml");
                   } catch (Exception e) {
                       log.error("Error scheduling send #0",e);
                   }
                  }
              }
              



              Using JMS for this may get into more trouble, so stick with async calls :)


              • 4. Re: Async e-mail on registration
                Marcos Maia Newbie

                Hi,


                sorry for taking so long to provide feedback! Just now had the opportunity to get back to this.


                You got it perfectly. It's all working now.


                Just took a look at your mentioned article and it really clarified things for me. Thank you.


                I have tried using timer-service persistence and was not able to. So I am using quartz instead.


                On componentxs.xml


                <async:quartz-dispatcher/>



                Also fixed my implementation to:




                @Asynchronous
                     public void enviaEmailAtivacao(User user)
                     {
                          Contexts.getConversationContext().set("user", user);
                          log.debug("Entrou no EmailRenderer.enviaEmailAtivacao");
                          renderer.render("/emailAtivacao.xhtml");
                     }
                




                It is all working now.


                regards.

                • 5. Re: Async e-mail on registration
                  mariusz bogucki Newbie

                  So if in asynch method there is no conversation context we can not really utilize lazy loading, because than renderer wont be able to access any lazy loaded objects since there is no extended entity manager, in rendered page we can only access objects that are passed as params.

                   

                  am I correct?