I have a multipart payload that I want to pass to a flow (an HTTP Listener):
--------=_Part_1_5138113571742769845
Content-Type: text/xml
Content-ID: <mm7-submit>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns="http://www.3gpp.org/ftp/Specs/archive/23_series/23.140/schema/REL-5-MM7-1-2">
...
</soap:Envelope>
--------=_Part_1_5138113571742769845
Content-Type: multipart/mixed; boundary="------=_Part_2_3815517668157287202"
Content-ID: <attachment>
--------=_Part_2_3815517668157287202
Content-Type: text/plain; name=text1.txt
Content-ID: <text1.txt>
Content-Location: bundled/text1.txt
This is the text part I want to access
--------=_Part_2_3815517668157287202
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-ID: <image.png>
Content-Location: bundled/image.jpg
aGk=
--------=_Part_2_3815517668157287202--
--------=_Part_1_5138113571742769845--
When I send this payload using SoapUI, I can access the text part as payload.parts.part1.content.parts.part0.content
.
How can I accomplish this with MuleSoft's tools (e.g. DataWeave expressions)? I want to be able to pass this payload from MUnit Set Event, which accepts DataWeave expressions and other formats.
I found the multipart page in DataWeave's documentation, but it shows how to convert other formats to multipart, whereas I have the multipart payload already, I just need to pass it to the flow in a way that it can parse.
I also tried to simply paste it in a DataWeave expression:
%dw 2.0
output multipart/form-data boundary="------=_Part_1_5138113571742769845"
---
--------=_Part_1_5138113571742769845
Content-Type: text/xml
...
But when it tried to evaluate payload.parts.part1.content.parts.part0.content
, I got the error:
Message : "javax.mail.internet.ParseException - Missing start boundary
Although I did specify the boundary. Am I missing something?
EDIT: I am using munit-runner version 2.3.9. The "Execution" part of the MUnit test case only has a Set Event and a Flow-ref (to the HTTP Listener, where I just try to log payload.parts.part1.content.parts.part0.content
).
The Set Event has "Start with an empty event" ticked, in the Payload tab under Value it has the DataWeave expression, under Media Type it has "multipart/form-data",
in the Attributes tab it has the headers:
"headers": {
"accept-encoding": "gzip,deflate",
"content-type": "multipart/related; boundary=\"------=_Part_1_5138113571742769845\"; type=\"text/xml\"; start=\"<mm7-submit>\"",
"host": "localhost:8081",
"connection": "Keep-Alive",
"user-agent": "Apache-HttpClient/4.5.5 (Java/16.0.1)"
}
EDIT 2: The full error trace is:
ERROR 2022-10-31 11:39:08,780 [[MuleRuntime].uber.12:
[poc7].api-main.CPU_LITE @3bf5d6df]
org.mule.runtime.core.internal.exception.OnErrorPropagateHandler:
******************************************************************************** Message : "javax.mail.internet.ParseException - Missing
start boundary javax.mail.internet.ParseException: Missing start
boundary at
javax.mail.internet.MimeMultipart.parse(MimeMultipart.java:656) at
javax.mail.internet.MimeMultipart.getCount(MimeMultipart.java:312) at
org.mule.weave.v2.module.multipart.MultiPartReader.doRead(MultiPartReader.scala:119)
at org.mule.weave.v2.module.reader.Reader.read(Reader.scala:35) at
org.mule.weave.v2.module.reader.Reader.read$(Reader.scala:33) at
org.mule.weave.v2.module.multipart.MultiPartReader.read(MultiPartReader.scala:46)
at
org.mule.weave.v2.el.MuleTypedValue.value(MuleTypedValue.scala:147)
at
org.mule.weave.v2.model.values.wrappers.DelegateValue.valueType(DelegateValue.scala:17)
at
org.mule.weave.v2.model.values.wrappers.DelegateValue.valueType$(DelegateValue.scala:16)
at
org.mule.weave.v2.el.MuleTypedValue.valueType(MuleTypedValue.scala:177)
at org.mule.weave.v2.model.types.ObjectType$.accepts(Type.scala:1068)
at
org.mule.weave.v2.interpreted.node.executors.BinaryOverloadedStaticExecutor.findMatchingFunction(BinaryOverloadedStaticExecutor.scala:151)
at
org.mule.weave.v2.interpreted.node.executors.BinaryOverloadedStaticExecutor.executeBinary(BinaryOverloadedStaticExecutor.scala:78)
at
org.mule.weave.v2.interpreted.node.ChainedBinaryOpNode.doExecute(ChainedBinaryOpNode.scala:37)
at
org.mule.weave.v2.interpreted.node.ValueNode.execute(ValueNode.scala:26)
at
org.mule.weave.v2.interpreted.node.ValueNode.execute$(ValueNode.scala:21)
at
org.mule.weave.v2.interpreted.node.ChainedBinaryOpNode.execute(ChainedBinaryOpNode.scala:7)
at
org.mule.weave.v2.interpreted.node.NullSafeNode.doExecute(NullSafeNode.scala:14)
at
org.mule.weave.v2.interpreted.node.ValueNode.execute(ValueNode.scala:26)
at
org.mule.weave.v2.interpreted.node.ValueNode.execute$(ValueNode.scala:21)
at
org.mule.weave.v2.interpreted.node.NullSafeNode.execute(NullSafeNode.scala:8)
at
org.mule.weave.v2.interpreted.node.structure.DocumentNode.doExecute(DocumentNode.scala:26)
at
org.mule.weave.v2.interpreted.node.ValueNode.execute(ValueNode.scala:26)
at
org.mule.weave.v2.interpreted.node.ValueNode.execute$(ValueNode.scala:21)
at
org.mule.weave.v2.interpreted.node.structure.DocumentNode.execute(DocumentNode.scala:11)
at
org.mule.weave.v2.interpreted.InterpretedMappingExecutableWeave.$anonfun$writeWith$3(InterpreterMappingCompilerPhase.scala:264)
at
org.mule.weave.v2.module.writer.WriterHelper$.writeValue(Writer.scala:161)
at
org.mule.weave.v2.module.writer.WriterHelper$.writeAndGetResult(Writer.scala:139)
at
org.mule.weave.v2.interpreted.InterpretedMappingExecutableWeave.writeWith(InterpreterMappingCompilerPhase.scala:264)
at
org.mule.weave.v2.el.WeaveExpressionLanguageSession.evaluateLogExpression(WeaveExpressionLanguageSession.scala:330)
[...]
at
reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2205)
at
reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribe(MonoFlatMapMany.java:134)
at
reactor.core.publisher.MonoCurrentContext.subscribe(MonoCurrentContext.java:35)
at
reactor.core.publisher.MonoFlatMapMany.subscribe(MonoFlatMapMany.java:52)
at reactor.core.publisher.MonoNext.subscribe(MonoNext.java:40) at
reactor.core.publisher.MonoOnErrorResume.subscribe(MonoOnErrorResume.java:44)
at reactor.core.publisher.MonoMap.subscribe(MonoMap.java:52) at
reactor.core.publisher.MonoMap.subscribe(MonoMap.java:52) at
reactor.core.publisher.MonoSubscriberContext.subscribe(MonoSubscriberContext.java:47)
at
reactor.core.publisher.MonoSubscriberContext.subscribe(MonoSubscriberContext.java:47)
at reactor.core.publisher.Mono.subscribe(Mono.java:3873) at
reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:420)
at
reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:204)
at
reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:204)
at
reactor.core.publisher.FluxPublishOn$PublishOnSubscriber.runAsync(FluxPublishOn.java:447)
at
reactor.core.publisher.FluxPublishOn$PublishOnSubscriber.run(FluxPublishOn.java:534)
at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:84) at
reactor.core.scheduler.WorkerTask.call(WorkerTask.java:37) at
java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at
org.mule.service.scheduler.internal.AbstractRunnableFutureDecorator.doRun(AbstractRunnableFutureDecorator.java:151)
at
org.mule.service.scheduler.internal.RunnableFutureDecorator.run(RunnableFutureDecorator.java:54)
at
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834), while reading
`payload` as MultiPart. Trace: at main (Unknown)" evaluating
expression: "payload.parts.part1.content.parts.part0.content". Element
: api-main/processors/2 @ poc7:poc7.xml:20 (Copy_of_Text_Logger)
Element DSL : <logger level="INFO"
doc:name="Copy_of_Text_Logger"
doc:id="3672afde-5a7c-4745-bd78-540d726e9354" message="Received text:
#[payload.parts.part1.content.parts.part0.content]"></logger> Error type : MULE:EXPRESSION FlowStack : at
api-main(api-main/processors/2 @ poc7:poc7.xml:20
(Copy_of_Text_Logger))
(set debug level logging or '-Dmule.verbose.exceptions=true' for
everything)
********************************************************************************
And the test XML is:
<munit:test name="poc7-test-suite-api-mainTest" doc:id="f625b0a6-55a7-431a-962f-cbc68587dca7" description="Test" expectedErrorType="ANY">
<munit:execution >
<munit:set-event doc:name="Set Event" doc:id="2fe9a6bc-b65d-4477-b705-010f247cec6f" >
<munit:payload value='%dw 2.0
output multipart/form-data
ns soap http://schemas.xmlsoap.org/soap/envelope/
---
{
parts: {
part0: {
headers: {
"Content-Type": "text/xml",
"Content-ID": "<mm7-submit>"
},
content: {
soap#Envelope: "\n ...\n"
}
},
part1: {
headers: {
"Content-Type": "multipart/mixed; boundary=\"------=_Part_2_3815517668157287202\"",
"Content-ID": "<attachment>"
},
content: {
parts: {
part0: {
headers: {
"Content-Type": "text/plain; name=text1.txt",
"Content-ID": "<text1.txt>",
"Content-Location": "bundled/text1.txt"
},
content: "This is the text part I want to access\n"
},
part1: {
headers: {
"Content-Type": "image/png",
"Content-Transfer-Encoding": "base64",
"Content-ID": "<image.png>",
"Content-Location": "bundled/image.jpg"
},
content: "hi"
}
}
}
}
}
}' mediaType="multipart/form-data" />
<munit:attributes value="#[{"headers": {
"accept-encoding": "gzip,deflate",
"content-type": "multipart/related; boundary=\"------=_Part_1_5138113571742769845\"; type=\"text/xml\"; start=\"<mm7-submit>\"",
"host": "localhost:8081",
"connection": "Keep-Alive",
"user-agent": "Apache-HttpClient/4.5.5 (Java/16.0.1)"
}
}]" />
</munit:set-event>
<flow-ref doc:name="Flow-ref to api-main" doc:id="75a9f728-f461-4233-a5b2-1a01d7b21e80" name="api-main"/>
</munit:execution>
<munit:validation >
<munit-tools:assert-equals message="Wrong HTTP Status code:" expected="#[746]" actual="#[message.inboundProperties['http.status']]" doc:name="Assert Equals"/>
</munit:validation>
</munit:test>
Wrapping the payload with #[]
in MUnit Set Event solved the problem.
So the only required change from what I wrote in the question was in Set Event -> Payload tab -> Value
.
Change from:
%dw 2.0
output multipart/form-data
---
[DataWeave expression]
To:
#[
%dw 2.0
output multipart/form-data
---
[DataWeave expression]
]