Přeskočit na hlavní obsah
  1. Tags/

Jython

2013


Vytvoření JMS Bridge na WebLogicu

Messaging bridge je šikovné řešení, pokud potřebujeme distribuovat zprávy mezi několika messaging systémy. Potřeboval jsem vytvořit JMS bridge na WebLogicu a protože jsem si oblíbil WebLogic Scripting Tool (WLST), tak jsem si napsal skript.

Nicméně dnes, vás milí čtenáři, nechci odfláknout pouhým WLST skriptem, ale podíváme se na téma trochu zeširoka. Prvně si zasadíme JMS bridge do kontextu Enterprise Integration Patterns (EIP), pak se podíváme, jak jde bridge naklikat ve WebLogic konzoli. A samozřejmě vás neochudím o to WLST :-)

Messaging Bridge

Nebyl bych to já, kdybych se nevytasil s nějakým patternem. Tak tady je - Messaging Bridge, jak je definován v EIP. (Věty kurzivou jsou citacemi z knihy Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions.)

Messaging Bridge řeší následující problém: "How can multiple messaging systems be connected so that messages available on one are also available on the others?" Integrační vzory řeší problémy obecně. V tomto případě jde o to, jak dostat zprávy z jednoho systému na jiný. Např. jak dostat zprávy z WebSphere MQ na MSMQ. Nebo JMS. Nebo TIBCO Randevouz. Nebo... Jasný, ne? Odkudkoliv kamkoliv.

Messaging Bridge tedy je "a way for messages on one messaging system that are of interest to applications on another messaging system to be made available on the second messaging system as well."

Protože většinou neexistuje způsob, jak propojit dva různé messaging systémy, propojují se jednotlivé, odpovídající kanály na daných systémech. "The Messaging Bridge is a set of Channel Adapters ... where each pair of adapters connects a pair of corresponding channels. The bridge acts as a map from one set of channels to the other and transforms the message format of one system to the other."

Vzor Messaging Bridge (zdroj EIP)

JMS Bridge

JMS bridge je speciální variantou Messaging bridge, který má několik omezení, nebo spíše možná zjednodušení. Tři hlavní jsou:
  • Propojuje pouze JMS systémy (různých dodavatelů).
  • Zprávy netransformuje (protože pracuje pouze s JMS zprávami).
  • Zprávy z jednoho (zdrojového) systému přeposílá na jiný (cílový). Čili nečiní je pouze dostupnými, ale provádí routing/forwarding.

JMS bridge běžně poskytují všichni dodavatelé JMS systémů, např.:

Zajímavým atributem u JMS bridge je Quality of Service (QoS), který říká, v jakém modu budou zprávy přeposílány:
  • At most once - nanejvýš jednou. Toto je nejbenevolentnější mod. Zpráva buď dorazí (maximálně jednou), anebo taky ne. A nám to tak vyhovuje.
  • Duplicates OK - duplicity jsou v pořádku. V tomto modu jsou zprávy potvrzeny, že dorazily na cílový systém. Může se stát, že stejná zpráva nám dorazí ve více instancích, ale to je v pořádku - řekli jsme přece, duplicity jsou OK. Výhodou je, že se žádná zpráva neztratí.
  • Exactly once - přesně jednou. Toto je nejvíc striktní mod, který nám nejen zaručuje, že každá zpráva dorazí na cílový systém, ale taky že tam dorazí právě jednou. Takový závazek není jen tak a zajistí nám ho JTA, čili distribuovaná transakce.

WebLogic JMS Bridge

Vytvoření JMS bridge na WebLogicu je otázkou chvilky, stačí mít připraveny správné ingredience. Co budeme potřebovat?
  • URL (a credentials) zdrojového serveru,
  • URL (a credentials) cílového serveru,
  • JNDI JMS adapteru (transakční, nebo netransakční)
    • eis.jms.WLSConnectionFactoryJNDIXA
    • eis.jms.WSLConnectionFactoryJNDINoTX
  • JNDI Connection Factory,
  • JNDI JMS destinace (fronty),
  • Quality of Service
    • Exactly-once
    • Duplicate-okay
    • Atmost-once

Pak už stačí jen naházet to do hrnce, zamíchat, podusit... a proklikat se průvodcem. Protože těch obrazovek ve wizardu je zbytečně moc, ukážu jenom screenshoty konečného stavu.

Pokud chceme použít transakční mod Exactly once, je dobré ještě před vytvářením bridge deployovat transakční adaptér jms-xa-adp.rar - vyhneme se tak zbytečným restartům (adapteru či WebLogicu). Adapter najdeme mezi knihovnami WebLogicu a nasazujeme ho jako aplikaci.

