alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Groovy example source code file (JmxBuilderModelMBean.java)

This example Groovy source code file (JmxBuilderModelMBean.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Groovy tags/keywords

attributechangedlistener, attributechangedlistener, closure, jmxbuilderexception, jmxbuildermodelmbean, management, map, map, mbeanexception, notificationfiltersupport, object, object, runtimeoperationsexception, string, string, util

The Groovy JmxBuilderModelMBean.java source code

/*
 * Copyright 2008 the original author or authors.
 *
 * Licensed 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 groovy.jmx.builder;

import groovy.lang.Closure;

import javax.management.*;
import javax.management.modelmbean.InvalidTargetObjectTypeException;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.RequiredModelMBean;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

/**
 * The JmxBuilderModelMBean is the MBean class that proxies exported POGO/POJO inside the MBeanServer.
 * When JmxBuilder exports an object instance, an instance of this class is created and exported inside the
 * MBeanServer.
 *
 * @author Vladimir Vivien
 */
public class JmxBuilderModelMBean extends RequiredModelMBean implements NotificationListener {
    private List<String> methodListeners = new ArrayList(0);
    private Object managedObject;

    public JmxBuilderModelMBean(Object objectRef) throws MBeanException, RuntimeOperationsException, InstanceNotFoundException, InvalidTargetObjectTypeException {
        super.setManagedResource(objectRef, "ObjectReference");
    }

    public JmxBuilderModelMBean() throws MBeanException, RuntimeOperationsException {
        super();
    }

    public JmxBuilderModelMBean(ModelMBeanInfo mbi) throws MBeanException, RuntimeOperationsException {
        super(mbi);
    }

    public synchronized void setManagedResource(Object obj) {
        managedObject = obj;
        try {
            super.setManagedResource(obj, "ObjectReference");
        } catch (Exception ex) {
            throw new JmxBuilderException(ex);
        }
    }

    /**
     * Registers listeners for operation calls (i.e. method, getter, and setter calls) when
     * invoked on this bean from the MBeanServer.  Descriptor should contain a map with layout
     * item -> [Map[methodListener:[target:"", tpe:"", callback:&Closure], ... ,]]
     *
     * @param descriptor MetaMap descriptor containing description of operation call listeners
     */
    public void addOperationCallListeners(Map<String, Map> descriptor) {
        if (descriptor == null) return;
        for (Map.Entry<String, Map> item : descriptor.entrySet()) {
            // set up method listeners (such as attributeListener and Operation Listeners)
            // item -> [Map[methodListener:[target:"", tpe:"", callback:&Closure], ... ,]]
            if (item.getValue().containsKey("methodListener")) {
                Map listener = (Map) item.getValue().get("methodListener");
                String target = (String) listener.get("target");
                methodListeners.add(target);
                String listenerType = (String) listener.get("type");
                listener.put("managedObject", this.managedObject);
                // register an attribute change notification listener with model mbean
                if (listenerType.equals("attributeChangeListener")) {
                    try {
                        this.addAttributeChangeNotificationListener(
                                AttributeChangedListener.getListener(), (String) listener.get("attribute"), listener
                        );
                    } catch (MBeanException e) {
                        throw new JmxBuilderException(e);
                    }
                }
                if (listenerType.equals("operationCallListener")) {
                    String eventType = "jmx.operation.call." + target;
                    NotificationFilterSupport filter = new NotificationFilterSupport();
                    filter.enableType(eventType);
                    this.addNotificationListener(JmxEventListener.getListener(), filter, listener);
                }
            }
        }
    }

    /**
     * Sets up event listeners for this MBean as described in the descriptor.
     * The descriptor contains a map with layout {item -> Map[event:"...", from:ObjectName, callback:&Closure],...,}
     *
     * @param server     the MBeanServer is to be registered.
     * @param descriptor a map containing info about the event
     */
    public void addEventListeners(MBeanServer server, Map<String, Map> descriptor) {
        for (Map.Entry<String, Map> item : descriptor.entrySet()) {
            Map<String, Object> listener = item.getValue();

            // register with server
            ObjectName broadcaster = (ObjectName) listener.get("from");
            try {
                String eventType = (String) listener.get("event");

                if (eventType != null) {
                    NotificationFilterSupport filter = new NotificationFilterSupport();
                    filter.enableType(eventType);
                    server.addNotificationListener(broadcaster, JmxEventListener.getListener(), filter, listener);
                } else {
                    server.addNotificationListener(broadcaster, JmxEventListener.getListener(), null, listener);
                }
            } catch (InstanceNotFoundException e) {
                throw new JmxBuilderException(e);
            }
        }
    }

    @Override
    public Object invoke(String opName, Object[] opArgs, String[] signature) throws MBeanException, ReflectionException {
        Object result = super.invoke(opName, opArgs, signature);
        if (methodListeners.contains(opName)) {
            this.sendNotification(buildCallListenerNotification(opName));
        }
        return result;
    }

    public void handleNotification(Notification note, Object handback) {
        //System.out.println("Received note!");
    }

    private Notification buildCallListenerNotification(String target) {
        return new Notification(
                "jmx.operation.call." + target,
                this,
                NumberSequencer.getNextSequence(),
                System.currentTimeMillis()
        );
    }


    private static class NumberSequencer {
        private static AtomicLong num;

        static {
            num = new AtomicLong(0);
        }

        public static long getNextSequence() {
            return num.incrementAndGet();
        }
    }

    /**
     * Internal class AttributeChangedListener provides hooks to handle attribute-change events
     * that occurs on registered MBeans.
     *
     * @author Vladimir Vivien
     * @see groovy.jmx.builder.JmxBuilderModelMBean
     */
    private static final class AttributeChangedListener implements NotificationListener {
        private static AttributeChangedListener listener;

        /**
         * Returns an instance of the AttributeChangedListener.
         *
         * @return
         */
        public static synchronized AttributeChangedListener getListener() {
            if (listener == null) {
                listener = new AttributeChangedListener();
            }
            return listener;
        }

        private AttributeChangedListener() {
        }

        public void handleNotification(Notification notification, Object handback) {
            AttributeChangeNotification note = (AttributeChangeNotification) notification;
            Map event = (Map) handback;
            if (event != null) {
                Object del = event.get("managedObject");
                Object callback = event.get("callback");
                if (callback != null && callback instanceof Closure) {
                    Closure closure = (Closure) callback;
                    closure.setDelegate(del);
                    if (closure.getMaximumNumberOfParameters() == 1)
                        closure.call(buildAttributeNotificationPacket(note));
                    else closure.call();
                }
            }
        }

        private static Map buildAttributeNotificationPacket(AttributeChangeNotification note) {
            Map<String, Object> result = new HashMap();
            result.put("oldValue", note.getOldValue());
            result.put("newValue", note.getNewValue());
            result.put("attribute", note.getAttributeName());
            result.put("attributeType", note.getAttributeType());
            result.put("sequenceNumber", note.getSequenceNumber());
            result.put("timeStamp", note.getTimeStamp());
            return result;
        }
    }
}

Other Groovy examples (source code examples)

Here is a short list of links related to this Groovy JmxBuilderModelMBean.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.