Monday, May 7, 2012

Spring AOP - or Aspect Oriented Programming

Well, as with project-1, I am including a brief example on using AOP. Here, I will give you a demonstration, but unlike previous examples, I will repeat all the necessary files since there are specifics in the applicationContext, annotations, beans and junit tests that will need to be covered and the code was not previously demonstrated. Although this tutorial is included in the broader project-2, the code is not dependent on the rest of the project.

First, what do we want to solve in this example? Let us say, we wish to monitor the performance of certain methods and report back to us, in a standardized way, what went on. We decide we want to annotate the methods we want to track, and by passing in a few arguments in the annotation, that will be enough to report back the time, name, etc.

In our CDI AOP example, we saw how powerful yet simple the CDI AOP model is. Spring is even more powerful, and more complex. AspectJ is even more of both. There are so many options with Spring's AOP that I will just go through what I consider a complete example that give's you many of what I believe to be common applications of AOP, and hopefully reduce the amount of time spent piecemealing all the different parts together.

Note: Spring uses AspectJ to handle it's annotations even though you don't have to implement the entire AspectJ environment. You can do everything via the xml files, and then you don't need AspectJ, but I like annotations, so we are going to implement this with AspectJ enabled.

Let's get started. First, we are going to need some additional libraries. Download the AspectJ jar file from http://www.eclipse.org/aspectj/ and extract the libraries directory to wherever you are putting your libraries.  Then include them in your project.

Next we need to modify our applicationContext.xml file.  I'm going to put here the context file for our unit test,   you can see the complete applicationContext at the end of the post: SpringAOPTest.xml

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation=
          "http://www.springframework.org/schema/beans 
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop 
           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd
          ">
    <context:annotation-config/>
    <context:component-scan base-package="com.sample"/>
    <aop:aspectj-autoproxy />
    <bean id="performanceProfiler" class="com.sample.aop.PerformanceInterceptor" />
</beans>
 
Now here we do have some items that we've seen in other posts, but let's go over the whole file anyway.  First, we declare the name spaces with the xlmns:...  Once that is done, we tell spring where to find the definitions for those name spaces with the xsi:schemaLocation.  Next we enable spring to be able to use annotations, and what packages to scan for annotations with the two <context..> lines. Enabling annotations is different from enabling AspectJ.  AspectJ allows us to use annotations to define our interceptor, which we want to do, but what we did first, was to enable us to scan the java classes and find say @Component to create a bean or @Autowired to inject a bean.  Next, we enable AspectJ, which we do with the <aop:aspectj-autoproxy/>.  And finally, we define the actual bean that is our AOP interceptor.  Now interestingly, the bean id doesn't really matter here.  It doesn't need to be the name of our interceptor class, nor the name of our annotation, and we don't inject it.  It could just as easily be PerformanceInterceptor, performanceInterceptor, performanceMonitor, or as I put it for demonstration, performanceProfiler.

So far, all we have done is enabled our ability to code / run our interceptor.  Now we need the parts that will make our interceptor work.  We need a bean that will be intercepted.  This is different then the interceptor bean.  We need an annotation.  This is different then the AspectJ annotations that define our interceptor.  We need the interceptor.  And we'll need a unit test.

Let's first give a bean to be intercepted.  TestPerformanceMonitorBean.java:

package com.sample.beans;
import com.sample.aop.PerformanceMonitor;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
/**
 * @author Thomas Dias
 */
@Component
@Scope("prototype")
@PerformanceMonitor(data="data")
public class TestPerformanceMonitorBean {
    @PerformanceMonitor(name="TPMB")
    public Object someMethod() {
        System.out.println("entered some method");
        return new Object();
    }
 
    @PerformanceMonitor(name="MyName", db="slfjksfkl")
    public void otherMethod(Object t) {
        System.out.println("second test");
    }
 
    public void thirdMethod() throws Exception {
        System.out.println("testing class annotation");
        throw new Exception();
    }
}

Here we defined our bean with an annotation @Component.  Because we enabled annotation configuration / scanning, this will be seen and a bean will be created.  We can then inject this bean into our unit test.  Now, the next line is @Scope("prototype").  Your scope is going to be defined by your requirements.  A Spring Bean by default is a Singleton per application context.  That can be very good, and, can be very bad.  So here, we demonstrate a bean that gets a new instance everytime someone uses this bean.  We could have used request scope in an http environment to accomplish this, but since we are currently only using this for a unit test and I wanted to demonstrate using scope, I just used prototype.

We annotated our class, and our methods with @PerformanceMonitor.  You'll see in a minute how we interpreted those annotations, but the way we implemented it, if there is a method annotation, it is used, otherwise it uses the class annotation.  Either the class annotation or the method annotation must be present, or our pointcut will not fire the interceptor.  Also notice, we have some methods returning values, and some methods throwing exceptions.  All of that is handled by the interceptor.

Now that we have our bean, we'll look at our annotation: PerformanceMonitor.java

package com.sample.aop;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @author Thomas Dias
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface PerformanceMonitor {
    public String name() default "";
    public String db() default ":";
    public String table() default ":";
    public String data() default ":";
}

