I have a simple Camel application that is tracing to a JMS endpoint. I am currently experiencing an issue where it appears that the received JMS message is not being acknowledged (It is reading from a queue without any messages being put on it and the current queue depth is not reducing).
Any idea on what may be causing this issue?
Tracing Route
from("jms.tracer")
.id("openlink-input-trace")
.process(new Processor()
{
#Override
public void process(Exchange exchange) throws Exception
{
System.out.println("test");
}
});
Spring JMS Config
<bean id="tracerQueueConnFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate" ref="jndiTemplate" />
<property name="jndiName" value="${jms.openlink-tracer-queue-qcf.jndiname}" />
</bean>
<bean id="proxyTracerQueueConnFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
<property name="targetConnectionFactory" ref="tracerQueueConnFactory" />
<property name="username" value="${jms.openlink-tracer-queue-qcf.username}" />
<property name="password" value="${jms.openlink-tracer-queue-qcf.password}" />
</bean>
<bean id="jmsTrace" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="proxyTracerQueueConnFactory" />
<property name="destinationResolver" ref="jndiResolver" />
</bean>
Spring Endpoint Config
<endpoint id="jms.tracer"
uri="jmsTrace:queue:${jms.openlink-tracer-queue.jndiname}" />
EDIT:
This is using TibcoEMS as the broker.
All I can see in the logs is the following:
[2012 Jul 11 11:39:46] DEBUG []
(AbstractPollingMessageListenerContainer.java:313) - Received message
of type [class com.tibco.tibjms.TibjmsObjectMessage] from consumer
[QueueReceiver[queue=f2b.prototype.tracer.queue]] of session
[com.tibco.tibjms.TibjmsSession#16c143]
[2012 Jul 11 11:39:46] DEBUG [] (EndpointMessageListener.java:72) -
Endpoint[jmsTrace://queue:/user_dev/db/us/GTO/CIFramework/S001DEV/f2b.prototype.tracer.queue:queue]
consumer received JMS message: ObjectMessage={ Header={
JMSMessageID={ID:db_us_GTO_CIFramework_S001DEV.20D84FDA9F769B1A97:3}
JMSDestination={Queue[f2b.prototype.tracer.queue]} JMSReplyTo={null}
JMSDeliveryMode={PERSISTENT} JMSRedelivered={false}
JMSCorrelationID={null} JMSType={null} JMSTimestamp={Wed Jul 11
10:53:48 CDT 2012} JMSExpiration={0} JMSPriority={4} } Properties={ }
Object={com.db.cif.tracer.jpa.model.JpaTraceEventMessage#1dfe3f} }
[2012 Jul 11 11:39:46] DEBUG [] (JmsTemplate.java:464) - Executing
callback on JMS Session: com.tibco.tibjms.TibjmsSession#16c143
[2012 Jul 11 11:39:46] DEBUG [] (JmsConfiguration.java:266) - Sending
JMS message to: Queue[f2b.prototype.tracer.queue] with message:
ObjectMessage={ Header={ JMSMessageID={null} JMSDestination={null}
JMSReplyTo={null} JMSDeliveryMode={PERSISTENT} JMSRedelivered={false}
JMSCorrelationID={null} JMSType={null} JMSTimestamp={0}
JMSExpiration={0} JMSPriority={4} } Properties={ }
Object={com.db.cif.tracer.jpa.model.JpaTraceEventMessage#16119a} }
test
[2012 Jul 11 11:39:52] DEBUG []
(AbstractPollingMessageListenerContainer.java:313) - Received message
of type [class com.tibco.tibjms.TibjmsObjectMessage] from consumer
[QueueReceiver[queue=f2b.prototype.tracer.queue]] of session
[com.tibco.tibjms.TibjmsSession#16c143]
[2012 Jul 11 11:39:52] DEBUG [] (EndpointMessageListener.java:72) -
Endpoint[jmsTrace://queue:/user_dev/db/us/GTO/CIFramework/S001DEV/f2b.prototype.tracer.queue:queue]
consumer received JMS message: ObjectMessage={ Header={
JMSMessageID={ID:db_us_GTO_CIFramework_S001DEV.20D84FDA9F769B1A97:4}
JMSDestination={Queue[f2b.prototype.tracer.queue]} JMSReplyTo={null}
JMSDeliveryMode={PERSISTENT} JMSRedelivered={false}
JMSCorrelationID={null} JMSType={null} JMSTimestamp={Wed Jul 11
10:53:50 CDT 2012} JMSExpiration={0} JMSPriority={4} } Properties={ }
Object={com.db.cif.tracer.jpa.model.JpaTraceEventMessage#1d81bc5} }
[2012 Jul 11 11:39:52] DEBUG [] (JmsTemplate.java:464) - Executing
callback on JMS Session: com.tibco.tibjms.TibjmsSession#16c143
[2012 Jul 11 11:39:52] DEBUG [] (JmsConfiguration.java:266) - Sending
JMS message to: Queue[f2b.prototype.tracer.queue] with message:
ObjectMessage={ Header={ JMSMessageID={null} JMSDestination={null}
JMSReplyTo={null} JMSDeliveryMode={PERSISTENT} JMSRedelivered={false}
JMSCorrelationID={null} JMSType={null} JMSTimestamp={0}
JMSExpiration={0} JMSPriority={4} } Properties={ }
Object={com.db.cif.tracer.jpa.model.JpaTraceEventMessage#3b09b4} }
I knew I was doing something stupid!
I took a closer look at the trace messages and realized that tracing was enabled on my context causing my tracer route to be traced and thus a nice little infinite loop.
Related
I am trying to use my own complex error handler for a rest dsl route. With myErrorHandler I define my own handler and its works. If occur an exception my handler is called and do his stuff. At the end of the handler I clear my exchange:
private void clearExchange() {
exchange.getIn().reset();
exchange.setException(null);
exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, 500);
exchange.getIn().setBody("Server Error");
}
but my main problem is, I don’t get as client a response with status code 500. My Application show me the exception stacktrace. If I use simple onException in my camelcontext, its works but my error handler are not called. I thought if an exception occur, the exchange go to my error handler and after this he go back to the consumer.
<bean id="myErrorHandler" class="org.apache.camel.builder.DefaultErrorHandlerBuilder">
<property name="onExceptionOccurred" ref="myErrorProcess"/>
</bean>
<bean id="myErrorProcess" class="de.myErrorProcess">
<property name="PropertiesFilePath" value="conf\general.properties"/>
</bean>
<camel:camelContext errorHandlerRef="myErrorHandler" xmlns="http://camel.apache.org/schema/spring">
<routeContextRef ref="RouteA"/>
<restConfiguration component="jetty" host="0.0.0.0" scheme="http" port="80"
apiContextPath="api-doc" enableCORS="false">
<componentProperty key="useContinuation" value="false"/>
<dataFormatProperty key="prettyPrint" value="true"/>
</restConfiguration>
<rest>
<get id="getPing" uri="/ping">
<responseMessage code="200" responseModel="de.model.Ping" message="Ok"/>
<to uri="direct:ping"/>
</get>
</rest>
</camel:camelContext>
I have Apache Camel route which invokes restlet component and used redelivery mechanism from the exception handler which performs some processing on every failure to update my database record but if I provide the redelivery delay of 2000, it is taking 24 seconds to retry the every preceding attempt. Below is the piece of code. Let me know why it is taking more delay than expected.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:cxf="http://camel.apache.org/schema/cxf"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd">
<!-- CXF Rest Endpoint Declaration -->
<cxf:rsServer address="http://localhost:9092/rest/corp"
id="FetchCDFRestRequest" serviceClass="com.tcl.Service.Service" />
<bean class="com.tcl.ExceptionOccurredRefProcessor" id="exProc" />
<bean class="org.apache.camel.builder.DeadLetterChannelBuilder"
id="DLCErrorHandler">
<property name="deadLetterUri"
value="activemq:queue:DMS.FAILURES.DLQ" />
<property name="redeliveryPolicy" ref="redeliveryPolicy" />
</bean>
<bean class="org.apache.camel.processor.RedeliveryPolicy"
id="redeliveryPolicy">
<property name="maximumRedeliveries"
value="3" />
<property name="maximumRedeliveryDelay" value="2000" />
<property name="retryAttemptedLogLevel" value="WARN" />
</bean>
<camelContext id="Corp"
xmlns="http://camel.apache.org/schema/spring">
<errorHandler id="eh" onExceptionOccurredRef="exProc">
<redeliveryPolicy id="redeliveryPolicy" />
</errorHandler>
<route errorHandlerRef="DLCErrorHandler"
id="MainRouteOppIDFolder" streamCache="true">
<from id="_CreateOppIDFolder"
uri="restlet:http://localhost:9092/rest/corp/createOppIDFolder?restletMethod=POST" />
----------
<to uri="restlet:http://localhost:9902/CreateOppIDFolder?restletMethod=POST" />
------------
<onException id="_onException1"
onExceptionOccurredRef="exProc"
redeliveryPolicyRef="redeliveryPolicy" useOriginalMessage="true">
<exception>java.lang.Exception</exception>
<handled>
<simple>true</simple>
</handled>
<log id="_log3" loggingLevel="INFO"
message="Handled ex >>>>> ${exception.message} " />
</onException>
</route>
</camelContext>
</beans>
Below are some of the logs
14:47:52.701 [Restlet-1879974483] WARN o.a.c.processor.DeadLetterChannel - Failed delivery for (MessageId: ID-DESKTOP-P2DBOO5-1580115331236-0-19 on ExchangeId: ID-DESKTOP-P2DBOO5-1580115331236-0-20). On delivery attempt: 0 caught: org.apache.camel.component.restlet.RestletOperationException: Restlet operation failed invoking http://localhost:9902/CreateOppIDFolder with statusCode: 500 /n responseBody:org.apache.cxf.interceptor.Fault: Could not send Message.
14:48:15.044 [Camel (MyCamel) thread #15 - ErrorHandlerRedeliveryTask] WARN o.a.c.processor.DeadLetterChannel - Failed delivery for (MessageId: ID-DESKTOP-P2DBOO5-1580115331236-0-19 on ExchangeId: ID-DESKTOP-P2DBOO5-1580115331236-0-20). On delivery attempt: 1 caught: org.apache.camel.component.restlet.RestletOperationException: Restlet operation failed invoking http://localhost:9902/CreateOppIDFolder with statusCode: 500 /n responseBody:org.apache.cxf.interceptor.Fault: Could not send Message.
14:48:37.252 [Camel (MyCamel) thread #17 - ErrorHandlerRedeliveryTask] WARN o.a.c.processor.DeadLetterChannel - Failed delivery for (MessageId: ID-DESKTOP-P2DBOO5-1580115331236-0-19 on ExchangeId: ID-DESKTOP-P2DBOO5-1580115331236-0-20). On delivery attempt: 2 caught: org.apache.camel.component.restlet.RestletOperationException: Restlet operation failed invoking http://localhost:9902/CreateOppIDFolder with statusCode: 500 /n responseBody:org.apache.cxf.interceptor.Fault: Could not send Message.
Any suggestions please?
Are you sure it is taking 24 seconds to (begin the) retry?
Couldn't it take around 24 seconds until the retry fails (end of retry)?
All three log statements are reporting an error 500 from the target endpoint. Is it possible that the retry starts after 2 seconds, makes the HTTP call, but it takes another 20 seconds until the endpoint answers with an error 500?
00:00 error occurs
00:02 Camel triggers retry after 2 seconds
00:02 HTTP call to http://localhost:9902...
00:xx Waiting for reponse from http://localhost:9902
00:2x Log output after 20-something seconds that retry is failed
Of some reason, QUEUE_A does not ALWAYS has 1 exchanges - sometimes it has 0, unless I add a Thread.sleep(100) to the test. I guess whenCompleted/whenDone isn't completely done when it actually says it's done. How can I verify that it is completely done?
multicast().parallelProcessing().to(QUEUE_A, QUEUE_B, QUEUE_C, QUEUE_D)
And testing with:
#Test
public void test() {
NotifyBuilder notify = new NotifyBuilder(context)
.from(QUEUE_INCOMING)
.whenCompleted(1)
.create();
template.sendBody(QUEUE_INCOMING, streamToString(loadResourceAsStream("/data/TestData.xml")));
boolean matches = notify.matches(4, SECONDS);
assertTrue("Notify failed", matches);
Thread.sleep(100); //Without this, it fails
verifyEndpoints(1, context, QUEUE_A, QUEUE_B, QUEUE_C, QUEUE_D);
}
public static void verifyEndpoints(int expectedSize, ModelCamelContext context, String... endpoints) {
for (String endpoint : endpoints) {
BrowsableEndpoint be = context.getEndpoint(endpoint, BrowsableEndpoint.class);
assertThat(String.format("Endpoint exchanges '%s' has wrong size", endpoint), be.getExchanges(), hasSize(expectedSize));
}
}
And the endpoint bean, using ActiveMQ when testing, but is going to use WebSphere MQ in prod:
<bean id="wmq" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory">
<bean class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="vm://localhost?broker.persistent=false" />
</bean>
</property>
</bean>
The problem is that you browse a WMQ asap after sending a message to it, and therefore depending on broker implementation and timing etc, you may not see the very last messages, when using the JMS browsing api.
And hence why it seems to fix when you wait a bit with the sleep.
I have a test case that loads up the blueprint.xml and persistence.xml at the start of the JUnit but when the test actually runs an error is thrown for not having a persistence provider.
Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named blacklisting-pu
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:69)
at org.springframework.orm.jpa.LocalEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalEntityManagerFactoryBean.java:92)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:310)
at org.apache.camel.component.jpa.JpaEndpoint.createEntityManagerFactory(JpaEndpoint.java:255)
at org.apache.camel.component.jpa.JpaEndpoint.getEntityManagerFactory(JpaEndpoint.java:165)
at org.apache.camel.component.jpa.JpaEndpoint.validate(JpaEndpoint.java:248)
at org.apache.camel.component.jpa.JpaEndpoint.createProducer(JpaEndpoint.java:103)
at org.apache.camel.impl.ProducerCache.doGetProducer(ProducerCache.java:405)
here is the first part of the log showing the provider is loaded:
16 blacklisting-pu TRACE [main] openjpa.Runtime - Setting the following properties from "file:/workspace/git/jdbc-util/target/test-classes/META-INF/persistence.xml" into configuration: {openjpa.jdbc.SynchronizeMappings=buildSchema(SchemaAction='add,deleteTableContents'), openjpa.ConnectionPassword=, openjpa.ConnectionDriverName=org.h2.Driver, javax.persistence.provider=org.apache.openjpa.persistence.PersistenceProviderImpl, openjpa.MetaDataFactory=jpa(Types=com.entity.MyEntity), openjpa.Log=DefaultLevel=TRACE, Tool=INFO, PersistenceVersion=1.0, openjpa.ConnectionUserName=, openjpa.ConnectionURL=jdbc:h2:mem:blacklisting;DB_CLOSE_DELAY=1000, openjpa.Id=blacklisting-pu}
74 blacklisting-pu TRACE [main] openjpa.Runtime - No cache marshaller found for id org.apache.openjpa.conf.MetaDataCacheMaintenance.
119 blacklisting-pu TRACE [main] openjpa.Runtime - No cache marshaller found for id org.apache.openjpa.conf.MetaDataCacheMaintenance.
128 blacklisting-pu TRACE [main] openjpa.MetaData - Scanning resource "META-INF/orm.xml" for persistent types.
129 blacklisting-pu TRACE [main] openjpa.MetaData - The persistent unit root url is "null"
129 blacklisting-pu TRACE [main] openjpa.MetaData - parsePersistentTypeNames() found [com.entity.BlacklistingEntity].
129 blacklisting-pu TRACE [main] openjpa.MetaData - Found 1 classes with metadata in 9 milliseconds.
132 blacklisting-pu TRACE [main] openjpa.MetaData - Clearing metadata repository"org.apache.openjpa.meta.MetaDataRepository#1766bfd8".
I had the test case working using spring and defining the route in a spring camel-context.xml but then I needed to move the route to a blueprint.xml and now it can't seem to find the persistence.xml at runtime for the tests.
I have been using this as my reference along with alot of googleing:
http://camel.apache.org/blueprint-testing.html
Any help would be much appreciated
EDIT:
I have ran the following as part of the setup method in JUnit and the calss is found without issue
Object obj = Class.forName("org.apache.openjpa.persistence.PersistenceProviderImpl").newInstance();
if(null==obj){
Assert.fail("org.apache.openjpa.persistence.PersistenceProviderImpl not present on classpath.");
}else{
LOG.info("the class {} exists on the calsspath.",obj.getClass().getName());
}
here is the log showing it loaded
Creating service instance
Service created: org.apache.aries.blueprint.ext.impl.ExtNamespaceHandler#10a33ce2
Creating listeners
the class org.apache.openjpa.persistence.PersistenceProviderImpl exists on the calsspath.
Persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0">
<persistence-unit name="blacklisting-pu" transaction-type="RESOURCE_LOCAL">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<class>com.entity.BlacklistingEntity</class>
<properties>
<property name="openjpa.ConnectionURL" value="jdbc:h2:mem:blacklisting;DB_CLOSE_DELAY=1000" />
<property name="openjpa.ConnectionDriverName" value="org.h2.Driver" />
<property name="openjpa.ConnectionUserName" value="" />
<property name="openjpa.ConnectionPassword" value="" />
<property name="openjpa.Log" value="DefaultLevel=TRACE, Tool=INFO" />
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(SchemaAction='add,deleteTableContents')" />
</properties>
</persistence-unit>
</persistence>
I have this :
15:20:06 | INFO | aultShutdownStrategy | mel.impl.DefaultShutdownStrategy 73 | Starting to graceful shutdown routes (timeout 300 seconds)
15:20:06 | INFO | aultShutdownStrategy | mel.impl.DefaultShutdownStrategy 106 | Graceful shutdown of routes completed in 0 seconds
15:20:06 | WARN | ltInflightRepository | l.impl.DefaultInflightRepository 91 | Shutting down while there are still 1 in flight exchanges.
I thought the graceful shutdown would wait for this in flight exchange to land!
Why does it say "shutdown of routes completed in 0 seconds"?
Could it be related to the Thread.sleep(30000); I wrote in a processor in the route where the exchange is still inflight?
EDIT :
I have this config into applicationContext :
<bean id="MainRouteBuilder" class="something.router2.MainRoute" init-method="init">
<property name="ruleService" >
<osgi:reference interface="something.router2.service.RuleService" />
</property>
<property name="controlInbox" value="${router.controlInbox}" />
<property name="errorBox" value="${router.errorBox}" />
<property name="rulesCamelContext" ref="secondCamelContext" />
</bean>
<!-- Camel -->
<camelContext xmlns="http://camel.apache.org/schema/spring" id="myCamelContext">
<routeBuilder ref="MainRouteBuilder"/>
</camelContext>
<camelContext xmlns="http://camel.apache.org/schema/spring" id="secondCamelContext">
</camelContext>
I try to stop "secondCamelContext" into a route using "myCamelContext".
How do you shutdown the application?
If you trigger a shutdown from a route then see this FAQ: http://camel.apache.org/how-can-i-stop-a-route-from-a-route.html how to do this correctly. If doing this wrong then you may have the situation above with 1 inflight message stuck in the registry when you shutdown.