1 2 Previous Next 17 Replies Latest reply on Mar 23, 2008 5:13 PM by Kenneth Christensen

    Direct PDF serving

    m k Newbie


      i have created a pdf with itext directly in my action class and iText is offering me some outputstream options (e.g. ByteArrayOutputStream, ...)

      Now i would like to send this pdf (stream)  to a browser without using a jsf (.xhtml) page. Or is there a tag to this ?
      I do not want to store the pdf on disc if i can avoid it.

      Is this possible ?

      Any ideas are welcome.

      Best regards.


        • 1. Re: Direct PDF serving
          Damian Harvey Apprentice

          Easy. Use the byteArrayOutputStream and hook it up to a servlet. You can keep the byteArrayOutputStream in memory in a conversation/session scoped Bean until the servlet needs it. Use Component.getInstance() in your servlet to access the Bean.



          • 2. Re: Direct PDF serving
            Keith Naas Novice


            Possibly an even easier way that doesn't require writing a custom servlet....write a Seam component that serves up the report - this is the approach we took for the application we demoed at JbossWorld.

            public class ReportAction
                private FacesContext facesContext;
                public void run() 
            final HttpServletResponse resp = (HttpServletResponse) facesContext.getExternalContext().getResponse();
            // run the report            
            // write the report to resp.getOutputStream()

            Then in xhtml

            <h:commandLink action="#{reportAction.run}"/>


            <s:link action="#{reportAction.run}"/>


            Good luck!

            • 3. Re: Direct PDF serving
              m k Newbie

              Thanks Keith,

              that was exactly the solution i was looking for. :-)

              • 4. Re: Direct PDF serving
                Damian Harvey Apprentice


                I gave this a go and it's very cool and easier to implement than the servlet. The only thing that escapes me at the moment is how to assign a filename to the download. With the servlet I used a servlet URL pattern so I could put any name in the link.

                What is the JSF equivalent of that?



                • 5. Re: Direct PDF serving
                  m k Newbie

                  That's easy, you simply have to set the Content-Disposition in the header:

                            final HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
                            response.setHeader("Content-Disposition", " attachment; filename=invoice.pdf");



                  • 6. Re: Direct PDF serving
                    Keith Naas Novice

                    Damian, Manuel has it dead on.  If I remember correctly IE behaves slightly differently than the other browsers so you may or may not see the right filename in all browsers.  I just found this article that describes IE's flakiness.

                    I would have replied sooner, but we just had a record snowfall of 16 inches and I've spent a good part of the day digging out of it!


                    • 7. Re: Direct PDF serving
                      Damian Harvey Apprentice

                      Genius. Thanks Manuel & Keith. Much appreciated.



                      • 8. Re: Direct PDF serving
                        Daniel Roth Apprentice

                        I have used exactly that technique a couple of times, but recently I got notice from quite a few customers that it did not work.

                        The problem was Safari (3+ something, whatever ships with their newest cat-release), where this approch does not work. So we also had to go with the custom servlet approach, which works fine.

                        • 9. Re: Direct PDF serving
                          Ken Hamilton Newbie

                          I implemented the solution described by Keith Naas on 3/6, and it got it working. I'm just learning, so it took a little while. Now that I have it, I would like to expose the servlet so that it is available by direct URL, instead of by JSF commandLink. Is that possible? How would I go about doing that?

                          • 10. Re: Direct PDF serving
                            m k Newbie


                            you can define a link to your action in pages.xml.

                            <page view-id="/pdf.xhtml" action="#{pdfgeneratorAction.generate}"/> 


                            • 11. Re: Direct PDF serving
                              Ken Hamilton Newbie

                              Thanks Manuel. Is there a way to configure it so that the page I use (/pdf.xhtml in your example) doesn't actually have to exist? I can certainly put the page in place, but it seems sort of kludgy, since it never gets displayed, and never should.

                              • 12. Re: Direct PDF serving
                                Ken Hamilton Newbie

                                Thanks for your help. I am new at this, so I'm certain I'm asking questions that would seem stupid to anyone who knows this stuff, but anyway, I have one more thing. I was hoping to pass form information in the request, and use that to manipulate the PDF created. After setting up access through pages.xml, I'm not seeing any parameters in the HttpServletRequest object. I promise I'm not trying to get you to write my code for me, but I'm up against the boundaries of my knowledge.

                                The HTML code that calls this looks like this:

                                <title>Connector test</title>
                                <p> </p>
                                <form action="http://localhost/hbi/services/pdf/test.seam" method="post">
                                <input name="content" id="content" type="text" size=20>
                                <div><input type="submit" value="PDF"></div>

                                My code looks like this, and I'm finding nothing in my parameterMap:

                                public class PrintServer extends SeamResourceServlet {
                                     private static final long serialVersionUID = 1278807414184735439L;
                                    private FacesContext facesContext;
                                     private static Log log;
                                     public void test( String message )
                                           throws ServletException, IOException, DocumentException
                                          final HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
                                          final HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
                                          log.info( "context path: " + request.getContextPath());
                                          log.info( "method: " + request.getMethod());
                                          log.info( "URI: " + request.getRequestURI());
                                          Map parameterMap = request.getParameterMap();
                                          if( parameterMap==null)
                                               log.info( "Can't get parameter names");
                                               log.info("Request Parameters: " + parameterMap.toString());
                                               Collection <Map.Entry> paramCollection =  parameterMap.entrySet();
                                               java.util.Iterator <Map.Entry> paramIterator = paramCollection.iterator();
                                               while( paramIterator.hasNext())
                                                    Map.Entry me = paramIterator.next();
                                                    String [] sa = (String [] ) me.getValue();
                                                    String sValue = "";
                                                    for( int i=0; i<sa.length; ++i )
                                                         sValue += sa[i] + ",";
                                                    log.info("Request Parameter " + me.getKey() + " size " + sValue);
                                               log.info("Request Parameters size: " + parameterMap.size());
                                          log.info("Request Querystring: " + request.getQueryString());
                                          ServletOutputStream out = response.getOutputStream();
                                          Document document = new Document();
                                          PdfWriter.getInstance(document, out);
                                          document.add(new Paragraph("Form message: " + message));
                                          response.setHeader("Content-Disposition", " attachment; filename=PrintTest.pdf");                      
                                          log.info("Run GraphServer.test");

                                • 13. Re: Direct PDF serving
                                  m k Newbie


                                  the beauty of the solution in 3 is, that it does even not use a servlet to deliver the PDF, so you can do everything in a standard seam way by calling an action, create the pdf and deliver it to the browser.

                                  Inside this action you have easy access to all form values.

                                  So why going the hard way ?


                                  • 14. Re: Direct PDF serving
                                    Ken Hamilton Newbie

                                    Thanks for your help Manuel.

                                    Am I going the hard way? I thought I was replicating the solution above. I do see that my code extends the SeamResourceServlet, but I'm not using that interface - it was left over from my servlet approach, and I forgot to remove it.

                                    I restarted my JBoss server (the whole machine, in fact) and now I'm seeing the form information. There must have been something left in my deployment that was interfering, and it got cleaned out by the restart. So the code I provided above works after all.

                                    As a last question, is there a better/simpler way to retrieve the form information than what I do above?

                                    Thanks again.

                                    1 2 Previous Next