Статьи

Замена стандартного трансформатора мула с пользовательской реализацией


Хотя есть
много документации о
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");
    }
    
}

      Просто убедитесь, что вы импортируете правильный MessagePropertiesTransformer здесь!

      • Установите отображение обработчика Spring
      • Добавьте файл ‘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]», и это преобразуется в реальное значение, которое я можно использовать в оставшейся части потока.