У меня есть составная полезная нагрузка, которую я хочу передать в поток (прослушиватель HTTP):
--------=_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--
Когда я отправляю эту полезную нагрузку с помощью SoapUI, я могу получить доступ к текстовой части как payload.parts.part1.content.parts.part0.content
.
Как это сделать с помощью инструментов MuleSoft (например, выражений DataWeave)? Я хочу иметь возможность передавать эту полезную нагрузку из события MUnit Set, которое принимает выражения DataWeave и другие форматы.
Я нашел составную страницу в документации DataWeave, но она показывает, как преобразовать другие форматы в составные, в то время как у меня уже есть составная полезная нагрузка, мне просто нужно передать ее потоку таким образом, чтобы он мог анализировать.
Я также попытался просто вставить его в выражение DataWeave:
%dw 2.0
output multipart/form-data boundary = "------=_Part_1_5138113571742769845"
---
--------=_Part_1_5138113571742769845
Content-Type: text/xml
...
Но когда он попытался оценить payload.parts.part1.content.parts.part0.content
, я получил ошибку:
Сообщение: "javax.mail.internet.ParseException - отсутствует начальная граница
Хотя границы я указал. Я что-то упускаю?
Обновлено: я использую munit-runner версии 2.3.9. Часть «Выполнение» тестового примера MUnit имеет только Set Event и Flow-ref (к HTTP-прослушивателю, где я просто пытаюсь войти payload.parts.part1.content.parts.part0.content
).
Событие Set имеет галочку «Начать с пустого события», на вкладке «Полезная нагрузка» в разделе «Значение» оно имеет выражение DataWeave, в разделе «Тип носителя» оно имеет «multipart/form-data»,
на вкладке Атрибуты у него есть заголовки:
"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)"
}
Обновлено еще раз: Полная трассировка ошибки:
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)
********************************************************************************
И тестовый XML:
<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>
Чтобы создать составной вывод, просто напишите нужную структуру в DataWeave и используйте правильный формат вывода. Не пытайтесь вставить в скрипт то, чего нет в DataWeave. За исключением, может быть, JSON, который достаточно похож.
Я проанализировал ваш ввод и вывел его в JSON, а затем использовал его как скрипт. Я удалил некоторые ненужные кавычки из ключей, но оставил необходимые для имен с символом дефиса. Затем я добавил объявление пространства имен для SOAP. Вы можете использовать функции DataWeave для остальных.
Пример:
%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"
}
}
}
}
}
}
Вывод:
------=_Part_5779_1231291611.1666866442792
Content-Type: text/xml
Content-ID: <mm7-submit>
Content-Disposition: form-data; name = "part0"
<soap:Envelope xmlns:soap = "http://schemas.xmlsoap.org/soap/envelope/">
...
</soap:Envelope>
------=_Part_5779_1231291611.1666866442792
Content-Type: multipart/mixed; boundary = "------=_Part_2_3815517668157287202"
Content-ID: <attachment>
Content-Disposition: form-data; name = "part1"
--------=_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
hi
--------=_Part_2_3815517668157287202--
------=_Part_5779_1231291611.1666866442792--
Возможно. Вы должны поделиться подробностями того, как вы используете преобразование в MUnit. В противном случае вопрос не закончен.
Поскольку ответ, кажется, работает для заданного вопроса, вам следует задать новый вопрос по проблеме MUnit.
Но в вопросе прямо говорится: «Я хочу иметь возможность передавать эту полезную нагрузку из события MUnit Set», а сообщение об ошибке, которое я написал в вопросе (которое также получено из решения в вашем ответе), исходит из события MUnit Set...
Затем добавьте все детали того, что вы делаете в Munit и версиях.
Добавлена версия и подробности, пожалуйста, дайте мне знать, если потребуется дополнительная информация.
Пожалуйста, добавьте XML для тестового примера MUnit и полную информацию об ошибке из журнала, а не только сообщение об ошибке. Если есть трассировка стека, то и то.
Добавлен тестовый XML. Полная трассировка ошибки была слишком длинной для сообщения, поэтому я оставил голову и хвост, надеюсь, все в порядке.
Вы не должны использовать формат кавычек для журналов или кода.
Хорошо, я обновил его до формата кода. Итак, вы знаете, почему я получаю сообщение об ошибке?
Обертывание полезной нагрузки с помощью #[]
в MUnit Set Event решило проблему.
Таким образом, единственное необходимое изменение по сравнению с тем, что я написал в вопросе, было в Set Event -> Payload tab -> Value
.
Меняться от:
%dw 2.0
output multipart/form-data
---
[DataWeave expression]
К:
#[
%dw 2.0
output multipart/form-data
---
[DataWeave expression]
]
Я попробовал это, и я все еще получаю ту же ошибку («Отсутствует начальная граница»), когда я передаю это как полезную нагрузку из события MUnit Set. Однако я попытался установить переменную («tempvar») в это выражение, а затем оценить
#[vars.tempvar.parts.part1.content.parts.part0.content]
, и это сработало. Так может быть, это проблема MUnit?