Статьи

Apache Camel Wire Tap Примеры

Если вы хотите отслеживать, отлаживать и устранять неполадки сообщений, проходящих по маршруту, не беспокоясь о постоянном удалении сообщения из канала, то вам необходимо использовать проводное нажатие .

Сигнал проводной связи действует как список получателей, который получает сообщения из входного канала и публикует их в обоих выходных каналах.

Первый должен быть к фактическому назначению, которое действует как первичный канал, а второй — к назначению проводного отвода, который действует как вторичный канал.

Прежде чем мы начнем с примера, давайте посмотрим на детали настройки.

В этом примере используются следующие рамки:

  1. Maven 3.2.3
  2. Apache Camel 2.15.1
  3. Весна 4.1.5. ВЫПУСК
  4. Eclipse as IDE, версия Luna 4.4.1.

зависимости

Мы просто полагаемся на основные компоненты верблюда и компонент логгера, поэтому наш pom.xml состоит из:

  1. camel-core
  2. slf4j-api
  3. slf4j-log4j12

pom.xml:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.javarticles.camel</groupId>
    <artifactId>camelHelloWorld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-core</artifactId>
            <version>2.15.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.12</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.12</version>
        </dependency>
    </dependencies>
</project>

Простой проволочный кран Пример

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

Проволочный кран

Проволочный кран

Вам нужно использовать оператор wireTap , указать URI конечной точки, куда отправлять копию сообщения. Процессор Wire Tap обрабатывает его в отдельном потоке, управляемом механизмом маршрутизации Camel.

В нашем примере мы отправляем сообщение «One» для direct:start чтобы инициировать маршрут. Копия сообщения будет отправлена ​​адресату WireTap direct:tap . Исходное сообщение сообщения продолжается по основному маршруту к bean для дальнейшей обработки. MyBean.addTwo добавляет строку «Два» к «Один». В маршруте прослушивания, который происходит в отдельном потоке, сообщение отправляется на MyBean.addThree чтобы добавить «Три» к «Один».

CamelWiretapExample:

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
package com.javarticles.camel;
 
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.util.jndi.JndiContext;
 
public class CamelWiretapExample {
    public static final void main(String[] args) throws Exception {
        JndiContext jndiContext = new JndiContext();
        jndiContext.bind("myBean", new MyBean());
        CamelContext camelContext = new DefaultCamelContext(jndiContext);
        try {
            camelContext.addRoutes(new RouteBuilder() {
                public void configure() {
                    from("direct:start")
                    .log("Main route: Send '${body}' to tap router")
                    .wireTap("direct:tap")
                    .log("Main route: Add 'two' to '${body}'")
                    .bean(MyBean.class, "addTwo")
                    .log("Main route: Output '${body}'");
 
                    from("direct:tap")
                    .log("Tap Wire route: received '${body}'")
                    .log("Tap Wire route: Add 'three' to '${body}'")
                    .bean(MyBean.class, "addThree")
                    .log("Tap Wire route: Output '${body}'");
                }
            });
            ProducerTemplate template = camelContext.createProducerTemplate();
            camelContext.start();
            template.sendBody("direct:start", "One");
        } finally {
            camelContext.stop();
        }
    }
}

MyBean:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package com.javarticles.camel;
 
import java.util.ArrayList;
import java.util.List;
 
public class MyBean {
 
    public String addTwo(String body) {
        return body + " and two";
    }
     
    public String addThree(String body) {
        return body + " and three";
    }       
}

Основной конечный результат маршрута — «Один и два». Выход назначения для отвода проводов — «Один и три».

Выход:

