%
% $Id: Notification.tex,v 1.10 2005-12-04 22:14:53 alphonse.bendt Exp $
%

The JacORB Notification Service is a partial implementation of
the Notification Service specified by the OMG.

\section{Unsupported Features}

The JacORB Notification Service does not support persistent connections or events.

\section{Installation}
\label{sec:installation}

\subsection{JDK 1.3}

If you're using JDK 1.3 and want to use the JacORB Notification
Service you'll need 
to download the additional library gnu.regexp from 
\href{http://www.cacas.org/java/gnu/regexp}{http://www.cacas.org/java/gnu/regexp}
and put it in your classpath. This is necessary because the JacORB
Notification Service uses regular expressions. Regular expressions are available in the JDK since version 1.4. Alternatively
you can download Jakarta Regexp \href{http://jakarta.apache.org/regexp}{http://jakarta.apache.org/regexp}.

\subsection{JDK 1.5}

The JacORB Notification Service uses the \href{http://www.mathcs.emory.edu/dcl/util/backport-util-concurrent/}{backport of JSR 166}. If you are using JDK 1.5 you don't need to use this extra library. Instead you can use the standardized java.util.concurrent package. By simply changing the package names inside the
sources and recompiling you can switch between the two versions.

Change to the directory \texttt{src/org/jacorb/notification} and invoke the command \texttt{ant convert.jdk5}. After that you have to recompile JacORB. The target \texttt{ant convert.jdk4} allows to switch back to backport-util-concurrent (These targets will simply replace all occurences of the string edu.emory.mathcs.backport.java.util.concurrent with java.util.concurrent and vice versa).
 
\section{Running the Notification Service}
\label{sec:ntfy-running}

Before the JacORB Notification Service can be accessed, a server
process must be started. Starting
the notification server is done by running

\cmdline{ntfy [-printIOR] [-printCorbaloc] [-writeIOR \emph{filename}]
  [-registerName \emph{nameID}[.\emph{nameKind}]] [-port \emph{oaPort}] [-channels
  \emph{channels}] [-help]} 

\begin{tabbing}
XX \= XXXXXXXXXXXXXXXXXXXXX \= XX \kill
\> -printIOR \> print the IOR to STDOUT \\
\> -printCorbaloc \> print the Corbaloc to STDOUT \\
\> -writeIOR \emph{filename} \> write the IOR to a file \\
\> -registerName \emph{nameId}[.\emph{nameKind}] \> make a Name Service entry
for the EventChannelFactory. \\
\> \> The Notification Service will resolve the Name Service \\
\> \> by invoking \\
\> \> \texttt{resolve\_initial\_references("NameService")}. \\
\> \> Ensure that your environment is set up properly. \\
\> -port \emph{oaport} \> start the Notification Service on the specified
port. \\
\> -channels \emph{channels} \> create a number of EventChannels. \\
\end{tabbing}

\subsection{Running as a NT Service or an UNIX Daemon}
\label{sec:runn-notif-serv-1}

With a little help from
\href{http://wrapper.tanukisoftware.org}{the Java Service Wrapper} it is
easy to run the JacORB notification service as a NT Service or as
an UNIX daemon. 


\subsubsection{Note for JDK 1.3 Users}
\label{sec:ntfy-jdk1.3}

As noted if you are running JDK 1.3 you need to provide an
additional library. If you use the wrapper you also need to add a
classpath entry to the wrapper configuration file.

Edit \texttt{bin/NotifyService-Wrapper.conf} and add a classpath
entry:

\begin{verbatim}
# Java Classpath (include wrapper.jar)  Add class path elements as
#  needed starting from 1
wrapper.java.classpath.1=../lib/wrapper-3.x.y.jar
...
wrapper.java.classpath.6=../lib/avalon-framework-4.1.5.jar
wrapper.java.classpath.7=../lib/gnu.regexp.jar
\end{verbatim}

\subsubsection{Installing and Running as a NT Service}
\label{sec:windows-service}

The necessary wrapper configuration files are located in the
\texttt{JacORB/bin} directory. 

The notification service can be installed as a NT service by double
clicking on the \texttt{NotifyService-Install-NT.bat} batch file which
is located in the \texttt{JacORB/bin} directory.
Alternatively you can open a Command Window and then run the install
script from the command prompt. 

\begin{verbatim}
  C:\JacORB\bin>NotifyService-Install-NT.bat
  wrapper  | JacORB Notification Service installed.
\end{verbatim}

Once the service has been installed, it can be started by opening up
the Service Control Panel, selecting the service, and then pressing
the start button.

The service can also be started and stopped from within a Command
Window by using the \texttt{net start JacORB-Notify} and \texttt{net
  stop JacORB-Notify} commands, or 
by passing commands to the wrapper.exe executable. 

The wrapper is set up to start the JacORB Notification Service
whenever the machine is rebooted. The service can be uninstalled by running the
\texttt{NotifyService-Uninstall-NT.bat} batch file. See the Windows specific
\href{http://wrapper.tanukisoftware.org/doc/english/launch-win.html}{wrapper
  documentation} for more details.
  
\subsubsection{Installing and Running as an UNIX Daemon}
\label{sec:inst-runn-as}

JacORB is shipped with a \texttt{sh} script which can be used to start
and stop the JacORB Notification Service controlled by the Java
Service Wrapper.

First you need to download the appropiate binary for your system from
\href{http://wrapper.tanukisoftware.org}{http://wrapper.tanukisoftware.org}.
The Java Service Wrapper is supported on Windows, Linux, Solaris, AIX,
HP-UX, Macintosh OS X, DEC OSF1, FreeBSD, and SGI Irix systems (Note:
You don't need to download anything if you are running Windows. All
necessary stuff is shipped with the JacORB distribution).

Install the Java Service Wrapper to a appropiate place by unzipping it 
(\emph{WRAPPER\_HOME}). Add
\texttt{\emph{WRAPPER\_HOME}/bin} to your PATH variable. If you don't
want to modify your PATH variable you can put a link to
\texttt{\emph{WRAPPER\_HOME}/bin/wrapper} in one of the directories
that's already in your PATH environment (e.g. \texttt{ln -s
  /usr/local/wrapper/bin/wrapper /usr/local/bin}).

Ensure that the shell-script
\texttt{JacORB/bin/ntfy-wrapper} has the executable bit set. Note that
the .sh script will attempt to create a pid file in the directory
specified by the property \texttt{PIDDIR} in the script. If
the user used to launch the Wrapper does not have permission to write
to this directory then this will result in an error. An alternative
that will work in most cases is to write the pid file to another
directory. To make this change, edit the .sh script and change the following setting: 

\begin{verbatim}
PIDDIR="."
\end{verbatim}
to something more appropiate:
\begin{verbatim}
PIDDIR="/var/run"
\end{verbatim}

\paragraph{Running in the console}
\label{sec:running-console}

 The JacORB notification service  can now be run by simply executing
 \texttt{bin/ntfy-wrapper console}.
When running using the console command, output from the notification
 service will be visible in the console. 
 The notification service can be terminated by hitting CTRL-C in the command
 window. This will cause the Wrapper to shut down the service cleanly.  

 If you omit the command the scripts prints the available commands.
 The script accepts the commands start, stop, restart and dump. The
 start, stop, and restart commands are common to most daemon scripts
 and are used to control the wrapper and the notification service  as
 a daemon process. The console 
 command will launch the wrapper in the current shell, making it
 possible to kill the application with CTRL-C. Finally the command
 dump will send a kill -3 signal to the wrapper causing its JVM
 to do a full thread dump.  
 
 \paragraph{Running as a Daemon Process}
 \label{sec:running-as-daemon}
 
 The application can be run as a detatched daemon process by executing
 the script using the \emph{start} command. 

 When running using the start  command, output from the JVM will only
 be visible by viewing the logfile \texttt{NotifyService-Wrapper.log}
 using \texttt{tail -f NotifyService-Wrapper.log}. The location of the
 logfile can be configured in the wrapper configuration file
 \texttt{bin/NotifyService-Wrapper.conf} 

 Because the application is running as a detatched process, it can not
 be terminated using CTRL-C and will continue to run even if the
 console is closed. 
 
 To stop the application rerun the script using the \emph{stop} command.
 
 \paragraph{Installing The Notification Service To Start on Reboot}
 \label{sec:inst-appl-start}

 This is system specific. See the UNIX specific
 \href{http://wrapper.tanukisoftware.org/doc/english/launch-nix.html}{wrapper
   documentation} for instructions for some platforms.

\subsection{Running as a JBoss Service}

The JacORB notification service can also be run as a jboss service.

As first step the jacorb.jar that is shipped with jboss (\texttt{JBOSS\_HOME/server/all/lib})
needs to be replaced to the current version (v2.2.3).
As next step the jboss-cosnotification.sar file can be deployed into jboss 
by copying it to \texttt{JBOSS\_HOME/server/all/deploy}.

After starting jboss a mbean for the notification service will show up in
the jboss jmx management console.

\section{Accessing the Notification Service}
\label{sec:access-notif-serv}

Configuring a default notification service as the ORB's default is done
by adding the URL that points to the service to the properties files
\texttt{.jacorb\_properties}. A valid URL can be obtained in various ways:
\begin{enumerate}
\item By specifying the option \texttt{-printIOR} as you start the
  notification service a stringified IOR is printed out to the
  console. From there you can copy it to a useful location.

\item Usually the stringified IOR makes most sense inside a file. Use
  the option \texttt{-writeIOR <filename>} to write the IOR to the specified
  file.

\item A more compact URL can be obtained by using the
  option \texttt{-printCorbaloc}. In conjunction with the option
  \texttt{-port} you can use the simplified corbaloc: URL of the form
  \texttt{corbaloc::ip-address:port/NotificationService}. This means
  all you need to know to construct an object reference to your
  notification service is the IP address of the machine and the port
  number the server process ist listening on (the one specified using
  \texttt{-port}). 

\end{enumerate}

Add the property \texttt{ORBInitRef.NotificationService} to your
properties file. The value can be a corbaloc: URL or alternatively the
file name where you saved the IOR.

The JacORB notification service is accessed using the standard CORBA
defined interface:

\small{
\begin{verbatim}
  // get a reference to the notification service
  ORB orb = ORB.init(args, null);
  org.omg.CORBA.Object obj; 
  obj = orb.resolve_initial_references("NotificationService");
  EventChannelFactory ecf = EventChannelFactoryHelper.narrow( o );
  IntHolder ih = new IntHolder();
  Property[] p1 = new Property[0];
  Property[] p2 = new Property[0];
  EventChannel ec = ecf.create_channel(p1, p2, ih);
  ...
\end{verbatim}
}

\section{Configuration}
\label{sec:ntfy-configuration}

Following is a brief description of the properties
that control Notification Service behaviour.

The Notification Service uses up to three Thread Pools with a configurable
size. The first Thread Pool is used to process the filtering of the
Messages. The second Thread Pool is used to deliver the Messages to the
Consumers. The third Thread Pool us used to pull Messages from PullSuppliers. 

\begin{small}
  \begin{longtable}{|p{5cm}|p{7.5cm}|p{1.5cm}|p{1.5cm}|}
    \caption{Notification Service Properties}\\
    \hline
    ~ \hfill \textbf {Property} \hfill ~ & ~ \hfill \textbf {Description}
    \hfill ~ & ~ \hfill \textbf {Type} \hfill ~ & \hfill \textbf{Default} \endhead
    \hline
    \verb"filter."
    \verb"thread_pool_size"\footnote{All notification service
    properties share the common prefix \emph{jacorb.notification} which
    is omitted here to save some space} &

    This is the Size of the Thread Pool used to process the filters.
    Increasing this value on a Multiprocessor machine or if Filters are on
    a different machine than the Channel could increase the Filtering
    Performance as multiple events can be processed concurrently. & 
    
    int $\geq$ 0 &

    2 \\
    \hline

    \verb"proxysupplier."
    \verb"thread_pool_size" &

    This is the Size of the Thread Pool used to deliver the Messages to
    the Consumers. By using the property
    \texttt{proxysupplier.threadpolicy}\footnote{also abbreviated.}
    it is also possible to use one Thread per ProxySupplier. &

    int $\geq$ 0 & 
    4 \\ \hline    

    \verb"proxyconsumer."
    \verb"thread_pool_size" &

    Specifies the Size of the Thread Pool used to pull Messages from
    PullSuppliers &

    int $>=$ 0 & 

    2 \\ \hline

    \verb"proxysupplier."
    \verb"threadpolicy" &

    Specify which thread policy the ProxySuppliers should use to deliver
    the Messages to its Consumers. Valid values are: 
    \begin{description}     
    \item[ThreadPool] a fixed number of threads is used. See property
      \verb"proxysupplier."
      \verb"thread_pool_size".

    \item[ThreadPerProxy] Each ProxySupplier uses its own thread.
      
    \end{description} & 
    string & Thread\-Pool \\ \hline

    \verb"supplier."
    \verb"poll_intervall" &

    Specifies how often Messages should be pulled from a PullSupplier. The
    value specifies the intervall between two pull-Operations. &

    milli\-seconds & 1000 \\ \hline

    \verb"supplier."
    \verb"max_number" &

    Specify the maximum number of Suppliers that may be connected to a
    Channel at a time. If a Supplier tries to connect, while this
    limit is exceeded, AdminLimitExceeded is raised. Note that this
    property can also be set programatically via the \texttt{set\_admin}
    operation. & int $>$ 0 & maximum int value \\ \hline

    \verb"consumer"
    \verb"max_number" &

    Specify the maximum number of Consumers that may be connected to a
    Channel at a time. If a Consumer tries to connect, while this
    limit is exceeded, AdminLimitExceeded is raised. Note that this
    property can also be set programatically via the
    \texttt{set\_admin} operation. &

    int $>$ 0 & maximum int value \\ \hline

    \verb"max_events_"
    \verb"per_consumer" &

    Specifies how many Events a ProxySupplier at most should queue for a
    consumer. If this number is exceeded Events are discarded according to
    the DiscardPolicy configured for the ProxySupplier. &

    int $>$ 0 & 100 \\ \hline

    \verb"max_batch_size" &

    Specifies the maximal number of Messages a SequencePushSupplier should
    queue before a delivery to its connected SequencedPushConsumer is
    forced. &

    int $>=0$ & 1 \\ \hline

    \verb"order_policy" &

    Specify how events that are queued should be ordered. Valid values
    are: 
    \begin{itemize}
    \item AnyOrder

    \item PriorityOrder

    \item DeadlineOrder

    \item FifoOrder
    \end{itemize} & 

    string & Priority\-Order \\ \hline

    \verb"discard_policy" &

    Specifies which Events are discarded if more than the  
    maximal number of events are queued for a consumer. 
    Valid values are:
    \begin{itemize}
    \item AnyOrder

    \item PriorityOrder

    \item DeadlineOrder

    \item FifoOrder

    \item LifoOrder
    \end{itemize} &

    string & Priority\-Order \\ \hline
       
    \verb"consumer."
    \verb"backout_interval" &

    After a delivery to a Consumer has failed the Channel will pause
    delivery to that Consumer for a while before retrying. This property
    specifies how long a consumer should stay disabled. &

    milli\-seconds & 1000 \\ \hline

    \verb"consumer."
    \verb"error_threshold" &

    Each failed delivery to a consumer increments an errorcounter. If this
    errorcounter exceeds the specified value the consumer is
    disconnected from the channel. &

    int $>=$ 0 & 3 \\ \hline

    \verb"default_filter_factory" &

    Specify which FilterFactory (\texttt{CosNotifyFilter::FilterFactory}) the
    attribute \texttt{EventChannel::\-default\_filter\_factory} should be set to. 
    Default value is \emph{builtin}. This special value implies that a
    FilterFactory will be created during start of the EventChannel.
    Its possible to set this property to a URL that points to another
    \texttt{CosNotifyFilter::FilterFactory} object. In this case no FilterFactory
    is started by the EventChannel. The URL is resolved by a call
    to \texttt{ORB::string\_to\_object}. &

    URL & builtin \\ \hline

    \verb"proxy.destroy_"
    \verb"causes_disconnect" &

    Specify if a destroyed Proxy should call the disconnect operation
    of its consumer/supplier. &

    boolean & on \\ \hline
  \end{longtable}
\end{small}

\subsection{Setting up Bidirectional GIOP}

If you have set the ORBInitializer property as described in Section \ref{sec:setting-up-bidir-orbinitializer} 
the Notification will automatically configure its POA to use Bidirectional GIOP.

\section{Monitoring the Notification Service}
\label{sec:ntfy-monitoring}

The JacORB Notification Service provides JMX MBean interfaces which make it possible to monitor and control the Service using a JMX console. This section will describe how to start a JMX enabled Notification Service and how to configure your JMX console to access the exposed MBeans.

\subsection{Download MX4J}

MX4J is an Open Source implementation of the JMX specification. You need to download the current release of MX4J (currently 3.0.1) from the JMX project page \href{mx4j.sourceforge.net}{mx4j.sourceforge.net} and install MX4J in an appropriate place.

\subsection{Edit Java Service Wrapper configuration}

The configuration file \emph{NotifyService-Wrapper-MX4J.conf.template} contains the necessary settings to start the
JMX enabled Notification Service. You have to edit the classpath. Replace the token @MX4J\_HOME@ with the concrete path to your MX4J installation.

\begin{verbatim}
# Java Classpath (include wrapper.jar)  Add class path elements as
#  needed starting from 1
wrapper.java.classpath.1=../lib/wrapper-3.x.y.jar
...
wrapper.java.classpath.8=@MX4J_HOME@/lib/mx4j.jar
wrapper.java.classpath.9=@MX4J_HOME@/lib/mx4j-remote.jar
wrapper.java.classpath.10=@MX4J_HOME@/lib/mx4j-tools.jar
\end{verbatim}

After customization of the configuration file it must be renamed to \emph{NotifyService-Wrapper.conf} as the start script reads its configuration from the so called file. 

\subsection{Start the Service}
consult section \ref{sec:runn-notif-serv-1} for further details to start the Service.

\subsection{Connecting to the management console}

The Notification Service web management console will be available at
\href{http://localhost:8001}{http://localhost:8001}.

A JSR 160 RMI connector allows a management console to connect to the Notification Service. The Service URL is \texttt{service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jndi/COSNotification}.

\section{Extending the JacORB Notification Service}
\subsection{Adding custom Filters}

The JacORB Notification Service supports the full ETCL filter grammar. If you need to use your own specialized filters you have to provide an implementation of the Filter Interface. You can extend the class
\texttt{org/jacorb/notification/filter/AbstractFilter.java} that provides generic filter management. 
See the class \texttt{org/jacorb/notification/filter/bsh/BSHFilter.java} for an example of an \href{http://www.beanshell.org/}{Beanshell} based custom filter.
Additionally to the standard ETCL grammar the FilterFactory will try to
load all filter grammars specified in jacorb.properties.
An entry must have the following form:
\texttt{jacorb.notification.filter.plugin.GRAMMAR=CLASSNAME} where \emph{GRAMMAR} should be replaced by the name of the grammar and \emph{CLASSNAME} should be replaced by the classname of the custom filter implementation.

custom filters can then be created by invoking \texttt{FilterFactory::create\_filter} or \texttt{FilterFactory::create\_mapping\_filter} and specifying \emph{GRAMMAR} as parameter.
 
 %% \section{Miscellaneous}
 
 %%TODO describe grinder
 
%%% Local Variables: 
%%% mode: latex
%%% TeX-master: "../ProgrammingGuide"
%%% End: 
