2012-02-06 11 views
8

A seguito di vari esempi di progettazione da documentazione primavera così come alcuni forum su Internet, il mio file contesto di applicazione si presenta come:registrazione JMX MBean utilizzando Spring in una JVM standalone

<beans> 
    <bean id="dH" class="abc.def.ghi.DH"> 
     <constructor-arg> 
      <value>0</value> 
     </constructor-arg> 
     <property name="num" value="100"/> 
    </bean> 
    <bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> 
      <property name="beans"> 
       <map> 
        <entry key="bean:name=dH1" value-ref="dH"/> 
       </map> 
      </property> 
    </bean> 
    <bean class="org.springframework.jmx.support.MBeanServerFactoryBean"/> 
</beans> 

Io corro questo senza alcun contenitore e su semplice JVM. Sono in grado di connettermi al mio processo tramite JConsole ma l'MBean non viene visualizzato. Tuttavia la registrazione del bean lo espone a livello di programmazione con successo.

MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer(); 
DH dh = new DH(0); 
mbeanServer.registerMBean(dh, new ObjectName("bean:name=dH1")); 

Ho provato a giocare con la configurazione Spring senza successo. Penso che il bean non stia registrando sul server MBean già in esecuzione accessibile da ManagementFactory.getPlatformMBeanServer(). Qualche idea sul problema?

risposta

11

Oltre a definire un MBeanServerFactory fagioli (come Nicholas notato nella loro answer) utilizzando ...

<bean class="org.springframework.jmx.support.MBeanServerFactoryBean"> 
    <property name="locateExistingServerIfPossible" value="true" /> 
</bean> 

... è necessario dire al MBeanExporter quello di gestire:

Se un bean implementa una delle interfacce di gestione JMX, MBeanExporter può semplicemente registrare l'MBean con il server tramite il processo di rilevamento automatico.

Se un bean non implementa una delle interfacce di gestione JMX, MBeanExporter creerà le informazioni di gestione utilizzando MBeanInfoAssembler fornito.

Supponendo che la classe abc.def.ghi.DH non implementa alcuna interfaccia JMX, provare a definire il vostro MBeanExporter come:

<bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> 
    <property name="assembler"> 
     <bean 
      class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler" 
     > 
      <property name="managedMethods"> 
       <list> 
        <value>getNum</value> 
       </list> 
      </property> 
     </bean> 
    </property> 
    <property name="beans"> 
     <map> 
      <entry key="bean:name=dH1" value-ref="dH"/> 
     </map> 
    </property> 
</bean> 

Guardando l'OpenJDK 7, Update 2, costruire 21 DefaultMBeanServerInterceptor.java fonte, la linea 898 crea un DynamicMBean per oggetti normali:

DynamicMBean mbean = Introspector.makeDynamicMBean(object); 

non ho il debug, ma scommetto mbeanServer.registerMBean(dh, new ObjectName("bean:name=dH1")) chiama infine DefaultMBeanServerInterceptor.registerObject(), che crea per te un DynamicMBean e registra correttamente i setter e i getter delle proprietà standard JavaBean.