1
2
3
4
5
6
12:19| INFO | MarkerIgnoringBase.java 95 | Main route: Send 'One' to tap router
12:19| INFO | MarkerIgnoringBase.java 95 | Main route: Add 'two' to 'One'
12:19| INFO | MarkerIgnoringBase.java 95 | Tap Wire route: received 'One'
12:19| INFO | MarkerIgnoringBase.java 95 | Tap Wire route: Add 'three' to 'One'
12:19| INFO | MarkerIgnoringBase.java 95 | Tap Wire route: Output 'One and three'
12:19| INFO | MarkerIgnoringBase.java 95 | Main route: Output 'One and two'

Мелкая копия сообщения в Wire Tap

Процессор Wire Tap по умолчанию создает поверхностную копию экземпляра Camel Exchange. Копия обмена отправляется конечной точке, указанной в операторе wireTap. Тело сообщения с прослушиванием по проводам содержит тот же объект, что и в исходном сообщении, что означает, что любое изменение внутреннего состояния этого объекта во время маршрута отводов может также привести к изменению тела основного сообщения.

В приведенном ниже примере вместо отправки строки «One» мы оборачиваем ее в объект MyPayload а затем отправляем по direct:start чтобы инициировать маршрут. Основной маршрут добавляет «два» к значению полезной нагрузки, аналогично, маршрут отводов, добавляет «три».

MyBean:

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
package com.javarticles.camel;
 
import java.util.ArrayList;
import java.util.List;
 
public class MyBean {
 
    public String addTwo(String body) {
        return body + " and two";
    }
     
    public String addThree(String body) {
        return body + " and three";
    }       
     
    public MyPayload addTwo(MyPayload body) {
        body.setValue(body.getValue() + " and two");
        return body;
    }
     
    public MyPayload addThree(MyPayload body) {
        body.setValue(body.getValue() + " and three");
        return body;
    }
}

MyPayload действует как объект-обертка, содержащий строковое значение.

MyPayload:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
package com.javarticles.camel;
 
public class MyPayload {
    private String value;
     
    public MyPayload(String value) {
        this.value = value;
    }
 
    public String getValue() {
        return value;
    }
 
    public void setValue(String value) {
        this.value = value;
    }
     
    public String toString() {
        return value;
    }   
}

Несмотря на то, что сообщение копируется в пункт назначения проводного подключения, объект, который он содержит, совпадает с объектом основного маршрута. Поскольку одновременная маршрутизация по проволоке происходит одновременно, существует возможность изменения сообщения основного маршрута.

CamelWiretapShallowCopyExample:

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
package com.javarticles.camel;
 
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.util.jndi.JndiContext;
 
public class CamelWiretapShallowCopyExample {
    public static final void main(String[] args) throws Exception {
        JndiContext jndiContext = new JndiContext();
        jndiContext.bind("myBean", new MyBean());
        CamelContext camelContext = new DefaultCamelContext(jndiContext);
        try {
            camelContext.addRoutes(new RouteBuilder() {
                public void configure() {
                    from("direct:start")
                    .log("Main route: Send '${body}' to tap router")
                    .wireTap("direct:tap")
                    .log("Main route: Add 'two' to '${body}'")
                    .bean(MyBean.class, "addTwo")
                    .log("Main route: Output '${body}'");
 
                    from("direct:tap")
                    .log("Tap Wire route: received '${body}'")
                    .log("Tap Wire route: Add 'three' to '${body}'")
                    .bean(MyBean.class, "addThree")
                    .log("Tap Wire route: Output '${body}'");
                }
            });
            ProducerTemplate template = camelContext.createProducerTemplate();
            camelContext.start();
            MyPayload payload = new MyPayload("One");
            template.sendBody("direct:start", payload);
            System.out.println("Final payload: " + payload.getValue());
        } finally {
            camelContext.stop();
        }
    }
}

Конечная полезная нагрузка повреждена, это «Один и три» вместо «Один и два». В нашем следующем разделе мы глубоко скопируем объект, прежде чем передать его в место назначения отводов.

Выход:

