[jboss-user] [Microcontainer] - How to emulate ServiceMBeanSupport using AOP

genman do-not-reply at jboss.com
Thu Jul 26 02:32:27 EDT 2007


I got this to work, it's pretty slick actually... Thanks Ales.

Service.java :

  | /**
  |  * Interface defines the basic operations for a service.
  |  */
  | public interface Service {
  | 	
  | 	/**
  | 	 * Possible states for a service.
  | 	 */
  | 	enum State {
  | 		/**
  | 		 * Initial state; no lifecycle methods called.
  | 		 */
  | 		INITIAL,
  | 		/**
  | 		 * Created state; dependencies not ready.
  | 		 */
  | 		CREATED,
  | 		/**
  | 		 * Started state; dependencies in started state.
  | 		 */
  | 		STARTED,
  | 		/**
  | 		 * Stopped state; dependencies also stopped.
  | 		 */
  | 		STOPPED,
  | 		/**
  | 		 * Destroyed state.
  | 		 */
  | 		DESTROYED
  | 	}
  | 	
  | 	/**
  | 	 * Starts the service
  | 	 * @throws Exception if this lifecycle method failed
  | 	 */
  | 	public void start() throws Exception;
  | 	
  | 	/**
  | 	 * Starts the service
  | 	 * @throws Exception if this lifecycle method failed
  | 	 */
  | 	public void stop() throws Exception;
  | 	
  | 	/**
  | 	 * Creates the service
  | 	 * @throws Exception if this lifecycle method failed
  | 	 */
  | 	public void create() throws Exception;
  | 	
  | 	/**
  | 	 * Destroys the service
  | 	 * @throws Exception if this lifecycle method failed
  | 	 */
  | 	public void destroy() throws Exception;
  | 	
  | 	/**
  | 	 * Returns the service state; or null if not known.
  | 	 */
  | 	public State getState();
  | 	
  | 	/**
  | 	 * Returns the service name; or null if not known.
  | 	 */
  | 	public String getName();
  | }
  | 

LifecycleInterceptor.java:

  | public class LifecycleInterceptor {
  | 
  | 	private Log log = LogFactory.getLog(getClass());
  | 
  | 	private Kernel kernel;
  | 	
  | 	/**
  | 	 * Maps the service method names to controller states.
  | 	 */
  | 	private enum Methods {
  | 		
  | 		start(ControllerState.INSTALLED),
  | 		stop(ControllerState.CREATE),
  | 		create(ControllerState.CREATE),
  | 		destroy(ControllerState.INSTANTIATED);
  | 
  | 		private ControllerState cs;
  | 		
  | 		Methods(ControllerState cs) {
  | 			this.cs = cs;
  | 		}
  | 		
  | 		public ControllerState getState() {
  | 			return cs;
  | 		}
  | 	};
  | 
  | 	private boolean calledByKernel() {
  | 		// The following detects if the kernel is calling us 
  | 		StackTraceElement[] sta = Thread.currentThread().getStackTrace();
  | 		for (StackTraceElement se : sta) {
  | 			String c = se.getClassName();
  | 			if (c.startsWith("org.jboss.kernel"))
  | 				return true;
  | 		}		
  | 		return false;
  | 	}
  | 	
  | 	/**
  | 	 * Determines the controller context, by method name chooses
  | 	 * and sets new controller state in the kernel.
  | 	 * 
  | 	 * If called by the kernel, returns.
  | 	 * 
  | 	 * @param inv method invocation
  | 	 */
  | 	public Object handle(Invocation inv) throws Throwable {
  | 		Service target = (Service) inv.getTargetObject();
  | 		
  | 		if (calledByKernel())
  | 			return inv.invokeNext();
  | 		
  | 		KernelController controller = kernel.getController();
  | 		ControllerContext context;
  | 		MethodInvocation minv = (MethodInvocation)inv;
  | 		String mname = minv.getMethod().getName();
  | 		context = kernel.getController().getContext(target.getName(), null);
  | 		if (context == null) {
  | 			log.debug("service not installed " + target.getName());
  | 			return inv.invokeNext();
  | 		}
  | 
  | 		// We assume the method call is a lifecycle method (by configuration)
  | 		ControllerState state = Methods.valueOf(mname).getState();
  | 		log.debug("controller change " + target.getName() + " to " + state.getStateString() + " for " + mname + "()");
  | 		controller.change(context, state);
  | 		return null;
  | 	}
  | 
  | 	/**
  | 	 * Returns kernel.
  | 	 */
  | 	public Kernel getKernel() {
  | 		return kernel;
  | 	}
  | 
  | 	/**
  | 	 * Sets kernel.
  | 	 */
  | 	public void setKernel(Kernel kernel) {
  | 		this.kernel = kernel;
  | 	}
  | 
  | }
  | 

-beans.xml declaration:


  |    <aop:aspect xmlns:aop="urn:jboss:aop-beans:1.0"
  |                name="LifecycleAdvice"
  |                class="LifecycleInterceptor"
  |                method="handle"
  |                pointcut="execution(public void com.autodesk.lbs.service.Service->*())">
  |     <property name="kernel">
  |       <inject bean="jboss.kernel:service=Kernel" />
  |     </property>
  |     <depends>LifecycleCallback</depends>
  |    </aop:aspect>
  | 

One weakness is that the Name has to be stored in the target, there's no way, given a Service to find its name in the Microcontainer. (That I know of.)

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4067683#4067683

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4067683



More information about the jboss-user mailing list