2012-02-14 17 views
12

siamo attualmente in fase di porting di alcuni dei nostri progetti da JBoss 4.x a JBoss 7. Finora tutto sembra funzionare bene, tranne che per i nostri MBean, che ci stiamo comunemente usando per fornire semplici operazioni di gestione.Port MBean da JBoss 4.x a JBoss 7

Ho cercato per un po 'di tempo, ma o non sono in grado di raggiungere il termine di ricerca corretto o mi manca una parte di conoscenza per colmare il divario tra la definizione di MBean in JBoss 4.x e JBoss 7.

Così, si spera che qualcuno in grado di fornire un suggerimento su quello che potrebbe essere mancante o dove avrei dovuto leggere (magari un po 'di documentazione, esempi, ecc)

in JBoss 4.x nostro Gli MBean hanno spesso questo aspetto:

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

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

Abbiamo usato ilAnnotazioneper definire il nome dell'oggetto e il descrittore xmbean e JBoss registrerebbe automaticamente tali mbeans.

Apparentemente, in JBoss 7 l'annotazione @Service non esiste più e quindi è necessario un altro approccio.

Finora, sono riuscito a registrare l'MBean manualmente con il server della piattaforma mbean, ma preferirei che JBoss lo facesse automaticamente. Inoltre, non sono riuscito a fornire descrizioni per i metodi/parametri finora (anche se sono più di una caratteristica piacevole).

io ripeto la domanda per chiarezza:

Come dovrei definire un MBean in JBoss 7 (Java EE 6), che fornisce le seguenti funzionalità?

  • distribuzione automatica
  • accesso a EJB
  • accessibile attraverso JConsole o JMX-Console (Attualmente sto usando la porta Dimitris Andreadis')
  • fornire descrizioni per i metodi/parametri

Aggiornamento

Ecco cosa ho ottenuto finora:

Innanzitutto, ho trovato questa proiezione, che utilizza CDI per avvolgere l'obiettivo di iniezione di qualsiasi bean annotato di conseguenza e fa la registrazione JMX nel metodo postConstruct(): http://code.google.com/p/jmx-annotations/. Inoltre, gli MBean trovati vengono scansionati per annotazioni classe/attributo/metodo/parametro che forniscono una descrizione per la proprietà annotata.

Tuttavia, il metodo postConstruct() non sembra essere chiamato per EJB (presumo che sia per non entrare in conflitto con il contenitore EJB). Quindi gli MBean ora non dovrebbero essere EJB ma semplici fagioli CDI.

Pertanto, ha lo svantaggio che gli MBean non vengono automaticamente istanziati. Per ovviare a questo, c'è un bean singleton che all'avvio esegue il ciclo di tutti i bean nello BeanManager e crea un'istanza di ogni MBean trovato. Poiché gli MBean hanno ancora il proprio target di iniezione, il suo metodo postConstruct() non verrà chiamato e il bean verrà registrato nel server MBean.

Ecco un quadro di massima della procedura di avvio:

  • un'estensione CDI personalizzato esegue la scansione di ciascun bean CDI per l'annotazione @MBean personalizzato
  • per ogni MBean elligible l'obiettivo di iniezione è avvolto
  • un Singleton verrà avviato bean che nel suo metodo @PostConstruct creerà istanze degli MBeans
  • verrà chiamato il metodo postConstruct() del target di iniezione dell'MBean e quindi l'MBean è registrato nel server MBean

Uno svantaggio di questo metodo sarebbe il contesto di transazione mancante durante l'esecuzione dei metodi MBean (tutte le chiamate EJB verranno eseguite in un contesto di transazione). Tuttavia, questo potrebbe essere risolto utilizzando un intercettore CDI che fornirà il contesto della transazione, se necessario. Il progetto Seam sembra avere intercettori appropriati per questo.

Non sono ancora sicuro se questo è un approccio sano e stabile, quindi qualsiasi commento costruttivo, suggerimenti ecc. Sono più che benvenuti.

risposta

3
+0

Ho visto anche questo, ma quello che non mi piace di questo approccio è che dovremmo inserire manualmente il codice di registrazione in ogni MBean (in molti casi non possiamo usare le super classi). Quindi attualmente utilizziamo il metodo che ho descritto sopra. Tuttavia, grazie per il suggerimento :) – Thomas

+1

Non ci sono molte opzioni. In JBoss 7 registri o usi programmaticamente jboss-service.xml. Se si desidera effettuare transazioni, l'uso dei bean EJB Singleton sarà probabilmente l'approccio più semplice. Puoi spostare il codice di registrazione dal mbeans e creare un StartupRegistrationBean che registra tutti gli mbeans in modo simile a quell'estensione CDI. – Chase

1

Penso che un modo più conciso per farlo è usare l'estensione CDI. prega di dare un'occhiata alla soluzione usiamo:

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

...

Questo codice sta lavorando di estensione 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); 
     } 

    } 
} 

Poi basta contrassegnare la classe da annotazioni e @Mbean sarà registrato automaticamente nel server Mbean:

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

Funziona come un charm)