1
2
3
4
5
6
7
8
15:25| INFO | MarkerIgnoringBase.java 95 | Main route: Send 'One' to tap router
15:25| INFO | MarkerIgnoringBase.java 95 | Main route: Add 'two' to 'One'
15:25| INFO | MarkerIgnoringBase.java 95 | Tap Wire route: received 'One'
15:25| INFO | MarkerIgnoringBase.java 95 | Tap Wire route: Add 'three' to 'One'
15:25| INFO | MarkerIgnoringBase.java 95 | Tap Wire route: Output 'One and three'
15:25| INFO | MarkerIgnoringBase.java 95 | Main route: Output 'One and three'
Final payload: One and three
15:25| INFO | DefaultCamelContext.java 2660 | Apache Camel 2.15.1 (CamelCont

Глубокая копия сообщения в Wire Tap

Wire Tap EIP предоставляет нам механизм для выполнения «глубокой» копии сообщения.

Давайте сначала добавим метод глубокого клонирования в MyPayload .

MyPayload:

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
package com.javarticles.camel;
 
public class MyPayload {
    private String value;
     
    public MyPayload(String value) {
        this.value = value;
    }
 
    public String getValue() {
        return value;
    }
 
    public void setValue(String value) {
        this.value = value;
    }
     
    public String toString() {
        return value;
    }
     
    public MyPayload deepClone() {
        MyPayload myPayload = new MyPayload(value);
        return myPayload;
    }
}

Затем реализуйте пользовательский Processor для глубокого клонирования объекта MyPayload .

MyPayloadClonePrepare:

01
02
03
04
05
06
07
08
09
10
11
package com.javarticles.camel;
 
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
 
public class MyPayloadClonePrepare implements Processor {
    public void process(Exchange exchange) throws Exception {
        MyPayload myPayload = exchange.getIn().getBody(MyPayload.class);
        exchange.getIn().setBody(myPayload.deepClone());
    }
}

Это нужно вызывать с onPrepare оператора onPrepare сразу после wireTap .

CamelWiretapOnPrepareExample:

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
package com.javarticles.camel;
 
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.util.jndi.JndiContext;
 
public class CamelWiretapOnPrepareExample {
    public static final void main(String[] args) throws Exception {
        JndiContext jndiContext = new JndiContext();
        jndiContext.bind("myBean", new MyBean());
        CamelContext camelContext = new DefaultCamelContext(jndiContext);
        try {
            camelContext.addRoutes(new RouteBuilder() {
                public void configure() {
                    from("direct:start")
                    .log("Send '${body}' to tap router")
                    .wireTap("direct:tap")
                       .onPrepare(new MyPayloadClonePrepare())
                    .end()
                    .delay(1000)
                    .log("Output of main '${body}'");
 
                    from("direct:tap")
                    .log("Tap router received '${body}'")
                    .bean(MyBean.class, "addThree")
                    .log("Output of tap '${body}'");
                }
            });
            ProducerTemplate template = camelContext.createProducerTemplate();
            camelContext.start();
            MyPayload payload = new MyPayload("One");
            template.sendBody("direct:start", payload);
            System.out.println("Final payload: " + payload.getValue());
        } finally {
            camelContext.stop();
        }
    }
}

Теперь на вывод основного маршрута не влияет маршрут отводов. Это правильно отображается как «Один и два».

Выход:

1
2
3
4
5
18:46| INFO | MarkerIgnoringBase.java 95 | Send 'One' to tap router
18:46| INFO | MarkerIgnoringBase.java 95 | Tap router received 'One'
18:46| INFO | MarkerIgnoringBase.java 95 | Output of tap 'One and three'
18:46| INFO | MarkerIgnoringBase.java 95 | Output of main 'One'
Final payload: One

Скачать исходный код

Это был пример Apache Camel Wire Tap. Вы можете скачать исходный код здесь: camelWireTapExample.zip

Ссылка: Apache Camel Wire Tap Примеры от нашего партнера JCG Рама Моккапати в блоге статей Java .