Хотя есть
много документации о
Mule ESB, проблема в этом посте все же заняла у меня некоторое время, чтобы понять это правильно. В этом посте я приведу полный пример того, как я заменил стандартную функциональность Mule (в данном случае преобразователь) своей собственной реализацией.
Моя проблема началась с
этого вопроса, который я разместил на форуме мулов без какого-либо ответа. Это заставило меня искать решение, которое является одним из преимуществ открытого исходного кода; это дает вам возможность сделать это.
Вскоре я понял, что желаемое поведение может быть легко реализовано с помощью небольшого изменения в
MessagePropertiesTransformer . Исходный код (я использую Mule CE версии 3.2.1) был такой:
protected void addProperties(MuleMessage message) { ... final String key = entry.getKey(); Object value= entry.getValue(); Object realValue = value; //Enable expression support for property values if (muleContext.getExpressionManager().isExpression(value.toString())) { realValue = muleContext.getExpressionManager().evaluate(value.toString(), message); } ...
То, что мы видим здесь, является частью метода addProperties объекта MessagePropertiesTransformer. Код проверяет, является ли предоставленное значение добавленного свойства выражением, и если да, то разрешает выражение в ‘realValue’.
То, как я изменил это:
protected void addProperties(MuleMessage message) { ... final String key = entry.getKey(); Object value= entry.getValue(); Object realValue = value; // Modified to be able to execute expression in expressions 🙂 while (muleContext.getExpressionManager().isExpression(realValue.toString())){ realValue = muleContext.getExpressionManager().evaluate(realValue.toString(), message); } ...
Как видите, я перебираю realValue до тех пор, пока он больше не будет выражением. С помощью этой строки кода я могу получить желаемое поведение: предоставление выражения, которое разрешается в выражение, которое разрешается в реальное значение. Пока что для легкой части. Теперь я хотел использовать мой модифицированный трансформатор вместо стандартного, если я использую конструкцию, подобную:
<message-properties-transformer scope="invocation"> <add-message-property key="field1" value="#[xpath:#[header:INVOCATION:my.attribute.1]]"/> </message-properties-transformer>
Я решил это, добавив свое собственное пространство имен в конфигурацию Mule. Хотя это описано
здесь, я думаю, что здесь удобно привести полный пример:
- Определите схему для вашего элемента
В моем случае это было просто, так как я не изменил ничего на этом уровне, поэтому я просто скопировал существующий элемент в свой собственный файл схемы, который я сохранил как «my-schema.xsd» в каталоге META-INF моего проекта:
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://www.pascalalma.net/schema/core" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.pascalalma.net/schema/core" xmlns:mule="http://www.mulesoft.org/schema/mule/core" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xsd:import namespace="http://www.mulesoft.org/schema/mule/core" schemaLocation="http://www.mulesoft.org/schema/mule/core/3.2/mule.xsd"/> <xsd:annotation> <xsd:documentation>My Mule Extension.</xsd:documentation> </xsd:annotation> <!-- My Transformer definition --> <xsd:element name="message-properties-transformer" type="mule:messagePropertiesTransformerType" substitutionGroup="mule:abstract-transformer"> <xsd:annotation> <xsd:documentation> A transformer that can add, delete or rename message properties. </xsd:documentation> </xsd:annotation> </xsd:element> </xsd:schema>
Просто убедитесь, что в XSD указан префикс типа и группы замещения, на который вы ссылаетесь, поскольку в противном случае вы получите ошибки о неизвестных элементах XML.
- Написать обработчик пространства имен
В этом случае это почти копия существующего NamespaceHandler для преобразователя:
package net.pascalalma.mule.config; import net.pascalalma.mule.config.spring.parsers.specific.MessagePropertiesTransformerDefinitionParser; import org.mule.config.spring.handlers.AbstractMuleNamespaceHandler; /** * * @author pascal */ public class MyNamespaceHandler extends AbstractMuleNamespaceHandler { @Override public void init() { registerBeanDefinitionParser("message-properties-transformer", new MessagePropertiesTransformerDefinitionParser()); } }
- Напишите определение парсера
Это становится скучно, но это также в значительной степени копия существующего MessagePropertiesTransformerDefinitionParser:
package net.pascalalma.mule.config.spring.parsers.specific; import net.pascalalma.mule.transformer.MessagePropertiesTransformer; import org.mule.config.spring.parsers.specific.MessageProcessorDefinitionParser; /** * * @author pascal */ public class MessagePropertiesTransformerDefinitionParser extends MessageProcessorDefinitionParser { public MessagePropertiesTransformerDefinitionParser() { super(MessagePropertiesTransformer.class); addAlias("scope", "scopeName"); } }
- Установите отображение обработчика Spring
Просто убедитесь, что вы импортируете правильный MessagePropertiesTransformer здесь!
Добавьте файл ‘spring.handlers’ в проект в каталоге META-INF, если он еще не существует. В файле положить следующее:
http\://www.pascalalma.net/schema/core=net.pascalalma.mule.config.MyNamespaceHandler
- Установите отображение локальной схемы
Добавьте файл ‘spring.schemas’ в проект в каталоге META-INF, если он еще не существует. В файле положить следующее:
http\://www.pascalalma.net/schema/core/1.0/my-schema.xsd=META-INF/my-schema.xsd
- Измените конфигурацию Mule, чтобы включить настраиваемое пространство имен
Я добавил следующие части в мою конфигурацию Mule. Сначала добавьте объявление схемы:
xmlns:pan="http://www.pascalalma.net/schema/core" ... xsi:schemaLocation="http://www.pascalalma.net/schema/core http://www.pascalalma.net/schema/core/1.0/my-schema.xsd
Затем я использую этот префикс пространства имен с моим преобразователем следующим образом:
<pan:message-properties-transformer scope="invocation"> <add-message-property key="field1" value="#[header:INVOCATION:id.attribute.1]"/> </pan:message-properties-transformer>
Как видите, я изменил содержимое поля field1, чтобы оно соответствовало моим потребностям. В настоящее время происходит то, что выражение «# [header: INVOCATION: id.attribute.1]» преобразуется в выражение XPath, например «# [xpath: / msg / header / ID]», и это преобразуется в реальное значение, которое я можно использовать в оставшейся части потока.