The interceptor will check the annotation on the class or method.  To do that, it must be kept around till runtime.  We do that with the @Retention(RetentionPolicy.RUNTIME) annotation.  Next we tell this annotation where it is allowed (on a class or a method) with the @Target line.  We turn this class into an annotation with the @interface annotation, and lastly we define some parameters that may be used with this annotation.  For our parameters, we supplied some default values.  We could have required that these parameters are supplied, but we wanted the usage of this annotation to be @PerformanceMonitor([name="someName"][,db="someDb"]...) where the attributes are separated by a comma and each attribute is optional.  

We have our bean annotated and our annotation defined, now I present the interceptor:  PerformanceInterceptor.java

package com.sample.aop;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
/**
 * @author Thomas Dias
 */
class PerformanceInfo {
    long startTime, endTime;
    String message, name, data, table, db;
    boolean success;
    PerformanceInfo(boolean b) {
        startTime = System.currentTimeMillis();
    }
    void stopTiming() {
        endTime = System.currentTimeMillis();
        System.out.println(name + " " + (endTime - startTime) + " " + db
                + " " + table + " " + data + " " + success + " " + message);
    }
    public void setData(String data) {
        this.data = data;
    }
    public void setDb(String db) {
        this.db = db;
    }
    public void setEndTime(long endTime) {
        this.endTime = endTime;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }
    public void setSuccess(boolean success) {
        this.success = success;
    }
    public void setTable(String table) {
        this.table = table;
    }
}

/** 
  * class that will perform the aop and intercept methods to monitor and log their performance
  * the method to be intercepted must be a public method, must be a bean annotated with:
  * @PerformanceMonitor(name="",db="",table="",data="") where the attributes name, db, table, and data are optional
  */
@Aspect
public class PerformanceInterceptor {
    @Around("execution(* com.sample..*.*(..)) && (@annotation(PerformanceMonitor) || @target(PerformanceMonitor))")
    public Object profile(ProceedingJoinPoint jp) throws Throwable {
        String methodName = jp.getSignature().getName();
        MethodSignature methodSignature = (MethodSignature)jp.getSignature();
        Method method = methodSignature.getMethod();
        if (method.getDeclaringClass().isInterface()) {
            method = jp.getTarget().getClass().getDeclaredMethod(methodName, method.getParameterTypes());    
        }
        PerformanceMonitor annotation = this.getPerformanceMonitorAnnotation(method);
        
        Throwable throwable = null;
        Object result = null;
        PerformanceInfo perf = new PerformanceInfo(true);
        perf.setSuccess(false);
        if(annotation.name().equals("")) {
            perf.setName(methodName);
        } else {
            perf.setName(annotation.name());
        }
        perf.setDb(annotation.db());
        perf.setTable(annotation.table());
        perf.setData(annotation.data());

        // Execute the method if result is null, fail
        try {
            result = jp.proceed();
            if (result == null) {
                perf.setMessage("Result is null");
            } else {
                perf.setSuccess(true);
            }
        } catch (Throwable e) {
            throwable = e;
            perf.setMessage("Error: " + e.getMessage());
        }

        perf.stopTiming();
        // do something with our performance object

        // If something was thrown throw it, else return the result
        if (throwable != null) {
            throw (throwable);
        }
        return result;
    }
    public PerformanceMonitor getPerformanceMonitorAnnotation(Method method) {
        for (Annotation a : method.getAnnotations()) {
            if (a instanceof PerformanceMonitor) {
                return (PerformanceMonitor) a;
            }
        }
        for (Annotation a : method.getDeclaringClass().getAnnotations()) {
            if (a instanceof PerformanceMonitor) {
                return (PerformanceMonitor) a;
            }
        }
        return null;
    }
}

Okay, so there is a lot more here then is necessary, but I figured we'd do a little more then just log the elapsed time to a log file.  The interceptor is instantiating another class that will be our timer, hold all the data like name, database, etc. and then we can pass that object elsewhere.  Our interceptor starts by getting the @Aspect annotation.  The PerformanceInterceptor then needs what is called a pointcut.  A pointcut is just a fancy name for the definition of what methods will be intercepted.  You can create a method that has a separate pointcut, or as we did here, we included the pointcut with the advice.  What is the advice?  The definition of what type of interceptor we are going to use.  Spring allows us several types of interceptors.  There are before a method, after a method, if a method throws and exception, if a method returns something, and around a method.  The around method combines the other types and is the one we chose for this interceptor.  I never mentioned what an interceptor is.  It intercepts the call to your method or field and performs some action.  Here, we are using it to catch all calls to a method annotated with @PerformanceMonitor and wrap that method in our action.  What is our interceptor?  Well, it is the method: public Object profile(ProceedingJoinPoint jp) throws Throwable.

Let us disect the pointcut we used for a moment.  First, when do we want to intercept?  When the method is about to be executed.  So, we start with methods at execution time.  Next, what is the signature of the methods we are intercepting?  Well, any return type, and any method who's package starts with com.sample. Any class name from those packages.  Any method name from those classes.  And lastly any method with any type of parameters. So, we have: execution(* com.sample..*.*(..))

