Sreeni's Weblog

How to create pluggable container-monitoring element in GlassFish v3

Friday Sep 11, 2009

For new modules like JRuby which can be added at runtime, it is possible to use v3 monitoring config using pluggability as given in the sample code below.

import org.glassfish.internal.api.Init;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.component.PostConstruct;
import org.jvnet.hk2.annotations.Inject;
import org.glassfish.api.Startup;
import com.sun.enterprise.config.serverbeans.MonitoringService;
import org.jvnet.hk2.config.SingleConfigCode;
import org.jvnet.hk2.config.ConfigSupport;
import org.glassfish.api.monitoring.ContainerMonitoring;
import org.jvnet.hk2.config.TransactionFailure;
import java.beans.PropertyVetoException;

@Service
public class AddonInit implements PostConstruct {

    @Inject
    MonitoringService ms;

    public void postConstruct() {
        mprint("addon init postConstruct() ...");
        if (ms.getContainerMonitoring("jruby") == null) {
            try {
                ConfigSupport.apply(new SingleConfigCode<MonitoringService>() {
                    public Object run(MonitoringService param)
                    throws PropertyVetoException, TransactionFailure {
                        ContainerMonitoring newItem = param.createChild(ContainerMonitoring.class);
                        newItem.setName("jruby");
                        newItem.setLevel("HIGH");
                        param.getContainerMonitoring().add(newItem);
                        return newItem;
                    }
                }, ms);
            } catch (TransactionFailure tf) {
                // log warning
                // handle exception
            }
        }
    }

    private void mprint(String str) {
        if (debug) {
            System.out.println("... MSR: " + str);
        }
    }

    private final boolean debug = true;
}

[2] Comments
Like this post? del.icio.us | furl | slashdot | technorati | digg

How to enable/disable monitoring and attach btrace-agent in GlassFish v3

Wednesday Sep 09, 2009

The monitoring funcationality including attaching btrace-agent is done based on the 'monitoring-enabled' attribute of 'monitoring-service' element. If monitoring-enabled is true then the btrace-agent is attached as part of startup. When monitoring-enabled is false, btrace-agent is not attached at startup time. However when user changes monitoring-enabled to true while the server is running, it should be possible to attach the btrace-agent and start monitoring functionality.

Purpose of this pair of commands is to provide enable /disable monitoring during run time without having to restart the server (Alternatively user should be able to use asadmin set command to enbale/disable the monitoring-enabled flag, but have to restart the server to take effect). It does attach btrace-agent based on the given pid and optionally sets the monitoring level for given modules.

enable-monitoring

enable-monitoring [--mbean=false] [--dtrace*=true] [--level web-container="LOW":ejb-container="HIGH"] [--options="debug=true"] [--pid=<pid>]

  • enable-monitoring
    sets the attribute 'monitoring-enabled' to 'true'
  • enable-monitoring --mbean=true --dtrace*=false
    sets the attribute 'monitoring-enabled' to 'true', mbean-enabled to true and dtrace-enabled to false
  • enable-monitoring --options="debug=true" --pid=<pid>
    sets the attribute 'monitoring-enabled' to 'true' and attaches btrace agent using --options
  • enable-monitoring --level web-container="LOW":ejb="HIGH"
    sets the levels for given modules in addition to 'monitoring-enabled'
disable-monitoring

disable-monitoring --modules="web-container,ejb-container"

  • disable-monitoring
    sets the attribute 'monitoring-enabled' to 'false'
  • disable-monitoring --modules="web-container,ejb-container"
    this command will just set the levels for given modules to 'OFF' and it does not change the value for 'monitoring-enabled'

*- Available as a value-add feature, made available only to the paid customers.

Above also caters an important use case of adhoc monitoring, i.e. turning monitoring on in production while server is running, for ex. enable dtrace on the fly.

[0] Comments
Like this post? del.icio.us | furl | slashdot | technorati | digg

How to make Grizzly Comet work with Java Client instead of Web Client

Thursday Feb 19, 2009

comet_client There are many examples illustrating the usage of Grizzly Comet for Web Client but not for Stand alone java client. I needed one and with help from Jeanfrancois Arcand, users@grizzly.dev.java.net and my colleague Prashant Abbagani, I came up with the following example.

Conventionally the client either polls or pulls the message from server periodically, the draw back with this approach is that the client wastes the resources and the messages may not be received in real time. Instead, in comet approach, the server pushes the messages to client in real time. For this example, I have used GlassFish v3 which comes bundled with Grizzly and Comet. Here are the steps:

  • Download and install GlassFish v3.
     
  • Enable comet support in GlassFish v3.
            ...
            <http-listener port="8080" id="http-listener-1" address="0.0.0.0" default-virtual-server="server" server-name="">
              <property name="cometSupport" value="true" />
            <http-listener>
            ...
    
  • Develop and deploy comet.war to push messages from server to client. You may like to refer to MyCometServlet.java source code.
     
  • Code the client CometClient.java and listen for server messages.

    Start the client.

    punit[105]: java CometClient
    init ...
    
  • Simulate posting messages to server using Post2CometServlet.java.

    Post message to server

    punit[54]: java Post2CometServlet
    punit[55]: java Post2CometServlet
    punit[56]: java Post2CometServlet
    punit[57]: java Post2CometServlet
    punit[58]: java Post2CometServlet
    
    The client output gets updated in real time as the messages are posted to the servlet.
    punit[105]: java CometClient
    init ...my message sent at 1235082867986
    my message sent at 1235082891002
    my message sent at 1235082892018
    my message sent at 1235082893714
    my message sent at 1235082894420
    

[3] Comments
Like this post? del.icio.us | furl | slashdot | technorati | digg

Proxy pattern for exposing jsr77 api and internal api using common implementation

