Статьи

Hello Camel: автоматическая передача файлов

Apache Camel описан на его главной веб-странице (и в Руководстве пользователя Camel ) как «универсальная инфраструктура интеграции с открытым исходным кодом, основанная на известных корпоративных шаблонах интеграции». Инфраструктура Camel основана на книге Enterprise Integration Patterns и предоставляет реализации шаблонов, описанных в этой книге . В этом посте я рассмотрел пример использования Hello World типа Camel.

Веб-страница Camel и руководство пользователя также ссылаются на ветку StackOverflow. Что такое Apache Camel? это включает в себя несколько хороших описаний Apache Camel. Дэвид Ньюкомб описал Верблюда там:


Apache Camel — это технология обмена сообщениями с возможностью маршрутизации. Он объединяет начальную и конечную точки обмена сообщениями, позволяя передавать сообщения из разных источников в разные места назначения. Например: JMS-> JSON, HTTP-> JMS или воронка FTP-> JMS, HTTP-> JMS, JMS => JSON.

В этой статье я рассмотрю простое использование Camel, которое не требует использования JMS-провайдера или даже FTP или HTTP. Простота примера упрощает использование Camel. В этом примере Camel используется для автоматической передачи файлов из указанного каталога в другой указанный каталог. Три случая будут продемонстрированы.

В первом случае файлы, помещенные в каталог «input», автоматически копируются в каталог «output», не затрагивая исходные файлы. Во втором случае файлы, помещенные в каталог «input», автоматически копируются в каталог «output», а затем файлы в каталоге «input» сохраняются в специальном подкаталоге «.camel» в каталоге «input». В третьем случае файлы удаляются из каталога «input» при копировании в каталог «output» (фактически это операция «move»). Все три случая реализованы с почти одинаковым кодом. Единственное различие между ними заключается в единственной строке, указывающей, как Camel должен обрабатывать передачу файлов.

В следующем листинге кода показан базовый код, необходимый для использования Camel для автоматического копирования файлов, помещенных во входной каталог, в другой выходной каталог с Camel.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
 * Simple executable function to demonstrate Camel file transfer.
 *
 * @param arguments Command line arguments; excepting duration in milliseconds
 *    as single argument.
 */
public static void main(final String[] arguments)
{
   final long durationMs = extractDurationMsFromCommandLineArgs(arguments);
   final CamelContext camelContext = new DefaultCamelContext();
   try
   {
      camelContext.addRoutes(
         new RouteBuilder()
         {
            @Override
            public void configure() throws Exception
            {
               from('file:C:\\datafiles\\input?noop=true').to('file:C:\\datafiles\\output');
            }
         });
      camelContext.start();
      Thread.sleep(durationMs);
      camelContext.stop();
   }
   catch (Exception camelException)
   {
      LOGGER.log(
        Level.SEVERE,
        'Exception trying to copy files - {0}',
        camelException.toString());
   }
}

Приведенный выше код демонстрирует минимальное использование Camel API и поддержку Camel Java DSL. CamelContext определяется с использованием экземпляра DefaultCamelContext (строка 10). Строки 13-21 добавляют маршрут Camel к этому конкретному контексту, а строка 22 начинает контекст с строки 24, останавливая контекст. Все довольно просто, но наиболее интересная часть для меня — это спецификация маршрутизации в строке 19.

Поскольку экземпляр, реализующий интерфейс RoutesBuilder, предоставляемый для контекста Camel, требует переопределения только своего абстрактного метода configure, его легко создать как анонимный класс, встроенный в вызов CamelContext.addRoutes (RoutesBuilder) . Это то, что я сделал в приведенном выше коде, и то, что сделано во многих примерах Camel, которые доступны онлайн.

Строка 19 показывает хорошо читаемый синтаксис, описывающий «от» и «до» части маршрутизации. В этом случае файлы, помещенные во входной каталог («from»), должны быть скопированы в выходной каталог («to»). Протокол «file» используется как в частях «from», так и в частях «to», потому что файловая система — это то место, откуда приходит и собирается «сообщение». ‘? Noop = true’ в вызове ‘from’ указывает, что ничего не должно быть изменено в файлах в каталоге ‘input’ (обработка должна иметь эффект ‘noop’ для исходных файлов).

Как только что упомянуто, строка 19 в приведенном выше коде инструктирует Camel копировать файлы, уже находящиеся или помещенные в каталог «input», в указанный каталог «output», не затрагивая файлы в каталоге «input». В некоторых случаях я могу захотеть «переместить» файлы, а не «скопировать» их. В таких случаях можно указать ?noop=true вместо ?noop=true при указании конечной точки ‘from’. Другими словами, строка 19 выше может быть заменена на эту, чтобы файлы удалялись из каталога «input» при помещении в каталог «output». Если на входе не ?noop=true ни один параметр (ни ?noop=true ни ?delete=true ), то происходит действие, попадающее между ними: файлы в каталоге ‘input’ перемещаются в специально созданный новый подкаталог под ‘входной’ каталог называется .camel . Три случая выделены следующим.

