« March 2009 | Main | July 2009 »

April 2009 Archives

April 8, 2009

A Simple Job Scheduler Example - WebLogic Server Clustered Timer

Did you know WebLogic Server can schedule future tasks similar to a cron job?  This even works in a WebLogic cluster.  Using a cluster ensures that as long as one of the managed servers in the cluster is available, your task has a high-availability characteristic and the task will execute.  This has come up for at least 3 of my local customers.  Every once in awhile I see questions about WebLogic timers from my peers, so I thought I’d share a simple example for how this works and some extra tidbits based on personal experience that might not be in the standard documentation.  Read on if you want to see how to schedule a simple println() task to execute every 30 seconds in a cluster that can survive server failures in both the WebLogic tier and the database tier (provided you use Oracle RAC).

HA

Background

Oracle (then BEA Systems) and IBM collaborated on a common API for Timers and Work Managers (think multi-threading) that would be portable across application servers.  They aptly named this API CommonJ.  This API has been supported in WebLogic Server since 9.x and apparently in WebSphere since 6.x.  When combined with WebLogic clustering support, the CommonJ Timer API is known as the Job Scheduler.  It requires some configuration as described in the docs, but essentially the way it works under the covers is by serializing the class that will execute the task and some related metadata to a database.  Using the leasing feature of WebLogic Server, exactly one cluster member will be responsible for JobScheduler (singleton service) which executes the Timer Tasks.  The server responsible for this service will check the database every 30 seconds to see if there are new tasks to execute.

Instructions for the System Out Example Timer

