Search This Blog

Saturday, March 2, 2013

JMS Foreign Server

What is Foreign Servers?

Foreign JMS servers can be used as a stand-alone component, similar to messaging bridges. These components  target application servers or clusters directly instead of an intermediary component like a JMS server.

Bridges vs Foreign Server


The JMS messaging bridge does introduce with an extra hop; messages are put into a local destination and then forwarded to the final destination. This is useful when the remote destination is not on highly available JEE container. The bridge will take the messages even when remote destination is not available and then forward them with build-in retry logic when the remote destination becomes available.

If the remote destination is highly available (WebLogic JMS or IBM MQ Series), foreign JMS server is preferable since it directly access the final destination without an extra hop. Mostly preferable for incoming queues on WebLogic 11g and later releases.

Best practices for Foreign Servers


Our best practices were centered around the standard of creating a single JMS Module per cluster (or app server if it wasn't clustered) and then creating both the Foreign server and the weblogic JMS queues/connection factories within the same module.
Also, having good naming conventions for your sub-deployments and JMS Modules

How does Weblogic Foreign Server works with external messaging system?


Configuring Foreign server on JMS Module

Foreign Server feature makes it possible to easily map to remote instances of WebLogic Server in another cluster or domain. so that they appear in the local JNDI tree as a local JMS object. Once the Foreign Provider is configured within Weblogic, for all practical JMS implementations within the code - it can be called as if it was on local JNDI lookup. Weblogic will make the remote calls transparent to your code. This allows you to change your destination via configuration on the Weblogic console or thru WLST.

Working in WLST, We need to connect to the Admin Server because this configuration changes can be done in online mode.
##################################
# FOREIGN JMS MODULE CONFIGURATION
##################################
fsjms_mod_name1=aFSmod
 
fr_server1=ForeignServer1
cnfurl1=file:/path/mq/bindings 
initialContextFactory1=com.sun.jndi.fscontext.RefFSContextFactory




Create JMS Module for Foreign Servers
 With the WebLogic 11g and later releases, Oracle has tried to merge both the internal and foreign JMS under a universal umbrella. However, the target options were kept different. To provide flexibility with the JMS portion, sub-deployments were introduced. Oracle seems to have been extended sub-deployments to Foreign Servers for the sake of consistency, making things quite complicated/messy.
WebLogic Foreign Server - IBM MQ 

Create JMS Foreign Server
This we can configure with the help of three arguments -There must be single JMS Module name per cluster, Multiple definitions of your connection factory will skew the JMS load-balancing.
  1. Connectiony Factory URL
  2. Foreign Server name
  3. Initial Context

Foreign Server MBean
JMS Foreign server is parent MBean with Foreign Connection Factory and Foreign Destination as childs.
Foreign Server MBean tree

The foreign JMS provider can be targeted to a WebLogic Server or a WebLogic Cluster.
Create JMS Foreign Destination
Create JMS Foreign Connection Factory

JMS Foreign Server Destination can be configured with the following details

  • Destination Name
  • Local JNDI
  • RemoteJNDI

The destination properties can be given as follows:

###############################################
# FOREIGN JMS DESTINATION CONFIGURATION
###############################################
destname1=ForeignDestination1
dest_ljndi1=mq/incoming/response
dest_rjndi1=MQSRC_TO_WL_JMS1

Similarly Foreign Connection Factory can be defined with the MQ connection factory details
###############################################
# FORIEGN JMS CONNECTION FACTORY CONFIGURATION
###############################################
fconf_name1=ForeignConnectionFactory1
fconf_ljndi1=MqConnectionFactory
fconf_rjndi1=REMOTE_JNDI1

create_ForeignServer.py

 
from java.io import File
from java.io import FileOutputStream
from java import io
from java.lang import Exception
from java.lang import Throwable
import os.path
 
import sys
 
def getJMSModulePath(jms_module_name):
        jms_module_path = "/JMSSystemResources/"+jms_module_name+"/JMSResource/"+jms_module_name
        return jms_module_path
 
def createFSJMSModule(jms_module_name,target_name):
        cd('/')
        module = create(jms_module_name, "JMSSystemResource")
        cluster = getMBean("Clusters/"+cluster_target_name)
        module.addTarget(cluster)
 
def createJMSFS(jms_module_name,cnurl,jms_fs_name,ini_fac):
        jms_module_path = getJMSModulePath(jms_module_name)
        cd(jms_module_path)
        cmo.createForeignServer(jms_fs_name)
        cd(jms_module_path+'/ForeignServers/'+jms_fs_name)
        cmo.setInitialContextFactory(ini_fac)
        cmo.setConnectionURL(cnurl)
        cmo.setDefaultTargetingEnabled(bool("true"))
        cmo.unSet('JNDIPropertiesCredentialEncrypted')
 
def getFSpath(jms_module_name,jms_fs_name):
        jms_module_path = getJMSModulePath(jms_module_name)
        jms_fs_path = jms_module_path+'/ForeignServers/'+jms_fs_name
        return jms_fs_path
 
def createFSdest(jms_module_name,jms_fs_name,jms_dest_name,ljndi,rjndi):
        cd('/')
        jms_fs_path = getFSpath(jms_module_name,jms_fs_name)
        cd(jms_fs_path)
        print jms_fs_path
        cmo.createForeignDestination(jms_dest_name)
        jms_fs_path=jms_fs_path+'/ForeignDestinations/'+jms_dest_name
        print jms_fs_path
        cd(jms_fs_path)
        cmo.setLocalJNDIName(ljndi)
        cmo.setRemoteJNDIName(rjndi)
 
def createFSconf(jms_module_name,jms_fs_name,jms_fconf_name,cljndi,crjndi):
        jms_fs_path = getFSpath(jms_module_name,jms_fs_name)
        cd(jms_fs_path)
        cmo.createForeignConnectionFactory(jms_fconf_name)
        cd(jms_fs_path+'/ForeignConnectionFactories/'+jms_fconf_name)
        cmo.setLocalJNDIName(cljndi)
        cmo.setRemoteJNDIName(crjndi)
############## MAIN SCRIPT starts  ##########
envproperty=""
if (len(sys.argv) > 1):
        envproperty=sys.argv[1]
else:
    print "Environment Property file not specified"
    sys.exit(2)
propInputStream=FileInputStream(envproperty)
configProps=Properties()
configProps.load(propInputStream)
 
adminUser=configProps.get("adminUser")
adminPassword=configProps.get("adminPassword")
adminURL=configProps.get("adminURL")
 
connect(adminUser,adminPassword,adminURL)
 
edit()
startEdit()
 
##############################################
#FOREIGN JMS SERVER CONFIGURATION
##############################################
total_dest=configProps.get("total_dest")
total_fconf=configProps.get("total_fconf")

cluster_target_name=configProps.get("clusterName")
 
trg=configProps.get("ForeignTargetServer")
fs_mod_name=configProps.get("fsjms_mod_name")
createFSJMSModule(fs_mod_name,trg)
 
n= int(tot_fs)
for i in range(1,n+1):
        fr_server=configProps.get("fr_server"+ str(i))
        cnfurl=configProps.get("cnfurl"+ str(i))
        ini_context=configProps.get("initialContextFactory"+ str(i))
        createJMSFS(fs_mod_name,cnfurl,fr_server,ini_context)
 
        d_name=configProps.get("destname"+ str(i))
        d_ljndi=configProps.get("dest_ljndi"+ str(i))
        d_rjndi=configProps.get("dest_rjndi"+ str(i))
        print d_ljndi,' == ', d_rjndi, b
        createFSdest(fs_mod_name,fr_server,d_name,d_ljndi,d_rjndi)
 
        fr_server=configProps.get("fr_server"+ str(i))
        j_conf=configProps.get("fconf_name"+ str(i))
        cn_ljndi=configProps.get("fconf_ljndi"+ str(i))
        cn_rjndi=configProps.get("fconf_rjndi"+ str(i))
        createFSconf(fs_mod_name,fr_server,j_conf,cn_ljndi,cn_rjndi)
 
# ####   MAIN SCRIPT END ########################################
save()
activate(block="true")
disconnect()
This script is generic you can add as many foreign server as you wish. You can better use it for receive the message with foreign servers that are having source at remote location. It could be connect to WebLogic JMS or it can connect to third party messaging servers such as MQ series or ActiveMQ etc. You can execute the script as follows:
$ java weblogic.WLST Foreign_jms.py ForeignJms.properties

References:

JMS Foreign Server MDB

Oracle doumentation on Foreign Server creation
  1. MQ Series 2 WebLogic
  2. WebLogic 10.3 with IBM MQ
  3. Jsure blog on WebLogic MQ

Thursday, January 31, 2013

JMS Module Uniform Distributed Queue using WLST


This post is continous series of JMS configurations experimenting with Python. Here the JMS module configuration changes for the JMS will be stored to config.xml repository and its sub-deployment module descriptor in a separate file. JMS system module can be defined with name, target to servers or cluster, its related sub-deployments such as Queue or publisher/Subscriber topics.

The WebLogic JMS related Mbeans are constructed as follows :
  • JMSBean
  • JMSSystemReourceMBean
  • QueueBean
  • JMSConnectionFactoryBean
  • DistributedQueueBean
  • UniformDistributedQueueBean
  • SubdeploymentMBean

While configuring you need to understand that JMS system module, that consists of ConnectionFactory that give access to the JMS services, and there could be a different scenario on demand. The machines are high-powered, low powered are in the same cluster then JMS destinations must be distributed destinations with ‘Allocate members Uniformly’ option set to false and manually select more physical destination from the high powered machines.The configuring JMS module is going to have various sub-deployment components in it. First we need to configure the JMS Module name, target to the advanced deployment as sub-deployment. 


Now you need brainstrom, and provide your customized domain with JMS module details in the properties file, let me give you sample :
############################################################################### 
# JMS MODULE CONFIGURATION
############################################################################### 
total_default_jms_module=1
jms_mod_name1=jmsSystemModule
jms_mod_target1=my_cluster

Subdeployment in JMS Module

Most of the Admins not really aware of the use of subdeployment. We need to configure a subdeployment per JMS Module. While configuring the subdeployment we have to provide the target as JMS servers which are configured in the first section. Why we need a subdeployment is interesting topic  • To avoid network traffic between JMS components communication • It will group Connection factories, queues, topics

 • Easy to migrate
WebLogic - JMS Module configuration using WLST

###############################################################################
# JMS SUBDEPLOY CONFIGURATION
###############################################################################
total_subdply=1
subdeployment_name=aJmssub

JMS Connection Factory

We have configured the ConnectionFactory properties as follows
###############################################################################
# JMS CONNECTION FACTORY CONFIGURATION
##########
conf_jndi1=myConnectionFactory
conf_name1=MyConnectionFactory
Configuring Uniform distributed queue using WLST We have configured the Queue with Distributed option because we have multiple JMS providers. The Uniform Distributed Queue is the one of the best practice when you have Clustered WebLogic Domain. While configuring this you need a name for the Uniform Distributed Queue and a JNDI name for it.
###############################################################################
#   UNIFORM DISTRIBUTED QUEUE CONFIGURATION
###############################################################################
total_udq=3
udq_name1=jmsIncomingChannel
udq_jndi1=jms/incoming/response
The JMS Module configuration with Subdeployment target to JMS Servers configured earlier. ConnectionFactory, Uniform Distributed Queue target to subdeployment.
from java.util import Properties
from java.io import FileInputStream
from java.io import File
from java.io import FileOutputStream
from java import io
from java.lang import Exception
from java.lang import Throwable
import os.path
import sys

envproperty=""
if (len(sys.argv) > 1):
        envproperty=sys.argv[1]
else:
        print "Environment Property file not specified"
        sys.exit(2)
propInputStream=FileInputStream(envproperty)
configProps=Properties()
configProps.load(propInputStream)

def createJMSModule(jms_module_name,cluster_target_name):
        cd('/JMSServers')
        jmssrvlist=ls(returnMap='true')
       # jmssrvlist=['AjmsServer1','AjmsServer2']
        cd('/')
        module = create(jms_module_name, "JMSSystemResource")
        cluster = getMBean("Clusters/"+cluster_target_name)
        module.addTarget(cluster)
        cd('/SystemResources/'+jms_module_name)

        module.createSubDeployment(subdeployment_name)
        cd('/SystemResources/'+jms_module_name+'/SubDeployments/'+subdeployment_name)
        list=[]
        for j in jmssrvlist:
                s='com.bea:Name='+j+',Type=JMSServer'
                list.append(ObjectName(str(s)))
        set('Targets',jarray.array(list, ObjectName))


def getJMSModulePath(jms_module_name):
        jms_module_path = "/JMSSystemResources/"+jms_module_name+"/JMSResource/"+jms_module_name
        return jms_module_path

def createJMSTEMP(jms_module_name,jms_temp_name):
        jms_module_path= getJMSModulePath(jms_module_name)
        cd(jms_module_path)
        cmo.createTemplate(jms_temp_name)
        cd(jms_module_path+'/Templates/'+jms_temp_name)
        cmo.setMaximumMessageSize(20)

def createJMSUDQ(jms_module_name,jndi,jms_udq_name):
        jms_module_path = getJMSModulePath(jms_module_name)
        cd(jms_module_path)
        cmo.createUniformDistributedQueue(jms_udq_name)
        cd(jms_module_path+'/UniformDistributedQueues/'+jms_udq_name)
        cmo.setJNDIName(jndi)
    #    cmo.setDefaultTargetingEnabled(bool("true"))
        cmo.setSubDeploymentName(subdeployment_name)

def createJMSConnectionFactory(jms_module_name,cfjndi,jms_cf_name):
        jms_module_path = getJMSModulePath(jms_module_name)
        cd(jms_module_path)
        cf = create(jms_cf_name,'ConnectionFactory')
        jms_cf_path = jms_module_path+'/ConnectionFactories/'+jms_cf_name
        cd(jms_cf_path)
        cf.setJNDIName(cfjndi)
        cd (jms_cf_path+'/SecurityParams/'+jms_cf_name)
        #cf.setAttachJMXUserId(bool("false"))
        cd(jms_cf_path+'/ClientParams/'+jms_cf_name)
        cmo.setClientIdPolicy('Restricted')
        cmo.setSubscriptionSharingPolicy('Exclusive')
        cmo.setMessagesMaximum(10)
        cd(jms_cf_path+'/TransactionParams/'+jms_cf_name)
        #cmo.setXAConnectionFactory(bool("true"))
        cd(jms_cf_path)
        cmo.setDefaultTargetingEnabled(bool("true"))

adminUser=configProps.get("adminUser")
adminPassword=configProps.get("adminPassword")
adminURL=configProps.get("adminURL")

connect(adminUser,adminPassword,adminURL)

edit()
startEdit()

 # ====# JMS CONFIGURATION## ##########################################
total_temp=configProps.get("total_temp")
total_udq=configProps.get("total_udq")
total_conf=configProps.get("total_conf")
tot_djmsm=configProps.get("total_default_jms_module")
subdeployment_name=configProps.get("subdeployment_name")

a=1
while(a <= int(tot_djmsm)):
        var1=int(a)
        jms_mod_name=configProps.get("jms_mod_name"+ str(var1))
        cluster=configProps.get("jms_mod_target"+ str(var1))
        createJMSModule(jms_mod_name,cluster)
        i=1

        while(i <= int(total_temp)):
                t_name=configProps.get("temp_name"+ str(i))
                createJMSTEMP(jms_mod_name,t_name)
                i = i + 1

        j=1
        while(j <= int(total_udq)):
                udq_name=configProps.get("udq_name"+ str(j))
                udq_jndi=configProps.get("udq_jndi"+ str(j))
                createJMSUDQ(jms_mod_name,udq_jndi,udq_name)
                j = j + 1
        k = 1
        while(k <= int(total_conf)):
                conf_name=configProps.get("conf_name"+ str(k))
                conf_jndi=configProps.get("conf_jndi"+ str(k))
                createJMSConnectionFactory(jms_mod_name,conf_jndi,conf_name)
                k = k + 1
        a = a+1

save()
activate(block="true")
disconnect()
############################################################

The sample properties listed for helping out how to create here for your projects.
###############################################################################
# JMS SUBDEPLOY CONFIGURATION
###############################################################################
total_subdply=1
total_default_jms_module=1
total_conf=1
subdeployment_name=demoSub

###############################################################################
# JMS CONNECTION FACTORY CONFIGURATION
######################################################
conf_jndi1=demoCF
conf_name1=jms/demoCF

###############################################################################
#   UNIFORM DISTRIBUTED QUEUE CONFIGURATION
###############################################################################
 

total_temp=0
total_udq=2
udq_name1=jmsIncomingChannel
udq_jndi1=jms/incoming/response
temp_name1=jmsIncomingChannel1

udq_name2=jmsOutgoingChannel
udq_jndi2=jms/outgoing/response
temp_name2=jmsOutgoingChannel1

adminUser=weblogic
adminPassword=welcome1
adminURL=t3://192.168.1.106:8100
###############################################################################
# JMS MODULE CONFIGURATION
###############################################################################
total_default_jms_module=1
jms_mod_name1=demo_jmsmod
jms_mod_target1=democlstr

To execute this JMS Module with subdeployments you need to pass the properties file as argument
java weblogic.WLST jms_module.py jms_module.properties
pavanbsd@ubuntu:~/pybin$ wlst jmsmodnq.py jmsmodnq.properties

Initializing WebLogic Scripting Tool (WLST) ...

Welcome to WebLogic Server Administration Scripting Shell

Type help() for help on available commands

Connecting to t3://192.168.1.106:8100 with userid weblogic ...
Successfully connected to Admin Server "demoadmin" that belongs to domain "demodomain".

Warning: An insecure protocol was used to connect to the
server. To ensure on-the-wire security, the SSL port or
Admin port should be used instead.

Location changed to edit tree. This is a writable tree with
DomainMBean as the root. To make changes you will need to start
an edit session via startEdit().

For more help, use help('edit')
You already have an edit session in progress and hence WLST will
continue with your edit session.

Starting an edit session ...
Started edit session, please be sure to save and activate your
changes once you are done.
drw-   jms_ms1
drw-   jms_ms2

MBean type JMSSystemResource with name demo_jmsmod has been created successfully.
MBean type ConnectionFactory with name jms/demoCF has been created successfully.
Saving all your changes ...
Saved all your changes successfully.
Activating all your changes, this may take a while ...
The edit lock associated with this edit session is released
once the activation is completed.
Activation completed
Disconnected from weblogic server: demoadmin

Keep writing back 🔙 your error screen shot comments and suggestions on this post. Keep smiling cheers!! 

Friday, January 25, 2013

JMS Server Configuration using WLST

Most of the message orient middleware architecture designs, while preparing the proof of concept for a new business domain they need to do multiple trails and errors. Configuring for such system resource task can be simplified with Python script. is one of the phases on other hand is setting up the thresholds and quota is next phase.
WebLogic  -  JMS Servers with File Store

Before entering into the scripting let us have brief JMS details, the basic types of JMS message communications are two:

  •  Point to Point (PTP) 
  • Publisher/Subscriber (Pub/Sub)
WLST JMS Server configuration
Usually JEE development lead or architect decides which kind of messaging could be suitable for the application. Once you got the “Sign-off” for the communication mechanism, the Middleware admin will be configuring the JMS system resources.
I like Jeff West video presentation about JMS Servers and their usage with uniform distributed Queue, Topic and newly introduced Partitioned distribution. For your reference embedding the video here.


Initially, we need a JMS persistence store configuration using WLST script, that enables you to configure as many JMS servers and persistence stores as required for an application deployment. The persistence store can be created with File Store or JDBC store options. As per your domain requirement you can specify the total number in the properties file. Suppose Architect team decided to use only File Stores then we can set 0 to JDBC total store so that the loop will be disabled for that.


What we do for JMS configuration using WLST?

The base JMS configuration is going to involve the following: a. Persistence store creation with Files: For each managed server where JMS servers configured there we need to create a File store. As best practice we create a dedicated folder where all the filestores can be stored per machine. Use the same directory structure for all machines where the filestores configured. b. Persistence store with JDBC: This we can use when your JMS message persistence requires huge message sizes. c. JMS server : we need to configure as many JMS servers as managed servers involve in JMS messaging
from java.util import Properties
from java.io import FileInputStream
from java.io import File
from java import io
from java.lang import Exception
from java.lang import Throwable
import os.path
import sys

def createFlstr(fstr_name,dir_name,target_name):
        cd('/')
        fst = create(fstr_name, "FileStore")
        cd('/FileStores/'+fstr_name)
        cmo.setDirectory(dir_name)
        fst.addTarget(getMBean("/Servers/"+target_name))

def createJDstr(jstr_name,ds_name,target_name,prefix):
        cd('/')
        jst = create(jstr_name, "JDBCStore")
        cd('/JDBCStores/'+jstr_name)
        cmo.setDataSource(getMBean('/SystemResources/'+ds_name))
        cmo.setPrefixName(prefix)
        jst.addTarget(getMBean("/Servers/"+target_name))

def createJMSsrvr(jms_srv_name,target_name,persis_store,page_dir, thrs_high, thrs_low, msg_size):
        cd('/')
        srvr = create(jms_srv_name, "JMSServer")
        cd('/Deployments/'+jms_srv_name)
        srvr.setPersistentStore(getMBean('/FileStores/'+persis_store))
#       srvr.setPersistentStore(getMBean('/JDBCStores/'+persis_store))
        srvr.setPagingDirectory(page_dir)
        srvr.addTarget(getMBean("/Servers/"+target_name))
        srvr.setBytesThresholdLow(long(thrs_low))
        srvr.setBytesThresholdHigh(long(thrs_high))
        srvr.setMaximumMessageSize(long(msg_size))

envproperty=""
if (len(sys.argv) > 1):
    envproperty=sys.argv[1]
else:
    print "Environment Property file not specified"
    sys.exit(2)
propInputStream=FileInputStream(envproperty)
configProps=Properties()
configProps.load(propInputStream)

adminUser=configProps.get("adminUser")
adminPassword=configProps.get("adminPassword")
adminURL=configProps.get("adminURL")

connect(adminUser,adminPassword,adminURL)

edit()
startEdit()

#=============# JMS SERVER and PERSISITENT STORE CONFIGURATION #=============#
total_fstore=configProps.get("total_fstore")
#total_jstore=configProps.get("total_jstore")
total_jmssrvr=configProps.get("total_jmssrvr")

j=1
while (j <= int(total_jmssrvr)):
        jms_srv_name=configProps.get("jms_srvr_name"+ str(j))
        trg=configProps.get("jms_srvr_target"+ str(j))
        persis_store=configProps.get("jms_srvr_persis_store_name"+str(j))
        page_dir=configProps.get("jms_srvr_pag_dir"+str(j))
        thrs_high=configProps.get("jms_srvr_by_threshold_high"+str(j))
        thrs_low=configProps.get("jms_srvr_by_threshold_low"+str(j))
        msg_size=configProps.get("jms_srvr_max_msg_size"+str(j))
        createFlstr(persis_store,page_dir,trg)
        createJMSsrvr(jms_srv_name,trg,persis_store,page_dir,thrs_high,thrs_low,msg_size)
        j = j+1
#==========================================================================================#
save()
activate()
To execute this script you need to workout on your properties file, indentation in the script.
$ java weblogic.WLST jms_servers.py jms_servers.properties

Generic advantage of this Script

Here most important thing is that when you wish that the persistance store could be a filestore then, it requires file path, if you are giving in the properties file assign absoulute path.
Sample properties file here
adminUser=weblogic
adminPassword=welcome1
adminURL=t3://192.168.1.106:8100
total_fstore=2
total_jmssrvr=2

jms_srvr_name1=jms_ms1
jms_srvr_target1=ms1
jms_srvr_persis_store_name1=jms_ms1_fs
jms_srvr_pag_dir1=/home/wlsdomains/demodomain/fs
jms_srvr_by_threshold_high1=10
jms_srvr_by_threshold_low1=5
jms_srvr_max_msg_size1=512

jms_srvr_name2=jms_ms2
jms_srvr_target2=ms2
jms_srvr_persis_store_name2=jms_ms2_fs
jms_srvr_pag_dir2=/home/wlsdomains/demodomain/fs
jms_srvr_by_threshold_high2=10
jms_srvr_by_threshold_low2=5
jms_srvr_max_msg_size2=512

Tuesday, January 8, 2013

Cluster manuplation with WLST

There could be situations where you might have seen this. such as in production environment one of the site will be decommissioned. All the site member machines hosting WebLogic Managed Servers will be kicked out of domain. finally the cluster will be removed.

In some cases your production environment might having business enhancement plans, so that there could be new geographical site will be added to to existing running domain then, there would be need of cluster or clusters addition to the domain and respective managed servers all added to it.

Here I got a thought that why don't we make a WLST script that will give you option of High Availability(HA) with above said options as well additon to it addtion of managed server and removal of managed servers.

OEPE is giving ready made scripts so I thought this would be easy to implement the logic.

Designing WebLogic Cluster

First you need to identify type of the cluster you need to implement. Single WebLogic Cluster can serve the minimum size of business requests. You need to identify the number of the server required on a cluster. You can choose Multi-tier cluster where you can have dedicated cluster for each service. After experiancing many production issues identified what all the configuration changes that makes standard and easy to handle the troubleshooting in production environments are collected and compiled as "Best practices" implementation for Managed server configuration with Jython script.

1. Log LEVELwith best suitable attributes
2. Log rotation for managed servers
3. Threadpool size settings with WLST
4. Diagnostic framework enabling with WLST

from java.util import *
from java.io import FileInputStream
from javax.management import *
import javax.management.Attribute
import sys

envproperty=""
if (len(sys.argv) > 1):
 envproperty=sys.argv[1]
else:
 print "Environment Property file not specified"
 sys.exit(2)

propInputStream=FileInputStream(envproperty)
configProps=Properties()
configProps.load(propInputStream)

def getp(x):
 """ This function will be used to fetch the properties file"""
        return configProps.get(x)
 

def logLevel(ms, k):
 lg = ms.getLog()
 lg.setFileName(''+domainHome+'/logs/bea/ms'+str(k)+'_'+domainName+'.log')
 lg.setLogFileSeverity('Info')
 lg.setRotationType('byTime')
 lg.setRotationTime("23:59")
 lg.setFileTimeSpan(24)
 lg.setDomainLogBroadcastSeverity('Error')
 lg.setMemoryBufferSeverity('Error')
 lg.setRedirectStdoutToServerLogEnabled(true)
 lg.setRedirectStderrToServerLogEnabled(true)
 lg.setStdoutSeverity('Error')
 
def setDiagnostics(ms, k):
 svrdiag = ms.getServerDiagnosticConfig()
 svrdiag.setDiagnosticContextEnabled(false)
 svrdiag.setDiagnosticStoreDir(''+domainHome+'/logs/store/diagnostics/ms'+str(k)+'_'+domainName+'/')

 defFileStore = ms.getDefaultFileStore()
 defFileStore.setDirectory(''+domainHome+'/logs/store/default/ms'+str(k)+'_'+domainName+'/')
  
 hvDataRetire = svrdiag.createWLDFDataRetirementByAge("HarvestDataRetirePolicy")
 hvDataRetire.setArchiveName(""+getp("ms_harvesarchivename")) 
 hvDataRetire.setEnabled(bool(getp("ms_harvesenabled")))
 hvDataRetire.setRetirementAge(int(getp("ms_harvesretireage")))
 hvDataRetire.setRetirementPeriod(int(getp("ms_harvesretireperiod")))
 hvDataRetire.setRetirementTime(int(getp("ms_harvesretiretime")))

 eventDataRetire = svrdiag.createWLDFDataRetirementByAge("EventDataRetirePolicy")
 eventDataRetire.setArchiveName(""+getp("ms_evtarchivename"))
 eventDataRetire.setEnabled(bool(getp("ms_evtenabled")))
 eventDataRetire.setRetirementAge(int(getp("ms_evtretireage")))
 eventDataRetire.setRetirementPeriod(int(getp("ms_evtretireperiod")))
 eventDataRetire.setRetirementTime(int(getp("ms_evtretiretime")))

def webserver_log(ms, k):
 wbsvr = ms.getWebServer()
 wbsvr.setPostTimeoutSecs(30)
 wbsvrlog = wbsvr.getWebServerLog()
 wbsvrlog.setFileName(''+domainHome+'/logs/ms'+str(k)+'_'+domainName+'_access.log')
 wbsvrlog.setLoggingEnabled(bool(getp("ms_accesslogenabled")))
 wbsvrlog.setLogFileFormat(""+getp("ms_accesslogformat"))
 wbsvrlog.setELFFields(""+getp("ms_extlogfomart"))
 wbsvrlog.setRotationType('byTime')
 wbsvrlog.setRotationTime("23:59")
 wbsvrlog.setFileTimeSpan(24)

 #execQ1 = ms.createExecuteQueue("weblogic.kernel.Default")
 #execQ1.setThreadCount(30)
 #execQ1.setThreadsIncrease(0) 
#####################################################################################
#  MANAGED SERVER CONFIGURATIONS
###################################################################################

def create_ms(k):
 ms = create(""+getp("man"+str(k)),'Server')
 ms.setListenAddress(""+getp("ms_listenaddress"+str(k)))
 ms.setListenPort(int(getp("ms_listenport"+str(k))))
 
 ms.setWeblogicPluginEnabled(bool(getp("ms_defaultwlplugin")))
 #ms.setUse81StyleExecuteQueues(true)
 ms.setMaxOpenSockCount(int(getp("ms_maxopensockcount")))
 ms.setNativeIOEnabled(bool(getp("ms_nativeioenabled")))
 ms.setStuckThreadMaxTime(int(getp("ms_stuckthreadmaxtime")))
 ms.setStuckThreadTimerInterval(int(getp("ms_stuckthreadtimerinterval")))
 ms.setLowMemoryGCThreshold(int(getp("ms_lowmemorygcthreshold")))
 ms.setLowMemorySampleSize(int(getp("ms_lowmemorysamplesize")))
 ms.setLowMemoryTimeInterval(int(getp("ms_lowmemorytimeinterval")))
 ms.setStagingMode(""+getp("ms_stagingmode"))
 ms.setAcceptBacklog(int(getp("ms_acceptbacklog")))
 ms.setLoginTimeoutMillis(int(getp("ms_logintimeoutmillis")))
 ms.setManagedServerIndependenceEnabled(bool(getp("ms_managedserverindependenceenabled")))
 ms.setTransactionLogFilePrefix(""+getp("ms_transactionlogfileprefix"))
 print ' ******* SETTTING MANAGED SERVER ATTRIBUTES for *********** '+getp("man"+str(k))
 logLevel(ms, k)
 setDiagnostics(ms, k)
 webserver_log(ms, k)
 ms.setCluster(clusTgt)
 
################ main program ####################################################
domainName=getp("domainName")
adminServerListenaddr=getp("adminServerListenaddr")
admin_listerport=getp("admlistenport")
adminURL="t3://"+adminServerListenaddr+":"+str(admin_listerport)
domainHome=getp("domainHome")

adminUser=getp("adminUser")
adminPassword=getp("adminPassword")
userConfigFile=""+domainHome+"/bin/userconfigfile.secure"
userKeyFile=""+domainHome+"/bin/userkeyfile.secure"

adminServerName=getp("adminServerName")
clusterName=getp("clusterName")
numMS=getp("total_mansrvr")

connect(adminUser,adminPassword,adminURL)
edit()
startEdit()
cd('/')
#####################################################################################
#  CLUSTER CONFIGURATIONS
#####################################################################################
print ' ******* CREATING CLUSTER *********** '
clu = cmo.createCluster(""+clusterName)
isMulticastTrue=getp("isMulticastTrue")
if (isMulticastTrue == "true"):
 clu.setMulticastAddress(getp("multi_address"))
 clu.setMulticastPort(getp("multi_port"))
else:
 clu.setClusterMessagingMode('unicast')

clu.setWeblogicPluginEnabled(true)
clu.setClusterAddress('')
#cd('/Clusters/'+clusterName+'/OverloadProtection/'+clusterName+'/ServerFailureTrigger/'+clusterName)
#clu.setMaxStuckThreadTime(300)
#clu.setStuckThreadCount(0)
#cd('/Clusters/'+clusterName+'/OverloadProtection/'+clusterName)
#clu.setPanicAction('system-exit')
#clu.setFailureAction('admin-state')
#clu.createServerFailureTrigger()
cd('/Clusters/'+clusterName)
clusTgt = cmo
cd('/')
for k in range(1, int(numMS)+1): 
 print getp("man"+str(k))
 create_ms(k) 
cd('/')
save()
activate(block="true")

disconnect()
#####################################################################################

Here I am publishing the sample properties file that I have tried on my Windows operating system, after the execution of basic domain running with Admin server. When we start the WebLogic 12c or 10.3.6 version on Windows 7 it is not able to open the 'Console'. Alternative solution for this is change the PermSize to 512m in the setDomainEnv.cmd select proper Java vendor and update the following lines.
 set WLS_MEM_ARGS_64BIT=-Xms512m -Xmx512m -XX:PermSize=512m
 set WLS_MEM_ARGS_32BIT=-Xms512m -Xmx512m -XX:PermSize=512m
Start the Admin server so that we can run the online WLST script to configure the number of managed server that are mentioned in the properties file. The properties file is extended for this Cluster implemenation is as follows:
#####################################################################################
# DOMAIN LEVEL CONFIGURATION
##################################################################################
domainTemplate=C:/Oracle/Middleware/wlserver_10.3/common/templates/domains/wls.jar
#Following property is the default property and should not be changed.
weblogicdomainpasspath=Security/base_domain/User/weblogic

adminUser=weblogic
adminPassword=weblogic123$
adminServerName=admin_cldom
adminServerListenaddr=localhost
admlistenport=7100

OverwriteDomain=true
domainName=cldom1
domainHome=C:/wldomains/cldom1

clusterName=cluster_cldom
isMulticastTrue=false
multi_address=
multi_port=
##################################################################################
# MANAGED SERVERS CONFIGURATIONS
##################################################################################
total_mansrvr=2

man1=rdms1_cldom
man2=rdms2_cldom

ms_listenaddress1=localhost
ms_listenaddress2=localhost

ms_listenport1=61001
ms_listenport2=61002

ms_selftunningthreadpoolsizemin=30
ms_selftunningthreadpoolsizemax=35
ms_defaultwlplugin=true
ms_maxopensockcount=1000
ms_nativeioenabled=true
ms_stuckthreadmaxtime=300
ms_stuckthreadtimerinterval=300
ms_lowmemorygcthreshold=5
ms_lowmemorysamplesize=10
ms_lowmemorytimeinterval=3600
ms_stagingmode=nostage
ms_acceptbacklog=65
ms_logintimeoutmillis=5000
ms_managedserverindependenceenabled=true
ms_transactionlogfileprefix=/xa_logs/cldom

ms_accesslogenabled=true
ms_accesslogformat=extended
ms_extlogfomart=c-ip date time cs-method sc-status time-taken bytes cs-uri cs(Referer)

ms_harvesarchivename=HarvestedDataArchive
ms_harvesenabled=true
ms_harvesretireage=168
ms_harvesretireperiod=24
ms_harvesretiretime=0

ms_evtarchivename=EventsDataArchive
ms_evtenabled=true
ms_evtretireage=168
ms_evtretireperiod=24
ms_evtretiretime=0
When we run the sample cluster domain on the Windows 7 the outcome is as follows:
C:\pbin>java weblogic.WLST cluster_conf.py mycldom.properties

Initializing WebLogic Scripting Tool (WLST) ...

Welcome to WebLogic Server Administration Scripting Shell

Type help() for help on available commands

Connecting to t3://localhost:7100 with userid weblogic ...
Successfully connected to Admin Server 'admin_cldom' that belongs to domain 'cld
om1'.

Warning: An insecure protocol was used to connect to the
server. To ensure on-the-wire security, the SSL port or
Admin port should be used instead.

Location changed to edit tree. This is a writable tree with
DomainMBean as the root. To make changes you will need to start
an edit session via startEdit().

For more help, use help(edit)

Starting an edit session ...
Started edit session, please be sure to save and activate your
changes once you are done.
 ******* CREATING CLUSTER ***********
rdms1_cldom
MBean type Server with name rdms1_cldom has been created successfully.
 ******* SETTTING MANAGED SERVER ATTRIBUTES for *********** rdms1_cldom
rdms2_cldom
MBean type Server with name rdms2_cldom has been created successfully.
 ******* SETTTING MANAGED SERVER ATTRIBUTES for *********** rdms2_cldom
Saving all your changes ...
Saved all your changes successfully.
Activating all your changes, this may take a while ...
The edit lock associated with this edit session is released
once the activation is completed.
Activation completed
Disconnected from weblogic server: admin_cldom

Sunday, November 18, 2012

Input and Output in WLST

In WLST we can have same kind of command line inputs and outputs as in Python and Jython languages. This can be useful when it is required to prepare a huge monitoring report using WLST or when you work for hundreds of servers in a domain such as in cloud where Middleware as a service (MAAS) and you need to find an automation task with WLST scripts.

Inputs in WLST

To read simple string of values we can use raw_input() built in function or sys.stdin.readline() method. For reading different data types such as number values we can use input() function, which internally calls raw_input() function and apply eval() to convert the input value to number values.
wls:/offline> x=raw_input('Enter a number:')
Enter a number:4009
wls:/offline> print x*2
40094009
wls:/offline> y=input('Enter a number: ')
Enter a number: 400
wls:/offline> print y*3
1200
Let’s experiment with Boolean type of variable in WLST
wls:/offline> b=input('Do you love WLST?')
Do you love WLST?True
wls:/offline> print b
1
wls:/offline> b=input('Do you love WLST?')
Do you love WLST?False
wls:/offline> print b
0
Here you enter as True or False but, the Boolean variables are stores on WLST SHELL as either zero or one. This is somewhat confusing you with regular Boolean types in other languages or UNIX it is opposite. One represents True value, zero represents False. So take care while you scripting for the Boolean type variables.
When you have the option to select the data in string format then go for raw_input() built-in function. This is much better way when situation demands your script to enter name of the WebLogic server instance or some questions to repeat the script task. On the other hand input() will be good option when you have to select multiple options for monitoring geographical sites to choose one of them with a numbered input.

Reading variable in WLST with stdin

We have one more option to read the values from the WLST command prompt that is using sys module. We can use sys.stdin.readline() method to read the input and assign it to a variable. This will fetches only text data in to the variable, so you use this when you want to input the strings.
wls:/offline> serv=sys.stdin.readline()
managed3_server
wls:/offline> serv
'managed3_server\n'
wls:/offline> print serv
managed3_server

Output in WLST

An output can be displayed using print command as we have seen many statements in WLST already. Although, we cover few basics of print statement, which accepts string as an argument.
  • Simple string to display
    print ‘Welcome to WLST!!!’
    
  • To display the string and variables combinations in Java Style concatenation that is using ‘+’ operator
    print  ‘Server Status ’+ stat
    
  • To display only WLST script variables then you can use the comma separated variables you can use the combination of string in the same line too
    print x, y
    
  • Now, we will see the good old C style formatting for the output, here we use % symbol followed by paranthesized list of variables that will be substituted in place of embedded conversion types (such as string - s, decimal - d, float - f) in the order.
    print ‘%14s %d %f’ %(server, freeJvm, throughput)
    
In WLST we can use the print statement for displaying the data from a variable or strings objects. We can display the combination of variables in the same line. This is possible with comma separation or simply we can use Java style of concatenation using plus symbol.

Obtain Environment variables in WLST

WLST supports the Jython capability that obtaining the environment variables from the System. To do this we need to import the os module (operating system) and use the environ dictionary variable.

wls:/offline> import os
wls:/offline> os.environ
{'WL_HOME': 'C:\\wls12c\\wlserver',  …}

You can pull out your required values of environment variable as you access the dictionary variable. Example you can retrieve WL_HOME or JAVA_HOME values as show below.

wls:/offline> os.environ["WL_HOME"]
'C:\\wls12c\\wlserver'

wls:/offline> os.environ["JAVA_HOME"]
'C:\\Java\\jdk1.6.0_34'

This WLST trick can be most often used; when you are configuring resources are creating WebLogic domains. Remember, This WLST trick will works on UNIX platform as well.



Friday, June 22, 2012

WLST JMS monitoring stats to CSV file

Intro: We got a mail from Richard who wish to write a WLST script to monitor a JMS Runtime. The Queue performance details wish to collect.

WLST script to monitor JMS and store the attribute values when there is Production live available or Performance test run  going on with multiple user load collect the statistcs and send that into a separate CSV file. Just to give little idea on CVS, A comma-separated values (CSV) file are also referred as a flat files, ascii files, and it is a spreadsheet convertible files. Richi want the logic to storing the statistics to a .csv file. Thought that it will be helpful for anyone who may have similar thoughts. We got the script idea from Richi that consisting the following prototype.

Writing to a CVS file has been simplified without using writer.csv, instead commas have been used and the file extension is hard coded as .csv, once you open the file you will see a prompt where in you need to select comma as the delimeter so that the values of jms statistics will be sorted accordingly, you can modify the script as per your need.

The script flow will be as mentioned below
  1. Open a file with write access.
  2. Get the RUNNING servers of the domain from domainRuntimeService.
  3. Print the headers of JMS counters.
  4. Get the details of JMS servers using JMSRuntime and JMSServers functions.
  5. Using a loop get the jms server destinations.
  6. Using a loop get the details of the parameters like ConsumersCurrentCount, ConsumersHighCount etc of the destinations and store those to variables.
  7. Print the variables.
  8. Close the file.
##################################################
#Title: WLST script to monitor JMS runtime and saving the values to CSV file
#Author: Sunil Nagavelli/Pavan Bhavani Shekar Devarakonda
#
###################################################
import sys


file1=open('JMS.csv','w+')

servers = domainRuntimeService.getServerRuntimes();

print>>file1, " ConsumersCurrentCount: ", ",", " ConsumersHighCount: ", ",", " DestinationType: ", ",", " BytesHighCount: ",
",", " BytesPendingCount: "

if (len(servers) > 0):
  for server in servers:
    jmsRuntime = server.getJMSRuntime();
    jmsServers = jmsRuntime.getJMSServers();
    for jmsServer in jmsServers:
      destinations = jmsServer.getDestinations();
      for destination in destinations:

        CCC = destination.getConsumersCurrentCount()
        CHC = destination.getConsumersHighCount()
        DT  = destination.getDestinationType()
        BHC = destination.getBytesHighCount()
        BPC = destination.getBytesPendingCount()

        print>>file1,CCC, ",", CHC, ",", DT,  ",", BHC, ",", BPC

print "values have been captured successfully into the csv file"
       
file1.close()

Sunday, June 10, 2012

JDBC Monitoring

JDBC Monitoring with LWLST script
One fine morning we (WLA support Team) got an assignment, The summary of the assignment was to find "How the WebLogic server instance performing for a DataSource?". WebLogic 9.x onwards a DataSource is associated with a ConnectionPool (a pool of connections to the DB). If we monitor ConnectionPool, inturn it is nothing but monitoring a DataSource.

Of-course the task is not that easy, I have gone through various WebLogic forums to find a appropriate solution for this task.

Oracle WebLogic provides two ways to Monitor a Datasource
1. Monitoring Datasource server wise
2. Testing the Connection Pool

Here I am publishing the same script which Madan Noru/Satya prepared in the old bea fourms or ObjectMix forums. Only one thing is difference is that displaying pattern, I had created a separate header, so that output looks good to see in a table form. To make this possible I have used C-Style print command from Python Language. This format you can change as per your screen display size.

The script will retrieve the JDBC Connection Pool MBean using adminHome, which is deprecated object in WLST. The output of the script will gives you the values of the following attributes:
  • DataSource Name
  • Maximum Capacity of the Connection Pool at Run-time
  • Active Connections Current Count
  • Active Connections High Count
  • Wait Seconds High Count
  • Waiting For Connection Current Count
  • State of the Connection Pool

#=======================================================
# This script will monitor the JDBC CONNECTION POOL
# more details on this script contact: Pavan Devarkonda
#=======================================================
connect("username","passwd","t3://AdminIP:AdminPort")
try:
 poolrtlist=adminHome.getMBeansByType('JDBCConnectionPoolRuntime')
 print ' '
 print ' '
 print 'JDBC CONNECTION POOLS'
 print ' '
 print 'Name Max Active Active WaitSecs Waiting State'
 print ' capacity Current HighCnt HighCnt Count'

 for poolRT in poolrtlist:
  pname = poolRT.getName()
  pmaxcapacity = poolRT.getAttribute("MaxCapacity")
  paccc = poolRT.getAttribute("ActiveConnectionsCurrentCount")
  pachc = poolRT.getAttribute("ActiveConnectionsHighCount")
  pwshc = poolRT.getAttribute("WaitSecondsHighCount")
  pwfccc = poolRT.getAttribute("WaitingForConnectionCurrentCount")
  pstate = poolRT.getAttribute("State")
  print '%10s %7d %7d %7d %7d %7d %10s' % (pname,pmaxcapacity,paccc,pachc, pwshc,pwfccc,pstate)
  print ' '
except:
  print 'Error:'
  dumpStack()
  pass
disconnect()

In Year 2012 revisting the same script

We have trouble in the produciton environment with JDBC Connection pool overloaded. All the ActiveConnectionCount reaching the MaxCapacity of the Connection pool. As a temprory workaround we need to reset the Connection pool for that movement. Permanent cure is tuning the Connection pool. For both solutions we need active monitoring the JDBC Connection pool.
To monitor this we have revisited the same script. Now adding more saus to the script we need to find that ActiveConnectionCount reaching 85% as threshold limit. Once it reaches 85 or greater then monitoring tool like HP OV/some other tool will reads log file generated by the script and then sends warns message to supporting Middleware Admin when threshold crossed. If you have sendmail service on your machine you can send message fromt he script itself.
To do this we had manupulated the above script according to the requirements
  1. We have specified DataSource that are causing this trouble
  2. Used separate properties file for user credentials.
  3. The output of script is redirected to a file
  4. Managed Server name opposite to the monitor values it is tricky but resolved The new script is

#=======================================================
# This script will monitor the JDBC CONNECTION POOL
# Date :  18 Apr 2012
#=======================================================
import sys
import time
try:
        loadProperties('./DBcheck.properties')
        fp=open('ActiveConn.log','a+')
        Date = time.ctime(time.time())
        admurl='t3://'+admAdrs+':'+admPort
        connect(userConfigFile=UCF, userKeyFile=UKEY, url=admurl)
        poolrtlist=adminHome.getMBeansByType('JDBCConnectionPoolRuntime')
        print ' '
        print 'JDBC CONNECTION POOLS'
        print>>fp, '================================================ '

 for poolRT in poolrtlist:
                pname = poolRT.getName()
                pmaxcapacity = poolRT.getAttribute("MaxCapacity")
                paccc = poolRT.getAttribute("ActiveConnectionsCurrentCount")
        
  if pname == 'myDataSource1' or pname == 'myDS2'' or pname == 'myDS3':
                        server= str(poolRT).split(',')[2].split('=')[1]
                        p=(paccc /(pmaxcapacity * 1.0)) * 100 
                        if p >= 85:
                                print >>fp, 'WARNING: The Active connections are Greater than Threshold 85%'
                        print>>fp, '%24s %15s %18s %7d %7d' % (Date,server,pname,pmaxcapacity,paccc)

except Exception, e:
        sys.stderr.write('ERROR: %s\n' % str(e))
        print 'Error:', e
        dumpStack()
        pass
fp.close()
disconnect()


-->

Post script actions

  1. Prepare a Shellscript that will let you know howmuch time it will counsume to run py script.
    clear
    date
    $JAVA_HOME/bin/java weblogic.WLST /path/urscript/jdbcmon.py
    date
    
  2. Schedule a scheduler to run this script autosys or crontab that invokes above shell script.
  3. Configure a monitoring tool frequently lookup the logs and send alert messages such as HP OVO or smpt mailing also fine.
What do you think about this new version of script? Write back your comments and suggestions to deliver better. Refernce Object Mix discussion:
http://objectmix.com/weblogic/549153-weblogic-monitoring-script-wlst-2.html -->

Thursday, October 27, 2011

WLST Errors and Exceptions

When first time you started using WLST you might get many of these Python based WLST Errors. Here I had collected few of them which are very simple to handle them with care. Only thing you need to understand when what kind of errors raises, and what need to do to handle them. When there is error on your flow of WLST Script or prompt don't be panic, relax for a moment then after a while take a deep breath and focus on your error and map with one of the following and do the required workaround.


In Jython we have issubclass() to check superclass, subclass relation we can verify class relationship. You can find parent-child relationship with it. As per my understanding the Error hierarchy can be defined in WLST(Jython) as follows:

This WLST(Jython) Error tree I prepared and posted for your reference, so that you can make your script in perfect manner, here you can find what is going wrong why it is happen while working out your script.
try:
 # WLST code Block 
 # perform some tasks that may throw an exception
except ExceptionType, ExceptionVar:
 # WLST code or
 # perform some exception handling
finally:
    # perform tasks that must always be completed (Will be performed before the exception is # raised.)
else:
 # execute code that must always be invoked

The pass statement in WLST

While writing WLST scripts, there are some situations where you need ‘do nothing’ statement syntactically. That is provided by the pass statement. When you start working on Exception handling this statement will be the first experimenting statement for you.

WLST raise statement

In WLST raise is used to generate or invoke an exception condition. The syntax of this statement allows three comma separated expressions which are optional. If no expression is present, WLST attempt to re-raise the last exception that was raised. This raise statement we can use when we need exception handling with robust scripts. When you pass the expressions to the raise statement, the first two expressions are evaluated to get the objects. These objects are then used to determine the type and value of the exception. Omitted expressions are treated as None. The third expression could be used for traceback objects.

wls:/offline> try:
...     raise Exception('SituationalResponse')
...except Exception, e:
...     print e
...
java.lang.Exception: SituationalResponse

SyntaxError

This you cannot be handled with the try-except block, because it will be thrown when your syntax is not in properly arranged, that is in the statement missing indentation or improper arguments. SyntaxError could be raised when the script lines are given for parsing, it will do token by token parsing wherever the improper syntax given WLST Shell points with cap char under the token.


Now let us see the sample indentation issue that raises the Syntax Error.
wls:/offline>; try:
...connect('system','weblogic103','t3://adminhost:adminport')
Traceback (innermost last):
(no code object)
at line 0
File
"", line 2
connect('system','weblogic103','t3://adminhost:adminport')
^
SyntaxError: invalid syntax

Another option for Syntax Error
This Error I have observed when I tried to migrate the WebLogic domain with createDomain() command.

wls:/offline/wdomain>createDomain('/home/backup/olddomain.jar', '/home/otherusr/domains/newdomain',’system', 'weblogic103')
Traceback (innermost last):
  (no code object) at line 0
  File "", line 1
        createDomain('/home/backup/olddomain.jar', '/home/otherusr/domains/newdomain',?system', 'weblogic103')
                                                                                                          ^
SyntaxError: Lexical error at line 1, column 99.  Encountered: "\ufffd" (65533), after : ""

This "Lexical error" got due to the copying from the webpage which has single quotes in different unicode value. When I retype the single quotes it was resolved.

Here in the above sample after issuing try block starting we must use a tab or 4 spaces before connect() command. When it found that is not
having proper indentation it raised the SyntaxError.

NameError


When the name used to do something like print or use in some other expression without assigning the value before it was defined then WLST will raises NameError. When first time scripting most of the time user encounters this unknowingly.

The following example might give you an idea how to resolve your issue.

wls:/offline> var1=100
wls:/offline> var3=var1+var2
Traceback (innermost last):
  File "", line 1, in ?

You can handle this kind of error with our try-except block
wls:/offline> try: var3=var1+var2
...except NameError, e:
...     print "Please check there is: ", sys.exc_info()[0], sys.exc_info()[1]
...
Please check there is:  exceptions.NameError var2

The beauty of handling your Exception/Error more transparent and easy to understand with sys.exc_info() list.

KeyError


This error can be raised by the WLST while using the dictionary objects or map objects accessed with non-matching key.
wls:/offline> urls['b']
Traceback (innermost last):
File
"", line 1, in ?
KeyError: b

ValueError

The ValueError is raised by the WLST shell when there is a inappropriate element is accessed in a list or a variable, that is such as the value specified for searching in the list with index() method. Removing the element which is not really exists in the list.
wls:/offline> L.index('web2')
Traceback (innermost last):
File
"<console>", line 1, in ?
ValueError: list.index(x): x not in list
I was working on thread and JVM monitoring script, encountered with the ValueError in different way. After storing the ThreadPool values, JVM values into local variables I was using C type of formatting to display the data in a row of Table. Some of the attribute values are Long integers, some of them plain integers some of them are strings.
 cd('/ServerRuntimes/'+ svr +'/ThreadPoolRuntime/ThreadPoolRuntime')
 thtot=`get('ExecuteThreadTotalCount')`
 thid= `get('ExecuteThreadIdleCount')`
 hog= `get('HoggingThreadCount')`
 sbth= `get('StandbyThreadCount')`
 cr =`get('CompletedRequestCount')`
 pr =`get('PendingUserRequestCount')`
 ql =`get('QueueLength')`
 th= `get('Throughput')`
 
 cd('/ServerRuntimes/'+svr+'/JVMRuntime/'+svr)
        freejvm = long(get('HeapFreeCurrent'))/(1024*1024)
        totaljvm = long(get('HeapSizeCurrent'))/(1024*1024)
        usedjvm = (totaljvm - freejvm)
      

When I ran with all numbered values with format as %5d it was shouted as follows:
ValueError: unsupported format character ' ' (0x20) at index 23
Don't know what attribute requires which format ... Initially to resolve this display without any format for all attributes values from the MBean.
print svr, thtot, thid, hog, sbth, cr, pr, ql, th, hs, totaljvm, freejvm, usedjvm
But still ValueError was exists, when I updated with formatter it was stuck with CompletedRequestCount that was not integer type, it is actually Long integer type and that was causing the Error. So, changed the format for that attribute it resolved one issue. Now the issue with different index number came... I have an idea that, if I found all the attributes and their data types then it will be easy to fix the right format for each. I tried the following way
print type(thtot),type(thid), type(hog), type(sbth), type(cr), type(pr), type(ql), type(th),type(freejvm), type(totaljvm), type(usedjvm)
formatted accordingly the ValueError is resolved.
print '%14s %10s %5s %5s %5s %5s %8s %5s %5s %8s %5dMB %5dMB %5dMB' %  (svr, hs, thtot, thid, hog, sbth, cr, pr, ql, th, totaljvm, freejvm, usedjvm) 
So now you can take care of Values of variables for your WLST code before use them for any operation!!

AttributeError


You might be on MBean tree where there is no such attribute defined and you tried to access it then WLST Shell raises AttributeError. Let us see an Example you can easily understand.

wls:/demodom/serverConfig> cmo.State()
Traceback (innermost last):
  File "", line 1, in ?
AttributeError: State
 
 

IndexError

The IndexError will be raised by the WLST shell, when thelist object is accessed with a out of range index value.

Let us see the example a list is defined with 5 elements

wls:/offline> L['app1', 'app2', 'app3', 'app4', 'web1']
when it is accessed with out of range index value say 7 then you get the IndexError.
wls:/offline> L[7]
Traceback (innermost last):
File
"<console>", line 1, in ?
IndexError: index out of range: 7

TypeError

The basic python object types int, str assignments or expressions or print statements with
concatenation does not allows you, raises the TypeError.

wls:/offline> print 'Number of servers:', 5
Number of servers: 5
 
wls:/offline>print 'Number of servers:'+ 5
Traceback (innermost last):
File
"<console>", line 1, in ?
TypeError: cannot concatenate 'str' and 'int' objects


Thanks for reading this post, Give your feedback in comments. cheers!!

Good References:
  1. http://www.doughellmann.com/articles/how-tos/python-exception-handling/
  2. http://www.jython.org/jythonbook/en/1.0/ExceptionHandlingDebug.html
  3. http://www.tutorialspoint.com/python/python_strings.htm

Monday, July 25, 2011

Wanna get the status of the applications in domain


In most of WebLogic domain environments we might have seen multiple applications deployed on WebLogic servers. It is difficult to check their status when server uses high CPU utilization. We can get the complete details by giving one input i.e., target-name.

We use navigate MBean tree more frequently while using interactive mode of WLST and in scripting. Here we can call any attribute from any MBean tree by using colon ':' at the MBean tree root. Here we go with a sample of  for you who struggling to understand navigate each and every time.

Please check the below code snippet and you can change as per your requirement.

#############################################################
"""
 This script will get you status of the applications which are deployed 
 in your WebLogic Domain.         
 script get you the colorful output                         
 NOTE : You need to give target name as an input to the script                
 Author: Krishna Sumanth Naishadam                         
"""
##############################################################
import sys

connect('username','password','t3://wl_admin_host:wl_admin_port')
targetName=sys.argv[1]
domainConfig()
apps=cmo.getAppDeployments()
for i in apps:
    navPath1=getMBean('domainConfig:/AppDeployments/'+i.getApplicationName())
    appID=navPath1.getApplicationIdentifier()
    navPath=getMBean('domainRuntime:/AppRuntimeStateRuntime/AppRuntimeStateRuntime')
    sts=navPath.getCurrentState(appID,targetName)
    if(sts == "STATE_ACTIVE"):
        print "\033[1;32m Status of " + i.getApplicationName() + ": " + sts + "\033[1;m"
    else:
        print "\033[1;31m Status of " + i.getApplicationName() + ": " + sts + "\033[1;m"
disconnect()
exit()
 

domain_app_status.sh
********************

WL_HOME="
# set up common environment
. "${WL_HOME}/server/bin/setWLSEnv.sh"

CLASSPATH="${CLASSPATH}:${WL_HOME}/common/eval/pointbase/lib/pbembedded51.jar:${WL_HOME}/common/eval/pointbase/lib/pbtools51.jar:${WL_HOME}/common/eval/pointbase/lib/pbclient51.jar"
read -p "Enter Target Name : " value1

"${JAVA_HOME}/bin/java" -Xmx124m -Dprod.props.file=${WL_HOME}/.product.properties weblogic.WLST domain_app_status.py $value1 $*

The lifecycle of deployment process happen in the following way:



The following Colors I had chosen for reflecting what state for a application on a server.
======
Status of APPNAME1: STATE_ACTIVE (Green Color)
Status of APPNAME2: STATE_FAILED (Red Color)
Status of APPNAME3: STATE_NEW (Red Color)


Please see below screenshot for exact output

References:

Sunday, March 20, 2011

WLST Tricks & Tips

Here I prepared few of the "Tips" and some commonly useful "Tricks" for developing the huge WLST scripts. These are all the learnings which I have came across in my daily working experiments with Programming Python commands for WLST scripts. These WLST commands can be applicable from WebLogic 9.x to WebLogic 10.3.6 and latest trending WebLogic 12c as well.
  1. Tip 1: Know about Where are you in WLST?


  2. On some situations you might need a clarity about which WebLogic version you are using. WebLogic 11g (10.3) has different subsequent versions 10.3.1,10.3.2,10.3.3 and 10.3.4, for all these the directory structure is ~/Oracle/Middleware/wlserver_10.3 which does not tells you about sub versions. Here WLST  is having a solution for this problem,

    You can find the current WebLogic version to which WLST is connected.

    wls:/offline> print version
    WebLogic Server 10.3.3.0  Fri Apr 9 00:05:28 PDT 2010 1321401
    

    How do you know that the WLST Shell running on which JVM version? The simple solution is you this following Python command that will gives you:

    wls:/offline> sys.platform
    'java1.6.0_21'

  3. Tip 2. How to know Jython version is used by WLST?


  4. To get the Jython version you can use sys.version_info method that will returns. or you can use sys.version exact version.

    wls:/offline> import sys
    wls:/offline> sys.version_info
    (2, 2, 1, 'final', 0)
    
    

    Tip 3. Introspection in WLST


    You might understand that using WLST provided help() sometimes you cannot reach your desired level of script code. Some thing that won't be documented but you might need it to develop the prototype in your WLST script. Often I found this could be a need, most helpful way to reach depth of WLST classes, modules, functions. Best way is we need to use Python introspection methods. It is a wonderful way to resolve your coding clues to use best performing script as outcome.

    In some of the situations, I felt using Jython (Java method) is lengthy than using Python. When Python giving you desired outcome in two lines of code why do you choose Java imports and classes and code become 6-10 lines.

    You might be confused sometimes, brain storm about something why a MBean not working or giving the value of an attribute etc. In your mind there could be a question "what is this actually??" Best solution for this is using Python introspection built-in methods.

    dir([WLST/Python Object])
    
    
    If your WLST MBean or module or a function has documented then you use the following to get that:
    _doc__
    

    In Jython there could be classes or interfaces
    __class__
    

    Tip 4. Naming Rules for WLST


    WLST script can have names are case sensitive and cannot start with a number.  They can contain letters, numbers, and underscore symbols. Let us see few examples here:
     state  State  _state  _2_state_  state_2  StatE

    Most of us face an issue what name makes sense for a variable, module or classwhile writing the WLST scripts. Just like Java Language you can follow specific naming rules, we can also find keyword list available in WLST with the following commands

    
    wls:/offline> import keyword
    wls:/offline> keyword.kwlist
    ['and', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'yield']
    

    Modules, packages: use lowercase
    Classes: use Capitalized first letters in the Words also follow for exceptions that you create
    Methods, attributes: use lowercase_words
    Local variables: use alphanumeric i, j, sum, x0, etc.
    Globals: use alphanumeric long_descriptive_names

    wls:/offline> sys.modules
    {'weblogic.store.admintool.CommandDefs.CommandType': , ...'sys': sys module, 'weblogic.management.scripting.utils': }
    
    
    
    

    Introspection reveals useful information about your program's objects

    Tip 4 Write a readable script


    While writing a script think about the human readers, Question yourself can you still read your own code ???
    next month?
    next year?
    • Be consistent (but not too consistent!)
    • Use white-space judiciously
    • Write appropriate comments
    • Write helpful doc strings -- not stories or novels
    • Confirm to the existing style even if it’s not your favorite style!
    • local consistency overrides global
    • Update the comments!!and the doc strings!!!

    """Brief one-line description.
    
    Longer description, documenting
    argument values, defaults,
    return values, and exceptions.
    """
    

    When to use classes in WLST? (...and when not!)
    If your script objective is going to have multiple object creation then go for Object-Orientation.

      • You could choose class members or attribute  at the first time
      • name clashes between attribute

    Tip 5 Convene print statement with str()


Most of us from Java/JEE development background common attitude is that using the + operator overloading for strings. Sometimes your WLST script might need to have a print statement, that could include values from a variable or some mathematical expression that might be int type or some other object type. Then such cases, better to use that variable type must be converted to string type by using Python built-in function str() as shown :

print 'Heap Size' + str(totalHeap)

Tip 6: Create single properties file

Every Middleware admin whoever uses this WLST in their environment builds, they must create/use a single properties file where you can have:

  1. Domain properties - username, password, admin url, cluster list
  2. Database configuration properties
  3. JMS configuration properties
  4. WorkManager properties
  5. Monitoring Threshold properties

Tip 7: Using time in WLST


In my daily news updates from social medias I found in reddit.com in the Python community doing excellent there is lots of news about the changes happening with Python programming. One of the blog found very nice examples with date and time functions in Python this can be applicable for our WLST too.

Setting UTC time zone in Python

WLST Tricks


We have come across many situations where it is simple trick works faster to work with WLST scripting. some of them collected here and future also we will update this WLST tricks

Trick 1. Multiple Assignment

In WLST you can assign multiple variables with corresponding multiple values at the same statement or command line.

wls:/offline> cl, ms = ['appclstr','webclstr'], ['app01','app02','web01','web02']
wls:/offline> cl
['appclstr', 'webclstr']
wls:/offline> ms
['app01', 'app02', 'web01', 'web02']


Trick 2. Connect admin without Credentials

When you use storeUserConfig() command for your WebLogic domain environment, the trick here is when you don't specifying any arguments such as user security file, key file paths. WebLogic system automatically generates the following two files:
1. username-WebLogicConfig.properties
2. username-WebLogicKey.properties

For example, Let us assume your user name is 'padmin' then storeUserConfig() command will generates two files as:
* padmin-WebLogicConfig.properties
* padmin-WebLogicKey.properties

Once you got this auto-generated files in you home ($HOME in Unix) directory, WLST Shell automatically detects its existance from this location. You don't need to give the userConfig, Key file paths while connecting. Simply you can connect by giving the adminurl as url value.

wls:/offline> connect(url='t3://myapp.host.com:8756')
Connecting to t3://myapp.host.com:8756 with userid weblogic ...
Successfully connected to Admin Server 'wadmn' that belongs to domain 'mydomain'.

Warning: An insecure protocol was used to connect to the
server. To ensure on-the-wire security, the SSL port or
Admin port should be used instead.

Trick 3: Command Trials

The interactive mode is great for getting instant feedback on the behavior of each WLST command. Having the whole startup, connection, session-init is time-consuming and the interactive mode of WLST avoids this.

First time if you are making a script better idea is have duplicate windows of the host. In one window you can edit and save according to your required changes, on the other hand you can execute the file with execfile('urScript.py').

Trick 4: Using loadProperties

One of my blog follower Raghu asked me how to use properties in the WLST script. Though I had used different types of properties from properties file, but his requirement is something different he want to reuse the WLST script only by changing the properties file.

cat mys.properties
SERVERS=myser1,myser2,myser3
ADMINSERVER=demoAdmin


Here is the WLST script snippet that uses above defined properties using loadProperties() built-in function call
loadProperties('path/mys.properties')
print SERVERS
serverlsit=SERVERS.split(',')
print serverlist[1]

for i in serverlist:
    print i

Remember that properties are just like Java language properties or C/C++ define constants, which holds name, and corresponding the string values. So when you store portno in properties file better convert using int().
Hope this is useful for your reusable scripts.

Trick 5: How to debug WLST script?

The best way to identify the WLST script bugs using dumpStack(). This works only when you are running interactive mode. If you found a script (such as my blog) or from somewhere after you update all properties you wish to test and it doesn't works! then you wish to debug it.

1. Using simple print variable values
2. Using Python exception values
3. Double check indentations
4. Casting values (converting values str to int or str to bool)

Some of the cases you need to understand that casting fails the values are not allowed to change because WLST variables are created in Runtime. The datatypes are strong type like Java and C++ languages and dynamic type while running it will be assigned to a datatype.

You can enable debug flag at the time of invocation of WLST shell.

java -Dpython.verbose=debug weblogic.WLST

Also you have one more option using debug("true") or set('DebugEnabled', 'true') in the starting of WLST script that will force debug output

If you are using OEPE (Eclipse for developing WLST) then you have much scope to debug every variable content. Right click on the WLST script select 'Debug As', choose 'WLST run' from the list Menu. Please check the screenshot that give you more clear idea on this Oracle link.

Trick Cancel the Edit in WLST

Today while working on WLST in interactive mode to fix the JMS configuration issue, sometime you start editing the configuration you might need to undo the changes you did on the edit tree. This is possible using cancelEdit() give the answer y to confirm when it prompts you. Else you can use cancelEdit('y') as a trick.

Trick 6: Suppress Junk Output in WLST

There is junk when you capture the list from ls(returnMap='true') command execution.
If you are running WLST in *nix based environment you can use /dev/null path for suppressing the junk outputs as shown below redirect command.

redirect('/dev/null','false')
ls()
redirect('/dev/null','true')


Trick 7: Resolve indentation/dedent issue with vi setting


WLST Code copied from NotePad++ to vi editor tabspace issue
when you write few lines in the notepad++ it takes 4 spaces as tabspace, but in the vi editor it is 8 it mismatches and cannot fit into the block. So when run the script it throws 'dedent' issue. To resolve this in vi editor you can set the tabspace=4

: set tabspace=4

Keep writing your valuable comments and great suggestions to improve this blog tutorial ...

References:
  1. 1. Dive into Python
  2. Python Library link
  3. http://forums.oracle.com/forums/thread.jspa?messageID=9416182&tstart=0

Monday, February 21, 2011

Configuring GridLink DataSources

WebLogic 10.3.4 is having new feature as High availability and fail over control with Oracle Notifying Service (ONS) as client at WebLogic sever side. Which enables your environment to track if one of RAC node is down or Listener down.

edit()
cd('/')
cmo.createJDBCSystemResource('ds1')

cd('/JDBCSystemResources/ds1/JDBCResource/ds1')
cmo.setName('ds1')

cd('/JDBCSystemResources/ds1/JDBCResource/ds1/JDBCDataSourceParams/ds1')
set('JNDINames',jarray.array([String('GLDS01')], String))

cd('/JDBCSystemResources/ds1/JDBCResource/ds1/JDBCDriverParams/ds1')
cmo.setUrl('jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)
(HOST=dbhost.com)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)
(HOST=dbhost.com)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=ORASERVICE)))\r\n\r\n')
cmo.setDriverName('oracle.jdbc.OracleDriver')
cmo.setPassword(DBPASS)

