<document>
  <header>
    <product>resin</product>
    <title>MBean listeners</title>
    <type>tutorial</type>
    <description>Example showing configuration of MBean event listeners.</description>
 <tutorial-startpage>listener</tutorial-startpage>
  </header>

<body>

<summary/>

<section title="Files in this tutorial">
<deftable>
<tr><td><viewfile-link file="WEB-INF/web.xml"/>
    <td>Configures the JMX-managed bean
<tr><td><viewfile-link file="WEB-INF/classes/example/Listener.java"/>
    <td>The listener bean implementation.
<tr><td><viewfile-link file="WEB-INF/classes/example/ListenerMBean.java"/>
    <td>The management interface for the listener.
<tr><td><viewfile-link file="WEB-INF/classes/example/Emitter.java"/>
    <td>The emitter bean implementation.
<tr><td><viewfile-link file="WEB-INF/classes/example/EmitterMBean.java"/>
    <td>The management interface for the emitter.
<tr><td><viewfile-link file="WEB-INF/classes/example/ListenerServlet.java"/>
    <td>Using the managed bean.
</deftable>
</section>

<section title="Emitter and Listener">

<p>JMX provides a general notification capability where MBean
<var/emitters/> send data to MBean <var/listeners/>.  Any managed
bean can be an emitter or a listener by implementing the
proper interfaces.  The listeners are hooked up to the emitters either
in the configuration file or through MBeanServer calls.</p>

<subsection title="Listener">

<p>A listener implements <code>NotificationListener</code> to receive
<code>Notification</code> events.  The notification contains information
for the type of the notification, the sender of the notification, and
any notification-specific information.</p>

<p>The listener implements the single <code>handleNotification</code>
method.  It's parameters are the notification and an opaque
<var/handback/> object.  The <var/handback/> is specified during
the listener registration and can be any information the listener
wants.</p>

<example title="Listener.java">
package example;

import javax.management.NotificationListener;
import javax.management.Notification;

public class Listener
  implements NotificationListener, ListenerMBean {
  private int _count;

  public void handleNotification(Notification notif,
                                 Object handback)
  {
    _count++;
  }

  public int getNotificationCount()
  {
    return _count;
  }
}
</example>

</subsection>

<subsection title="Emitter">

<p>The Emitter sends notifications.  Any managed bean which implements
the <code>NotificationEmitter</code> interface can be an emitter.  Many
Emitters will extend the <code>NotificationBroadcasterSupport</code>,
although this is not required.</p>

<p><code>NotificationBroadcasterSupport</code> will handle the logic
for adding and removing listeners as well as sending notifications to
the proper listener.  By extending
<code>NotificationBroadcasterSupport</code>, the emitter only needs to
call <code>sendNotification</code> to send the notification.</p>

<p>The first argument for the <code>Notification</code> is the notification
type.  Because each emitter can send multiple notifications, the type
tells the listener which event has happened.</p>

<p>The second argument is typically the <code>ObjectName</code> for
the emitter.  Often, emitters will use
the <code>MBeanRegistration</code> interface to find out the
<code>ObjectName</code>.</p>

<example title="Emitter.java">
package example;

import javax.management.NotificationBroadcasterSupport;
import javax.management.Notification;

/**
 * Implements an MBean which sends notifications.
 */
public class Emitter extends NotificationBroadcasterSupport
  implements EmitterMBean {
  private long _sequence;
  
  /**
   * Sends a notification.
   */
  public void send()
  {
    Notification notif;

    notif = new Notification("example.send", this, _sequence++);

    sendNotification(notif);
  }
}
</example>

</subsection>

<section title="web.xml configuration">

<p>The web.xml (or resin.conf) configures the resource with the
&lt;resource> tag just as with
<a href="doc|resource|index">other resources</a>.  The resources is
registered as an MBean by specifying an <var/mbean-name/>.

<example title="web.xml">
&lt;web-app xmlns="http://caucho.com/ns/resin">
  &lt;resource mbean-name="example:name=emitter"
            type="example.Emitter">
  &lt;/resource>

  &lt;resource mbean-name="example:name=listener"
            type="example.Listener">
    &lt;listener mbean-name="example:name=emitter" handback="tutorial"/>
  &lt;/resource>
&lt;/web-app>
</example>

<deftable>
<tr><th>tag<th>description
<tr><td>resource<td>defines the resource
<tr><td>mbean-name<td>the MBean name of the resource
<tr><td>type<td>the class name of the resource bean
<tr><td>listener<td>registers the mbean with a notification emitter mbean
<tr><td>handback<td>a custom object to be passed back to the listener
</deftable>

</section>

<section title="Using the listener">

<p>This example provides a <code>send()</code> method to
trigger a notification, but most notifications occuring when
specific events occur, e.g. when a pool fills up.</p>

<p>In this case, invoking the <code>send()</code> method triggers
the notification which will be sent to any waiting listeners.  Calling
<code>listener.getNotificationCount()</code> checks that the listener
is getting called back.</p>

<example title="ListenerServlet.java">
public class ListenerServlet extends GenericServlet {
  private EmitterMBean _emitter;
  private ListenerMBean _listener;

  public void setEmitter(EmitterMBean emitter)
  {
    _emitter = emitter;
  }

  public void setListener(ListenerMBean listener)
  {
    _listener = listener;
  }

  public void service(ServletRequest request,
		      ServletResponse response)
    throws ServletException, IOException
  {
    PrintWriter out = response.getWriter();
    
    _emitter.send();

    out.println("listener count: " + _listener.getNotificationCount());
  }
}
</example>
<results title="output">
count: 15
</results>
<results title="log">
[15:37:15.545] notification(type=example.send,handback=tutorial)
[15:37:16.624] notification(type=example.send,handback=tutorial)
[15:37:17.453] notification(type=example.send,handback=tutorial)
</results>

</section>

<section title="Configuration with Dependency Injection">

<p>The ListenerServlet example follows the
Dependency Injection pattern.  Resin's web.xml will assemble the
correct EmitterMBean and ListenerMBean.  Using the Dependency Injection
pattern simplifies the servlet, makes it more configurable,
and more testable.</p>

<p>The configuration takes advantage of the "mbean:" JNDI scheme in Resin.
The name following "mbean:" is used to lookup the mbean instance.  The
"mbean:" scheme then constructs a proxy for the mbean.  The proxy
of the JNDI lookup is then passed to <code>setEmitter</code>
and <code>setListener</code>.</p>

<example title="web.xml">
&lt;servlet-mapping url-pattern="/listener"
                 servlet-class="example.ListenerServlet">
  &lt;init>
    &lt;emitter>\${jndi:lookup("mbean:example:name=emitter")}&lt;/emitter>
    &lt;listener>\${jndi:lookup("mbean:example:name=listener")}&lt;/listener>
  &lt;/init>
&lt;/servlet-mapping>
</example>

</section>

</section>

<section title="Compatibility">

<p>Notifications and listeners are part of the JMX standard.
Client MBean proxies are standard and can be generated
with <code>javax.management.MBeanServerInvocationHandler</code>
</p>

<p>The &lt;resource> configuration is Resin-specific.  The support
for the Dependency Injection for servlet configuration
and the "mbean:" JNDI scheme are also Resin-specific.</p>

</section>

  </body>
</document>
