12 Replies Latest reply on May 1, 2007 9:47 PM by gmarcus

    Renderer is not resolving a variable

    gmarcus

      I need to send an email to a user when they register on my website that includes a link back to the website to confirm their email address. I want to dynamically build the URL depending on the server it is deployed to.

      I am trying to use a variable defined in components.xml:

      <factory name="basePath" value="#{facesContext.externalContext.request.scheme}://#{facesContext.externalContext.request.serverName}:#{facesContext.externalContext.request.serverPort}#{facesContext.externalContext.request.contextPath}/"/>
      

      NOTE: This text is all one line in components.xml. The forum is wrapping the text here for display purposes.

      I have a SLSB that is invoking Renderer to send an email to the user:
       public String register()
       {
       List existing = em.createQuery("select u.username from User u where u.username=#{user.username}")
       .getResultList();
      
       if ( existing.size()==0 )
       {
       // save the user
       user.setValidated(false);
       em.persist(user);
       log.info("Registered new user #{user.username}");
       FacesMessages.instance().add("An account has been created for #{user.username}.");
      
       // setup a verification token
       Token verificationToken = new Token(user.getUsername());
       em.persist(verificationToken);
      
       // place the token hash into the session for use by email verification
       Contexts.getSessionContext().set("outtoken", verificationToken.getHash());
       log.info("Created a new Token for #{user.username}: #0", verificationToken.getHash());
      
       // send an email verification
       try
       {
       renderer.render("/emailverification.xhtml");
       FacesMessages.instance().add("An email has been sent to #{user.email}. Please follow the instructions sent to you via email to complete the registration process.");
       }
       catch (Exception e)
       {
       log.error("Error sending mail", e);
       FacesMessages.instance().add("There was a problem sending your verification email. Please try again later.");
       }
      
       return "success";
       }
       else
       {
       FacesMessages.instance().add("User #{user.username} already exists");
       return null;
       }
       }
      


      emailverification.xhtml
      <m:message xmlns="http://www.w3.org/1999/xhtml"
       xmlns:m="http://jboss.com/products/seam/mail"
       xmlns:s="http://jboss.com/products/seam/taglib"
       xmlns:ui="http://java.sun.com/jsf/facelets"
       xmlns:f="http://java.sun.com/jsf/core"
       xmlns:h="http://java.sun.com/jsf/html">
      
      
       <m:from name="Support" address="no-reply@example.com" />
       <m:to name="#{user.name}">#{user.email}</m:to>
       <m:subject>Email Verification</m:subject>
       <m:body>
       <p><h:outputText value="Dear #{user.name}" />,</p>
       <p>Thank you for registering for a new account.
       In order to use your account,
       you must complete your registration by clicking on the link below.</p>
       <p><a href="#{basepath}/validate.seam?tk=#{outtoken}">Click here</a> to complete your registration.</p>
       <p>Regards,</p>
       <p>Glenn</p>
       </m:body>
      </m:message>
      


      Here is a sample of the email that is generated:
      Dear Bob,
      
      Thank you for registering for a new account. In order to use your account,
      you must complete your registration by clicking on the link below.
      
      /validate.seam?tk=gnqerr
      
      Regards,
      
      Glenn
      



      The raw email message shows that the href is not set correctly:
      From: Support <no-reply@example.com>
      To: Bob <me@glennmarcus.com>
      Subject: Email Verification
      Mime-Version: 1.0
      Content-Type: multipart/mixed; boundary="----=_Part_28_7998763.1178031447360"
      Date: Tue, 1 May 2007 10:57:27 -0400 (EDT)
      
      ------=_Part_28_7998763.1178031447360
      Content-Type: text/html; charset=ISO-8859-1
      Content-Transfer-Encoding: 7bit
      Content-Disposition: inline
      
      
       <p>Dear Bob,</p>
       <p>Thank you for registering for a new account.
       In order to use your account,
       you must complete your registration by clicking on the link below.</p>
       <p><a href="/validate.seam?tk=gnqerr">/validate.seam?tk=gnqerr</a></p>
       <p>Regards,</p>
       <p>Glenn</p>
      ------=_Part_28_7998763.1178031447360--
      



      The other variables #{user.name}, #{user.email}, #{outtoken} ) all get resolved correctly. The #{basepath} does not.

      1) Why doesn't #{basepath} resolve?
      2) Is there a better way to dynamically build an href in an email message being sent by Renderer?

      Thanks,
      Glenn

        • 1. Re: Renderer is not resolving a variable
          christian.bauer

          I think needs a scope, this works for me:

           <factory name="themePath" scope="APPLICATION"
           value="#{facesContext.externalContext.request.contextPath}/themes/#{wikiPreferences.themeName}"/>
          


          Otherwise it defaults to ScopeType.UNSPECIFIED, which I think only works for factory methods declared in a component (the scope of the component is used). I'm surprised that some examples in the documentation show without scope, so my explanation is probably not 100% correct.


          • 2. Re: Renderer is not resolving a variable
            christian.bauer

            The forum stripped out the word < factory > in my response...

            • 3. Re: Renderer is not resolving a variable
              gmarcus

              Sorry, but I submitted the wrong emailverification.xhtml.
              Here is the correct version that generated the email above:
              emailverification.xhtml

              <m:message xmlns="http://www.w3.org/1999/xhtml"
               xmlns:m="http://jboss.com/products/seam/mail"
               xmlns:s="http://jboss.com/products/seam/taglib"
               xmlns:ui="http://java.sun.com/jsf/facelets"
               xmlns:f="http://java.sun.com/jsf/core"
               xmlns:h="http://java.sun.com/jsf/html">
              
              
               <m:from name="Support" address="no-reply@example.com" />
               <m:to name="#{user.name}">#{user.email}</m:to>
               <m:subject>Email Verification</m:subject>
               <m:body>
               <p><h:outputText value="Dear #{user.name}" />,</p>
               <p>Thank you for registering for a new account.
               In order to use your account,
               you must complete your registration by clicking on the link below.</p>
               <p><a href="#{basepath}/validate.seam?tk=#{outtoken}">#{basepath}/validate.seam?tk=#{outtoken}</a></p>
               <p>Regards,</p>
               <p>Glenn</p>
               </m:body>
              </m:message>
              


              • 4. Re: Renderer is not resolving a variable
                gmarcus

                 

                "christian.bauer@jboss.com" wrote:
                I think <factory> needs a scope, this works for me:

                 <factory name="themePath" scope="APPLICATION"
                 value="#{facesContext.externalContext.request.contextPath}/themes/#{wikiPreferences.themeName}"/>
                


                Otherwise it defaults to ScopeType.UNSPECIFIED, which I think only works for factory methods declared in a component (the scope of the component is used). I'm surprised that some examples in the documentation show <factory> without scope, so my explanation is probably not 100% correct.


                I added scope="APPLICATION" and I am still not seeing #{basepath} resolving.

                • 5. Re: Renderer is not resolving a variable
                  pmuir

                  You realise Seam mail does this for you? All you need to do is #{facesContext.externalContext.requestContextPath} is use (or just use an s:link or similar which automatically prepends the requestContextPath).

                  h:outputLink unfortunately doesn't prepend this for you.

                  • 6. Re: Renderer is not resolving a variable
                    pmuir

                    ooops, my english went wrong there!

                    Just use #{facesContext.externalContext.requestContextPath} and you get the whole path of the server - http://www.example.com:8080/app/blah.seam - when you are rendering mail.

                    • 7. Re: Renderer is not resolving a variable
                      gmarcus

                       

                      "petemuir" wrote:
                      ooops, my english went wrong there!

                      Just use #{facesContext.externalContext.requestContextPath} and you get the whole path of the server - http://www.example.com:8080/app/blah.seam - when you are rendering mail.


                      I tried that and I now get the application name, but none of the protocol, port or server.

                      New emailverification.xml
                      <m:message xmlns="http://www.w3.org/1999/xhtml"
                       xmlns:m="http://jboss.com/products/seam/mail"
                       xmlns:s="http://jboss.com/products/seam/taglib"
                       xmlns:ui="http://java.sun.com/jsf/facelets"
                       xmlns:f="http://java.sun.com/jsf/core"
                       xmlns:h="http://java.sun.com/jsf/html">
                      
                      
                       <m:from name="Support" address="no-reply@example.com" />
                       <m:to name="#{user.name}">#{user.email}</m:to>
                       <m:subject>Email Verification</m:subject>
                       <m:body>
                       <p><h:outputText value="Dear #{user.name}" />,</p>
                       <p>Thank you for registering for a new account.
                       In order to use your account,
                       you must complete your registration by clicking on the link below.</p>
                       <p><a href="#{facesContext.externalContext.requestContextPath}/validate.seam?tk=#{outtoken}">#{facesContext.externalContext.requestContextPath}/validate.seam?tk=#{outtoken}</a></p>
                       <p>Regards,</p>
                       <p>Glenn</p>
                       </m:body>
                      </m:message>
                      


                      New generated email source:
                      From: Support <no-reply@example.com>
                      To: Glenn <me@glennmarcus.com>
                      Subject: Email Verification
                      Mime-Version: 1.0
                      Content-Type: multipart/mixed; boundary="----=_Part_30_12739979.1178034355270"
                      Date: Tue, 1 May 2007 11:45:55 -0400 (EDT)
                      
                      ------=_Part_30_12739979.1178034355270
                      Content-Type: text/html; charset=ISO-8859-1
                      Content-Transfer-Encoding: 7bit
                      Content-Disposition: inline
                      
                      
                       <p>Dear Glenn,</p>
                       <p>Thank you for registering for a new account.
                       In order to use your account,
                       you must complete your registration by clicking on the link below.</p>
                       <p><a href="/fresh/validate.seam?tk=jrnncz">/fresh/validate.seam?tk=jrnncz</a></p>
                       <p>Regards,</p>
                       <p>Glenn</p>
                      ------=_Part_30_12739979.1178034355270--
                      
                      


                      • 8. Re: Renderer is not resolving a variable
                        pmuir

                        Which version of Seam?

                        • 9. Re: Renderer is not resolving a variable
                          gmarcus

                           

                          "petemuir" wrote:
                          Which version of Seam?


                          1.2.1.GA

                          • 10. Re: Renderer is not resolving a variable
                            christian.bauer
                            • 11. Re: Renderer is not resolving a variable
                              pmuir

                              sorry - you would need to set the urlBase attribute on m:message for this to work (this is prepended)

                              • 12. Re: Renderer is not resolving a variable
                                gmarcus

                                After re-installing seam, rebuilding my app and trying different debugging patterns, I found the issue:

                                I was using #{basepath} and not #{basePath}

                                I just learned that case matters.
                                Sorry to waste everyone's time.