Nasazený resource adapter jms-xa-adp.rar (ve struktuře Deployments)

Bridge se sestává ze dvou destinací (zdrojové a cílové):

Definice JMS (source) destination

a samotného bridge:

Definice JMS bridge

Že nám bridge funguje, poznáme podle jeho stavu (záložka Monitoring) a taky doporučuju si nějakou zprávu cvičně přeposlat. Světe div se, ale transakce můžou zlobit.

Stavy JMS bridgů (záložka Monitoring)

WLST

No a máme tady velké finále, ke kterému jsem nenápadně, ale cílevědomě směřoval. Takže tady je: WLST v celé své pythoní kráse :-)
#
# properties
#
user = 'weblogic'
password = 'welcome1'
server = 't3://sandman:7001'
# source credentials
sourceJmsUser = 'weblogic'
sourceJmsPassword = 'welcome1'
sourceURL = 't3://sandman:7003'
# target credentials
targetJmsUser = 'weblogic'
targetJmsPassword = 'welcome1'
targetURL = 't3://sandman:7004'
# JMS servers
servers = ['SourceServer']
targets = []
# queues
queues = [
'EVM_EVE_CMS',
'EVM_EVE_FC',
'EVM_EVE_GEN',
'EVM_EVE_PTS',
'NTF_PARTY',
'NTF_PRODUCT']
adapterJNDI = 'eis.jms.WLSConnectionFactoryJNDIXA'
connectionFactory = 'jms/sws/SWSConnectionFactory'
qualityOfService = 'Exactly-once'
jndiPrefix = 'jms/sws/'

# connection
connect(user, password, server)

# edit mode
edit()
startEdit()

# get targets
for server in servers:
targets.append(getMBean('/Servers/' + server))
print '\nTargets:', targets, '\n'

#
# create bridges
#
print '\n### Create bridges:\n'
for queue in queues:
bridgeName = queue + '_bridge'
sourceName = queue + '_source'
targetName = queue + '_target'
# delete an old bridge
ref = getMBean('/MessagingBridges/' + bridgeName)
if ref != None:
cd('/MessagingBridges')
delete(bridgeName, 'MessagingBridge')
# delete an old source destination
ref = getMBean('/JMSBridgeDestinations/' + sourceName)
if ref != None:
cd('/JMSBridgeDestinations')
delete(sourceName, 'JMSBridgeDestination')
# delete an old target destination
ref = getMBean('/JMSBridgeDestinations/' + targetName)
if ref != None:
cd('/JMSBridgeDestinations')
delete(targetName, 'JMSBridgeDestination')
# create a new source destination
cd('/')
cmo.createJMSBridgeDestination(sourceName)
cd('/JMSBridgeDestinations/' + sourceName)
cmo.setAdapterJNDIName(adapterJNDI)
cmo.setConnectionFactoryJNDIName(connectionFactory)
cmo.setConnectionURL(sourceURL)
cmo.setDestinationJNDIName(jndiPrefix + queue)
cmo.setUserName(sourceJmsUser)
cmo.setUserPassword(sourceJmsPassword)
print 'Source:', cmo
# create a new target destination
cd('/')
cmo.createJMSBridgeDestination(targetName)
cd('/JMSBridgeDestinations/' + targetName)
cmo.setAdapterJNDIName(adapterJNDI)
cmo.setConnectionFactoryJNDIName(connectionFactory)
cmo.setConnectionURL(targetURL)
cmo.setDestinationJNDIName(jndiPrefix + queue)
cmo.setUserName(targetJmsUser)
cmo.setUserPassword(targetJmsPassword)
print 'Target:', cmo
# create a new bridge
cd('/')
cmo.createMessagingBridge(bridgeName)
cd('/MessagingBridges/' + bridgeName)
cmo.setSourceDestination(getMBean('/JMSBridgeDestinations/' + sourceName))
cmo.setTargetDestination(getMBean('/JMSBridgeDestinations/' + targetName))
cmo.setStarted(true)
cmo.setQualityOfService(qualityOfService)
cmo.setTargets(targets)
print 'Bridge:', cmo, '\n'

# save and finish
save()
activate()
disconnect()
exit()

Související články

Vytvoření JDBC datasource na WebLogicu pomocí WLST

·1 min

Dneska to bude jen taková variace na minulé téma (vytvoření JMS zdrojů pomocí WLST), aneb jak na WebLogicu vytvořit JDBC datasource pomocí skriptovacího nástroje WLST (WebLogic Scripting Tool).

Podstatné věci o WLST jsem zmínil v uvedeném postu, takže je tady už nebudu opakovat a eventuálně vás pro doplňující informace odkazuji tam.

