Tom Janofsky Consulting

Here are the PowerPoint slides for a presentation I gave for the Delaware Valley BEA Users' Group, entitled "Weblogic Admin Best Practices".

This presentation covered a broad range of best practices, hints and tips, and general advice for the use of WebLogic in a production environment. [Disclaimer] Some of the following advice adheres closely to WebLogic recommendations (e.g. the security section) others are not BEA documented approaches (.wlnotdelete, how to hassle BEA support). Many statements are generalizations representing a personal point of view, and your mileage may vary.


Process






Deployment Architecture








Debugging WebLogic Administration




















Performance









Security










Scripting

The attached script exposes the following capabilities of WebLogic Administration to the command line:

#!/bin/bash
#
# This script exposes some WebLogic maintenance functions on the command line
# In particular, it allows for stopping servers, and starting and stopping applications
# from the command line
#
# Upkeep: This script will need new servers added as they are added to the environment
#
# Author: Tom Janofsky
#
CLASSPATH=${BEA_HOME}/weblogic700/server/lib/weblogic.jar

#
# First, a menu to get the server we want to operate on
#
echo
echo "Server List"
echo "-----------"
echo

PS3="Select Server >"
OPTIONS="server1 server2 Quit"
select opt in $OPTIONS; do
	if [ "$opt" = "server1" ]; then
        	ADMIN_URL="t3://server1:7001"
		SERVER_URL="t3://server1:7001"
		SERVER="server1"
		break
	elif [ "$opt" = "server2" ]; then
        	ADMIN_URL="t3://server2:7001"
		SERVER_URL="t3://server2:7004"
		SERVER="serv er2"
		break
	elif [ "$opt" = "Quit" ]; then
		exit 0
	else
		echo "Not a valid server"
	fi

done

#
#Get the admin password
#
echo
echo -n "Please enter the admin password for this server: "
read -s PA
echo

#
# Pick an operation
#

JAVA_CMD="${BEA_HOME}/jdk131_06/bin/java"
ADMIN_CMD="${JAVA_CMD} -classpath ${CLASSPATH} weblogic.Admin -url ${ADMIN_URL} -username weblogic -password ${PASSWORD}"
SERVER_CMD="${JAVA_CMD} -classpath ${CLASSPATH} weblogic.Admin -url ${SERVER_URL} -username weblogic -password ${PASSWORD}"
DEPLOY_CMD="${JAVA_CMD} -classpath ${CLASSPATH} weblogic.Deployer -adminurl ${ADMIN_URL} -username weblogic -password ${PASSWORD}"
PS3="Select Command >"

while [ true ]; do

   echo
   echo "Operations"
   echo "----------"
   echo

   OPTIONS="Ping Shutdown View-License List-JNDI View-Log Thread-Dump Get-Server-State List-Installed-Applications Stop-Application Start-Application Pick-Another-Server Quit"

   select opt in $OPTIONS; do
	if [ "$opt" = "Ping" ]; then
		${ADMIN_CMD} PING
		break
	elif [ "$opt" = "Shutdown" ]; then
		${ADMIN_CMD} SHUTDOWN ${SERVER}
		break
	elif [ "$opt" = "View-License" ]; then
		${ADMIN_CMD} LICENSES
		break
	elif [ "$opt" = "List-JNDI" ]; then
		${SERVER_CMD} LIST /
		break
	elif [ "$opt" = "View-Log" ]; then
		${SERVER_CMD} SERVERLOG
		break
	elif [ "$opt" = "Thread-Dump" ]; then
		${SERVER_CMD} THREAD_DUMP
		break
	elif [ "$opt" = "Get-Server-State" ]; then
		${SERVER_CMD} GET -pretty -type ServerRuntime -property State
		break
	elif [ "$opt" = "List-Installed-Applications" ]; then
		${SERVER_CMD} GET -pretty -type ApplicationRuntime -property ApplicationName
		break
	elif [ "$opt" = "Start-Application" ]; then
		echo "Enter application name:"
		read APP_NAME
		${DEPLOY_CMD} -undeploy -name ${APP_NAME}
		break
	elif [ "$opt" = "Stop-Application" ]; then
		echo "Enter application name:"
		read APP_NAME
		${DEPLOY_CMD} -activate -name ${APP_NAME}
		break
	elif [ "$opt" = "Pick-Another-Server" ]; then
		exit
	elif [ "$opt" = "Quit" ]; then
		exit 0
	else
		echo "Not a valid operation"
	fi

   done
