Announcement Announcement Module
Collapse
No announcement yet.
PDF View + flow continuation Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • PDF View + flow continuation

    Hello,

    in the middle of my WebFlow i've got a JasperReportsPdfView. The PDFView uses the attachment header and has no user interaction and so the Flow can not continue. Is there a possibility to show the PDFView and continue the main Flow without userinteraction?

  • #2
    Is there a possibility to show the PDFView and continue the main Flow without userinteraction?
    You could show the PDF in a popup window or <iframe> and have buttons on the main page that signal events in the flow.
    One thing to keep in mind here is that the flow cannot be in one state and accept events in another state. In more practical terms this means that you probably can't show the PDF directly as a view from a view-state because that would mean that the flow is stuck in that view state. Instead you can have your flow prepare the PDF and have a seperate classic Spring MVC controller (or just a Servlet even) sent it to the client.

    Check the following tip for some info on how you could access the PDF in your flow execution (flow scope probably) from a Servlet:

    http://www.ervacon.com/products/swf/tips/tip1.html

    Erwin

    Comment


    • #3
      Thank you for your answer.

      The external controller or Filter dosen't work for my situation.
      I found a solution which could work but i don't know if this is ugly bad practice.

      I've a view and after this view the system populates the data for the pdf-file. Then an action writes the generated pdf report directly into the response. So long so good or bad?

      If this action end's successfull then the flow ends with an flowredirect an i get this error:

      java.lang.IllegalStateException
      at org.apache.catalina.connector.ResponseFacade.sendR edirect(ResponseFacade.java:432)
      at org.springframework.web.servlet.view.RedirectView. sendRedirect(RedirectView.java:262)
      at org.springframework.web.servlet.view.RedirectView. renderMergedOutputModel(RedirectView.java:166)
      at org.springframework.web.servlet.view.AbstractView. render(AbstractView.java:249)
      at org.springframework.web.servlet.DispatcherServlet. render(DispatcherServlet.java:1105)
      at org.springframework.web.servlet.DispatcherServlet. doDispatch(DispatcherServlet.java:841)
      at org.springframework.web.servlet.DispatcherServlet. doService(DispatcherServlet.java:755)
      at org.springframework.web.servlet.FrameworkServlet.p rocessRequest(FrameworkServlet.java:396)
      at org.springframework.web.servlet.FrameworkServlet.d oGet(FrameworkServlet.java:350)
      at javax.servlet.http.HttpServlet.service(HttpServlet .java:697)
      at javax.servlet.http.HttpServlet.service(HttpServlet .java:810)
      at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:252)
      at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:173)
      at org.springframework.orm.jpa.support.OpenEntityMana gerInViewFilter.doFilterInternal(OpenEntityManager InViewFilter.java:113)
      at org.springframework.web.filter.OncePerRequestFilte r.doFilter(OncePerRequestFilter.java:77)
      at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:202)
      at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:173)
      at org.springframework.web.filter.CharacterEncodingFi lter.doFilterInternal(CharacterEncodingFilter.java :78)
      at org.springframework.web.filter.OncePerRequestFilte r.doFilter(OncePerRequestFilter.java:77)
      at org.apache.catalina.core.ApplicationFilterChain.in ternalDoFilter(ApplicationFilterChain.java:202)
      at org.apache.catalina.core.ApplicationFilterChain.do Filter(ApplicationFilterChain.java:173)


      Why do i get this error?

      Comment


      • #4
        I've a view and after this view the system populates the data for the pdf-file. Then an action writes the generated pdf report directly into the response. So long so good or bad?
        It's not necessarily a bad practice, but it has a few downsides. Doing it this way is basically the same as having a PDF view for a view state, which limits your navigation possibilities once the PDF is visible in the browser (as we mentioned before).

        The IllegalStateException you see is caused by the fact that you're writing data to the response when SWF still wants to issue a REDIRECT (because of the alwaysRedirectOnPause behavior). The Servlet API (and HTTP in general) don't allow you to 'change your mind': once data has been written (committed) to the client, you can no longer back out and do a redirect.
        Make your action a render-action of a view state to avoid this.

        Erwin

        Comment


        • #5
          What is the best way to start a subflow in a new Window?

          Comment


          • #6
            Please post this question in a seperate thread. That will make it easier for other people to find answers on the forum.

            Erwin

            Comment


            • #7
              We display our PDF in a separate window as follows:

              JSP code:
              HTML Code:
              <a href='application?_flowExecutionKey=<c:out value="${flowExecutionKey}"/>&_eventId=viewPdfEvent' target="_blank">View and Print Your Application</a>
              This happens in a subflow, as below. The main flow in the browser page is still active.

              Flow Xml code:
              HTML Code:
                  <bean id="pdfViewResolver" class="org.springframework.web.servlet.view.XmlViewResolver">
                      <property name="order" value="1"/>
                      <property name="location" value="/WEB-INF/my-views.xml"/>
                  </bean>
              
              
                  <view-state id="finishedApplicationState" view="finishApplication">
                      <transition on="finishedEvent" to="finishEndState"/>
                      <transition on="viewPdfEvent" to="showPdfState"/>
                  </view-state>
              
                  <!-- The display of the PDF happens outside the online application flow -->
                  <subflow-state id="showPdfState" flow="showPdfFlow">
                      <attribute-mapper>
                          <input-mapper><mapping source="flowScope.registrationDetails" target="registrationDetails"/></input-mapper>
                      </attribute-mapper>
                  </subflow-state>
              
                  <!-- display of the PDF is defined in its own subflow, as the user may still have to press a "finish" button in
                       the main window.
                       -->
                  <inline-flow id="showPdfFlow">
                      <flow>
                          <input-mapper><input-attribute name="registrationDetails"/></input-mapper>
                          <start-state idref="displayPdfState"/>
                          <view-state id="displayPdfState" view="pdfApplication"/>
                      </flow>
                  </inline-flow>
              my-views.xml :
              HTML Code:
                  <bean name="pdfApplication" class="com.mycompany.views.PDFApplication" />
              PDFApplication.java :
              PHP Code:
              public class PDFApplication extends AbstractPdfView {

                  protected 
              void buildPdfDocument(
                      
              Map model,
                      
              Document doc,
                      
              PdfWriter writer,
                      
              HttpServletRequest req,
                      
              HttpServletResponse resp)
                      
              throws Exception {

                      
              RegistrationDetails regDetails = (RegistrationDetailsmodel.get("registrationDetails");
                      
              doc.add(new Paragraph("\nblah :" regDetails.getBlah().toString()));
                  }

              Hope this helps.

              Comment


              • #8
                This is very interesting solution, although it works only with continuations.

                But if I'm allowed to notice, you don't have to use subflow state to display pdf in new browser window. Because when you continue your main flow, you are in fact continuing -previous- continuation state; which is unrelated to weather you use subflow's or main flow's view state for showing pdf in your new browser window...

                I was wondering the following:
                Each time you display pdf, you'll get one continuation state that will be stuck in its view state. So if I have situation:

                1. From view state "A" user do transition to view state "B"
                2. User clicks back button in browser (he's back to page "A")
                3. User do transition to view state "C"

                Now, is the continuation state of view state "B" cleared or not (since it is not reachable from the browser using back-forward buttons)? I was just wondering, if these "stuck" continuation states can cause any side effects, or something...


                Anyway, thanks for sharing knowledge, cunneen.

                Regards,
                Igor.

                Comment


                • #9
                  This is very interesting solution, although it works only with continuations.

                  But if I'm allowed to notice, you don't have to use subflow state to display pdf in new browser window. Because when you continue your main flow, you are in fact continuing -previous- continuation state; which is unrelated to weather you use subflow's or main flow's view state for showing pdf in your new browser window..
                  Correct.

                  Now, is the continuation state of view state "B" cleared or not
                  Not necessarily. The only side effect of these snapshots is that they take up server resources (memory).

                  Check the following tips for info on how to manage your server side resources when using SWF:
                  http://www.ervacon.com/products/swf/tips/tip2.html

                  Erwin

                  Comment


                  • #10
                    Thanks for your comments Igor. You've got me thinking.

                    Originally posted by imilina View Post
                    ...you don't have to use subflow state to display pdf in new browser window. Because when you continue your main flow, you are in fact continuing -previous- continuation state; which is unrelated to weather you use subflow's or main flow's view state for showing pdf in your new browser window...
                    I considered this, but decided that in my case it was better modelled as a subflow. This way, the idea of the PDF display being "outside of the main flow" is explicit in the flow definition, rather than being an additional view state like all the others.

                    Originally posted by imilina View Post
                    Now, is the continuation state of view state "B" cleared or not (since it is not reachable from the browser using back-forward buttons)? I was just wondering, if these "stuck" continuation states can cause any side effects, or something...
                    Erwin, does this mean that a view-state with no exit transitions will still have stale continuations stored in the repository (e.g. the displayPdfState in my example) ?

                    Comment


                    • #11
                      does this mean that a view-state with no exit transitions will still have stale continuations stored in the repository
                      Yes. At the moment SWF does not detect that a particular flow execution continuation snapshot is 'stuck' in a view-state. In general this is also impossible to detect since the user can have custom TransitionCriteria for a transition (e.g. a global transition).
                      We also need this snapshot for possible view refreshes, so we have to hold on to it.

                      Anyway, as the tip that I referenced above explains, there is a 'maxContinuations' property to control this.

                      Erwin

                      Comment


                      • #12
                        Thanks for the reply. In the case of my PDF, I've changed the view-state "displayPdfState" in the subflow to an end-state, to help reduce the number of stale continuations.

                        Comment


                        • #13
                          hi,

                          i have a very similar problem but working with swf2 (2.0.3 currently) together with JSF (the set up is very much like swf2-jsf example app).

                          my requirement is that after some event in the browser (clicking a link or button) i have to stream a pdf document to the client which is generated on the server on the fly. the user after receiving the pdf should be able to perform some more actions on the interface (eg continue the flow in swf2 terms).

                          pls direct me a bit how to do that in swf2.

                          some things i tried:
                          • i managed the streaming without an IllegalArgumentException if i finished my flow -- but this is not suitable for me since i need to keep my user "in flow" so to say
                          • i tried to define a subflow for the streaming (which did not contain any view-state) and stream the pdf with ending the subflow but the IllegalArgument remained since returning to the parentflow meant a redirect i suppose.
                          • i also tried to fiddle around with FlowHandlerAdapter but that is perhaps not the right way to solve this.
                          • i considered implementing a pdfview (have not tried) but reading through the threads here it has not seemed to be a good solution either.

                          i might miss a conceptual thing here with swf2 i guess but actually i migrate my application from plain jsf. with that streaming a pdf document to the client was easy: in a backing bean i just directly wrote in the response.output stream after setting content type to "application/pdf" etc. and called FacesContex.responseComplete. that was it.

                          Comment


                          • #14
                            found thread on topic but will it work with swf2?

                            hi,

                            i found this thread:
                            showthread.php?t=52454, although this showpost.php?p=179387&postcount=11 post in the thread raises some questions again if method described in the thread would work with swf2. any thoughts?

                            (the forum would not let me post proper links saying that i can only post external links if i made 15 posts. but since these are internal links i put them in like this. sry.)

                            btw i also tried to use externalContext.recordResponseComplete() but having a look in the sourcecode shows that this flag on externalContext is only considered at very limited situations.

                            thx in advance,
                            --
                            ben

                            Comment


                            • #15
                              for future reference if anybody needs this info: the solution showed in the above quoted forumthread works with swf2 nicely and it is likely to work for any kind of binary data streaming problem. thx to jamesclinton

                              Comment

                              Working...
                              X