These instructions assume starting from scratch with nothing but a basic WebLogic Server installation and a database like Oracle XE.  I run all of this easily on my 2+ yr old laptop (I do have 3+ gig of ram).  The documentation is more detailed now, so definitely refer to that as well.

  1. Create a new domain with 1 Admin Server and at least one Managed Server that will be a part of a cluster.  Refer to the Oracle By Example page for WLS if you need help with this, but you should be able to do all of this from the Configuration Wizard.  I named my cluster “myCluster” and my managed servers “managedServer1” and “managedServer2”.
  2. Set up the database – Basically run the DDL for your DB, which will create a table called WEBLOGIC_TIMERS. If you don’t set up database often, here is my simple POC sequence with Oracle XE.  In production, I would recommend Oracle RAC with a Multi Data Source, but you can POC this with an XE database or a single database node if you can live with a single point of failure.  Open the XE database web console and create a new database user, of course I use weblogic/weblogic for the user name password and give them admin rights.  Start sqlplus and login as that user.  Navigate to the directory that contains the DDL you want to run and use the @ syntax to execute the DDL like this.  You can of course ignore the messages about the comments not being valid commands: scheduler.ddl
  3. Keep the sql prompt open, we’ll use it again in a minute.  Notice that the script is in the oracle\920 directory, that simply means for 9.2+ of Oracle DB, it works totally fine for me on XE 10g.
  4. Configure the data source – Create a new data source for this and target it at all the servers in your domain (or at least the ones in your cluster) and specify it as the cluster’s JobScheduler Data Source.  I recommend that you test your data source when you are creating it.
  5. Set up leasing – You can use consensus or database leasing, but since we already using the DB for the Job Scheduler, just do database leasing which creates a table called ACTIVE (at least in the recent releases of WLS, it used to be something like WEBLOGIC_ACTIVE in earlier releases).  This means running the appropriate WL_HOME/server/db/dbname/leasing.ddl as well as configuring the data source, which can be the same one you used before, and configuring the cluster to use that data source for leasing.  Make sure you note database based leasing requires a highly-available database.  If the connection goes away, the managed servers will fail.  For this reason you can use multi data sources with Oracle RAC to get an even more HA architecture, but Oracle XE works fine for a POC.  I got consensus leasing to work at one time in the past using WLS 9.2, but if I remember correctly I had to install Node Manager and configure “machines” for my servers for it to work.  So DB-based leasing is what I’m using in this example because it’s simpler and I have not had issues with it before. leasing.ddl
  6. Write some code – There is a sample in the docs showing how to look up the job scheduler and schedule a task.  I’ll take care of that for you, here is a WAR (Servlet 2.5 based) that has code to register the task via a servlet and a JAR file that contains the class that implements the TimerListener interface.  The source code is at the way bottom of this post.
  7. Deploy the WAR file, target it at the cluster, and make sure the application is started.
  8. Edit your server classpath to contain the timer implementation class which is in the JAR referenced earlier.  You might be asking yourself, why the heck does the timer listener class need to be placed on the system classpath?!!  Well if you think about how the classloaders work, the singleton service running the tasks does not have access to the classes from the JEE module that registered the timer.  It is running as a WebLogic system thread.  This class will be deserialized from the database, potentially on another server.  So I recommend not doing anything too sophisticated in the timer listener.  If you have lots of logic with multiple classes, just consider having the timer listener drop a message on a distributed JMS queue, which can have an MDB from another application that does all of your heavy lifting.  Back to putting the TimerListener implementation on the classpath, I accomplished this by added the following line to my domain’s setDomainEnv.cmd script.  There is also the option to use an EJB Timer, which apparently does not have the system classpath requirement, but I haven’t tried that before.
    set PRE_CLASSPATH=C:\JDeveloper\mywork\JobSchedulerApp\TimerListener\deploy\TimerListener.jar
    
  9. Optional – Enable verbose logging for the related sub-systems, I find this helpful when troubleshooting. 
    set JAVA_OPTIONS=%JAVA_OPTIONS% -Dweblogic.debug.DebugSingletonServices=true -Dweblogic.JobScheduler=true

  10. Restart your Admin Server and Managed Server.  Make sure you see the JAR in the classpath settings in the log file.  args
  11. If your enabled the additional logging, you should see that leasing and job scheduler are creating log entries like the following in the managed server log file (not in standard out!). 
  12. ####<Apr 8, 2009 3:10:01 PM CDT> <Debug> <SingletonServices> <jbayer-lap> <managedServer1> <[ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1239221401078> <BEA-000000> <SingletonMonitor: Checking Failed Leases> 
    ####<Apr 8, 2009 3:10:11 PM CDT> <Debug> <SingletonServices> <jbayer-lap> <managedServer1> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1239221411078> <BEA-000000> <SingletonMonitor: Now checking lease statuses.> 
    ####<Apr 8, 2009 3:10:11 PM CDT> <Debug> <SingletonServices> <jbayer-lap> <managedServer1> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1239221411078> <BEA-000000> <SingletonMonitor: Checking for registered Migratable Targets and Singleton Services without a lease> 
    ####<Apr 8, 2009 3:10:11 PM CDT> <Debug> <SingletonServices> <jbayer-lap> <managedServer1> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1239221411078> <BEA-000000> <SingletonMonitor: TimerMaster - Found an owner - -7090657857495109585/managedServer1> 
    ####<Apr 8, 2009 3:10:11 PM CDT> <Debug> <SingletonServices> <jbayer-lap> <managedServer1> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1239221411078> <BEA-000000> <SingletonMonitor: Checking existant, but expired leases> 
    ####<Apr 8, 2009 3:10:11 PM CDT> <Debug> <SingletonServices> <jbayer-lap> <managedServer1> <[ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1239221411078> <BEA-000000> <SingletonMonitor: Checking Failed Leases> 
    ####<Apr 8, 2009 3:10:21 PM CDT> <Debug> <SingletonServices> <jbayer-lap> <managedServer1> <[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1239221421078> <BEA-000000> <SingletonMonitor: Now checking lease statuses.> 
    ####<Apr 8, 2009 3:10:21 PM CDT> <Debug> <SingletonServices> <jbayer-lap> <managedServer1> <[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1239221421078> <BEA-000000> <SingletonMonitor: Checking for registered Migratable Targets and Singleton Services without a lease> 
    ####<Apr 8, 2009 3:10:21 PM CDT> <Debug> <SingletonServices> <jbayer-lap> <managedServer1> <[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1239221421078> <BEA-000000> <SingletonMonitor: TimerMaster - Found an owner - -7090657857495109585/managedServer1> 
    ####<Apr 8, 2009 3:10:21 PM CDT> <Debug> <SingletonServices> <jbayer-lap> <managedServer1> <[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1239221421078> <BEA-000000> <SingletonMonitor: Checking existant, but expired leases> 
    ####<Apr 8, 2009 3:10:21 PM CDT> <Debug> <SingletonServices> <jbayer-lap> <managedServer1> <[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'> <<WLS Kernel>> <> <> <1239221421078> <BEA-000000> <SingletonMonitor: Checking Failed Leases> 

  13. Register the timer by hitting the URL or invoking the web service of one of the managed servers.  In my case that is http://localhost:7011/TimerWeb/timerservlet.  Note that each time you invoke the URL successfully a new timer listener will be registered with the cluster, so you probably only want to do this once.
  14. Notice the messages in standard out if this is working correctly.
  15. timerExpired() called at 4/8/09 3:12 PM
    timerExpired() called at 4/8/09 3:13 PM

  16. Shut down the managed server that has the messages printing to standard out.  You should see the messages show up on another managed server in the cluster in standard out.
  17. Now shut down all of the managed servers and restart at least one.
  18. You should see the timer task start printing to standard out when one of the managed servers in the cluster is available.

