<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-file</artifactId>
</dependency>
Класс EmailToOrderTransformer является реализацией интерфейса Spring Integration Transformer посредством расширения AbstractMailMessageTransformer (показано в следующем листинге).
Листинг 9.6. Преобразование входящих писем в тако-заказы с использованием интеграционного преобразователя
@Component
public class EmailToOrderTransformer
extends AbstractMailMessageTransformer<Order> {
@Override
protected AbstractIntegrationMessageBuilder<Order> doTransform(Message mailMessage)
throws Exception {
Order tacoOrder = processPayload(mailMessage);
return MessageBuilder.withPayload(tacoOrder);
}
…
}
AbstractMailMessageTransformer - удобный базовый класс для обработки сообщений, чья полезная нагрузка - это электронная почта. Он заботится о извлечении информации электронной почты из входящего сообщения в объект Message, который передается в метод doTransform().
В методе doTransform() вы передаете Message private методу с именем processPayload() для анализа электронной почты на получения объекта Order. Несмотря на то, что этот объект Order не похож на объект Order, используемый в основном приложении TacoCloud; это немного проще:
package tacos.email;
import java.util.ArrayList;
import java.util.List;
import lombok.Data;
@Data
public class Order {
private final String email;
private List<Taco> tacos = new ArrayList<>();
public void addTaco(Taco taco) {
this.tacos.add(taco);
}
}
Вместо того, чтобы содержать всю информацию о доставке и выставлении счетов клиентам, этот класс Order несет только электронную почту клиента, полученную из входящей электронной почты.
Парсинг электронных писем в тако-заказы является нетривиальной задачей. На самом деле, даже простенькая реализация включает в себя несколько десятков строк кода. И эти несколько десятков строк кода ничего не дадут для дальнейшего обсуждения Spring Integration и того, как реализовать трансформер. Поэтому, чтобы сэкономить место, я опускаю детали метода processPayload().
Последнее, что делает EmailToOrderTransformer, это возвращает MessageBuilder с полезной нагрузкой, содержащей объект Order. Сообщение, сгенерированное MessageBuilder, отправляется последнему компоненту в потоке интеграции: обработчику сообщений, который отправляет заказ в Taco Cloud API. OrderSubmitMessageHandler, показанный в следующем листинге, реализует GenericHandler в Spring Integration для обработки сообщений с полезной нагрузкой Order.
Листинг 9.7. Отправка заказов в Taco Cloud API через обработчик сообщений
package tacos.email;
import java.util.Map;
import org.springframework.integration.handler.GenericHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class OrderSubmitMessageHandler implements GenericHandler<Order> {
private RestTemplate rest;
private ApiProperties apiProps;
public OrderSubmitMessageHandler(
ApiProperties apiProps, RestTemplate rest) {
this.apiProps = apiProps;
this.rest = rest;
}
@Override
public Object handle(Order order, Map<String, Object> headers) {
rest.postForObject(apiProps.getUrl(), order, String.class);
return null;
}
}
Чтобы удовлетворить требования интерфейса GenericHandler, OrderSubmitMessageHandler переопределяет метод handle(). Этот метод получает входящий объект Order и использует внедренный RestTemplate для отправки Order посредством POST запроса на URL-адрес, полученный из объекте ApiProperties. Наконец, метод handle() возвращает null, чтобы указать, что этот обработчик отмечает конец потока.
ApiProperties используется, чтобы избежать жесткого кодирования URL-адреса при вызове postForObject(). Это файл свойств конфигурации, который выглядит следующим образом:
@Data
@ConfigurationProperties(prefix="tacocloud.api")
@Componentpublic class ApiProperties {
private String url;
}
А в application.yml URL-адрес для Taco Cloud API может быть настроен следующим образом:
tacocloud:
api:
urclass="underline" http://api.tacocloud.com
Чтобы сделать RestTemplate доступным в проекте, чтобы его можно было внедрить в OrderSubmitMessageHandler, необходимо добавить веб-стартер Spring Boot в сборку проекта:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
В то время как это делает RestTemplate доступным в classpath, оно также запускает автоконфигурирование для Spring MVC. В качестве автономного потока Spring Integration приложению не требуется Spring MVC или даже встроенный Tomcat, который обеспечивает автоконфигурация. Поэтому вам следует отключить автоконфигурирование Spring MVC с помощью следующей записи в application.ymclass="underline"
spring:
main:
web-application-type: none
Свойство spring.main.web-application-type может быть установлено в servlet, reactive или none. Когда Spring MVC находится в classpath, автоконфигурация устанавливает его значение в servlet. Но здесь вы переопределяете его на none, чтобы Spring MVC и Tomcat не были автоматически сконфигурированы. (Мы поговорим подробнее о том, что означает, что приложение является reactive веб-приложением в главе 11.)