Jess Information

Jess Home
Jess 7 Features
Download Now!
Online Demo

Documentation
FAQ
Manual
Mailing List
Jess Wiki

More information Related Web Sites
User Contributions
JSR94 Info
Developer's Log
About This Site

JESS ®, the Rule Engine for the JavaTM Platform

Jess Wiki: Watch Router

You can direct watch information to different routers attached to different files using the WatchRouter class. Since it is a JessListener, it can be added to your Rete object using the addJessListener method so that it is notified when a Jess event occurs. However, to fully override the watch mechanism supplied in Jess, you must sub-class jess.Rete and override the setWatchRouter and eventHappened methods as follows. If you do this, there will be no need to add the WatchRouter to the Rete object.

/** This Rete object allows watch information to be sent to different ouput routers. */
public class MyRete extends jess.Rete {
    /** The watch router */
    private final WatchRouter watchRouter = new WatchRouter();

    /** Set the default watch router
     * @see jess.Rete#setWatchRouter(java.lang.String)
     */
    public String setWatchRouter(String s) throws JessException {
        return watchRouter.setWatchDefaultRouter(s);
    }

    /** Set the watchActivationRouter
     * @param watchActivationRouter the watchActivationRouter to set
     */
    public String setWatchActivationsRouter(String watchActivationRouter) {
        return watchRouter.setWatchActivationsRouter(watchActivationRouter);
    }

    /** Set the watchDefruleFiredRouter
     * @param watchDefruleFiredRouter the watchDefruleFiredRouter to set
     */
    public String setWatchRulesRouter(String watchDefruleFiredRouter) {
        return watchRouter.setWatchRulesRouter(watchDefruleFiredRouter);
    }

    /** Set the watchDefruleRouter
     * @param watchDefruleRouter the watchDefruleRouter to set
     */
    public String setWatchCompilationsRouter(String watchDefruleRouter) {
        return watchRouter.setWatchCompilationsRouter(watchDefruleRouter);
    }

    /** Set the watchFactRouter
     * @param watchFactRouter the watchFactRouter to set
     */
    public String setWatchFactsRouter(String watchFactRouter) {
        return watchRouter.setWatchFactsRouter(watchFactRouter);
    }

    /** Set the watchFocusRouter
     * @param watchFocusRouter the watchFocusRouter to set
     */
    public String setWatchFocusRouter(String watchFocusRouter) {
        return watchRouter.setWatchFocusRouter(watchFocusRouter);
    }

    /** Event listener for watch events
     * @see jess.Rete#eventHappened(jess.JessEvent)
     */
    public void eventHappened(JessEvent je) {
        watchRouter.eventHappened(je);
    }
}

In order to use the WatchRouter class, you must first create one or more output routers in Jess. Then create an instance of WatchRouter and set the router names for the items you want to watch to the router(s) you created.

Note: There are two things you should be careful of when using WatchRouter:

  • It uses package-private members in the Rete object and must, therefore, reside in the "jess" package.
  • It may not work correctly in a J2EE environment due to the hierarchical class loader's restrictions on accessing package-private members in library classes. This will depend on your particular J2EE configuration.

/** WatchRouter.
 * 
 * <P>Created on Aug 8, 2006</P>
 * @author George A. Williamson Jr. (Ihfe020)
 * @author ©Union Pacific Railroad
 */
public class WatchRouter implements JessListener {
    /** The newline string */
    private static final transient String newline
        = System.getProperty("line.separator");

    /** The index */
    private int index = 1;

    /** The watch activation router */
    private String watchActivationRouter;
    /** The watch defrule fired router */
    private String watchDefruleFiredRouter;
    /** The watch defrule router */
    private String watchDefruleRouter;
    /** The watch fact router */
    private String watchFactRouter;
    /** The watch focus router */
    private String watchFocusRouter;
    /** The default watch router */
    private String watchDefaultRouter;

    /** Construct a new WatchRouter */
    public WatchRouter() {}

