2012-02-14 99 views
12

我们目前正在将我们的一些项目从JBoss 4.x移植到JBoss 7. 到目前为止,除MBean之外,一切看起来都很好,我们通常用来提供简单的管理操作。从JBoss 4.x到JBoss端口MBean 7

我一直在寻找相当长一段时间了,但无论是我不能用正确的搜索词了正在添加的还是我失去了一些片知识的弥合的JBoss 4.x的MBean定义之间的差距和JBoss 7

因此,希望有人能对我可能丢失提供线索或者我不得不阅读(也许一些文档,示例等)

到JBoss 4.x的我们MBeans通常如下所示:

@Service(objectName = "Domain:Name=SomeMBean", 
    xmbean="resource:<path-to-xmbean.xml>") 
class SomeMBean 
{ 
    @EJB 
    private SomeService someService;  

    public String someOperation() 
    { 
    someService.doSomething(); 
    return "success"; 
    } 
} 

我们使用了@Service注释来定义对象名称和xmbean描述符,JBoss会自动注册这些mbean。

显然,在JBoss 7中,@Service注释不再存在,因此需要另一种方法。

到目前为止,我设法通过平台mbean服务器手动注册MBean,但我更喜欢JBoss自动执行该操作。另外,到目前为止,我还没有设法提供方法/参数的描述(尽管这些功能更好)。

我把问题再重复一遍为清楚:

我如何定义在JBoss中7(Java EE 6的),可提供以下功能的MBean?

  • 自动部署
  • 访问的EJB
  • 通过JConsole的或JMX-控制台(我目前使用的Dimitris安德烈亚端口)
  • 为方法提供的描述可存取/参数

更新

这是我到目前为止:

首先,我发现这个投影,使用CDI来包装被相应注解与确实在postConstruct()方法的JMX登记任何bean的喷射目标:http://code.google.com/p/jmx-annotations/。此外,搜索找到的MBean的类/属性/方法/参数注释,为注释的属性提供描述。

但是,postConstruct()方法似乎不被称为EJB(我假设这是为了不与EJB容器冲突)。因此,MBeans现在不应该是EJB,而应该是简单的CDI bean。

但是,因此,MBean不会自动实例化。为了克服这个问题,有一个singleton bean在启动时循环遍历BeanManager中的所有bean,并创建每个找到的MBean的实例。由于MBean仍然具有其注入目标,因此将不会调用其postConstruct()方法,并且该Bean将在MBean服务器中注册。

这里的启动过程的粗略概述:

  • 定制CDI扩展扫描每个CDI豆自定义@MBean注释
  • 每个elligible的MBean注入目标被包裹
  • 单身bean将开始在@PostConstruct方法中创建MBean的实例
  • MBean的注入目标的postConstruct()方法将被调用,因此MBean在MBean服务器中注册

此方法的一个缺点是执行MBean方法(任何EJB调用将在事务上下文中运行)时丢失的事务上下文。不过,如果需要的话,这可以使用CDI拦截器来修复,该拦截器将提供事务上下文。 Seam项目似乎有适当的拦截器。

我仍然不知道这是一个理智和稳定的方法,因此,任何有建设性的意见,提示等方面都更受欢迎。

回答

3
+0

我看到还有,但我不喜欢有关的做法是,我们不得不手动将登记码到每一个MBean的(我们不能使用在许多情况下,超类)。因此我们目前使用上面描述的方法。不过谢谢你的建议:) – Thomas 2012-07-06 07:47:41

+1

没有多少选择。在JBoss 7中,你以编程方式注册或使用jboss-service.xml。如果你想要交易,那么使用Singleton EJBs可能是最简单的方法。你可以移动的注册码出来的MBean并创建注册你的MBean并以类似于CDI扩展一个时尚StartupRegistrationBean。 – Chase 2012-07-08 01:45:41

1

我觉得更简洁的方式来做到这一点是使用CDI扩展。 请看一看的解决方案,我们使用:

@Documented 
@Retention(value=RUNTIME) 
@Target(value=TYPE) 
@Inherited 
public @interface MBean { 
    String value() default ""; 
} 

...

CDI扩展的这是工作代码:

public class ManagementExtension implements Extension { 

    private static Logger log = LoggerFactory 
      .getLogger(ManagementExtension.class); 

    public <T> void processInjectionTarget(@Observes ProcessInjectionTarget<T> pit) { 

     // check if the MBean annotation is present 
     AnnotatedType<T> at = pit.getAnnotatedType(); 
     if (at.isAnnotationPresent(MBean.class)) { 
      // it makes sense to register JMX interfaces only for singletons 
      if (!at.isAnnotationPresent(Singleton.class)) { 
       log.warn("Ignoring attemt to register JMX interface for a non-singleton EJB: " 
         + at.getJavaClass().getName()); 
       return; 
      } 

      try { 
       // decorate the InjectionTarget 
       InjectionTarget<T> delegate = pit.getInjectionTarget(); 
       InjectionTarget<T> wrapper = new JmxInjectionTarget<T>(delegate, getObjectName(at)); 

       // change the InjectionTarget with the decorated one 
       pit.setInjectionTarget(wrapper); 
      } catch (Exception e) { 
       log.warn("Cannot get JMX object name for: " + at.getJavaClass().getName(), e); 
      } 

     } 
    } 

    private <T> ObjectName getObjectName(AnnotatedType<T> at) throws MalformedObjectNameException { 

     String name = at.getAnnotation(MBean.class).value(); 

     if (name.isEmpty()) { 
      name = at.getJavaClass().getPackage().getName() + ":type=" 
        + at.getJavaClass().getSimpleName(); 
     } 

     return new ObjectName(name); 
    } 

    private class JmxInjectionTarget<T> implements InjectionTarget<T> { 

     private final InjectionTarget<T> d; 
     private final ObjectName objectName; 

     public JmxInjectionTarget(InjectionTarget<T> delegate, ObjectName objectName) { 
      this.d = delegate; 
      this.objectName = objectName; 
     } 
     @Override 
     public void dispose(T instance) { 
      d.dispose(instance); 
     } 

     @Override 
     public Set<InjectionPoint> getInjectionPoints() { 
      return d.getInjectionPoints(); 
     } 

     @Override 
     public T produce(CreationalContext<T> ctx) { 
      return d.produce(ctx); 
     } 

     @Override 
     public void inject(T instance, CreationalContext<T> ctx) { 
      d.inject(instance, ctx); 
      //the next piece of code better be done in postConstruct but... 
      //got no idea why but postConstruct never gets called 
      //for Singleton EJB bean 
      MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); 
      try { 
       if(mBeanServer.isRegistered(objectName)) 
       mBeanServer.unregisterMBean(objectName); 
       mBeanServer.registerMBean(instance, objectName); 
      } catch (Exception e) { 
       log.warn("Cannot register "+objectName, e); 
       return; 
      } 
      log.info("added JMX registration for: " + objectName); 
     } 

     @Override 
     public void postConstruct(T instance) { 
      d.postConstruct(instance); 
     } 

     @Override 
     public void preDestroy(T instance) { 
      d.preDestroy(instance); 
     } 

    } 
} 

然后只是@Mbean注释你的类和将自动在Mbean服务器上注册:

@Startup 
@Singleton 
@MBean("com.synapsense:type=JmxBindName") 
public class SomeService 

像一个魅力)