Summary

So you should have a working timer example in WebLogic Server that survives failures.  The debug messages in the managed server log files can be helpful in trouble-shooting in case anything goes wrong.  A couple other things to note, you cannot cancel timer tasks via CommonJ API calls when running in the JobScheduler.  You have to use the JobRuntimeMBean for that.  I’ll show an example of using this bean with WLST in another entry.  Here is the source code for the servlet and the timer listener classes.  Hopefully this will help you utilize this powerful capability built-in to WebLogic.

package view.jamesbayer;
import commonj.timers.TimerManager;
import jamesbayer.client.SystemOutTimerListener;
import java.io.IOException;
import java.io.PrintWriter;
import javax.naming.InitialContext;
import javax.servlet.*;
import javax.servlet.http.*;
public class TimerServlet extends HttpServlet {
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }
    public void service(HttpServletRequest request,
                        HttpServletResponse response) throws ServletException,
                                                             IOException {
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<head><title>TimerServlet</title></head>");
        try {
            System.out.println("service() entering try block to intialize the timer from JNDI");
            InitialContext ic = new InitialContext();
            TimerManager jobScheduler =
                (TimerManager)ic.lookup("weblogic.JobScheduler");
            System.out.println("jobScheduler reference " + jobScheduler);
            commonj.timers.TimerListener timerListener =
                new SystemOutTimerListener();
            System.out.println("timerListener reference " + timerListener);
            jobScheduler.schedule(timerListener, 0, 30 * 1000);
            //execute this job every 30 seconds
            System.out.println("service() started the timer");
            out.write("Started the timer - status:");
        } catch (Throwable t) {
            System.out.println("service() error initializing timer manager with JNDI name weblogic.JobScheduler " +                               t);
        }
        out.println("</body></html>");
        out.close();
    }
}

package jamesbayer.client;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import commonj.timers.Timer;
import commonj.timers.TimerListener;
public class SystemOutTimerListener implements Serializable, TimerListener 
{
	private static final long serialVersionUID = 8313912206357147939L;
	public void timerExpired(Timer timer) 
	{
		SimpleDateFormat sdf = new SimpleDateFormat();
		System.out.println( "timerExpired() called at " + sdf.format( new Date() ) );
	}
}

April 9, 2009

Using WLST with the WebLogic Server Job Scheduler

I recently wrote about a simple example using the WebLogic Server Job Scheduler.  This describes how to cancel the jobs and get visibility into job execution status.

jmx [2]

Cancelling a task

One of the things to note about the JobScheduler is that you cannot call certain CommonJ API calls, particularly around cancelling tasks.  The way to do that is via the JobSchedulerRuntimeMBean, exposed with console functionality or via JMX.  Obviously the console is great for on-demand access, but what if you want to script things to make automated decisions?