Wednesday Feb 18, 2009

GlassFish v3 is designed to be modular not only in architecture but in distribution as well. The distributions range from compact version 'Nucleus' to full blown version 'Enterprise' through 'Web', and 'PE' distributions.

We need to support jsr77 in Enterprise version so we'll need jsr77 interfaces to be available only in Enterprise version and not the lower versions like 'Web' and 'PE'. However we need to use jsr77 like monitoring data types for exposing monitoring data in 'Web' and 'PE' distributions. This poses a challenge of maintaining same data types but in two different packages. To avoid this maintenance hassle, we can use proxy pattern as described below.

Assume that we need to expose two interfaces with different package names but with same method signatures. Let us call them javax.management.j2ee.statistics.Statistic and org.glassfish.internal.api.Statistic. The corresponding implementations are javax.management.j2ee.statistics.JSR77StatisticImpl and org.glassfish.internal.api.IntStatisticImpl respectively. Recall that our idea of using proxy pattern is to avoid the maintenance hassle and for that we make JSR77StatisticImpl extend IntStatisticImpl and implement javax.management.j2ee.statistics.Statistic. This makes it reuse the common implementation.

Using dynamic proxy api, we can expose the required interface at runtime as shown below with working example.

  • Create glassfish internal Statistic interface under <stats_proxy_pattern>/internal-api
     
  • Create glassfish internal Statistic implementation IntStatisticImpl under <stats_proxy_pattern>/internal-api
     
  • Create jsr77 Statistic interface under <stats_proxy_pattern>/jsr77
     
  • Create jsr77 Statistic implementation JSR77StatisticImpl under <stats_proxy_pattern>/jsr77
     
  • Create StatsProxy under <stats_proxy_pattern>/monitor
     
  • First let us test the internal Statistic data type using the following code under <stats_proxy_pattern>.
    import org.glassfish.internal.api.*;
    import com.sun.enterprise.monitor.*;
    
    /**
     * Verify the stat types at runtime
     * @author Sreenivas Munnangi
     */
    
    public class TestStatInterface {
        public static void main (String args[]) {
            System.out.println("TestStatInterface");
            try {
                //interanl Statistic
                Statistic stat = (Statistic) StatsProxy.newInstance(new IntStatisticImpl());
                System.out.println("TestStatInterface: before calling method getName on proxy ...");
                System.out.println("TestStatInterface: stat.getName() = " + stat.getName());
                System.out.println("TestStatInterface: after calling method getName on proxy ...");
                System.out.println("TestStatInterface: before calling method getStartTime on proxy ...");
                System.out.println("TestStatInterface: stat.getStartTime() = " + stat.getStartTime());
                System.out.println("TestStatInterface: after calling method getStartTime on proxy ...");
            } catch (Exception e) {
                System.out.println("Caught exception ...");
                e.printStackTrace();
            }
        }
    }
    
    When we build and run the above code, we see the following output. 
    I have used build.xml from the attached example, 
    link is provided at the end of this blog.
    
    run:
         [java] TestStatInterface
         [java] TestStatInterface: before calling method getName on proxy ...
         [java] statsproxy before method getName
         [java] result = called getName() ...
         [java] statsproxy after method getName
    
         [java] TestStatInterface: stat.getName() = called getName() ...
         [java] TestStatInterface: after calling method getName on proxy ...
         [java] TestStatInterface: before calling method getStartTime on proxy ...
         [java] statsproxy before method getStartTime
         [java] result = 1234985924526
         [java] statsproxy after method getStartTime
         [java] TestStatInterface: stat.getStartTime() = 1234985924526
         [java] TestStatInterface: after calling method getStartTime on proxy ...
    
    BUILD SUCCESSFUL
    
  • Now test for jsr77 Statistic type. Notice the change in imports.
    import javax.management.j2ee.statistics.*;
    import com.sun.enterprise.monitor.*;
    
    /**
     * Verify the stat types at runtime
     * @author Sreenivas Munnangi
     */
    
    public class TestStatInterface {
        public static void main (String args[]) {
            System.out.println("TestStatInterface");
            try {
                //jsr77 Statistic
                Statistic stat = (Statistic) StatsProxy.newInstance(new JSR77StatisticImpl());
                System.out.println("TestStatInterface: before calling method getName on proxy ...");
                System.out.println("TestStatInterface: stat.getName() = " + stat.getName());
                System.out.println("TestStatInterface: after calling method getName on proxy ...");
                System.out.println("TestStatInterface: before calling method getStartTime on proxy ...");
                System.out.println("TestStatInterface: stat.getStartTime() = " + stat.getStartTime());
                System.out.println("TestStatInterface: after calling method getStartTime on proxy ...");
            } catch (Exception e) {
                System.out.println("Caught exception ...");
                e.printStackTrace();
            }
        }
    }
    
    Following is the output which will be similar to what 
    we have seen earlier since they both use common implementation.
    
    run:
         [java] TestStatInterface
         [java] TestStatInterface: before calling method getName on proxy ...
         [java] statsproxy before method getName
         [java] result = called getName() ...
         [java] statsproxy after method getName
         [java] TestStatInterface: stat.getName() = called getName() ...
         [java] TestStatInterface: after calling method getName on proxy ...
         [java] TestStatInterface: before calling method getStartTime on proxy ...
         [java] statsproxy before method getStartTime
         [java] result = 1234986155422
         [java] statsproxy after method getStartTime
         [java] TestStatInterface: stat.getStartTime() = 1234986155422
         [java] TestStatInterface: after calling method getStartTime on proxy ...
    
    BUILD SUCCESSFUL
    
Download the complete example.

[1] Comments
Like this post? del.icio.us | furl | slashdot | technorati | digg