done




And don't forget about direct programmatic access to MBeans - you can have complete control this way. Also be sure to check out WLShell. The attached program shows how to create and manipulate JDBC connection pools and data sources.

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import weblogic.management.Helper;
import weblogic.management.MBeanHome;
import weblogic.management.MBeanCreationException;
import weblogic.management.DistributedManagementException;
import weblogic.management.configuration.JDBCConnectionPoolMBean;
import weblogic.management.configuration.JDBCDataSourceMBean;
import weblogic.management.configuration.ServerMBean;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.management.InstanceNotFoundException;
import javax.management.InvalidAttributeValueException;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * This class will create connection pools and data sources in a running WebLogic server
 * from an XML file of the format:
 *
 *

 <datasources>
    <server name="myserver"
        url="t3://localhost:7001"
        adminUser="weblogic"
        adminPassword="password">

        <pool driver="oracle.jdbc.driver.OracleDriver"
            url="jdbc:oracle:thin:@host:1521:SID"
            user="USER"
            password="PWD"
            pool_name="pool_name"
            ds_name="ds_name"
            />
        <pool driver="oracle.jdbc.driver.OracleDriver"
            url="jdbc:oracle:thin:@host2:1521:SID2"
            user="user"
            password="PWD"
            pool_name="pool_name2"
            ds_name="ds_name2"
            />

    </server>
    </datasources>

 *
 *
 * Each pool entry will create its own connection pool and JDBC data source.  If a connection pool
 * of the given name already exists, it's parameters will be updated to the params in the file.  If a
 * data source of the given ds_name already exists, it will also be updated.
 *
 * @author Tom Janofsky
 *
 */
public class CreateWebLogicJDBC {

    public static void main(String[] args) throws Exception {
        new CreateWebLogicJDBC().execute(args);
    }

    private void execute(String[] args) throws ParserConfigurationException, SAXException, IOException, InstanceNotFoundException, MBeanCreationException, InvalidAttributeValueException, DistributedManagementException {
        InputStream is = null;
        if (args.length != 1) { //try loading it from the classpath, if not, show usage
            is = this.getClass().getResourceAsStream("datasources.xml");
            if (is == null) usage();
        } else {
            is = new FileInputStream(args[0]);
        }

        //load and parse XML
        WeblogicJDBCData[] dataSources = getDataSources(is);

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        System.out.print("WebLogic host URL is ("+WeblogicJDBCData.serverurl+") Hit enter to accept, or type new URL:");
        String line = br.readLine();
        if (line != null && line.trim().length() > 0) WeblogicJDBCData.serverurl = line;

        System.out.print("WebLogic server name is ("+WeblogicJDBCData.serverName+") Hit enter to accept, or type new name:");
        line = br.readLine();
        if (line != null && line.trim().length() > 0) WeblogicJDBCData.serverName = line;

        System.out.print("WebLogic username is ("+WeblogicJDBCData.adminUser+") Hit enter to accept, or type new user:");
        line = br.readLine();
        if (line != null && line.trim().length() > 0) WeblogicJDBCData.adminUser = line;

        System.out.print("WebLogic password is ("+WeblogicJDBCData.adminPassword+") Hit enter to accept, or type new pwd:");
        line = br.readLine();
        if (line != null && line.trim().length() > 0) WeblogicJDBCData.adminPassword = line;

        //create a datasource for each entry
        for (int i = 0; i < dataSources.length; i++) {
            WeblogicJDBCData source = dataSources[i];

            //Get the admin home and the server bean
            MBeanHome adminHome = Helper.getAdminMBeanHome(source.adminUser, source.adminPassword, source.serverurl);
            ServerMBean serverMBean = (ServerMBean) adminHome.getAdminMBean(source.serverName, "Server");
            JDBCConnectionPoolMBean poolBean = (JDBCConnectionPoolMBean) adminHome.findOrCreateAdminMBean(source.pool_name, "JDBCConnectionPool");
            Properties pros = new Properties();
            pros.put("user", source.user);

            // Set DataSource attributes
            poolBean.setURL(source.dsurl);
            poolBean.setDriverName(source.driver);
            poolBean.setProperties(pros);
            poolBean.setPassword(source.password);
            poolBean.setLoginDelaySeconds(1);
            poolBean.setInitialCapacity(0);
            poolBean.setMaxCapacity(2);
            poolBean.setCapacityIncrement(1);
            poolBean.setShrinkingEnabled(true);
            poolBean.setShrinkPeriodMinutes(10);
            poolBean.setRefreshMinutes(10);
            poolBean.setTestTableName("dual");
            poolBean.addTarget(serverMBean);

            // Create DataSource  MBean
            JDBCDataSourceMBean dsMBeans = (JDBCDataSourceMBean) adminHome.findOrCreateAdminMBean(source.pool_name, "JDBCDataSource");

            // Set DataSource attributes
            dsMBeans.setJNDIName(source.ds_name);
            dsMBeans.setPoolName(source.pool_name);

            // Startup datasource
            dsMBeans.addTarget(serverMBean);

            is.close();
            System.out.println("Set datasource = " + dataSources[i].dsurl);
        }
    }