We see from this example, we have a lot of power in defining what will be intercepted.  If we used the pointcut above as is, we intercept all the methods (from package com.sample) executed by any bean, and we didn't want that, so we put in another qualifier.  We said, is the method annotated? or is the class annotated?  We did that by: @annotation(PerformanceMonitor) || @target(PerformanceMonitor)

Tie those two together with an && (or and) and we have our pointcut: @Around("execution(* com.sample..*.*(..)) && (@annotation(PerformanceMonitor) || @target(PerformanceMonitor))").  Because the method we are intercepting may throw an exception, our interceptor will pass that along by declaring that it may throw an exception. And it needs to return whatever our intercepted method was going to return.  So, we return an object.

So, now our interceptor will execute when a method is executed.  Now why do I use that term?  because in AspectJ, there are also interceptors when a method is called.  Spring doesn't do that, but it is out there.  Now when a method is intercepted, we continue on to the method by having the interceptor call the JoinPoint.proceed().  With the @Around advice, we use the ProceedingJoinPoint.  You'll see the proceed() called toward the bottom of the method, but first, we interpret the annotations and assign values based on them.  We get the start time, etc.  Then we use the try catch to continue on with proceed().  We stop timing, log the information, throw the exception if one was thrown, or return what was returned.  And we're done.

Let's test it with a unit test:  PerformanceInterceptorTest.java

