9 Replies Latest reply on Aug 16, 2013 8:18 AM by cyberoblivion

    Seam 2.3.0 with icefaces 3.2  exception when rendering email

    cyberoblivion

      I have a simple xhtml  page

       

      <m:message xmlns="http://www.w3.org/1999/xhtml"
                 xmlns:m="http://jboss.org/schema/seam/mail"
                 xmlns:h="http://java.sun.com/jsf/html">    
          <m:from name="Peter" address="peter@example.com" />
          <m:to name="jim@example.com"  >jim@example.com</m:to>
          <m:subject>Try out Seam!</m:subject>
          <m:body>
              <p><h:outputText value="Dear #{person.firstname}" />,</p>
              <p>You can try out Seam by visiting 
                  <a href="http://labs.jboss.com/jbossseam">http://labs.jboss.com/jbossseam</a>.</p>
              <p>Regards,</p>
              <p>Pete</p>
          </m:body>
      </m:message>
      
      

       

      I try to send it using

       

        public void sendTestEmail() {
              try {
                  Renderer.instance().render("/admin/useradmin/testEmail.xhtml");
                  JsfUtils.addInfoMessage("Email sent successfully");
              } catch (Exception e) {
                  JsfUtils.addErrorMessage("Email sending failed: " + e.getMessage());
                  log.error("Email sending failed: ", e);
              }
          }
      
      

       

      but I get an exception in the Renderer.instance().render method

       

      Exception:

       

      at org.icefaces.impl.context.DOMResponseWriter.appendToCursor(DOMResponseWriter.java:395)

                at org.icefaces.impl.context.DOMResponseWriter.writeText(DOMResponseWriter.java:344)

                at org.jboss.seam.mail.ui.context.MailResponseWriter.writeText(MailResponseWriter.java:181)

                at com.sun.faces.facelets.compiler.LiteralTextInstruction.write(LiteralTextInstruction.java:76)

                at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)

                at org.jboss.seam.ui.util.JSF.renderChild(JSF.java:172)

                at org.jboss.seam.ui.util.JSF.renderChildren(JSF.java:163)

                at org.jboss.seam.mail.ui.MailComponent.encode(MailComponent.java:85)

                at org.jboss.seam.mail.ui.MailComponent.encode(MailComponent.java:44)

                at org.jboss.seam.mail.ui.AddressComponent.getInternetAddress(AddressComponent.java:28)

                at org.jboss.seam.mail.ui.RecipientAddressComponent.encodeBegin(RecipientAddressComponent.java:25)

                at org.jboss.seam.ui.util.JSF.renderChild(JSF.java:172)

                at org.jboss.seam.ui.util.JSF.renderChildren(JSF.java:163)

                at org.jboss.seam.mail.ui.UIMessage.encodeChildren(UIMessage.java:192)

                at org.jboss.seam.ui.util.JSF.renderChild(JSF.java:175)

                at org.jboss.seam.ui.util.JSF.renderChildren(JSF.java:163)

                at org.jboss.seam.ui.facelet.RendererRequest.renderFacelet(RendererRequest.java:138)

                at org.jboss.seam.ui.facelet.RendererRequest.run(RendererRequest.java:106)

                at org.jboss.seam.ui.facelet.FaceletsRenderer.render(FaceletsRenderer.java:43)

                at com.ciminc.compass.navigator.admin.comps.UserAdmin.sendTestEmail(UserAdmin.java:101)

       

      I have looked in the appropriate icefaces javacode. and there are variable obviously expecting to not be null at this point.

      here the code snippet from org.icefaces.impl.context.DOMResponseWriter

       

      private Node appendToCursor(String data) { 
      if (cursor == null) { 
      Element doc = document.getDocumentElement(); 
      
      

       

      both cursor and document are null when excecution reaches this point.

       

      This used to work in icefaces 1.8.2 and seam 2.2.2.

       

      My question is why is icefaces even trying to render this content as I have no reference to any icefaces components on this page. Also is there any configuration I can do to avoid this issue?

      Any work arounds or suggestions are appreciated.

       

       

      The workaround I came up with is now attached


        • 1. Re: Seam 2.3.0 with icefaces 3.2  exception when rendering email
          tsimas78

          Hi!

           

          i think you have to try don't use any space or tab between <m:body> and <p> tag (<m:body><p>). after this you can call the render method without error, but it is possible that the html mail doesn't generate correctly. in this situation you should modify MailComponent.java.

          • 2. Re: Seam 2.3.0 with icefaces 3.2  exception when rendering email
            cyberoblivion

            I tried your solution. It has no effect. The page xhtml was actually copied directly from the seam manual so I think it is ok.

             

            I did find a solution to this issue. The idea came from a blog I found http://www.bradchen.com/blog/2011/07/render-facelets-programmatically

            So I created very similar code to set the responsewriter to a custom one and then build and render the children mannually. kind of a hack but best solution for now because icefaces isn't officially supporting seam 2.3.0 yet. Hopefully in the future they will.

             

            Thanks anyway

            1 of 1 people found this helpful
            • 3. Re: Seam 2.3.0 with icefaces 3.2  exception when rendering email
              jonathanmclarke

              Hi Ben,

               

              Do you have a standard framework example for the Seam 2.3.0 and Icefaces 3.2 combination? Did you change the seam-gen process, or build the project manually? Could you provide an example, please? Ideall,y I would like to incorporate Icefaces 3.2 into the seam-gen process so I can generate a stock system and then carry on developing.

               

              Jonathan.

              • 4. Re: Seam 2.3.0 with icefaces 3.2  exception when rendering email
                cyberoblivion

                Jonatha,

                I don't really have a standard framework example so I quickly put one together for you. It was hacked together from an old seamgen project but I put the updates in it for the latest libraries I have been working with.

                Hibernate 4.1.9, Spring 3.2, Icefaces 3.2, Seam 2.3, etc.

                It is a maven3 project but I can't seem to figure out how to attach it..

                Let me know if this would be useful for you I could email it.

                • 5. Re: Seam 2.3.0 with icefaces 3.2  exception when rendering email
                  jonathanmclarke

                  Hi Ben,

                   

                  Yes, that would be very helpful, if you could send to jonathan.m.clarke@o2.co.uk. I have had a conference call with Icesoft management, and support for Seam under Icefaces 3.x and Icefaces Mobile is apparently only going to come if there's a demand for it. They did some work for me to test how easy it is to get Icefaces Mobile working under Seam 2.3, but it's not enough to confidently roll out a production solution. It's difficult to gauge any insight into the demand for that, though, because they support Spring under Icefaces 3.x, so clearly the Spring community want and need it. If you've got any thoughts, it would be nice to generate a bit of interest and get the whole integration going again.

                   

                  Jonathan.

                  • 6. Re: Seam 2.3.0 with icefaces 3.2  exception when rendering email
                    tstolpma

                    I am currently stumbling over exactly the same issue (using Seam 2.3.1 and IceFaces 3.3.0) while rendering mail templates.

                     

                    Has there been any progress on this issue in the meanwhile?

                    • 7. Re: Seam 2.3.0 with icefaces 3.2  exception when rendering email
                      cyberoblivion

                      I attached my workaround to the original post. Hope it helps

                      • 8. Re: Seam 2.3.0 with icefaces 3.2  exception when rendering email
                        tstolpma

                        Thanks for sharing, yet I can not find any solution in the archive, only the example site. Do I miss something?

                         

                        Yet there is another solution I found to avoid triggering the IceFaces renderer: If you can afford to miss HTML based mails the following will work for plain text mail to generate:

                         

                        {code:xml}

                        <m:body type="plain">Dear #{person.firstname}"

                        You can try out Seam by visiting http://labs.jboss.com/jbossseam .

                        Regards,
                        Pete

                        </m:body>

                        {code}

                        • 9. Re: Seam 2.3.0 with icefaces 3.2  exception when rendering email
                          cyberoblivion

                          Sorry yeah that guy was asking a different question. Anyway this is the solution I came up with

                           

                           

                          @Name("faceletStringRender")
                          @Scope(ScopeType.APPLICATION)
                          public class FaceletStringRender implements Serializable {
                              private static Log log = Logging.getLog(FaceletStringRender.class); 
                              @Create
                              public void init() {
                                  log.debug("Creating: faceletStringRender");
                              }
                          
                              /**
                               * Render the Facelets template specified.
                               *
                               * @param template path to the Facelets template
                               * @return rendered content of the Facelets template
                               */
                              public String renderView(String template, FacesContext context) {
                                  try {
                                      // store the original response writer
                                      ResponseWriter originalWriter = context.getResponseWriter();
                          
                                      // put in a StringWriter to capture the output
                                      StringWriter stringWriter = new StringWriter();
                                      ResponseWriter writer = createResponseWriter(context, stringWriter);
                                      context.setResponseWriter(writer);
                          
                                      // create a UIViewRoot instance using the template specified
                                      ViewHandler viewHandler = context.getApplication().getViewHandler();
                                      UIViewRoot view = viewHandler.createView(context, template);
                          
                                      // the fun part -- do the actual rendering here
                                      ViewDeclarationLanguage vdl = viewHandler
                                              .getViewDeclarationLanguage(context, template);
                                      vdl.buildView(context, view);
                                      renderChildren(context, view);
                          
                                      // restore the response writer
                                      if (originalWriter != null) {
                                          context.setResponseWriter(originalWriter);
                                      }
                                      return stringWriter.toString();
                                  } catch (IOException exception) {
                                      log.warn("error rending to string", exception);
                                      throw new RuntimeException(exception);
                                  }
                              }
                            
                              /**
                               * Create ResponseWriter. Taken from FaceletViewDeclarationLanguage.java of
                               * MyFaces.
                               */
                              private ResponseWriter createResponseWriter(FacesContext context,
                                      Writer writer) {
                                  ExternalContext extContext = context.getExternalContext();
                                  Map<String, Object> requestMap = extContext.getRequestMap();
                                  String contentType = (String) requestMap.get("facelets.ContentType");
                                  String encoding = (String) requestMap.get("facelets.Encoding");
                                  RenderKit renderKit = context.getRenderKit();
                                  return renderKit.createResponseWriter(writer, contentType, encoding);
                              }
                          
                          
                              /**
                               * Render a UIComponent. Taken from JSF.java of Seam 2.2.
                               */
                              private void renderChildren(FacesContext context, UIComponent component)
                                      throws IOException {
                                  List<UIComponent> children = component.getChildren();
                                  for (int i = 0, size = component.getChildCount(); i < size; i++) {
                                      UIComponent child = (UIComponent) children.get(i);
                                      renderChild(context, child);
                                  }
                              } 
                          
                              /**
                               * Render the child and all its children components.
                               */
                              private void renderChild(FacesContext context, UIComponent child)
                                      throws IOException {
                                  if (child.isRendered()) {
                                      child.encodeAll(context);
                                  }
                              }
                            
                              public static FaceletStringRender instance() {
                                  return Expressions.instance().createValueExpression("#{faceletStringRender}", FaceletStringRender.class).getValue();
                              }
                          }
                          

                           

                          Then to use it is simple

                           

                           String res = FaceletStringRender.instance().renderView("/admin/emailWelcome.xhtml", FacesContext.getCurrentInstance());