Results 1 to 3 of 3

Thread: Writing a byte[] to the response without getting an exception

  1. #1
    Join Date
    Jan 2009
    Posts
    5

    Default Writing a byte[] to the response without getting an exception

    Hi All,

    I have been using Webflow 1.0.3 (version required by client) to create a little application to show (not create) a pdf file in the browser. I have it working fine, but when viewing the pdf I get an org.springframework.webflow.engine.NoMatchingTrans itionExceptionexception in the log.

    Here is my Action class:
    Code:
    public class Action extends FormAction {
      public Event getFile(RequestContext ctx) throws Exception {
      ....
      // Get the response object from the context
      ServletExternalContext servletContext = (ServletExternalContext)ctx.getExternalContext();
      HttpServletResponse response = servletContext.getResponse();
      
      try {
        getFileResponse = serviceStub.getFile(getFileRequest);
        
        // Get the response from web service and convert to a byte array
        DataHandler fileHandler = getFileResponse.get_return();
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        fileHandler.writeTo(os);
        file = os.toByteArray();
        
        response.setContentType("application/pdf");
        response.setContentLength(file.length);
        
        // Set the filename and cache settings (for IE)
        response.setHeader("Content-Disposition", "inline; filename=file.pdf");
        response.setHeader("Pragma", "public");
        response.setHeader("Cache-Control", "cache");
        response.setHeader("Cache-Control", "must-revalidate");
        
        // Write the file to the response
        ServletOutputStream outputStream = response.getOutputStream();
        outputStream.write(file); 
        outputStream.flush();
        outputStream.close();
      
      } catch (RemoteException e) {
        e.printStackTrace();
      }
      catch (IOException e) {
        e.printStackTrace();
      }
      return null;
      //return success();
    And here is my flow definition:
    Code:
    <start-state idref="printHelloWorldView" />
    
    <view-state id="printHelloWorldView" view="index">
      <transition on="submit" to="getViewAction"/>
    </view-state>
    
    <action-state id="getViewAction"> 
      <action bean="action" method="getFile" />
      <transition on="*" to="finish"/>
    </action-state>
    
    <end-state id="finish" view="finish"/>
    And the exception I get is:
    Code:
    org.springframework.webflow.engine.NoMatchingTransitionException: No transition was matched on the event(s) signaled by the [1] action(s) that executed in this action state 'getViewAction' of flow 'main'; transitions must be defined to handle action result outcomes -- possible flow configuration error? Note: the eventIds signaled were: 'array<String>[[null]]', while the supported set of transitional criteria for this action state is 'array<TransitionCriteria>[*]'
    	at org.springframework.webflow.engine.ActionState.doEnter(ActionState.java:212)
    	at org.springframework.webflow.engine.State.enter(State.java:200)
    	at org.springframework.webflow.engine.Transition.execute(Transition.java:229)
    So, I understand why this is happening, it's because I am writing directly to the http response object (which is outside the scope of Webflow), no Event object is returned and therefore the flow controller doesn't know what to do next.

    As you can see I also tried returning sucess(), but I now get an exception saying: java.lang.IllegalStateException: getOutputStream() has already been called for this response.

    So does anyone have any ideas about how to get around this problem? I need to view the pdf inline rather than being a download/attachment so I can't use org.springframework.web.servlet.view.document.Abst ractPdfView. Also I get a file from a web service request rather than building it myself too.

    Sorry for such a long post, thanks in a advance for any help, it's greatly appreciated.

    Dave

  2. #2
    Join Date
    Aug 2006
    Location
    Arequipa-Peru / South America
    Posts
    2,795

    Default

    I think that return null; is not a valid Event value.
    therefore in your exception appear

    Code:
    transitions must be defined to handle action result outcomes 
    -- possible flow configuration error?
    Note: the eventIds signaled were: 'array<String>[[null]]'

    You should use your comment line return success();

    First time that I see on="*" (is legal?)

    As you can see I also tried returning sucess(), but I now get an exception saying: java.lang.IllegalStateException: getOutputStream() has already been called for this response.
    It should be the correct approach,
    therefore getOutputStream() must be handle


    So does anyone have any ideas about how to get around this problem? I need to view the pdf inline rather than being a download/attachment so I can't use org.springframework.web.servlet.view.document.Abst ractPdfView. Also I get a file from a web service request rather than building it myself too.
    Ok by parts (for the second bold part),

    normally I used to work with
    org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
    Can you use jasperreport to generate the report?
    and send it to the flow scope?

    (for the first bold part)
    the same browser (Firefox, Opera, IE I dont know) let you configure if the pdf should be open in the same browser window/tab (your requeriment) or if should be download , therefore check it out.

    I hope you project works in an intranet therefore then configure each browser in the worst of the cases (I dont know if with java code you can do mandatory that the browser open in the same window the pdf file - perhaps your code do that, but you are missing maybe do the fusion with SWF (sending the object to the flow scope) to avoid the exception)

    but see jasperreport how a solution, it works fine with SWF

    HTH
    Last edited by dr_pompeii; Jan 11th, 2009 at 06:38 PM.
    - Manuel Jordan

    Kill Your Pride, Share Your Knowledge With All
    The Fear Of The LORD Is The Beginning Of Knowledge, But Fools Despise Wisdom And Discipline. Proverbs 1:7

    Blog


    Technical Reviewer of Apress

    • Pro SpringSource dm Server
    • Spring Enterprise Recipes: A Problem-Solution Approach
    • Spring Recipes: A Problem-Solution Approach, 2nd Edition
    • Pro Spring Integration
    • Pro Spring Batch
    • Pro Spring 3
    • Pro Spring MVC: With Web Flow
    • Pro Spring Security

  3. #3
    Join Date
    Jan 2009
    Posts
    5

    Thumbs up Got it working!!!

    Thanks for the quick response. I followed your suggestion and extended AbstractView.

    For anyone else who comes across this problem this is how I fixed it:
    Servlet config, notice the order=1, thats what makes all this work
    Code:
    <!-- Resolves the pdf view to a PDF document -->
    <bean id="pdfViewResolver" class="view.PDFViewResolver">
      <property name="order" value="1" />
    </bean>
    
    <!-- Resolves flow view names to .jsp templates -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/WEB-INF/jsp/" />
      <property name="suffix" value=".jsp" />
      <property name="order" value="2" />
    </bean>
    My flow definition:
    Code:
    <view-state id="indexView" view="index">
      <transition on="submit" to="pdfRenderer"/>
    </view-state>
    
    <view-state id="pdfRenderer" view="pdf">
      <render-actions>
        <action bean="action" method="renderPDF"/>
      </render-actions>
    </view-state>
    My action class:
    Code:
    public Event renderPDF(RequestContext ctx) {
      byte[] file = getFileFromWebService();
      ctx.getFlashScope().put("file", file);
      
      return success();
    }
    My View class:
    Code:
    public class PDFView extends AbstractView {
    @Override
    protected final void renderMergedOutputModel(
        Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
      
      byte[] file = (byte[])model.get("file");
      if(null == file) {
        System.err.println("File is NULL");
      }
    
      response.setContentType("application/pdf);
      response.setContentLength(file.length);
      
      response.setHeader("Content-disposition", "inline;filename=file.pdf");
      response.setHeader("Cache-Control", "cache");
      response.addHeader("Cache-Control", "must-revalidate");
      response.setHeader("Pragma", "public");
      
      ServletOutputStream out = response.getOutputStream();
      out.write(file);
      
      out.flush();
    }
    And lastly my View Resolver:
    Code:
    public class PDFViewResolver extends AbstractCachingViewResolver implements Ordered {
    
    @Override
    protected View loadView(String viewName, Locale local) throws Exception {
      if (viewName != null) {
        if ("pdf".equals(viewName)) {
          logger.debug("Creating an PDFView for view name " + viewName);
          return new PDFView();
        }
      }
      return null;
    }
    Thanks @dr_pompeii

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •