Industrialisation Websphere Application Server

De nos jours l’industrialisation occupe une grande place dans les développements en entreprise. Son but est d’éviter d’éffectuer des opérations manuelles qui peuvent être longues, fastidieuses et répétitives.
Au cours de plusieurs missions j’ai pu observer ce que le manque d’industrialisation peut engendrer lors des déploiements d’applications.Certaines personnes diront que cela nécessite un coût et donc de la charge lors de sa mise en place, mais on se rend compte que le gain de qualité apparaît quasi-immédiatement, de plus, des gains quantitativement sur le long terme.

Au plus tôt les processus d’industrialisation sont mis en place, moins cela nécessite de temps pour les mettre en place, bref d’autres sites expliqueront mieux que moi la valeur ajoutée de l’industrialisation.

Les serveurs d’applications.

La mise en place d’application J2EE en industrie est une chose relativement compliquée dans les grands SI. C’est pourquoi aujourd’hui les editeurs de serveurs d’applications : Oracle Weblogic, Oracle Glassfish, IBM Websphere AS, etc… proposent différentes manières d’administrer leurs serveurs d’applications via des API qui peuvent être scriptées afin d’appliquer la règle  :

write once, run everywhere.

Ces API permettent

  • Création de profile Websphere application serveur.
  • Le deploy ou Undeploy d’applications.
  • La création des ressources (JMS, MQ, JDBC, Activation Spect, Connection Factory, etc…)
  • L’arrêt et relance du serveur.
  • Etc..

Les API

IBM propose deux API pour permettre d’administrer leur serveur d’application : JACL et WSADMIN via Jython

  • JACL est la premiere API mise à disposition par IBM, celle-ci est un set d’API devenu deprecated.
  • WSAMIN est une API Jython permettant de mettre à jour le Webshpere AS. IBM conseil d’utiliser celle-ci.

Jython est un interpreteur python écrit en java, il permet d’exécuter du python avec le support de librarie Java.

Dans cet article nous allons nous focaliser sur l’utilisation de WSADMIN


Fonctionnement de  WSADMIN.

IBM fournit un script exécutable permettant de d’initialiser le contexte Jython wsadmin.bat ou wsadmin.sh suivant l’environnement d’exécution.

Ces scripts se situent dans le répertoire /bin du profile Websphere AS.

d:\IBM\WID7_WTE\runtimes\bi_v7\profiles\qwps\bin\wsadmin.bat -f <fichier jython>

Script Jython

Création d’un ressource JDBC


serverName = "server1"

# chemin vers le fichier du driver
classpath = "${ORACLE_JDBC_DRIVER_PATH}/ojdbc6.jar"
#-----------------------------------------------------------------
#CREATION PROVIDER JDBC
#-----------------------------------------------------------------

# description du fournisseur
description = "Oracle JDBC Driver"

# nom du fournisseur
label = "Oracle JDBC Driver"
# type de connexion
implClassName = "oracle.jdbc.pool.OracleConnectionPoolDataSource"

otherAttrsList = [["classpath", classpath], ["description", description]]
AdminJDBC.createJDBCProvider(AdminControl.getNode(), serverName, label, implClassName, otherAttrsList)

#-----------------------------------------------------------------
#CREATION ALIAS
#-----------------------------------------------------------------

# login
user = "userOracle"
# mot de passe
password = "passwordOracle"

aliasAuthent = 'alias-name'

AdminResources.createJAASAuthenticationAlias(aliasAuthent,user,password)

# nom que portera la DataSource
nameDataSource = "datasourceName"
# alias JNDI
JNDIName = "jdbc/datasourceName"

# propriétés supplémentaires pour le connecteur Oracle
properties = [[["name", "URL"], ["type", "java.lang.String"], ["value", dbDSN]]]

# liste d'attributs pour la création
otherAttrsList = [['description', nameDataSource], ['jndiName', JNDIName], ['authDataAlias', aliasAuthent], ['datasourceHelperClassname', "com.ibm.websphere.rsadapter.Oracle11gDataStoreHelper"], ['providerType', jdbcProviderName], ['propertySet', [["resourceProperties", properties]]]]

AdminJDBC.createDataSource( AdminControl.getCell(), serverName, jdbcProviderName, nameDataSource, otherAttrsList)

Création d’une ressource MQ


#Recuperation du provider MQ
mqJmsProvider = AdminConfig.getid('/Cell:'+AdminControl.getCell()+'/JMSProvider:WebSphere MQ JMS Provider/')

#Creation Queue  IN
createMQQueue("MQ_NAME", "mq/MQ_NAME", "TO.IN.ENTRETIEN", mqJmsProvider)

#-----------------------------------------------------------------
#CREATION MQ QUEUE
#-----------------------------------------------------------------
def createMQQueue(pQueueName, pJndiName, pMqQueue, pJmsProvider):
    try:
    #Parametres de la Queue
        mqQueueName = ['name', pQueueName]
        mqQueueJndi = ['jndiName', pJndiName]
        mqQueue = ['baseQueueName', pMqQueue]
        mqQueueAttributs = [mqQueueName, mqQueueJndi, mqQueue]
        #Creation de la queue
        AdminConfig.create('MQQueue', pJmsProvider, mqQueueAttributs)
        #Affectation des droits sur la QUEUE
        createCustomPropertiesMQ(pQueueName, "MDREAD", "YES")
        createCustomPropertiesMQ(pQueueName, "MDWRITE", "YES")
        createCustomPropertiesMQ(pQueueName, "MSGBODY", "MQ")
        print "La queue MQ "+pQueueName+" a ete creee"
    except:
        print "Erreur lors de la création de la Queue : " + pQueueName
        print 'exception non interpréter ',sys.exc_info()