#
# properties
#
user = ‘weblogic’
password = ’<password>’
server = ‘t3://<host>:7001’
dsName = ’<datasource>’
dsPath = ’/JDBCSystemResources/’ + dsName + ’/JDBCResource/’ + dsName
clusterName = ‘soa_cluster’

# connection
connect(user, password, server)

# edit mode
edit()
startEdit()

#
# delete an old JDBC resource
#
if cmo.lookupJDBCSystemResource(dsName):
delete(dsName, ‘JDBCSystemResource’)

#
# create JDBC resource
#
cmo.createJDBCSystemResource(dsName)
# set datasource name
cd(dsPath)
cmo.setName(dsName)
# set JNDI name
cd(dsPath + ’/JDBCDataSourceParams/’ + dsName)
cmo.setJNDINames([‘jdbc/’ + dsName])
# set driver
cd(dsPath + ’/JDBCDriverParams/’ + dsName)
cmo.setDriverName(‘oracle.jdbc.xa.client.OracleXADataSource’)
cmo.setPassword(’<password>’)
cmo.setUrl(‘jdbc:oracle:thin:@<host>:1521:<SID>’)
# set username
cd(dsPath + ’/JDBCDriverParams/’ + dsName + ’/Properties/’ + dsName)
cmo.createProperty(‘user’)
cd(dsPath + ’/JDBCDriverParams/’ + dsName + ’/Properties/’ + dsName + ’/Properties/user’)
cmo.setValue(’<user>’)
# set targets
cd(’/JDBCSystemResources/’ + dsName)
cmo.setTargets([getMBean(’/Clusters/’ + clusterName)])

# save and finish
save()
activate()
disconnect()
exit()

Související články

Vytvoření WebLogic Distributed Queue pomocí WLST

·3 min

Pokud nějaká aplikace používá JMS zdroje, bývají  tyto zpravidla externí. (Výjimkou je JMS broker embeddovaný uvnitř aplikace.) Tyto externí zdroje bývají často vytvořeny na aplikačním serveru, ve kterém je většinou JMS server už obsažen. Pokud naše aplikace používá např. JMS fronty, musí je “někdo” na daném JMS serveru vytvořit. Ten někdo je na vývojovém a někdy i testovacím prostředí vývojář, na dalších prostředích už to bývá administrátor.

Podle daného aplikačního serveru se JMS zdroje dají buď naklikat v nějaké administrátorské konzoli, nebo je potřeba poeditovat/vytvořit nějaké konfigurační soubory. Třetí možností je tyto  zdroje nějakým nástrojem naskriptovat. V případě aplikačního serveru WebLogic je takovým nástrojem WebLogic Scripting Tool (WLST).

Jak už jsem psal v minlém zápisku o mazání dat z MDS, WLST je v Jythonu napsaný nástroj pro správu WebLogic serveru, který funguje ve dvou režimech - offline a online. V online režimu se WLST připojuje k běžícímu WebLogicu a operuje nad stromem jeho MBeans. Pro správu JMS zdrojů je potřeba používat WLST online.

Distributed Queue

Věc, kterou jsem potřeboval vyřešit, bylo vytvoření distribuované fronty ve WebLogicovém clusteru. Cluster byl velmi jednoduchý - admin server a dva nody (managed servery). Vzhledem ke clusteru bylo potřeba vytvořit logickou frontu, která by měla stejný JNDI (jako na vývojovém prostředí s jedním nodem) a zastřešovala by fronty na jednotlivých nodech. Na WebLogicu je toto řešeno distribuovanými destinacemi (queue/topic). Pokud si to neumíte představit, distribuovaná fronta funguje v podstatě jako klasický load balancer.

Distribuovaná fronta (WebLogic Administration Console)

Členové distribuované destinace (WebLogic Administration Console)

WLST a JMS

Použití WLST je po krátké praxi poměrně intuitivní a jednoduché. Zpočátku může dělat problém se orientovat ve struktuře (stromech) MBean. V tomto může napomoci celkem slušná dokumentace: navigace MBeans, Javadoc a MBean reference. Pak už stačí jenom lehké základy Pythonu.

V následujícím skriptu je několik věcí, které můžou trochu ztížit čtení/pochopení skriptu, takže ještě kratičká legenda:
  • Target. Cílové umístění zdroje, nebo aplikace, např. server, cluster, JMS server ad. V případě deploymentu (aplikace) tím říkám, na které nody/clustery chci aplikaci nasadit.
  • SubDeployment. Mechanismus pro seskupení a umístění JMS zdrojů. V rámci subdeploymentu říkám, na které cíle (targets) chci dané zdroje nasadit. Může to být libovolná kombinace, nebo podmnožina.
  • cmo. Proměnná, která reprezentuje “aktuálně spravovaný objekt” (current management object). Je to vlastně MBeana, která má momentálně “focus”. Tak, jak se prochází stromem MBean, tak se tato proměnná automaticky mění.

# properties
user = ‘weblogic’
password = ’<password>’
server = ‘t3://<host>:7001’
subDeploymentName = ‘EVMJMSServers’
queuePath = ‘JMSResource/SOAJMSModule/UniformDistributedQueues/’
queueName = ‘EVM_DLQ’
jndiPrefix = ‘jms/b2b/’
loadBalancing = ‘Round-Robin’

# connection
connect(user, password, server)

# edit mode
edit()
startEdit()

# get targets
s1 = getMBean(’/JMSServers/SOAJMSServer_auto_1’)
s2 = getMBean(’/JMSServers/SOAJMSServer_auto_2’)

#
# create a SubDeployment
#
cd(’/JMSSystemResources/SOAJMSModule’)
# delete an old SubDeployment
if cmo.lookupSubDeployment(subDeploymentName):
delete(subDeploymentName, ‘SubDeployment’)
# create a new SubDeployment
cmo.createSubDeployment(subDeploymentName)
subDeployment = cmo.lookupSubDeployment(subDeploymentName)
subDeployment.setTargets([s1, s2])

#
# create a ldistributed queue
#
resource = cmo.getJMSResource()
# delete an old queue
ref = getMBean(queuePath + queueName)
if ref != None:
cd(‘JMSResource/SOAJMSModule’)
delete(queueName, ‘UniformDistributedQueue’)
# create a new queue
resource.createUniformDistributedQueue(queueName)
distributedQueue = resource.lookupUniformDistributedQueue(queueName)
distributedQueue.setJNDIName(jndiPrefix + queueName)
distributedQueue.setLoadBalancingPolicy(loadBalancing)
distributedQueue.setSubDeploymentName(subDeploymentName)

# save and finish
save()
activate()
disconnect()
exit()

Související články

Odstranění metadat z MDS

·2 min
Dneska to bude jedna praktická. Aneb jak v SOA Suite smazat z MDS (MetaData Store) nějaká metadata, soubory nebo adresář. Práce s MDS není z počátku úplně intuitivní, dokumentace není úplně jednoduše k nalezení a informace aby člověk vyškrabával z různých blogů a fór.

Tak, jak na to. Možnosti jsou dvě. Jednak použít WLST, nebo Ant skript, který je součástí SOA Suite (ten ale umožní pouze smazání adresáře).

WLST

WebLogic Scripting Tool (WLST) je zajímavý, v Jythonu napsaný, nástroj na administraci WebLogic serveru. Lze s ním pracovat dvěma způsoby: offline a online. Bohužel, s ohledem na MDS, je potřeba pro mazání souborů použít online způsob a pro smazání adresáře naopak offline (a také se používají dvě různé funkce). WLST zpravidla najdeme v adresáři <ORACLE_HOME>/oracle_common/common/bin.

Smazání souboru

Pro smazání jednoho a více souborů lze použít příkaz deleteMetadata. Vzhledem k tomu, že se tento příkaz používá online, je potřeba se prvně připojit k WebLogic administračnímu serveru. A po zadání mazacího příkazu se zase odpojit.
connect('weblogic', '<password>', 't3://<AdminServer>:7001')
deleteMetadata(
application='soa-infra',
server='soa_server1',
docs='/apps/<pathToFile>/DeadLetterQueue-v1.0.wsdl')
disconnect()
exit()


Smazání adresáře

Pro smazání adresáře slouží offline příkaz sca_removeSharedData. Problém s tímhle příkazem je, že není součástí standardních WLST modulů, ale je součástí instalace SOA Suite. Proto aby fungoval, je potřeba spustiti WLST z odpovídajícího adresáře: <ORACLE_HOME>/Oracle_SOA1/common/bin.

Dalším rozdílem je, že se nezadává cesta k administrativnímu serveru, ale ke spravovanému (managed) serveru, na kterém MDS běží.
sca_removeSharedData(
'http://<ManagedServer>:8001',
'public/evm/iface/DeadLetterQueue-v1',
'weblogic', '<password>')



Ant

Součástí instalace vývojového prostředí pro SOA Suite (JDeveloper) je i sada Ant skriptů mmj. pro buildování, (unit) testování a deployment. A také pro smazání adresáře z MDS. Tímto způsobem nejde mazat jednotlivé soubory.

Soubory se dají najít v adresáři <ORACLE_HOME>/jdeveloper/bin.
ant -f ant-sca-deploy.xml removeSharedData
-DserverURL=<ManagedServer>
-DfolderName=<pathToFolder>
-Duser=<user>
-Dpassword=<password>

Související články