Here is some sample output from a WLST session that shows me browsing to the JobSchedulerRuntimeMBean, finding an active task and cancelling it.

wls:/offline> connect('weblogic','weblogic','t3://localhost:7011')
Connecting to t3://localhost:7011 with userid weblogic ...
Successfully connected to managed Server 'managedServer1' that belongs to domain 'wldf_domain'.
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.
wls:/wldf_domain/serverConfig> domainRuntime()
DomainRuntime MBeanServer is not enabled on a Managed Server.
wls:/wldf_domain/serverConfig> ls()
dr--   AdminConsole
dr--   AppDeployments
dr--   BridgeDestinations
dr--   Clusters
dr--   CustomResources
dr--   DeploymentConfiguration
dr--   Deployments
dr--   EmbeddedLDAP
dr--   ErrorHandlings
dr--   FileStores
dr--   InternalAppDeployments
dr--   InternalLibraries
dr--   JDBCDataSourceFactories
dr--   JDBCStores
dr--   JDBCSystemResources
dr--   JMSBridgeDestinations
dr--   JMSInteropModules
dr--   JMSServers
dr--   JMSSystemResources
dr--   JMX
dr--   JTA
dr--   JoltConnectionPools
dr--   Libraries
dr--   Log
dr--   LogFilters
dr--   Machines
dr--   MailSessions
dr--   MessagingBridges
dr--   MigratableTargets
dr--   RemoteSAFContexts
dr--   SAFAgents
dr--   SNMPAgent
dr--   SNMPAgentDeployments
dr--   Security
dr--   SecurityConfiguration
dr--   SelfTuning
dr--   Servers
dr--   ShutdownClasses
dr--   SingletonServices
dr--   StartupClasses
dr--   SystemResources
dr--   Targets
dr--   VirtualHosts
dr--   WLDFSystemResources
dr--   WLECConnectionPools
dr--   WSReliableDeliveryPolicies
dr--   WTCServers
dr--   WebAppContainer
dr--   WebserviceSecurities
dr--   XMLEntityCaches
dr--   XMLRegistries
-r--   AdminServerName                              AdminServer
-r--   AdministrationMBeanAuditingEnabled           false
-r--   AdministrationPort                           9002
-r--   AdministrationPortEnabled                    false
-r--   AdministrationProtocol                       t3s
-r--   ArchiveConfigurationCount                    0
-r--   ClusterConstraintsEnabled                    false
-r--   ConfigBackupEnabled                          false
-r--   ConfigurationAuditType                       none
-r--   ConfigurationVersion                         10.3.0.0
-r--   ConsoleContextPath                           console
-r--   ConsoleEnabled                               true
-r--   ConsoleExtensionDirectory                    console-ext
-r--   DomainVersion                                10.3.0.0
-r--   GuardianEnabled                              false
-r--   InternalAppsDeployOnDemandEnabled            true
-r--   LastModificationTime                         0
-r--   Name                                         wldf_domain
-r--   Notes                                        null
-r--   Parent                                       null
-r--   ProductionModeEnabled                        false
-r--   RootDirectory                                C:\Oracle\wls10gR3\user_projects\domains\wldf_domain
-r--   Type                                         Domain
-r-x   freezeCurrentValue                           Void : String(attributeName)
-r-x   isSet                                        Boolean : String(propertyName)
-r-x   unSet                                        Void : String(propertyName)
wls:/wldf_domain/serverConfig> serverRuntime()
wls:/wldf_domain/serverRuntime> ls()
dr--   ApplicationRuntimes
dr--   AsyncReplicationRuntime
dr--   ClusterRuntime
dr--   ConnectorServiceRuntime
dr--   DefaultExecuteQueueRuntime
dr--   EntityCacheCumulativeRuntime
dr--   EntityCacheCurrentStateRuntime
dr--   EntityCacheHistoricalRuntime
dr--   ExecuteQueueRuntimes
dr--   JDBCServiceRuntime
dr--   JMSRuntime
dr--   JTARuntime
dr--   JVMRuntime
dr--   JoltRuntime
dr--   LibraryRuntimes
dr--   LogBroadcasterRuntime
dr--   LogRuntime
dr--   MANAsyncReplicationRuntime
dr--   MANReplicationRuntime
dr--   MailSessionRuntimes
dr--   MaxThreadsConstraintRuntimes
dr--   MinThreadsConstraintRuntimes
dr--   PathServiceRuntime
dr--   PersistentStoreRuntimes
dr--   RequestClassRuntimes
dr--   SAFRuntime
dr--   SNMPAgentRuntime
dr--   ServerChannelRuntimes
dr--   ServerSecurityRuntime
dr--   ServerServices
dr--   SingleSignOnServicesRuntime
dr--   ThreadPoolRuntime
dr--   TimerRuntime
dr--   WANReplicationRuntime
dr--   WLDFRuntime
dr--   WTCRuntime
dr--   WebServerRuntimes
dr--   WorkManagerRuntimes
-r--   ActivationTime                               1237559025844
-r--   AdminServer                                  false
-r--   AdminServerHost                              192.168.2.1
-r--   AdminServerListenPort                        7001
-r--   AdminServerListenPortSecure                  false
-r--   AdministrationPort                           9002
-r--   AdministrationPortEnabled                    false
-r--   AdministrationURL                            t3://192.168.2.1:7011
-r--   CurrentDirectory                             C:\Oracle\wls10gR3\user_projects\domains\wldf_domain\.
-r--   CurrentMachine
-r--   DefaultExecuteQueueRuntime                   null
-r--   DefaultURL                                   t3://192.168.2.1:7011
-r--   EntityCacheCumulativeRuntime                 null
-r--   EntityCacheCurrentStateRuntime               null
-r--   EntityCacheHistoricalRuntime                 null
-r--   HealthState                                  Component:ServerRuntime,State:HEALTH_OK,MBean:managedServer1,ReasonCode:[]
-r--   JoltRuntime                                  null
-r--   ListenAddress                                JBAYER-LAP/192.168.2.1
-r--   ListenPort                                   7011
-r--   ListenPortEnabled                            true
-r--   MANAsyncReplicationRuntime                   null
-r--   MANReplicationRuntime                        null
-r--   Name                                         managedServer1
-r--   OpenSocketsCurrentCount                      3
-r--   Parent                                       null
-r--   PathServiceRuntime                           null
-r--   RestartRequired                              false
-r--   RestartsTotalCount                           0
-r--   SSLListenAddress                             null
-r--   SSLListenPort                                7002
-r--   SSLListenPortEnabled                         false
-r--   ServerClasspath                              C:\Oracle\wls10gR3\JROCKI~1\jre\bin\jrockit\jrockit1.6.0.jar;C:\Oracle\wls10gR3\JROCKI~1\jre\bin\jrockit\jmapi.jar;C:\Oracle\wls10gR3\JROCKI~1\
3\JROCKI~1\jre\bin\jrockit\rmp.jar;C:\Oracle\wls10gR3\JROCKI~1\jre\bin\jrockit\latency.jar;C:\Oracle\wls10gR3\JROCKI~1\jre\lib\resources.jar;C:\Oracle\wls10gR3\JROCKI~1\jre\lib\rt.jar;C:\Oracle\w
acle\wls10gR3\JROCKI~1\jre\lib\jsse.jar;C:\Oracle\wls10gR3\JROCKI~1\jre\lib\jce.jar;C:\Oracle\wls10gR3\JROCKI~1\jre\lib\charsets.jar;C:\Oracle\wls10gR3\JROCKI~1\jre\classes;C:\JDeveloper\mywork\J
ener.jar;C:\Oracle\wls10gR3\patch_wlw1030\profiles\default\sys_manifest_classpath\weblogic_patch.jar;C:\Oracle\wls10gR3\patch_wls1030\profiles\default\sys_manifest_classpath\weblogic_patch.jar;C:
ult\sys_manifest_classpath\weblogic_patch.jar;C:\Oracle\wls10gR3\patch_cie670\profiles\default\sys_manifest_classpath\weblogic_patch.jar;C:\Oracle\wls10gR3\patch_cie660\profiles\default\sys_manif
s10gR3\patch_alsb1030\profiles\default\sys_manifest_classpath\weblogic_patch.jar;C:\Oracle\wls10gR3\JROCKI~1\lib\tools.jar;C:\Oracle\wls10gR3\WLSERV~1.3\server\lib\weblogic_sp.jar;C:\Oracle\wls10
cle\wls10gR3\modules\features\weblogic.server.modules_10.3.0.0.jar;C:\Oracle\wls10gR3\WLSERV~1.3\server\lib\webservices.jar;C:\Oracle\wls10gR3\modules\ORGAPA~1.5/lib/ant-all.jar;C:\Oracle\wls10gR
\Oracle\wls10gR3\jdeveloper\modules\features\adf.share_11.1.1.jar;;C:\Oracle\wls10gR3\WLSERV~1.3\common\eval\pointbase\lib\pbclient57.jar;C:\Oracle\wls10gR3\WLSERV~1.3\server\lib\xqrl.jar;;;C:\Or
sysext_manifest_classpath\weblogic_ext_patch.jar
-r--   SocketsOpenedTotalCount                      3
-r--   State                                        RUNNING
-r--   StateVal                                     2
-r--   Type                                         ServerRuntime
-r--   WANReplicationRuntime                        null
-r--   WLECConnectionServiceRuntime                 null
-r--   WeblogicVersion                              WebLogic Server Temporary Patch for CR380042 Thu Sep 11 13:33:40 PDT 2008
WebLogic Server Temporary Patch for 7372756 Fri Sep 12 17:05:44 EDT 2008
WebLogic Server Temporary Patch for CR380913 Wed Oct 15 13:24:22 PDT 2008
WebLogic Server Temporary Patch for CR381739 Tue Oct 21 14:06:14 IST 2008
WebLogic Server Temporary Patch for CR381056 Mon Oct 06 10:48:50 EDT 2008
WebLogic Server Temporary Patch for CR374413, CR378680 Tue Sep 02 09:55:36 PDT 2008
WebLogic Server Temporary Patch for CR378102 Wed Sep 10 23:28:48 PDT 2008
WebLogic Server Temporary Patch for CR378741 Tue Sep 09 13:08:51 PDT 2008
WebLogic Server Temporary Patch for CR378781, CR380313 Fri Sep 19 13:34:16 PDT 2008
WebLogic Server 10.3  Fri Jul 25 16:30:05 EDT 2008 1137967
-r-x   addRequestClassRuntime                       Boolean : WebLogicMBean(weblogic.management.runtime.RequestClassRuntimeMBean)
-r-x   forceShutdown                                Void :
-r-x   forceSuspend                                 Void :
-r-x   getServerChannel                             java.net.InetSocketAddress : String(protocol)
-r-x   getURL                                       String : String(protocol)
-r-x   preDeregister                                Void :
-r-x   restartSSLChannels                           Void :
-r-x   resume                                       Void :
-r-x   shutdown                                     Void :
-r-x   shutdown                                     Void : Integer(timeout),Boolean(ignoreSessions)
-r-x   start                                        Void :
-r-x   suspend                                      Void :
-r-x   suspend                                      Void : Integer(timeout),Boolean(ignoreSessions)
wls:/wldf_domain/serverRuntime> cd('ClusterRuntime')
wls:/wldf_domain/serverRuntime/ClusterRuntime> ls()
dr--   myCluster
wls:/wldf_domain/serverRuntime/ClusterRuntime> cd('myCluster')
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster> ls()
dr--   JobSchedulerRuntime
dr--   ServerMigrationRuntime
dr--   UnicastMessaging
-r--   ActiveSingletonServices                      java.lang.String[TimerMaster]
-r--   AliveServerCount                             1
-r--   CurrentMachine                               null
-r--   CurrentSecondaryServer
-r--   DetailedSecondariesDistribution              null
-r--   ForeignFragmentsDroppedCount                 0
-r--   FragmentsReceivedCount                       581
-r--   FragmentsSentCount                           581
-r--   HealthState                                  Component:null,State:HEALTH_OK,MBean:null,ReasonCode:[]
-r--   MulticastMessagesLostCount                   0
-r--   Name                                         myCluster
-r--   PrimaryCount                                 0
-r--   ResendRequestsCount                          0
-r--   SecondaryCount                               0
-r--   SecondaryDistributionNames                   null
-r--   SecondaryServerDetails
-r--   ServerNames                                  java.lang.String[managedServer1]
-r--   Type                                         ClusterRuntime
-r--   UnicastMessaging                             null
-r-x   preDeregister                                Void :
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster> cd('JobSchedulerRuntime')
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster/JobSchedulerRuntime> ls()
dr--   JobSchedulerRuntime
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster/JobSchedulerRuntime> cd('JobSchedulerRuntime')
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster/JobSchedulerRuntime/JobSchedulerRuntime> ls()
dr--   ExecutedJobs
-r--   Name                                         JobSchedulerRuntime
-r--   Type                                         JobSchedulerRuntime
-r-x   getJob                                       WebLogicMBean : String(id)
-r-x   preDeregister                                Void :
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster/JobSchedulerRuntime/JobSchedulerRuntime> cd('ExecutedJobs')
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster/JobSchedulerRuntime/JobSchedulerRuntime/ExecutedJobs> ls()
dr--   JobRuntime-managedServer1_1237564053328
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster/JobSchedulerRuntime/JobSchedulerRuntime/ExecutedJobs> cd('JobRuntime-managedServer1_1237564053328')
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster/JobSchedulerRuntime/JobSchedulerRuntime/ExecutedJobs/JobRuntime-managedServer1_1237564053328> ls()
-r--   Description                                  jamesbayer.client.SystemOutTimerListener@2ed941
-r--   ID                                           managedServer1_1237564053328
-r--   LastLocalExecutionTime                       1237564580328
-r--   LocalExecutionCount                          18
-r--   Name                                         JobRuntime-managedServer1_1237564053328
-r--   Period                                       30000
-r--   State                                        Running
-r--   Timeout                                      6719
-r--   TimerListener                                jamesbayer.client.SystemOutTimerListener@333c5d
-r--   Type                                         JobRuntime
-r-x   cancel                                       Void :
-r-x   preDeregister                                Void :
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster/JobSchedulerRuntime/JobSchedulerRuntime/ExecutedJobs/JobRuntime-managedServer1_1237564053328> ls()
-r--   Description                                  jamesbayer.client.SystemOutTimerListener@2ed941
-r--   ID                                           managedServer1_1237564053328
-r--   LastLocalExecutionTime                       1237564850547
-r--   LocalExecutionCount                          27
-r--   Name                                         JobRuntime-managedServer1_1237564053328
-r--   Period                                       30000
-r--   State                                        Running
-r--   Timeout                                      18812
-r--   TimerListener                                jamesbayer.client.SystemOutTimerListener@349b7f
-r--   Type                                         JobRuntime
-r-x   cancel                                       Void :
-r-x   preDeregister                                Void :
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster/JobSchedulerRuntime/JobSchedulerRuntime/ExecutedJobs/JobRuntime-managedServer1_1237564053328> cmo.cancel()
wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster/JobSchedulerRuntime/JobSchedulerRuntime/ExecutedJobs/JobRuntime-managedServer1_1237564053328> ls()
-r--   Description                                  jamesbayer.client.SystemOutTimerListener@2ed941
-r--   ID                                           managedServer1_1237564053328
-r--   LastLocalExecutionTime                       1237564850547
-r--   LocalExecutionCount                          27
-r--   Name                                         JobRuntime-managedServer1_1237564053328
-r--   Period                                       30000
-r--   State                                        Cancelled
-r--   Timeout                                      -1
-r--   TimerListener                                null
-r--   Type                                         JobRuntime
-r-x   cancel                                       Void :
-r-x   preDeregister                                Void :