package com.sample.aop;
import com.sample.beans.TestPerformanceMonitorBean;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.junit.Assert.*;
/**
 * @author Thomas Dias
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="/SpringAOPTest.xml")
public class PerformanceInterceptorTest {
    @Autowired
    TestPerformanceMonitorBean instance;
    
    @Test
    public void testProfile() throws Throwable {
        Object a = instance.someMethod();
        assertNotNull(a);
        instance.otherMethod(null);
        try {
            instance.thirdMethod(); 
            fail("method should have thrown an exception");
        } catch (Exception e) {
        }
    }
}

The output

entered some method
TPMB 33 : : : true null
second test
MyName 0 slfjksfkl : : false Result is null
testing class annotation
thirdMethod 0 : : data false Error: null

Reviewing the output, we see that the first line from the interceptor comes after the output from the method we called. The interceptor wrapped the method and started the timer before calling the method, then after the method returned, it output the details. We see the "TPMB" from our annotation, the time it took, the default values for the attributes we didn't supply. Next we have our success value of true because the method returned a non null value result. And finally null as our message, since we never set it. The second method is called, and the output from the interceptor has the name and db attributes set, so they output. 0 is the time which simply means we didn't do enough in our method. The success is false, since nothing was returned. Of course, we notice on further inspection, the method we called was of return type void. And lastly our message was set to say "Result is null". The third method gets its annotation from the class. We didn't supply a name, so the name was set to the called method name. The method threw an exception, so success was set to false. And there we have it. An interceptor based on an annotation to profile whatever method or class we chose. Hopefully I have given enough of a base and answered a few of your questions.

Wednesday, March 14, 2012

JSF and Swing Part 3 - JSF push solution

After we saw how easy it was to push information to a Swing client, we might be tempted to believe it is similarly easy to push data to our JSF client.  But, in reality, that process is quite complicated.  There are several ways to accomplish the task, but many of the technologies are still in transition.  Richfaces, Primefaces, and Icefaces all have mechanisms to push data to a JSF client, but each has its downside and I don't think any are ready for "primetime".  Depending on the version you use you may be implementing push with a version of polling instead of an actual push technology.  The versions that do use push technology still seem to have compatibility issues with either the container, browser, or other libraries you are using.  Part of the reason for this, is the WebSocket API is still being defined and the different projects are implementing the spec without a complete definition.  That said, we are going to implement our own component using WebSockets.  We will not use any of the predefined push components from Icefaces, Richfaces, or Primefaces.  We will also demonstrate the usage of CDI events.

First, what is a WebSocket.  WebSockets are new to HTML5 and as previously said, are still being defined.  But the essence is that the client is going to establish a connection with the server using HTTP, then the connection will be kept open and used by the server to send data back.  The client will create a listener to listen for any data being sent by the server.  We will implement a WebSocket using Glassfish and grizzly.

To begin, we are going to need a WebSocket "server" that the clients are going to connect to, and receive broadcasts from.  To do this, we are going to implement a servlet running in our container.  We modify our web.xml by adding our servlet:

    <servlet>
        <servlet-name>WebSocketServletProcessMonitor</servlet-name>
        <servlet-class>com.sample.sockets.WebSocketServletProcessMonitor</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>WebSocketServletProcessMonitor</servlet-name>
        <url-pattern>/monitor</url-pattern>
    </servlet-mapping>

Then, we have our servlet WebSocketServletProcessMonitor.java:

package com.sample.sockets;
import com.sample.beans.ProcessEvent;
import com.sun.grizzly.websockets.WebSocketEngine;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import java.util.logging.Logger;
import javax.enterprise.event.Observes;
import javax.inject.Inject;
public class WebSocketServletProcessMonitor extends HttpServlet {
    static final Logger logger = Logger.getLogger(WebSocketEngine.WEBSOCKET);
    @Inject
    private MonitorApplication monitorApplication;
    public WebSocketServletProcessMonitor() {
        WebSocketServletProcessMonitor.logger.info("Created Process Monitor Servlet");
    }
    @Override
    public void init(ServletConfig config) throws ServletException {
        WebSocketEngine.getEngine().register(monitorApplication);
        WebSocketServletProcessMonitor.logger.info("initializing servlet");
    }
    @Override
    public void destroy() {
        WebSocketEngine.getEngine().unregister(monitorApplication);
        WebSocketServletProcessMonitor.logger.info("destroying servlet");
    }
    public synchronized void processEventListener(@Observes ProcessEvent pushEvent) {

        WebSocketServletProcessMonitor.logger.info("processEventListener");
        if(pushEvent.getRun()) {
            monitorApplication.monitorProcess();
        } else {
            monitorApplication.stopProcess();
        }
}

And our MonitorApplication.java:

package com.sample.sockets;
import com.sample.beans.ProcessEvent;
import com.sun.grizzly.tcp.Request;
import com.sun.grizzly.websockets.DefaultWebSocket;
import com.sun.grizzly.websockets.ProtocolHandler;
import com.sun.grizzly.websockets.WebSocket;
import com.sun.grizzly.websockets.WebSocketApplication;
import com.sun.grizzly.websockets.WebSocketException;
import com.sun.grizzly.websockets.WebSocketListener;
import javax.annotation.PreDestroy;
import javax.inject.Named;
import javax.ejb.Singleton;
@Named("monitorApplication")
@Singleton
public class MonitorApplication extends WebSocketApplication {
    @Override
    public WebSocket createWebSocket(ProtocolHandler protocolHandler, WebSocketListener... listeners) {
        WebSocketServletProcessMonitor.logger.info("createWebSocket");
        return new DefaultWebSocket(protocolHandler, listeners);
    }
    @Override
    public boolean isApplicationRequest(Request request) {
        WebSocketServletProcessMonitor.logger.info("isApplicationRequest");
        final String uri = request.requestURI().toString();
        return uri.endsWith("/monitor");
    }
    @Override
    public void onMessage(WebSocket socket, String text) {
        broadcast(text);
    }
    public void broadcast(String text) {
        for (WebSocket webSocket : getWebSockets()) {
            if (!webSocket.isConnected()) {
                continue;
            }
            try {
                WebSocketServletProcessMonitor.logger.info("Broadcasting : " + text + "-");
                webSocket.send(text);
            } catch (WebSocketException e) {
                remove(webSocket);
            }
        }
    }
    @PreDestroy
    public void destroy() {
        WebSocketServletProcessMonitor.logger.info("destroyMonitorApplication");
        done=true;
        if(thread != null && thread.isAlive()) try {
            thread.interrupt();
        } catch (Exception e) {
        }
    }
    private boolean done = false;
    private Thread thread = null;
    private class MonitorProcess extends Thread {
        @Override
        public void run() {
            int size = ObservedStatus.values().length;
            int status = 0;
            for (int i = 0; i < 100 && !done;) {
                try {
                    Thread.sleep(50);
                    String message = "Status: " + ObservedStatus.values()[status] + " " + i;
                    WebSocketServletProcessMonitor.logger.info("message");
                    broadcast(message);
                } catch (Exception e) {
                }
                if (i == 99) {
                    status = ++status % size;
                }
                i = (++i) % 100;
            }
            thread = null;
            done = false;
        }
    }
    public enum ObservedStatus {
        OK, WARNING, ERROR;
    }
    public synchronized void monitorProcess() {
        WebSocketServletProcessMonitor.logger.info("processEventListener");
        if (thread == null) {
            thread = new MonitorProcess();
            thread.start();
        }
    }
    public synchronized void stopProcess() {
        done = true;
    }
    public boolean isRunning() {
        return (thread != null && thread.isAlive() && !done);
    }
}

Our MonitorApplication is a server wide process that will broadcast to all the listeners the status of our process.  To do that, we made it an EJB singleton.  This will ensure when we create servlets on the fly for our incoming web connections, we have a consistent MonitorApplication, and that there will only be one thread running for monitoring our processes.

So what is our servlet doing?  Well, when a url comes in that ends in /monitor, a servlet will be created to process it.  It then registers our EJB as the WebSocket processor.  Then, when the client creates a WebSocket, the EJB will register it as a WebSocket in its list of WebSockets.  When the EJB receives a message, it will send that message to all its listeners.  We could at this time process the message, but we chose not to.  We could have listened to a message that said, "Start Monitor Process" or "End Monitor Process" to start and stop our thread that generates our messages, but I wanted to demonstrate doing that with CDI events, why?  Well, it isn't necessarily true that a client would start or stop the process, you might have some server event doing that and how would you communicate that to our MonitorApplication?  I.e. the client clicked some button that did a bunch of business logic which ended up starting or stopping the thread.  The business logic has not created a WebSocket, the client did.  So, how would you communicate that to the MonitorApplication?  Of course, you could inject the singleton ejb MonitorApplication into that class processing the business logic, but with an event listener, that class would be decoupled from the EJB and could notify any listeners to that event.  So, in the servlet we observed our cdi event ProcessEvent, and if it is fired, we pass the processEvent to our EJB so it can start or stop our thread.  Now, we aren't actually supposed to create a thread in an EJB, but because we are demonstrating the communication to a client via a WebSocket and not the monitoring of a process (the monitoring of the process is just to facilitate the discussion), we took a simplified course that works since we are using a Singleton EJB (well, it seemed simplified, but I decided to modify the code, see the bottom of this post for a proper implementation).

Our ProcessEvent.java:

package com.sample.beans;
/**
 * @author Thomas Dias
 */
