/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.management; import java.util.List; import javax.management.Attribute; import javax.management.MBeanServer; import javax.management.ObjectName; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.apache.camel.Exchange; import org.apache.camel.api.management.mbean.BacklogTracerEventMessage; import org.apache.camel.builder.RouteBuilder; public class BacklogTracerTest extends ManagementTestSupport { @SuppressWarnings("unchecked") public void testBacklogTracerEventMessage() throws Exception { // JMX tests dont work well on AIX CI servers (hangs them) if (isPlatform("aix")) { return; } MBeanServer mbeanServer = getMBeanServer(); ObjectName on = new ObjectName("org.apache.camel:context=camel-1,type=tracer,name=BacklogTracer"); assertNotNull(on); assertTrue(mbeanServer.isRegistered(on)); Boolean enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled"); assertEquals("Should not be enabled", Boolean.FALSE, enabled); Integer size = (Integer) mbeanServer.getAttribute(on, "BacklogSize"); assertEquals("Should be 1000", 1000, size.intValue()); Boolean removeOnDump = (Boolean) mbeanServer.getAttribute(on, "RemoveOnDump"); assertEquals(Boolean.TRUE, removeOnDump); // enable it mbeanServer.setAttribute(on, new Attribute("Enabled", Boolean.TRUE)); getMockEndpoint("mock:foo").expectedMessageCount(2); getMockEndpoint("mock:bar").expectedMessageCount(2); template.sendBody("direct:start", "Hello World"); template.sendBody("direct:start", "Bye World"); assertMockEndpointsSatisfied(); List<Exchange> exchanges = getMockEndpoint("mock:foo").getReceivedExchanges(); List<BacklogTracerEventMessage> events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpTracedMessages", new Object[]{"foo"}, new String[]{"java.lang.String"}); assertNotNull(events); assertEquals(2, events.size()); BacklogTracerEventMessage event1 = events.get(0); assertEquals("foo", event1.getToNode()); assertEquals(" <message exchangeId=\"" + exchanges.get(0).getExchangeId() + "\">\n" + " <body type=\"java.lang.String\">Hello World</body>\n" + " </message>", event1.getMessageAsXml()); BacklogTracerEventMessage event2 = events.get(1); assertEquals("foo", event2.getToNode()); assertEquals(" <message exchangeId=\"" + exchanges.get(1).getExchangeId() + "\">\n" + " <body type=\"java.lang.String\">Bye World</body>\n" + " </message>", event2.getMessageAsXml()); } public void testBacklogTracerEventMessageAsXml() throws Exception { MBeanServer mbeanServer = getMBeanServer(); ObjectName on = new ObjectName("org.apache.camel:context=camel-1,type=tracer,name=BacklogTracer"); assertNotNull(on); mbeanServer.isRegistered(on); Boolean enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled"); assertEquals("Should not be enabled", Boolean.FALSE, enabled); Integer size = (Integer) mbeanServer.getAttribute(on, "BacklogSize"); assertEquals("Should be 1000", 1000, size.intValue()); // enable it mbeanServer.setAttribute(on, new Attribute("Enabled", Boolean.TRUE)); getMockEndpoint("mock:foo").expectedMessageCount(2); getMockEndpoint("mock:bar").expectedMessageCount(2); template.sendBody("direct:start", "Hello World"); template.sendBody("direct:start", "Bye World"); assertMockEndpointsSatisfied(); String events = (String) mbeanServer.invoke(on, "dumpTracedMessagesAsXml", new Object[]{"foo"}, new String[]{"java.lang.String"}); assertNotNull(events); log.info(events); // should be valid XML Document dom = context.getTypeConverter().convertTo(Document.class, events); assertNotNull(dom); NodeList list = dom.getElementsByTagName("backlogTracerEventMessage"); assertEquals(2, list.getLength()); } @SuppressWarnings("unchecked") public void testBacklogTracerEventMessageDumpAll() throws Exception { MBeanServer mbeanServer = getMBeanServer(); ObjectName on = new ObjectName("org.apache.camel:context=camel-1,type=tracer,name=BacklogTracer"); assertNotNull(on); mbeanServer.isRegistered(on); Boolean enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled"); assertEquals("Should not be enabled", Boolean.FALSE, enabled); // enable it mbeanServer.setAttribute(on, new Attribute("Enabled", Boolean.TRUE)); getMockEndpoint("mock:foo").expectedMessageCount(2); getMockEndpoint("mock:bar").expectedMessageCount(2); template.sendBody("direct:start", "Hello World"); template.sendBody("direct:start", "Bye World"); assertMockEndpointsSatisfied(); List<Exchange> fooExchanges = getMockEndpoint("mock:foo").getReceivedExchanges(); List<Exchange> barExchanges = getMockEndpoint("mock:bar").getReceivedExchanges(); List<BacklogTracerEventMessage> events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpAllTracedMessages", null, null); assertNotNull(events); assertEquals(6, events.size()); BacklogTracerEventMessage event0 = events.get(0); assertEquals("route1", event0.getRouteId()); assertEquals(null, event0.getToNode()); assertEquals(" <message exchangeId=\"" + fooExchanges.get(0).getExchangeId() + "\">\n" + " <body type=\"java.lang.String\">Hello World</body>\n" + " </message>", event0.getMessageAsXml()); BacklogTracerEventMessage event1 = events.get(1); assertEquals("route1", event1.getRouteId()); assertEquals("foo", event1.getToNode()); assertEquals(" <message exchangeId=\"" + fooExchanges.get(0).getExchangeId() + "\">\n" + " <body type=\"java.lang.String\">Hello World</body>\n" + " </message>", event1.getMessageAsXml()); BacklogTracerEventMessage event2 = events.get(2); assertEquals("route1", event2.getRouteId()); assertEquals("bar", event2.getToNode()); assertEquals(" <message exchangeId=\"" + barExchanges.get(0).getExchangeId() + "\">\n" + " <body type=\"java.lang.String\">Hello World</body>\n" + " </message>", event2.getMessageAsXml()); BacklogTracerEventMessage event3 = events.get(3); assertEquals("route1", event3.getRouteId()); assertEquals(null, event3.getToNode()); assertEquals(" <message exchangeId=\"" + fooExchanges.get(1).getExchangeId() + "\">\n" + " <body type=\"java.lang.String\">Bye World</body>\n" + " </message>", event3.getMessageAsXml()); BacklogTracerEventMessage event4 = events.get(4); assertEquals("route1", event4.getRouteId()); assertEquals("foo", event4.getToNode()); assertEquals(" <message exchangeId=\"" + fooExchanges.get(1).getExchangeId() + "\">\n" + " <body type=\"java.lang.String\">Bye World</body>\n" + " </message>", event3.getMessageAsXml()); BacklogTracerEventMessage event5 = events.get(5); assertEquals("route1", event5.getRouteId()); assertEquals("bar", event5.getToNode()); assertEquals(" <message exchangeId=\"" + barExchanges.get(1).getExchangeId() + "\">\n" + " <body type=\"java.lang.String\">Bye World</body>\n" + " </message>", event4.getMessageAsXml()); } public void testBacklogTracerEventMessageDumpAllAsXml() throws Exception { MBeanServer mbeanServer = getMBeanServer(); ObjectName on = new ObjectName("org.apache.camel:context=camel-1,type=tracer,name=BacklogTracer"); assertNotNull(on); mbeanServer.isRegistered(on); Boolean enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled"); assertEquals("Should not be enabled", Boolean.FALSE, enabled); // enable it mbeanServer.setAttribute(on, new Attribute("Enabled", Boolean.TRUE)); getMockEndpoint("mock:foo").expectedMessageCount(2); getMockEndpoint("mock:bar").expectedMessageCount(2); template.sendBody("direct:start", "Hello World"); template.sendBody("direct:start", "Bye World"); assertMockEndpointsSatisfied(); String events = (String) mbeanServer.invoke(on, "dumpAllTracedMessagesAsXml", null, null); assertNotNull(events); log.info(events); // should be valid XML Document dom = context.getTypeConverter().convertTo(Document.class, events); assertNotNull(dom); NodeList list = dom.getElementsByTagName("backlogTracerEventMessage"); assertEquals(6, list.getLength()); } @SuppressWarnings("unchecked") public void testBacklogTracerNotRemoveOnDump() throws Exception { MBeanServer mbeanServer = getMBeanServer(); ObjectName on = new ObjectName("org.apache.camel:context=camel-1,type=tracer,name=BacklogTracer"); assertNotNull(on); mbeanServer.isRegistered(on); Boolean removeOnDump = (Boolean) mbeanServer.getAttribute(on, "RemoveOnDump"); assertEquals(Boolean.TRUE, removeOnDump); // disable it mbeanServer.setAttribute(on, new Attribute("RemoveOnDump", Boolean.FALSE)); Boolean enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled"); assertEquals("Should not be enabled", Boolean.FALSE, enabled); // enable it mbeanServer.setAttribute(on, new Attribute("Enabled", Boolean.TRUE)); getMockEndpoint("mock:foo").expectedMessageCount(2); getMockEndpoint("mock:bar").expectedMessageCount(2); template.sendBody("direct:start", "Hello World"); template.sendBody("direct:start", "Bye World"); assertMockEndpointsSatisfied(); List<BacklogTracerEventMessage> events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpAllTracedMessages", null, null); assertNotNull(events); assertEquals(6, events.size()); // and if we get again they are still there events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpAllTracedMessages", null, null); assertNotNull(events); assertEquals(6, events.size()); // send in another message resetMocks(); getMockEndpoint("mock:foo").expectedMessageCount(1); getMockEndpoint("mock:bar").expectedMessageCount(1); template.sendBody("direct:start", "Hi World"); assertMockEndpointsSatisfied(); // and now we should have 3 more messages events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpAllTracedMessages", null, null); assertNotNull(events); assertEquals(9, events.size()); } @SuppressWarnings("unchecked") public void testBacklogTracerNotRemoveOnDumpPattern() throws Exception { MBeanServer mbeanServer = getMBeanServer(); ObjectName on = new ObjectName("org.apache.camel:context=camel-1,type=tracer,name=BacklogTracer"); assertNotNull(on); mbeanServer.isRegistered(on); Boolean removeOnDump = (Boolean) mbeanServer.getAttribute(on, "RemoveOnDump"); assertEquals(Boolean.TRUE, removeOnDump); // disable it mbeanServer.setAttribute(on, new Attribute("RemoveOnDump", Boolean.FALSE)); Boolean enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled"); assertEquals("Should not be enabled", Boolean.FALSE, enabled); // enable it mbeanServer.setAttribute(on, new Attribute("Enabled", Boolean.TRUE)); getMockEndpoint("mock:foo").expectedMessageCount(2); getMockEndpoint("mock:bar").expectedMessageCount(2); template.sendBody("direct:start", "Hello World"); template.sendBody("direct:start", "Bye World"); assertMockEndpointsSatisfied(); List<BacklogTracerEventMessage> events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpTracedMessages", new Object[]{"foo"}, new String[]{"java.lang.String"}); assertNotNull(events); assertEquals(2, events.size()); // and if we get again they are still there events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpTracedMessages", new Object[]{"foo"}, new String[]{"java.lang.String"}); assertEquals(2, events.size()); // send in another message resetMocks(); getMockEndpoint("mock:foo").expectedMessageCount(1); getMockEndpoint("mock:bar").expectedMessageCount(1); template.sendBody("direct:start", "Hi World"); assertMockEndpointsSatisfied(); // and now we should have 3 more messages events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpTracedMessages", new Object[]{"foo"}, new String[]{"java.lang.String"}); assertNotNull(events); assertEquals(3, events.size()); // and bar should also have 3 traced messages events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpTracedMessages", new Object[]{"bar"}, new String[]{"java.lang.String"}); assertNotNull(events); assertEquals(3, events.size()); } @SuppressWarnings("unchecked") public void testBacklogTracerNotRemoveOverflow() throws Exception { MBeanServer mbeanServer = getMBeanServer(); ObjectName on = new ObjectName("org.apache.camel:context=camel-1,type=tracer,name=BacklogTracer"); assertNotNull(on); mbeanServer.isRegistered(on); Boolean removeOnDump = (Boolean) mbeanServer.getAttribute(on, "RemoveOnDump"); assertEquals(Boolean.TRUE, removeOnDump); // disable it mbeanServer.setAttribute(on, new Attribute("RemoveOnDump", Boolean.FALSE)); Integer size = (Integer) mbeanServer.getAttribute(on, "BacklogSize"); assertEquals("Should be 1000", 1000, size.intValue()); // change size to 2 x 10 (as we need for first as well) mbeanServer.setAttribute(on, new Attribute("BacklogSize", 20)); // set the pattern to match only foo mbeanServer.setAttribute(on, new Attribute("TracePattern", "foo")); Boolean enabled = (Boolean) mbeanServer.getAttribute(on, "Enabled"); assertEquals("Should not be enabled", Boolean.FALSE, enabled); // enable it mbeanServer.setAttribute(on, new Attribute("Enabled", Boolean.TRUE)); getMockEndpoint("mock:foo").expectedMessageCount(10); getMockEndpoint("mock:bar").expectedMessageCount(10); for (int i = 0; i < 10; i++) { template.sendBody("direct:start", "###" + i + "###"); } assertMockEndpointsSatisfied(); List<BacklogTracerEventMessage> events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpTracedMessages", new Object[]{"foo"}, new String[]{"java.lang.String"}); assertEquals(10, events.size()); // the first should be 0 and the last 9 String xml = events.get(0).getMessageAsXml(); assertTrue(xml.contains("###0###")); xml = events.get(9).getMessageAsXml(); assertTrue(xml.contains("###9###")); // send in another message template.sendBody("direct:start", "###" + 10 + "###"); events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpTracedMessages", new Object[]{"foo"}, new String[]{"java.lang.String"}); assertEquals(10, events.size()); // and we are shifted one now xml = events.get(0).getMessageAsXml(); assertTrue(xml.contains("###1###")); xml = events.get(9).getMessageAsXml(); assertTrue(xml.contains("###10###")); // send in 4 messages template.sendBody("direct:start", "###" + 11 + "###"); template.sendBody("direct:start", "###" + 12 + "###"); template.sendBody("direct:start", "###" + 13 + "###"); template.sendBody("direct:start", "###" + 14 + "###"); events = (List<BacklogTracerEventMessage>) mbeanServer.invoke(on, "dumpTracedMessages", new Object[]{"foo"}, new String[]{"java.lang.String"}); assertEquals(10, events.size()); // and we are shifted +4 now xml = events.get(0).getMessageAsXml(); assertTrue(xml.contains("###5###")); xml = events.get(9).getMessageAsXml(); assertTrue(xml.contains("###14###")); } @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { context.setUseBreadcrumb(false); from("direct:start") .to("mock:foo").id("foo") .to("mock:bar").id("bar"); } }; } }