cd('/JDBCSystemResources/ds1/JDBCResource/ds1/JDBCConnectionPoolParams/ds1')
cmo.setTestTableName('SQL SELECT 1 FROM DUAL\r\n\r\n')

cd('/JDBCSystemResources/ds1/JDBCResource/ds1/JDBCDriverParams/ds1/Properties/ds1')
cmo.createProperty('user')

cd('/JDBCSystemResources/ds1/JDBCResource/ds1/JDBCDriverParams/ds1/Properties/ds1/Properties/user')
cmo.setValue('DBUSER')

cd('/JDBCSystemResources/ds1/JDBCResource/ds1/JDBCDataSourceParams/ds1')
cmo.setGlobalTransactionsProtocol('TwoPhaseCommit')
 
cd('/SystemResources/ds1')
set('Targets',jarray.array([ObjectName('com.bea:Name=appclstr,Type=Cluster')], ObjectName))

 cd('/JDBCSystemResources/ds1/JDBCResource/ds1/JDBCOracleParams/ds1')
cmo.setFanEnabled(true)
cmo.setOnsNodeList('node1host.com:6200,node2host.com:6200')

save()
activate()


Before you configure this, make sure ONS service configure at RAC nodes. So, please confirm it from your ORACLE DBA. One more things, this is applicable only when your environment have Oracle Database 10.2.+ for RAC.