public class ProcessEvent {
    private boolean run;
    public ProcessEvent(boolean run) {
        this.run = run;
    }
    public boolean getRun() {
        return run;
    }
    public void setRun(boolean run) {
        this.run = run;
    }
}

This just lets us pass a specific object that we can observe to tell us whether we should start or stop our thread.

Now we need our JSF page, index.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <title>My JSF Process Monitor</title>
        <script type="text/javascript" >
            var websocket = null;
            function startMonitor() {
                var Socket = "MozWebSocket" in window ? MozWebSocket : WebSocket;
                websocket = new Socket('ws://localhost:8080/socketSample/monitor');
                websocket.onopen = function() {
                    websocket.send('test message');
                };
                websocket.onmessage = function (evt) {
                    try {
                       document.getElementById('messages').innerHTML=evt.data;
                    } catch(exception) {
                    }
                };
                websocket.onclose = function() {
                };
                document.getElementById('startButton').disabled=true;
                document.getElementById('stopButton').disabled=false;
            }
            function stopMonitor() {
                document.getElementById('startButton').disabled=false;
                document.getElementById('stopButton').disabled=true;
                websocket.close();
                websocket = null;
            }
        </script>
    </h:head>
    <h:body>
        <h:form id="myform" prependId="false">
            <h:commandButton type="button" id="startButton" value="Start Monitor" onclick="startMonitor();" />
            <h:commandButton type="button" id="stopButton" value="End Monitor" disabled="true" onclick="stopMonitor();" />
            <h:commandButton id="startProcessButton" value="Start Process" actionListener="#{observerBean.startProcess}" >
                <f:ajax execute="startProcessButton" render="startProcessButton stopProcessButton"/>
            </h:commandButton>
            <h:commandButton id="stopProcessButton" value="Stop Process" actionListener="#{observerBean.stopProcess}" >
                <f:ajax execute="stopProcessButton" render="startProcessButton stopProcessButton"/>
            </h:commandButton>
            <br/>
            <h:outputText id="messages" value="Message Area"/>
        </h:form>
    </h:body>
</html>

Okay, I cheated and put it all in the one .xhtml file.  You really should separate out the javascript, but I left it in here for clarity.  When the start or stop monitor buttons are pressed, a web socket is established or closed.  The web socket is what will listen for any messages from the server.  When a message is received, the onMessage method will be invoked which will update the html in our messages component.  The start and stop process buttons will execute our backing bean's corresponding actionlisteners to fire the start and stop ProcessEvent. We disable and enable the monitor buttons on the client side with Javascript, we enable and disable the process buttons by asking the bean if the thread is alive.

Our JSF bean ObserverBean.java

package com.sample.beans;
import com.sample.sockets.MonitorApplication;
import java.io.Serializable;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.event.Event;
import javax.enterprise.inject.Any;
import javax.faces.event.ActionEvent;
import javax.inject.Inject;
import javax.inject.Named;
/**
 * @author Thomas Dias
 */
@Named
@RequestScoped
public class ObserverBean implements Serializable {
    @Inject
    @Any
    Event<ProcessEvent> processEvent;
    @Inject
    MonitorApplication monitorApplication;
    public ObserverBean() {
    }
    public void startProcess(ActionEvent e) {
        processEvent.fire(new ProcessEvent(true));
    }
    public void stopProcess(ActionEvent e) {
        processEvent.fire(new ProcessEvent(false));
    }
}

And that, surprisingly, is it.  We linked our application to the libraries already contained in Glassfish and we have the ability for the server to monitor any process we want and send our clients status on an as needed basis.  Multiple clients will all get the same broadcast.  We look forward to the day when WebSockets are finalized and all the vendors have implemented compatible components, but for now, we still have a completely workable solution for implementing push technology.

Oh, and finally, the application looks like:




Where the 'Status: OK 72' is a constantly changing message.

Asynchronous EJB to run a background process.
Okay, I didn't feel like I could leave the tutorial with the EJB spawning a thread.  So, we'll take a moment to revise the code and use an asynchronous EJB instead of spawning the thread.

First the EJB, we'll move the MonitorProcess to its own class and make it a stateless EJB 3.1 bean.

package com.sample.sockets;
import com.sample.sockets.MonitorApplication.ObservedStatus;
import java.util.concurrent.Future;
import javax.ejb.AsyncResult;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;
/**
 * @author Thomas Dias
 */