Ecco alcuni file di test che funzionano con Spring Framework 3.0.5 e Oracle HotSpot Java 1.6.0_24. Dopo aver impostato la variabile di ambiente CLASSPATH, è sufficiente eseguire javac *.java e java Main e utilizzare VisualVM (o un'applicazione simile) per connettersi all'applicazione java in esecuzione per visualizzare gli MBean registrati.

ac.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" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
     http://www.springframework.org/schema/beans/spring-beans.xsd" 
    default-lazy-init="true" 
> 
    <bean id="test" class="Test" /> 
    <bean class="org.springframework.jmx.support.MBeanServerFactoryBean"> 
     <property name="locateExistingServerIfPossible" value="true" /> 
    </bean> 
    <bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> 
     <property name="assembler"> 
      <bean 
       class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler" 
      > 
       <property name="managedMethods"> 
        <list> 
         <value>getVal</value> 
         <value>setVal</value> 
        </list> 
       </property> 
      </bean> 
     </property> 
     <property name="beans"> 
      <map> 
       <entry key="bean:name=Test" value-ref="test"/> 
      </map> 
     </property> 
    </bean> 
</beans> 

Test.java:

public class Test { 
    private String val = ""; 
    public String getVal() { 
     return val; 
    } 
    public void setVal(String v) { 
     val = v; 
    } 
} 

Main.java:

import org.springframework.context.ApplicationContext; 
import org.springframework.context.support.ClassPathXmlApplicationContext; 
public class Main { 
    public static void main(final String[] args) { 
     ApplicationContext ac = new ClassPathXmlApplicationContext("ac.xml"); 
     try { 
      Thread.sleep(1000 * 60 * 5); 
     } catch (final Throwable t) {} 
    } 
} 
+0

Grazie per averlo scoperto @Dan. Quando viene caricato il contesto Spring o anche il dh viene creato utilizzando il contesto, la riga Introspector non viene nemmeno eseguita. Tuttavia, la registrazione manuale del bean chiama la stessa linea. Non penso che Spring stia cercando di registrare il bean con queste configurazioni. Manca qualcosa ... –

+0

Questo funziona per me usando Spring 3.0.5 e un semplice JavaBean con un getter/setter di proprietà; Posso collegarmi alla mia semplice app di test con VisualVM e vedere l'MBean di test che è stato registrato utilizzando la definizione di bean 'MBeanExporter' che ho fornito. Prova a suddividere il tuo scenario in un semplice modulo, fallo funzionare, quindi ricostruisci quello che hai attualmente e vedi dove si trova il tuo problema. –

+0

Utilizzo di Spring 3.1.0 Ho provato con il tuo XML fornito con e senza -Dcom.sun.management.jmxremote come opzione di programma, ancora senza fortuna. Sto caricando il contesto nel modo seguente: BeanFactory factory = new XmlBeanFactory (new ClassPathResource ("/ application-context.xml")); e quindi caricando l'MBean desiderato come: factory.getBean (DH.class); So che questo suona ingenuo, ma c'è un modo in cui possiamo abbinare i nostri XML completi e la semplice struttura del programma? –

2

Il problema riguarda MBeanServerFactoryBean.

Dal javadoc:

Per impostazione predefinita, MBeanServerFactoryBean sarà sempre creare una nuova MBeanServer anche se uno è già in esecuzione. Per fare in modo che MBeanServerFactoryBean tenti di individuare prima un MBeanServer in esecuzione, imposta il valore della proprietà "locateExistingServerIfPossible" su "true".

Prova questo config:

<bean class="org.springframework.jmx.support.MBeanServerFactoryBean"> 
    <property name="locateExistingServerIfPossible" value="true" /> 
</bean> 

================================ =================

provare a specificare il MBeanServer nel bean esportatore:

<bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> 
    <property name="beans"> 
     <map> 
       <entry key="bean:name=dH1" value-ref="dH" /> 
      </map> 
     </property> 
     <property name="server" ref="MBeanServer" /> 
</bean> 
<bean id="MBeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean"> 
    <property name="locateExistingServerIfPossible" value="true" /> 
</bean> 

=========== ================================= ============================

Ok, diamo l'approccio forza bruta e acquisire la piattaforma MBeanServer direttamente:

<bean class="org.springframework.jmx.export.MBeanExporter" lazy-init="false"> 
    <property name="beans"> 
     <map> 
       <entry key="bean:name=dH1" value-ref="dH" /> 
      </map> 
     </property> 
     <property name="server"> 
      <bean id="MBeanServer" class="java.lang.management.ManagementFactory" factory-method="getPlatformMBeanServer"/> 
     </property> 
</bean> 
+0

già provato @Nicholas. Ho provato anche senza fortuna .. –

+0

non ho avuto fortuna anche con questo .. –

+0

Grazie per gli altri suggerimenti @Nicholas. Sebbene provarli entrambi non hanno registrato anche gli MBean. –

Problemi correlati