Файлы, скопированные из файлов данных \ input в datafiles \ output без влияния на исходные файлы

1
from('file:C:\\datafiles\\input?noop=true').to('file:C:\\datafiles\\output');

Файлы, перемещенные из файлов данных \ input в datafiles \ output

1
from('file:C:\\datafiles\\input?delete=true').to('file:C:\\datafiles\\output');

Файлы, скопированные из файлов данных \ input в datafiles \ output и исходные файлы, перемещены в подкаталог .camel

1
from('file:C:\\datafiles\\input').to('file:C:\\datafiles\\output');

В качестве дополнительного примечания, использование беглого «от» и «до» является примером Java DSL Camel. Camel реализует это с помощью наследования реализации (такие методы, как «from» и «to» определены в классе RouteBuilder ), а не с помощью статического импорта (подход, часто используемый для DSL на основе Java).

Хотя обычно анонимные экземпляры RouteBuilder в Camel Context, это не является обязательным требованием. Могут быть ситуации, в которых выгодно иметь автономные классы, которые расширяют RouteBuilder и экземпляры этих расширенных классов передаются в контекст Camel. Я буду использовать этот подход, чтобы продемонстрировать все три случая, которые я описал ранее. Следующий листинг кода показывает класс, который расширяет RouteBuilder . Во многих случаях у меня был бы конструктор без аргументов, но в этом случае я использую конструктор, чтобы определить, какой тип передачи файлов должен поддерживаться маршрутом Camel.

В следующем листинге кода показан именованный автономный класс, который обрабатывает все три случая, показанные выше (копирование, копирование с архивированием входных файлов и перемещение). Это единственное расширение RouteBuilder использует перечисление в своем конструкторе, чтобы определить, как сконфигурировать входную конечную точку.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package dustin.examples.camel;
 
import org.apache.camel.builder.RouteBuilder;
 
/**
 * Camel-based Route Builder for transferring files.
 *
 * @author Dustin
 */
public class FileTransferRouteBuilder extends RouteBuilder
{
   public enum FileTransferType
   {
      COPY_WITHOUT_IMPACTING_ORIGINALS('C'),
      COPY_WITH_ARCHIVED_ORIGINALS('A'),
      MOVE('M');
 
      private final String letter;
 
      FileTransferType(final String newLetter)
      {
         this.letter = newLetter;
      }
 
      public String getLetter()
      {
         return this.letter;
      }
 
      public static FileTransferType fromLetter(final String letter)
      {
         FileTransferType match = null;
         for (final FileTransferType type : FileTransferType.values())
         {
            if (type.getLetter().equalsIgnoreCase(letter))
            {
               match = type;
               break;
            }
         }
         return match;
      }
   }
 
   private final String fromEndPointString;
   private final static String FROM_BASE = 'file:C:\\datafiles\\input';
   private final static String FROM_NOOP = FROM_BASE + '?noop=true';
   private final static String FROM_MOVE = FROM_BASE + '?delete=true';
 
   public FileTransferRouteBuilder(final FileTransferType newFileTransferType)
   {
      if (newFileTransferType != null)
      {
         switch (newFileTransferType)
         {
            case COPY_WITHOUT_IMPACTING_ORIGINALS :
               this.fromEndPointString = FROM_NOOP;
               break;
            case COPY_WITH_ARCHIVED_ORIGINALS :
               this.fromEndPointString = FROM_BASE;
               break;
            case MOVE :
               this.fromEndPointString = FROM_MOVE;
               break;
            default :
               this.fromEndPointString = FROM_NOOP;
         }
      }
      else
      {
         fromEndPointString = FROM_NOOP;
      }
   }
 
   @Override
   public void configure() throws Exception
   {
      from(this.fromEndPointString).to('file:C:\\datafiles\\output');
   }
}

Этот блог продемонстрировал использование Camel для простой маршрутизации файлов из одного каталога в другой. Camel поддерживает множество других транспортных механизмов и форматов данных, которые здесь не показаны. Camel также поддерживает возможность трансформации маршрутизируемых сообщений / данных, что также здесь не показано. Этот пост был посвящен тому, что, вероятно, будет самым простым примером того, как применять Camel полезным способом, но Camel поддерживает гораздо больше, чем показано в этом простом примере.

Ссылка: Hello Camel: Автоматическая передача файлов от нашего партнера JCG Дастина Маркса в блоге Inspired by Actual Events .