All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.camel.component.jmx.JMXEndpoint Maven / Gradle / Ivy

There is a newer version: 4.8.0
Show newest version
/*
 * 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.component.jmx;

import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.ExecutorService;

import javax.management.MalformedObjectNameException;
import javax.management.NotificationFilter;
import javax.management.ObjectName;

import org.apache.camel.Consumer;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.spi.UriParam;
import org.apache.camel.spi.UriPath;
import org.apache.camel.support.DefaultEndpoint;
import org.apache.camel.util.ObjectHelper;

/**
 * The jmx component allows to receive JMX notifications.
 *
 * Endpoint that describes a connection to an mbean.
 * 

* The component can connect to the local platform mbean server with the following URI: *

* jmx://platform?options *

* A remote mbean server url can be provided following the initial JMX scheme like so: *

* jmx:service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi?options *

* You can append query options to the URI in the following format, ?options=value&option2=value&... */ @UriEndpoint(firstVersion = "2.6.0", scheme = "jmx", title = "JMX", syntax = "jmx:serverURL", consumerOnly = true, label = "monitoring") public class JMXEndpoint extends DefaultEndpoint { // error messages as constants so they can be asserted on from unit tests protected static final String ERR_PLATFORM_SERVER = "Monitor type consumer only supported on platform server."; protected static final String ERR_THRESHOLD_LOW = "ThresholdLow must be set when monitoring a gauge attribute."; protected static final String ERR_THRESHOLD_HIGH = "ThresholdHigh must be set when monitoring a gauge attribute."; protected static final String ERR_GAUGE_NOTIFY = "One or both of NotifyHigh and NotifyLow must be true when monitoring a gauge attribute."; protected static final String ERR_STRING_NOTIFY = "One or both of NotifyDiffer and NotifyMatch must be true when monitoring a string attribute."; protected static final String ERR_STRING_TO_COMPARE = "StringToCompare must be specified when monitoring a string attribute."; protected static final String ERR_OBSERVED_ATTRIBUTE = "Observed attribute must be specified"; /** * Server url comes from the remaining endpoint. Use platform to connect to local JVM. */ @UriPath private String serverURL; /** * The domain for the mbean you're connecting to */ @UriParam @Metadata(required = true) private String objectDomain; /** * The name key for the mbean you're connecting to. This value is mutually exclusive with the object properties that get passed. */ @UriParam private String objectName; /** * The attribute to observe for the monitor bean or consumer. */ @UriParam private String observedAttribute; /** * The frequency to poll the bean to check the monitor (monitor types only). */ @UriParam(defaultValue = "10000") private long granularityPeriod = 10000; /** * The type of monitor to create. One of string, gauge, counter (monitor types only). */ @UriParam(enums = "counter,gauge,string") private String monitorType; /** * Initial threshold for the monitor. The value must exceed this before notifications are fired (counter monitor only). */ @UriParam(label = "counter") private int initThreshold; /** * The amount to increment the threshold after it's been exceeded (counter monitor only). */ @UriParam(label = "counter") private int offset; /** * The value at which the counter is reset to zero (counter monitor only). */ @UriParam(label = "counter") private int modulus; /** * If true, then the value reported in the notification is the difference from the threshold as opposed to the value itself (counter and gauge monitor only). */ @UriParam(label = "counter,gauge") private boolean differenceMode; /** * If true, the gauge will fire a notification when the high threshold is exceeded (gauge monitor only). */ @UriParam(label = "gauge") private boolean notifyHigh; /** * If true, the gauge will fire a notification when the low threshold is exceeded (gauge monitor only). */ @UriParam(label = "gauge") private boolean notifyLow; /** * Value for the gauge's high threshold (gauge monitor only). */ @UriParam(label = "gauge") private Double thresholdHigh; /** * Value for the gauge's low threshold (gauge monitor only). */ @UriParam(label = "gauge") private Double thresholdLow; /** * If true, will fire a notification when the string attribute differs from the string to compare (string monitor or consumer). * By default the consumer will notify match if observed attribute and string to compare has been configured. */ @UriParam(label = "consumer,string") private boolean notifyDiffer; /** * If true, will fire a notification when the string attribute matches the string to compare (string monitor or consumer). * By default the consumer will notify match if observed attribute and string to compare has been configured. */ @UriParam(label = "consumer,string") private boolean notifyMatch; /** * Value for attribute to compare (string monitor or consumer). * By default the consumer will notify match if observed attribute and string to compare has been configured. */ @UriParam(label = "consumer,string") private String stringToCompare; /** * Format for the message body. Either "xml" or "raw". If xml, the notification is serialized to xml. If raw, then the raw java object is set as the body. */ @UriParam(defaultValue = "xml", enums = "xml,raw") private String format = "xml"; /** * Credentials for making a remote connection */ @UriParam(label = "security", secret = true) private String user; /** * Credentials for making a remote connection */ @UriParam(label = "security", secret = true) private String password; /** * Reference to a bean that implements the NotificationFilter. */ @UriParam(label = "advanced") private NotificationFilter notificationFilter; /** * Value to handback to the listener when a notification is received. This value will be put in the message header with the key "jmx.handback" */ @UriParam(label = "advanced") private Object handback; /** * If true the consumer will throw an exception if unable to establish the JMX connection upon startup. If false, the consumer will attempt * to establish the JMX connection every 'x' seconds until the connection is made -- where 'x' is the configured reconnectionDelay */ @UriParam(label = "advanced", defaultValue = "true") private boolean testConnectionOnStartup = true; /** * If true the consumer will attempt to reconnect to the JMX server when any connection failure occurs. The consumer will attempt * to re-establish the JMX connection every 'x' seconds until the connection is made-- where 'x' is the configured reconnectionDelay */ @UriParam(label = "advanced") private boolean reconnectOnConnectionFailure; /** * The number of seconds to wait before attempting to retry establishment of the initial connection or attempt to reconnect a lost connection */ @UriParam(label = "advanced", defaultValue = "10") private int reconnectDelay = 10; /** * Properties for the object name. These values will be used if the objectName param is not set */ @UriParam(label = "advanced", prefix = "key.", multiValue = true) private Map objectProperties; /** * To use a custom shared thread pool for the consumers. By default each consume has their own thread-pool to process and route notifications. */ @UriParam(label = "advanced") private ExecutorService executorService; /** * Cached object name that was built from the objectName param or the hashtable */ private transient ObjectName jmxObjectName; public JMXEndpoint(String aEndpointUri, JMXComponent aComponent) { super(aEndpointUri, aComponent); } @Override public Consumer createConsumer(Processor aProcessor) throws Exception { // validate that all of the endpoint is configured properly if (getMonitorType() != null) { if (!isPlatformServer()) { throw new IllegalArgumentException(ERR_PLATFORM_SERVER); } if (ObjectHelper.isEmpty(getObservedAttribute())) { throw new IllegalArgumentException(ERR_OBSERVED_ATTRIBUTE); } if (getMonitorType().equals("string")) { if (ObjectHelper.isEmpty(getStringToCompare())) { throw new IllegalArgumentException(ERR_STRING_TO_COMPARE); } if (!isNotifyDiffer() && !isNotifyMatch()) { throw new IllegalArgumentException(ERR_STRING_NOTIFY); } } else if (getMonitorType().equals("gauge")) { if (!isNotifyHigh() && !isNotifyLow()) { throw new IllegalArgumentException(ERR_GAUGE_NOTIFY); } if (getThresholdHigh() == null) { throw new IllegalArgumentException(ERR_THRESHOLD_HIGH); } if (getThresholdLow() == null) { throw new IllegalArgumentException(ERR_THRESHOLD_LOW); } } JMXMonitorConsumer answer = new JMXMonitorConsumer(this, aProcessor); configureConsumer(answer); return answer; } else { // shouldn't need any other validation. JMXConsumer answer = new JMXConsumer(this, aProcessor); configureConsumer(answer); return answer; } } @Override public Producer createProducer() throws Exception { throw new UnsupportedOperationException("producing JMX notifications is not supported"); } public String getFormat() { return format; } public void setFormat(String aFormat) { format = aFormat; } public boolean isXML() { return "xml".equals(getFormat()); } public boolean isPlatformServer() { return "platform".equals(getServerURL()); } public String getUser() { return user; } public void setUser(String aUser) { user = aUser; } public String getPassword() { return password; } public void setPassword(String aPassword) { password = aPassword; } public String getObjectDomain() { return objectDomain; } public void setObjectDomain(String aObjectDomain) { objectDomain = aObjectDomain; } public String getObjectName() { return objectName; } public void setObjectName(String aObjectName) { if (getObjectProperties() != null) { throw new IllegalArgumentException("Cannot set both objectName and objectProperties"); } objectName = aObjectName; } protected String getServerURL() { return serverURL; } protected void setServerURL(String aServerURL) { serverURL = aServerURL; } public NotificationFilter getNotificationFilter() { return notificationFilter; } public void setNotificationFilter(NotificationFilter aFilterRef) { notificationFilter = aFilterRef; } public Object getHandback() { return handback; } public void setHandback(Object aHandback) { handback = aHandback; } public Map getObjectProperties() { return objectProperties; } /** * Setter for the ObjectProperties is either called by reflection when * processing the URI or manually by the component. *

* If the URI contained a value with a reference like "objectProperties=#myHashtable" * then the Hashtable will be set in place. *

* If there are extra properties that begin with "key." then the component will * create a Hashtable with these values after removing the "key." prefix. */ public void setObjectProperties(Map objectProperties) { if (getObjectName() != null) { throw new IllegalArgumentException("Cannot set both objectName and objectProperties"); } this.objectProperties = objectProperties; } protected ObjectName getJMXObjectName() throws MalformedObjectNameException { if (jmxObjectName == null) { ObjectName on = buildObjectName(); setJMXObjectName(on); } return jmxObjectName; } protected void setJMXObjectName(ObjectName aCachedObjectName) { jmxObjectName = aCachedObjectName; } public String getObservedAttribute() { return observedAttribute; } public void setObservedAttribute(String aObservedAttribute) { observedAttribute = aObservedAttribute; } public long getGranularityPeriod() { return granularityPeriod; } public void setGranularityPeriod(long aGranularityPeriod) { granularityPeriod = aGranularityPeriod; } public String getMonitorType() { return monitorType; } public void setMonitorType(String aMonitorType) { monitorType = aMonitorType; } public int getInitThreshold() { return initThreshold; } public void setInitThreshold(int aInitThreshold) { initThreshold = aInitThreshold; } public int getOffset() { return offset; } public void setOffset(int aOffset) { offset = aOffset; } public int getModulus() { return modulus; } public void setModulus(int aModulus) { modulus = aModulus; } public boolean isDifferenceMode() { return differenceMode; } public void setDifferenceMode(boolean aDifferenceMode) { differenceMode = aDifferenceMode; } public boolean isNotifyHigh() { return notifyHigh; } public void setNotifyHigh(boolean aNotifyHigh) { notifyHigh = aNotifyHigh; } public boolean isNotifyLow() { return notifyLow; } public void setNotifyLow(boolean aNotifyLow) { notifyLow = aNotifyLow; } public Double getThresholdHigh() { return thresholdHigh; } public void setThresholdHigh(Double aThresholdHigh) { thresholdHigh = aThresholdHigh; } public Double getThresholdLow() { return thresholdLow; } public void setThresholdLow(Double aThresholdLow) { thresholdLow = aThresholdLow; } public boolean isNotifyDiffer() { return notifyDiffer; } public void setNotifyDiffer(boolean aNotifyDiffer) { notifyDiffer = aNotifyDiffer; } public boolean isNotifyMatch() { return notifyMatch; } public void setNotifyMatch(boolean aNotifyMatch) { notifyMatch = aNotifyMatch; } public String getStringToCompare() { return stringToCompare; } public void setStringToCompare(String aStringToCompare) { stringToCompare = aStringToCompare; } public boolean isTestConnectionOnStartup() { return this.testConnectionOnStartup; } public void setTestConnectionOnStartup(boolean testConnectionOnStartup) { this.testConnectionOnStartup = testConnectionOnStartup; } public boolean isReconnectOnConnectionFailure() { return this.reconnectOnConnectionFailure; } public void setReconnectOnConnectionFailure(boolean reconnectOnConnectionFailure) { this.reconnectOnConnectionFailure = reconnectOnConnectionFailure; } public int getReconnectDelay() { return this.reconnectDelay; } public void setReconnectDelay(int reconnectDelay) { this.reconnectDelay = reconnectDelay; } public ExecutorService getExecutorService() { return executorService; } public void setExecutorService(ExecutorService executorService) { this.executorService = executorService; } private ObjectName buildObjectName() throws MalformedObjectNameException { ObjectName objectName; if (getObjectProperties() == null) { StringBuilder sb = new StringBuilder(getObjectDomain()).append(':').append("name=").append(getObjectName()); objectName = new ObjectName(sb.toString()); } else { Hashtable ht = new Hashtable<>(); ht.putAll(getObjectProperties()); objectName = new ObjectName(getObjectDomain(), ht); } return objectName; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy