How to send PDF FileStream directly as response???

View: New views
8 Messages — Rating Filter:   Alert me  

How to send PDF FileStream directly as response???

by pocketom :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

I got a little bit stuck. I have a little Java method that generates a PDF file by using the iText library. Now I want to configure Mule so that a CXF request (or any other suitable transport for inbound, e.g. axis) is used to request a PDF file which is generated on the fly (not stored somewhere locally on hard disk).
How can I stream the resulting pdf file directly to the requester (webbrowser)?  I have a method that returns a FileOutputStream, is that enough to configure it to act as a PDF download webservice or what else do I need?

THX!

Re: How to send PDF FileStream directly as response???

by pocketom :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Nobody any idea or hint how to solve this without setting up an own webserver? Can Muleserver handle this directly?

Re: How to send PDF FileStream directly as response???

by John D'Emic :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

An easy way to do it, without resorting to SOAP, is to use an HTTP inbound-endpoint.  Something like this should work:

 <service name="pdfService">
            <inbound>
                <http:inbound-endpoint address="http://localhost:9090/pdf" method="GET" synchronous="true" contentType="application/pdf"/>
            </inbound>
            <component class="com.company.pdfconverter"/>
  </service>

Just make sure your returning the byte array from the output stream.  GET requests to "http://localhost:9090/pdf" should then return the generated PDF.

Cheers,
-jd

pocketom wrote:
Nobody any idea or hint how to solve this without setting up an own webserver? Can Muleserver handle this directly?

Re: How to send PDF FileStream directly as response???

by pocketom () :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi John,
thanx a lot for your reply! It works fine!


I have one question remaining:

Concurrent client access seems to be a problem. How would I need to configure the http endpoint to allow for multiple client requests simultaneously? Or do I need to encapsulate my component class into a threaded version?

Here is the error message that comes up the Mule console when clicking rapidly on the refresh button in my browser:

<code>
ERROR 2009-07-01 15:15:42,209 [HttpConnector.receiver.6] org.mule.DefaultExceptionStrategy: Caught exception in Exception Strategy: Software caused connection abort: socket write error
java.net.SocketException: Software caused connection abort: socket write error
        at java.net.SocketOutputStream.socketWrite0(Native Method)
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
        at java.io.DataOutputStream.write(DataOutputStream.java:90)
        at java.io.FilterOutputStream.write(FilterOutputStream.java:80)
        at org.mule.transport.http.HttpResponse$1.write(HttpResponse.java:323)
        at org.mule.transport.http.HttpServerConnection.writeResponse(HttpServerConnection.java:293)
        at org.mule.transport.http.HttpMessageReceiver$HttpWorker.run(HttpMessageReceiver.java:190)
        at org.mule.work.WorkerContext.run(WorkerContext.java:310)
        at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1061)
        at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:575)
        at java.lang.Thread.run(Thread.java:619)

</code>

Re: How to send PDF FileStream directly as response???

by John D'Emic :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hmmm...not sure what's happening here, but you can try using a pooled-component if you're worried about concurrent access on your component class. Take a look at here for more info:

http://www.mulesource.org/display/MULE2USER/Configuring+Java+Components

Cheers,
-jd


pocketom wrote:
Hi John,
thanx a lot for your reply! It works fine!


I have one question remaining:

Concurrent client access seems to be a problem. How would I need to configure the http endpoint to allow for multiple client requests simultaneously? Or do I need to encapsulate my component class into a threaded version?

Here is the error message that comes up the Mule console when clicking rapidly on the refresh button in my browser:

<code>
ERROR 2009-07-01 15:15:42,209 [HttpConnector.receiver.6] org.mule.DefaultExceptionStrategy: Caught exception in Exception Strategy: Software caused connection abort: socket write error
java.net.SocketException: Software caused connection abort: socket write error
        at java.net.SocketOutputStream.socketWrite0(Native Method)
        at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
        at java.io.DataOutputStream.write(DataOutputStream.java:90)
        at java.io.FilterOutputStream.write(FilterOutputStream.java:80)
        at org.mule.transport.http.HttpResponse$1.write(HttpResponse.java:323)
        at org.mule.transport.http.HttpServerConnection.writeResponse(HttpServerConnection.java:293)
        at org.mule.transport.http.HttpMessageReceiver$HttpWorker.run(HttpMessageReceiver.java:190)
        at org.mule.work.WorkerContext.run(WorkerContext.java:310)
        at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1061)
        at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:575)
        at java.lang.Thread.run(Thread.java:619)

</code>

Re: How to send PDF FileStream directly as response???

by Andrew Perepelytsya :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Actually, it's nothing about concurrent access. This is a valid error, as you're terminating a client connection abruptly. Before we can claim any 'concurrency' issues, please provide the source of your component. There shouldn't be absolutely no issue with concurrent access, unless a custom component stores state and doesn't properly guard it.

HTH,
Andrew

Re: How to send PDF FileStream directly as response???

by pocketom :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi, and thank you for your replies.

Here is the demo source code:




Service Interface:

package com.mycompany.pdfservice;

import java.io.IOException;

import com.lowagie.text.DocumentException;

public interface OnDemandFileService {

        public byte[] serve2File(String request) throws DocumentException, IOException;
}



Service Component

package com.mycompany.pdfservice;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfWriter;
import com.mwgbiotechag.pdfengine.Graph2D;
import com.mwgbiotechag.pdfengine.Point2D;
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