This GridLink datasource is the alternative for Multi datasource. You don't need to configure individual data sources for each node. In this GridLink you can enter all the RAC node details at once. Targeting and testing is same as generic data source you can verify on your WebLogic console.

Best References
1. http://download.oracle.com/docs/cd/E17904_01/web.1111/e13737/gridlink_datasources.htm
2. http://www.cnblogs.com/mengheyun/archive/2011/02/13/1953114.html
3. http://theblasfrompas.blogspot.com/2011/02/jruby-script-to-monitor-oracle-weblogic.html
4. http://www.youtube.com/watch?v=THBUr_x7mUE
5. http://www.youtube.com/watch?v=5icksYdkj-c

Thursday, February 17, 2011

OEPE the best WLST Editor


Now we have, Oracle given a nice GUI editor for WLST scripts. I started looking about it one of my blog commenter Lukas was asked me about it. Oracle released two versions of this Eclipse editor:
  1. Eclipse 3.6 (Helios) Edition
  2. Eclipse 3.5.2 (Galileo) Edition
It has built support for Python scripts and PyDev. Recently I had downloaded new OEPE-Galileo-All-In-One-11.1.1.6.0.201007221355-Win32.Zip. It is really “All in One” why because it has connectivity to WebLogic Server Local/Remote options with all categories of versions supported by WLST. It is included WLST MBean Explorer, built-in WLST Help provided in one of tab.