@Stateless
public class MonitorProcess {
    @Asynchronous
    public Future<String> monitor(MonitorApplication monitorApplication) {
        int status = 0;
        for (int i = 0; monitorApplication.isRun(); i++) {
            try {
                Thread.sleep(20);
                String message = "Status: " + ObservedStatus.values()[status] + " " + i;
                monitorApplication.broadcast(message);
            } catch (Exception e) {
            }
            if (i == 99) {
                status = ++status % ObservedStatus.values().length;
                i = 0;
            }
        }
        return new AsyncResult("done");
    }
}

Here we have an annotation @Asynchronous for the method, which will make the container spawn a thread instead of us doing it.  The return type of Future<String> will allow us to get the result, check if the process is done, tell it to stop, etc.  Although, I did pass in the MonitorApplication so it had access to the WebSockets and the process can check if it is time to stop running.

Next, we modify our MonitorApplication:

package com.sample.sockets;
import com.sun.grizzly.tcp.Request;
import com.sun.grizzly.websockets.DefaultWebSocket;
import com.sun.grizzly.websockets.ProtocolHandler;
import com.sun.grizzly.websockets.WebSocket;
import com.sun.grizzly.websockets.WebSocketApplication;
import com.sun.grizzly.websockets.WebSocketException;
import com.sun.grizzly.websockets.WebSocketListener;
import java.util.concurrent.Future;
import javax.inject.Named;
import javax.ejb.Singleton;
import javax.inject.Inject;
@Named("monitorApplication")
@Singleton
public class MonitorApplication extends WebSocketApplication {
    @Inject
    MonitorProcess monitorProcess;
    @Override
    public WebSocket createWebSocket(ProtocolHandler protocolHandler, WebSocketListener... listeners) {
        WebSocketServletProcessMonitor.logger.info("createWebSocket");
        return new DefaultWebSocket(protocolHandler, listeners);
    }
    @Override
    public boolean isApplicationRequest(Request request) {
        WebSocketServletProcessMonitor.logger.info("isApplicationRequest");
        final String uri = request.requestURI().toString();
        return uri.endsWith("/monitor");
    }
    @Override
    public void onMessage(WebSocket socket, String text) {
        broadcast(text);
    }
    public void broadcast(String text) {
        for (WebSocket webSocket : getWebSockets()) {
            if (!webSocket.isConnected()) {
                continue;
            }
            try {
                webSocket.send(text);
            } catch (WebSocketException e) {
                remove(webSocket);
            }
        }
    }
    private boolean run = true;
    Future<String> result;
    public synchronized void monitorProcess() {
        run = true;
        if (result == null || result.isDone()) {
            result = monitorProcess.monitor(this);
        }
        System.out.println("Started Process");
    }
    public synchronized void stopProcess() {
        if (result == null || result.isDone()) {
            System.out.println("No process to stop");
        } else {
            if(result.cancel(true)) {
                System.out.println("Process stopped");
            }
        }
        run = false;
        result = null;
    }
    public boolean isRun() {
        return run;
    }
    public boolean isRunning() {
        boolean running = (result != null && !result.isDone());
        return running;
    }
    public enum ObservedStatus {
        OK, WARNING, ERROR;
    }
}

When we look at it, we realize it actually isn't any harder then the first approach, so there isn't really any reason to go outside the EJB parameters and spawn our own thread. You may ask why I didn't put the @Asynchronous method in the MonitorApplication class, but there was a conflict with it being a WebSocketApplication. I want to visit several more iterations of push including JMS (the approved way prior to EJB 3.1), Spring, etc. But I will spawn that off to a separate post at the end of this tutorial. For now, we'll continue the conversation regarding JSF and Swing.


Saturday, March 3, 2012

JSF and Swing Part 2 - The Swing Soultion

Here we have our common code. Which, of course, means we have a complete decoupling from our presentation layer. Unfortunately, we will also have to worry about our framework, but we will do that later.

We have an enum for our statuses: ObservedStatus.java

package com.sample.observe;
public enum ObservedStatus {
    OK, WARNING, ERROR;
}

Typically I'd embed a status class like this in the class it relates to, but since we don't want any knowledge of the implementation, even this is pulled out.

The next class is a singleton. One of the better ways of implementing a singleton is to make it an enum: ObservableSingleton.java:

