Author: davsclaus Date: Mon Dec 6 08:02:24 2010 New Revision: 1042541 URL: http://svn.apache.org/viewvc?rev=1042541&view=rev Log: CAMEL-3279, CAMEL-3392: Improved JMX. Any processor used in the route DSL will be managed. Allow custom Processor to be ManagementAware and expose its own set of attributes/operations with Spring JMX annotations, and have those enlisted instead of the default ManagedProcessor mbean. Using node id for ObjectName for managed processor.
Added: camel/trunk/camel-core/src/main/java/org/apache/camel/management/JmxMBeanAssembler.java camel/trunk/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCustomProcessor.java camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedCustomProcessorTest.java Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementAgent.java camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementNamingStrategy.java camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessDefinition.java camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java camel/trunk/camel-core/src/test/java/org/apache/camel/builder/RouteBuilderTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/management/JmxInstrumentationCustomMBeanTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/management/JmxInstrumentationUsingDefaultsTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/management/MultiInstanceProcessorTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TraceInterceptorFactoryCreatesHandlerTest.java camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TraceInterceptorSubclassFactory.java camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java camel/trunk/examples/pom.xml Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementAgent.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementAgent.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementAgent.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementAgent.java Mon Dec 6 08:02:24 2010 @@ -32,9 +32,6 @@ import javax.management.MBeanServerFacto import javax.management.NotCompliantMBeanException; import javax.management.ObjectInstance; import javax.management.ObjectName; -import javax.management.modelmbean.InvalidTargetObjectTypeException; -import javax.management.modelmbean.ModelMBeanInfo; -import javax.management.modelmbean.RequiredModelMBean; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; @@ -46,8 +43,6 @@ import org.apache.camel.spi.ManagementAg import org.apache.camel.util.ObjectHelper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource; -import org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler; /** * Default implementation of the Camel JMX service agent @@ -65,7 +60,7 @@ public class DefaultManagementAgent exte private ExecutorService executorService; private MBeanServer server; private final Set<ObjectName> mbeansRegistered = new HashSet<ObjectName>(); - private MetadataMBeanInfoAssembler assembler; + private JmxMBeanAssembler assembler; private JMXConnectorServer cs; private Integer registryPort; @@ -216,15 +211,8 @@ public class DefaultManagementAgent exte registerMBeanWithServer(obj, name, forceRegistration); } catch (NotCompliantMBeanException e) { // If this is not a "normal" MBean, then try to deploy it using JMX annotations - ModelMBeanInfo mbi; - mbi = assembler.getMBeanInfo(obj, name.toString()); - RequiredModelMBean mbean = (RequiredModelMBean)server.instantiate(RequiredModelMBean.class.getName()); - mbean.setModelMBeanInfo(mbi); - try { - mbean.setManagedResource(obj, "ObjectReference"); - } catch (InvalidTargetObjectTypeException itotex) { - throw new JMException(itotex.getMessage()); - } + Object mbean = assembler.assemble(obj, name); + // and register the mbean registerMBeanWithServer(mbean, name, forceRegistration); } } @@ -245,8 +233,6 @@ public class DefaultManagementAgent exte protected void doStart() throws Exception { ObjectHelper.notNull(camelContext, "CamelContext"); - assembler = new MetadataMBeanInfoAssembler(); - assembler.setAttributeSource(new AnnotationJmxAttributeSource()); // create mbean server if is has not be injected. if (server == null) { @@ -254,6 +240,8 @@ public class DefaultManagementAgent exte createMBeanServer(); } + assembler = new JmxMBeanAssembler(server); + if (LOG.isDebugEnabled()) { LOG.debug("Starting JMX agent on server: " + getMBeanServer()); } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementLifecycleStrategy.java Mon Dec 6 08:02:24 2010 @@ -28,6 +28,7 @@ import javax.management.ObjectName; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; +import org.apache.camel.Channel; import org.apache.camel.Component; import org.apache.camel.Consumer; import org.apache.camel.Endpoint; @@ -48,6 +49,7 @@ import org.apache.camel.management.mbean import org.apache.camel.management.mbean.ManagedCamelContext; import org.apache.camel.management.mbean.ManagedComponent; import org.apache.camel.management.mbean.ManagedConsumer; +import org.apache.camel.management.mbean.ManagedCustomProcessor; import org.apache.camel.management.mbean.ManagedDelayer; import org.apache.camel.management.mbean.ManagedEndpoint; import org.apache.camel.management.mbean.ManagedErrorHandler; @@ -73,9 +75,12 @@ import org.apache.camel.model.PolicyDefi import org.apache.camel.model.ProcessorDefinition; import org.apache.camel.model.RouteDefinition; import org.apache.camel.processor.Delayer; +import org.apache.camel.processor.DelegateAsyncProcessor; +import org.apache.camel.processor.DelegateProcessor; import org.apache.camel.processor.ErrorHandler; import org.apache.camel.processor.SendProcessor; import org.apache.camel.processor.Throttler; +import org.apache.camel.processor.WrapProcessor; import org.apache.camel.processor.interceptor.Tracer; import org.apache.camel.spi.BrowsableEndpoint; import org.apache.camel.spi.CamelContextNameStrategy; @@ -84,6 +89,7 @@ import org.apache.camel.spi.LifecycleStr import org.apache.camel.spi.ManagementAware; import org.apache.camel.spi.ManagementStrategy; import org.apache.camel.spi.RouteContext; +import org.apache.camel.spi.UnitOfWork; import org.apache.camel.util.KeyValueHolder; import org.apache.camel.util.ObjectHelper; import org.apache.commons.logging.Log; @@ -371,6 +377,11 @@ public class DefaultManagementLifecycleS @SuppressWarnings("unchecked") private Object getManagedObjectForService(CamelContext context, Service service, Route route) { + // skip channel, UoW and dont double wrap instrumentation + if (service instanceof Channel || service instanceof UnitOfWork || service instanceof InstrumentationProcessor) { + return null; + } + ManagedService answer = null; if (service instanceof ManagementAware) { @@ -440,20 +451,46 @@ public class DefaultManagementLifecycleS return managedObject; } + @SuppressWarnings("unchecked") private Object createManagedObjectForProcessor(CamelContext context, Processor processor, ProcessorDefinition definition, Route route) { - // skip error handlers - if (processor instanceof ErrorHandler) { - return false; - } - ManagedProcessor answer = null; - if (processor instanceof Delayer) { - answer = new ManagedDelayer(context, (Delayer) processor, definition); - } else if (processor instanceof Throttler) { - answer = new ManagedThrottler(context, (Throttler) processor, definition); - } else if (processor instanceof SendProcessor) { - answer = new ManagedSendProcessor(context, (SendProcessor) processor, definition); + + // unwrap delegates as we want the real target processor + Processor target = processor; + while (target != null) { + + // skip error handlers + if (target instanceof ErrorHandler) { + return false; + } + + // look for specialized processor which we should prefer to use + if (target instanceof Delayer) { + answer = new ManagedDelayer(context, (Delayer) target, definition); + } else if (target instanceof Throttler) { + answer = new ManagedThrottler(context, (Throttler) target, definition); + } else if (target instanceof SendProcessor) { + answer = new ManagedSendProcessor(context, (SendProcessor) target, definition); + } else if (target instanceof ManagementAware) { + Object managedObject = ((ManagementAware) target).getManagedObject(processor); + answer = new ManagedCustomProcessor(context, managedObject, target, definition); + } + + if (answer != null) { + // break out as we found an answer + break; + } + + // no answer yet, so unwrap any delegates and try again + if (target instanceof DelegateProcessor) { + target = ((DelegateProcessor) target).getProcessor(); + } else if (target instanceof DelegateAsyncProcessor) { + target = ((DelegateAsyncProcessor) target).getProcessor(); + } else { + // no delegate so we dont have any target to try next + target = null; + } } if (answer == null) { Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementNamingStrategy.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementNamingStrategy.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementNamingStrategy.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/DefaultManagementNamingStrategy.java Mon Dec 6 08:02:24 2010 @@ -119,17 +119,7 @@ public class DefaultManagementNamingStra buffer.append(domainName).append(":"); buffer.append(KEY_CONTEXT + "=").append(getContextId(context)).append(","); buffer.append(KEY_TYPE + "=").append(TYPE_PROCESSOR).append(","); - - if (definition.hasCustomIdAssigned()) { - // use id in name - String nodeId = definition.getId(); - buffer.append(KEY_NAME + "=").append(ObjectName.quote(nodeId)); - } else { - // create a name based on its instance - buffer.append(KEY_NAME + "=") - .append(processor.getClass().getSimpleName()) - .append("(").append(ObjectHelper.getIdentityHashCode(processor)).append(")"); - } + buffer.append(KEY_NAME + "=").append(ObjectName.quote(definition.getId())); return createObjectName(buffer); } Added: camel/trunk/camel-core/src/main/java/org/apache/camel/management/JmxMBeanAssembler.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/JmxMBeanAssembler.java?rev=1042541&view=auto ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/management/JmxMBeanAssembler.java (added) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/JmxMBeanAssembler.java Mon Dec 6 08:02:24 2010 @@ -0,0 +1,73 @@ +/** + * 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 javax.management.JMException; +import javax.management.MBeanServer; +import javax.management.ObjectName; +import javax.management.modelmbean.InvalidTargetObjectTypeException; +import javax.management.modelmbean.ModelMBeanInfo; +import javax.management.modelmbean.RequiredModelMBean; + +import org.apache.camel.management.mbean.ManagedCustomProcessor; +import org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource; +import org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler; + +/** + * An assembler to assemble a {...@link javax.management.modelmbean.RequiredModelMBean} which can be used + * to register the object in JMX. The assembler is capable of using the Spring JMX annotations to + * gather the list of JMX operations and attributes. + * + * @version $Revision$ + */ +public class JmxMBeanAssembler { + + private final MetadataMBeanInfoAssembler assembler; + private final MBeanServer server; + + public JmxMBeanAssembler(MBeanServer server) { + this.server = server; + this.assembler = new MetadataMBeanInfoAssembler(); + this.assembler.setAttributeSource(new AnnotationJmxAttributeSource()); + } + + public RequiredModelMBean assemble(Object obj, ObjectName name) throws JMException { + ModelMBeanInfo mbi; + + if (obj instanceof ManagedCustomProcessor) { + Object custom = ((ManagedCustomProcessor) obj).getManagedObject(); + // get the mbean info from the custom managed object + mbi = assembler.getMBeanInfo(custom, name.toString()); + // and let the custom object be registered in JMX + obj = custom; + } else { + mbi = assembler.getMBeanInfo(obj, name.toString()); + } + + RequiredModelMBean mbean = (RequiredModelMBean) server.instantiate(RequiredModelMBean.class.getName()); + mbean.setModelMBeanInfo(mbi); + + try { + mbean.setManagedResource(obj, "ObjectReference"); + } catch (InvalidTargetObjectTypeException itotex) { + throw new JMException(itotex.getMessage()); + } + + return mbean; + } + +} Added: camel/trunk/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCustomProcessor.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCustomProcessor.java?rev=1042541&view=auto ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCustomProcessor.java (added) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/management/mbean/ManagedCustomProcessor.java Mon Dec 6 08:02:24 2010 @@ -0,0 +1,42 @@ +/** + * 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.mbean; + +import org.apache.camel.CamelContext; +import org.apache.camel.Processor; +import org.apache.camel.model.ProcessorDefinition; + +/** + * A managed custom processor is a processor which implements the {...@link org.apache.camel.spi.ManagementAware} + * interface. + * + * @version $Revision$ + */ +public class ManagedCustomProcessor extends ManagedProcessor { + private final Object managedObject; + + public ManagedCustomProcessor(CamelContext context, Object managedObject, Processor processor, + ProcessorDefinition<?> definition) { + super(context, processor, definition); + this.managedObject = managedObject; + } + + public Object getManagedObject() { + return managedObject; + } + +} Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessDefinition.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessDefinition.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessDefinition.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/model/ProcessDefinition.java Mon Dec 6 08:02:24 2010 @@ -23,6 +23,8 @@ import javax.xml.bind.annotation.XmlRoot import javax.xml.bind.annotation.XmlTransient; import org.apache.camel.Processor; +import org.apache.camel.Service; +import org.apache.camel.processor.WrapProcessor; import org.apache.camel.spi.RouteContext; import org.apache.camel.util.ObjectHelper; @@ -84,6 +86,12 @@ public class ProcessDefinition extends O processor = routeContext.lookup(getRef(), Processor.class); ObjectHelper.notNull(processor, "registry entry called " + getRef(), this); } + + // ensure its wrapped in a Service so we can manage it from eg. JMX + // (a Processor must be a Service to be enlisted in JMX) + if (!(processor instanceof Service)) { + processor = new WrapProcessor(processor, processor); + } return processor; } } Modified: camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java (original) +++ camel/trunk/camel-core/src/main/java/org/apache/camel/util/IntrospectionSupport.java Mon Dec 6 08:02:24 2010 @@ -219,6 +219,16 @@ public final class IntrospectionSupport } } + public static Method getPropertySetter(Class<?> type, String propertyName) throws NoSuchMethodException { + String name = "set" + ObjectHelper.capitalize(propertyName); + for (Method method : type.getMethods()) { + if (isSetter(method) && method.getName().equals(name)) { + return method; + } + } + throw new NoSuchMethodException(type.getCanonicalName() + "." + name); + } + public static boolean isPropertyIsGetter(Class<?> type, String propertyName) { try { Method method = type.getMethod("is" + ObjectHelper.capitalize(propertyName)); Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/builder/RouteBuilderTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/builder/RouteBuilderTest.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/builder/RouteBuilderTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/builder/RouteBuilderTest.java Mon Dec 6 08:02:24 2010 @@ -194,10 +194,6 @@ public class RouteBuilderTest extends Te for (Route route : routes) { Endpoint key = route.getEndpoint(); assertEquals("From endpoint", "seda://a", key.getEndpointUri()); - EventDrivenConsumerRoute consumer = assertIsInstanceOf(EventDrivenConsumerRoute.class, route); - Channel channel = unwrapChannel(consumer.getProcessor()); - - assertEquals("Should be called with my processor", myProcessor, channel.getNextProcessor()); } } @@ -225,12 +221,6 @@ public class RouteBuilderTest extends Te for (Route route : routes) { Endpoint key = route.getEndpoint(); assertEquals("From endpoint", "seda://a", key.getEndpointUri()); - - EventDrivenConsumerRoute consumer = assertIsInstanceOf(EventDrivenConsumerRoute.class, route); - Channel channel = unwrapChannel(consumer.getProcessor()); - - FilterProcessor filterProcessor = assertIsInstanceOf(FilterProcessor.class, channel.getNextProcessor()); - assertEquals("Should be called with my processor", myProcessor, unwrapChannel(filterProcessor.getProcessor()).getNextProcessor()); } } Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/management/JmxInstrumentationCustomMBeanTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/management/JmxInstrumentationCustomMBeanTest.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/management/JmxInstrumentationCustomMBeanTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/management/JmxInstrumentationCustomMBeanTest.java Mon Dec 6 08:02:24 2010 @@ -100,7 +100,7 @@ public class JmxInstrumentationCustomMBe assertEquals("Could not find 1 context: " + s, 1, s.size()); s = CastUtils.cast(mbsc.queryNames(new ObjectName(domainName + ":type=processors,*"), null)); - assertEquals("Could not find 2 processors: " + s, 2, s.size()); + assertEquals("Could not find 1 processors: " + s, 1, s.size()); s = CastUtils.cast(mbsc.queryNames(new ObjectName(domainName + ":type=routes,*"), null)); assertEquals("Could not find 1 route: " + s, 1, s.size()); Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/management/JmxInstrumentationUsingDefaultsTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/management/JmxInstrumentationUsingDefaultsTest.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/management/JmxInstrumentationUsingDefaultsTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/management/JmxInstrumentationUsingDefaultsTest.java Mon Dec 6 08:02:24 2010 @@ -69,7 +69,7 @@ public class JmxInstrumentationUsingDefa assertEquals("Could not find 1 context: " + s, 1, s.size()); s = mbsc.queryNames(new ObjectName(domainName + ":type=processors,*"), null); - assertEquals("Could not find 2 processors: " + s, 2, s.size()); + assertEquals("Could not find 1 processors: " + s, 1, s.size()); s = mbsc.queryNames(new ObjectName(domainName + ":type=consumers,*"), null); assertEquals("Could not find 1 consumers: " + s, 1, s.size()); Added: camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedCustomProcessorTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedCustomProcessorTest.java?rev=1042541&view=auto ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedCustomProcessorTest.java (added) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/management/ManagedCustomProcessorTest.java Mon Dec 6 08:02:24 2010 @@ -0,0 +1,113 @@ +/** + * 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 javax.management.Attribute; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +import org.apache.camel.CamelContext; +import org.apache.camel.ContextTestSupport; +import org.apache.camel.Exchange; +import org.apache.camel.Processor; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.spi.ManagementAware; +import org.springframework.jmx.export.annotation.ManagedAttribute; +import org.springframework.jmx.export.annotation.ManagedResource; + +/** + * @version $Revision: 950375 $ + */ +public class ManagedCustomProcessorTest extends ContextTestSupport { + + @Override + protected boolean useJmx() { + return true; + } + + @Override + protected CamelContext createCamelContext() throws Exception { + CamelContext context = super.createCamelContext(); + DefaultManagementNamingStrategy naming = (DefaultManagementNamingStrategy) context.getManagementStrategy().getManagementNamingStrategy(); + naming.setHostName("localhost"); + naming.setDomainName("org.apache.camel"); + return context; + } + + public void testManageCustomProcessor() throws Exception { + MBeanServer mbeanServer = context.getManagementStrategy().getManagementAgent().getMBeanServer(); + ObjectName on = ObjectName.getInstance("org.apache.camel:context=localhost/camel-1,type=processors,name=\"custom\""); + + getMockEndpoint("mock:result").expectedMessageCount(1); + getMockEndpoint("mock:result").expectedHeaderReceived("foo", "hey"); + template.sendBody("direct:start", "Hello World"); + assertMockEndpointsSatisfied(); + + String foo = (String) mbeanServer.getAttribute(on, "Foo"); + assertEquals("hey", foo); + + // change foo + mbeanServer.setAttribute(on, new Attribute("Foo", "changed")); + + resetMocks(); + + getMockEndpoint("mock:result").expectedMessageCount(1); + getMockEndpoint("mock:result").expectedHeaderReceived("foo", "changed"); + template.sendBody("direct:start", "Bye World"); + assertMockEndpointsSatisfied(); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:start").routeId("foo") + .process(new MyCustomProcessor()).id("custom") + .to("mock:result"); + } + }; + } + + // START SNIPPET: e1 + @ManagedResource + public static class MyCustomProcessor implements ManagementAware<Processor>, Processor { + private String foo = "hey"; + + public Object getManagedObject(Processor object) { + // just return this as we use Spring JMX annotations to define which attributes/operations + // to be enlisted in JMX + return this; + } + + @ManagedAttribute + public String getFoo() { + return foo; + } + + @ManagedAttribute + public void setFoo(String foo) { + this.foo = foo; + } + + public void process(Exchange exchange) throws Exception { + exchange.getIn().setHeader("foo", getFoo()); + } + } + // END SNIPPET: e1 + +} Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/management/MultiInstanceProcessorTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/management/MultiInstanceProcessorTest.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/management/MultiInstanceProcessorTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/management/MultiInstanceProcessorTest.java Mon Dec 6 08:02:24 2010 @@ -66,7 +66,7 @@ public class MultiInstanceProcessorTest assertEquals("Could not find 1 context: " + s, 1, s.size()); s = mbsc.queryNames(new ObjectName(domainName + ":type=processors,*"), null); - assertEquals("Could not find 2 processor: " + s, 2, s.size()); + assertEquals("Could not find 3 processor: " + s, 3, s.size()); s = mbsc.queryNames(new ObjectName(domainName + ":type=routes,*"), null); assertEquals("Could not find 1 route: " + s, 1, s.size()); Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TraceInterceptorFactoryCreatesHandlerTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TraceInterceptorFactoryCreatesHandlerTest.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TraceInterceptorFactoryCreatesHandlerTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TraceInterceptorFactoryCreatesHandlerTest.java Mon Dec 6 08:02:24 2010 @@ -22,7 +22,9 @@ import java.util.List; import org.apache.camel.CamelContext; import org.apache.camel.Processor; import org.apache.camel.model.ProcessorDefinition; +import org.apache.camel.processor.DelegateAsyncProcessor; import org.apache.camel.processor.DelegateProcessor; +import org.apache.camel.processor.WrapProcessor; public class TraceInterceptorFactoryCreatesHandlerTest extends TracingTestBase { @@ -38,8 +40,11 @@ public class TraceInterceptorFactoryCrea public Processor createTraceInterceptor(ProcessorDefinition node, Processor target, TraceFormatter formatter, Tracer tracer) { TraceInterceptor interceptor = new TraceInterceptor(node, target, formatter, tracer); + if (target instanceof WrapProcessor) { + target = ((WrapProcessor) target).getProcessor(); + } while (target instanceof DelegateProcessor) { - target = ((org.apache.camel.management.InstrumentationProcessor) target).getProcessor(); + target = ((DelegateProcessor) target).getProcessor(); } if (traceAllNodes || !target.getClass().equals(TraceTestProcessor.class)) { TraceHandlerTestHandler traceHandler = new TraceHandlerTestHandler(eventMessages); Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TraceInterceptorSubclassFactory.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TraceInterceptorSubclassFactory.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TraceInterceptorSubclassFactory.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/processor/interceptor/TraceInterceptorSubclassFactory.java Mon Dec 6 08:02:24 2010 @@ -22,6 +22,7 @@ import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.model.ProcessorDefinition; import org.apache.camel.processor.DelegateProcessor; +import org.apache.camel.processor.WrapProcessor; public class TraceInterceptorSubclassFactory implements TraceInterceptorFactory { private List<StringBuilder> eventMessages; @@ -53,8 +54,11 @@ public class TraceInterceptorSubclassFac super(node, target, formatter, tracer); this.eventMessages = eventMessages; this.factory = factory; + if (target instanceof WrapProcessor) { + target = ((WrapProcessor) target).getProcessor(); + } while (target instanceof DelegateProcessor) { - target = ((org.apache.camel.management.InstrumentationProcessor) target).getProcessor(); + target = ((DelegateProcessor) target).getProcessor(); } if (target.getClass().equals(TraceTestProcessor.class)) { traceThisNode = false; Modified: camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java URL: http://svn.apache.org/viewvc/camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java (original) +++ camel/trunk/camel-core/src/test/java/org/apache/camel/util/IntrospectionSupportTest.java Mon Dec 6 08:02:24 2010 @@ -162,6 +162,16 @@ public class IntrospectionSupportTest ex assertEquals("Claus", name); } + public void testSetProperty() throws Exception { + ExampleBean bean = new ExampleBean(); + bean.setId("123"); + bean.setName("Claus"); + bean.setPrice(10.0); + + IntrospectionSupport.setProperty(bean, "name", "James"); + assertEquals("James", bean.getName()); + } + public void testAnotherGetProperty() throws Exception { AnotherExampleBean bean = new AnotherExampleBean(); bean.setName("Claus"); @@ -181,7 +191,7 @@ public class IntrospectionSupportTest ex assertEquals(Boolean.TRUE, IntrospectionSupport.getProperty(bean, "little")); } - public void testGetPropertyLocaleIndependend() throws Exception { + public void testGetPropertyLocaleIndependent() throws Exception { Locale oldLocale = Locale.getDefault(); Locale.setDefault(new Locale("tr", "TR")); @@ -210,6 +220,29 @@ public class IntrospectionSupportTest ex Method name = IntrospectionSupport.getPropertyGetter(ExampleBean.class, "name"); assertEquals("getName", name.getName()); + + try { + IntrospectionSupport.getPropertyGetter(ExampleBean.class, "xxx"); + fail("Should have thrown exception"); + } catch (NoSuchMethodException e) { + assertEquals("org.apache.camel.util.jndi.ExampleBean.getXxx()", e.getMessage()); + } + } + + public void testGetPropertySetter() throws Exception { + ExampleBean bean = new ExampleBean(); + bean.setName("Claus"); + bean.setPrice(10.0); + + Method name = IntrospectionSupport.getPropertySetter(ExampleBean.class, "name"); + assertEquals("setName", name.getName()); + + try { + IntrospectionSupport.getPropertySetter(ExampleBean.class, "xxx"); + fail("Should have thrown exception"); + } catch (NoSuchMethodException e) { + assertEquals("org.apache.camel.util.jndi.ExampleBean.setXxx", e.getMessage()); + } } public void testIsGetter() throws Exception { Modified: camel/trunk/examples/pom.xml URL: http://svn.apache.org/viewvc/camel/trunk/examples/pom.xml?rev=1042541&r1=1042540&r2=1042541&view=diff ============================================================================== --- camel/trunk/examples/pom.xml (original) +++ camel/trunk/examples/pom.xml Mon Dec 6 08:02:24 2010 @@ -77,14 +77,14 @@ <repositories> <repository> <id>dynamic.repo</id> - <name>Repository Dynamicly Added Via the Command Line</name> + <name>Repository Dynamically Added Via the Command Line</name> <url>$remoteRepo</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>dynamic.repo</id> - <name>Repository Dynamicly Added Via the Command Line</name> + <name>Repository Dynamically Added Via the Command Line</name> <url>$remoteRepo</url> </pluginRepository> </pluginRepositories>