Création d’une connexion factory


#Recuperation du provider MQ
mqJmsProvider = AdminConfig.getid('/Cell:'+AdminControl.getCell()+'/JMSProvider:WebSphere MQ JMS Provider/')

#Creation Connection Factory
createMQConnectionFactory("MQ_CF_NAME", "mq/MQ_CF_NAME", mqJmsProvider)

def createMQConnectionFactory(pMqFactoryName, pJndiName, pJmsProvider):
  try:
    #Parametres de la Connection Factory
    mqConnectionFactoryName = ['name', pMqFactoryName]
    mqConnectionFactoryJndi = ['jndiName', pJndiName]
    mqConnectionFactoryAttributs = [mqConnectionFactoryName, mqConnectionFactoryJndi]
    #Chargement du template pour la creation de la connection Factory
    mqConnectionFactoryTemplate = AdminConfig.listTemplates('MQConnectionFactory').split(java.lang.System.getProperty('line.separator'))[0]
    #Creation de la connection Factory
    AdminConfig.createUsingTemplate('MQConnectionFactory', pJmsProvider, mqConnectionFactoryAttributs, mqConnectionFactoryTemplate)
    print "La connection factory " +pMqFactoryName+ " a ete creee"
  except:
      print "Probleme lors de la creation de la connection factory : " + pMqFactoryName
      print 'exception non interpréter ',sys.exc_info()

Création d’un alias d’authentification

#-----------------------------------------------------------------
#CREATION ALIAS
#-----------------------------------------------------------------

# login
user = "userOracle"
# mot de passe
password = "passwordOracle"

AdminResources.createJAASAuthenticationAlias(aliasAuthentViseur,user,password)

Création d’une Spécification d’activation

#Creation Activation Spec
nodeId = AdminConfig.getid('/Cell:'+AdminControl.getCell()+'/Node:'+AdminControl.getNode()+'/J2CResourceAdapter:WebSphere MQ Resource Adapter')
createActivationSpec(nodeId ,"mq/MQ_AS_NAME", "MQ_AS_NAME")

#-----------------------------------------------------------------
#Ajoute Une activation spec
#-----------------------------------------------------------------
def createActivationSpec(pObjectId, pJndi, pName):
    try:
      ac = AdminConfig.list('ActivationSpec', pObjectId)
      name = ['name', pName]
      jname = ['jndiName', pJndi]
      cdattr = ['activationSpec', ac]
      j2cacAttrs = [name, jname,cdattr]
      AdminConfig.create('J2CActivationSpec', pObjectId, j2cacAttrs)
      print "L activation spec  "+pName+" a ete creee"
    except:
        import sys
        print 'Erreur lors de la creation de l activationspec : exception non interpréter ',sys.exc_info()

Création d’une Spécification d’activation

updateCustomPropertiesAS("MQ_AS_NAME", "destination", "mq/MQ_AS_NAME")

#-----------------------------------------------------------------
#Ajoute ou modifie les properties passees en parametre a une ActivationSpec
#-----------------------------------------------------------------
def updateCustomPropertiesAS(pASpecName, pName, pValue):
    try:
      j2cObjectId = AdminConfig.getid('/J2CActivationSpec:'+pASpecName)
      props = AdminConfig.list("J2EEResourceProperty",j2cObjectId)
      propsList = props.split(lineSeparator)
      if propsList != []:
      	isExist = 'false'
        for propsItem in propsList:
        	if pName == AdminConfig.showAttribute(propsItem,"name"):
      			isExist = 'true'
      			value = ['value', pValue]
      			AdminConfig.modify(propsItem, [value])
      	if isExist == 'false':
      		name = ['name', pName]
	      	value = ['value', pValue]
	      	rpAttrs = [name, value]
	      	AdminConfig.create('J2EEResourceProperty', j2cObjectId, rpAttrs)
    except:
      	print "La mise a jour de la propriete a echoue : " + pName
      	print 'exception non interpréter ',sys.exc_info()

Déploiement d’une application

deployApp('ApplicationName', 'Application.ear', 'cluster1')
def deployApp(appNam, earPath, clusterName):
    try:
        applicatExist = AdminApplication.checkIfAppExists(appNam)
        if applicatExist == 'false':
            print 'deploy : %s Mediation ' % appNam
            #r = AdminApplication.installAppWithNodeAndServerOptions(appNam, earPath, AdminControl.getNode(), "server1")
            #Si l'application est deploye sur un env non cluster commenter cette ligne et decommenter la ligne au dessus
            r = AdminApplication.installAppWithClusterOption(appNam,earPath,clusterName)
            if r == 1:
                print 'installation de %s est terminée ...' % appNam
                #AdminApplication.startApplicationOnSingleServer(appNam, "qnode", "server1")
                #startApplication(appNam)
                print 'l\'application %s est demarrée ...' % appNam
                # enregistrement de la configuration
                AdminConfig.save()
                print 'sauvegarde de la config ...'
    except Exception:
        print 'exception non interceptée ...', sys.exc_info()

Lecture d’un fichier properties

#Chargement de la config
properties = loadProperties('config.properties')

#-----------------------------------------------------------------
# Methode CHARGE UN FICHIER DE PROPRIETES ET CONSTRUIT UNE MAP
# CE QUI PERMET D'OBTENIR UNE VALEUR EN FONCTION D'UNE CLe
# prend 1 paramètre
# fileName
#-----------------------------------------------------------------
def loadProperties(fileName):
    properties = Properties()
    input = FileInputStream(fileName)
    properties.load(input)
    input.close()
    result= {}
    for entry in properties.entrySet():
      result[entry.key] = entry.value
    return result

print properties['oracle.port']

About Sébastien Renno