package com.sample.observe;
import java.util.HashSet;
import java.util.Set;
public enum ObservableSingleton implements ObservableInterface {
    MONITOR_PROCESS_ONE;
    public static final String NOT_RUNNING_MESSAGE = "Not Running";
    private ObservedStatus status = ObservedStatus.OK;
    private String message = NOT_RUNNING_MESSAGE;
    private Set<ObserverInterface> listeners = new HashSet<ObserverInterface>();
    private Thread thread = null;
    public void setMessage(ObservedStatus status, String message) {
        this.status = status;
        this.message = message;
        notifyListeners();
    }
    public String getMessage() {
        return message;
    }
    public ObservedStatus getStatus() {
        return status;
    }
//    The setters for the two getters are replaced with the above setMessage
//    public void setMessage(String message) ;
//    public void setStatus(ObservedStatus status) ;
    public synchronized void registerListener(ObserverInterface listener) {
        listeners.add(listener);
    }
    public synchronized void removeListener(ObserverInterface listener) {
        listeners.remove(listener);
    }
    public synchronized void notifyListeners() {
        for (ObserverInterface listener : listeners) {
            listener.updateListener(this);
        }
    }
    private boolean done = false;
    public synchronized void startProcess() {
        done = false;
        if (thread == null || !thread.isAlive()) {
            thread = new Thread() {
                @Override
                public void run() {
                    int size = ObservedStatus.values().length;
                    int status = 0;
                    for (int i = 0; i < 100 && !done;) {
                        try {
                            Thread.sleep(50);
                            setMessage(ObservedStatus.values()[status], Integer.toString(i));
                        } catch (Exception e) {
                        }
                        if(i == 99) status = ++status % size;
                        i = (++i) % 100;
                    }
                }
            };
            thread.start();
        }
    }
    public synchronized void stopProcess() {
        done = true;
        if (thread.isAlive()) {
            thread.interrupt();
        }
        thread = null;
        message = NOT_RUNNING_MESSAGE;
    }
}


Why do we need a singleton?  What if we are monitoring multiple processes?  The singleton is per process to be monitored.  So if we had a process to monitor the health of the database, a process to monitor the network status, and a process to monitor some input from the user, that would be 3 instances of an Observable, but, there would only be one instance for each of them.  In the example shown, that would be accomplised by adding values to our enum. i.e. MONITOR_PROCESS_ONE, MONITOR_DB_HEALTH, MONITOR_NETWORK, MONITOR_INPUT.  Each would have its own thread, listeners, etc.

So, as we can see, the business tier is completely decoupled from the presentation tier.  We have no knowledge of, nor care, how it has been implemented.  We have synchronized our methods.  Each method is a small fast running block of code.  The one area we need to be careful of is synchronizing our notifyListeners.  This method is calling another method beyond this classes control.  What if the method listener.updateListener is a long running process itself? Or, it waits on another process?  If we don't synchronize it, then the listener hash set could be modified while we are in the middle of processing.  A solution would be to synchronize the cloning of the listeners set, then start a thread to iterate through and notify them.  This would guarantee the observable wasn't stopped by poorly written code in the observer.  But, of course, leaving it here will improve performance and expose poorly written code, such that we'll leave it this way.

Note: to change whatever we are monitoring is a simple replacement of the start and stop process methods.

Thus completes the first iteration of our project.  Next we will do the same thing in JSF.  Then we will compare the two and transition from Swing to JSF.

Friday, March 2, 2012

JSF and Swing Part 1 - Overview

Overview
Typically, your web application runs as a n-tiered application, with the presentation tier being the web browser, the business tier as the application server, and the data tier as the database server.  A desktop application will run the presentation tier, possibly the business tier, and possibly the data tier.  To illustrate this, think of a game as a desktop application, and a web application.  There are, of course, other models, but we will focus on how we create a desktop application where the presentation tier is replaceable with a web based layer.

The Business Problem
Let us look at a common problem many business applications must solve, the Observer Design Pattern.  We have a process or business logic component that will report back to the client when some status has changed.

The Design Implications
First, we can see the need to decouple the presentation layer is a must.  In the real world, the separation is not always enforced or complete, but by adhering to a design to interface paradigm, we will achieve complete decoupling - well, almost complete, we still need the instance.  (Note: even this minor coupling will be decoupled when we move to an injection model.)

The application:
We have Start and End Monitor buttons that will initiate or stop the listening of some process that will send us messages.  We have Start and End Process buttons that will start or stop the process that will send us messages.  And we have the message area where the 'WARNING : 72' is changing based on the messages sent from the process.

The Basic Swing Solution:
We have a single frame application with a menu bar that has buttons to turn on and off the monitoring, and on and off the process we are going to monitor.  We could have used a toggle button to turn on and off the monitoring, but I chose to display distinct buttons for each function.  The process could be any process, including a remote process.  For demonstration purposes it is just a thread we start and stop with the Start and End Process buttons.

MainFrame.java

