13 Replies Latest reply on Apr 27, 2014 1:02 PM by sweety senorita

    saving pdf before rendering it to ui

    Pulkit Mehra Newbie
      Hi All,

      I am using seam-pdf.jar(i-text) for pdf generation.
      According to my business logic before rendering pdf to user i need to save it in some contenet management system(say alfresco) for future reference.

      I need byte[] of generated pdf.

      I am new to seam and what i have learned is that pdf generation in seam is on-the-fly and only last one conversation.

      Code i have written is


      ========================================================
      @Stateful
      @Name("ApostillePDFGeneratorContext")
      @Scope(ScopeType.CONVERSATION)
      public  class ApostillePDFGeneratorContextBean implements ApostillePDFGeneratorContext {
             

             
      // calling it from ui  
        public String generatePDF(){
                      tryIt();
                      return "appostillingTemplate";
              }
             
             
      //Tweak : hard coded id...how to get id at runtime..not known as of now but id per converation is always one(observation)
             
      @Begin
      private void tryIt(){
      EmptyFacesContext emptyFacesContext = new EmptyFacesContext();

      byte[] bytes = null;

      try {

      Renderer renderer = Renderer.instance();
      renderer.render("/view/ApositllePDFTemplate.xhtml");
                             
                                                         Context conversation = Contexts.getConversationContext();
                         
                                                  DocumentStore store=DocumentStore.instance();

      //I HAVE HARD CODED ID AS "1".(dont to how to get docID)                                               DocumentData data=store.getDocumentData("1");

      bytes=data.getData();
      } finally {
         emptyFacesContext.restore();
      }
        endConversation();
      }
             
      @End
      private void endConversation(){
      System.out.println("pdf conversation ended");  
      }
             
      }


      ==================================================

      public class EmptyFacesContext extends MockFacesContext {

         FacesContext originalFacesContext;

      public EmptyFacesContext(){
          super(new MockExternalContext());
      originalFacesContext =FacesContext.getCurrentInstance();
              createViewRoot();
                     
              FacesContext.setCurrentInstance(this);
          }

          public void restore(){
               setCurrentInstance(originalFacesContext);
          }

      }

      ========================================================

      My Propblem(s) :
      1) how to get docID at runtime
      2)Is there any other way to save pdf before rendering it.

      Any help would be really appreciated.
      Thanks in advance.

      Best Regards,
      Pulkit Mehra
        • 2. Re: saving pdf before rendering it to ui
          Pulkit Mehra Newbie

          Hi Robert,

          Thanks for the reply.Your sugesstion really helped me but i am stuck in below piece of code.

          ===============================================================
          DocumentStore store=DocumentStore.instance();

          //I HAVE HARD CODED ID AS "1".(dont know how to get docID of generated PDF)

          DocumentData data=store.getDocumentData("1");

          Bytes[] bytes=data.getData();

          ===============================================================

          problems faced:

          1)I am not able to get docID of generated pdf by using API's.

          Any reply would be really appriciated.
          Thanks in advance.

          Regards,
          Pulkit
          • 3. Re: saving pdf before rendering it to ui
            Robert Morse Apprentice

            In your p:document tag, add this:


            exportKey="#{someSeamComponent.documentKey}"


            (Obviously, the component name and attribute are arbitrary).


            Then, when you get the data from the DocumentStore, reference the documentKey attribute.


            If you wanted to make your hardcoded example work, simply add this to your p:document tag and you should be all set:


            exportKey="1"


            Here's a complete example from something I'm working on:




            <p:document xmlns:ui="http://java.sun.com/jsf/facelets"
                 xmlns:f="http://java.sun.com/jsf/core"
                 xmlns:p="http://jboss.com/products/seam/pdf" type="PDF"
                 pageSize="LETTER" orientation="portrait" margins="72 72 72 72"
                 subject="Your Subject Here"
                 title="Your Title Here"
                 author="Your Name Here" creator="And Here Too"
                 keywords="Some keywords"
                 exportKey="#{pdfMap.documentKey}">
            
            




            Then, after rendering it:




            DocumentData docStoreData = (DocumentData)Contexts.getEventContext().get(pdfMap.getDocumentKey());





            Notice that you're looking at the Event context.


            Hope this helps.


            • 4. Re: saving pdf before rendering it to ui
              alone alone Newbie

              Hello,


              I spend a lot of time trying to put it together, thanks for the discussions around this :P
              but I don't really get it. So my question is :


              where should I call this ApostillePDFGeneratorContextBean.tryIt() ?
              Indeed every time I end up with the error : seam URI scheme is not file


              I obviously miss something but what?


              nb:I didn't modify UIDocument.java from jboss-seam-pdf-sources.jar.

              • 5. Re: saving pdf before rendering it to ui
                Pulkit Mehra Newbie
                Click HELP for text formatting instructions. Then edit this text and check the preview.

                Hi Pigeret,

                Here is my complete code :

                1. Make a conversation bean and add this method into it :
                //===========================================================
                @Begin
                public byte[] renderingPDFForBytes(){
                   
                   byte[] pdfBytes=null;
                   EmptyFacesContext emptyFacesContext = new EmptyFacesContext();
                                                                                                byte[] bytes = null;
                try {

                        Renderer renderer = Renderer.instance();
                        renderer.render("ApostillingTemplate.xhtml");
                  Context conversation = Contexts.getConversationContext();
                                   
                  for(String s : conversation.getNames()){
                       System.out.println("s  : "+s);
                   }
                                       
                   String h=Manager.instance().getCurrentConversationId();
                     store=DocumentStore.instance();

                  //My Proble is this hard coded ID...I need dynamic ID
                  DocumentData data=store.getDocumentData("1); 

                   pdfBytes=data.getData();

                } finally {
                    emptyFacesContext.restore();
                   }

                   endConversation();
                   return pdfBytes;
                }
                       
                        /**
                         * End conversation.
                         */
                        @End
                        public void endConversation(){
                                System.out.println("pdf conversation ended");  
                        }
                       
                //=======================================================

                2)Here is My EmptyFacesContext :

                //========================================================

                import javax.faces.context.FacesContext;

                import org.jboss.seam.mock.MockExternalContext;
                import org.jboss.seam.mock.MockFacesContext;

                public class EmptyFacesContext extends MockFacesContext {

                    FacesContext originalFacesContext;

                    public EmptyFacesContext(){
                        super(new MockExternalContext());
                        originalFacesContext = FacesContext.getCurrentInstance();
                        createViewRoot();
                                System.out.println("inside empty faces context");
                        FacesContext.setCurrentInstance(this);
                    }

                    public void restore(){
                        System.out.println("inside restore");
                        setCurrentInstance(originalFacesContext);
                    }

                }

                //============================================================

                3)Here is Templeate for Generating PDF .Save it as ApostillingTemplate.xhtml

                <?xml version="1.0" encoding="UTF-8"?>
                <p:document
                        xmlns:p="http://jboss.com/products/seam/pdf"
                        xmlns:ui="http://java.sun.com/jsf/facelets"
                        xmlns:s="http://jboss.com/products/seam/taglib"
                        xmlns:f="http://java.sun.com/jsf/core"
                        xmlns:c="http://java.sun.com/jstl/core"
                    paperSize="A4"
                    creator="PIA"
                    title="Apostilling Template"
                    type="pdf"
                    exportKey="1"
                    >

                <p:paragraph alignment="center">
                <p:font size="18" style="underline bold" family="Arial, Verdana, sans-serif">
                <p:text value="APOSTILLE"/>
                </p:font>
                </p:paragraph>

                <p:paragraph><p:text value="   "/></p:paragraph>

                <p:paragraph alignment="center">
                <p:font size="10" style="bold" family="Arial, Verdana, sans-serif">
                <p:text value="dfdf"/>
                </p:font>
                </p:paragraph>

                <p:font size="9" family="Arial, Verdana, sans-serif">
                <p:table columns="2" widths="1 25">
                        <f:facet name="defaultCell">
                                <p:cell horizontalAlignment="left" verticalAlignment="top" paddingTop="20" border="0">
                                </p:cell>
                        </f:facet>

                <p:cell><p:paragraph><p:text value="1."/></p:paragraph></p:cell>

                <p:cell>
                <p:paragraph><p:text value="Country: "/> <p:text value="fsdfr"/></p:paragraph>
                </p:cell>

                <p:cell></p:cell>
                <p:cell><p:paragraph><p:text value="This public document"/></p:paragraph></p:cell>

                <p:cell><p:paragraph><p:text value="2."/></p:paragraph></p:cell>

                <p:cell>
                <p:paragraph><p:text value="Has been signed by     "/> <p:text value="dsfdfd"/></p:paragraph>
                </p:cell>

                <p:cell><p:paragraph><p:text value="3."/></p:paragraph></p:cell>

                <p:cell>
                <p:paragraph><p:text value="Acting in the capacity of     "/> <p:text value="gfgreertre"/></p:paragraph>
                </p:cell>

                <p:cell><p:paragraph><p:text value="4."/></p:paragraph></p:cell>

                <p:cell>
                <p:paragraph><p:text value="Bears the seal/stamp     "/> <p:text value="gfgrftr"/></p:paragraph>
                </p:cell>

                <p:cell></p:cell>
                <p:cell><p:paragraph><p:text value="Certified"/></p:paragraph></p:cell>

                <p:cell><p:paragraph><p:text value="5."/></p:paragraph></p:cell>

                <p:cell>
                <p:paragraph>
                <p:text value="At "/> <p:text value="fdgrfr"/>
                <p:text value="            "/>
                <p:text value="6. On "/> <p:text value="fsfffgfsd"/>
                        </p:text>
                </p:paragraph>
                </p:cell>

                <p:cell><p:paragraph><p:text value="7."/></p:paragraph></p:cell>

                <p:cell>
                <p:paragraph>

                </p:paragraph>
                </p:cell>


                <p:cell><p:paragraph><p:text value="8."/></p:paragraph></p:cell>

                <p:cell>
                <p:paragraph>
                <p:text value="Number:"/>
                <p:text value=""/>
                </p:paragraph>
                </p:cell>

                <p:cell><p:paragraph><p:text value="9."/></p:paragraph></p:cell>

                <p:cell>
                <p:paragraph><p:text value="Seal"/>
                <p:text value="                           "/>
                <p:text value="10. Signature:"/></p:paragraph>
                </p:cell>
                </p:table>

                <p:table columns="5" widths="2 1 2 2 1">
                                <f:facet name="defaultCell">
                                        <p:cell horizontalAlignment="left" verticalAlignment="top" paddingTop="20" border="0"></p:cell>
                                </f:facet>
                                <p:cell>
                                                </p:cell>

                                <p:cell></p:cell>

                                <p:cell>
                                                                </p:cell>


                                <p:cell horizontalAlignment="left" verticalAlignment="bottom" paddingTop="40" border="0">
                               
                                <p:paragraph alignment="right></p:paragraph>

                                </p:cell>

                                <p:cell></p:cell>
                                <p:cell></p:cell>

                </p:table>
                </p:font>

                <p:table columns="1">
                        <f:facet name="defaultCell">
                                <p:cell horizontalAlignment="justify" verticalAlignment="top" paddingTop="40" border="0">
                                </p:cell>
                        </f:facet>

                        <p:cell>
                                <p:paragraph>
                                <p:font size="7" family="Arial, Verdana, sans-serif" style="bold">
                               
                                </p:font>
                                <p:font size="7" family="Arial, Verdana, sans-serif">
                               
                                </p:font>
                                </p:paragraph>
                        </p:cell>
                </p:table>


                </p:document>

                //========================================================


                4:My web.xml.

                //========================================================

                <?xml version="1.0" encoding="UTF-8"?>
                <web-app id="WebApp_ID" version="2.5"
                xmlns="http://java.sun.com/xml/ns/javaee"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
                <display-name>ecanoc</display-name>
                <context-param>
                  <param-name>org.richfaces.SKIN</param-name>
                  <param-value>#{themebean.skin}</param-value>
                </context-param>
                       
                  <context-param>
                        <param-name>org.ajax4jsf.RESOURCE_URI_PREFIX</param-name>
                        <param-value>a4jResources</param-value>
                    </context-param>     

                <!-- Filter for tomahawk -->
                <filter>
                  <filter-name>MyFacesExtensionsFilter</filter-name>
                  <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
                  <init-param>
                   <param-name>maxFileSize</param-name>
                   <param-value>20m</param-value>
                  </init-param>
                </filter>
                       
                <context-param>
                  <param-name>facelets.DEVELOPMENT</param-name>
                  <param-value>true</param-value>
                </context-param>
                <context-param>
                  <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
                  <param-value>.xhtml</param-value>
                </context-param>
                <context-param>
                  <param-name>org.ajax4jsf.SKIN</param-name>
                  <param-value>classic</param-value>
                </context-param>
                <context-param>
                  <param-name>facelets.LIBRARIES</param-name>
                  <param-value>/WEB-INF/sandbox.taglib.xml; /WEB-INF/tomahawk.taglib.xml</param-value>
                </context-param>
                <filter>
                  <filter-name>Seam Filter</filter-name>
                  <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
                </filter>
                <filter>
                  <display-name>Ajax4jsf Filter</display-name>
                  <filter-name>ajax4jsf</filter-name>
                  <filter-class>org.ajax4jsf.Filter</filter-class>
                </filter>

                <!-- extension mapping for adding <script/>, <link/>, and other resource tags to JSF-pages  -->

                <!-- extension mapping for serving page-independent resources (javascript, stylesheets, images, etc.)  -->
                <filter-mapping>
                        <filter-name>MyFacesExtensionsFilter</filter-name>
                        <!-- servlet-name must match the name of your javax.faces.webapp.FacesServlet entry -->
                        <servlet-name>Faces Servlet</servlet-name>
                    </filter-mapping>

                <filter-mapping>
                  <filter-name>MyFacesExtensionsFilter</filter-name>
                  <url-pattern>*.xhtml</url-pattern>
                </filter-mapping>
                <filter-mapping>
                  <filter-name>MyFacesExtensionsFilter</filter-name>
                  <url-pattern>/faces/myFacesExtensionResource/*</url-pattern>
                </filter-mapping>
                <filter-mapping>
                  <filter-name>Seam Filter</filter-name>
                  <url-pattern>/*</url-pattern>
                </filter-mapping>
                <filter-mapping>
                  <filter-name>ajax4jsf</filter-name>
                  <servlet-name>Faces Servlet</servlet-name>
                  <dispatcher>REQUEST</dispatcher>
                  <dispatcher>FORWARD</dispatcher>
                  <dispatcher>INCLUDE</dispatcher>
                </filter-mapping>

                <filter>
                        <filter-name>Seam Servlet Filter</filter-name>
                        <filter-class>org.jboss.seam.servlet.SeamServletFilter</filter-class>
                </filter>
                <filter-mapping>
                        <filter-name>Seam Servlet Filter</filter-name>
                        <url-pattern>*.pdf</url-pattern>
                </filter-mapping>

                <listener>
                  <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
                </listener>
                <servlet>
                  <servlet-name>Faces Servlet</servlet-name>
                  <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
                  <load-on-startup>1</load-on-startup>
                </servlet>
                <servlet>
                  <servlet-name>Seam Resource Servlet</servlet-name>
                  <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
                </servlet>

                <servlet-mapping>
                  <servlet-name>Faces Servlet</servlet-name>
                  <url-pattern>*.xhtml</url-pattern>
                </servlet-mapping>
                <servlet-mapping>
                  <servlet-name>Seam Resource Servlet</servlet-name>
                  <url-pattern>/seam/resource/*</url-pattern>
                </servlet-mapping>

                <welcome-file-list>
                  <welcome-file>index.xhtml</welcome-file>
                </welcome-file-list>
                <login-config>
                  <auth-method>BASIC</auth-method>
                </login-config>
                <!--<security-constraint>
                  <display-name>Restrict raw XHTML Documents</display-name>
                  <web-resource-collection>
                   <web-resource-name>XHTML</web-resource-name>
                   <url-pattern>*.xhtml</url-pattern>
                  </web-resource-collection>
                  <auth-constraint/>
                </security-constraint>
                <login-config>
                  <auth-method>BASIC</auth-method>
                </login-config>-->
                <session-config>
                        <session-timeout>30</session-timeout>
                </session-config>
                </web-app>



                //==========================================================

                5: Call Conversation bean method(renderingPDFForBytes).PDF is generated on the fly in one request cycle.In order to get PDF bytes we have to mention its unique ID..which is  always 1(my observation).
                Still i am not able to get ID by using some Seam API.

                I hope this will Help.

                regards,
                Pulkit
                • 6. Re: saving pdf before rendering it to ui
                  alone alone Newbie
                  Hi thanks for the complete reply,
                  nevertheless still doesn't work.

                  I have seam 2.1.1GA.

                  when it is on the line :
                  EmptyFacesContext emptyFacesContext = new EmptyFacesContext();

                  I still got this exception so I assume I don't understand this line and what it is involving
                  since I can't figure out why it is throwing an error.
                  So I still need you help on that one

                  20:52:37,076 ERROR [STDERR] java.lang.IllegalArgumentException: URI scheme is not "file"
                  20:52:37,097 ERROR [STDERR]      at java.io.File.<init>(File.java:366)
                  20:52:37,097 ERROR [STDERR]      at org.jboss.seam.mock.MockServletContext.<init>(MockServletContext.java:59)
                  20:52:37,097 ERROR [STDERR]      at org.jboss.seam.mock.MockExternalContext.<init>(MockExternalContext.java:50)
                  20:52:37,098 ERROR [STDERR]      at com.nerodia.pdf.EmptyFacesContext.<init>(EmptyFacesContext.java:14)
                  20:52:37,098 ERROR [STDERR]      at com.nerodia.pdf.PdfSaverByte.renderingPDFForBytes(PdfSaverByte.java:50)
                  20:52:37,099 ERROR [STDERR]      at com.nerodia.pdf.PdfSaverByte.generatePDF(PdfSaverByte.java:39)
                  20:52:37,099 ERROR [STDERR]      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                  20:52:37,099 ERROR [STDERR]      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                  20:52:37,099 ERROR [STDERR]      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                  20:52:37,100 ERROR [STDERR]      at java.lang.reflect.Method.invoke(Method.java:597)
                  20:52:37,100 ERROR [STDERR]      at org.jboss.aop.joinpoint.MethodInvocation.invokeTarget(MethodInvocation.java:122)
                  20:52:37,100 ERROR [STDERR]      at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:111)
                  20:52:37,100 ERROR [STDERR]      at org.jboss.ejb3.EJBContainerInvocationWrapper.invokeNext(EJBContainerInvocationWrapper.java:69)
                  20:52:37,100 ERROR [STDERR]      at org.jboss.ejb3.interceptors.aop.InvocationContextInterceptor$InvocationContext.proceed(InvocationContextInterceptor.java:138)
                  ................
                  • 7. Re: saving pdf before rendering it to ui
                    alone alone Newbie
                    if it can enlight you this line throw the exception `first`
                    (MockServletContext.java:59) :

                    webappRoot = new File(getClass().getResource("/.").toURI());

                    I also use urlrewrite, in my project.
                    Can it be problematic?
                    • 8. Re: saving pdf before rendering it to ui
                      alone alone Newbie

                      hi,
                      me again...
                      I tried lots of way to solve this problem,
                      but I am stuck :/
                      I don't want to use the solution which consist on modifying the pdflib because
                      sometime the web user will need to download the pdf, and sometime we will need to save
                      it first to make a preview (on the fly).
                      Honestly I spend the last few evening trying to understand what is the problem.


                      So my team and I have :
                      JSeam 2.1.1GA
                      JBoss-5.0.1.GA
                      EAR project


                      the vfs folder doesn't seam to exists and so the web.xml doesn't either.


                      Just ask if I can give more infos,


                      I am stuck,
                      this sound like an SOS and it is.
                      Is there another way to get a byte response?



                      Sincerely,
                      black bird

                      • 9. Re: saving pdf before rendering it to ui
                        yachaa Newbie

                        Hi guys,


                        Are there any luck on this?


                        The problem seems to be originated from the vfs in jboss.


                        Constructor of MockServletContext:59 is throwing the exception


                        webappRoot = new File(getClass().getResource("/.").toURI());
                        because getClass().getResource("/.").toURI() returns vsfmemory:///blahblah instead of the expected "file:///c:/jbossdeployment"


                        vsfmemory:/// is not a URI file scheme.


                        Inputs are very much appreciated.


                        Thanks,


                        Ivan

                        • 10. Re: saving pdf before rendering it to ui
                          Dmitry Shultz Newbie

                          I found the solution that works for me.




                          class EmptyFacesContext extends MockFacesContext {
                          
                              FacesContext originalFacesContext;
                          
                              public EmptyFacesContext() {
                                  super(new MockExternalContext(new MyMockServletContext()));
                                  originalFacesContext = FacesContext.getCurrentInstance();
                                  createViewRoot();
                                  FacesContext.setCurrentInstance(this);
                              }
                          
                              public void restore() {
                                  setCurrentInstance(originalFacesContext);
                              }
                          
                          }



                          Note the MyMockServletContext in the constructor, it is the same code as MockServletContext coming with Seam except of the line for discovering the web.xml path:



                          File webxml = new File(((ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext()).getRealPath("/WEB-INF/web.xml"));




                          It returns correct path in my environment (Glassfish V2)


                          • 11. Re: saving pdf before rendering it to ui
                            yachaa Newbie

                            Problem has been solved now. The same work in JBossAS 5.1


                            Thanks

                            • 12. Re: saving pdf before rendering it to ui
                              Robert Becker Newbie

                              I know this thread is a bit old but I just struggled to save multiple generated documents into single files. As none of the mentioned solutions worked for me with seam 2.2.2, I finally came up with this strikingly simple solution:

                              private static ByteArrayDocumentData getMostRecentDocumentDataFromStore() throws IOException, IllegalArgumentException {
                                      DocumentStore doc = DocumentStore.instance();
                                      // try to find the last available id
                                      Integer lastId = 1;
                                      while (doc.idIsValid(lastId.toString())) {
                                          lastId++;
                                      }
                                      ByteArrayDocumentData docStoreData = (ByteArrayDocumentData) doc.getDocumentData(Long.toString(lastId - 1));
                                      return docStoreData;
                                  }

                               

                              So I simply increment a counter until the document store says it is an invalid ID. Than I use the last value which worked. Saves me from using MockContexts or Reflection...

                              • 13. Re: saving pdf before rendering it to ui
                                sweety senorita Newbie

                                Dear Robert,

                                 

                                Would you please send me the source code that you tried. Thanks in advance.@