Créez et déployez des MBeans pour gérer les services à l’aide de la console JMX. Exposez les attributs et les opérations de service pour permettre l’exécution des tâches d’administration.
Pour plus d’informations sur l’utilisation de la console JMX, voir Surveillance des ressources du serveur à l’aide de la console JMX.
Sur la plateforme Apache Felix, vous déployez MBeans en tant que services OSGi. Lorsqu’un service MBean est enregistré dans le registre de service OSGi, le module Aries JMX Whiteboard enregistre automatiquement le MBean avec le serveur MBean. Le MBean est alors disponible pour la console JMX qui expose les attributs et opérations publics.
Les MBeans que vous créez pour gérer les ressources CQ5 ou CRX sont basés sur l’interface javax.management.DynamicMBean. Pour les créer, vous devez suivre les modèles de conception habituels, comme indiqué dans la spécification JMX :
En plus de configurer l’interface de gestion, l’interface paramètre également l’interface de service OSGi. La classe d’implémentation met en oeuvre le service OSGi.
Le package module com.adobe.granite.jmx.annotation offre plusieurs annotations et classes pour fournir facilement des métadonnées MBean à la console JMX. Utilisez ces annotations et classes au lieu d’ajouter des informations directement à l’objet MBeanInfo du MBean.
Annotations
Ajoutez des annotations à l’interface de gestion pour spécifier les métadonnées MBean. Les informations apparaissent dans la console JMX pour chaque classe d’implémentation déployée. Les annotations suivantes sont disponibles (pour plus d’informations, voir la section com.adobe.granite.jmx.annotation JavaDocs) :
Description : fournit une description de la classe ou de la méthode MBean. Lorsqu’elle est utilisée dans la déclaration de classe, la description est visible dans la page de la console JMX pour le MBean. Lorsqu’elle est utilisée sur une méthode, la description s’affiche sous forme de texte de survol pour l’attribut ou l’opération correspondant.
Impact : répercussions d’une méthode. Les valeurs de paramètre valides sont les champs définis par javax.management.MBeanOperationInfo.
Nom : spécifie le nom à afficher pour un paramètre d’opération. Utilisez cette annotation pour remplacer le nom réel du paramètre de méthode utilisé dans l’interface.
OpenTypeInfo : spécifie la classe à utiliser pour représenter les données composites ou les données tabulaires dans la console JMX. Utilisation avec les MBeans ouverts
TabularTypeInfo: Utilisé pour annoter la classe utilisée pour représenter les données tabulaires.
Classes
Les classes sont fournies pour la création de MBeans dynamiques qui utilisent les annotations que vous ajoutez à leurs interfaces :
En règle générale, le MBean reflète le service OSGi que vous souhaitez gérer. Sur la plateforme Felix, vous créez le MBean comme vous le feriez pour le déploiement sur d’autres plates-formes de serveur Java. La principale différence réside dans le fait que vous pouvez utiliser des annotations pour spécifier les informations MBean :
L’exemple suivant MBean fournit des informations sur le référentiel CRX. L’interface utilise l’annotation Description pour fournir des informations à la console JMX.
package com.adobe.example.myapp;
import com.adobe.granite.jmx.annotation.Description;
@Description("Example MBean that exposes repository properties.")
public interface ExampleMBean {
@Description("The name of the repository.")
String getRepositoryName();
@Description("The vendor of the repository.")
String getRepositoryVendor();
@Description("The URL of repository vendor.")
String getVendorUrl();
}
La classe d’implémentation utilise le service SlingRepository pour récupérer des informations sur le référentiel CRX.
package com.adobe.example.myapp;
import org.apache.felix.scr.annotations.*;
import org.apache.sling.jcr.api.SlingRepository;
import com.adobe.granite.jmx.annotation.AnnotatedStandardMBean;
import javax.management.*;
public class ExampleMBeanImpl extends AnnotatedStandardMBean implements ExampleMBean {
@Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY)
private SlingRepository repository;
public ExampleMBeanImpl() throws NotCompliantMBeanException {
super(ExampleMBean.class);
}
public String getRepositoryName() {
return repository.getDescriptor("jcr.repository.name");
}
public String getRepositoryVendor() {
return repository.getDescriptor("jcr.repository.vendor");
}
public String getVendorUrl() {
return repository.getDescriptor("jcr.repository.vendor.url");
}
}
Le graphique suivant montre la page de ce MBean dans la console JMX.
Lorsque vous enregistrez des MBeans en tant que service OSGi, ils sont automatiquement enregistrés avec le serveur MBean. Pour installer un MBean sur CQ5, incluez-le dans un lot et exportez le service MBean comme vous le feriez pour tout autre service OSGi.
Outre les métadonnées liées à OSGi, vous devez également fournir les métadonnées requises par le module Aries JMX Whiteboard pour enregistrer le MBean auprès du serveur MBean :
Nom de l’interface DynamicMBean : déclarez que le service MBean implémente l’interface javax.management.DynamicMBea
n. Cette déclaration indique au module Aries JMX Whiteboard que le service est un service MBean.
Propriétés du domaine et de la clé MBean : sur Felix, cette information est entrée en tant que propriété du service OSGi du MBean. Il s’agit des informations similaires à celles que vous fournissez habituellement au serveur MBean dans un objet javax.management.ObjectName
.
Lorsque votre MBean reflète un service unique, une seule instance du service MBean est requise. Dans ce cas, si vous utilisez le module externe Felix SCR Maven, vous pouvez utiliser les annotations SCR (Apache Felix Service Component Runtime) sur la classe d’implémentation MBean pour spécifier les métadonnées associées à JMX. Pour instancier plusieurs instances MBean, vous pouvez créer une autre classe qui effectue cet enregistrement du service OSGi du MBean. Dans ce cas, les métadonnées liées à JMX sont générées au moment de l’exécution.
MBean unique
Les MBeans pour lesquels vous pouvez définir tous les attributs et toutes les opérations au moment de la conception peuvent être déployés à l’aide d’annotations SCR dans la classe d’implémentation MBean. Dans l’exemple suivant, l’attribut value
de l’annotation Service
déclare que le service implémente l’interface DynamicMBean
. L’attribut name
de l’annotation Property
spécifie les propriétés de domaine et de clé JMX.
package com.adobe.example.myapp;
import org.apache.felix.scr.annotations.*;
import org.apache.sling.jcr.api.SlingRepository;
import com.adobe.granite.jmx.annotation.AnnotatedStandardMBean;
import javax.management.*;
@Component(immediate = true)
@Property(name = "jmx.objectname", value="com.adobe.example:type=CRX")
@Service(value = DynamicMBean.class)
public class ExampleMBeanImpl extends AnnotatedStandardMBean implements ExampleMBean {
@Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY)
private SlingRepository repository;
public ExampleMBeanImpl() throws NotCompliantMBeanException {
super(ExampleMBean.class);
}
public String getRepositoryName() {
return repository.getDescriptor("jcr.repository.name");
}
public String getRepositoryVendor() {
return repository.getDescriptor("jcr.repository.vendor");
}
public String getVendorUrl() {
return repository.getDescriptor("jcr.repository.vendor.url");
}
}
Plusieurs instances de service MBean
Pour gérer plusieurs instances d’un service géré, il convient de créer plusieurs instances du service MBean correspondant. En outre, les instances de service MBean doivent être créées ou supprimées lorsque des instances gérées sont démarrées ou arrêtées. Vous pouvez créer une classe de gestionnaire MBean pour instancier les services MBean à l’exécution et gérer le cycle de vie du service.
Utilisez BundleContext pour enregistrer le MBean en tant que service OSGi. Incluez les informations relatives à JMX dans l’objet Dictionary que vous utilisez comme argument de la méthode BundleContext.registerService .
Dans l’exemple de code suivant, le service ExampleMBean est enregistré par programmation. L’objet componentContext est ComponentContext, qui permet d’accéder à BundleContext.
Dictionary mbeanProps = new Hashtable();
mbeanProps.put("jmx.objectname", "com.adobe.example:type=CRX");
ExampleMBeanImpl mbean = new ExampleMBeanImpl();
ServiceRegistration serviceregistration =
componentContext.getBundleContext().registerService(DynamicMBean.class.getName(), mbean, mbeanProps);
L’exemple de MBean de la section suivante fournit des détails supplémentaires.
Un gestionnaire de service MBean est utile si les configurations de service sont stockées dans le référentiel. Le gestionnaire peut récupérer les informations de service et les utiliser pour configurer et créer le MBean correspondant. La classe manager peut également écouter les événements de modification du référentiel et mettre à jour les services MBean en conséquence.
Le MBean de cet exemple fournit des informations sur les modèles de processus CQ5 stockés dans le référentiel. Une classe de gestionnaire MBean crée des MBeans basés sur des modèles de processus stockés dans le référentiel et qui enregistrent leur service OSGi au moment de l’exécution. Cet exemple consiste en un seul lot contenant les membres suivants :
Remarque : par souci de simplicité, le code de cet exemple n’effectue pas de journalisation ou ne réagit pas aux exceptions levées.
WorkflowMBeanManagerImpl inclut une méthode d’activation de composant. Lorsque le composant est activé, la méthode effectue les tâches suivantes :
Les métadonnées MBean s’affichent dans la console JMX avec le domaine com.adobe.example , le type workflow_model et Propriétés est le chemin d’accès du noeud de configuration du modèle de workflow.
Cet exemple nécessite une interface MBean et une implémentation qui se reflète sur l’interface com.day.cq.workflow.model.WorkflowModel
. Le MBean est très simple. Ainsi, l’exemple peut se concentrer sur les aspects de configuration et de déploiement de la conception. Le MBean expose un seul attribut, le nom du modèle.
package com.adobe.example.myapp.api;
import com.adobe.granite.jmx.annotation.Description;
@Description("Example MBean that exposes Workflow model properties.")
public interface WorkflowMBean {
@Description("The name of the Workflow model.")
String getModelName();
}
package com.adobe.example.myapp.impl;
import javax.management.NotCompliantMBeanException;
import com.day.cq.workflow.model.WorkflowModel;
import com.adobe.example.myapp.api.WorkflowMBean;
import com.adobe.granite.jmx.annotation.AnnotatedStandardMBean;
public class WorkflowMBeanImpl extends AnnotatedStandardMBean implements WorkflowMBean {
WorkflowModel model;
protected WorkflowMBeanImpl(WorkflowModel inmodel)
throws NotCompliantMBeanException {
super(WorkflowMBean.class);
model=inmodel;
}
public String getModelName() {
return model.getTitle();
}
}
Le service WorkflowMBeanManager inclut la méthode d’activation du composant qui crée les services WorkflowMBean. La mise en oeuvre du service comprend les méthodes suivantes :
L’implémentation WorkflowMBeanManager crée uniquement des services MBean pour les configurations de modèle qui existent une fois le composant activé. Une implémentation plus robuste écoute les événements du référentiel concernant les nouvelles configurations de modèle et les modifications ou suppressions de la configuration de modèle existante. Lorsqu’une modification se produit, le gestionnaire peut créer, modifier ou supprimer le service WorkflowMBean correspondant.
package com.adobe.example.myapp.api;
public interface WorkflowMBeanManager {
}
package com.adobe.example.myapp.impl;
import java.util.*;
import org.apache.felix.scr.annotations.*;
import javax.jcr.Session;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.management.ObjectName;
import org.apache.sling.jcr.api.SlingRepository;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.day.cq.workflow.WorkflowService;
import com.day.cq.workflow.WorkflowSession;
import com.adobe.example.myapp.api.WorkflowMBean;
import com.adobe.example.myapp.api.WorkflowMBeanManager;
/**Instantiates and registers WorkflowMBean services */
@Component(immediate=true)
@Service(value=WorkflowMBeanManager.class)
public class WorkflowMBeanManagerImpl implements WorkflowMBeanManager {
//The ComponentContext provides access to the BundleContext
private ComponentContext componentContext;
//Use the SlingRepository service to read model nodes
@Reference
private SlingRepository repository = null;
//Use the WorkflowService service to create WorkflowModel objects
@Reference
private WorkflowService workflowservice = null;
private Session session;
//Details about model nodes
private static final String MODEL_ROOT ="/etc/workflow/models";
private static final String MODEL_NODE = "model";
private Set<String> modelIds = new HashSet<String>();
//Storage for ServiceRegistrations for MBean services
private Collection<ServiceRegistration> mbeanRegistrations= new Vector<ServiceRegistration>(0,1);
@Activate
protected void activate(ComponentContext ctx) {
//Traverse the repository and load the model nodes
try {
session = repository.loginAdministrative(null);
// load and store model node paths
if (session.nodeExists(MODEL_ROOT)) {
getModelIds(session.getNode(MODEL_ROOT));
}
//Create MBeans for each model
for(String modid: modelIds){
makeMBean(modid);
}
}catch(Exception e){ }
}
/**
* Add JMX domain and key properties to a collection
* Instantiate a WorkflowModel and its WorkflowMBeanImpl object
* Register the MBean OSGi service
*/
private void makeMBean(String modelId) {
// create MBean for the model
try {
Dictionary<String, String> mbeanProps = new Hashtable<String, String>();
//These properties appear on the JMX Console home page
mbeanProps.put("jmx.objectname", "com.adobe.example:type=workflow_model,id=" + ObjectName.quote(modelId));
WorkflowSession wfsession = workflowservice.getWorkflowSession(session);
WorkflowMBeanImpl mbean = new WorkflowMBeanImpl(wfsession.getModel(modelId));
ServiceRegistration serviceregistration = componentContext.getBundleContext().registerService(WorkflowMBean.class.getName(), mbean, mbeanProps);
//Store the ServiceRegistration objects for deactivation
mbeanRegistrations.add(serviceregistration);
} catch (Throwable t) {}
}
/**
* Traverses the repository branch below a given Node. Stores the path of each model node.
*/
private void getModelIds(Node node) throws RepositoryException {
try{
NodeIterator iter = node.getNodes();
while (iter.hasNext()) {
Node n = iter.nextNode();
//Look for "jcr:content" nodes
if (n.getName().equals("jcr:content")) {
//get the path of the model node and save it
if(n.hasNode(MODEL_NODE)){
modelIds.add(n.getNode(MODEL_NODE).getPath());
}
} else{
//Scan child nodes
getModelIds(n);
}
}
}catch(Exception e){ }
}
/**
* Log out of the JCR session and unregister WorkflowMBean services
*/
@Deactivate
protected void deactivate() {
session.logout();
session=null;
for(ServiceRegistration sr:mbeanRegistrations){
sr.unregister();
}
}
}
Par souci de commodité, nous proposons de copier et de coller le code XML suivant dans le fichier pom.xml de votre projet pour créer le bundle de composants. Le POM fait référence à plusieurs dépendances et modules externes requis.
Modules externes:
Remarque : au moment de la rédaction de ce document, le module externe maven scr n’est pas compatible avec le module externe m2e pour Eclipse. (Voir Bogue Felix 3170.) Pour utiliser l’IDE Eclipse, installez Maven et utilisez l’interface de ligne de commande pour créer des versions.
<project xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.adobe.example.myapp</groupId>
<artifactId>workflow-mbean</artifactId>
<version>0.0.2-SNAPSHOT</version>
<name>mbean-simple</name>
<url>www.adobe.com</url>
<description>A simple MBean</description>
<packaging>bundle</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.7.2</version>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>1.4.3</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>com.adobe.example.myapp.*;version=${project.version}</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
<version>1.6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.api</artifactId>
<version>2.0.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr</artifactId>
<version>1.6.1-R1236132</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.jcr.api</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>com.adobe.granite</groupId>
<artifactId>com.adobe.granite.jmx</artifactId>
<version>0.1.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.day.cq.wcm</groupId>
<artifactId>cq-wcm-mobile-api</artifactId>
<version>5.5.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.day.cq.workflow</groupId>
<artifactId>cq-workflow-api</artifactId>
<version>5.5.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.jcr</groupId>
<artifactId>jcr</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Ajoutez le profil suivant à votre fichier de paramètres Maven pour utiliser le référentiel public Adobe.
<profile>
<id>adobe-public</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<releaseRepository-Id>adobe-public-releases</releaseRepository-Id>
<releaseRepository-Name>Adobe Public Releases</releaseRepository-Name>
<releaseRepository-URL>https://repo1.maven.org/maven2/com/adobe/</releaseRepository-URL>
</properties>
<repositories>
<repository>
<id>adobe-public-releases</id>
<name>Adobe Public Repository</name>
<url>https://repo1.maven.org/maven2/com/adobe/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>adobe-public-releases</id>
<name>Adobe Public Repository</name>
<url>https://repo1.maven.org/maven2/com/adobe/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>