Warm tip: This article is reproduced from serverfault.com, please click

Sending PDF over HTTP Request in Mule 4

发布于 2020-12-05 14:38:46

I have in my flow an HTTP request (say, DOC Service) where I get a PDF from a service, and I have to send the PDF to an OCR application through another HTTP Request (say, OCR Service). I am receiving the PDF from DOC Service as application/pdf type, and the OCR Service is set to receive multipart/form-data type.

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:ftp="http://www.mulesoft.org/schema/mule/ftp" xmlns:file="http://www.mulesoft.org/schema/mule/file"
    xmlns:http="http://www.mulesoft.org/schema/mule/http"
    xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
    <flow name="on-mq-messageFlow" doc:id="eca15aeb-da46-491a-97e1-f73aa5fcd45b" >
        <set-payload value='#[%dw 2.0
output application/json
---
read(payload,"application/json")]' doc:name="Set Payload" doc:id="929f7b70-ae47-4fe3-abd2-e89ae092899e" />
        <set-variable value="#[payload]" doc:name="Set MQ Payload" doc:id="9716ed4b-4d16-4b9e-8ac8-1dab5646fe0f" variableName="mqPayload"/>
        <http:request method="POST" doc:name="Doc Request" doc:id="0e92add3-d576-444d-8070-9d09e6e3c5c5" config-ref="DOC_configuration" path="${doc.request.path}" outputMimeType='multipart/form-data; boundary=----aA1bB2cC3dD4'>
            <http:headers ><![CDATA[#[output application/java
---
{
    "client-id" : "12345",
    "client-secret" : "12345"
}]]]></http:headers>
            <http:uri-params ><![CDATA[#[output application/java
---
{
    "doc_id" : payload.data.ID
}]]]></http:uri-params>

        </http:request>
        <http:request method="POST" doc:name="Send Doc to OCR" doc:id="76f60ddb-f570-42be-b85e-ccb2d2ae3703" config-ref="OCR_Request_configuration" path="${ocr.request.path}" outputMimeType="multipart/form-data; boundary=----aA1bB2cC3dD4">
            <http:body ><![CDATA[#[%dw 2.0
output multipart/form-data
---
{
    parts: {
        file: {
            headers: {
                "Content-Type": payload.^mimeType
            },
            content: payload
        },
        id: {
            headers: {
                "Content-Type": "text/plain"
            },
            content: vars.mqPayload.data.ID
        }
    }
}]]]></http:body>
            <http:headers ><![CDATA[#[output application/java
---
{
    "client-id" : "12345",
    "Accept" : "*/*",
    "client-secret" : "12345",
    "Content-Type" : "multipart/form-data; boundary=----aA1bB2cC3dD4"
}]]]></http:headers>
        </http:request>
        <ee:transform doc:name="Final Response" doc:id="cf68dbc1-cee3-4809-9511-a0794be2b5f7">
            <ee:message>
                <ee:set-payload><![CDATA[%dw 2.0
output application/json
---
{
    "status": "Success",
    message: "Completed"
}
]]></ee:set-payload>
            </ee:message>
        </ee:transform>
    </flow>
</mule>

I have to add another text field along with the PDF file before sending the payload to OCR Service. For that, I have defined payload as multipart/form-data by selecting the elements of parts of form-data and modifying it like given in the answer here, but getting below error. I have also set MimeType for both DOC Service and OCR Service as multipart/form-data.

ERROR 2020-12-05 21:57:57,159 [[MuleRuntime].cpuLight.02: [doc-process-api].on-mq-messageFlow.CPU_LITE @6ec62e93] [event: 0e82ca00-3717-11eb-ab69-005056ac6a26] org.mule.runtime.core.internal.exception.OnErrorPropagateHandler: 
********************************************************************************
Message               : "javax.mail.internet.ParseException - Missing start boundary, while reading `payload` as MultiPart.
Trace:
  at main (Unknown), while writing MultiPart.
Trace:
  at main (Unknown)" evaluating expression: "%dw 2.0
output multipart/form-data
---
{
parts: {
file: {
headers: {
"Content-Type": payload.^mimeType
},
content: payload
},
external_id: {
headers: {
"Content-Type": "text/plain"
},
content: vars.mqPayload.data.ID
}
}
}".
Element               : on-mq-messageFlow/processors/4 @ doc-process-api:on-mq-message.xml:46 (Send Doc to OCR)
Element XML           : <http:request method="POST" doc:name="Send Doc to OCR" doc:id="76f60ddb-f570-42be-b85e-ccb2d2ae3703" config-ref="OCR_Request_configuration" path="${ocr.request.path}" outputMimeType="multipart/form-data; boundary=----aA1bB2cC3dD4">
                        <http:body>#[%dw 2.0
output multipart/form-data
---
{
    parts: {
        file: {
            headers: {
                "Content-Type": payload.^mimeType
            },
            content: payload
        },
        external_id: {
            headers: {
                "Content-Type": "text/plain"
            },
            content: vars.mqPayload.data.ID
        }
    }
}]</http:body>
                        <http:headers>#[output application/java
---
{
    "client-id" : "12345",
    "Accept" : "*/*",
    "client-secret" : "12345",
    "Content-Type" : "multipart/form-data; boundary=----aA1bB2cC3dD4"
}]</http:headers>
                        </http:request>