Automating JobScheduler status checking

One of my customers asked me about how they could periodically check if a task was running in the cluster, and if it is not then send someone an email, etc.  Basically, the sky is the limit with scripting.  A more advanced use of this would be to connect this to alerts in WebLogic Diagnsotic Framework or SNMP traps in Oracle Enterprise Manager, but this is a start.  Here is a python script that you can invoke with WLST that will do several things:

  • Connect to the Admin Server
  • Get a list of all managed servers in the cluster
  • Check each managed server for a particular running timer task
  • If no running tasks are found exit with a non-zero exit code, otherwise exit a zero exit code

isJobRunning.py

user='weblogic'
pw='weblogic'
adminServer='localhost'
adminPort='7001'
clusterName='myCluster'
timerRunning=false
timerClass='jamesbayer.client.SystemOutTimerListener'
## Standard Connection
try:
  connect(user,pw,'t3://'+adminServer+':'+adminPort)
except:
  print 'Error connecting to Admin Server'
## Get the list of managed servers in the cluster
try:
  domainConfig()
  cd('Clusters/'+clusterName)
  managedServers=cmo.getServers()
  print 'Found ' + `len(managedServers)` + ' managed servers'
except:
  print 'Error navigating DomainConfig MBean tree for the list of managed servers'
## Loop through managed servers and look for the job
domainRuntime()
for managedServer in managedServers:
  try:
    managedServerName=managedServer.getName()
    print 'Trying ' + managedServerName
    cd('/ServerRuntimes/'+managedServerName)
    if cmo.getState() == 'RUNNING':
      cd( '/ServerRuntimes/'+managedServerName+'/ClusterRuntime/'+clusterName+'/JobSchedulerRuntime/JobSchedulerRuntime')
      try:
        jobs=cmo.getExecutedJobs()
        for job in jobs:
          if job.getDescription().find(timerClass) > -1 and job.getState() == 'Running':
            timerRunning=true
            print timerClass + ' is running on ' +  managedServerName
      except:
        print 'Error checking ' + managedServerName + ' ExecutedJobs'
    else:
      print managedServerName + ' is not RUNNING'
  except:
    print 'Error checking JobScheduler on ' + managedServerName
  if timerRunning:
    break
