10 Replies Latest reply on Jan 17, 2011 7:20 AM by nickarls

    render jsf page in java

    senthilnz

      Hi,

       

      I'm not sure whether this is a right forum to ask, I see this is a J2EE design pattern. I wanted to render a JSF(xhtml) page in java class. Does anyone knows about the api or a sample program? I know there is one available in Seam but I'm not using seam in my application.

       

      Thanks in advance

      SK

        • 1. render jsf page in java
          jaikiran

          S K wrote:

           

          Hi,

           

          I'm not sure whether this is a right forum to ask, I see this is a J2EE design pattern.

          We have a JSF forum. I've moved this thread there.

          • 2. render jsf page in java
            nickarls
            • 3. Re: render jsf page in java
              ssilvert

              Sorry I missed your post before Nicklas.

               

              JSFUnit could certainly do something like that, but since you are only worried about the client-side HTML it would be simpler to just use plain HtmlUnit.

               

              If you have a running JSF application to do the rendering then this is pretty easy with HtmlUnit.

               

              WebClient webClient = new WebClient();
              HtmlPage page = (HtmlPage)webClient.getPage("http://localhost:8080/myjsfapp/mypage.jsf");
              

               

              If you don't have a running JSF application it gets a little tougher.  You could use a mock HttpServletRequest and HtppServletResponse.  Then look at the source code for FacesServlet and see how it uses that to create a FacesContext and render the page.  FacesServlet.java is pretty short and relatively easy to understand.  So you would basically just do what FacesServlet does.

               

              Stan

              • 4. render jsf page in java
                nickarls

                Technically would like to be able to pass a xhtml page to an asynchronous task or such and it would render the template so we're probably talking mocks. Seam 2 had this construct where it used mocks and swapped out the current FacesContext and replaced the output stream with a collecting BAOS if I remember correctly.

                • 5. render jsf page in java
                  ssilvert

                  Yea, it wouldn't be that hard.  It would make a nice open source project.

                   

                  Stan

                  • 6. render jsf page in java
                    senthilnz

                    Actually, my need was not for Unit test rather for runtime render a jsf page and send the output as an email, here I can use seam function but I didn't use seam in my project. Meanwhile I used a different approach to render the jsf page using FacesContext class, here the point is that you must run with active facescontext instance.

                     

                    You can place the below code anywhere in your file,

                     

                    public String renderView(String template) {

                                FacesContext faces = FacesContext.getCurrentInstance();

                                ExternalContext context = faces.getExternalContext();

                               

                                HttpServletResponse response = (HttpServletResponse)

                                        context.getResponse();

                                ResponseCatcher catcher = new ResponseCatcher(response);

                                try {

                                ViewHandler views = faces.getApplication().getViewHandler();

                                // render the message

                                    context.setResponse(catcher);

                                    context.getRequestMap().put("emailClient", true);

                                    views.renderView(faces, views.createView(faces, template));

                                    context.getRequestMap().remove("emailClient");

                                    context.setResponse(response);

                                } catch (IOException ioe) {

                                    String msg = "Failed to render email internally";

                                    faces.addMessage(null, new FacesMessage(

                                            FacesMessage.SEVERITY_ERROR, msg, msg));

                                    return null;

                                }

                                return catcher.toString();

                            }

                     

                    The ResponseCatcher class which extends HttpServletResponse class,

                     

                    /*
                    * To change this template, choose Tools | Templates
                    * and open the template in the editor.
                    */

                    package test;

                    import java.io.CharArrayWriter;
                    import java.io.IOException;
                    import java.io.PrintWriter;
                    import java.util.Collection;
                    import java.util.Locale;
                    import javax.servlet.ServletOutputStream;
                    import javax.servlet.http.Cookie;
                    import javax.servlet.http.HttpServletResponse;

                    /**
                    *
                    * @author SK
                    */
                    public class ResponseCatcher implements HttpServletResponse {
                    /** the backing output stream for text content */
                        CharArrayWriter output;

                        /** a writer for the servlet to use */
                        PrintWriter writer;

                        /** a real response object to pass tricky methods to */
                        HttpServletResponse response;
                        private ServletOutputStream soStream;


                        /**
                         * Create the response wrapper.
                         */
                        public ResponseCatcher(HttpServletResponse response) {
                            this.response = response;
                            output = new CharArrayWriter();//loaded
                            writer = new PrintWriter(output, true);
                        }


                        /**
                         * Return a print writer so it can be used by the servlet. The print
                         * writer is used for text output.
                         */
                        public PrintWriter getWriter() {
                            return writer;
                        }

                        public void flushBuffer() throws IOException {
                            writer.flush();
                        }

                        public boolean isCommitted() {
                            return false;
                        }

                        public boolean containsHeader(String arg0) {
                            return false;
                        }

                        /* wrapped methods */
                        public String encodeURL(String arg0) {
                            return response.encodeURL(arg0);
                        }

                        public String encodeRedirectURL(String arg0) {
                            return response.encodeRedirectURL(arg0);
                        }

                        public String encodeUrl(String arg0) {
                            return response.encodeUrl(arg0);
                        }

                        public String encodeRedirectUrl(String arg0) {
                            return response.encodeRedirectUrl(arg0);
                        }

                        public String getCharacterEncoding() {
                            return response.getCharacterEncoding();
                        }

                        public String getContentType() {
                            return response.getContentType();
                        }

                        public int getBufferSize() {
                            return response.getBufferSize();
                        }

                        public Locale getLocale() {
                            return response.getLocale();
                        }

                        public void sendError(int arg0, String arg1) throws IOException {
                            response.sendError(arg0, arg1);
                        }

                        public void sendError(int arg0) throws IOException {
                            response.sendError(arg0);
                        }

                        public void sendRedirect(String arg0) throws IOException {
                            response.sendRedirect(arg0);
                        }

                        /* null ops */
                        public void addCookie(Cookie arg0) {}
                        public void setDateHeader(String arg0, long arg1) {}
                        public void addDateHeader(String arg0, long arg1) {}
                        public void setHeader(String arg0, String arg1) {}
                        public void addHeader(String arg0, String arg1) {}
                        public void setIntHeader(String arg0, int arg1) {}
                        public void addIntHeader(String arg0, int arg1) {}
                        public void setStatus(int arg0) {}
                        public void setStatus(int arg0, String arg1) {}
                        public void setCharacterEncoding(String arg0) {}
                        public void setContentLength(int arg0) {}
                        public void setContentType(String arg0) {}
                        public void setBufferSize(int arg0) {}
                        public void resetBuffer() {}
                        public void reset() {}
                        public void setLocale(Locale arg0) {}

                        /* unsupported methods */
                        public ServletOutputStream getOutputStream() throws IOException {
                            return soStream;
                        }

                        /**
                         * Return the captured content.
                         */
                        @Override
                        public String toString() {
                            return output.toString();
                        }

                        public String getHeader(String string) {
                            return null;
                        }

                        public Collection<String> getHeaders(String string) {
                            return null;
                        }

                        public Collection<String> getHeaderNames() {
                            return null;
                        }

                        public int getStatus() {
                            throw new UnsupportedOperationException("Not supported yet.");
                        }

                    }

                     

                    I did also rendered jsf page which used CDI injected bean in the page.

                     

                    Thanks

                    SK

                    • 7. render jsf page in java
                      ssilvert

                      If you are running in-container, why not use HtmlUnit and just have the two lines of code like I showed earlier?  You don't need to be in the context of a unit test to use the HtmlUnit API.  HtmlUnit is just a headless browser.

                       

                      Stan

                      • 8. render jsf page in java
                        nickarls

                        So you're saying one could have an application scoped JSF hidden somewhere, bootstrapped with a ServletContext-overridden class and then do the virtual-render-trick by faking what ServletContext does (with mock requests)? That way, e.g. MDB:s could use that virtual-JSF?

                        • 9. render jsf page in java
                          ssilvert

                          Yes, it's doable.  But again, if there is an app server running somewhere you might as well use HtmlUnit and send real HttpRequests to a real FacesServlet running in a real environment.

                           

                          Stan

                          • 10. render jsf page in java
                            nickarls

                            The advantage of the standalone-JSF would perhaps that it could be separetly configurable. And you wouldn't have to trick around with the FacesContext instance. And it could be run in a truly headless mode.

                             

                            I did a quick run in SE and tried to get it running with a mocked ServletContext (run it a pass through the Mojarra 2 ConfigListener SC initialized event) and then another through the FacesServlet init() but I must have gotten something wrong since the FactoryFinder wasn't that cooperative. Although I think you could work against the lifecycle directly like the FacesServlet does, I think.