Here I am going to tell about that what you need to look in this because introductory blog already given by Edwin Biemond from Oracle
OEPE for WLST 

Video blog...
There is nothing to know about much about hidden MBean hierarchies. WLST on OEPE (Eclipse) makes more fun in creating new scripts. More over the OEPE Templates are awesome!! God bless this template creator.  Oracle WLST people given commonly used scripts as templates. Which makes you no efforts to write the line-by-line script writing. GUI makes more work in less time meaning increasing productivity and performance!!!

Ready made Templates
OEPE gave us the following templates as ready-made script templates. You need to change the values or parameters to whatever you want to name for your environment or WebLogic domain. 

  1. Default: WLST online
  2. Create Basic WebLogic Domain
  3. Create WebLogic Cluster
  4. Create WebLogic Domain with JMS and JDBC Resources
  5. Configuring JMS System Resource
  6. Configuring JDBC DataSource Delete  JDBC Data Source
  7. Delete JMS System Resource
  8. Delete WebLogic Cluster
You might be using WebLogic portal or WebLogic Integration or some other WebLogic domain these are core common scripts templates can be applicable to any of them.



Most of the developers requires the Deleting JDBC resources and want to create a fresh DataSource with changed database parameters.

In production environment some of the sites you might need to remove the machines due to their utter performance. “Delete WebLogic Cluster” is the wonderful script for you. You need to give the managed servers list, cluster(s) you want to remove from the domain.
Cons of OEPE
  1. To run OEPE on your desktop requires good amount of MEMORY (RAM).
  2. Sometimes iexplorer stuck you cannot open OEPE anyway it is Windows issue.
  3. JVM Settings of eclipse.ini file need to be updated according to your operating environment. Anyway I found the best reference to solve JVM settings issue at stackoverflow.com
Expecting more exciting things from WLST users so…keep writing your comments, updates about OEPE using WLST.




In these amazon ads you can click on 'Look inside' give you some idea about the above books. And don't forget to enjoy the sample chapters of these books.

While working on eclipse there could be need to pass arguments to your WLST script. Yes!! You can do that goto Run As options select Run Configuration. In the Run Configuration window select the Arguments tab,  you can give Program Arguments.

Good References:
1. http://www.oracle.com/technetwork/developer-tools/eclipse/downloads/index.html
2. http://biemond.blogspot.com/2010/08/wlst-scripting-with-oracle-enterprise.html
3. http://stackoverflow.com/questions/142357/what-are-the-best-jvm-settings-for-eclipse

Popular Posts