disconnect()
if timerRunning:
  print 'The Job is Running'
  exit(exitcode=0)
else:
  print 'The Job is NOT Running'
  exit(exitcode=1)

Script output

C:\Oracle\wls10gR3\user_projects\domains\wldf_domain>bin\setDomainEnv.cmd
C:\Oracle\wls10gR3\user_projects\domains\wldf_domain>java weblogic.WLST C:\MyData\Accounts\PepsiAmericas\JobScheduler\isJobRunning.py
Initializing WebLogic Scripting Tool (WLST) ...
Welcome to WebLogic Server Administration Scripting Shell
Type help() for help on available commands
Connecting to t3://localhost:7001 with userid weblogic ...
Successfully connected to Admin Server 'AdminServer' that belongs to domain 'wldf_domain'.
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 serverRuntime tree. This is a read-only tree with DomainMBean as the root.
For more help, use help(domainConfig)
Found 1 managed servers
Location changed to domainRuntime tree. This is a read-only tree with DomainMBean as the root.
For more help, use help(domainRuntime)
Trying managedServer1
Disconnected from weblogic server: AdminServer
The Job is Running
Exiting WebLogic Scripting Tool.
C:\Oracle\wls10gR3\user_projects\domains\wldf_domain>

About April 2009

This page contains all entries posted to James Bayer's Blog in April 2009. They are listed from oldest to newest.

March 2009 is the previous archive.

July 2009 is the next archive.

Many more can be found on the main index page or by looking through the archives.

Powered by
Movable Type and Oracle