I actually need to write a little daemon based on the JVM (I’ll explain why in a future post). As the groovy fan I am, I was looking for a ready to use receipt, this one is interesting but show only how to write, not to read 🙂 After getting some help from Guillaume here a working sample:
In my previous post, I demonstrate how to set a property for each http-service in a glassfish domain using groovy and jmx. Here the code to create a new JDBC Connection Pool, still using groovy and JMX/AMX APIs.
importjavax.management.ObjectNameimportjavax.management.remote.JMXConnectorFactoryas JmxFactory
importjavax.management.remote.JMXServiceURLas JmxUrl
importjavax.management.MBeanServerConnection//def uri = 'service:jmx:rmi:///jndi/rmi://portal3:46302/jmxrmi'def uri ='service:jmx:rmi:///jndi/rmi://localhost:8686/jmxrmi'def login ='admin'def password ='adminadmin'importjavax.management.Querydef jmxurl =new JmxUrl(uri)def attributes =newHashtable()def buffer =[ login, password ]
attributes.put("jmx.remote.credentials", (String[]) buffer)def server = JmxFactory.connect(jmxurl, attributes).mBeanServerConnectiondef createJDBCConnectionPool ={ name ->def objectname =new ObjectName("amx:j2eeType=X-DomainConfig,name=na")def options =newArrayList()
options.add(name)
options.add("com.mysql.jdbc.jdbc2.optional.MysqlDataSource")def properties =['ResType':'javax.sql.DataSource']
options.add(properties asMap)
server.invoke(objectname,
"createJDBCConnectionPoolConfig",
options asObject[],
["java.lang.String","java.lang.String","java.util.Map"]asString[])/* To add other properties, we need to invoke setProperty to new object */
objectname =new ObjectName("amx:j2eeType=X-JDBCConnectionPoolConfig,name="+ name)
server.invoke(objectname, "setPropertyValue", ["user", "xwiki"]asObject[], ["java.lang.String", "java.lang.String"]asString[])
server.invoke(objectname, "setPropertyValue", ["password", "xwiki"]asObject[], ["java.lang.String", "java.lang.String"]asString[])
server.invoke(objectname, "setPropertyValue", ["databaseName", "xwiki"]asObject[], ["java.lang.String", "java.lang.String"]asString[])
server.invoke(objectname, "setPropertyValue", ["serverName", "localhost"]asObject[], ["java.lang.String", "java.lang.String"]asString[])
server.invoke(objectname, "setPropertyValue", ["port", "3306"]asObject[], ["java.lang.String", "java.lang.String"]asString[])
server.invoke(objectname, "setPropertyValue", ["networkProtocol", "tcp"]asObject[], ["java.lang.String", "java.lang.String"]asString[])}
createJDBCConnectionPool("xwikiPool")
import javax.management.ObjectName
import javax.management.remote.JMXConnectorFactory as JmxFactory
import javax.management.remote.JMXServiceURL as JmxUrl
import javax.management.MBeanServerConnection
//def uri = 'service:jmx:rmi:///jndi/rmi://portal3:46302/jmxrmi'
def uri = 'service:jmx:rmi:///jndi/rmi://localhost:8686/jmxrmi'
def login = 'admin'
def password = 'adminadmin'
import javax.management.Query
def jmxurl = new JmxUrl(uri)
def attributes = new Hashtable()
def buffer = [ login, password ]
attributes.put("jmx.remote.credentials", (String[]) buffer)
def server = JmxFactory.connect(jmxurl, attributes).mBeanServerConnection
def createJDBCConnectionPool = { name ->
def objectname = new ObjectName("amx:j2eeType=X-DomainConfig,name=na")
def options = new ArrayList()
options.add(name)
options.add("com.mysql.jdbc.jdbc2.optional.MysqlDataSource")
def properties = [
'ResType':'javax.sql.DataSource'
]
options.add(properties as Map)
server.invoke(objectname,
"createJDBCConnectionPoolConfig",
options as Object[],
["java.lang.String","java.lang.String","java.util.Map"] as String[] )
/* To add other properties, we need to invoke setProperty to new object */
objectname = new ObjectName("amx:j2eeType=X-JDBCConnectionPoolConfig,name=" + name)
server.invoke(objectname, "setPropertyValue", [ "user", "xwiki"] as Object[], [ "java.lang.String", "java.lang.String"] as String[])
server.invoke(objectname, "setPropertyValue", [ "password", "xwiki"] as Object[], [ "java.lang.String", "java.lang.String"] as String[])
server.invoke(objectname, "setPropertyValue", [ "databaseName", "xwiki"] as Object[], [ "java.lang.String", "java.lang.String"] as String[])
server.invoke(objectname, "setPropertyValue", [ "serverName", "localhost"] as Object[], [ "java.lang.String", "java.lang.String"] as String[])
server.invoke(objectname, "setPropertyValue", [ "port", "3306"] as Object[], [ "java.lang.String", "java.lang.String"] as String[])
server.invoke(objectname, "setPropertyValue", [ "networkProtocol", "tcp"] as Object[], [ "java.lang.String", "java.lang.String"] as String[])
}
createJDBCConnectionPool("xwikiPool")
As you probably noticed, I can’t create properties directly using the invokation of createJDBCConnectionPool. Indeed, we can specifly only few properties (take a look at the complete list). However, once the object is created, we can use the setPropertValue to create any properties we want.
At my new work, we have a lot of glassfish in production. For some of them, we even have almost 10 instances per DAS (Domain Admin Server). As a (good) system administrator, I’m a lazy man. After having to installed and created a glassfish with 10 instances, I was really tired to click, click, and click again through the web interface. Yes I know, it’s possible to edit the files directly, but I think it’s not very convenient. First, it’s easy to make mistakes, it’s not atomic, and finally you need to restart/reload the instance.
So, I was wondering if it’s possible to proceed some configuration using JMX/AMX (AppServer Management Extensions). I start to browse MBeans using JConsole, and check that’s really possible to modify the configuration, and the answer is yes. Ok, my first try is a simple one, I just want enable access.log, meaning set accessLoggingEnabled property to true for each http-service. Since I’m not really good to write Java, I wrote a groovy script. Here it comes :
Encore un billet dans la série XWiki, mais décidemment, cet outil me rend vraiment beaucoup de services. Ma dernière oeuvre (sic) consiste en la création d’une mini gestion des membres de l’association (GUSES, pour ceux qui ne le savent pas déjà !). Nous utilisons déjà Galette pour gérer les cotisations, mais malheureusement il n’y a rien (à ma connaissance) pour y brancher des hooks, dans mon cas ajouter l’utilisateur à la liste de diffusion de l’assocation.
Bref, quel rapport avec XWiki me direz vous ? Et bien, gràce à la bibliothèque SSH Trilead pour Java j’ai écrire une classe Groovy qui me permet d’exécuter des commandes (au sens unix) à distance. Et via quelques scripts shell et perl, il m’est désormais possible lors de l’ajout d’un utilisateur dans XWiki, d’automatiquement l’ajouter dans la base Galette, mais aussi l’inscrire à la liste de diffusion. D’autant plus que ces deux opérations étaient jusqu’alors réalisé par deux personnes différentes, n’arrangeant rien.
Un petit d’exemple d’utilisation de ma classe Groovy (sshhelper), en Groovy :
Il est à noter que j’ai eu des problèmes (avec la bibliothèque Trilead) d’authentification en login / mot de passe vers des serveurs Linux (Debian) alors que cela fonctionne vers des serveurs Solaris. Cependant, l’authentification par clé a fonctionné vers les deux OS.
J’en rêvais, alors je l’ai fais ! Mon idée était de disposer d’un ensemble d’outils pour générer facilement des requêtes SPML, j’ai donc créer une petite bibliothèque Java, et écris quelques scripts groovy associés, en pratique cela donne :
Comme vous pouvez le constater, cela deviens très simple. De plus, dans ma lancé, je me suis dis pourquoi ne pas créer une servlet recevant des requêtes SPML pour les traduires dans des WebServices EJBCA. C’est maintenant chose faite. Bien que je n’implémente actuellement que la méthode addRequest, cela me permet de provisionner des entités depuis un producteur SPML, comme par exemple Sun Identity Manager. La “traduction” entre SPML et la couche EJBCA se fais au travers d’un script groovy (et oui, encore du groovy, groovy c’est le bien !), de la manière suivante :
Actuellement le code est plutôt un POC que production ready, mais avec un peu de chance cela ne saurait tarder, et après tout ca permet déjà de faire des choses sympas !
Il y a peu de temps, j’ai mentionné la joie de ma découverte de xwiki. Quelques jours plus tard, et surtout après quelques heures de geekage intensif (et de lecture de documentation de velocity, hibernate, groovy, xwiki…) je viens de réussir à faire ce que je voulais ! À savoir avoir une macro permettant depuis mon xwiki d’aller récupérer des informations depuis un bugzilla à partir du numéro du bug. Concrêtement, dans ma page, j’utilise le code suivant :
#showBug(“123”)
pour obtenir le résultat suivant :
#226: Add a property to deactivate email verification
#231: Implement the Request Certificate uc
la couleur est dépendante du statut du bug. Voilà, c’est peut être pas grand chose, mais je suis vraiment impressionné par la rapiditié de développement que fournit xwiki au travers de velocity/groovy. Note : le code est disponible en attachement, néanmois je sais que ce n’est pas très optimisé, je vais le faire évoluer.