    /** Validate the router
     * @return the validated router
     */
    private String validateRouter(String router) {
        if (router == null
            || router.equalsIgnoreCase("nil")
            || router.equalsIgnoreCase("default"))
        {
            return null;
        }
        return router;
    }

    /** Get the watchDefaultRouter
     * @return the watchDefaultRouter
     */
    public String getWatchDefaultRouter() {
        return watchDefaultRouter != null
               ? watchDefaultRouter
               : "WSTDOUT";
    }

    /** Set the watchDefaultRouter
     * @param watchDefaultRouter the watchDefaultRouter to set
     */
    public String setWatchDefaultRouter(String watchDefaultRouter) {
        String old = this.watchDefaultRouter;
        this.watchDefaultRouter = validateRouter(watchDefaultRouter);
        return old;
    }

    /** Get the router name
     * @return the router name
     */
    private String getRouter(String router) {
        return router != null
               ? router
               : getWatchDefaultRouter();
    }

    /** Get the watchActivationRouter
     * @return the watchActivationRouter
     */
    public String getWatchActivationRouter() {
        return getRouter(watchActivationRouter);
    }

    /** Set the watchActivationRouter
     * @param watchActivationRouter the watchActivationRouter to set
     */
    public String setWatchActivationsRouter(String watchActivationRouter) {
        String old = this.watchActivationRouter;
        this.watchActivationRouter = validateRouter(watchActivationRouter);
        return old;
    }

    /** Get the watchDefruleFiredRouter
     * @return the watchDefruleFiredRouter
     */
    public String getWatchDefruleFiredRouter() {
        return getRouter(watchDefruleFiredRouter);
    }

    /** Set the watchDefruleFiredRouter
     * @param watchDefruleFiredRouter the watchDefruleFiredRouter to set
     */
    public String setWatchRulesRouter(String watchDefruleFiredRouter) {
        String old = this.watchDefruleFiredRouter;
        this.watchDefruleFiredRouter = validateRouter(watchDefruleFiredRouter);
        return old;
    }

    /** Get the watchDefruleRouter
     * @return the watchDefruleRouter
     */
    public String getWatchDefruleRouter() {
        return getRouter(watchDefruleRouter);
    }

    /** Set the watchDefruleRouter
     * @param watchDefruleRouter the watchDefruleRouter to set
     */
    public String setWatchCompilationsRouter(String watchDefruleRouter) {
        String old = this.watchDefruleRouter;
        this.watchDefruleRouter = validateRouter(watchDefruleRouter);
        return old;
    }

    /** Get the watchFactRouter
     * @return the watchFactRouter
     */
    public String getWatchFactRouter() {
        return getRouter(watchFactRouter);
    }

    /** Set the watchFactRouter
     * @param watchFactRouter the watchFactRouter to set
     */
    public String setWatchFactsRouter(String watchFactRouter) {
        String old = this.watchFactRouter;
        this.watchFactRouter = validateRouter(watchFactRouter);
        return old;
    }

    /** Get the watchFocusRouter
     * @return the watchFocusRouter
     */
    public String getWatchFocusRouter() {
        return getRouter(watchFocusRouter);
    }

    /** Set the watchFocusRouter
     * @param watchFocusRouter the watchFocusRouter to set
     */
    public String setWatchFocusRouter(String watchFocusRouter) {
        String old = this.watchFocusRouter;
        this.watchFocusRouter = validateRouter(watchFocusRouter);
        return old;
    }

    public void printIndex(Writer w) throws IOException {
        if (index < 10) { w.write(" "); }
        if (index < 100) { w.write(" "); }
        if (index < 1000) { w.write(" "); }
        w.write(new Integer(index++).toString());
        w.write(" ");
    }

    private Writer getOutputRouter(Rete engine, String watchRouter) {
        Writer writer = engine.getOutputRouter(watchRouter);
        if (writer == null && !watchRouter.equals(getWatchDefaultRouter())) {
            writer = engine.getOutputRouter(getWatchDefaultRouter());
        }
        return writer;
    }

