#spring #routing #apache-camel #messaging
#весна #маршрутизация #apache-camel #обмен сообщениями
Вопрос:
Я пытаюсь отфильтровать нулевые тела из моего маршрута. Маршрут опрашивает функцию каждые полсекунды или около того. Итак, я получаю эту ошибку в своей консоли также каждые полсекунды. Вот трассировка стека:
Message History
---------------------------------------------------------------------------------------------------------------------------------------
RouteId ProcessorId Processor Elapsed (ms)
[route1 ] [route1 ] [browserBean ] [ 0]
[route1 ] [filter1 ] [filter[simple{(${body} == null)}] ] [ 0]
Exchange
--------------------------------------------------------------------------------------- ------------------------------------------------
Exchange[
Id ID-CO183LTCS06-54352-1403798372606-0-1058
ExchangePattern InOnly
Headers {breadcrumbId=ID-CO183LTCS06-54352-1403798372606-0-1057, CamelRedelivered=false, CamelRedeliveryCounter=0}
BodyType null
Body [Body is null]
]
Stacktrace
---------------------------------------------------------------------------------------------------------------------------------------
java.lang.NullPointerException: null
at com.hello.integration.GreetingController.greeting(GreetingController.java:15)
at sun.reflect.GeneratedMethodAccessor22.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.camel.component.bean.MethodInfo.invoke(MethodInfo.java:407)
at org.apache.camel.component.bean.MethodInfo$1.doProceed(MethodInfo.java:278)
at org.apache.camel.component.bean.MethodInfo$1.proceed(MethodInfo.java:251)
at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:166)
at org.apache.camel.util.AsyncProcessorHelper.process(AsyncProcessorHelper.java:105)
at org.apache.camel.component.bean.BeanProcessor.process(BeanProcessor.java:67)
at org.apache.camel.impl.ProcessorPollingConsumer.receive(ProcessorPollingConsumer.java:58)
at org.apache.camel.impl.ProcessorPollingConsumer.receiveNoWait(ProcessorPollingConsumer.java: 66)
at org.apache.camel.impl.DefaultScheduledPollConsumer.poll(DefaultScheduledPollConsumer.java:48)
at org.apache.camel.impl.ScheduledPollConsumer.doRun(ScheduledPollConsumer.java:187)
at org.apache.camel.impl.ScheduledPollConsumer.run(ScheduledPollConsumer.java:114)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Есть идеи? Я чувствую, что это просто, но я искал решения по всему Интернету и не могу найти ничего, что решило бы мою проблему.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/osgi
http://camel.apache.org/schema/osgi/camel-osgi.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="browserBean"/>
<filter>
<simple>${body} == null</simple>
<stop/>
</filter>
<to uri="jms:queue:testQSource"/>
<to uri="myBean"/>
<log message="Routing message from testQSource to testQDestination queue with data ${body}"/>
<to uri="jms:queue:testQDestination"/>
<to uri="finalBean"/>
<log message="message: ${body}"/>
</route>
</camelContext>
<camel:camelContext id="camel-client">
<camel:template id="camelTemplate" />
</camel:camelContext>
<bean id="jms" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="brokerURL" value="tcp://localhost:61616" />
</bean>
<bean id="myBean" class="com.example.integration.modifier"/>
<bean id="finalBean" class="com.example.integration.ActionApp"/>
<bean id="browserBean" class="com.hello.integration.GreetingController"/>
</beans>
РЕДАКТИРОВАТЬ: нулевое тело поступает из следующей функции:
package com.hello.integration;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
@Controller
public class GreetingController {
@MessageMapping("/hello")
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
//Thread.sleep(3000); // simulated delay
return new Greeting("Hello, " message.getName() "!");
}
}
Несмотря на то, что я пытаюсь отфильтровать нулевые тела, я все еще получаю ошибку. Я отфильтровываю их слишком поздно?
Ответ №1:
Вы не можете поместить фильтр внутри тега from . Приведенный ниже маршрут должен работать 🙂
<camelContext xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="browserBean"/>
<filter>
<simple>${body} == null</simple>
<stop/>
</filter>
<to uri="jms:queue:testQSource"/>
<to uri="myBean"/>
<log message="Routing message from testQSource to testQDestination queue with data ${body}"/>
<to uri="jms:queue:testQDestination"/>
<to uri="finalBean"/>
<log message="message: ${body}"/>
</route>
Комментарии:
1. Спасибо, Виллем! К сожалению, даже после реализации этого хитроумного маршрута я все еще получаю ту же ошибку. Я отредактировал свой вопрос, чтобы отразить изменение в моем маршруте, а также опубликовать трассировку стека и функцию, которая возвращает null. Я был бы очень признателен, если бы вы взглянули.
2. Я хочу получать только одно сообщение за раз. Я буду отправлять только одно сообщение из приложения browser / UI. Тогда он станет потребителем, а не производителем. Я не уверен, как настроить camel так, чтобы он смотрел только тогда, когда есть что забрать, или только тогда, когда что-то нужно забрать, если что-то есть.
3. Я думаю, вы можете рассмотреть возможность использования шаблона producer для отправки сообщения в camel route вместо вызова browserBean из camel route.
Ответ №2:
Вы также можете использовать предложение выбора, как еще один способ сделать это. Вот один из примеров:
<route>
<from uri="direct:routePublishedResponse"/>
<bean ref="caseHearingHandler"/>
<choice>
<when>
<simple>${body} != null</simple>
<to uri="direct:resultSubRoute">
</when>
<otherwise>
<log message="skipping due to NULL body" loggingLevel="DEBUG" />
</otherwise>
</choice>
</route>