Error type            : MULE:EXPRESSION
Payload Type          : org.mule.runtime.core.internal.streaming.bytes.ManagedCursorStreamProvider
--------------------------------------------------------------------------------
Root Exception stack trace:
org.mule.runtime.api.el.ExpressionExecutionException: javax.mail.internet.ParseException - Missing start boundary, while reading `payload` as MultiPart.
Trace:
  at main (Unknown), while writing MultiPart.
Trace:
  at main (Unknown)
    at org.mule.weave.v2.el.WeaveExpressionLanguageSession.doEvaluate(WeaveExpressionLanguageSession.scala:130)
    at org.mule.weave.v2.el.WeaveExpressionLanguageSession.evaluate(WeaveExpressionLanguageSession.scala:77)
    at org.mule.weave.v2.el.WeaveExpressionLanguageSession.evaluate(WeaveExpressionLanguageSession.scala:103)
    at org.mule.runtime.core.internal.el.dataweave.DataWeaveExpressionLanguageAdaptor$1.evaluate(DataWeaveExpressionLanguageAdaptor.java:252)
    at org.mule.runtime.core.internal.el.DefaultExpressionManagerSession.evaluate(DefaultExpressionManagerSession.java:38)
    at org.mule.runtime.core.privileged.util.attribute.ExpressionAttributeEvaluatorDelegate.resolveExpressionWithSession(ExpressionAttributeEvaluatorDelegate.java:70)
    at org.mule.runtime.core.privileged.util.attribute.ExpressionAttributeEvaluatorDelegate.resolve(ExpressionAttributeEvaluatorDelegate.java:56)
    at org.mule.runtime.core.privileged.util.AttributeEvaluator.resolveTypedValue(AttributeEvaluator.java:104)
    at org.mule.runtime.module.extension.internal.runtime.resolver.ExpressionValueResolver.resolveTypedValue(ExpressionValueResolver.java:122)
    at org.mule.runtime.module.extension.internal.runtime.resolver.ExpressionTypedValueValueResolver.resolve(ExpressionTypedValueValueResolver.java:46)
    at org.mule.runtime.module.extension.internal.runtime.resolver.ExpressionTypedValueValueResolver.resolve(ExpressionTypedValueValueResolver.java:29)
    at org.mule.runtime.module.extension.internal.runtime.resolver.ResolverUtils.resolveRecursively(ResolverUtils.java:90)
    at org.mule.runtime.module.extension.internal.runtime.resolver.ResolverSet.resolve(ResolverSet.java:109)
    at org.mule.runtime.module.extension.internal.runtime.operation.ComponentMessageProcessor.getResolutionResult(ComponentMessageProcessor.java:586)
    at org.mule.runtime.module.extension.internal.runtime.operation.ComponentMessageProcessor.lambda$apply$6(ComponentMessageProcessor.java:194)
    at org.mule.runtime.core.api.util.func.CheckedFunction.apply(CheckedFunction.java:19)
    at org.mule.runtime.core.api.rx.Exceptions.lambda$checkedFunction$2(Exceptions.java:84)
    at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:381)
    at reactor.core.publisher.FluxFlatMap$FlatMapMain.tryEmit(FluxFlatMap.java:532)
    at reactor.core.publisher.FluxFlatMap$FlatMapInner.onNext(FluxFlatMap.java:974)
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121)
    at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2071)
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:162)
    at reactor.core.publisher.FluxFlatMap$FlatMapInner.onSubscribe(FluxFlatMap.java:964)
    at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90)
    at reactor.core.publisher.MonoCurrentContext.subscribe(MonoCurrentContext.java:35)
    at reactor.core.publisher.MonoMapFuseable.subscribe(MonoMapFuseable.java:59)
    at reactor.core.publisher.Mono.subscribe(Mono.java:3858)
    at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:420)
    at org.mule.runtime.core.privileged.processor.chain.AbstractMessageProcessorChain$1.onNext(AbstractMessageProcessorChain.java:292)
    at org.mule.runtime.core.privileged.processor.chain.AbstractMessageProcessorChain$1.onNext(AbstractMessageProcessorChain.java:285)
    at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:204)
    at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onNext(FluxOnAssembly.java:345)
    at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:204)
    at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.tryOnNext(FluxContextStart.java:111)
    at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.tryOnNext(FluxContextStart.java:109)
    at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.tryOnNext(FluxMapFuseable.java:303)
    at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.tryOnNext(FluxContextStart.java:109)
    at reactor.core.publisher.FluxPublishOn$PublishOnConditionalSubscriber.runAsync(FluxPublishOn.java:866)
    at reactor.core.publisher.FluxPublishOn$PublishOnConditionalSubscriber.run(FluxPublishOn.java:939)
    at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:84)
    at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:37)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.mule.service.scheduler.internal.AbstractRunnableFutureDecorator.doRun(AbstractRunnableFutureDecorator.java:111)
    at org.mule.service.scheduler.internal.RunnableFutureDecorator.run(RunnableFutureDecorator.java:54)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

To fix that I tried adding boundary in headers as Content-Type like below, and still getting the same error.

"Content-Type: "multipart/form-data; boundary=----aA1bB2cC3dD4"

Here I don't need to parse anything, just handover the PDF from one service to another service, but by adding an extra field. How can I achieve this? Any help is appreciated.

Questioner
Dan
Viewed
0
afelisatti 2020-12-06 00:33:30

The error is happening because you are miss typing the DOC service as multipart so DataWeave attempts to read the PDF as such. The mime type parameter affects the output of your operation, saying "this is the type I produce". But in the case of HTTP, that is automatically determined based on the "Content-Type" header, you do not need to specify the mime types beyond your DataWeave transformation for the ORC service.