package com.sample.swing;
import com.sample.observe.ObservableInterface;
import com.sample.observe.ObservableSingleton;
import com.sample.swing.components.ObserverComponent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
public class MainFrame extends JFrame {
    JButton startMonitorButton = new JButton("Start Monitor");
    JButton endMonitorButton = new JButton("End Monitor");
    JButton startProcessButton = new JButton("Start Process");
    JButton endProcessButton = new JButton("End Process");
    ObservableInterface processToMonitor = ObservableSingleton.MONITOR_PROCESS_ONE;
    ObserverComponent status = new ObserverComponent(startMonitorButton, endMonitorButton, processToMonitor);
    private javax.swing.JPanel viewPanel;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    public MainFrame() {
        super("My Main Frame");
        initComponents();
    }
    private void initComponents() {
        startMonitorButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                MainFrame.this.startMonitorButton.setEnabled(false);
                MainFrame.this.endMonitorButton.setEnabled(true);
                processToMonitor.registerListener(MainFrame.this.status);
            }
        });
        endMonitorButton.setEnabled(false);
        endMonitorButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                MainFrame.this.startMonitorButton.setEnabled(true);
                MainFrame.this.endMonitorButton.setEnabled(false);
                processToMonitor.removeListener(MainFrame.this.status);
            }
        });
        startProcessButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                MainFrame.this.startProcessButton.setEnabled(false);
                MainFrame.this.endProcessButton.setEnabled(true);
                processToMonitor.startProcess();
            }
        });
        endProcessButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                MainFrame.this.startProcessButton.setEnabled(true);
                MainFrame.this.endProcessButton.setEnabled(false);
                processToMonitor.stopProcess();
            }
        });
        endProcessButton.setEnabled(false);
        mainPanel = new JPanel();
        mainPanel.setName("MainPanel");
        mainPanel.add(status);
        menuBar = new JMenuBar();
        menuBar.setName("menuBar");
        menuBar.add(startMonitorButton);
        menuBar.add(endMonitorButton);
        menuBar.add(startProcessButton);
        menuBar.add(endProcessButton);
        this.add(mainPanel);
        this.setJMenuBar(menuBar);
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    }
}

SampleSwingApp.java

package com.sample.swing;
import javax.swing.JFrame;
import org.jdesktop.application.SingleFrameApplication;
public class SampleSwingApp extends SingleFrameApplication {
    /**
     * At startup create and show the main frame of the application.
     */
    @Override protected void startup() {
        JFrame mainFrame = new MainFrame();
        this.setMainFrame(mainFrame);
        this.show(mainFrame);
    }
    /**
     * Main method launching the application.
     */
    public static void main(String[] args) {
        launch(SampleSwingApp.class, args);
    }
}

ObserverComponent.java

package com.sample.swing.components;
import com.sample.observe.ObservableInterface;
import com.sample.observe.ObserverInterface;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class ObserverComponent extends JLabel implements ObserverInterface {
    ObservableInterface processToMonitor;
    public ObserverComponent(ObservableInterface processToMonitor) {
        super("Invalid Status");
        this.processToMonitor = processToMonitor;
        setText(message(processToMonitor));
    }
    private String message(ObservableInterface status) {
        StringBuilder value = new StringBuilder(status.getStatus().toString());
        value.append(" : ");
        value.append(status.getMessage());
        return value.toString();
    }
    public synchronized void updateListener(ObservableInterface status) {
        final String message = message(status);
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                setText(message);
            }
        });
    }
}

The interfaces:
ObserverInterface.java

package com.sample.observe;
public interface ObserverInterface {
    void updateListener(ObservableInterface status); // called when a change has occurred on the monitored item/process
}

ObservableInterface.java

package com.sample.observe;
public interface ObservableInterface {
    public void setMessage(ObservedStatus status, String message); // sets the current status and message
    public String getMessage(); // returns a message sent with the status
    public ObservedStatus getStatus(); // returns the current status
    public void registerListener(ObserverInterface listener); // adds a listener
    public void removeListener(ObserverInterface listener); // removes a listener
    public void notifyListeners(); // notifies all listeners of a status change
    public void startProcess(); // starts the process to be monitored
    public void stopProcess(); // stops the process to be monitored
}

We can always add additional features like isProcessRunning, countObservers, etc., but here we have a basic observer/observable pattern.

Here we have our presentation layer.  Note: the only tight coupling from our presentation layer to any other layer is the assignment  processToMonitor = ObservableSingleton.MONITOR_PROCESS_ONE;.  Although this is a simple app, I chose the observer pattern to demonstrate a complex issue.  From this issue, you can see how you can decouple your entire view, no matter how complex, from the other layers.

We have 3 basic classes here.  The first class is the application SampleSwingApp, where main resides.  This simply launches the app.  The second class MainFrame sets up the view by creating a menu bar with 4 buttons, and the display panel for watching the process.  The third class ObserverComponent extends JLabel and is the component put in MainFrame's panel to report the changes coming from the monitored process.  Note: this is an event driven model, we do not pull the status of the process, we register a listener, and when a change occurs, we are notified.

There are distinct events that occur in the observer design pattern:
   1:  The process to monitor is started.
   2:  The process to monitor is stopped.
   3:  A listener or listeners are registered.
   4:  A listener is deactivated and removed from listening
   5:  Listeners are notified of status changes.

Because multiple threads are running, the order and timing of the above events are undefined.  A listener can be registered before or after a process is started.  A listener can be deactivated before, after, or during a process running.  A process can be started or stopped at any time.  And so, we need to ensure thread safety, i.e. we do not notify a listener that no longer wants to be notified, we receive a proper status, we notify all processes appropriately, etc.

The MainFrame sets up an action event for each button.  These actions register or unregister the listener, start or stop the process, and enable and disable the appropriate buttons.

The ObserverComponent simply implements the updateListener method that the Observable class will call.  Now this method has two notable items: it is not on the Swing thread, therefor, it needs to use the SwingUtilities.invokeLater.  And we don't want to be called twice whereby we update the status with the 1st status after we have updated the status with the 2nd status, therefor, we synchronize the method.