public class PDFServiceComponent implements OnDemandFileService
{
        @Override
        public byte[] serve2File(String request) throws DocumentException, IOException
        {
                System.out.println("PDFService:Request="+request);
                System.out.println("PDFService:\tNew PDF Document Requested");
               
                //benchmark
                long start = System.currentTimeMillis();  
           
                //pages
                int numberpages = 100;
   
                ByteOutputStream bops = new ByteOutputStream();    
                Document document = new Document();    
                PdfWriter writer = PdfWriter.getInstance(document, bops);    
                document.open();
       
                for (int i = 1; i <= numberpages; i++)
                {
                                document.add(new Chunk("Hello PDF Service - Page "+i));
                                document.newPage();
                }    
                document.close();    
   
 
                long end = System.currentTimeMillis();
                long time= end-start;
   
                System.out.println("PDFService:\tPDF Generation finished");
                System.out.println("PDFService:\tOverall generation time: "+time+" ms+\t("+((float)time/numberpages)+"ms/page)");
                System.out.println("\n");

                return bops.getBytes();
        }



Here the Mule conf.xml:


<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesource.org/schema/mule/core/2.2"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:spring="http://www.springframework.org/schema/beans"
       xmlns:http="http://www.mulesource.org/schema/mule/http/2.2"
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.mulesource.org/schema/mule/core/2.2 http://www.mulesource.org/schema/mule/core/2.2/mule.xsd
       http://www.mulesource.org/schema/mule/http/2.2 http://www.mulesource.org/schema/mule/http/2.2/mule-http.xsd">


    <description>        
    </description>
   
   
    <http:connector name="HttpConnector" enableCookies="true" keepAlive="true"/>
    <model name="pdfonthefly">
         <service name="pdftest">
            <inbound>
                <http:inbound-endpoint address="http://localhost:9090/pdf" method="GET" synchronous="true" contentType="attachment/pdf"  />
            </inbound>
            <component class="com.mycompany.pdfservice.PDFServiceComponent"/>
  </service>
    </model>    
</mule>

Parent Message unknown Re: How to send PDF FileStream directly as response???

by Andrew Perepelytsya :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Unless PDF.getWriter() factory method is not thead-safe, you're fine (guard it otherwise). I see no other concurrency concerns. Thus, it's only the client terminating the connection unexpectedly that is a problem. Actually, not a problem, any server will print the same error when a client requested data, but then disappeared without properly closing the tcp session. The server has data for the client, but nowhere to send it.

HTH,
Andrew

On Jul 2, 2009 6:27 AM, "pocketom" <birnexxx@...> wrote:


Hi, and thank you for your replies.

Here is the demo source code:




Service Interface:

package com.mycompany.pdfservice;

import java.io.IOException;

import com.lowagie.text.DocumentException;

public interface OnDemandFileService {

       public byte[] serve2File(String request) throws DocumentException,
IOException;
}


Service Component

package com.mycompany.pdfservice;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfWriter;
import com.mwgbiotechag.pdfengine.Graph2D;
import com.mwgbiotechag.pdfengine.Point2D;
import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;

public class PDFServiceComponent implements OnDemandFileService
{
       @Override
       public byte[] serve2File(String request) throws DocumentException,
IOException
       {
               System.out.println("PDFService:Request="+request);
               System.out.println("PDFService:\tNew PDF Document Requested");

               //benchmark
               long start = System.currentTimeMillis();

               //pages
               int numberpages = 100;

               ByteOutputStream bops = new ByteOutputStream();
               Document document = new Document();
               PdfWriter writer = PdfWriter.getInstance(document, bops);
               document.open();

               for (int i = 1; i <= numberpages; i++)
               {
                               document.add(new Chunk("Hello PDF Service - Page "+i));
                               document.newPage();
               }
               document.close();


               long end = System.currentTimeMillis();
               long time= end-start;

               System.out.println("PDFService:\tPDF Generation finished");
               System.out.println("PDFService:\tOverall generation time: "+time+"
ms+\t("+((float)time/numberpages)+"ms/page)");
               System.out.println("\n");

               return bops.getBytes();
       }



Here the Mule conf.xml:


<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns="http://www.mulesource.org/schema/mule/core/2.2"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:spring="http://www.springframework.org/schema/beans"
      xmlns:http="http://www.mulesource.org/schema/mule/http/2.2"
   xsi:schemaLocation="
      http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://www.mulesource.org/schema/mule/core/2.2
http://www.mulesource.org/schema/mule/core/2.2/mule.xsd
      http://www.mulesource.org/schema/mule/http/2.2
http://www.mulesource.org/schema/mule/http/2.2/mule-http.xsd">


   <description>
   </description>


   <http:connector name="HttpConnector" enableCookies="true"
keepAlive="true"/>
   <model name="pdfonthefly">
        <service name="pdftest">

<inbound> <http:inbound-endpoint address="http://localhost:9090/pdf"

method="GET" synchronous="true" contentType="attachment/pdf"  />
           </inbound>
           <component
class="com.mycompany.pdfservice.PDFServiceComponent"/>
               </service>
   </model>
</mule>

--
View this message in context: http://www.nabble.com/How-to-send-PDF-FileStream-directly-as-response----tp24256692p24304324.html

Sent from the Mule - User mailing list archive at Nabble.com. ------------------------------------...