    /**
     * Parse the XML file, and build data sources
     * @param file
     * @return
     * @throws ParserConfigurationException
     * @throws SAXException
     * @throws IOException
     */
    private static WeblogicJDBCData[] getDataSources(InputStream file) throws ParserConfigurationException, SAXException, IOException {
        List list = new ArrayList();

        DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();
        builder.setValidating(false);
        builder.setExpandEntityReferences(false);
        DocumentBuilder db1 = builder.newDocumentBuilder();
        DocumentBuilder db = db1;
        Document doc = db.parse(file);
        Element root = doc.getDocumentElement();
        NodeList beans = root.getChildNodes();
        for (int i = 0; i < beans.getLength(); i++) {
            Node node = beans.item(i);


            if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equals("server")) {
                Element element = (Element) node;
                WeblogicJDBCData.serverurl = element.getAttribute("url");
                WeblogicJDBCData.serverName = element.getAttribute("name");
                WeblogicJDBCData.adminUser = element.getAttribute("adminUser");
                WeblogicJDBCData.adminPassword = element.getAttribute("adminPassword");

                NodeList children = node.getChildNodes();
                for (int j = 0; j < children.getLength(); j++) {
                    Node child = children.item(j);
                    if (child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals("pool")) {
                        Element pool = (Element) child;

                        WeblogicJDBCData data = new WeblogicJDBCData();
                        data.driver = pool.getAttribute("driver");
                        data.ds_name = pool.getAttribute("ds_name");
                        data.user = pool.getAttribute("user");
                        data.password = pool.getAttribute("password");
                        data.dsurl = pool.getAttribute("url");
                        data.pool_name = pool.getAttribute("pool_name");
                        list.add(data);
                    }
                }
            }
        }

        return (WeblogicJDBCData[]) list.toArray(new WeblogicJDBCData[list.size()]);
    }

    /**
     * Display usage and exit
     */
    private static void usage() {
        System.err.println("Usage: java CreateWebLogicJDBC ");
        System.exit(1);
    }

    /**
     * Inner class representing the data source
     */
    private static class WeblogicJDBCData {
        //deliberately static since these are the same for one run
        static String serverurl;
        static String serverName;
        static String adminUser;
        static String adminPassword;

        String driver;
        String dsurl;
        String user;
        String password;
        String ds_name;
        String pool_name;
    }
}

straight to the top