    public void eventHappened(JessEvent je) {
        // Get the engine
        Rete engine = null;
        Context context = je.getContext();
        if (context != null) {
            engine = je.getContext().getEngine();
        }
        if (engine == null && je.getSource() instanceof Rete) {
            engine = (Rete) je.getSource();
        }
        if (engine == null) { return; }

        if (!engine.watchingAny())
            return;

        try {
            int type = je.getType();
            boolean remove = (type & JessEvent.REMOVED) != 0;
            boolean modified = (type & JessEvent.MODIFIED) != 0;

            switch (type & ~JessEvent.REMOVED & ~JessEvent.MODIFIED) {

                case JessEvent.FACT: {
                    Writer w = getOutputRouter(engine, getWatchFactRouter());
                    if (!= null && engine.watching(WatchConstants.FACTS)) {
                        Fact f = (Fact) je.getObject();
                        printIndex(w);
                        w.write(remove
                                ? "<== "
                                : modified
                                  ? "<=> "
                                  : "==> ");
                        w.write("f-");
                        w.write(new Integer(f.getFactId()).toString());
                        w.write(" ");
                        w.write(!= null ? f.toString() : "null");
                        w.write(newline);
                        w.flush();
                    }
                    break;
                }

                case JessEvent.FOCUS: {
                    Writer w = getOutputRouter(engine, getWatchFocusRouter());
                    if (!= null && engine.watching(WatchConstants.FOCUS)) {
                        printIndex(w);
                        w.write(remove ? "<== " : "==> ");
                        w.write("Focus ");
                        w.write(je.getObject() != null
                                ? je.getObject().toString()
                                : "null");
                        w.write(newline);
                        w.flush();
                    }
                    break;
                }

                case JessEvent.DEFRULE_FIRED: {
                    Writer w = getOutputRouter(engine, getWatchDefruleFiredRouter());
                    if (!= null && engine.watching(WatchConstants.RULES)) {
                        PrintWriter pw = new PrintWriter(w);
                        printIndex(pw);
                        ((Activation) je.getObject()).debugPrint(pw);
                        w.flush();
                        pw.flush();
                    }
                    break;
                }

                case JessEvent.ACTIVATION: {
                    Writer w = getOutputRouter(engine, getWatchActivationRouter());
                    if (!= null && engine.watching(WatchConstants.ACTIVATIONS)) {
                        Activation a = (Activation) je.getObject();
                        printIndex(w);
                        w.write(remove ? "<== " : "==> ");
                        w.write("Activation: ");
                        w.write(a.getRule().getDisplayName());
                        w.write(" : ");
                        w.write(a.getToken().factList());
                        w.write(newline);
                        w.flush();
                    }
                    break;
                }

                case JessEvent.DEFRULE: {
                    Writer w = getOutputRouter(engine, getWatchDefruleRouter());
                    if (!= null &&
                        engine.watching(WatchConstants.COMPILATIONS) &&
                        !remove)
                    {
                        printIndex(w);
                        w.write(((HasLHS) je.getObject())
                                .getCompilationTrace()
                                .toString());
                        w.write(newline);
                        w.flush();
                    }
                    break;
                }

                default:
                    break;
            }
        }
        catch (Exception e) {
            PrintWriter pw = engine.getErrStream();
            if (pw == null) {
                pw = engine.getOutStream();
                if (pw == null) {
                    Writer w = getOutputRouter(engine, getWatchDefaultRouter());
                    if (!= null) {
                        pw = new PrintWriter(w);
                    }
                }
            }

            if (pw != null) {
                e.printStackTrace(pw);
                pw.flush();
            }
        }
    }
}

Once the Rete object has been subclassed and the setWatch?Router methods have been added, corresponding user functions can be added using the SetWatchRouter class so that the watch routers can be directed from within the Jess code.

Submitted by:
GeorgeWilliamson
Union Pacific Railroad
gawillia@up.com



DebuggingTips


Front Page | Sandbox | Recent Changes | Powered by Friki | Last Edited: 18 January 2007