X

Recent Posts

Coherence

Coherence*Web with WebLogic Server Simple Example and Troubleshooting Overview

This quick troubleshooting guide covers a basicsetup of a simple sample application using Coherence*Web instead of traditional WebLogic Server session replication. I used Coherence 3.6.1.x and WebLogic Server 10.3.4 for when I originally created this example, but the steps should be similar for any Coherence 3.5+ and WebLogic Server release capable of using the Coherence*Web SPI, which include some older releases of WLS, but consider 10.3.1+ as the most well-worn-path.  I apologize for the formatting, which is a bit sloppy compared to my normal blog posts.  This has been in a word doc on my desktop for a long time waiting for when I had time to post it properly.  Given two requests for this in the last week I figured a sloppy blog post was better than not sharing it broadly. For simplicity, we are assuming 2 WebLogicServer managed server instances in a WLS Cluster are running Coherence*Web asstorage disabled nodes. The WebLogicServers will have a simple test web application located here deployed that stores session data on aCoherence cluster with 2 storage enabled cache servers. There are a sequence of steps that helpvalidate that session failover is working properly. Some of these steps are from productdocumentation, and I've supplemented with my own comments in red. Notethat this example will not use Active Cache, which is a way to manage Coherenceconfiguration and Cache Server lifecycle from WebLogic Server. I recommend users understand this examplefirst before adding on Active Cache. More detail on Active Cache including a video is covered in this blogentry http://blogs.oracle.com/jamesbayer/entry/weblogic_server_1034_screencas 2.2.6.2 Configuring EAR-Scoped Cluster Nodes To use Coherence*Web forsession management in EAR-scoped cluster nodes, follow these steps: Use the WebLogic Server Administration Console to deploy the coherence.jar and coherence-web-spi.war files as shared libraries to all of the target servers where the application will be deployed. See "Install a Java EE Library" in Oracle Fusion Middleware Oracle WebLogic Server Administration Console Help for more information. I always recommend using ashared library to include the coherence.jar on the classpath of yourapplication instead of the approach where it is embedded directly inside yourapplication (say in APP-INF/lib or WEB-INF/lib). This way if you patch or upgrade Coherence, themost you need to do is redeploy the coherence.jar shared library and yourapplication. If you use the approachwhere your application directly embeds coherence.jar inside of it, then youneed a new build of your application which updates the embedded coherence.jar, which is typically an undesirable process. Note: The WLS 10.3.1 AdministrativeConsole will not let you deploy coherence.jar without an error, but you can usethe WLST command like: deploy('coherence','/scratch/jbayer/coherence/lib/coherence.jar',libraryModule='true') This consoledeployment issue does not affect WLS10.3.2+. However, you may note whatappears to be an error when deploying coherence.jar, but if you read it closely "Assuming this is a library deployment." you will see that it isnot an error, it is a warning and you can proceed with the deployment.. Assumingyou are using an EAR, create a library reference to coherence in your sampleapplication. Assuming you have an EARfile with a WAR module inside, then weblogic-application.xml looks like this: <weblogic-application ...> ... <library-ref> <library-name>coherence</library-name> </library-ref> ... </weblogic-application> Theabove library-ref element will merge the coherence.jar into the APP-INF/lib ofthe App during the deployment process, which will make Coherence classes EARscoped. Quickaside, If you are using a stand-alone WAR file that is not encapsulated insideof an EAR, then instead of using a library reference, you can use an OptionalPackage approach to refer to the library, which involves creating an entry inthe META-INF/manifest.mf of the WAR file like this: Manifest-Version: 1.0 Class-Path: Extension-List: coherencejar coherencejar-Extension-Name: coherence Notethat there must be a newline at the end of the last line with text otherwise itwill not work correctly. Unlike thelibrary reference mechanism, the library is not merged into an archive on diskat deployment time, rather it utilizes a Java Optional Package approach to putthe coherence.jar on the classpath. Forthe WAR modules, have the weblogic.xml use a library reference for thecoherence-web-spi.war like this: <wls:weblogic-web-app ... <wls:library-ref> <wls:library-name>coherence-web-spi</wls:library-name> </wls:library-ref> </wls:weblogic-web-app> Thiswill merge the contents of the coherence-web-spi.war with the application's webmodule. Nowwe also have to configure the tangosol-coherence-override.xml file if you wantto override default configuration settings. One such setting I like to override is to use Well-Known-Addresses(WKA), which is a unicast approach instead of the default multicast networkingthat many Network Administrators do not permit. The tangosol-coherence-override.xml file approach will be easier than using-D options on the command line because in WLS there may be multiple web applicationsusing different Coherence configurations, and if you use -D options on the Javacommand line, then it is the same configuration for all Coherence instances inthat JVM without some other tedious intervention. I used the latest release of OracleEnterprise Pack for Eclipse (OEPE) to createthe below configuration file with the Coherence tooling, which will use thesetwo WKA addresses and auto-increment the port the more servers you start(default). I put one copy in the EARfiles APP-INF/classes directory and one in $COHERENCE_HOME. You can replace the hostname of adc2101131.us.oracle.com with appropriate hostnames for your systems. Note that the newer versions of Coherence useXSD instead of DTD. <?xml version="1.0"?> <!DOCTYPE coherence SYSTEM "coherence-override.dtd"> <coherence> <cluster-config> <unicast-listener> <well-known-addresses> <socket-address id="2"> <address>adc2101131.us.oracle.com</address> <port>8090</port> </socket-address> <socket-address id="1"> <address>adc2101131.us.oracle.com</address> <port>8088</port> </socket-address> </well-known-addresses> <address system-property="tangosol.coherence.localhost">adc2101131.us.oracle.com</address> <port system-property="tangosol.coherence.localport">8088</port> <port-auto-adjust system-property="tangosol.coherence.localport.adjust">true</port-auto-adjust> </unicast-listener> </cluster-config> </coherence> Then beforeyou deploy the application to Weblogic Server, you need to setup and start thecache servers. I simply clone$COHERENCE_HOME/bin/cache-server.sh to$COHERENCE_HOME/bin/sessions-cache-server.sh I'll have bolded and highlighted the edits I made.... #!/bin/sh # This will start acache server # specify theCoherence installation directory COHERENCE_HOME=. # specify the JVMheap size MEMORY=512m if [ ! -f${COHERENCE_HOME}/bin/session-cache-server.sh ]; then echo "session-cache-server.sh: must be runfrom the Coherence installation directory." exit fi if [ -f$JAVA_HOME/bin/java ]; then JAVAEXEC=$JAVA_HOME/bin/java else JAVAEXEC=java fi JAVA_OPTS="-Xms$MEMORY-Xmx$MEMORY -Dtangosol.coherence.session.localstorage=true-Dtangosol.coherence.cacheconfig=WEB-INF/classes/session-cache-config.xml-Dtangosol.coherence.override=/scratch/jbayer/coherence/tangosol-coherence-override.xml" $JAVAEXEC -server-showversion $JAVA_OPTS -cp "$COHERENCE_HOME/lib/coherence.jar:$COHERENCE_HOME/lib/coherence-web-spi.war"com.tangosol.net.DefaultCacheServer $1 Then starttwo instances of the session-cache-server.sh from the $COHERENCE_HOME directorylike this: bash-3.2$bin/session-cache-server.sh Make sure they join the cluster together andsee each other by viewing the member list in the output. Here is the output from the firstserver. Note the highlighted areas inred which show that: · the override file we intend isbeing used · the session-cache-config.xml fromthe coherence-web-spi.war is being used · that the protocol specified in theoverride is being used, in this case WKA mans unicast instead of multicast · the distributed sessions service isstorage enabled bash-3.2$ bin/session-cache-server.sh java version "1.6.0_21" Java(TM) SE Runtime Environment (build 1.6.0_21-b51) Java HotSpot(TM) Server VM (build 17.0-b17, mixed mode) 2011-02-15 23:26:56.374/0.580 Oracle Coherence 3.6.1.0<Info> (thread=main, member=n/a): Loaded operational configuration from"jar:file:/scratch/jbayer/coherence/lib/coherence.jar!/tangosol-coherence.xml" 2011-02-15 23:26:56.379/0.585 Oracle Coherence 3.6.1.0<Info> (thread=main, member=n/a): Loaded operational overrides from"file:/scratch/jbayer/coherence/tangosol-coherence-override.xml" 2011-02-15 23:26:56.386/0.592 Oracle Coherence 3.6.1.0<D5> (thread=main, member=n/a): Optional configuration override"/custom-mbeans.xml" is not specified Oracle Coherence Version 3.6.1.0 Build 19636 Grid Edition: Developmentmode Copyright (c) 2000, 2010, Oracle and/or its affiliates. Allrights reserved. 2011-02-15 23:26:56.760/0.966 Oracle Coherence GE 3.6.1.0<Info> (thread=main, member=n/a): Loaded cache configuration from"jar:file:/scratch/jbayer/coherence/lib/coherence-web-spi.war!/WEB-INF/classes/session-cache-config.xml" 2011-02-15 23:26:57.257/1.463 Oracle Coherence GE 3.6.1.0<D4> (thread=main, member=n/a): TCMP bound to /10.229.188.238:8088 usingSystemSocketProvider 2011-02-15 23:27:27.613/31.819 Oracle Coherence GE 3.6.1.0<Info> (thread=Cluster, member=n/a): Created a new cluster withMember(Id=1, Timestamp=2011-02-15 23:26:57.261, Address=10.229.188.238:8088,MachineId=21486, Location=machine:jbayer-vm,process:30802,Role=CoherenceServer, Edition=Grid Edition, Mode=Development, CpuCount=2,SocketCount=2) UID=0x0AE5BCEE0000012E2D5D5EED53EE1F98 2011-02-15 23:27:27.616/31.822 Oracle Coherence GE 3.6.1.0<Info> (thread=main, member=n/a): Started cluster Name=n/a WellKnownAddressList(Size=2, WKA{Address=10.229.188.238, Port=8090} WKA{Address=10.229.188.238, Port=8088} ) MasterMemberSet ( ThisMember=Member(Id=1,Timestamp=2011-02-15 23:26:57.261, Address=10.229.188.238:8088,MachineId=21486, Location=machine:jbayer-vm,process:30802,Role=CoherenceServer) OldestMember=Member(Id=1,Timestamp=2011-02-15 23:26:57.261, Address=10.229.188.238:8088,MachineId=21486, Location=machine:jbayer-vm,process:30802,Role=CoherenceServer) ActualMemberSet=MemberSet(Size=1, BitSetCount=2 Member(Id=1,Timestamp=2011-02-15 23:26:57.261, Address=10.229.188.238:8088,MachineId=21486, Location=machine:jbayer-vm,process:30802,Role=CoherenceServer) ) RecycleMillis=1200000 RecycleSet=MemberSet(Size=0, BitSetCount=0 ) ) TcpRing{Connections=[]} IpMonitor{AddressListSize=0} 2011-02-15 23:27:27.665/31.871 Oracle Coherence GE 3.6.1.0<D5> (thread=Invocation:Management, member=1): Service Management joinedthe cluster with senior service member 1 2011-02-15 23:27:27.828/32.034 Oracle Coherence GE 3.6.1.0<D5> (thread=ReplicatedCache:ReplicatedSessionsMisc, member=1): ServiceReplicatedSessionsMisc joined the cluster with senior service member 1 2011-02-15 23:27:28.074/32.280 Oracle Coherence GE 3.6.1.0<D5> (thread=DistributedCache:DistributedSessions, member=1): ServiceDistributedSessions joined the cluster with senior service member 1 2011-02-15 23:27:28.105/32.311 Oracle Coherence GE 3.6.1.0<Info> (thread=main, member=1): Services ( ClusterService{Name=Cluster, State=(SERVICE_STARTED, STATE_JOINED),Id=0, Version=3.6, OldestMemberId=1} InvocationService{Name=Management, State=(SERVICE_STARTED), Id=1,Version=3.1, OldestMemberId=1} ReplicatedCache{Name=ReplicatedSessionsMisc, State=(SERVICE_STARTED),Id=2, Version=3.0, OldestMemberId=1} PartitionedCache{Name=DistributedSessions, State=(SERVICE_STARTED), LocalStorage=enabled, PartitionCount=257,BackupCount=1, AssignedPartitions=257, BackupPartitions=0} ) Started DefaultCacheServer... Here is the output from the second cache server. Note that it shows both servers being partof the cluster now. I'll highlight a fewthings to look for. Notably, the sameconfiguration values are used as the previous cluster and that this time themember id is 2 and at the end this node asks the member 1 for some partitions. bash-3.2$ bin/session-cache-server.sh java version "1.6.0_21" Java(TM) SE Runtime Environment (build 1.6.0_21-b51) Java HotSpot(TM) Server VM (build 17.0-b17, mixed mode) 2011-02-15 23:34:51.856/0.251 Oracle Coherence 3.6.1.0<Info> (thread=main, member=n/a): Loaded operational configuration from"jar:file:/scratch/jbayer/coherence/lib/coherence.jar!/tangosol-coherence.xml" 2011-02-15 23:34:51.861/0.256 Oracle Coherence 3.6.1.0<Info> (thread=main, member=n/a): Loaded operational overrides from"file:/scratch/jbayer/coherence/tangosol-coherence-override.xml" 2011-02-15 23:34:51.866/0.261 Oracle Coherence 3.6.1.0<D5> (thread=main, member=n/a): Optional configuration override"/custom-mbeans.xml" is not specified Oracle Coherence Version 3.6.1.0 Build 19636 Grid Edition: Developmentmode Copyright (c) 2000, 2010, Oracle and/or its affiliates. Allrights reserved. 2011-02-15 23:34:52.147/0.542 Oracle Coherence GE 3.6.1.0<Info> (thread=main, member=n/a): Loaded cache configuration from"jar:file:/scratch/jbayer/coherence/lib/coherence-web-spi.war!/WEB-INF/classes/session-cache-config.xml" 2011-02-15 23:34:52.500/0.895 Oracle Coherence GE 3.6.1.0<D4> (thread=main, member=n/a): TCMP bound to /10.229.188.238:8090using SystemSocketProvider 2011-02-15 23:35:16.251/24.646 Oracle Coherence GE 3.6.1.0<Info> (thread=Cluster, member=n/a): ThisMember(Id=2, Timestamp=2011-02-15 23:35:16.04,Address=10.229.188.238:8090, MachineId=21486,Location=machine:jbayer-vm,process:31080, Role=CoherenceServer, Edition=GridEdition, Mode=Development, CpuCount=2, SocketCount=2) joined cluster withsenior Member(Id=1, Timestamp=2011-02-15 23:34:45.487,Address=10.229.188.238:8088, MachineId=21486,Location=machine:jbayer-vm,process:31060, Role=CoherenceServer, Edition=GridEdition, Mode=Development, CpuCount=2, SocketCount=2) 2011-02-15 23:35:16.270/24.665 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 1 joined Service Cluster withsenior member 1 2011-02-15 23:35:16.270/24.665 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 1 joined Service Managementwith senior member 1 2011-02-15 23:35:16.270/24.665 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 1 joined ServiceReplicatedSessionsMisc with senior member 1 2011-02-15 23:35:16.270/24.665 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 1 joined ServiceDistributedSessions with senior member 1 2011-02-15 23:35:16.273/24.668 Oracle Coherence GE 3.6.1.0<Info> (thread=main, member=n/a): Started cluster Name=n/a WellKnownAddressList(Size=2, WKA{Address=10.229.188.238, Port=8088} WKA{Address=10.229.188.238, Port=8090} ) MasterMemberSet ( ThisMember=Member(Id=2,Timestamp=2011-02-15 23:35:16.04, Address=10.229.188.238:8090, MachineId=21486,Location=machine:jbayer-vm,process:31080, Role=CoherenceServer) OldestMember=Member(Id=1, Timestamp=2011-02-15 23:34:45.487,Address=10.229.188.238:8088, MachineId=21486,Location=machine:jbayer-vm,process:31060, Role=CoherenceServer) ActualMemberSet=MemberSet(Size=2,BitSetCount=2 Member(Id=1,Timestamp=2011-02-15 23:34:45.487, Address=10.229.188.238:8088,MachineId=21486, Location=machine:jbayer-vm,process:31060,Role=CoherenceServer) Member(Id=2,Timestamp=2011-02-15 23:35:16.04, Address=10.229.188.238:8090, MachineId=21486,Location=machine:jbayer-vm,process:31080, Role=CoherenceServer) ) RecycleMillis=1200000 RecycleSet=MemberSet(Size=0, BitSetCount=0 ) ) TcpRing{Connections=[1]} IpMonitor{AddressListSize=0} 2011-02-15 23:35:16.321/24.716 Oracle Coherence GE 3.6.1.0<D5> (thread=Invocation:Management, member=2): Service Management joinedthe cluster with senior service member 1 2011-02-15 23:35:16.429/24.825 Oracle Coherence GE 3.6.1.0<D5> (thread=ReplicatedCache:ReplicatedSessionsMisc, member=2): ServiceReplicatedSessionsMisc joined the cluster with senior service member 1 2011-02-15 23:35:16.618/25.013 Oracle Coherence GE 3.6.1.0<D5> (thread=DistributedCache:DistributedSessions, member=2): ServiceDistributedSessions joined the cluster with senior service member 1 2011-02-15 23:35:16.648/25.043 Oracle Coherence GE 3.6.1.0<Info> (thread=main, member=2): Services ( ClusterService{Name=Cluster, State=(SERVICE_STARTED, STATE_JOINED),Id=0, Version=3.6, OldestMemberId=1} InvocationService{Name=Management, State=(SERVICE_STARTED), Id=1,Version=3.1, OldestMemberId=1} ReplicatedCache{Name=ReplicatedSessionsMisc, State=(SERVICE_STARTED),Id=2, Version=3.0, OldestMemberId=1} PartitionedCache{Name=DistributedSessions, State=(SERVICE_STARTED), LocalStorage=enabled, PartitionCount=257,BackupCount=1, AssignedPartitions=0, BackupPartitions=0} ) Started DefaultCacheServer... 2011-02-15 23:35:16.657/25.052 Oracle Coherence GE 3.6.1.0<D4> (thread=DistributedCache:DistributedSessions, member=2): Asking member 1 for 128 primary partitions If the cluster has formed well, then we areready to deploy the application to WebLogic Server. Deploy CWebTestApp.ear (assuming you have thecorrect values for APP-INF/classes/tangosol-coherence-override.xml inside of itand see if it activates and joins the cluster. Here is output from one of the two managed servers in the WLS cluster. Your output may vary to a degree. <Feb 16, 2011 12:12:02 AM PST> <Notice><WebLogicServer> <BEA-000360> <Server started in RUNNINGmode> <Feb 16, 2011 12:13:09 AM PST> <Warning><Munger> <BEA-2156203> <A version attribute was not found inelement application in the deployment descriptor in/scratch/jbayer/wls1034/user_projects/domains/base_domain/servers/ManagedServer_2/stage/CWebTestApp/CWebTestApp.ear/META-INF/application.xml.A version attribute is required, but this version of the Weblogic Server willassume that the JEE5 is used. Future versions of the Weblogic Server willreject descriptors that do not specify the JEE version.> <Feb 16, 2011 12:13:09 AM PST> <Warning><Munger> <BEA-2156203> <A version attribute was not found inelement application in the deployment descriptor in/scratch/jbayer/wls1034/user_projects/domains/base_domain/servers/ManagedServer_2/tmp/_WL_user/CWebTestApp/sapbbg/META-INF/application.xml.A version attribute is required, but this version of the Weblogic Server willassume that the JEE5 is used. Future versions of the Weblogic Server willreject descriptors that do not specify the JEE version.> 2011-02-16 00:13:10.175/115.554 Oracle Coherence 3.6.1.0<Info> (thread=[STANDBY] ExecuteThread: '5' for queue:'weblogic.kernel.Default (self-tuning)', member=n/a): Loaded operationalconfiguration from "zip:/scratch/jbayer/wls1034/user_projects/domains/base_domain/servers/ManagedServer_2/stage/coherence/3.6.1.0@3.6.1.0/coherence.jar!/tangosol-coherence.xml" 2011-02-16 00:13:10.190/115.568 Oracle Coherence 3.6.1.0<Info> (thread=[STANDBY] ExecuteThread: '5' for queue:'weblogic.kernel.Default (self-tuning)', member=n/a): Loaded operationaloverrides from"zip:/scratch/jbayer/wls1034/user_projects/domains/base_domain/servers/ManagedServer_2/stage/coherence/3.6.1.0@3.6.1.0/coherence.jar!/tangosol-coherence-override-dev.xml" 2011-02-16 00:13:10.191/115.569 Oracle Coherence 3.6.1.0<Info> (thread=[STANDBY] ExecuteThread: '5' for queue:'weblogic.kernel.Default (self-tuning)', member=n/a): Loaded operationaloverrides from"file:/scratch/jbayer/wls1034/user_projects/domains/base_domain/servers/ManagedServer_2/tmp/_WL_user/CWebTestApp/sapbbg/APP-INF/classes/tangosol-coherence-override.xml" 2011-02-16 00:13:10.197/115.575 Oracle Coherence 3.6.1.0<D5> (thread=[STANDBY] ExecuteThread: '5' for queue:'weblogic.kernel.Default (self-tuning)', member=n/a): Optional configurationoverride "/custom-mbeans.xml" is not specified Oracle Coherence Version 3.6.1.0 Build 19636 Grid Edition: Developmentmode Copyright (c) 2000, 2010, Oracle and/or its affiliates. Allrights reserved. 2011-02-16 00:13:10.391/115.769 Oracle Coherence GE 3.6.1.0<Info> (thread=[STANDBY] ExecuteThread: '5' for queue:'weblogic.kernel.Default (self-tuning)', member=n/a): Loaded cacheconfiguration from"file:/scratch/jbayer/wls1034/user_projects/domains/base_domain/servers/ManagedServer_2/tmp/_WL_user/coherence-web-spi/4yxuqd/WEB-INF/classes/session-cache-config.xml" <Feb 16, 2011 12:13:10 AM PST> <Warning><WorkManager> <BEA-002919> <Unable to find a WorkManager withname wm/CoherenceWorkManager. Dispatch policy wm/CoherenceWorkManager will mapto the default WorkManager for the application CWebTestApp> 2011-02-16 00:13:10.681/116.059 Oracle Coherence GE 3.6.1.0<D5> (thread=[ACTIVE] ExecuteThread: '0' for queue:'weblogic.kernel.Default (self-tuning)', member=n/a): Clustered Session CacheName=session-storage Local Session CacheName=local-session-storage Local Session AttributeCache Name=local-attribute-storage Death Certificate CacheName=session-death-certificates SessionDistributionController Class Name= AttributeScopeControllerClassName=com.tangosol.coherence.servlet.AbstractHttpSessionCollection$ApplicationScopeController Maximum Session InactiveSeconds=3600 Session ID CharacterLength=52 Session LockingEnforced=false Member Session LockingEnforced=false Application SessionLocking Enforced=false Thread Session LockingEnforced=false Session Get LockTimeout=300 Suspect AttributeDetection=false Strict "ServletSpecification" Exception Handling=true Sticky SessionOwnership=false Sticky Session OwnershipService Name=SessionOwnership Assume Session Localityfor Reaping=false Parallel SessionReaping=true Allow LocalAttributes=false Use Default Session IDDecoding=true Use Default Session IDEncoding=false Session Expiry FilterFactory= 2011-02-16 00:13:11.256/116.634 Oracle Coherence GE 3.6.1.0<Warning> (thread=[ACTIVE] ExecuteThread: '0' for queue:'weblogic.kernel.Default (self-tuning)', member=n/a): PreferredUnicastUdpSocketfailed to set receive buffer size to 1428 packets (1.99MB); actual size is 25%,357 packets (512KB). Consult your OS documentation regarding increasing themaximum socket buffer size. Proceeding with the actual value may causesub-optimal performance. 2011-02-16 00:13:11.257/116.635 Oracle Coherence GE 3.6.1.0<D4> (thread=[ACTIVE] ExecuteThread: '0' for queue:'weblogic.kernel.Default (self-tuning)', member=n/a): TCMP bound to/10.229.188.238:8094 using SystemSocketProvider 2011-02-16 00:13:11.595/116.973 Oracle Coherence GE 3.6.1.0<Info> (thread=Cluster, member=n/a): Failed to satisfy the variance:allowed=16, actual=45 2011-02-16 00:13:11.596/116.974 Oracle Coherence GE 3.6.1.0<Info> (thread=Cluster, member=n/a): Increasing allowable variance to 19 2011-02-16 00:13:11.944/117.322 Oracle Coherence GE 3.6.1.0<Info> (thread=Cluster, member=n/a): This Member(Id=10,Timestamp=2011-02-16 00:13:11.72, Address=10.229.188.238:8094, MachineId=21486,Location=machine:jbayer-vm,process:32763, Role=WeblogicServer, Edition=GridEdition, Mode=Development, CpuCount=2, SocketCount=2) joined cluster withsenior Member(Id=1, Timestamp=2011-02-15 23:34:45.487,Address=10.229.188.238:8088, MachineId=21486,Location=machine:jbayer-vm,process:31060, Role=CoherenceServer, Edition=GridEdition, Mode=Development, CpuCount=2, SocketCount=2) 2011-02-16 00:13:11.997/117.375 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member(Id=2, Timestamp=2011-02-1523:35:16.04, Address=10.229.188.238:8090, MachineId=21486,Location=machine:jbayer-vm,process:31080, Role=CoherenceServer) joined Clusterwith senior member 1 2011-02-16 00:13:11.999/117.377 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member(Id=9, Timestamp=2011-02-1600:13:11.687, Address=10.229.188.238:8092, MachineId=21486,Location=machine:jbayer-vm,process:32676, Role=WeblogicServer) joined Clusterwith senior member 1 2011-02-16 00:13:12.044/117.422 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 1 joined Service Cluster withsenior member 1 2011-02-16 00:13:12.045/117.424 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 1 joined Service Managementwith senior member 1 2011-02-16 00:13:12.046/117.424 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 1 joined ServiceReplicatedSessionsMisc with senior member 1 2011-02-16 00:13:12.046/117.424 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 1 joined ServiceDistributedSessions with senior member 1 2011-02-16 00:13:12.046/117.424 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 2 joined Service Cluster withsenior member 1 2011-02-16 00:13:12.046/117.424 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 2 joined Service Managementwith senior member 1 2011-02-16 00:13:12.046/117.424 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 2 joined ServiceReplicatedSessionsMisc with senior member 1 2011-02-16 00:13:12.046/117.424 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=n/a): Member 2 joined Service DistributedSessionswith senior member 1 2011-02-16 00:13:12.087/117.465 Oracle Coherence GE 3.6.1.0<Info> (thread=[ACTIVE] ExecuteThread: '0' for queue:'weblogic.kernel.Default (self-tuning)', member=n/a): Started cluster Name=n/a WellKnownAddressList(Size=2, WKA{Address=10.229.188.238, Port=8088} WKA{Address=10.229.188.238, Port=8090} ) MasterMemberSet ( ThisMember=Member(Id=10,Timestamp=2011-02-16 00:13:11.72, Address=10.229.188.238:8094, MachineId=21486,Location=machine:jbayer-vm,process:32763, Role=WeblogicServer) OldestMember=Member(Id=1, Timestamp=2011-02-15 23:34:45.487,Address=10.229.188.238:8088, MachineId=21486,Location=machine:jbayer-vm,process:31060, Role=CoherenceServer) ActualMemberSet=MemberSet(Size=4,BitSetCount=2 Member(Id=1,Timestamp=2011-02-15 23:34:45.487, Address=10.229.188.238:8088,MachineId=21486, Location=machine:jbayer-vm,process:31060, Role=CoherenceServer) Member(Id=2,Timestamp=2011-02-15 23:35:16.04, Address=10.229.188.238:8090, MachineId=21486,Location=machine:jbayer-vm,process:31080, Role=CoherenceServer) Member(Id=9,Timestamp=2011-02-16 00:13:11.687, Address=10.229.188.238:8092,MachineId=21486, Location=machine:jbayer-vm,process:32676, Role=WeblogicServer) Member(Id=10,Timestamp=2011-02-16 00:13:11.72, Address=10.229.188.238:8094, MachineId=21486,Location=machine:jbayer-vm,process:32763, Role=WeblogicServer) ) RecycleMillis=1200000 RecycleSet=MemberSet(Size=0, BitSetCount=0 ) ) TcpRing{Connections=[9]} IpMonitor{AddressListSize=0} 2011-02-16 00:13:12.199/117.577 Oracle Coherence GE 3.6.1.0<D5> (thread=Invocation:Management, member=10): Service Management joinedthe cluster with senior service member 1 2011-02-16 00:13:12.234/117.612 Oracle Coherence GE 3.6.1.0 <D5>(thread=Cluster, member=10): Member 9 joined Service Management with seniormember 1 2011-02-16 00:13:12.478/117.856 Oracle Coherence GE 3.6.1.0<D5> (thread=DistributedCache:DistributedSessions, member=10): ServiceDistributedSessions joined the cluster with senior service member 1 2011-02-16 00:13:12.560/117.938 Oracle Coherence GE 3.6.1.0<D5> (thread=Cluster, member=10): Member 9 joined ServiceDistributedSessions with senior member 1 2011-02-16 00:13:12.618/117.996 Oracle Coherence GE 3.6.1.0<Info> (thread=[ACTIVE] ExecuteThread: '0' for queue:'weblogic.kernel.Default (self-tuning)', member=10): Configured session model"SplitHttpSessionCollection": Clustered Session CacheName=session-storage Local Session CacheName=local-session-storage Local Session AttributeCache Name=local-attribute-storage Death Certificate CacheName=session-death-certificates SessionDistributionController Class Name= AttributeScopeControllerClass Name=com.tangosol.coherence.servlet.AbstractHttpSessionCollection$ApplicationScopeController Maximum Session InactiveSeconds=3600 Session ID CharacterLength=52 Session LockingEnforced=false Member Session LockingEnforced=false Application SessionLocking Enforced=false Thread Session LockingEnforced=false Session Get LockTimeout=300 Suspect AttributeDetection=false Strict "ServletSpecification" Exception Handling=true Sticky SessionOwnership=false Sticky Session OwnershipService Name=SessionOwnership Assume Session Localityfor Reaping=false Parallel SessionReaping=true Allow LocalAttributes=false Use Default Session IDDecoding=true Use Default Session IDEncoding=false Session Expiry FilterFactory= 2011-02-16 00:13:12.723/118.101 Oracle Coherence GE 3.6.1.0<Info> (thread=[ACTIVE] ExecuteThread: '0' for queue:'weblogic.kernel.Default (self-tuning)', member=10): RegisteringHttpSessionManager(ServetContext=ServletContextWrapper (2.5) SessionHelper!=null MajorVersion=2 MinorVersion=5 Clustered=false ServletContext(wrapped)=weblogic.servlet.internal.session.CoherenceWebServletContextWrapper@1bc1ecee AttributeMap=null Oracle Coherence3.6.1.0) using object name "type=HttpSessionManager,nodeId=10,appId=CWebTestAppcounter" If so, now try invoking the index.jsp of thecounter context path. If both managedservers on are the same hostname, then the same cookie will be sent by thebrowser (ports differences are ignored by browsers when sending cookies), andyou should see the counter increment by 1 when you have the same session. If your WLS servers happen to have differentIP addresses or hostnames, then you will have to use a load balancer. More on that later. To see if Coherence is really being used forsession state, kill all the WLS JVM(s) (not the Coherence session cacheservers!). Hit refresh in your browser. Both servers should be down. Keep the browser sessions open. Nowrestart the WLS managed servers. Sincethe browser is open, the session reference is still in your browser cookie. When WLS servers are started again and you canrefresh the page, the count should pick up where you left off and not startover. Now you can try the load balancer such as Apacheor the simple one included with coherence. In this case I'm going to have the simple load balancer on port 8080 andrefer to the managed servers on ports 8001/8002 respectively. java -cpcoherence.jar com.tangosol.net.LoadBalancer adc2101131:8080 adc2101131:8001adc2101131:8002 Now I should be able to hit the load balancerdirectly on port 8080. Using the samebrowser session, I see that the cookie is still valid. Plus I see that the output from the simple loadbalancer shows me going to both servers, therefore we observe that the simpleCoherence load balancer is not sticky. Below is an example of that output: routing to 10.229.188.238:8002 routing to 10.229.188.238:8001 Now you should be able to stop one WLS managedserver and refresh and still get a valid result. If you refresh several times the LoadBalanceroutput should have something like this in the System.Out showing that it failedto connect to the server you stopped. *** could not connect to 10.229.188.238:8002;java.net.ConnectException: Connection refused Thenstop the other WLS managed server. Refreshusing the proxy address and there should be a failure to connect from thebrowser. Then restart the managed serveryou stopped first and the session should recover. This marks the end of the basic Coherence*Webwith WebLogic Server example. For moreinformation, I recommend reading the Coherence*Web documentation and turning onthe JMX reporting features of Coherence and using a tool like JConsole toexplore the MBeans for Coherence*Web.

This quick troubleshooting guide covers a basicsetup of a simple sample application using Coherence*Web instead of traditional WebLogic Server session replication. I used Coherence 3.6.1.x and...

WLS

JRockit Flight Recorder Plugin for WebLogic Tab Pack behind a Proxy

One of my favorite demos to show is JRockit Flight Recorder integration with WebLogic Server and the WebLogic Server Diagnostic Framework.  It's a great way to see what's going on inside applications and the JVM without agents using out-of-the-box defaults with WebLogic Server and JRockit.  I've made video's and blog posts about it previously and we'll be happy to give you a demo of it at Oracle Open World at the JavaOne booth or the WebLogic Server booth at the Demogrounds.  JRockit Mission Control, which is used to view the JVM recordings called JFRs for JRockit Flight Recording, has some plugins that it downloads from an Eclipse Update site to get the WebLogic Server specific view.  If you're behind a firewall and need to use a proxy, there is a simple way to launch JRMC from a java command line that let's you specify the proxy host, port and other settings you might use like authentication.  So from the JRockit bin directory, this is the command that you can use to launch Mission Control and make sure you use a proxy for network connections so you can use the Update Site with the proxy you specify.  You can substitute your JROCKIT_HOME for your actual path and your actual proxy settings instead of the ones we use at Oracle. JROCKIT_HOME/bin/java -Dhttp.proxyPort=80-Dhttp.proxyHost=www-proxy.us.oracle.com -jar JROCKIT_HOME/missioncontrol/mc.jar  Once you launch JRMC with the proxy enabled (or without the proxy settings if you do not need a proxy to access the Oracle Eclipse Update Site), you can then use the link to install the experimental plugin from the Help menu as shown below.  The one you want for sure is the WebLogic Tab Pack.

One of my favorite demos to show is JRockit Flight Recorder integration with WebLogic Server and the WebLogic Server Diagnostic Framework.  It's a great way to see what's going on inside applications...

WLS

wlstonweb - An Innovative Tool for WebLogic Scripting

Antonio De Juan from Oracle Support introduced me to a very innovative web application he built and put on www.samplecode.oracle.com called wlstonweb.  This cool web application has 2 primary features. 1) Interactive WLST Sessions via a web browser 2) WLST Script Management via a web browser The interactive WLST session via a web interface is surprisingly almost equivalent to using WLST from a shell because it leverages AJAX and JQuery Prototype.  The obvious benefit is, you can do everything that WLST exposes all from a web interface, which means that if you're on a mobile device, using someone else's computer, traveling, etc you have a lot of Administrative and Operation capabilities available even though you may not have a terminal handy. The WLST Script management features allows you to organize your WLST scripts on the file system in a catalog as well as create, edit, and run the scripts directly from the web interface.  This is a great way to share WLST scripts that are used often among different parts of an organization and build up a catalog of scripts. I created a brief recording showcasing wlstonweb. I encourage you to watch it in 720p so the recording isn't blurry.  Check it out and contact Antonio via the samplecode site if you have comments or suggestions.  The sampelcode UI can be difficult to navigate for new users, so go to the wlstonweb project home page -> File Releases -> war file -> prototype -> wlstonweb.war to download it . Nice work Antonio!

Antonio De Juan from Oracle Support introduced me to a very innovative web application he built and put on www.samplecode.oracle.com called wlstonweb.  This cool web application has 2 primary...

WLS

Create WebLogic Diagnostic Image With Metric Thresholds

My colleague Jeff West pointed me to Stack Overflow today where someone had a question about how to take a thread dump when a certain condition was present.  In their case, they are trying to troubleshoot a low thread count.  Their monitoring tools were missing the critical time window and by the time the thread dump was taken, the threads had recovered.  I thought this would be a great opportunity to see if a Diagnostic Image would contain a thread dump (yes it does), and whether I could automatically set WebLogic to create the Diagnostic Image easily when this condition was present (yes it is).  Below is the image illustrating the issue they were trying to solve. Check out this recording if you want to know more about triggering actions when certain conditions are met automatically with WebLogic Server.  I show a WebLogic Diagnostic Framework (WLDF) System Module, configure a Notification and a Watch based on a JMX metric threshold.  The Watch has with an Alarm with a manual reset (via JMX/WLST) so that the Watch will not fire again until I reset it although you can also choose not to have Alarms or have them reset automatically after a time period. I encourage you to watch this video in 720p mode or higher for clarity.  You can change that using the menu at the bottom right video widget.  It will not display correctly in this blog template when using 720p mode.

My colleague Jeff West pointed me to Stack Overflow today where someone had a question about how to take a thread dump when a certain condition was present.  In their case, they are trying to...

WLS

WebLogic Server JMS WLST Script – Who is Connected To My Server

Update 6/27/2011: Tom Barnes indicated a clarification, check out the comments.Ever want to know who was connected to your WebLogic Server instance for troubleshooting?  An email exchange about this topic and JMS came up this week, and I’ve heard it come up once or twice before too.  Sometimes it’s interesting or helpful to know the list of JMS clients (IP Addresses, JMS Destinations, message counts) that are connected to a particular JMS server.  This can be helpful for troubleshooting.  Tom Barnes from the WebLogic Server JMS team provided some helpful advice: The JMS connection runtime mbean has “getHostAddress”, which returns the host address of the connecting client JVM as a string.  A connection runtime can contain session runtimes, which in turn can contain consumer runtimes.  The consumer runtime, in turn has a “getDestinationName” and “getMemberDestinationName”.  I think that this means you could write a WLST script, for example, to dump all consumers, their destinations, plus their parent session’s parent connection’s host addresses.    Note that the client runtime mbeans (connection, session, and consumer) won’t necessarily be hosted on the same JVM as a destination that’s in the same cluster (client messages route from their connection host to their ultimate destination in the same cluster). Writing the Script So armed with this information, I decided to take the challenge and see if I could write a WLST script to do this.  It’s always helpful to have the WebLogic Server MBean Reference handy for activities like this.  This one is focused on JMS Consumers and I only took a subset of the information available, but it could be modified easily to do Producers.  I haven’t tried this on a more complex environment, but it works in my simple sandbox case, so it should give you the general idea. # Better to use Secure Config File approach for login as shown here http://buttso.blogspot.com/2011/02/using-secure-config-files-with-weblogic.html connect('weblogic','welcome1','t3://localhost:7001')   # Navigate to the Server Runtime and get the Server Name serverRuntime() serverName = cmo.getName()   # Multiple JMS Servers could be hosted by a single WLS server cd('JMSRuntime/' + serverName + '.jms' ) jmsServers=cmo.getJMSServers()   # Find the list of all JMSServers for this server namesOfJMSServers = '' for jmsServer in jmsServers: namesOfJMSServers = jmsServer.getName() + ' '   # Count the number of connections jmsConnections=cmo.getConnections() print str(len(jmsConnections)) + ' JMS Connections found for ' + serverName + ' with JMSServers ' + namesOfJMSServers   # Recurse the MBean tree for each connection and pull out some information about consumers for jmsConnection in jmsConnections: try: print 'JMS Connection:' print ' Host Address = ' + jmsConnection.getHostAddress() print ' ClientID = ' + str( jmsConnection.getClientID() ) print ' Sessions Current = ' + str( jmsConnection.getSessionsCurrentCount() ) jmsSessions = jmsConnection.getSessions() for jmsSession in jmsSessions: jmsConsumers = jmsSession.getConsumers() for jmsConsumer in jmsConsumers: print ' Consumer:' print ' Name = ' + jmsConsumer.getName() print ' Messages Received = ' + str(jmsConsumer.getMessagesReceivedCount()) print ' Member Destination Name = ' + jmsConsumer.getMemberDestinationName() except: print 'Error retrieving JMS Consumer Information' dumpStack() # Cleanup disconnect() exit() Example Output I expect the output to look something like this and loop through all the connections, this is just the first one: 1 JMS Connections found for AdminServer with JMSServers myJMSServerJMS Connection:  Host Address = 127.0.0.1  ClientID = None  Sessions Current = 16   Consumer:     Name = consumer40     Messages Received = 1     Member Destination Name = myJMSModule!myQueue Notice that it has the IP Address of the client.  There are 16 Sessions open because I’m using an MDB, which defaults to 16 connections, so this matches what I expect.  Let’s see what the full output actually looks like: D:\Oracle\fmw11gr1ps3\user_projects\domains\offline_domain>java weblogic.WLST d:\temp\jms.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 'offline_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 ServerRuntimeMBean as the root. For more help, use help(serverRuntime)   1 JMS Connections found for AdminServer with JMSServers myJMSServer JMS Connection: Host Address = 127.0.0.1 ClientID = None Sessions Current = 16 Consumer: Name = consumer40 Messages Received = 2 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer34 Messages Received = 2 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer37 Messages Received = 2 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer16 Messages Received = 2 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer46 Messages Received = 2 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer49 Messages Received = 2 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer43 Messages Received = 1 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer55 Messages Received = 1 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer25 Messages Received = 1 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer22 Messages Received = 1 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer19 Messages Received = 1 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer52 Messages Received = 1 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer31 Messages Received = 1 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer58 Messages Received = 1 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer28 Messages Received = 1 Member Destination Name = myJMSModule!myQueue Consumer: Name = consumer61 Messages Received = 1 Member Destination Name = myJMSModule!myQueue Disconnected from weblogic server: AdminServer     Exiting WebLogic Scripting Tool. Thanks to Tom Barnes for the hints and the inspiration to write this up. Image of telephone switchboard courtesy of http://www.JoeTourist.net/ JoeTourist InfoSystems

Update 6/27/2011: Tom Barnes indicated a clarification, check out the comments. Ever want to know who was connected to your WebLogic Server instance for troubleshooting?  An email exchange about this...

WLS

WebLogic Server–Use the Execution Context ID in Applications–Lessons From Hansel and Gretel

I learned a neat trick this week.  Don’t let your breadcrumbs go to waste like Hansel and Gretel did!  Keep track of the code path, logs and errors for each request as they flow through the system.  Earlier this week an OTN forum post in the WLS – General category by Oracle Ace John Stegeman asked a question how to retrieve the Execution Context ID so that it could be used on an error page that a user could provide to a help desk or use to check with application administrators so they could look up what went wrong.  What is the Execution Context ID (ECID)?  Fusion Middleware injects an ECID as a request enters the system and it says with the request as it flows from Oracle HTTP Server to Oracle Web Cache to multiple WebLogic Servers to the Oracle Database. It’s a way to uniquely identify a request across tiers.  According to the documentation it’s: The value of the ECID is a unique identifier that can be used to correlate individual events as being part of the same request execution flow. For example, events that are identified as being related to a particular request typically have the same ECID value.  The format of the ECID string itself is determined by an internal mechanism that is subject to change; therefore, you should not have or place any dependencies on that format. The novel idea that I see John had was to extend this concept beyond the diagnostic information that is captured by Fusion Middleware.  Why not also use this identifier in your logs and errors so you can correlate even more information together!  Your logging might already identify the user, so why not identify the request so you filter down even more.  All you need to do inside of WebLogic Server to get ahold of this information is invoke DiagnosticConextHelper: weblogic.diagnostics.context.DiagnosticContextHelper.getContextId() This class has other helpful methods to see other values tracked by the diagnostics framework too.  This way I can see even more detail and get information across tiers. In performance profiling, this can be very handy to track down where time is being spent in code.  I’ve blogged and made videos about this before.  JRockit Flight Recorder can use the WLDF Diagnostic Volume in WLS 10.3.3+ to automatically capture and correlate lots of helpful information for each request without installing any special agents and with the out-of-the-box JRockit and WLS settings!  You can see here how information is displayed in JRockit Flight Recorder about a single request as it calls a Servlet, which calls an EJB, which gets a DB connection, which starts a transaction, etc.  You can get timings around everything and even see the SQL that is used. http://download.oracle.com/docs/cd/E21764_01/web.1111/e13714/using_flightrecorder.htm#WLDFC480 Recent versions of the WLS console also are able to visualize this data too, so it works with other JVMs besides JRockit when you turn on WLDF instrumentation. I wrote a little sample application that verified to myself that the ECID did actually cross JVM boundaries.  I invoked a Servlet in one JVM, which acted as an EJB client to Stateless Session Bean running in another JVM.  Each call returned the same ECID.  You need to turn on WLDF Instrumentation for this to work otherwise the framework returns null.  I’m glad John put me on to this API as I have some interesting ideas on how to correlate some information together.

I learned a neat trick this week.  Don’t let your breadcrumbs go to waste like Hansel and Gretel did!  Keep track of the code path, logs and errors for each request as they flow through the system.  Ea...

WLS

Sharing a Class With a WebLogic Classloader Without Modifying Scripts

A question (mostly original with some slight editing on my part) came up on our internal mailing list today that I thought might be interesting to those that have cloassloader questions.  For a quick refresher on the options for classloading in WebLogic, click the image to see a larger image or get the presentation from the bottom of the post on slideshare.  The key for this scenario is the DOMAIN_HOME/lib directory. Scenario: We have a embeddable java component which gets shipped within every webapp in our suite of products. This embeddable java component has a cache object which is loaded every time the component is initialized by the webapp. This cache object is a singleton and has the same content across all the webapps. We have one managed server in which many ear files are deployed to. Each ear initialize's this embeddable java component on start up. Issue: When I profile the objects loaded (using Classloader Analysis Tool) in each of these web apps I see that this cache singleton object is loaded in each one of the web app class loaders. I would like to load just one of these singleton objects and reference the same object across all the ear's. This saves heap space and all the calls that it takes to create this cache object in each ear. Even though its a singleton I see that since the class loaders are different for each ear that it creates a new cache object. I have an understanding of the weblogic class loader hierarchies (bootstrap, system, webapp etc). I don't want to move this embeddable java component and its dependencies to the system class loader by modifying the scripts or environment variables.  Are there other options? My answer:  Have a look at the DOMAIN_HOME/lib directory. http://download.oracle.com/docs/cd/E21764_01/web.1111/e13706/classloading.htm#i1096881 To try it, just drop the jars you want to be shared in the DOMAIN_HOME/lib directory. Here’s an example.  /** To change this template, choose Tools | Templates* and open the template in the editor.*/package test; import java.util.Map; /**** @author jbayer*/public class SharedCache { public static final Map<String,String> mapCache = new java.util.HashMap<String, String> (); static { System.out.println( SharedCache.class.toString() + " loaded into a classloader" + SharedCache.class.getClassLoader().toString() ); }  public SharedCache() { } } Now I use this class in two webapps named WebApplication1 and WebApplication2 that refer to the SharedCache class in their identical index.jsp <%@page contentType="text/html" pageEncoding="UTF-8" import="test.*"%><!DOCTYPE html><html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <h1>Hello World! Cache size: <% SharedCache myCache = new SharedCache(); out.print( myCache.mapCache.size() ); %> </h1> </body></html> When the test.SharedCache class is loaded from each web application respectively, you should see the following in the System.out showing that 2 versions of the class were loaded into separate classloaders for each web module: class test.SharedCache loaded into a classloaderweblogic.utils.classloaders.ChangeAwareClassLoader@bde4ac finder: weblogic.utils.classloaders.CodeGenClassFinder@1ff9980 annotation: WebApplication1@webclass test.SharedCache loaded into a classloaderweblogic.utils.classloaders.ChangeAwareClassLoader@4a4acd finder: weblogic.utils.classloaders.CodeGenClassFinder@3f08e3 annotation: WebApplication2@web Once you drop the jar with the test.SharedCache in the DOMAIN_HOME/lib and restart the server, and access both web apps, you'll see the class is now shared from one system classloader: class test.SharedCache loaded into a classloaderjava.net.URLClassLoader@88e2dd And if you use CAT, you can see that both applications use the same System Classloader.  Click to enlarge.  The hash code shows that the same classloader is used for both applications. Check out Jeff West’s recording on WebLogic Server classloaders and CAT. http://www.slideshare.net/jeffreyawest/weblogic-filtering-classloader-and-classloader-analysis-tool-demo WebLogic's ClassLoaders, Filtering ClassLoader and ClassLoader Analysis Tool View more presentations from Jeffrey West

A question (mostly original with some slight editing on my part) came up on our internal mailing list today that I thought might be interesting to those that have cloassloader questions.  For a quick...

WLS

Use WLST to Delete All JMS Messages From a Destination

I got a question today about whether WebLogic Server has any tools to delete all messages from a JMS Queue.  It just so happens that the WLS Console has this capability already.  It’s available on the screen after the “Show Messages” button is clicked on a destination’s Monitoring tab as seen in the screen shot below. The console is great for something ad-hoc, but what if I want to automate this?  Well it just so happens that the console is just a weblogic application layered on top of the JMX Management interface.  If you look at the MBean Reference, you’ll find a JMSDestinationRuntimeMBean that includes the operation deleteMessages that takes a JMS Message Selector as an argument.  If you pass an empty string, that is essentially a wild card that matches all messages. Coding a stand-alone JMX client for this is kind of lame, so let’s do something more suitable to scripting.  In addition to the console, WebLogic Scripting Tool (WLST) based on Jython is another way to browse and invoke MBeans, so an equivalent interactive shell session to delete messages from a destination would looks like this: D:\Oracle\fmw11gr1ps3\user_projects\domains\hotspot_domain\bin>setDomainEnv.cmd D:\Oracle\fmw11gr1ps3\user_projects\domains\hotspot_domain>java weblogic.WLST   Initializing WebLogic Scripting Tool (WLST) ...   Welcome to WebLogic Server Administration Scripting Shell   Type help() for help on available commands   wls:/offline> connect('weblogic','welcome1','t3://localhost:7001') Connecting to t3://localhost:7001 with userid weblogic ... Successfully connected to Admin Server 'AdminServer' that belongs to domain 'hotspot_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:/hotspot_domain/serverConfig> serverRuntime() Location changed to serverRuntime tree. This is a read-only tree with ServerRuntimeMBean as the root. For more help, use help(serverRuntime)   wls:/hotspot_domain/serverRuntime> cd('JMSRuntime/AdminServer.jms/JMSServers/JMSServer-0/Destinations/SystemModule-0!Queue-0') wls:/hotspot_domain/serverRuntime/JMSRuntime/AdminServer.jms/JMSServers/JMSServer-0/Destinations/SystemModule-0!Queue-0> ls() dr-- DurableSubscribers   -r-- BytesCurrentCount 0 -r-- BytesHighCount 174620 -r-- BytesPendingCount 0 -r-- BytesReceivedCount 253548 -r-- BytesThresholdTime 0 -r-- ConsumersCurrentCount 0 -r-- ConsumersHighCount 0 -r-- ConsumersTotalCount 0 -r-- ConsumptionPaused false -r-- ConsumptionPausedState Consumption-Enabled -r-- DestinationInfo javax.management.openmbean.CompositeDataSupport(compositeType=javax.management.openmbean.CompositeType(name=DestinationInfo,items=((itemName=ApplicationName,itemType=javax.management.openmbean.SimpleType(name=java.lang.String)),(itemName=ModuleName,itemType=javax.management.openmbean.SimpleType(name=java.lang.String)),(itemName openmbean.SimpleType(name=java.lang.Boolean)),(itemName=SerializedDestination,itemType=javax.management.openmbean.SimpleType(name=java.lang.String)),(itemName=ServerName,itemType=javax.management.openmbean.SimpleType(name=java.lang.String)),(itemName=Topic,itemType=javax.management.openmbean.SimpleType(name=java.lang.Boolean)),(itemName=VersionNumber,itemType=javax.management.op ule-0!Queue-0, Queue=true, SerializedDestination=rO0ABXNyACN3ZWJsb2dpYy5qbXMuY29tbW9uLkRlc3RpbmF0aW9uSW1wbFSmyJ1qZfv8DAAAeHB3kLZBABZTeXN0ZW1Nb2R1bGUtMCFRdWV1ZS0wAAtKTVNTZXJ2ZXItMAAOU3lzdGVtTW9kdWxlLTABAANBbGwCAlb6IS6T5qL/AAAACgEAC0FkbWluU2VydmVyAC2EGgJW+iEuk+ai/wAAAAsBAAtBZG1pblNlcnZlcgAthBoAAQAQX1dMU19BZG1pblNlcnZlcng=, ServerName=JMSServer-0, Topic=false, VersionNumber=1}) -r-- DestinationType Queue -r-- DurableSubscribers null -r-- InsertionPaused false -r-- InsertionPausedState Insertion-Enabled -r-- MessagesCurrentCount 0 -r-- MessagesDeletedCurrentCount 3 -r-- MessagesHighCount 2 -r-- MessagesMovedCurrentCount 0 -r-- MessagesPendingCount 0 -r-- MessagesReceivedCount 3 -r-- MessagesThresholdTime 0 -r-- Name SystemModule-0!Queue-0 -r-- Paused false -r-- ProductionPaused false -r-- ProductionPausedState Production-Enabled -r-- State advertised_in_cluster_jndi -r-- Type JMSDestinationRuntime   -r-x closeCursor Void : String(cursorHandle) -r-x deleteMessages Integer : String(selector) -r-x getCursorEndPosition Long : String(cursorHandle) -r-x getCursorSize Long : String(cursorHandle) -r-x getCursorStartPosition Long : String(cursorHandle) -r-x getItems javax.management.openmbean.CompositeData[] : String(cursorHandle),Long(start),Integer(count) -r-x getMessage javax.management.openmbean.CompositeData : String(cursorHandle),Long(messageHandle) -r-x getMessage javax.management.openmbean.CompositeData : String(cursorHandle),String(messageID) -r-x getMessage javax.management.openmbean.CompositeData : String(messageID) -r-x getMessages String : String(selector),Integer(timeout) -r-x getMessages String : String(selector),Integer(timeout),Integer(state) -r-x getNext javax.management.openmbean.CompositeData[] : String(cursorHandle),Integer(count) -r-x getPrevious javax.management.openmbean.CompositeData[] : String(cursorHandle),Integer(count) -r-x importMessages Void : javax.management.openmbean.CompositeData[],Boolean(replaceOnly) -r-x moveMessages Integer : String(java.lang.String),javax.management.openmbean.CompositeData,Integer(java.lang.Integer) -r-x moveMessages Integer : String(selector),javax.management.openmbean.CompositeData -r-x pause Void : -r-x pauseConsumption Void : -r-x pauseInsertion Void : -r-x pauseProduction Void : -r-x preDeregister Void : -r-x resume Void : -r-x resumeConsumption Void : -r-x resumeInsertion Void : -r-x resumeProduction Void : -r-x sort Long : String(cursorHandle),Long(start),String[](fields),Boolean[](ascending)   wls:/hotspot_domain/serverRuntime/JMSRuntime/AdminServer.jms/JMSServers/JMSServer-0/Destinations/SystemModule-0!Queue-0> cmo.deleteMessages('') 2where the domain name is “hotspot_domain”, the JMS Server name is “JMSServer-0”, the Queue name is “Queue-0” and the System Module is named “SystemModule-0”.  To invoke the operation, I use the “cmo” object, which is the “Current Management Object” that represents the currently navigated to MBean.  The 2 indicates that two messages were deleted.  Combining this WLST code with a recent post by my colleague Steve that shows you how to use an encrypted file to store the authentication credentials, you could easily turn this into a secure automated script.  If you need help with that step, a long while back I blogged about some WLST basics.  Happy scripting.

I got a question today about whether WebLogic Server has any tools to delete all messages from a JMS Queue.  It just so happens that the WLS Console has this capability already.  It’s available on the...

WLS

Look Inside WebLogic Server Embedded LDAP with an LDAP Explorer

Today a question came up on our internal WebLogic Server mailing lists about an issue deleting a Group from WebLogic Server.  The group had a special character in the name. The WLS console refused to delete the group with the message a java.net.MalformedURLException and another message saying “Errors must be corrected before proceeding.” as shown below. The group aa:bb is the one with the issue.  Click to enlarge. WebLogic Server includes an embedded LDAP server that can be used for managing users and groups for “reasonably small environments (10,000 or fewer users)”.  For organizations scaling larger or using more high-end features, I recommend looking at one of Oracle’s very popular enterprise directory services products like Oracle Internet Directory or Oracle Directory Server Enterprise Edition.  You can configure multiple authenicators in WebLogic Server so that you can use multiple directories at the same time. I am not sure WebLogic Server supports special characters in group names for the Embedded LDAP server, but in this case both the console and WLST reported the same issue deleting the group with the special character in the name.  Here’s the WLST output: wls:/hotspot_domain/serverConfig/SecurityConfiguration/hotspot_domain/Realms/myrealm/AuthenticationProviders/DefaultAuthenticator> cmo.removeGroup('aa:bb') Traceback (innermost last): File "<console>", line 1, in ? weblogic.security.providers.authentication.LDAPAtnDelegateException: [Security:090296]invalid URL ldap:///ou=people,ou=myrealm,dc=hotspot_domain??sub?(&(objectclass=person)(wlsMemberOf=cn=aa:bb,ou=groups,ou=myrealm,dc=hotspot_domain)) at weblogic.security.providers.authentication.LDAPAtnGroupMembersNameList.advance(LDAPAtnGroupMembersNameList.java:254) at weblogic.security.providers.authentication.LDAPAtnGroupMembersNameList.<init>(LDAPAtnGroupMembersNameList.java:119) at weblogic.security.providers.authentication.LDAPAtnDelegate.listGroupMembers(LDAPAtnDelegate.java:1392) at weblogic.security.providers.authentication.LDAPAtnDelegate.removeGroup(LDAPAtnDelegate.java:1989) at weblogic.security.providers.authentication.DefaultAuthenticatorImpl.removeGroup(DefaultAuthenticatorImpl.java:242) at weblogic.security.providers.authentication.DefaultAuthenticatorMBeanImpl.removeGroup(DefaultAuthenticatorMBeanImpl.java:407) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at weblogic.management.jmx.modelmbean.WLSModelMBean.invoke(WLSModelMBean.java:437) at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:836) at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:761) at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase$16.run(WLSMBeanServerInterceptorBase.java:449) at java.security.AccessController.doPrivileged(Native Method) at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase.invoke(WLSMBeanServerInterceptorBase.java:447) at weblogic.management.mbeanservers.internal.JMXContextInterceptor.invoke(JMXContextInterceptor.java:263) at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase$16.run(WLSMBeanServerInterceptorBase.java:449) at java.security.AccessController.doPrivileged(Native Method) at weblogic.management.jmx.mbeanserver.WLSMBeanServerInterceptorBase.invoke(WLSMBeanServerInterceptorBase.java:447) at weblogic.management.mbeanservers.internal.SecurityInterceptor.invoke(SecurityInterceptor.java:444) at weblogic.management.jmx.mbeanserver.WLSMBeanServer.invoke(WLSMBeanServer.java:323) at weblogic.management.mbeanservers.internal.JMXConnectorSubjectForwarder$11$1.run(JMXConnectorSubjectForwarder.java:663) at java.security.AccessController.doPrivileged(Native Method) at weblogic.management.mbeanservers.internal.JMXConnectorSubjectForwarder$11.run(JMXConnectorSubjectForwarder.java:661) at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363) at weblogic.management.mbeanservers.internal.JMXConnectorSubjectForwarder.invoke(JMXConnectorSubjectForwarder.java:654) at javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1427) at javax.management.remote.rmi.RMIConnectionImpl.access$200(RMIConnectionImpl.java:72) at javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1265) at java.security.AccessController.doPrivileged(Native Method) at javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1367) at javax.management.remote.rmi.RMIConnectionImpl.invoke(RMIConnectionImpl.java:788) at javax.management.remote.rmi.RMIConnectionImpl_WLSkel.invoke(Unknown Source) at weblogic.rmi.internal.BasicServerRef.invoke(BasicServerRef.java:667) at weblogic.rmi.internal.BasicServerRef$1.run(BasicServerRef.java:522) at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:363) at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:146) at weblogic.rmi.internal.BasicServerRef.handleRequest(BasicServerRef.java:518) at weblogic.rmi.internal.wls.WLSExecuteRequest.run(WLSExecuteRequest.java:118) at weblogic.work.ExecuteThread.execute(ExecuteThread.java:207) at weblogic.work.ExecuteThread.run(ExecuteThread.java:176) Caused by: java.net.MalformedURLException at netscape.ldap.LDAPUrl.readNextConstruct(LDAPUrl.java:651) at netscape.ldap.LDAPUrl.parseUrl(LDAPUrl.java:277) at netscape.ldap.LDAPUrl.<init>(LDAPUrl.java:114) at weblogic.security.providers.authentication.LDAPAtnGroupMembersNameList.advance(LDAPAtnGroupMembersNameList.java:224) ... 41 moreIt’s fairly clear that in order to work that the : character needs to be URL encoded to %3A or similar.  But all is not lost, there is another way.  You can configure an LDAP Explorer like JXplorer to WebLogic Server Embedded LDAP and browse/edit the entries.Follow the instructions here, being sure to change the authentication credentials to the Embedded LDAP server to some value you know, as by default they are some unknown value.  You’ll need to reboot the WebLogic Server Admin Server after making this change.Now configure JXplorer to connect as described in the documentation.  I’ve circled the important inputs.  In this example, my domain name is “hotspot_domain” which listens on the localhost listen address and port 7001.  The cn=Admin user name is a constant identifier for the Administrator of the embedded LDAP and that does not change, but you need to know what it is so you can enter it into the tool you use.Once you connect successfully, you can explore the entries and in this case delete the group that is no longer desired.

Today a question came up on our internal WebLogic Server mailing lists about an issue deleting a Group from WebLogic Server.  The group had a special character in the name. The WLS console refused to...

Coherence

WebLogic Server 10.3.4 Screencast – Coherence Server Lifecycle Management

Below is a quick overview of a new feature introduced in WebLogic Server 10.3.4 that continues to deepen the Coherence and WebLogic Server integration.  Previously Oracle introduced Coherence Clusters as a concept that could be used to manage Coherence configuration for instances of Coherence that ran inside of WebLogic Server JVMs.  Now Oracle has introduced Coherence Servers, which are stand-alone JVMs not running inside WebLogic Server that are thin wrappers around a Coherence DefaultCacheServer.  The Coherence Server can reference the Coherence Cluster configuration as well as specify fine-grained settings for each Coherence Server such as a name, port, classpath, and JVM options.  This feature ties into WebLogic Server Node Manager, which is a process that can always be running as a service on each operating system instance where your WebLogic or Coherence processes can run.  From one central location WebLogic Server users can easily manage the configuration and lifecycle of their Coherence JVMs in addition to their WebLogic Server JVMs potentially running on many, many different hosts.  This should be a useful feature for customers that use WebLogic Server and Coherence together as well as for Coherence customers that do not utilize WebLogic Server much today, but would like additional manageability and control over Coherence processes.  Check out the documentation for detail and examples of scripts.  There is a short (5 min) screencast below.  

Below is a quick overview of a new feature introduced in WebLogic Server 10.3.4 that continues to deepen the Coherence and WebLogic Server integration.  Previously Oracle introduced Coherence...

WLS

WebLogic Scripting Tool Tip – relax the syntax with the easy button

I stumbled on to this feature in WLST tonight called easeSyntax.  Apparently it’s a hidden feature that one of the WebLogic support engineers blogged about that allows you to simplify the commands in the interactive mode to have fewer parentheses and quotes.  For example, see how some of the commands instead of typing “ls()” I can type '”ls” or “cd(“/somepath”)” can become “cd /somepath”.  It’s not going to save the world, but it will help cut down on some extra typing. The example I was researching when stumbling into this was for how to print the runtime status of deployed application named “hello” on the “AdminServer”.  See the below output. wls:/base_domain/domainConfig> easeSyntax()   You have chosen to ease syntax for some WLST commands. However, the easy syntax should be strictly used in interactive mode. Easy syntax will not function properly in script mode and when used in loops. You can still use the regular jython syntax although you have opted for easy syntax. Use easeSyntax to turn this off. Use help(easeSyntax) for commands that support easy syntax wls:/base_domain/domainConfig> domainRuntime   wls:/base_domain/domainRuntime> ls dr-- AppRuntimeStateRuntime dr-- CoherenceServerLifeCycleRuntimes dr-- ConsoleRuntime dr-- DeployerRuntime dr-- DeploymentManager dr-- DomainServices dr-- LogRuntime dr-- MessageDrivenControlEJBRuntime dr-- MigratableServiceCoordinatorRuntime dr-- MigrationDataRuntimes dr-- PolicySubjectManagerRuntime dr-- SNMPAgentRuntime dr-- ServerLifeCycleRuntimes dr-- ServerRuntimes dr-- ServerServices dr-- ServiceMigrationDataRuntimes   -r-- ActivationTime Wed Dec 15 22:37:02 PST 2010 -r-- MessageDrivenControlEJBRuntime null -r-- MigrationDataRuntimes null -r-- Name base_domain -rw- Parent null -r-- ServiceMigrationDataRuntimes null -r-- Type DomainRuntime   -r-x preDeregister Void : -r-x restartSystemResource Void : WebLogicMBean(weblogic.management.configuration.SystemResourceMBean)   wls:/base_domain/domainRuntime> cd AppRuntimeStateRuntime/AppRuntimeStateRuntime wls:/base_domain/domainRuntime/AppRuntimeStateRuntime/AppRuntimeStateRuntime> ls   -r-- ApplicationIds java.lang.String[active-cache#1.0@1.0, coherence-web-spi#1.0.0.0@1.0.0.0, coherence#3. -r-- Name AppRuntimeStateRuntime -r-- Type AppRuntimeStateRuntime   -r-x getCurrentState String : String(appid),String(moduleid),String(subModuleId),String(target) -r-x getCurrentState String : String(appid),String(moduleid),String(target) -r-x getCurrentState String : String(appid),String(target) -r-x getIntendedState String : String(appid) -r-x getIntendedState String : String(appid),String(target) -r-x getModuleIds String[] : String(appid) -r-x getModuleTargets String[] : String(appid),String(moduleid) -r-x getModuleTargets String[] : String(appid),String(moduleid),String(subModuleId) -r-x getModuleType String : String(appid),String(moduleid) -r-x getRetireTimeMillis Long : String(appid) -r-x getRetireTimeoutSeconds Integer : String(appid) -r-x getSubmoduleIds String[] : String(appid),String(moduleid) -r-x isActiveVersion Boolean : String(appid) -r-x isAdminMode Boolean : String(appid),String(java.lang.String) -r-x preDeregister Void :   wls:/base_domain/domainRuntime/AppRuntimeStateRuntime/AppRuntimeStateRuntime> cmo.getCurrentState('hello','AdminServer') 'STATE_ACTIVE' wls:/base_domain/domainRuntime/AppRuntimeStateRuntime/AppRuntimeStateRuntime> cd / wls:/base_domain/domainRuntime>

I stumbled on to this feature in WLST tonight called easeSyntax.  Apparently it’s a hidden feature that one of the WebLogic support engineers blogged about that allows you to simplify the commands in...

WLS

WebLogic Notifications – Watch the Log and Send Email

Can WebLogic send an email when a certain message shows up in the WLS log?  The answer is yes and it is pretty straight-forward to configure.  In this case, my colleague Sherwood wanted to get an email when the message indicating that an SSL certificate is going to expire within 30 days is written to the log.  The WebLogic Diagnostic Framework or WLDF enables this capability with a sub-feature called Watches and Notifications.  Here is a real simple example to get an email when the server starts in a RUNNING state. Configure a Mail Session The console docs give you the step-by-step.  Here’s what mine looks like – don’t forget to target it at all of your servers.  I use Apache James as mail server on my localhost.  Click to enlarge. Configure a Diagnostic System Module The console docs again give you the step-by step, make sure you target it at your server. Once you have the system module in place, then configure a Notifcation that references the Mail Session you set up previously.  You can see from the screenshot that there is an easy way to change the subject and body of the email.  Click to enlarge. Then configure a Log Watch that uses the Notification.  In my server log, the message looks like this: ####<Jul 15, 2010 8:16:46 PM CDT> <Notice> <WebLogicServer> <jbayer-us> <AdminServer> <main> <<WLS Kernel>> <> <> <1279243006546> <BEA-000360> <Server started in RUNNING mode>So that means we should use the expression builder to look for this particular message id.  Remember, WebLogic is multi-lingual, so instead of looking for the hard-coded text, just search for the unique ID of the untranslated log message. The last step is a gotcha I missed the first time.  The log message we are searching for is at a “Notice” level.  By default Log Watches only are fired against “Warning” and higher (I think – I forgot what the default was).  You need to change it on the “Watches and Notifications” tab of the Diagnostic System Module.  Click to enlarge. That should be it, restart the server so that the message is logged and check your email.  Click to enlarge. Of course WLDF can do a lot more sophisticated notifications too.  In addition to email possible notifcation actions are JMS, JMX, SNMP traps, and capturing a system diagnostic image.  The watches can be more sophisticated too, such as watching JMX attributes which is described in this other blog.  If you have any issues, it can be useful to enable “Debug” of the parts of the diagnostics subsystem in your Server configuration and check out the log messages.Screencast following the procedure above

Can WebLogic send an email when a certain message shows up in the WLS log?  The answer is yes and it is pretty straight-forward to configure.  In this case, my colleague Sherwood wanted to get an...

WebLogic Server Screencasts - Where does the time go?

I recently recorded several short screencasts illustrating various approaches to find out where time is being spent as client requests flow through WebLogic Server.  WebLogic Server has a very powerful diagnostics and monitoring sub-system called WebLogic Diagnostic Framework (WLDF) that has many knobs and dials.  However, many customers I work with just want to get started with the basics and not learn all of the expert nuances of WLDF upfront.  The latest WLS 11gR1 PS2 release (aka WLS 10.3.3) includes new features that surface WLDF in a way that is much easier to use – particularly to track request timings. JRockit Mission Control and Flight Recorder – Easy and Fast Perhaps the most exciting feature introduced in WLS 10.3.3 is the improved integration with JRockit.  As of R28 of JRockit, a default recording can always be kept on – similar to how a black-box works in an airplane.  So if you have a crash, you can look back into the black box and see what happened.  Marcus Hirt from the JRockit team has some more detail.  But this isn’t just for low-level JVM data, WLS 10.3.3 also adds the ability to publish WebLogic events to these JRockit recordings with a very simple “volume” dial in the console or WLST.  No knowledge of deployment descriptors or WLDF is required.  So if you think that a particular web page is slow, simply configure the volume to either low, medium or high and get a recording of some requests and it’s easy to see timings inside and around each request.  The documentation has a lot more detail, but these two screencasts provide an idea of how easy it is to get going with these new capabilities in WLS 10.3.3 and R28 of JRockit.  Keep in mind that this is an extremely low overhead approach that is designed with production use in mind. JRockit Mission Control – Using JRockit Flight Recorder with WebLogic Server JRockit Mission Control – Experimental WebLogic Server Plugin WLS Console Request Performance This feature visually shows individual requests as they flow through various WLS subsystems such as Servlets, EJBs, JDBC, JMS, WebServices, JTA, etc and tracks the timings around each part of the request as well as the total time.  So if a particular web page is slow, you can use this feature to instrument an application and find out where the time is being spent.  This is more of a lowest-common-denominator approach than JRockit Flight Recorder in that it works for all supported JVM’s and not just the most recent JRockit R28 release.  It also works with older releases of WebLogic down to 9.2 if you use the older console extension applet.  The Request Performance console view introduced in 10.3.3 is a replacement for part of the diagnostics applet from previous releases.  This recording uses an application that leverages the weblogic-diagnostics.xml deployment descriptor to specify which subsystems to trace timings for, but instead of creating a deployment descriptor it’s also possible to use the WLS Console –> Deployments –> <Your Application> –> Configuration –> Instrumentation tab to add monitors from the instrumentation library with the Console user interface.  Under the covers the console will use a deployment plan behind the visual tooling and relieves you of the burden of creating a deployment descriptor.

I recently recorded several short screencasts illustrating various approaches to find out where time is being spent as client requests flow through WebLogic Server.  WebLogic Server has a very...

WLS

Record and Play your WebLogic Console Tasks Like a DVR

Automation using WebLogic Scripting Tool Today on the Oracle internal mailing list for WebLogic Server questions someone asked how to automate the configuration of the thread model for WebLogic Server and they were having trouble with the jython scripting syntax.  I’ve previously written about this feature called Work Managers and the associated constraints.  However, I did not show how to automate the process of configuring this without the console using WebLogic Scripting Tool – the jython scripting automation environment abbreviated as WLST.  I’ve written some very basic introductions to WLST before and there is also an Oracle By Example on the subject, but this is a bit more advanced.  Fear not because there is a really easy-to-use feature of the WLS console that lets you “Record” user actions just like a DVR.  Using these recordings of the web-based console, you can easily create a script even if you are unfamiliar with the WLST syntax and API.  I’m a big fan of both DVR’s and automation as can be evidenced with this old Halloween picture taken during simpler times.  Obviously the Cast Away and The Big Labowski references show some age.  I was a big Tivo fan-boy back in the day and I still think it’s the best DVR. I strongly believe that WebLogic Scripting Tool (WLST) is an absolutely essential tool for automating administration tasks in anything beyond a development environment.  Even in development environments you can make a case that it makes sense to start the automation for environments downstream.  I promise you that once you start using it for any tasks that you do even semi-regularly, you won’t go back to clicking through the console.  It’s simply so much more efficient and less error-prone to run a script. Let’s say you need to create a Work Manager and MaxThreadsConstraint – the easy way to do it is configure it in the WLS console first while capturing the commands with a recording.  See the images for the simple steps – click to enlarge. Record Console Configurations to a File Review the Recordings and Make Slight Modifications In order to make the recorded .py file directly callable as a stand-alone script I added calls to the connect() and edit() functions at the beginning and calls to disconnect() and exit() at the end – otherwise the main section of the script was provided by the console recording.  Below is the resulting file I saved as d:/temp/wm.py connect('weblogic','welcome1', 't3://localhost:7001') edit() startEdit()   cd('/SelfTuning/wl_server') cmo.createMaxThreadsConstraint('MaxThreadsConstraint-0')   cd('/SelfTuning/wl_server/MaxThreadsConstraints/MaxThreadsConstraint-0') set('Targets',jarray.array([ObjectName('com.bea:Name=examplesServer,Type=Server')], ObjectName)) cmo.setCount(5) cmo.unSet('ConnectionPoolName')   cd('/SelfTuning/wl_server') cmo.createWorkManager('WorkManager-0') cd('/SelfTuning/wl_server/WorkManagers/WorkManager-0') set('Targets',jarray.array([ObjectName('com.bea:Name=examplesServer,Type=Server')], ObjectName))   cmo.setMaxThreadsConstraint(getMBean('/SelfTuning/wl_server/MaxThreadsConstraints/MaxThreadsConstraint-0')) cmo.setIgnoreStuckThreads(false)   activate() disconnect() exit()Run the ScriptIf you want to test it be sure to delete the Work Manager and MaxThreadConstraint that you had previously created in the console.  Do something like the following - set up the environment and tell WLST to execute the script which happens in the first 2 lines, the rest doesn’t require any user input:D:\Oracle\wls11g\wlserver_10.3\samples\domains\wl_server\bin>setDomainEnv.cmd D:\Oracle\wls11g\wlserver_10.3\samples\domains\wl_server>java weblogic.WLST d:\temp\wm.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 'examplesServer' that belongs to domain 'wl_server'.   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. 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: examplesServer     Exiting WebLogic Scripting Tool.  Now if you go back and look in the console the changes have been made and we now have a compete script.  Of course there is a full MBean reference and you can learn the nuances of jython and WLST, but why not let the WLS console do most of the work for you!  Happy scripting.

Automation using WebLogic Scripting Tool Today on the Oracle internal mailing list for WebLogic Server questions someone asked how to automate the configuration of the thread model for WebLogic Server...

Eclipse

Do Not Kill – Use JRockit JRCMD

One extremely valuable skill you should learn as someone who works with Java is to understand a thread dump.  One of my customers this week had a situation where their web application was acting up and we were able to see some misbehaving code very quickly by looking inside their application to see what each thread was doing.  It might be intimidating to you at first, but I can’t emphasize enough how much reading thread dumps will help your troubleshooting skills.  This post will illustrate a simple way to do this with the JRockit JVM.  In a subsequent post I’ll give some pointers that would work on other JVM’s and you can always refer to my previous post on JVM tools Now my first preference is to always use JRockit Mission Control, which is an Eclipse RCP based tool that ships with JRockit that tells you virtually everything that’s going on inside the JVM in a very easy-to-understand way.  But let’s say you are logged into a remote system that is running in production that doesn’t have graphics libraries and you need to be able to maneuver on the command line.  To get thread dumps quickly, cleanly and easily with JRockit it’s much easier to use the <JROCKIT_INSTALL>/bin/jrcmd command than kill –3 or Cntrl-Break.  This way output can be redirected to a file of your choosing without having to know a bunch of command line tricks.  There are so many other powerful commands that you can use from with JRCMD, but let’s start simple and I think you’ll appreciate how easy this is. From any shell on a machine where a JRockit JVM is running simply call JRCMD with no arguments.  The output is a list of every process id and command line of each Java command on this system. Copyright (c) 2009 Microsoft Corporation. All rights reserved.D:\>cd Oracle D:\Oracle>cd wls11g\jrockit_160_14_R27.6.5-32\bin D:\Oracle\wls11g\jrockit_160_14_R27.6.5-32\bin>jrcmd 3792 jrockit.tools.jrcmd.JrCmd 6016 com.pointbase.net.netServer /noconsole /port:9082 /d:3 /pointbase.ini=D:\Oracle\wls11g\USER_P~1\domains\MEDREC~1\pointbase.ini 4512 weblogic.Server If you want to see all the available commands for a particular process, simply add the process id and the “help” command as arguments:D:\Oracle\wls11g\jrockit_160_14_R27.6.5-32\bin>jrcmd 4512 help 4512: The following commands are available:  kill_rmp_server  start_rmp_server  kill_management_server  start_management_server  checkjrarecording  stopjrarecording  startjrarecording  print_object_summary  memleakserver  print_codegenlist  print_class_summary  run_optfile  dump_codelayout  dump_codelist  dump_codemap  print_utf8pool  print_properties  print_threads  datadump_request  runsystemgc  runfinalization  heap_diagnostics  oom_diagnostics  print_exceptions  version  timestamp  command_line  memprof  sanity  verbosity  set_filename  help  print_memusage Wow, there are a lot of commands available.  What if you do not know all the options for how to use a command?  For help with any specific command use 'help <command>'.  So here is how to see the help for the print_threads command:D:\Oracle\wls11g\jrockit_160_14_R27.6.5-32\bin>jrcmd 4512 help print_threads 4512: Print all threads with stacktraces.  nativestack - include native frames in the stacktrace (bool,  false)  javastack - print java stack frames (bool, true)  monitors - print lock information (bool, true)  jvmmonitors - include the jvm internal monitors (bool, false)  internal - print JRockit internal threads (bool, true)  concurrentlocks - print java.util.concurrent locks (bool, false)  compact - print all threads with the same stacktrace together  (will not print nativestack or monitors) (bool,  false) So let’s say the defaults are ok, we can now send the thread dump to a file easily by redirecting the output.  Often times more than 1 thread dump is useful, if they are several moments apart you can tell if a certain thread is “stuck” on a piece of code.D:\Oracle\wls11g\jrockit_160_14_R27.6.5-32\bin>jrcmd 4512 print_threads > d:\temp\threaddump1.txt D:\Oracle\wls11g\jrockit_160_14_R27.6.5-32\bin>jrcmd 4512 print_threads > d:\temp\threaddump2.txt Let’s take a look at threaddump1.txt.  You’ll see every thread in the JVM and the code stack it took to get to that point.4512: ===== FULL THREAD DUMP ===============Mon Feb 08 14:18:55 2010BEA JRockit(R) R27.6.5-32_o-121899-1.6.0_14-20091001-2107-windows-ia32 "Main Thread" id=1 idx=0x4 tid=7192 prio=5 alive, in native, waiting -- Waiting for notification on: weblogic/t3/srvr/T3Srvr@0x15127DF0[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at java/lang/Object.wait(Object.java:485) at weblogic/t3/srvr/T3Srvr.waitForDeath(T3Srvr.java:849) ^-- Lock released while waiting: weblogic/t3/srvr/T3Srvr@0x15127DF0[fat lock] at weblogic/t3/srvr/T3Srvr.run(T3Srvr.java:465) at weblogic/Server.main(Server.java:67) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "(Signal Handler)" id=2 idx=0x8 tid=7248 prio=5 alive, in native, daemon "(GC Main Thread)" id=3 idx=0xc tid=7900 prio=5 alive, in native, native_waiting, daemon "(GC Worker Thread 1)" id=? idx=0x10 tid=6548 prio=5 alive, in native, daemon "(GC Worker Thread 2)" id=? idx=0x14 tid=6344 prio=5 alive, in native, daemon "(Code Generation Thread 1)" id=4 idx=0x18 tid=3748 prio=5 alive, in native, native_waiting, daemon "(Code Optimization Thread 1)" id=5 idx=0x1c tid=4364 prio=5 alive, in native, native_waiting, daemon "(VM Periodic Task)" id=6 idx=0x20 tid=3024 prio=10 alive, in native, daemon "(Attach Listener)" id=7 idx=0x24 tid=7988 prio=5 alive, in native, daemon "Finalizer" id=8 idx=0x28 tid=5232 prio=8 alive, in native, native_waiting, daemon at jrockit/memory/Finalizer.waitForFinalizees([Ljava/lang/Object;)I(Native Method) at jrockit/memory/Finalizer.access$500(Finalizer.java:12) at jrockit/memory/Finalizer$4.run(Finalizer.java:159) at java/lang/Thread.run(Thread.java:619) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "Reference Handler" id=9 idx=0x2c tid=7412 prio=10 alive, in native, native_waiting, daemon at java/lang/ref/Reference.waitForActivatedQueue()Ljava/lang/ref/Reference;(Native Method) at java/lang/ref/Reference.access$100(Reference.java:11) at java/lang/ref/Reference$ReferenceHandler.run(Reference.java:79) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "(Sensor Event Thread)" id=10 idx=0x30 tid=7088 prio=5 alive, in native, daemon "Timer-0" id=13 idx=0x34 tid=4852 prio=5 alive, in native, waiting, daemon -- Waiting for notification on: java/util/TaskQueue@0x14DDC788[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at java/lang/Object.wait(Object.java:485) at java/util/TimerThread.mainLoop(Timer.java:483) ^-- Lock released while waiting: java/util/TaskQueue@0x14DDC788[fat lock] at java/util/TimerThread.run(Timer.java:462) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "Timer-1" id=14 idx=0x38 tid=8100 prio=5 alive, in native, waiting, daemon -- Waiting for notification on: java/util/TaskQueue@0x14DDCB40[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at java/util/TimerThread.mainLoop(Timer.java:509) ^-- Lock released while waiting: java/util/TaskQueue@0x14DDCB40[fat lock] at java/util/TimerThread.run(Timer.java:462) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "[ACTIVE] ExecuteThread: '0' for queue: 'weblogic.kernel.Default (self-tuning)'" id=15 idx=0x3c tid=924 prio=5 alive, in native, waiting, daemon -- Waiting for notification on: weblogic/work/ExecuteThread@0x14F4A3A0[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at java/lang/Object.wait(Object.java:485) at weblogic/work/ExecuteThread.waitForRequest(ExecuteThread.java:157) ^-- Lock released while waiting: weblogic/work/ExecuteThread@0x14F4A3A0[fat lock] at weblogic/work/ExecuteThread.run(ExecuteThread.java:178) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "weblogic.time.TimeEventGenerator" id=16 idx=0x40 tid=7480 prio=9 alive, in native, waiting, daemon -- Waiting for notification on: weblogic/time/common/internal/TimeTable@0x14E49080[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at weblogic/time/common/internal/TimeTable.snooze(TimeTable.java:286) ^-- Lock released while waiting: weblogic/time/common/internal/TimeTable@0x14E49080[fat lock] at weblogic/time/common/internal/TimeEventGenerator.run(TimeEventGenerator.java:117) at java/lang/Thread.run(Thread.java:619) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "JMAPI event thread" id=17 idx=0x44 tid=7080 prio=5 alive, in native, native_waiting, daemon "weblogic.timers.TimerThread" id=18 idx=0x48 tid=2812 prio=9 alive, in native, waiting, daemon -- Waiting for notification on: weblogic/timers/internal/TimerThread@0x150324B8[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at weblogic/timers/internal/TimerThread$Thread.run(TimerThread.java:267) ^-- Lock released while waiting: weblogic/timers/internal/TimerThread@0x150324B8[fat lock] at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "[STANDBY] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)'" id=19 idx=0x4c tid=7476 prio=5 alive, in native, waiting, daemon -- Waiting for notification on: weblogic/work/ExecuteThread@0x14F4A478[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at java/lang/Object.wait(Object.java:485) at weblogic/work/ExecuteThread.waitForRequest(ExecuteThread.java:157) ^-- Lock released while waiting: weblogic/work/ExecuteThread@0x14F4A478[fat lock] at weblogic/work/ExecuteThread.run(ExecuteThread.java:178) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "Thread-7" id=22 idx=0x50 tid=4816 prio=5 alive, in native, parked, daemon -- Parking to wait for: java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject@0x14DDD658 at jrockit/vm/Locks.park0(J)V(Native Method) at jrockit/vm/Locks.park(Locks.java:2517) at sun/misc/Unsafe.park(ZJ)V(Native Method) at java/util/concurrent/locks/LockSupport.park(LockSupport.java:158) at java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1925) at java/util/concurrent/LinkedBlockingQueue.take(LinkedBlockingQueue.java:358) at weblogic/utils/concurrent/JDK15ConcurrentBlockingQueue.take(JDK15ConcurrentBlockingQueue.java:89) at weblogic/store/internal/PersistentStoreImpl.getOutstandingWork(PersistentStoreImpl.java:567) at weblogic/store/internal/PersistentStoreImpl.run(PersistentStoreImpl.java:615) at weblogic/store/internal/PersistentStoreImpl$2.run(PersistentStoreImpl.java:383) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "ExecuteThread: '0' for queue: 'weblogic.socket.Muxer'" id=23 idx=0x54 tid=7536 prio=5 alive, in native, daemon at weblogic/socket/NTSocketMuxer.getIoCompletionResult(Lweblogic/socket/NTSocketMuxer$IoCompletionData;)Z(Native Method) at weblogic/socket/NTSocketMuxer.processSockets(NTSocketMuxer.java:81) at weblogic/socket/SocketReaderRequest.run(SocketReaderRequest.java:29) at weblogic/socket/SocketReaderRequest.execute(SocketReaderRequest.java:42) at weblogic/kernel/ExecuteThread.execute(ExecuteThread.java:145) at weblogic/kernel/ExecuteThread.run(ExecuteThread.java:117) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "ExecuteThread: '1' for queue: 'weblogic.socket.Muxer'" id=24 idx=0x58 tid=6252 prio=5 alive, in native, daemon at weblogic/socket/NTSocketMuxer.getIoCompletionResult(Lweblogic/socket/NTSocketMuxer$IoCompletionData;)Z(Native Method) at weblogic/socket/NTSocketMuxer.processSockets(NTSocketMuxer.java:81) at weblogic/socket/SocketReaderRequest.run(SocketReaderRequest.java:29) at weblogic/socket/SocketReaderRequest.execute(SocketReaderRequest.java:42) at weblogic/kernel/ExecuteThread.execute(ExecuteThread.java:145) at weblogic/kernel/ExecuteThread.run(ExecuteThread.java:117) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "ExecuteThread: '2' for queue: 'weblogic.socket.Muxer'" id=25 idx=0x5c tid=4064 prio=5 alive, in native, daemon at weblogic/socket/NTSocketMuxer.getIoCompletionResult(Lweblogic/socket/NTSocketMuxer$IoCompletionData;)Z(Native Method) at weblogic/socket/NTSocketMuxer.processSockets(NTSocketMuxer.java:81) at weblogic/socket/SocketReaderRequest.run(SocketReaderRequest.java:29) at weblogic/socket/SocketReaderRequest.execute(SocketReaderRequest.java:42) at weblogic/kernel/ExecuteThread.execute(ExecuteThread.java:145) at weblogic/kernel/ExecuteThread.run(ExecuteThread.java:117) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "VDE Transaction Processor Thread" id=28 idx=0x60 tid=4904 prio=2 alive, in native, waiting, daemon -- Waiting for notification on: com/octetstring/vde/backend/standard/TransactionProcessor@0x15036280[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at java/lang/Object.wait(Object.java:485) at com/octetstring/vde/backend/standard/TransactionProcessor.waitChange(TransactionProcessor.java:367) ^-- Lock released while waiting: com/octetstring/vde/backend/standard/TransactionProcessor@0x15036280[fat lock] at com/octetstring/vde/backend/standard/TransactionProcessor.run(TransactionProcessor.java:212) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "DoSManager" id=30 idx=0x68 tid=7072 prio=6 alive, in native, sleeping, native_waiting, daemon at java/lang/Thread.sleep(J)V(Native Method) at com/octetstring/vde/DoSManager.run(DoSManager.java:433) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "Thread-11" id=31 idx=0x6c tid=3288 prio=5 alive, in native, parked, daemon -- Parking to wait for: java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject@0x14DDD868 at jrockit/vm/Locks.park0(J)V(Native Method) at jrockit/vm/Locks.park(Locks.java:2517) at sun/misc/Unsafe.park(ZJ)V(Native Method) at java/util/concurrent/locks/LockSupport.park(LockSupport.java:158) at java/util/concurrent/locks/AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:1925) at java/util/concurrent/LinkedBlockingQueue.take(LinkedBlockingQueue.java:358) at weblogic/utils/concurrent/JDK15ConcurrentBlockingQueue.take(JDK15ConcurrentBlockingQueue.java:89) at weblogic/store/internal/PersistentStoreImpl.getOutstandingWork(PersistentStoreImpl.java:567) at weblogic/store/internal/PersistentStoreImpl.run(PersistentStoreImpl.java:615) at weblogic/store/internal/PersistentStoreImpl$2.run(PersistentStoreImpl.java:383) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "[STANDBY] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)'" id=32 idx=0x70 tid=7216 prio=5 alive, in native, waiting, daemon -- Waiting for notification on: weblogic/work/ExecuteThread@0x14F4A550[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at java/lang/Object.wait(Object.java:485) at weblogic/work/ExecuteThread.waitForRequest(ExecuteThread.java:157) ^-- Lock released while waiting: weblogic/work/ExecuteThread@0x14F4A550[fat lock] at weblogic/work/ExecuteThread.run(ExecuteThread.java:178) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "[STANDBY] ExecuteThread: '3' for queue: 'weblogic.kernel.Default (self-tuning)'" id=33 idx=0x74 tid=7764 prio=5 alive, in native, waiting, daemon -- Waiting for notification on: weblogic/work/ExecuteThread@0x0BAA3938[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at java/lang/Object.wait(Object.java:485) at weblogic/work/ExecuteThread.waitForRequest(ExecuteThread.java:157) ^-- Lock released while waiting: weblogic/work/ExecuteThread@0x0BAA3938[fat lock] at weblogic/work/ExecuteThread.run(ExecuteThread.java:178) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "[STANDBY] ExecuteThread: '4' for queue: 'weblogic.kernel.Default (self-tuning)'" id=45 idx=0xa4 tid=8104 prio=5 alive, in native, waiting, daemon -- Waiting for notification on: weblogic/work/ExecuteThread@0x089001E8[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at java/lang/Object.wait(Object.java:485) at weblogic/work/ExecuteThread.waitForRequest(ExecuteThread.java:157) ^-- Lock released while waiting: weblogic/work/ExecuteThread@0x089001E8[fat lock] at weblogic/work/ExecuteThread.run(ExecuteThread.java:178) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "DynamicListenThread[MedRec Local Network Channel]" id=46 idx=0xa8 tid=7452 prio=9 alive, in native, daemon at java/net/PlainSocketImpl.socketAccept(Ljava/net/SocketImpl;)V(Native Method) at java/net/PlainSocketImpl.accept(PlainSocketImpl.java:390) ^-- Holding lock: java/net/SocksSocketImpl@0x09374A98[biased lock] at java/net/ServerSocket.implAccept(ServerSocket.java:453) at java/net/ServerSocket.accept(ServerSocket.java:421) at weblogic/socket/WeblogicServerSocket.accept(WeblogicServerSocket.java:38) at weblogic/server/channels/DynamicListenThread$SocketAccepter.accept(DynamicListenThread.java:528) at weblogic/server/channels/DynamicListenThread$SocketAccepter.access$200(DynamicListenThread.java:420) at weblogic/server/channels/DynamicListenThread.run(DynamicListenThread.java:171) at java/lang/Thread.run(Thread.java:619) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "DynamicListenThread[Default]" id=47 idx=0xac tid=4092 prio=9 alive, in native, daemon at java/net/PlainSocketImpl.socketAccept(Ljava/net/SocketImpl;)V(Native Method) at java/net/PlainSocketImpl.accept(PlainSocketImpl.java:390) ^-- Holding lock: java/net/SocksSocketImpl@0x09380038[biased lock] at java/net/ServerSocket.implAccept(ServerSocket.java:453) at java/net/ServerSocket.accept(ServerSocket.java:421) at weblogic/socket/WeblogicServerSocket.accept(WeblogicServerSocket.java:38) at weblogic/server/channels/DynamicListenThread$SocketAccepter.accept(DynamicListenThread.java:528) at weblogic/server/channels/DynamicListenThread$SocketAccepter.access$200(DynamicListenThread.java:420) at weblogic/server/channels/DynamicListenThread.run(DynamicListenThread.java:171) at java/lang/Thread.run(Thread.java:619) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "DynamicSSLListenThread[DefaultSecure]" id=48 idx=0xb0 tid=6196 prio=9 alive, in native, daemon at java/net/PlainSocketImpl.socketAccept(Ljava/net/SocketImpl;)V(Native Method) at java/net/PlainSocketImpl.accept(PlainSocketImpl.java:390) ^-- Holding lock: java/net/SocksSocketImpl@0x093978B8[biased lock] at java/net/ServerSocket.implAccept(ServerSocket.java:453) at javax/net/ssl/impl/SSLServerSocketImpl.accept()Ljava/net/Socket;(Unknown Source) at weblogic/server/channels/DynamicListenThread$SocketAccepter.accept(DynamicListenThread.java:528) at weblogic/server/channels/DynamicListenThread$SocketAccepter.access$200(DynamicListenThread.java:420) at weblogic/server/channels/DynamicListenThread.run(DynamicListenThread.java:171) at java/lang/Thread.run(Thread.java:619) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "Java2D Disposer" id=49 idx=0xb4 tid=6356 prio=10 alive, in native, waiting, daemon -- Waiting for notification on: java/lang/ref/ReferenceQueue$Lock@0x09D79E60[fat lock] at jrockit/vm/Threads.waitForNotifySignal(JLjava/lang/Object;)Z(Native Method) at java/lang/Object.wait(J)V(Native Method) at java/lang/ref/ReferenceQueue.remove(ReferenceQueue.java:118) ^-- Lock released while waiting: java/lang/ref/ReferenceQueue$Lock@0x09D79E60[fat lock] at java/lang/ref/ReferenceQueue.remove(ReferenceQueue.java:134) at sun/java2d/Disposer.run(Disposer.java:125) at java/lang/Thread.run(Thread.java:619) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace "AWT-Windows" id=50 idx=0xbc tid=8000 prio=6 alive, in native, daemon at sun/awt/windows/WToolkit.eventLoop()V(Native Method) at sun/awt/windows/WToolkit.run(WToolkit.java:291) at java/lang/Thread.run(Thread.java:619) at jrockit/vm/RNI.c2java(IIIII)V(Native Method) -- end of trace ===== END OF THREAD DUMP ===============  The 2009 book Professional Oracle WebLogic Server has excellent information about how to read WLS thread dumps starting on page 686.  But for those of you that want Cliff Notes, STUCK threads are bad.  A thread that has the name STUCK in it’s name has been identified as not being returned to the thread pool for a configured amount of time, which defaults to 10 minutes.  In a subsequent post I’ll show you how to use JRockit Mission Control to look at threads which has some nice tooling for sorting through this detail.Also check out some other posts related to this:http://blogs.oracle.com/staffan/2008/08/useful_tool_jrcmd.htmlhttp://blogs.oracle.com/staffan/2008/08/more_jrcmd_tricks.htmlhttp://www.oracle.com/technology/pub/articles/dev2arch/2007/12/jrockit-tuning3.html

One extremely valuable skill you should learn as someone who works with Java is to understand a thread dump.  One of my customers this week had a situation where their web application was acting up...

WLS

Work Manager Leash for Slow JSPs in WebLogic Server

If part of your application goes bad, you do not want issues to cascade to the rest of your application or the rest of the server.  Based on my recent discovery of Michael Nygard’s architecture writings, this post will be somewhat applicable to his Bulkhead pattern (see page 39) of his excellent presentation.   I’ve been told that his ReleaseIt! book is phenomenal by peers I respect, so it’s already on it’s way to my bookshelf.  WebLogic has a way to put a leash on a JSP with only a few minor deployment descriptor edits – read on for an example on how to not let one resource intensive JSP bring you down. Actual Customer Problem One of my customers has an interesting problem with a long-running JSP.  They use a 3rd party java library exposed via a JSP that brings back large amounts of content from a backend file system.  This can take tens of minutes to process each request.  Within the same application (WAR file) they also have many short-lived requests hitting normal JSPs like a traditional web application.  In some cases they were having stability problems when too many threads were busy (STUCK threads) on the long-running JSP, taking up lots of server memory and starving threads from the fast JSPs.  In some cases, they would have to restart the WLS instance to recover stability.  The reason - by default the application components and even the rest of WebLogic Server are all using threads from the same default Work Manager – which is used by WebLogic Server’s self-tuning thread pool. Potential Solution Using Custom Work Manager and Constraint In 9.x and above of WebLogic, you have the ability to use a WorkManager with different types of constraints to control the shared threads in WebLogic Server.  Here is a detailed article on Work Managers on OTN. Work Managers can be used to put some constraints on a troublesome JSP such as the max number of threads and the max number of requests that are being serviced and queued (called a capacity constraint) simply by editing the web.xml and weblogic.xml deployment descriptors.  Requests over the capacity constraint will result in a 503 error code.  Using web.xml a special page can be shown in this case that provides a helpful message as to why this condition exists instead of the default 503 page and the application can stay up while limited access to the JSPs that hog server resources. Simple Example 2 JSPs - normal.jsp and veryslow.jsp - the veryslow.jsp has a 30 second java.lang.Thread.sleep() A simple Filter that applies to both JSPs that simply logs to standard out – This is included just to show that Filters are not affected by Work Managers – you don’t have to worry about a Russian Nested Doll issue to target a work manager successfully at a JSP, even if it has Filters. 503error.html page (for the informational message in the overload condition).  I included this to show you that this can be a custom pretty page and does not have to be the ugly Internal Server Error page that you see by default. weblogic.xml with a custom Work Manager defined in  with constraints: <?xml version="1.0" encoding="UTF-8"?> <wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"> <wls:weblogic-version>10.3.2</wls:weblogic-version> <wls:context-root>WorkManagerWeb</wls:context-root> <wls:work-manager> <wls:name>myCustomWorkManager</wls:name> <wls:max-threads-constraint> <wls:name>5MaxThreads</wls:name> <wls:count>5</wls:count> </wls:max-threads-constraint> <wls:capacity> <wls:name>7MaxCapacity</wls:name> <wls:count>7</wls:count> </wls:capacity> </wls:work-manager> </wls:weblogic-web-app>web.xml – this simply shows how you can target a custom Work Manager directly at a JSP/Servlet – It is probably more common to target a Work Manager at an entire web application – but we have a very targeted use case in this example.  In EJB modules, work managers are targeted per EJB or MDB.  The important part is looking at the init-param of the veryslow.jsp.  The 503 error code page is also defined here.<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>WorkManagerWeb</display-name> <welcome-file-list> <welcome-file>normal.jsp</welcome-file> </welcome-file-list> <error-page> <error-code>503</error-code> <location>/503error.html</location> </error-page> <filter> <display-name>BarFilter</display-name> <filter-name>BarFilter</filter-name> <filter-class>foo.BarFilter</filter-class> </filter> <filter-mapping> <filter-name>BarFilter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <servlet> <servlet-name>VerySlowJSP</servlet-name> <jsp-file>veryslow.jsp</jsp-file> <init-param> <param-name>wl-dispatch-policy</param-name> <param-value>myCustomWorkManager</param-value> </init-param> </servlet> </web-app>Here’s an illustration with a max thread constraint of 5 and a capacity constraint of 7 showing what will happen when 10 requests hit veryslow.jsp at the same time. Here is a JMeter report using 10 threads instantaneously hitting normal.jsp which uses the default Work Manager from WLS.  Notice that all finish executing right away which is exactly as we expect because there are no relevant constraints in the default Work Manager. Here is a JMeter report showing 10 requests instantaneously hitting veryslow.jsp which uses the custom Work Manager with the constraints discussed before.  In this case we see 3 rejected requests (the last 3 in), 5 that complete in 30 seconds, and 2 that complete in 60 seconds.  This is exactly what we expect given our constraints since 2 threads will wait not only for their 30 second sleep, but also for the 30 second sleep for the thread that they are waiting on. When you go to the browser and hit veryslow.jsp while the veryslow test is being run, you get the 503error.html page defined in web.xml to come up.Here’s the access.log from the test – notice the 503 codes:127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/normal.jsp HTTP/1.1" 200 304 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/normal.jsp HTTP/1.1" 200 304 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/normal.jsp HTTP/1.1" 200 304 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/normal.jsp HTTP/1.1" 200 304 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/normal.jsp HTTP/1.1" 200 304 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/normal.jsp HTTP/1.1" 200 304 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/normal.jsp HTTP/1.1" 200 304 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/normal.jsp HTTP/1.1" 200 304 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/veryslow.jsp HTTP/1.1" 503 348 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/normal.jsp HTTP/1.1" 200 304 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/veryslow.jsp HTTP/1.1" 503 348 127.0.0.1 - - [30/Dec/2009:11:35:32 -0600] "GET /WorkManagerWeb/normal.jsp HTTP/1.1" 200 304 127.0.0.1 - - [30/Dec/2009:11:35:32 -0600] "GET /WorkManagerWeb/veryslow.jsp HTTP/1.1" 503 348 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/veryslow.jsp HTTP/1.1" 200 396 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/veryslow.jsp HTTP/1.1" 200 396 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/veryslow.jsp HTTP/1.1" 200 396 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/veryslow.jsp HTTP/1.1" 200 396 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/veryslow.jsp HTTP/1.1" 200 396 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/veryslow.jsp HTTP/1.1" 200 396 127.0.0.1 - - [30/Dec/2009:11:35:31 -0600] "GET /WorkManagerWeb/veryslow.jsp HTTP/1.1" 200 396Here’s the Standard Out log – notice that both JSP’s use the Filter and it is not affected by using different work managers for JSPs.Dec 30, 2009 11:33:20 AM - BarFilter [ACTIVE] ExecuteThread: '14' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:20 AM - BarFilter [ACTIVE] ExecuteThread: '12' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:20 AM - BarFilter [ACTIVE] ExecuteThread: '10' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:20 AM - BarFilter [ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - BarFilter [ACTIVE] ExecuteThread: '8' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - BarFilter [ACTIVE] ExecuteThread: '24' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - BarFilter [ACTIVE] ExecuteThread: '11' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - Normal JSP hit [ACTIVE] ExecuteThread: '24' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - Normal JSP hit [ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - Normal JSP hit [ACTIVE] ExecuteThread: '8' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - Normal JSP hit [ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - Normal JSP hit [ACTIVE] ExecuteThread: '14' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - Normal JSP hit [ACTIVE] ExecuteThread: '11' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - Normal JSP hit [ACTIVE] ExecuteThread: '10' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - Normal JSP hit [ACTIVE] ExecuteThread: '12' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - BarFilter [ACTIVE] ExecuteThread: '12' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - BarFilter [ACTIVE] ExecuteThread: '10' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - BarFilter [ACTIVE] ExecuteThread: '11' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - BarFilter [ACTIVE] ExecuteThread: '14' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - BarFilter [ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - BarFilter [ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - Normal JSP hit [ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - BarFilter [ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - Normal JSP hit [ACTIVE] ExecuteThread: '2' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - VerySlow JSP Starting to sleep [ACTIVE] ExecuteThread: '10' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - VerySlow JSP Starting to sleep [ACTIVE] ExecuteThread: '14' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - VerySlow JSP Starting to sleep [ACTIVE] ExecuteThread: '11' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - VerySlow JSP Starting to sleep [ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:21 AM - VerySlow JSP Starting to sleep [ACTIVE] ExecuteThread: '12' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:51 AM - VerySlow JSP awake [ACTIVE] ExecuteThread: '1' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:51 AM - VerySlow JSP awake [ACTIVE] ExecuteThread: '11' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:52 AM - VerySlow JSP awake [ACTIVE] ExecuteThread: '12' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:52 AM - BarFilter [ACTIVE] ExecuteThread: '11' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:52 AM - BarFilter [ACTIVE] ExecuteThread: '12' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:52 AM - VerySlow JSP awake [ACTIVE] ExecuteThread: '10' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:52 AM - VerySlow JSP awake [ACTIVE] ExecuteThread: '14' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:52 AM - VerySlow JSP Starting to sleep [ACTIVE] ExecuteThread: '12' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:33:52 AM - VerySlow JSP Starting to sleep [ACTIVE] ExecuteThread: '11' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:34:22 AM - VerySlow JSP awake [ACTIVE] ExecuteThread: '11' for queue: 'weblogic.kernel.Default (self-tuning)' Dec 30, 2009 11:34:22 AM - VerySlow JSP awake [ACTIVE] ExecuteThread: '12' for queue: 'weblogic.kernel.Default (self-tuning)'I’ve attached the code for this example that includes both the war file and my Oracle Enterprise Pack for Eclipse project.As you can see, it’s pretty easy to put constraints on individual JSPs, Servlets, EJB’s, MDB’s, and entire web applications using only a few deployment descriptor edits.  That’s a very powerful feature when you need it to keep hogs from bogging down other parts of your application or your WLS instance.

If part of your application goes bad, you do not want issues to cascade to the rest of your application or the rest of the server.  Based on my recent discovery of Michael Nygard’s architecture writing...

WebLogic NodeManager Quick Start

*Update 1/10/2010* I realized after my post that I forgot a few things.  1) You should always have a catchy image at the top of a blog post to add some visual context to your post (see TechCrunch for a blog that almost always follows this).  So I’ve added a NodeManager architecture diagram.  2) My colleague Phil Aston (co-author of the book I recommend below) pointed out a much simpler way of configuring the classpath to use StartScriptEnabled=true in nodemanager.properties which I refer to below. One of my customers is new to WebLogic and asked if I could instruct them how to automatically start their WebLogic Server instances when the OS is booted.  Node Manager can be used for that and more.  I put together a quick start guide that might help you get started quickly if you’re new to Node Manager like I was earlier today.  I’ve translated most of that documentation into a quick blog post.  I’ve definitely cut some corners (using demo certs, default path to the domain dir and node manager dir, etc).  If you want to get a feel for Node Manager quickly taking those grains of salt, read-on.  There is no included service for *nix systems, you’ll have to create an xinetd service one yourself and there are examples of that in the documentation and in the book referenced below. Introduction This is a short guide to getting started with WebLogic Server Node Manager, the process agent used to start and stop WebLogic Server instances. This is not a substitute for the complete documentation, but merely intended to get up and running quickly. Upon completiion of these steps, WebLogic Server processes should be automatically managed by Node Manager. When an OS instance is rebooted, WebLogic Server should return to the state it was in prior to the reboot (either started or stopped). Official documentation: http://download.oracle.com/docs/cd/E12839_01/web.1111/e13740/nodemgr_config.htm Professional Oracle WebLogic Server book with real-world advice and best practices for Node Manager starting on page 560: http://www.amazon.com/Professional-Oracle-WebLogic-Server-Programmer/dp/0470484306 The book is highly recommended as I mentioned I cut some corners here for simplicity. Starting Point The assumption is that the WebLogic Server installation has been done and that the Node Manager Windows Service was installed as a part of the installation. Any paths reflected below should be updated to reflect your directory structures. In fact, it probably would not be a bad idea to find/replace some of the following with the relevant strings: WebLogic Server installation path: D:\Oracle\wls11g Hostname: jbayer-us Domain path: D:\Oracle\wls11g\user_projects\domains\my_domain Uninstall / Reinstall NodeManager Service This needs to be done if you installed Node Manager with the standard installer because by default Node Manager binds to localhost. So as more OS instances are added, it will be required to have Node Manager instances on the network communicate to each other. This can only happen if Node Manager binds to an network interface that is available remotely. open cmd prompt run D:\Oracle\wls11g\wlserver_10.3\server\bin\setWLSEnv.cmd run D:\Oracle\wls11g\wlserver_10.3\server\bin\uninstallNodeMgrSvc.cmd Make backup copy of installNodeMgrSvc.cmd edit installNodeMgrSvc.cmd to bind to hostname for remote starts set NODEMGR_HOST=jbayer-us run D:\Oracle\wls11g\wlserver_10.3\server\bin\installNodeMgrSvc.cmd start the service – mine is called “Oracle WebLogic NodeManager…” but on older versions it’s likely will start with “BEA …” starting the NodeManager process should create the nodemanager.properties file we will edit next CrashRecovery and StartupScriptEnabled (updated 01/10/2010) We want to Enable NodeManager to restore servers to their last known state after a reboot. Open nodemanager.properties from the directory D:\Oracle\wls11g\wlserver_10.3\common\nodemanager\ Change the CrashRecoveryEnabled property from false to true: CrashRecoveryEnabled=true Also, because the domain’s \bin\startWebLogic script already has classpath configured, which is especially helpful for use with SmartUpdate that manages WebLogic patches as those classpath’s are not trivial to understand, I strongly recommend setting StartupScriptEnabled=true StartScriptEnabled=true in nodemanager.properties (Thanks to Ray T for the typo fix 6/29/10) stop/start node manager after making changes to nodemanager.properties Set up the Machines Go to the domain's AdminServer console http://localhost:7001/console If you need to start it, run <your_domain_dir>\bin\startWebLogic.cmd With the console navigate to <domain_name> -> Environment -> Machines Create a new machine – I named mine after the hostname of the server - jbayer-us If you have more than one OS instance, create one machine for each. In console go to <domain_name> -> Environment -> Servers Create a new server, example: managedServer1 Put in the listen address to the hostname you want to bind to, in my case jbayer-us Change the port to 8001or another available port so as not to conflict with the 7001 port of the AdminServer Assign managedServer1 it to the jbayer-us machine you just created - <domain_name> -> Enviornment -> Servers -> managedServer1 There should be a dropdown you can use to select the machine Click the save button on this settings page (don't forget this step) Now activate changes if required We need to assign the machine for the AdminServer, this cannot be done while the AdminServer is running. Stop AdminServer Open the domain config, example - D:\Oracle\wls11g\user_projects\domains\my_domain\config\config.xml Find the element used to assign the machine for managedServer1 <machine>jbayer-us</machine> Copy that and paste that element right after the AdminServer <name/> element If it is not already set, also specify the AdminServer listen address to be the hostname to bind to, by default it is blank which means bind to all network interfaces. After these changes my config.xml snippet for the AdminServer looks like this: <server><name>AdminServer</name><machine>jbayer-us</machine><listen-address>jbayer-us</listen-address></server>.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }Start the AdminServer again with the domain directory’s bin\startWebLogic.cmd Check the console page <domain_name> -> Environment -> Servers to see that the servers are defined correctly as expected Enroll the domain with Node Manager (updated 01/10/2010)  Navigate with a command prompt go to the domain directory run bin\setDomainEnv.cmd run java weblogic.WLST connect to the AdminServer with your credentials: connect('weblogic','welcome1','t3://jbayer-us:7001') Make sure you use forward slashes instead of backslashes in Windows: nmEnroll(domainDir='D:/Oracle/wls11g/user_projects/domains/my_domain',nmHome='D:/Oracle/wls11g/wlserver_10.3/common/nodemanager') Now go back to the web console - http://localhost:7001, for each server in the environment, go to the server start tab and put in the appropriate values. If you are using StartScriptEnabled=true in nodemanager.properties, then the classpath and jvm arguments from the script will be used first and the values you specify on the Server Startup tab will get added to the end, so you only need to enter values that are unique to each server in the classpath and arguments section. If you’re using Sun JDK instead of JRockit, then use –Xrs instead of –Xnohup refer to the official docs for more on this, but it has to do with handling OS signals properly. 7-2-10 update: Reader Ray T writes in with another tip:  “After some testing: starting, stopping servers, killing processes, rebooting etc after the configuration, I also found that I could not get the managed servers to shutdown cleanly - or at least the console would not recognize that they had. This had the added side effect of then not letting me start/restart a managed server via the console. I found that also adding StopScriptEnabled=true solved that final problem.”Click the image to enlarge – actual text values below:Java HomeD:\Oracle\wls11g\jrockit_160_14_R27.6.5-32Java VendorOracleBEA HomeD:\Oracle\wls11gRoot DirectoryD:\Oracle\wls11g\user_projects\domains\my_domainClasspath is empty as the script values are sufficientArguments-XnohupSecurity Policy FileD:\Oracle\wls11g\wlserver_10.3\server\lib\weblogic.policyUser NameweblogicPasswordwelcome1Confirm Passwordwelcome1Save Now do the same thing for each managed server. Activate the changes if required Node Manager Domain Username and PasswordSet the Node Manager username/password for the domain in the console Click <domain_name> in the console navigator Select Security tab Expand to the "Advanced" options about half-way down the page Choose a Node Manager username/password and put it in the username/password/confirm boxes your credentials, these could be unique from your user used to start the AdminServer, but I chose to keep mine the same weblogic/welcome1.  If you change this user name and password, then you’ll need to specify both when using the command nmConnect().  Thanks Ray T for the catch - 6/29/10. Decrease Log Verbosity For Standard Out In console, go to each server's Logging -> General page Expand to the Advanced section half-way down the page Change the standard out notice level to "Critical" This log file that captures Standard Out does not roll over while a server is running, so it's really important to make sure this file doesn't get too large. Note that this is not the server log file, this is only standard out.  Have NodeManager Start and Stop the ServersIf it is running, shutdown the AdminServer Start the AdminServer with NodeManager Go to domain dir run bin\setDomainEnv.cmd run java weblogic.WLST nmConnect(domainName='my_domain')  nmConnect(domainName=’my_domain’, username=’weblogic’, password=’welcome1’)  6/29/10 Updated thanks to Ray T who noticed that if you change the domain’s Node Manager user and password in the section above called “Node Manager Username and Password” that you’ll need to specify those values here otherwise the defaults of weblogic/welcome1 are used, which worked in my case, but not for others. nmStart('AdminServer') Go to console -> Environment -> Servers control tab and start the managed server from the console. It will send a command to Node Manager which actually performs the operation on the console's behalf. Gotcha! – If you have never started the managed server ever before and you try to start it from Node Manager, you might get an error.  In the server log it mjght say something like: Booting as admin server, but servername, managedServer1, does not match the admin server name, AdminServer  To get around this, simply start the Managed Server for the first time using either the Admin Console Servers->Control tab or the startManagedWebLogic.cmd script.  Subsequent nmStart commands should not have this issue any longer. Test Killing and RestartingIf the servers are started successfully by Node Manager, try and kill a process from task manager and see if it restarts.Looking at the Node Manager directory in the domain for each Managed Server, you will be able to see the state - below is a screenshot of managedServer1's files. The PID and .state files should tell you what you need to know to see if the server recovered.  If it did not, the .out file in the server log directory should hopefully give you a clue why. If manual killing of the process restarts a Server then you are ready to test an operating system reboot. Reboot the machine without stopping the WebLogic Servers. Each server should be restored to the state that it was in when the OS was rebooted.If you have questions, post them in the WLS General OTN forum as I’m not an expert on Node Manager – just someone who wanted have a quick start guide.  Cheers, James

*Update 1/10/2010* I realized after my post that I forgot a few things.  1) You should always have a catchy image at the top of a blog post to add some visual context to your post (see TechCrunch for a...

WLS

Open the Black Box - Oracle JRockit, Sun Hotspot and IBM J9 JVM Tools

Are you aware of the different tools available in the JVM you use to help troubleshoot and look under the hood?  Over the past couple of weeks several of my customers have been involved in several WebLogic support escalations with different JVM vendors.  It was an opportunity for me to learn a about the different tools – some unique to each JVM - and I want to document what I’ve found thus far.  I am by no means an expert in this area, but based on what I’ve seen there is not a high-level of awareness about the tools freely available.  I think you’ll find that there is a lot of innovation in JRockit Mission Control, and VisualVM is also a promising tool that you should get familiar with.  *Updated 12/31/2009* Brian Peacock from IBM’s JVM team pointed me towards IBM’s JDK’s newer tools that look to all be available as plug-ins from the IBM Support Assistant and I was not aware of all of them during my original post.  Especially if you’re using the IBM JVM, make sure you’re aware of these powerful tools as they look to represent a big improvement over the older IBM JDK tools. I purposely am not covering 3rd party commercial products as I am not familiar with them and the list is long. *Updated 1/12/2010* Check out this nice OTN article covering both VisualVM and JRockit in more detail with screenhots. http://www.oracle.com/technology/pub/articles/heimburger-tuning.html Dip Your Toe In The Water With JConsole or VisualVM Sun has a detailed article about common symptoms and JVM tools to use for each, which I highly recommend.  But if the JVM is mostly a black-box to you, then trying to analyze some of the low-level detail that comes out of the JVM tools can be very intimidating at first and you can start by keeping it simple.  Two important questions to ask for JVM health are: 1) Is the JVM on a sustainable path? 2) What is the JVM doing? The easiest way to get a quick answer to these questions that works across all JVM vendors and modern releases is JConsole because it ships with the JDK, so you know it’s there without a separate download.  The JDK documentation shows you how to use it on either a local or remote JVM.  Starting with JDK 1.6 update 7 there is a better tool called visualvm that ships with the JDK, but it can also be downloaded and used (with JDK 1.6) to monitor 1.4.2 and later JDKs.  I’m going to show visualvm because it’s simply newer and better. VisualVM Monitor Tab This snapshot is a stable and sustainable JVM (WebLogic Server on a JRockitJDK) where trend lines are relatively flat.  The memory utilization is low and returns to normal levels after each Garbage Collection.  The threads are not constantly increasing, and the CPU utilization is very low.  If you saw either the memory or threads going up constantly or saw extremely high CPU utilization, it would be worth investigating further.  Trend lines that slope up and to the right are signs of an upcoming problem. Visual VM Threads Tab The Threads tab shows a color coded timeline for all the threads by state and also has sub-tabs with views to sort by table columns and show extra detail.  You can also generate a full thread dump from this tab, which will open the current execution stack for each thread in the JVM in a new tab.  This reminds me a lot of the Mission Control Latency Analyzer. More on WebLogic Threads Support often asks for several thread dumps taken at 10-15 second intervals when Service Requests are filed.  By looking at the current point of execution of each thread over a period of time, you can identify whether some threads are stuck on something that should be fast, identify resource contention, etc. If you’re using WebLogic Server, you do not necessarily have to worry about how each JVM has different ways to create a thread dump and potentially even different output formats.  Simply use the WLST threadDump() command regardless of which JVM or platform you are on and it should work the same to produce text output.  Max actually has a good example of how to do this on a periodic basis. The 2009 book Professional Oracle WebLogic Server has excellent information about how to read WLS thread dumps starting on page 686.  But for those of you that want Cliff Notes, STUCK threads are bad.  A thread that has the name STUCK in it’s name has been identified as not being returned to the thread pool for a configured amount of time, which defaults to 10 minutes. Digging Deeper with Specialized JDK Tools Thread Dump Analysis If you want to use the JVM tools that help decipher thread dumps, then you may need another technique as the format of the thread dump varies depending on the vendor.  These can help you find lock contention, bogged down resources, and other nasty problems. Oracle JRockit – There is not a dedicated tool for Thread Dumps in JRockit as the format is human readable.  The JRockit documentation has a section describing thread dump analysis.  JRockit Mission Control also has some thread analysis both the live Console tool and the JRockit Runtime Analyzer recordings files.  For an entire mapping of Sun JDK tools to JRockit tools, look at this page in the docs. Sun Hotspot – the jdk\bin\jstack command produces output suitable for Thread Dump Analyzer, a project on java.net that has many useful features for analyzing multiple thread dumps. IBM J9 – The IBM JDK does not use a human readable format for it’s core files, so it’s especially important to know about the IBM Thread and Monitor Dump Analyzer for Java hosted on AlphaWorks.  The author published an article in JDJ covering how it works.  It’s a nice tool. Heap Analysis Oracle JRockit Mission Control has both the Memory Leak Detector and the JRockit Runtime Analyzer that excellent and easy to use visual tools.  On the command line, JRCMD also has a heap_diagnostics command that produces a human readable text file.  Paul Done has written about it recently. Sun Hotspot – At the lowest level, there is a JVM tool called Java Heap Analysis Tool or jhat that ships with the JDK.  Additionally VisualVM also includes heap dump analysis features.  Eclipse Memory Analysis Tool (MAT) also supports both Sun and IBM JVM binary heaps as has a really nice report for finding Leak Suspects that doesn’t require advanced JVM knowledge to use. IBM J9 – There are several tools available including the IBM Support Assistant (ISA) Plugins, the original is the Memory Dump Diagnostic for Java.  There are several beta plugins for ISA that offer more functionality.  Eclipse MAT now supports the IBM JDK also.  The oldest tool to my knowledge is the AlphaWorks project Heap Analyzer. Garbage Collection Analysis GCViewer claims some support for all 3 of the vendors verbose logging formats.  It is not clear whether all new JDK releases are forward compatible. Oracle JRockit – Instead of the Sun -verbose:gc option, JRockit has an -Xverbose:memory command.  Additionally, the JRockit Runtime Analyzer files have detailed GC information presented in an easy to understand way. Sun Hotspot - -verbose:gc on the command line and a visual tool named appropriately visualgc. IBM J9 – AlphaWorks has a tool called IBM Pattern Modeling and Analysis Tool for Java Garbage Collector that parses the IBM JDK verbose gc output and makes very nice graphs. Summary Overall I really like JRockit Mission Control and use it most often.  It ships with the JRockit JDK so there is no separate download.  It integrates with Eclipse (including OEPE) and links me directly to the line of code in JDT.  It has a helpful network auto discovery protocol built-in that don’t require me to install remote daemons on other machines to find remote JVMs.  Perhaps most importantly to me, I have the most experience with it, find it the easiest to use and most consolidated.  Truthfully, I haven’t given VisualVM enough screen-time yet for a fair comparison and there is an Eclipse launcher for it that I have yet to try.  I also have to give IBM credit for really having a nice vision with the IBM Support Assistant even though I don’t think it’s capabilities or user experience quite match what Oracle and Sun have yet strictly from a JDK tooling perspective.  I’m also not sure it will ever be shipped with the IBM JDK.  IBM ISA is intended for a broader-than-java product support perspective and has a larger scope than just the JDK.  If you have any other JDK vendor tools that I should have covered but omitted please let me know.

Are you aware of the different tools available in the JVM you use to help troubleshoot and look under the hood?  Over the past couple of weeks several of my customers have been involved in several...

WebLogic Server Shared Libraries – Including Jars

In my last post about including static resources in shared libraries, I had a follow-up question about how to include multiple jar files in a library.  I alluded to it in my post, but here is a concrete example that should make it more clear. Suppose I have 2 jars, that need to be deployed together, and I want to do that in a single shared library that my new web application will reference. Foo.java – packaged in foo.jar 1: package com.oracle.otn.samples.wls; 2:   3: public class Foo 4: { 5: public String toString() 6: { 7: return "Foo"; 8: } 9: }.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }Bar.java – packaged in bar.jar – notice that Bar extends Foo, so unless both jars are available at runtime, we should expect to see an error. 1: package com.oracle.otn.samples.wls; 2:   3: public class Bar extends Foo { 4: 5: public String toString() 6: { 7: return super.toString() + "Bar"; 8: } 9: }.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }To build a shared library for these, I simply construct a new packaging structure for this library that includes both foo.jar and bar.jar in the WEB-INF/lib of my shared library.  Of course I also need to configure a MANIFEST.MF.Here is the file structure of my shared library I call manyjars.war.  The jars is in this library’s WEB-INF/lib directory will be added to the WEB-INF/lib of any application that references this library when the application is initialized. 1: d:\temp>jar -tf manyjars.war 2: META-INF/ 3: META-INF/MANIFEST.MF 4: WEB-INF/ 5: WEB-INF/lib/ 6: WEB-INF/lib/bar.jar 7: WEB-INF/lib/foo.jar.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }Here is the MANIFEST.MF file: 1: Manifest-Version: 1.0 2: Specification-Title: ManyJars 3: Specification-Version: 1.0 4: Implementation-Title: ManyJars Implementation 5: Implementation-Version: 1.0 6: Implementation-Vendor: Oracle 7: Extension-Name: ManyJars.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }I can now deploy this shared library to WebLogic Server (or Oracle Enterprise Pack for Eclipse – OEPE - will do it for you if you configure the library there and refer to it in your application).  Here is how it looks in the console once it’s deployed. In my new web application, I refer to the library in my weblogic.xml – again OEPE for insert this reference for you if you use the tooling: 1: <?xml version="1.0" encoding="UTF-8"?> 2: <wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"> 3: <wls:weblogic-version>10.3.2</wls:weblogic-version> 4: <wls:context-root>FooBarWeb</wls:context-root> 5: <wls:library-ref> 6: <wls:library-name>ManyJars</wls:library-name> 7: <wls:specification-version>1.0</wls:specification-version> 8: <wls:exact-match>true</wls:exact-match> 9: </wls:library-ref> 10: </wls:weblogic-web-app>.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }So now if I have a simple index.jsp that refers to the Bar class we showed earlier, it should all work: If I wanted to include these jars at the EAR level, the procedure would be similar, except that I would create an ear-based shared library packaging and instead of WEB-INF/lib, I would place the jars in APP-INF/lib.  Instead of referring to the shared library in weblogic.xml, I would use weblogic-application.xml.You can download my files here if you want to try this.  Good luck.

In my last post about including static resources in shared libraries, I had a follow-up question about how to include multiple jar files in a library.  I alluded to it in my post, but here is a...

Eclipse

WebLogic Server Shared Libraries For Static Resources

In the OTN WLS General forum someone asked a question regarding using Shared Libraries to share static web resources among applications.  “Basically, we are trying to load jquery, css files, shared images, and what not into a shared library for access from other Web Applications.”  Shared libraries will handle this use case well.  I’ve put together a basic example using a simple image that is put into a shared library that is referenced by another web application.  The image in the screen shot below is from a shared library.  The web application that references it simply contains the JSP and a reference to the shared library in the weblogic.xml deployment descriptor. Basic Steps Assemble the resources (images, css, etc) in a base directory, with subdirectories if desired In the main directory, create a META-INF/MANIFEST.MF file describing the library Package the base directory as a WAR file Deploy the WAR as a library to WLS Refer to the Shared Library in a web application’s WEB-INF/weblogic.xml Refer to the static resources from the library in the web application as if they are local to your application Here is the link to the full documentation that describes all of the options for Shared Libraries in WebLogic. Simple Example I recommend taking a look at the shared libraries that ship with WebLogic Server to use as an example.  In WLS 10.3.x they are located here: <MIDDLEWARE_HOME>\wlserver_10.3\common\deployable-libraries Here is what my META-INF/MANIFEST.MF file looks like for my example, I simply copied an existing MANFIEST.MF from jsf-1.2.war and made edits: Manifest-Version: 1.0Specification-Title: ImagesSpecification-Version: 1.0Implementation-Title: Images ImplementationImplementation-Version: 1.0Implementation-Vendor: OracleExtension-Name: imagesHere is what the packaging of the library looks like after zipping it up as a WAR file:C:\temp\images>jar -tf images.warMETA-INF/META-INF/MANIFEST.MForalogo_small.gifAs you can see, it’s only a simple WAR file with an oracle image in the base directory with a META-INF/MANIFEST.MF file describing the library.  To deploy this to the WLS, you can do that as normal other than noting that it is a library.  After doing that it will show up like this in the console: If you’re using Oracle Enterprise Pack for Eclipse and set your Windows->Preferences->Server->Runtime Environments correctly, then the existing shared libraries should be available in Preferences->WebLogic->Shared Libraries and you can add the library you just created to the list.  This will allow you to edit the WEB-INF/weblogic.xml in the IDE with a dialog box, correctly specify the reference to the shared library, and deploy the shared library for you to the server if it has not been done already when you deploy the application.weblogic.xml<?xml version="1.0" encoding="UTF-8"?><wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"> <wls:weblogic-version>10.3.2</wls:weblogic-version> <wls:context-root>ImagesWeb</wls:context-root> <wls:library-ref> <wls:library-name>images</wls:library-name> <wls:specification-version>1.0</wls:specification-version> <wls:exact-match>true</wls:exact-match> </wls:library-ref></wls:weblogic-web-app>Now in the index.jsp, I can simply refer to the image as if it were in my base directory of the application like this:<img src=""

In the OTN WLS General forum someone asked a question regarding using Shared Libraries to share static web resources among applications.  “Basically, we are trying to load jquery, css files, shared...

Coherence

Synchronizing Coherence Clusters – A Tour of Push Replication

Lately I've been able to do some Coherence work with some local customers and play with the Coherence Incubator projects.  This entry will showcase one of the examples for Push Replication for sharing data among separate Coherence clusters. Inter-cluster Data Replication Coherence clustering technology makes a lot of sense for customers to be able to scale applications horizontally and reliably with very fast predictable performance.  This is of course easy to do within one data center on a fast network.  One of the common challenges that customers have is around High Availability and Disaster Recovery and keeping data synchronized across data centers.  Normally Coherence is optimized to use UDP unicast or multicast, but what happens if the network is unreliable and/or has high latency which is common when networking multiple data centers?  The answer is Coherence TCP Extend, which addresses these challenges by using TCP and the result is that multiple Coherence clusters can communicate together. Multiple data centers are not the only reason you need to keep multiple clusters in sync.  I recently came across a use case where it made sense to have separate Coherence clusters on different physical machines.  The JVM processes for each machine have a single digit millisecond SLA for round trip time per request, so they are very sensitive to any outside events and it was a requirement to isolate the processes as much as possible.  In this scenario one physical machine was Active and one was Passive for fail-over.  During load-testing on the Active machine we found that bringing up cluster members on the Passive machine in the middle of the test impacted performance when both machines were part of the same cluster.  Using a single Coherence cluster per machine ensures that the impact of cluster membership events are isolated to that machine only. Leveraging the Coherence Incubator Push Replication pattern, multiple Coherence clusters can keep data in sync whether they are on the same network subnet with low-latency or hundreds of miles apart in separate data centers.  Let's take a look at the simplest example, which is Active - Passive scenario.  In this situation we'll use Push Replication to make sure that Cache Entry operations (insert/update/delete) in the Active cache are replicated in the Passive cache. Run the Example To run this example called ActivePassiveExample - which is included in the src distribution of the Push Replication Pattern, I used the following software: Coherence 3.5.2 for Java, Coherence Common 1.4.0 Command Pattern 2.4.0 Messaging Pattern 2.4.0 Push Replication Pattern 2.4.0 Apache Ant 1.7.1 JMX RI 1.2.1 - this is optional, simply do not issue the "-http" on either of the jmx ant targets which will prevent the JMX HTTP Adapter from binding My build.xml and other example code The Ant Approach One of my colleagues Randy Stafford introduced me using an ant build.xml file to organize different types of Coherence cluster processes.  I found it to be a much simpler and cleaner approach than what I had been doing (multiple shell scripts or multiple Eclipse launch configurations).  This way it is simple to centralize the shared configuration to a set of properties that are used by all of the ant targets and each process can easily override one of the properties with a -DpropertyName=propertyValue at the command line.  Take a look at the build.xml file and let me know what you think. Step by Step Set the build.properties paths according to your environment Set up shells with ANT_HOME and JAVA_HOME and the PATH, setAntEnv.txt is an example Run ant from those shells with the appropriate targets as described in build.xml.  Minimum for this example: ant compile (you can reuse this shell) ant run_active_cache_server ant run_passive_cache_server ant run_active_publisher Most likely you will also want to run the JMX and Console processes to see the values. ant run_active_jmx ant run_passive_jmx ant run_passive_console Guided Tour Once the JMX processes are running for Active and Passive, you can use jconsole to locally bind to the two MBeanConnector process. To verify that the passive cache received all the updates you can execute the run_passive_console target and execute two commands to see the contents. cache passive-cache list Notice that at the bottom of my output that the entry values are the last ten number leading up to 10000, which is what we expect looking at the sample publishing code. [java] ClusterService{Name=Cluster, State=(SERVICE_STARTED, STATE_JOINED), Id=0, Version=3.5, OldestMemberId=1} [java] InvocationService{Name=Management, State=(SERVICE_STARTED), Id=1, Version=3.1, OldestMemberId=1} [java] )cache passive-cache [java] 2009-10-22 17:07:31.797/10.344 Oracle Coherence GE 3.5.1/461p2 <Info> (thread=Main Thread, member=3): Loaded cache configuration from "jar:file:/C:/Oracle/coherence-v3.5.1b461/coherence/lib/coherence.jar!/coherence-cache-config.xml" [java] 2009-10-22 17:07:32.156/10.703 Oracle Coherence GE 3.5.1/461p2 <D5> (thread=DistributedCache, member=3): Service DistributedCache joined the cluster with senior service member 1 [java] 2009-10-22 17:07:32.172/10.719 Oracle Coherence GE 3.5.1/461p2 <D5> (thread=DistributedCache, member=3): Service DistributedCache: received ServiceConfigSync containing 259 entries [java] <distributed-scheme> [java] <scheme-name>example-distributed</scheme-name> [java] <service-name>DistributedCache</service-name> [java] <backing-map-scheme> [java] <local-scheme> [java] <scheme-ref>example-binary-backing-map</scheme-ref> [java] </local-scheme> [java] </backing-map-scheme> [java] <autostart>true</autostart> [java] </distributed-scheme> [java] Map (?):list [java] 2 = 9992 [java] 3 = 9993 [java] 1 = 9991 [java] 0 = 10000 [java] 5 = 9995 [java] 4 = 9994 [java] 6 = 9996 [java] 8 = 9998 [java] 9 = 9999 [java] 7 = 9997 [java] Map (passive-cache):Let's look at the Active cluster processes.  You can see that there are caches defined for many of the Incubator patterns.  Below you can see that the publishing-active cache should have a size of 10 after running the run_active_publisher ant target. Consider the role of some of the other caches:DistributedCacheForCommandPattern - stores command contexts and co-located commands DistributedCacheForMessages - stores messages (in this case - entries that need to be pushed to the other cluster) DistributedCacheForSubscriptions - maintains durable subscribers for the publishersYou can learn more about these caches by looking at the Coherence Incubator Wiki and reviewing the cache-config xml files that correspond to the Incubator project they are named for.Looking at the MBean for the PublishingService, you can find operations to suspend, resume, and drain messages that have yet to be published. So if you suspend() the PublishingService, any changes to the publishing-active cache will be queued up as messages in the DistributedCacheForMessages coherence.messagingpattern.messages cache.  You can try this by executing the suspend() operation then the run_active_publisher target again.  You should then see the messaging cache full of the operations waiting to be replicated to the passive-cache. Now if you execute the resume() operation on the PublisherService, the messages will replicate to the passive-cache.  Alternatively you could execute the drain() operation and all of the messages waiting to be replicated would be deleted and the passive-cache would never receive those updates.On the Passive cluster, you can see the TCP Extend working by looking at the ConnectionManager and the Connection MBeans.  The passive process is listening in this case on port 20000 and has 1 active connection. ConclusionThis should give you a quick idea of the capabilities of the Push Replication Pattern and some of the JMX enabled capabilities in the Coherence Incubator projects.  This is the most basic example and there are also samples for Hub-and-Spoke, Active-Active, and Federated patterns which are more complex.

Lately I've been able to do some Coherence work with some local customers and play with the Coherence Incubator projects.  This entry will showcase one of the examples for Push Replication for...

WLS

BEA Product Documentation is Moving to Oracle.com Websites

As part of the decommissioning of bea.com websites to oracle.com websites, edocs.bea.com is going to be shutdown at the end of August 2009.  This means if you have bookmarked or linked to edocs in other places, those links will break.  Metalink Note 876228.1 has the official announcement on the support website. The new OTN URL for legacy BEA releases is: http://www.oracle.com/technology/documentation/bea_doc_index.html The new OTN URL for legacy WLS releases is: http://www.oracle.com/technology/documentation/weblogic_server.html My Documentation Tips In case you forget or misplace these URL’s it’s helpful to know how to navigate there from scratch.  Let me give you a short tour that will at least point you on how to find the older WebLogic Server release documentation.  The documentation for the 11g release of middleware (powered by WebLogic 10.3.1) has a new look and feel compared to edocs.   You can always find the documentation by starting at OTN http://www.oracle.com/technology/. There is a drop-down menu that will take you to the middleware documentation. http://www.oracle.com/technology/documentation/middleware.html If you click through to the 11g html library you’ll land at a page like this: http://download.oracle.com/docs/cd/E12839_01/index.htm There is a link in the left column to drill down into WebLogic Server which takes you here: http://download.oracle.com/docs/cd/E12839_01/wls.htm On the bottom right-hand side of the WLS page you’ll see the links to the older releases.       Personally the way I like to use the documentation is via google search. I have a keyboard shortcut that allows me to type “wls securing web applications” which then automatically opens a the google search for: site:http://download.oracle.com/docs/cd/E12839_01/ securing web applications Check out the results, it works pretty well. http://www.google.com/search?&ie=utf-8&oe=utf-8&rls=org.mozilla:en-US:official&client=firefox-a&q=site%3Ahttp%3A%2F%2Fdownload.oracle.com%2Fdocs%2Fcd%2FE12839_01%2F+securing+web+applications

As part of the decommissioning of bea.com websites to oracle.com websites, edocs.bea.com is going to be shutdown at the end of August 2009.  This means if you have bookmarked or linked to edocs in...

WLS

11gR1 Update and a Deployment Plan Example for WebLogic Server

7-23-09 Update: I updated this post slightly overnight after I thought of a few additional comments, an easier approach and I took in feedback from a comment. 11gR1 Release It is a very exciting time to be involved with Oracle Fusion Middleware.  First, there are many new features and capabilities in the recently released 11gR1 that I’m learning about in training this week.  My focus is mostly on WebLogic Server and surrounding technologies categorized in the Application Grid space and the SOA products.  Beyond the best-of-breed qualities in the stand-alone middleware products, there is an ever-increasing amount of synergy between Oracle’s other products, both middleware and elsewhere.  The number of products certified and making use of WebLogic Server is incredible.  This has high value for customers in the consolidation of skill-sets and infrastructure.  I am personally very impressed with the amount of innovation that has occurred in a little over a year since Oracle acquired BEA Systems, and I’m excited about what is coming in future releases.  My blog folder where I store ideas for future blog entries just keeps getting more and more backlogged as I come across things worth investigating and sharing. Deployment Plan JSR-88 Example in WebLogic Server The Forum Question One of the ways I gauge the increasing interest in WebLogic Server is the increasing number of posts in the WebLogic Server - General forum on OTN.  Today was an especially busy day and someone inquired on a fairly straight-forward problem: Can I change the context root of a web application without modifying the archive? How can you do it? Fortunately if you need to make minor configuration adjustments in application deployment descriptors (such as web.xml, weblogic.xml, application.xml, or weblogic-application.xml), but do not need to change any application code you can use a Deployment Plan (also known as JSR-88) to do this in WebLogic Server deployments.  I’m not going to go into great detail here, but the essential idea is that an xml file, usually called Plan.xml that is located outside the application archive, can be used to override or set undeclared values in the deployment descriptors that are embedded in an application archive.  See the image below. Why would you ever need this? There are many reasons why you may not want to modify an application archive, one of which is testing.  For example, if you have successfully completed testing for a particular version an application, it is desirable to keep the application archive unmodified between environments so you can have increased confidence that the application will behave the same in multiple environments as it is promoted.  Another reason might be portability.  You could have one generic J2EE or JEE application archive without proprietary deployment descriptors and put all of those proprietary deployment descriptor values outside of that archive.  I know that WebLogic Portal code used this feature at one time to change the verbosity of a log level that was set with a Servlet initialization paramter, so you could also use this to change configuration values at runtime provided those are in a supported deployment descriptor. Several other WebLogic bloggers have addressed Deployment Plans, so before I write about how I addressed this particular forum question, just know that you can get a general overview and more detailed examples from the following posts: http://m-button.blogspot.com/2008/08/how-to-use-deployment-plan.html http://biemond.blogspot.com/2009/04/using-weblogic-deployment-plan-to.html In French – but with some screencasts - http://blog.xebia.fr/2008/04/17/les-plans-de-deploiement-weblogic/ and translated to English with Google http://bit.ly/SbQPx A Simple Example There is a context-root element in a web application module’s weblogic.xml file that specifies the context root of the application.  When building a web application with Oracle Enterprise Pack for Eclipse, the value is automatically set to the Web Application name.  Check out the WEB-INF/weblogic.xml from my Web Application named PlanWEB. <?xml version="1.0" encoding="UTF-8"?><wls:weblogic-web-app xmlns:wls="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd http://xmlns.oracle.com/weblogic/weblogic-web-app http://xmlns.oracle.com/weblogic/weblogic-web-app/1.0/weblogic-web-app.xsd"> <wls:weblogic-version>10.3.1</wls:weblogic-version> <wls:context-root>PlanWEB</wls:context-root></wls:weblogic-web-app>I have confirmed that my application is deployed and listening at the /PlanWEB context root on my server.  How you deploy it, weblogic.Deployer, WLST, or the console is up to you.  Now lets say I want to change the context root to /FooWEB at runtime, even though the weblogic.xml file in the application archive will have PlanWEB listed in the deployment descriptor.Option 1 – The Console – The easy GUI driven wayBrowse the deployment, specifically to the web module of the context root you want to change.  Here’s a shot of my Deployments page after I have expanded the EAR to see it’s modules.Home –> Deployments –> PlanEAR Click on PlanWEB, then click the configuration tab and look at the bottom of that page.  You’ll see the current context root, but not editable (depending on your console preferences it may already be editable). Lock and edit the console if you have not already and put in a new value like “FooWEB” and click the save button. The next page should prompt you for the location where the console should write the plan.xml file on the file system.  Choose whatever location makes sense, but it probably makes sense to put it somewhere in the domain directory structure or some other standard or convention you come up with. Now activate the session.  The context root should now be /FooWEB and the configuration tab of the console show now also reflect that. Here is my plan.xml that the WebLogic Server Console generated for me.<?xml version='1.0' encoding='UTF-8'?><deployment-plan xmlns="http://xmlns.oracle.com/weblogic/deployment-plan" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.oracle.com/weblogic/deployment-plan http://xmlns.oracle.com/weblogic/deployment-plan/1.0/deployment-plan.xsd"> <application-name>foo</application-name> <variable-definition> <variable> <name>WeblogicWebApp_ContextRoots_12483492503430</name> <value>"FooWEB"</value> </variable> </variable-definition> <module-override> <module-name>PlanEAR.ear</module-name> <module-type>ear</module-type> <module-descriptor external="false"> <root-element>weblogic-application</root-element> <uri>META-INF/weblogic-application.xml</uri> </module-descriptor> <module-descriptor external="false"> <root-element>application</root-element> <uri>META-INF/application.xml</uri> </module-descriptor> <module-descriptor external="true"> <root-element>wldf-resource</root-element> <uri>META-INF/weblogic-diagnostics.xml</uri> </module-descriptor> </module-override> <module-override> <module-name>PlanWEB.war</module-name> <module-type>war</module-type> <module-descriptor external="false"> <root-element>weblogic-web-app</root-element> <uri>WEB-INF/weblogic.xml</uri> <variable-assignment> <name>WeblogicWebApp_ContextRoots_12483492503430</name> <xpath>/weblogic-web-app/context-root</xpath> <operation>replace</operation> </variable-assignment> </module-descriptor> <module-descriptor external="false"> <root-element>web-app</root-element> <uri>WEB-INF/web.xml</uri> </module-descriptor> </module-override> <config-root>C:\temp\foo\plan</config-root></deployment-plan>Option 2 – weblogic.PlanGenerator – a more manual approach that could be used for automationHere are the steps for creating the deployment plan yourself with weblogic.PlanGenerator.Export the EAR file to a directory – my enterprise archive name is PlanEAR.ear Go to your domain's bin dir with a shell and call setDomainEnv Call a command like this from the dir where the EAR is with the configured shell: java weblogic.PlanGenerator -all -plan Plan.xml PlanEAR.earThat should generate a Plan.xml file in that directory with a bunch of stubs for values you could change at runtime in the Plan.xml file.   Change the value of the variable for the context root.  Note that the variable name is auto-generated, but it still yields a clue by the variable name prefix. Original:<variable><name>WeblogicWebApp_ContextRoots_12482790756401</name><value xsi:nil="true"></value></variable>New:<variable><name>WeblogicWebApp_ContextRoots_12482790756401</name><value>FooWEB</value></variable>Note that I did not use quotes for FooWEB whereas the console approach did use them.  Either way seemed to work just fine. In order to override the context root we need to do a replace operation in the variable assignment since the element already exists in the archive. Edit Plan.xml again, this time modifying the relevant variable assignment section of the Plan.xml.  Note, if the weblogic.xml did not already have the context-root explicitly listed as an xml element, then the original section could have been used. Original:<variable-assignment> <name>WeblogicWebApp_ContextRoots_12482790756401</name> <xpath>/weblogic-web-app/context-root</xpath></variable-assignment>New:<variable-assignment> <name>WeblogicWebApp_ContextRoots_12482790756401</name> <xpath>/weblogic-web-app/context-root</xpath><operation>replace</operation> </variable-assignment>Now we can use the weblogic.Deployer command for a redeployment with this new deployment plan Plan.xml and the EAR.  We also could have used WLST.java weblogic.Deployer -adminurl t3://localhost:7001 -user weblogic -password welcome1 -redeploy -name PlanEAR -source PlanEAR.ear -targets AdminServer -plan Plan.xmlAfter the command completes, I can now access the application at http://locahost:7001/FooWEB/. Special thanks to fellow bloggers Max, Edwin, and Benoit for their entries related to this topic.  Cheers.

7-23-09 Update: I updated this post slightly overnight after I thought of a few additional comments, an easier approach and I took in feedback from a comment. 11gR1 Release It is a very exciting time...

WLS

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. 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 theserver. To ensure on-the-wire security, the SSL port orAdmin 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-- AdminConsoledr-- AppDeploymentsdr-- BridgeDestinationsdr-- Clustersdr-- CustomResourcesdr-- DeploymentConfigurationdr-- Deploymentsdr-- EmbeddedLDAPdr-- ErrorHandlingsdr-- FileStoresdr-- InternalAppDeploymentsdr-- InternalLibrariesdr-- JDBCDataSourceFactoriesdr-- JDBCStoresdr-- JDBCSystemResourcesdr-- JMSBridgeDestinationsdr-- JMSInteropModulesdr-- JMSServersdr-- JMSSystemResourcesdr-- JMXdr-- JTAdr-- JoltConnectionPoolsdr-- Librariesdr-- Logdr-- LogFiltersdr-- Machinesdr-- MailSessionsdr-- MessagingBridgesdr-- MigratableTargetsdr-- RemoteSAFContextsdr-- SAFAgentsdr-- SNMPAgentdr-- SNMPAgentDeploymentsdr-- Securitydr-- SecurityConfigurationdr-- SelfTuningdr-- Serversdr-- ShutdownClassesdr-- SingletonServicesdr-- StartupClassesdr-- SystemResourcesdr-- Targetsdr-- VirtualHostsdr-- WLDFSystemResourcesdr-- WLECConnectionPoolsdr-- WSReliableDeliveryPoliciesdr-- WTCServersdr-- WebAppContainerdr-- WebserviceSecuritiesdr-- XMLEntityCachesdr-- 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-- ApplicationRuntimesdr-- AsyncReplicationRuntimedr-- ClusterRuntimedr-- ConnectorServiceRuntimedr-- DefaultExecuteQueueRuntimedr-- EntityCacheCumulativeRuntimedr-- EntityCacheCurrentStateRuntimedr-- EntityCacheHistoricalRuntimedr-- ExecuteQueueRuntimesdr-- JDBCServiceRuntimedr-- JMSRuntimedr-- JTARuntimedr-- JVMRuntimedr-- JoltRuntimedr-- LibraryRuntimesdr-- LogBroadcasterRuntimedr-- LogRuntimedr-- MANAsyncReplicationRuntimedr-- MANReplicationRuntimedr-- MailSessionRuntimesdr-- MaxThreadsConstraintRuntimesdr-- MinThreadsConstraintRuntimesdr-- PathServiceRuntimedr-- PersistentStoreRuntimesdr-- RequestClassRuntimesdr-- SAFRuntimedr-- SNMPAgentRuntimedr-- ServerChannelRuntimesdr-- ServerSecurityRuntimedr-- ServerServicesdr-- SingleSignOnServicesRuntimedr-- ThreadPoolRuntimedr-- TimerRuntimedr-- WANReplicationRuntimedr-- WLDFRuntimedr-- WTCRuntimedr-- WebServerRuntimesdr-- 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\wacle\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\Jener.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_manifs10gR3\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\wls10cle\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:\Orsysext_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 2008WebLogic Server Temporary Patch for 7372756 Fri Sep 12 17:05:44 EDT 2008WebLogic Server Temporary Patch for CR380913 Wed Oct 15 13:24:22 PDT 2008WebLogic Server Temporary Patch for CR381739 Tue Oct 21 14:06:14 IST 2008WebLogic Server Temporary Patch for CR381056 Mon Oct 06 10:48:50 EDT 2008WebLogic Server Temporary Patch for CR374413, CR378680 Tue Sep 02 09:55:36 PDT 2008WebLogic Server Temporary Patch for CR378102 Wed Sep 10 23:28:48 PDT 2008WebLogic Server Temporary Patch for CR378741 Tue Sep 09 13:08:51 PDT 2008WebLogic Server Temporary Patch for CR378781, CR380313 Fri Sep 19 13:34:16 PDT 2008WebLogic 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-- myClusterwls:/wldf_domain/serverRuntime/ClusterRuntime> cd('myCluster')wls:/wldf_domain/serverRuntime/ClusterRuntime/myCluster> ls()dr-- JobSchedulerRuntimedr-- ServerMigrationRuntimedr-- 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-- JobSchedulerRuntimewls:/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_1237564053328wls:/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 checkingOne 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.pyuser='weblogic'pw='weblogic'adminServer='localhost'adminPort='7001'clusterName='myCluster'timerRunning=falsetimerClass='jamesbayer.client.SystemOutTimerListener'## Standard Connectiontry: connect(user,pw,'t3://'+adminServer+':'+adminPort)except: print 'Error connecting to Admin Server'## Get the list of managed servers in the clustertry: 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 jobdomainRuntime()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: breakdisconnect()if timerRunning: print 'The Job is Running' exit(exitcode=0)else: print 'The Job is NOT Running' exit(exitcode=1)Script outputC:\Oracle\wls10gR3\user_projects\domains\wldf_domain>bin\setDomainEnv.cmdC:\Oracle\wls10gR3\user_projects\domains\wldf_domain>java weblogic.WLST C:\MyData\Accounts\PepsiAmericas\JobScheduler\isJobRunning.pyInitializing WebLogic Scripting Tool (WLST) ...Welcome to WebLogic Server Administration Scripting ShellType help() for help on available commandsConnecting 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 theserver. To ensure on-the-wire security, the SSL port orAdmin 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 serversLocation changed to domainRuntime tree. This is a read-only tree with DomainMBean as the root.For more help, use help(domainRuntime)Trying managedServer1Disconnected from weblogic server: AdminServerThe Job is RunningExiting WebLogic Scripting Tool.C:\Oracle\wls10gR3\user_projects\domains\wldf_domain>

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. Cancelling a task One of the things...

WLS

A Simple Job Scheduler Example - WebLogic Server Clustered Timer

*Dec 17th, 2010 Update* Someone commented on another entry about this very helpful EJB3 Timer write-up for WebLogic Server that is also very relevant to this topic. http://shaoxiongyang.blogspot.com/2010/10/how-to-use-ejb-3-timer-in-weblogic-10.htmlDid 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). 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. 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". 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: 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. 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. 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. 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. Deploy the WAR file, target it at the cluster, and make sure the application is started. 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 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 Restart your Admin Server and Managed Server.  Make sure you see the JAR in the classpath settings in the log file.  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!).  ####<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> 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. Notice the messages in standard out if this is working correctly. timerExpired() called at 4/8/09 3:12 PMtimerExpired() called at 4/8/09 3:13 PM 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. Now shut down all of the managed servers and restart at least one. You should see the timer task start printing to standard out when one of the managed servers in the cluster is available.SummarySo 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() ) );}}

*Dec 17th, 2010 Update* Someone commented on another entry about this very helpful EJB3 Timer write-up for WebLogic Server that is also very relevant to this topic. http://shaoxiongyang.blogspot.com/20...

Oracle Enterprise Pack for Eclipse 11g – WebLogic Interop Tip

OEPE 11g is out I had to rush out and try it.  I used the full install from OTN.  I assume most users of OEPE 11g will also be WebLogic users.  Out of the box, Workspaces are not pre-configured with a WTP Server Runtime or WebLogic Shared Libraries because OEPE doesn’t know where WebLogic is installed or which version you want to use if you have multiple installations.  There is a simple way to enable this by specifying your WebLogic home in the eclipse.ini file.  I added the following line (substitute your path to WLS): -Dweblogic.home=C:/Oracle/wls10gR3/wlserver_10.3Now your Workspaces (existing and new) should become populated with a WebLogic Server Runtime of the version you specified with WebLogic Shared Libraries.  Ah, but there is another gotcha!  In order for this to work with WLS 10gR3 Eclipse needs to be started with a JDK6 JVM.  In my case,  my system’s default JVM was JDK5, so I had to explicitly tell OEPE 11g to start with JDK 6 by specifying the JVM in eclipse.ini.  If you use JRockit instead of Sun you may want to make other adjustments such as making the min/max memory the same and not configuring PermSize at all, but those are just extra tweaks. Again, specify your specific path, but here is mine:-vmC:/Oracle/wls10gR3/jrockit_160_05/jre/bin/javaw.exeUsing Windows->Preferences you should be able to see the end result when you launch Eclipse.  Be sure to check out the OEPE 11g tutorials for some great examples.

OEPE 11g is out I had to rush out and try it.  I used the full install from OTN.  I assume most users of OEPE 11g will also be WebLogic users.  Out of the box, Workspaces are not pre-configured with...

Eclipse

Eclipse2JDev Series – An Eclipse user tries JDeveloper

Since I’ve joined Oracle via the BEA acquisition I have had the opportunity to start learning JDevleoper and I like it a lot, but I’ve had some bumps in the road since I’m so used to Eclipse.  Much of the IDE tooling for the Oracle’s SOA, BPM, and Application Server products is migrating to JDeveloper, which is Oracle’s comprehensive IDE.  This gives developers using Oracle products a very easy-to-use and highly integrated development environment.  Oracle is still strongly committed to the Eclipse community as evidenced by the contributions to many Eclipse detailed on the Oracle Enterprise Pack for Eclipse page and just announced 11g.  There are some differences for accomplishing certain tasks in JDeveloper and Eclipse and I thought I’d write about my transition from the perspective of a long-time Eclipse user.  Some members of the JDeveloper team have agreed to vet these entries and I hope others will contribute some knowledge as well.  I’ll use Workshop 10gR3 and JDeveloper 11g as my points of comparison. Application and Project Archive Packaging This use case was part of the inspiration for this series, simply to have an Enterprise Application with a Web Module that has a dependency on a Java project that is also included in the exported EAR.  In Eclipse WTP, this is accomplished by creating 3 separate projects and linking them together: Enterprise Application Project – named LibraryTestApp Utility Project – named LibraryUtility Dynamic Web Project – named LibraryWeb As you can see in the J2EE Module Dependencies section of the LibraryTestApp project, I have placed dependencies on the other 2 projects, which results in the LibraryUtility.jar being placed in the EAR’s APP-INF/lib and the WAR being included in the EAR as well.   JDeveloper has the concept of an Application, which is a container for Projects.  So first create a new Generic Application named LibraryTestApp.  The wizard guides you through the creation of a project for this application, and selected JSP and Servlet technologies and name the project LibraryWeb.  Then add a new Java Project to this Application and call it LibraryUtility.  Both of these projects are initially empty, so create a new JSP file in the Web project.  Looking at the structure for the web module, you can see that it has a WEB-INF directory, but no lib directory underneath it. How To Create a Directory I’m going to side-track this a bit and talk about a variation to this use case.  The first time I tried this I already had a pre-built jar file on the file system and my very first intuition was to create a lib directory underneath of WEB-INF and copy the file over.  JDeveloper does not allow you to create folders with a right-click on WEB-INF.  In fact, creating a folder is not directly supported in JDeveloper.  You can indirectly accomplish it by launching the “New…” wizard and generic file, and put the folder name in the Wizard.  This was not exactly intuitive to me as I was used to the Resource Perspective in Eclipse that gives you a pretty good idea of what all the files look like on the file system and lets you manipulate them.  I heard from the product team that this is an often requested feature and is being considered for future JDeveloper releases.  It turns out that you can also just add something to the file system and JDeveloper will pick it up, but there is a better way.  More on that later, but first a little more background on the Application and Project settings. Deployment Profiles and Dependencies in JDeveloper The concept of Applications and Projects will be new to Eclipse users where everything is a Project, but this helps group projects together instead of having a cluttered workspace full of potentially unrelated projects.  It turns out that you can right-click on the Application name in the Application Navigator and select Application Properties.  Similarly, you can right click on the Project name and select Project Properties.  Alt-Enter also works as a short-cut exactly as in Eclipse.  Inside of Project Properties there is a menu option for Deployments.  From an Eclipse perspective, if you want to create a jar file from a java project you can right-click on the project and select “Export->Export…->Java->Jar”.  JDeveloper does not have an “Export” option, but this is covered by a Deployment Profile.  By default there is no Deployment Profile for the project, so create a new one and name it what you want the jar to be named.  You can see that this will jar up this project and place it in the project’s deploy directory. You can explore this even further by looking at the File Groups->Project Output->Contributors and see that the Build Output and Project Dependencies both make up the contents of this jar.  Now that we have a jar, let’s turn to the LibraryWeb project that we want to use the LibraryUtility.jar.  Remember earlier when I tried to manually add the jar to the WEB-INF/lib directory?  I should have just used the “Project Properties->Libraries and Classpath” for the ViewController web module project and added the jar file to the classpath.  Notice that the “Export” checkbox is selected which means this jar will be packaged as part of the WAR under WEB-INF/lib.  So similar to the LibraryUtiilty project, you can create a Deployment Profile for the LibraryWeb project.  This time select WAR as the archive type.  You can see that the jar will be included in the WAR under the WEB-INF/lib contributors. Notice that the Deployment Profile also has a menu option for Profile Dependencies.  There you can indicate that this Deployment Profile depends on the Deployment Profile that builds the jar for the LibraryUtility project. You can follow similar steps to create a Deployment Profile for the Application via the Application Properties, this time selecting an EAR archive type.  Now we have a similar experience to Eclipse where I can right click on the project select Deploy->LibraryTestApp-> to EAR file.  In fact, I can get fancy in the Application’s Deployment Profile and specify the path to the LibraryUtility.jar file in the EAR to be in APP-INF/lib.  You can set up multiple deployment profiles per project or application, so it’s actually more flexible than the Eclipse structure. If you notice the Deploy->LibraryTestApp-> as has a “to” option as well as “to EAR file”.  Using this option I can deploy this archive to a running WLS server, more detail on that in another entry. An Alternative Approach – Project Dependencies There is alternative to the Libraries and Classpath linked to Deployment Profile approach that JDeveloper actually uses by default for Fusion Web Applications.  When you create a new Fusion Web Application, a Model project and a ViewController project are created by default.  In ViewController->Project Properties->Dependencies you will see a dependency on the Model project.  Now look at the auto-generated Deployment Profile for the ViewController project and you will see this causes the build output of the Model project to be added to the build output of the ViewController project because of the checkbox for “Project Dependencies” in the WEB-INF/classes contributors section.  This results in only one combined module inside the EAR, instead of two separate ones.  So which method is better – Project Dependencies or linking the Libraries and Classpath to another project’s Deployment Profile?  It is really a matter of taste, but since I had a preconceived notion for the structure of the EAR in the original use case, the Libraries and Classpath linked to the LibraryUtility project’s Deployment Profile worked best for me. Summary So the key take-aways are: JDeveloper organizes Projects inside of Applications Applications and Projects have the concept of Deployment Profiles and Dependencies, which can be used to structure the archives as we like them Deployment Profiles can then deploy the archives directly to running servers as well as the file system Hopefully this gives a good introduction to some of the distinctions for developing and packaging Enterprise Applications and Modules in Eclipse and JDeveloper. Potential Future Topics Here is a list of potential topics that I think are interesting for comparison’s sake, let me know if there are others you’d like to hear about. IDE meta-data IDE shortcuts Monitoring network traffic Deploying to a server Facets versus Technology Scope

Since I’ve joined Oracle via the BEA acquisition I have had the opportunity to start learning JDevleoper and I like it a lot, but I’ve had some bumps in the road since I’m so used to Eclipse.  Much...

WLS

Workaround for Using JConsole with WLS 10gR3 JMX

4-24-2009 Update – Please see the comments of this entry for a solution that only requires setting the classpath and does not require a custom RMI/IIOP proxy.  Thanks to Kai and Mic for commenting with an easier solution.  James I came across a surprising interoperability issue the other day using JConsole to browse WLS 10gR3 JMX MBeans.  Read on to see how to I got around it.  One of my customers wanted to monitor some WLS services running in a cluster recently, so in doing a little research I decided to pull up JConsole to see what the JMX Beans looked like.  Of course WLST works well for this, but I didn’t quite know where the MBean was located so I wanted something visual that I could navigate in a tree fashion without typing commands. In order to bring up JConsole, you need to follow some basic steps in the documentation to enable RMI on the server you want to connect to: http://edocs.bea.com/wls/docs103/jmxinst/accesscust.html#wp1107229  Be sure to set the default RMI user and password and you will also need to restart the servers after you perform this configuration so it takes effect. So normally you could just launch JConsole from the JDK’s bin directory and plug-in your connection info.  In my case I am using JDK 6 from the WLS Example server which is running on port 7001.  This is the URI I put into JConsole: service:jmx:iiop:///jndi/iiop://localhost:7001/weblogic.management.mbeanservers.runtimeMy RMI default user and password is “weblogic”Well, to my surprise I got a JConsole Output window that kept scrolling with errors.  Here is the beginning of the stack:com.sun.corba.se.impl.encoding.CDRInputStream_1_0_read_valueWARNING: "IOP00810257: (MARSHAL) Could not find class" at com.sun.corba.se.imple.logging.ORBUtilSystemException.couldNotFindClass(ORBUtilSystemException:7756) ....I looked around a bit on Google and found that since JDK 5 there has been a bug in the IIOP RMI stack in the JDK.  Thankfully there is a work-around that involves creating a simple poor-man’s proxy.  So I compiled and ran the RMIIIOPProxy.java file from that link (I removed the package name for brevity) and tried again to connect again while the proxy was running.  This time it worked.C:\temp>java RMIIIOPProxy 7011 weblogic.management.mbeanservers.runtime localhost 7001 weblogic.management.mbeanservers.runtimeConnection established with south server at: service:jmx:iiop:///jndi/iiop://localhost:7001/weblogic.management.mbeanservers.runtimeProxy server listening at: service:jmx:rmi:///jndi/rmi://localhost:7011/weblogic.management.mbeanservers.runtimeStrike <Enter> to exitSo now there is a simple proxy that listens on port 7011 which then connects to port 7001 on my behalf and gets around the bug.  I simply take the JMX URI from the proxy console output and plug that back in to JConsole, this time with a successful connection.  Notice that this URI does not include IIOP.  Now I get browse the MBeans, see the attributes, and execute operations like I expect.  I also tried this with JDK 5’s JConsole and the same issue was present and solved by the work-around.

4-24-2009 Update – Please see the comments of this entry for a solution that only requires setting the classpath and does not require a custom RMI/IIOP proxy.  Thanks to Kai and Mic for commenting...

WLS

Hermes JMS – Revisited for WebLogic Server JMS 10gR3

Hermes JMS is an open source JMS Browser created by Colin Crist and hosted on Sourgeforge that works with numerous JMS implementations including WebLogic JMS and Oracle Application Server JMS.  I have written about using Hermes and WebLogic together before so see that entry for an overview.  I have found that this tool works great for me to quickly view/move/delete JMS messages in queues and topics.  This entry is simply an update for the recent version of Hermes 1.13 and WebLogic Server 10gR3.  Here’s a screenshot that highlights just some of the capabilities, click to enlarge.   I like using the off-line installation from Sourceforge for reasons that will probably become apparent below, but there is also a Web Start version on the project home page. I found an old comment that I had written that claimed using the same JVM as the WLS server with Hermes helps, so I modify the %HERMES_INSTALL%\bin\hermes.bat file to use JRockit from WLS 10gR3: SET JAVA_HOME=C:\Oracle\wls10gR3\jrockit_160_05set PATH=C:\Oracle\wls10gR3\jrockit_160_05\binLaunch Hermes and go to Options->Preferences to add the weblogic.jar to the providers tab, this is nice because presumably I could use multiple WLS versions (I haven’t tried that) Configure a new Session in the GUI.  Then right click on the session and select “Discover” and you should have all the destinations available to browse. The Session gets saved in hermes-config.xml (C:\.hermes\hermes-config.xml on my machine) and the relevant snippet looks like this: <factory classpathId="weblogic10.3"> <provider className="hermes.JNDIConnectionFactory"> <properties> <property name="initialContextFactory" value="weblogic.jndi.WLInitialContextFactory"/> <property name="providerURL" value="t3://localhost:7001"/> <property name="securityCredentials" value="weblogic"/> <property name="binding" value="javax/jms/QueueConnectionFactory"/> <property name="securityPrincipal" value="weblogic"/> </properties> </provider> <connection clientID="" connectionPerThread="false"> <session audit="false" id="examplesQCF" reconnects="0" transacted="true" useConsumerForQueueBrowse="false"/> </connection> <destination domain="1" name="weblogic/wsee/DefaultQueue"/> <destination domain="1" name="weblogic/examples/ejb30/ExampleQueue"/> <destination domain="2" name="weblogic/examples/jms/exampleTopic"/> <destination domain="1" name="weblogic/examples/jms/exampleQueue"/> <destination domain="1" name="jms/MULTIDATASOURCE_MDB_QUEUE"/> <destination domain="2" name="quotes"/> <destination domain="2" name="stockTopic"/> <extension className="hermes.ext.weblogic.WebLogicJMSAdminFactory"> <properties/> </extension> </factory>Now you should be ready to browse.  You could also take the alternative route of binding to the Initial Context of the server, which then makes it easy to create multiple Sessions from the Connection Factory objects.  However, I had trouble doing this without editing the hermes-config.xml due to what might be a fluke in the GUI for changing the class-loader provider from System to the WebLogic10.3 one that has the weblogic.jar.  If you have trouble with this you can either edit the hermes-config.xml file to have the correct provider or just add the weblogic.jar to the classpath (so System inherits it).  Good luck with Hermes.

Hermes JMS is an open source JMS Browser created by Colin Crist and hosted on Sourgeforge that works with numerous JMS implementations including WebLogic JMS and Oracle Application Server JMS.  I have...

WLS

WebLogic Server Resources – My Comprehensive List

Overview Prior to joining BEA over 3 years ago, I never used WebLogic Server and had to come up to speed very quickly.  I have assembled my list of favorite resources for acquiring WebLogic knowledge.  Now that Oracle has declared WebLogic Server as the strategic application server platform I expect that many Oracle employees, customers and partners will be in a similar situation as I was when I joined BEA.  The good news is that there are many excellent ways to come up to speed in many different media formats. The Basics – Terminology and Concepts Step zero is to understand some of the concepts and terminology that are specific to WebLogic Server.  There is a very short and easy presentation that does this that has been posted on slideshare.  If you need the very high-level, then start here.  Of course you can get all of this from the documentation in a more verbose way; however I have not found a better concise introduction than this presentation. Oracle WebLogic Server Basic Concepts View SlideShare presentation or Upload your own. (tags: weblogic oracle) Baby Steps – Oracle By Example Oracle has a very nice concept called “Oracle By Example” where they explain in detail with screenshots how to perform specific tasks.  Now there is a complete Oracle By Example section on WebLogic Server with lessons for Installing and Configuring Oracle WebLogic Server Instance , Create a Basic Cluster, Using the WebLogic Server Administration Console and many others.  You have to crawl before you walk and run, so be sure to check these out as they are great for getting started. Samples and Examples Ship With the Product It surprises me how often people do not know that WebLogic Server has example source code and an sample domain that can be installed with the product.  In the past this was part of the default installation, but I believe with 10gR3 that you now have to specify the option to install the samples as part of a custom installation.  If you did the default installation you should be able to add the examples by running the installer again and selecting the custom installation to add only the examples to an existing installation.  You can see detail about the samples by opening the file <WEBLOGIC_INSTALLATION>\wlserver_10.3\samples\server\wls_samples_overview.html Check out the complete index of the 10gR3 examples on the image below and see how many specific examples are included.  For example, there web services examples for several of the WS-* specifications, in some cases mixed and matched together.  A simple rule of thumb is to always check the examples whenever you are getting started with a feature for the first time or you need a refresher on a feature you have not used in a while.  Many of the examples also can be used as a template to build on for your scripts and code. The examples instructions also include instructions on how to start the Examples Server also known as the samples domain, so be sure to check those instructions out as most examples will get deployed to the samples domain located at <WEBLOGIC_INSTALLATION>\wlserver_10.3\samples\domains\wl_server Required Reading - Documentation Although it is not as fun as watching a screencast or as quick as a topic tailored presentation, you absolutely must become familiar with the standard documentation when you get in to any level of detail on WebLogic features.  Here are a couple non-obvious items from the docs table of contents that I have circled on the left that you should note. What’s New – Provides a breakdown by subsystem of what has changed between releases, sometimes there are new features that do not get featured on the front-page, but that are very nice to know about. Known and Resolved Issues – These can come in very handy when you trying to discover if an issue you’ve run into is currently known about and potentially resolved.  It has the specific bug number (known as a CR in WebLogic speak) that can come in handy when interfacing with support. Supported Configurations – I cannot stress enough how important it is that you review the documentation for the specific OS / Chipset / JVM combination that you are using in various environments.  When using proprietary OS’s like HP-UX or AIX for example, only very specific JVM versions are supported and there may be specific patches required for the OS, the JVM, and WebLogic Server.  I have seen issues come up many times in the field when these pre-tested and certified versions are not adhered to strictly.  Take a look at this page for AIX 5.3 for example which gives precise version information and special installation instructions and patch information for this combination. Documentation Search Tip - One short-cut that I use often when searching the documentation is the google “site:” syntax.  So for example, to constrain my search the WebLogic Server 10gR3 documentation for the words “deployment descriptor” you can specify the path to restrict the results to.  I type this in the google search bar:  site:http://edocs.bea.com/wls/docs103/ deployment descriptorYou can take specify a deeper path as well, so if I only wanted to search a portion of the JMS documentation, I could have used the path http://edocs.bea.com/wls/docs103/jms In fact, I have another short-cut that simplifies this further, I use a tool called SlickRun where I can create my own short-cuts by keyword.  I have created a “wls” keyword so I can type the following command into a prompt that is always keyboard accessible:wls deployment descriptorand SlickRun will open my browser, put in the google site syntax for me, and substitue the “deployment descriptor” phrase to be my search terms.  But I digress…The final thing I will mention about the documentation is that it is a living set of documents.  If you find a gap that needs to be filled, an area that needs improvement or more detail, or a mistake then please participate in making the documentation better by sending feedback via the link at the bottom of each page or emailing it to docsupport at bea dot com.Oracle Technology Network (OTN)Many of the resources mentioned here are part of the Oracle Technology Network which has tons of information.  Here are some of my favorites for WebLogic:WebLogic Server Product Page – This is the center of the universe for WebLogic.  Do not miss the recorded demos (a list is below). WebLogic Server Product Blog – Many great posts by the product team.RSS feed for all WebLogic related articles and news ForumsThere are many product specific forums on the Oracle Technology Network that are monitored by experts to answer informed questions.  In WebLogic Server’s case there are even sub-forums for specific sub-systems of WebLogic Server that are often monitored by developers and experts in those subject areas.  In addition to the Generic WebLogic Server forum that I like to read, there are currently forums specific to JDBC, Security, Web Services, etc.  This is not a comprehensive list and they are adding more all the time, so check the Application Server category to see if there is a specific WebLogic forum for your question.  One of the most important things to remember is that the detailed, well-researched, and well-explained questions are most likely to get a helpful response.  If you are lazy and have not used some of the resources above or if you do not provide enough detail so that someone with no context can figure out what you are asking, then you end up wasting people’s time.  There is also a read-only archive of the former BEA dev2dev forums that is especially helpful for researching questions on older releases.I really like using the RSS feeds from the forums to find out about new postings in my RSS Reader.  You can also do other handy things like watch a specific thread so you receive emails about any updates to that thread only instead of for the entire forum.Oracle provides a formal support process for their customers with defined Service Level Agreements and the forums are not a substitute for that.  They are a community-based volunteer mechanism to help both the questioners and the responders further their knowledge.  So if you use the forums to post questions, give back and help answer some of the questions too.  Even if you only start by redirecting people to previous answers or a better forum to post their question in, you can help build the community and learn yourself.SupportWhenever an issue or question comes up that has urgency, I urge my customers to open a support case.  I use this simple support quick reference guide with my customers that has all contact information and describes how to open a support case, escalate an issue, etc on only one page.  It’s easy to print out and post somewhere where management, developers and administrators can see it.  WebLogic support is still handled by the http://support.bea.com website as of this post, but over time it will migrate to the My Oracle Support website formerly known as Metalink.Support Patterns - The WebLogic support patterns are a fantastic way to try self-service support on common issues.  These are used by the support engineers and are common enough to be published for anyone to use.  They are broken down by topic area and I often find myself pointing customers to this information.  For example, if you need to troubleshoot multicast issues in a cluster there is a page dedicated to that topic.Oracle UniversityFormal training courses from Oracle University and certifications are a great way to build knowledge.  WebLogic courses are currently listed under the BEA section.SummaryI’m sure that I have omitted some excellent resources by accident.  There are published books on these topics and many WebLogic blogs out there, not all of which are hosted on blogs.oracle.com.Once you participate in the community awhile you make connections with experts in many subject areas.  The relationships that I have built up over time with the product team and specialists are helpful, but it did not happen over night.  So my advice is to participate in the community and take advantage of the many resources out there.  Leave a comment if you have any favorites resources that I left out.

Overview Prior to joining BEA over 3 years ago, I never used WebLogic Server and had to come up to speed very quickly.  I have assembled my list of favorite resources for acquiring WebLogic knowledge. ...

Eclipse

Real-time Updates on WebPages - Part 2 - Hello World Comet Application

Overview *10/21/2008 Update* I mention in this post that I had an issue with Dojo 1.2.0, well I figured it out, read Part 3 for details. Last week I wrote about the introduction of a HTTP Publish-Subscribe Server in WebLogic Server 10gR3.  The new feature is based on the concept of Comet and implements the Bayeux protocol and is very useful for publishing events immediately to subscribed clients over HTTP.  There are many uses for a feature like this, essentially any time where stale information should be updated on a web page as soon as possible.  This entry will showcase a basic Hello World example application that will demonstrate the basic mechanics for using this feature.  Click the image to enlarge and get a better look at the application. Pre-reqs Dev Tools - I built this example with Oracle Enterprise Pack for Eclipse 1.0.0, the Eclipse 3.4 version, which you can download here.  If you just want to deploy the WAR file, then you can skip this. Application Server - You will need WebLogic Server 10gR3. Browser Debugging  - You must have Firebug for Firefox if you spend any time doing web development.  I insist. Javascript Framework - It's also probably not a good idea for me to include Dojo Toolkit source with my example without getting approval, so grab a copy of that too.  I used version 1.1.1 because 1.2.0 was not out last week and more importantly when I tried 1.2.0 tonight, I got the error message below which leads me to believe there is a compatibility issue with 1.2.0 and the Bayeux implementation on WLS.  More to come when I figure this out.  I see that Dojo 1.2.0 version supports an additional connection type that WLS's pubsub server doesn't accept currently.  The bottom line is use Dojo 1.1.1 for now. *10/21/2008 Update* I mention in this post that I had an issue with Dojo 1.2.0, well I figured it out, read Part 3 for details. [{"channel": "/meta/handshake", "successful": false, "error": "402:long-polling-json-encoded:Invalid supportedConnectionTypes attribute.", "supportedConnectionTypes": ["long-polling","callback-polling"], "version": "1.0", "minimumVersion": "0.1", "advice": {"reconnect": "none", "interval": 500, "multiple-clients": false}}]Server-sideThe example consists of server-side components that simply requires editing two deployment descriptor files in your web application's WEB-INF folder.  The typical steps section of the documentation are pretty clear.  In your weblogic.xml file, add a reference to the pubsub library, which will cause WLS to merge the files in the pubsub library with your application at runtime.  Here is the simplest that file could look:<?xml version="1.0" encoding="UTF-8"?><weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><library-ref><library-name>pubsub</library-name><specification-version>1.0</specification-version> </library-ref> </weblogic-web-app>Secondly, you will need a weblogic-pubsub.xml file.  Below is the simple one for my sample application.  Notice the channel pattern definition, which is concept very similar to a Topic in JMS, except that there is also pattern matching.  There are also some configuration constraints for the channel pattern.<?xml version="1.0" encoding="UTF-8"?><wlps:weblogic-pubsub xmlns:wlps="http://www.bea.com/ns/weblogic/weblogic-pubsub"><wlps:channel><wlps:channel-pattern>/hello/**</wlps:channel-pattern><!--since no handler defined, the default handler will be used --></wlps:channel> <wlps:channel-constraint><wlps:channel-resource-collection><wlps:channel-resource-name>subscribe</wlps:channel-resource-name><wlps:description>subscribe channel constraint</wlps:description><wlps:channel-pattern>/hello/*</wlps:channel-pattern><wlps:channel-operation>subscribe</wlps:channel-operation><wlps:channel-operation>create</wlps:channel-operation><wlps:channel-operation>publish</wlps:channel-operation></wlps:channel-resource-collection><!-- Open this up for all users, if this section is enabled, web users will need to authenticate<wlps:auth-constraint><!- allow only user with "subscriber" role to subscribe to above channels -><wlps:role-name>subscriber</wlps:role-name></wlps:auth-constraint> --></wlps:channel-constraint>Client-sideThe simple.jsp that is included with my project showcases the most basic example of Dojo client API.  For additional functionality, look at the source of index.jsp.  Both of these files just as easily could be html files instead of jsp.<html><head><!-- Import Dojo --><script type="text/javascript" src=""dojo-release-1.1.1/dojo/dojo

Overview *10/21/2008 Update* I mention in this post that I had an issue with Dojo 1.2.0, well I figured it out, read Part 3 for details. Last week I wrote about the introduction of a HTTP Publish-Subsc...

Real-time Updates on Web Pages - WebLogic Server 10gR3 New Feature

I was excited to learn via the popular blog TechCrunch that FriendFeed announced a beta of "Real-time" updates for their html pages using long polling or server push.  This is showcased on a page highlighting the Presidential debate.  One of the quotes I like was from Robert Scoble who said “This is wild. It’s like the web has been turned into a chat room.” Why is this relevant to WebLogic Server and enterprise customers?  Well, you can build sites like this using WebLogic completely with out of the box features that are also enterprise-ready.  WebLogic Server 10gR3 now includes an enterprise class HTTP Publish and Subscribe Server that implements the Bayeux protocol. This protocol provides the ability to apply the Ajax concept known as Comet. This means that simple web clients based only on html and javascript can be notified nearly instantly as events are observed by the server; no Applets, Flash, or Silverlight required. The HTTP Publish and Subscribe Server takes advantage of the groundwork laid in previous releases with the Future Response Servlet and Abstract Asynchronous Servlet.  A stock tracking example ships with the server shows real-time updates to market data directly in the browser and on a chart.  Click the image to enlarge.  When you see this example in action, observe that the stock ticker properties and chart are truly "live" and are constantly changing with new market data updates. Consider how often this comes up in web applications.  I'd be shocked if you've never found yourself repeatedly hitting refresh on your browser to     - check the status of an online auction     - try and buy tickets to popular concert at a ticket broker that had a waiting room     - see whether your stock trade went through     - see if you have new web mail     - see if new articles have been posted on a busy news site Just like the manual refresh situations described above, many web applications have handled stale data checks by automatically refreshing the entire page.  MyYahoo and DrudgeReport are both extremely popular sites still perform a periodic complete refresh.  Ajax has helped improve this situation to some degree by providing a mechanism to only update a page partially without a complete page refresh, which can be faster and more efficient to the client, network, and server resources than request all the page resources again.  However, the AJAX technique often involved periodic server polling techniques, asking the basic question over and over again, "Anything new yet?".  The quicker the page needs display new updates, the more often the client still needs to check for them.  It should remind you of the long road trip cliche "Are we there yet?".  This can result in very inefficient behavior creating a lot of unnecessary network traffic and server load. Creative javascript and server-side developers started coming up with ways to push server events to clients using standard HTTP.   One of the members of the Dojo Toolkit javascript framework coined the term Comet, a play on the Ajax name, to describe the concept.  With the Bayeux protocol, they have found a way to mitigate some of the concerns polling to make it more efficient on the client and server. In fact, many applications are now being built that take advantage of Comet techniques.  Take a chat application for example, Google Talk, YahooIM, and Meebo all have basic html and javascript clients that can participate in live chats.  In fact, previous versions of WebLogic Server included a chat example that applied this technique in a raw way.  See my previous post about it. You can find the information about the stock example and run it with the samples domain. <WEBLOGIC_INSTALLATION>\wlserver_10.3\samples\server\examples\src\examples\webapp\pubsub\stock - Note, use IE or another non-FF browser as the sample application does work with latest version of Firefox, I tried FF 3.0.3. The reason is that the html client code uses an old version of the Dojo Toolkit (0.4) that no longer behaves nicely with FF3.  You can tell that this sample was actually built awhile ago in web time. Several new Dojo releases have come out since then, as of this post the latest is 1.1.1, but it's still useful for demonstrating the concept. A sample application I created with Dojo 1.1.1 worked fine in both IE and Firefox.  I'll plan on writing about in a follow-up entry as there is enough to say to make this a series of posts.  Dojo and WebLogic together provide a very compelling solution, but there are other javascript frameworks out there like JQuery that are also providing client software for this and the WebLogic implementation is compatible with any Bayeux client.  More to come soon.

I was excited to learn via the popular blog TechCrunch that FriendFeed announced a beta of "Real-time" updates for their html pages using long polling or server push.  This is showcased on a page high...

WLS

REST Building Momentum

Lately I've been noticing a lot more references to REST implementations in industry publications.  Today I learned via InfoQ that Netflix recently announced their new REST-based API.  I'm not sure what language or framework they used for the implementation, but I think that REST interfaces will continue to increase and be a technology that is relevant to enterprise Java developers. At BEA, some of the products such as WebLogic Portal 10.2 and already contained REST API's and other products already had increased developer-friendly REST support in the roadmap such as Oracle Service Bus (formly known as AquaLogic Service Bus).  There is no doubt that customer demand is calling for this in enterprise software. With JSR 311: JAX-RS: The Java API for RESTful Web Services and the Jersey reference implementation java developers have an annotations based framework to productively implement REST-style services.  There are other java frameworks out there besides Jersey, but this one caught my attention because it's based on the JSR and a reference implementation.  In fact, I stumbled across Oracle developer Gerard Davison's blog that details how to get started with Jersey in WebLogic Server.  If you have an interest in REST for Java, be sure to look at these frameworks for a jumpstart.  In my humble opinion SOAP-based web services still have more enterprise Java mind-share, but I would look for that to balance out over time. Here's the hello world code snippet from the Jersey Wiki: package com.sun.ws.rest.samples.helloworld.resources;import javax.ws.rs.GET;import javax.ws.rs.Produces;import javax.ws.rs.Path;// The Java class will be hosted at the URI path "/helloworld"@Path("/helloworld")public class HelloWorldResource { // The Java method will process HTTP GET requests @GET// The Java method will produce content identified by the MIME Media// type "text/plain" @Produces("text/plain")public String getClichedMessage() {// Return some cliched textual contentreturn "Hello World"; }}

Lately I've been noticing a lot more references to REST implementations in industry publications.  Today I learned via InfoQ that Netflix recently announced their new REST-based API.  I'm not sure...

WLS

JMS with .NET - WebLogic Server 10gR3 Example

Overview Update: 9/25/2009 - Since the documentation has moved to OTN, please refer to This link for the 11gR1 release of JMS .NET client documentation.WebLogic Server 10gR3 contains an officially developed and supported .NET JMS client library for the first time.  Previous versions of WebLogic Server have shipped with C library support which is still included.  Some independent projects were able to use the C libraries to add unofficial .NET support in the past, but this latest WLS release takes things to the next level.  There was a question today in the WLS forums about VB support, so I decided to try the example.  In about 20 minutes I had the C# example working (I had WLS and Visual C# 2008 Express installed previously).  Here are some screenshots and notes from my test. Software Prerequisites WebLogic Server 10gR3 Visual C# 2008 Express Edition or your favorite .NET compiler - this one is free and useful for doing the basics Basic Steps I started by reviewing the new .NET client documentation for WebLogic Server.  The basic gist of it is the default installation of WLS includes the WebLogic.Messaging.dll library in <WEBLOGIC_INSTALLATION>\modules\com.bea.weblogic.jms.dotnetclient_1.0.0.0.  All you need to do is create a reference to that DLL and your ready to use the .NET WLS JMS API.  In fact, a complete C# example console application is provided in the docs. Build the C# Client So the first thing is to do launch Visual C# and create a new project and select the Console Application template. On the right hand side of the window, you should see the Solution Explorer, simply right click on the References and select Add Reference.  You'll need to browse to the WebLogic.Messaging.dll location and click OK. Then simply replace the existing CS file with the MessagingSample.cs file provided in the documentation.  I found it simple enough to right click on the project and select Add->Class, name the file MessagingSample.cs and paste over the generated contents.  Then I deleted the original .cs file that was created by default for the project. Then just save and build the solution.  F6 is the shortcut for this or you can use the menu Build->Build Solution.  My .exe was placed in a location like this, but you can configure it:  D:\MyData\Visual Studio 2008\Projects\WebLogicJMSExample\WebLogicJMSExample\bin\Release WebLogic Server JMS Configuration When you look at the source code in the example, you can see that it assumes some basic host and port information along with a basic queue and topic are available in WebLogic Server JMS.  private string host = "localhost";private int port = 7001;private string cfName = "weblogic.jms.ConnectionFactory";private string queueName = "jms.queue.TestQueue1";private string topicName = "jms.topic.TestTopic1";If you use the examples server domain, which you can start from <WEBLOGIC_INSTALLATION>\wlserver_10.3\samples\domains\wl_server\bin\startWebLogic.cmd (sh) then you simply need to add a queue or topic or change the example C# code to point to the JNDI name of your queue and topic.  Here's a screenshot of my examples server JMS module after I've done the configuration.  Notice that I've set both the JNDI name and targeted the queue and topic to the subdeployment.  Click the image to enlarge it.  I had a little trouble with the JNDI tree the first time through because I forgot to target the topic and queue to the subdeployment and therefore the JNDI name wasn't published correctly.  To make sure you got it right, you can check the JNDI tree.  From the console choose Environment->Servers->examplesServer(admin).  The next page should have a link that says "View JNDI Tree".  From there you can validate that the queue and topic are available as you expect.  Since I had made a mistake the first time through, I found that I had to restart WLS to get the JNDI tree correct, but this step should not be necessary if you configure the JMS module correctly the first time. Once the JNDI names are verified, try the executable.D:\MyData\Visual Studio 2008\Projects\WebLogicJMSExample\WebLogicJMSExample\bin\Release>WebLogicJMSExample.exeWebLogic JMS .NET Client DemoSettings: host = localhost port = 7001 cf = weblogic.jms.ConnectionFactory queue = jms.queue.TestQueue1 topic = jms.topic.TestTopic1-- DemoSyncQueueReceiveWithAutoAcknowledge --t3://localhost:7001Trying to connect to URL: T3://localhost:7001Successful in connecting to URL: localhost:7001Sent Message: JMSMessageID=ID:<294131.1221078898734.0> JMSRedelivered=False JMSXDeliveryCount= Text=My q messageReceived Message: JMSMessageID=ID:<294131.1221078898734.0> JMSRedelivered=False JMSXDeliveryCount=1 Text=My q message-- DemoAsyncNondurableTopicConsumerAutoAcknowledge --t3://localhost:7001Trying to connect to URL: T3://localhost:7001Successful in connecting to URL: localhost:7001Sent Message: JMSMessageID=ID:<294131.1221078899219.0> JMSRedelivered=False JMSXDeliveryCount= Text=My topic messageReceived Message Asynchronously: JMSMessageID=ID:<294131.1221078899219.0> JMSRedelivered=False JMSXDeliveryCount=1 Text=My topic message-- DemoSyncTopicDurableSubscriberClientAcknowledge --t3://localhost:7001Trying to connect to URL: T3://localhost:7001Successful in connecting to URL: localhost:7001Sent Message To Durable Subscriber: JMSMessageID=ID:<294131.1221078900406.0> JMSRedelivered=False JMSXDeliveryCount= Text=My durable messageDurable Subscriber Received Message: JMSMessageID=ID:<294131.1221078900406.0> JMSRedelivered=False JMSXDeliveryCount=1 Text=My durable messageDurable Subscriber Received Message Again: JMSMessageID=ID:<294131.1221078900406.0> JMSRedelivered=True JMSXDeliveryCount=2 Text=My durable messageD:\MyData\Visual Studio 2008\Projects\WebLogicJMSExample\WebLogicJMSExample\bin\Release>After you run the test, you can look at the queue and the topic in the console and go to the monitoring tab.  If the test ran successfully, you should see the message counts and client counts indicate that the test run.You can download my Visual C# 2008 Solution.If you plan to use this feature, please contact me at james dot bayer at oracle dot com or leave a comment.  I know the JMS team is very interested to hear how our customers are planning to use the .NET support.

Overview Update: 9/25/2009 - Since the documentation has moved to OTN, please refer to This link for the 11gR1 release of JMS .NET client documentation. WebLogic Server 10gR3 contains an officially dev...

Eclipse

Workshop for WebLogic 10.3 JEE 5 Trial and Error

Now that Workshop 10.3 is available, I test drove the new JEE 5 support with a very basic EJB 3 scenario.  Namely, create a remote stateless session bean and invoke it from a stand-alone java client.  I stumbled around at first since my first guesses for using the new Workshop JEE5 feature support worked were incorrect.  So I've decided to write up my experience in case it will help someone else.  It turns out that JEE 5 really does simplify things, and overall I think it is a big improvement. Background A few weeks ago WebLogic Server 10.3 (also known as WebLogic Server 10g Release 3) was released and Workshop for WebLogic 10.3 was also bundled with the full server installer.  You can download it separately on the Developer Tools section on the OTN download site.  Pieter Humphrey's entry on the tools blog that details lots of new features or Andrei Cioroianu's OTN article for a more thorough walk-through show-casing more features.  In previous releases of Workshop, the wizards/tooling only supported EJB 2.1 development with WebLogic's EJBGen (or EJBDoclet based on XDoclet) even though WebLogic Server 10.0 and newer support JEE 5 and EJB 3. Old School EJB 2.x For review and comparison, consider the way I was familiar with in Workshop 9.2 through 10.2 to  create a simple stateless session bean and client.  Click the image to enlarge the screen captures. Create a new EAR project (EAR facet version 1.4 and WebLogic EAR extensions facet versioned to the release of the app server you are deploying to).  Create a new EJB project (with EJB Module facet version 2.1 and WebLogic EJBGen Support facet version for your WLS release).  On the next page in the wizard, do not select the client project option (in fact I do not think it will even let you).    Go to the EJB project properties->WebLogic EJB->Jar settings - EJB client jar and indicate the location the client jar should be placed as an output of a build (try to use an absolute path here or it will place the jar relative to the current working directory). Create a session bean - typically right-click on the "ejbModule" source folder and select New->WebLogic Session Bean.  This will open a wizard, which results in a stubbed out session bean.  The bean has annotations for the weblogic.ejbgen package.  During a project build (triggered by a deploy or an export), weblogic.EJBGen is invoked, which builds out all of the EJB plumbing for you (local, remote, home interfaces, classes, deployment descriptors, the ejb client jar, etc.). Develop a client class with a main method to invoke the session bean. For an example of how to develop the the EJB 2.x client class, you can go look at the examples that ship with WLS.  <SERVER_HOME>\wlserver_10.3\samples\server\examples\src\examples\ejb\ejb20\basic\statelessSession\Client.java.  Essentially, it involves getting a JNDI context, finding the ejb home, creating an instance and narrowing that object....phew I'm tired just thinking about all of that.  However, this model is fairly well known to enterprise java developers now. New School EJB 3 I assumed the steps would be similar for JEE 5 and EJB 3, but I was a little off.  I'll highlight the areas where it is different or non-intuitive in red. Create a new EAR project (EAR facet version 5.0 and WebLogic EAR extensions facet versioned to the release of the app server you are deploying to) Create a new EJB project (EJB Module facet version 3.0 and NO WebLogic EJBGen Support facet).  Since we are planning to use the client without EJBGen, this time select the client jar option on the next screen in the wizard.  This will result in another project being created just for the client interfaces and client code.   You do not create a session bean using the menu New-> and navigating to WebLogic Session Bean, rather you simply create a basic interface for your EJB in the EJB Client project.  You could place it somewhere else, such as the EJB Project, but since the EJB Client project is already on the classpath for the EJB project, putting the interface in the EJB Client is a nice way of packaging that interface so it can be easily referenced in other projects .  Not using the menu or a wizard to create the session bean surprised me, but since JEE 5 and EJB 3 is so simple, it makes sense that you would not need a wizard. Create a class implementing that interface and annotate the class with @Stateless and @Remote.  You could also annotate the interface with @Remote instead of the class.  It's up to you.  I prefer keeping all the EJB annotations in one file and keeping the interface clean.  I find it easy to just use code-completion Ctrl-Space on the annotation which adds the import statement.  In the @Stateless annotation, specify the mappedName attribute so you will know the JNDI name.  The formula for the JNDI name is documented here.  Basically it is mappedName#FullyQualifiedInterfaceName.  So in my example the JNDI name would be  HelloWorld#test.HelloWorld.  Create the class with the main method that will invoke the session bean.  There is no sample of this for EJB 3 in the examples, probably because it is so easy.  I put this in it's own Java Project, but you could put it in the client project as well depending on your packaging structure.  The code to do the invocation is so simple, no more home interfaces and narrowing, simply cast the returned object from the lookup to the interface and perform the invocation. ic = getInitialContext();HelloWorld helloWorld = (HelloWorld) ic.lookup(HELLO_WORLD_JNDI_NAME);log(helloWorld.hello("James"));To actually run the Main method class in Workshop, I right click on the class in the Project Explorer and select Run As->Open Run Dialog.  In the classpath tab, be sure to add the wlclient.jar file located here <SERVER_HOME>\wlserver_10.3\server\lib to the User Entries section and remove the WebLogic System Libraries from the Bootstrap Entries section.  If you forget to remove the WebLogic System Libraries, you will get a stack like this: Exception in thread "Main Thread" java.lang.NoClassDefFoundError: weblogic/kernel/KernelStatus If you put both the Main method and interface in the same jar file, you can invoke it with only 2 jars on the classpath, JEE doesn't get much simpler than this: D:\TEMP\jeeclient>java -cp d:\wls103\wlserver_10.3\server\lib\wlclient.jar;HelloJava.jar test.TestClientHello JamesConclusionThere may be better ways to go about this, and I'd love to hear about it if you've found a better approach or have comments on the approach I've described above.  My Workshop 10.3 projects are available here with all my code.  Simply File->Import->General->Existing Projects into Workspace->From Archive and give it a shot and enjoy much improved support for JEE 5 and EJB 3 in Workshop. 

Now that Workshop 10.3 is available, I test drove the new JEE 5 support with a very basic EJB 3 scenario.  Namely, create a remote stateless session bean and invoke it from a stand-alone java client. ...

Using REST with Oracle Service Bus

Overview Oracle Service Bus (OSB), the rebranded name for BEA's AquaLogic Service Bus, is one of the products I help customers with frequently.  Recently questions from both customers and internally at Oracle have been increasing about OSB support for REST. In this entry I cover the current and future state of REST support in OSB. Background REST can be a loaded term.  There are a couple of InfoQ articles introducing REST and REST Anti-Patterns that should be required reading for those considering a REST architecture.  What does REST support really mean in the context of an Enterprise Service Bus? A Service Bus applies mediation to both clients and providers of services.  This results in a loosely coupled architecture, as well as other benefits.  Being loosely coupled means that Providers and Consumers can now vary different aspects of a message exchange: Location of Provider/Consumer Transport (Http, Https, JMS, EJB, FTP, Email, etc) Message Format (SOAP, POX - Plain Old Xml, JSON, txt, etc) Invocation Style (Asynchronous, Synchronous) Security (Basic Auth, SSL, Web Service Security, etc) Two aspects where Service Bus support for REST would apply in an example would be Transport and Message Format. A Contrived But Realistic Example   Consider a contrived example where REST support in the Service Bus could easily come up.  Assume an organization already has an Order SOAP based service that is mediated by the Service Bus.  Currently this service is used by several applications from different business units.  SOAP web services with well-known XSD contracts work great for an interchange format for existing systems.  However, there is a new initiative to give management a mobile application to get order status.  The sponsoring executive has heard that AJAX is important and tasked an intern to quickly build the front-end because of frustration with IT delays.  The front-end is quickly mocked up using an AJAX framework and the executive tells the IT staff to deploy it immediately.  The problem is that the client-side AJAX framework doesn't work with SOAP and XML, it was mocked up with JSON. Instead of developing a second Order Service to support this new invocation style and format, OSB can be configured to mediate both the invocation style and the message format and reuse the perfectly working, tested, provisioned, etc Order Service.  A new proxy could be configured to accept HTTP requests and map them to SOAP over HTTP.  The response, which is normally XML described by XSD, can be converted to JSON. OSB Capabilities A common REST approach in practice is the use of HTTP verbs POST, GET, PUT, and DELETE to correspond to the CRUD methods of CREATE, READ, UPDATE, DELETE.  So we can map those verbs to the Order Service, mapping DELETE to cancelOrder since it is against company policy to delete orders from the system. The HTTP transport for inbound requests (a Proxy) in the Service Bus provides a mechanism to intercept invocations to a user customized URI base path.  So if my server binds to the context "user_configured_path" and localhost and port 7001, then the HTTP Proxy intercepts all HTTP GET and POST calls to http://localhost:7001/user_configured_path .  This includes suffixes to that path such as http://localhost:7001/user_configured_path/foo/bar/etc . AquaLogic Service Bus 3.0 (as well as 2.x releases of ALSB) supports GET and POST use cases, but does not have developer friendly support for HTTP verbs PUT and DELETE out of the box.  For GET requests, pertinent information is available in the $inbound/ctx:transport/ctx:request/http:relative-URI variable.  To parse query string information, use $inbound/ctx:transport/ctx:request/http:query-string.   A common pattern for HTTP GET is to use XQuery parsing functions on that variable to extract extra path detail, but the $body variable will be empty.  For POST requests, the same applies, but the $body variable may have a message payload submitted as xml, text, or some other format. I have heard from product management that first class support for HTTP verbs such as PUT and DELETE is planned in the next release of OSB, which is scheduled sometime in the Fall of 2008.  For customers that require PUT and DELETE verb support immediately, OSB does have a transport SDK, which could be used to add inbound and outbound REST support.  That approach would require some development.  There are other inbound options besides the transport SDK, such as a basic approach of deploying an HTTP servlet with doDelete() and doPut() implemented.  This servlet could be deployed on OSB instances and forward to specific proxies to provide PUT and DELETE support.  An outbound option would be to use a java call-out to invoke a REST style provider. Returning to the example for a moment, the executive dashboard only requires order status in the first release, so only HTTP GET support is necessary.  In the existing SOAP-based Order Service, the interaction looks like this: An equivalent REST-ful URL might look like http://localhost:7001/Order/123 where 123 is the OrderID.  Clients using this interface might expect a JSON response like this: {"Status":"Submitted","OrderID":"123","OrderDetailID":"345","CustomerID":"234"}Types like int are supported JSON values, although the above value types are strings as you can see by the double quotes.  Let's just assume that strings are ok for now to make this easier.  Here is a proxy configuration bound to the Order URI context: Notice that the response type is "text" because we will convert the XML to JSON.  I tried using the JSON java library from json.org to convert xml nodes in the response to a JSON format.  One gotcha is namespace conversion.  For simplicity I tested with xml nodes with no namespaces, and that worked.  That code looks like this:  org.json.JSONObject j = org.json.XML.toJSONObject( xmlStringBuffer.toString() );System.out.println( j.toString() );There are other techniques to convert between XML and JSON that use convention to map namespaces to JSON structures, but that is for another time.  Because my example used real-world xml with namespaces, I used a java callout to loop over child nodes of an XmlObject to build the JSON structure in java code.  Let me know what you think and if you have considered alternative approaches.  I've attached my code artifacts that are completely for illustrative purposes only and worked on my machine with ALSB 3.0 and Workshop 10.2.For another example that works with currently released versions of Service Bus, check out "The Definitive Guide to SOA - BEA AquaLogic Service Bus" by Jeff Davies.  In the book he has a Command example where a Proxy is used for a service that handles multiple types of commands.  An updated version of the book should be available shortly.

Overview Oracle Service Bus (OSB), the rebranded name for BEA's AquaLogic Service Bus, is one of the products I help customers with frequently.  Recently questions from both customers and internally at...

ALSB FTP Nuance

This was originally posted on my dev2dev blog June 18th, 2008. One of my customers just recently had an issue with AquaLogic Service Bus's FTP transport.  They were attempting to write a file to a remote ftp site using a Business Service, but they kept getting a 553 error from the FTP server.  The stack looked similar to this: com.bea.wli.sb.transports.TransportException: Received error response (553) from FTP server [localhost] IP [127.0.0.1 port [21] status [connected] upon executing command [stor ./data/inbound/somefile.csv]at com.bea.wli.sb.transports.ftp.connector.FTPTransportProvider.sendMessage(FTPTransportProvider.java:399)at com.bea.wli.sb.transports.ftp.connector.FTPTransportProvider.sendMessageAsync(FTPTransportProvider.java:289)at sun.reflect.GeneratedMethodAccessor579.invoke(Unknown Source)at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)at java.lang.reflect.Method.invoke(Method.java:585)It turns out that the path on the business service should be relative to the user of the service account of the FTP Business Service based on the directory the user was being placed in upon a successful ftp login.So the original FTP URI was ftp://locahost:21/data/inbound/but since a specific user was being used being placed in a user-specific directory by the ftp-server, the URI should have been:ftp://localhost:21/../../data/inboundThe relative path components are required because the "data" directory is two levels above where the user was being placed.  If you encounter this problem and need help from support, reference case 790268 and they should be able to help you out.

This was originally posted on my dev2dev blog June 18th, 2008. One of my customers just recently had an issue with AquaLogic Service Bus's FTP transport.  They were attempting to write a file to a...

Using X.509 Certificates for Identity Propagation with Web Service Security in WebLogic Server

This was originally posted on my dev2dev blog April 29th, 2008. One of my customers is considering a web services interface for exchanging information with their clients.  Security is a very important consideration in their design, so they are considering using best practices for authentication, integrity and confidentiality.  In this post I'll explain some detail around my experiences setting up a simple prototype using Web Service Security hands-on. Introduction Currently they plan on using HTTPS for the transport, but SSL may be terminated by SSL hardware accelerators before it reaches the application server, so transport level security is not enough in this instance, we'll also need some message level security.  The newer WS-Security 1.1 specification is available in the latest releases of WebLogic Server, but WS-Security 1.0 has maximum interoperability with other web services stacks.  So it you are not in control of web service stack's that your clients are using, it's best to use the older standard.  SAML, Username, and X.509 Token Profiles can be used for authentication.  In this instance since certificates are already required for SSL, it will be straightforward to also use them to authenticate identity.  This is a similar use-case to a previous dev2dev article posted on securing web services in WLS 9.2, but in this case we are going to use the X.509 certificates for the identity propagation instead of Username Token.  The formal name for this is the OASIS WS-Security X.509 Token Profile.  The identity in the certificate will map to an LDAP user. Note that WebLogic Server ships with examples that perform User-name Token authentication located at <BEA_HOME>\wlserver_10.0\samples\server\examples\src\examples\webservices\wss1.1 I was not able to find a X.509 Token Profile example, so I wrote it up here and hopefully you can benefit from my experiences by getting this running and understand the steps in under an hour. Client Diagram Server-side Diagram Basic Steps Client Certificate Setup (10 minutes) Server Configuration (20 minutes) Server-side JWS Programming (15 minutes) Client-side Web Service Programming (15 minutes) Client Certificate Setup First, set up a java key store and certificate identifying a user that we can map to an LDAP user.  In this example I use only the CN attribute.  This CN attribute will map to a user in WebLogic's embedded LDAP, but you can use another enterprise LDAP (Active Directory, eDirectory, OpenLDAP) just as easily.  We will use self-signed certificates in this simple example, but in production I would highly encourage you to use certificates issued by a Certificate Authority. keytool -genkey -v -keyalg RSA -sigalg SHA1withRSA -keystore D:/bea102/wlserver_10.0/samples/domains/wl_server/keystores/Identity.jks -alias testalias -keysize 1024 -keypass weblogic -storepass weblogic -dname CN=secuser' Now we need to export the pubic key to a .pem file so we can import it on the server side. keytool -export -alias testalias -file testalias.pem -sigalg SHA1withRSA -keystore D:/bea102/wlserver_10.0/samples/domains/wl_server/keystores/Identity.jks -storepass weblogic -rfc   Server Configuration Some administrative configuration is required in the console to load the certificate into the trusted certificate chain and to tell the web services security stack to do identity propagation when X.509 tokens are found. WebLogic ships with a DemoTrust keystore that can be used for testing purposes.  Again, for production domains, you would want to not use the DemoTrust keystore, but it works well for prototyping the configuration steps.  Here is how I imported the certificate into the keystore. keytool -v -import -trustcacerts -alias testalias -file testalias.pem -keystore D:/bea102/wlserver_10.0/server/lib/DemoTrust.jks -keypass DemoTrustKeyStorePassPhrase -noprompt Web Service Security Configuration for the domain is also required.  Follow the console configuration instructions here.  Then follow the instructions here to configure the identity propagation with a Token Handler.  Note that one of the steps will specify that we are using the CN attribute to map to the user name in LDAP. If you have not already done so, create a user. Server-side JWS Programming In order to require authentication on a web service, you need only specify a policy via an annotation in the JWS file.  WLS ships with a policy inside the weblogic.jar file known as Auth.xml (as well as Sign.xml and Encrypt.xml which are explained in the earlier article I mentioned).  Here is a simple JWS file that shows how to attach that policy.  This will require all users calling the time operation to be authenticated.  Use the context object to retrieve the identity principal used to validate that we are indeed using an authenticated user. package com.bea.sample.webservice; import java.util.Date; import javax.jws.WebMethod;import javax.jws.WebService; import weblogic.jws.Context;import weblogic.jws.Policies;import weblogic.jws.Policy;import weblogic.wsee.jws.JwsContext; @WebServicepublic class Auth { @Contextprivate JwsContext ctx; @WebMethod @Policies({ @Policy(uri = "policy:Auth.xml", direction=Policy.Direction.inbound )})public String time() {return "User " + ctx.getCallerPrincipal() + " " + (new Date().toString()); }} Client-side JAX-RPC Programming The normal way to generate JAX-RPC clients provided by BEA is to use clientgen.  In this case we need to add a special parameter generatePolicyMethods="true" to indicate that policy is being used and generate extra methods on the stubs that are created.  Here is the snippet from the build.xml file for ant that generates the client code. <target name="run-clientgen" depends="clean"> <taskdef name="clientgen" classname="weblogic.wsee.tools.anttasks.ClientGenTask" classpathref="

This was originally posted on my dev2dev blog April 29th, 2008. One of my customers is considering a web services interface for exchanging information with their clients.  Security is a very important...

Playing with Workshop and the Dojo Ajax Framework

This was originally posted on my dev2dev blog March 23rd, 2008.  After posting it, I discovered and it was also reported by others that IE had trouble with the code-as-is.  I have not revisited this yet. I have been Inspired by the recent article by Gary Horen called "Ajax programming with BEA Workshop" and the numerous blogs from Skip Sauls that have touched on JSON and Firefox plug-ins like Firebug and YSlow.  I decided to try using what I perceive to be the most popular javascript framework, Dojo, to solve a relatively simple requirement from one of my customers to populate the options of a select drop-down based on the selection of another drop-down without refreshing the page.  For example, the options in the City drop-down will be populated based on the user's selection of an option in the State drop-down.  Here's a look at the finished example. The State drop-down is the only one available, the City and the Submit button are disabled. This is not a normal html select, it is a Dijit FilteringSelect that has enhanced capabilities, such as type-ahead, and the user selects a state. Once a state is selected, the list of cities is populated and is now enabled. Once a user selects a city, the submit button is now enabled.  This has all happened without a screen refresh and provides a better user experience. The Tools BEA Workshop 10.2 Aptana Studio - Set of javascript plug-ins for Eclipse that among other things help with Javascript debugging Firefox 2 Firebug - Great Firefox plug-in for debugging client side issues Dojo 1.0.2 Getting Started The Workshop 10.2 projects used for this example (minus Dojo) are available here.  Import the projects, extract Dojo 1.0.2 to the WebContent folder of the DynamicSelectWEB project and deploy the DynamicSelectEAR project to a server to get it up and running.  This includes a city / state web service in the CitiesStatesWEB project that returns the city and state information.  The ServiceControl in the DyanmicSelectWEB project is assuming that web service is deployed to localhost and port 7001, so make sure to adjust that if your server settings are different. I could have tried using IceFaces, an Ajax-enabled JSF framework, but I think it's important to get the fundamentals down before adding additional layers of complexity.  So my first recommendation is to start simple with plain HTML and JSON files.  Once you get the basics going, then add in the dynamic pieces (JSPs, etc). The Dojo documentation has some excellent basic examples in the "Book of Dojo 1.0".  After reading the of the form basics, particularly the FilteringSelect example, I figured out the basic framework.  Each FilteringSelect object has an attribute called a "store" that is responsible for holding data for the options.  You can populate the store programmaticly in javascript, by invoking a URL that returns JSON, etc.  The example uses a static states.txt file that shows what the JSON looks like and I use that as a basis for my purposes.  It is easy to take the JSON response and create a new dojo.data.ItemFileReadStore and set the "store" value of the FilteringSelect to that new value without any complex parsing.  I use the same json.jsp for populating both the cities and the states; and the action code in the pageflow just populates some lists for that jsp that can be reused to populate any select-based Dojo element. Here's a look at how easy Dojo makes it to wire up events to javascript functions.  This onLoad function gets called when the page loads via some javascript on the body tag.  The "states", "cities", and "myButton" references are the id's of the DOM objects.  "onChange" and "onClick" are the names of the events to register.   "onchange_states", "onchange_cities", and "button_click" are the names of javascript functions to call respectively when those events occur. function onLoad() {var states = dijit.byId("states"); dojo.connect(states, "onChange", "onchange_states");var cities = dijit.byId("cities"); dojo.connect(cities, "onChange", "onchange_cities");var button = dijit.byId("myButton"); dojo.connect(button, "onClick", "button_click");}Since Workshop has very nice Apache Beehive pageflow tooling, I just prototyped using that framework.  Below is a look at my site-map.  You can see how I started with a test.html file.  Once I got that working, then I migrated the code over to the index.jsp and added in the dynamic elements.  Each drop-down onChange calls a different pageflow action, that return dynamic JSON.  You can see that in the getCities action, I'm passing the entire form.  This way I can pull out the value of the selected state and only return the cities for that state. GotchasTake note of this css code that the FilteringSelect requires to display properly.  I had to use this approach instead of the @import example used on the Dojo site due to an issue in one of the Eclipse plug-ins that caused a hang consistently.<link rel="stylesheet" type="text/css" href="

This was originally posted on my dev2dev blog March 23rd, 2008.  After posting it, I discovered and it was also reported by others that IE had trouble with the code-as-is.  I have not revisited this...

Scala Development with Eclipse and WebLogic

This was originally posted on my dev2dev blog February 6th, 2008. At the end of my previous post about the hype/buzz for alternative programming languages I promised an entry on my experimenting with Scala in WebLogic.  I have only spent a few hours of weekend time playing around, so I can't say much yet, but I'll document some of my first impressions and experiences in this post.  This is not meant to be a post on learning Scala,  For that I recommend an excellent podcast from Bill Venners that goes into great detail about Scala and why you might use it.  I highly recommend it, it is well-worth the listen.  If you prefer reading, then start with The busy Java developer's guide to Scala: Functional programming for the object oriented.  This is a post that documents my experience of using Scala with tooling and an application server familiar to java developers, namely Eclipse and WebLogic Server. Prequisites Download Eclipse 3.3 / WTP 2.0.1.  I used wtp-all-in-one-sdk-R-2.0.1.  Workshop 10.0/10.1 are still based on Eclipse 3.2, so they won't work with the Scala Plugin for Eclipse, which requires 3.3. In order to easily deploy code to WLS, use Eclipse Update to install WebLogic Server Tools, I used version 1.1.2 from update site https://dev2devclub.bea.com/updates/wls-tools/europa/ Use Eclipse Update to install the Scala Plugin for Eclipse.  I used version 2.6.5 from update site http://www.scala-lang.org/downloads/scala-plugin/ Obligatory HelloWorld After restarting Eclipse because of the new plug-ins, I didn't have to set any paths to configure the Scala Plugin as the set of 5 scala plugins installed include the Scala SDK.  Simply follow the instructions at the bottom of the Scala Plugin for Eclipse page to create your first HelloWorld application to make sure that everything is wired up correctly.  I did not encounter a single snag with HelloWorld at all and my console printed "HelloWorld" in no time flat. Interoperability with Java The scalac compiler takes .scala files and builds .class files that have a dependency on the scala-library.jar.  Go check out the bin directory in the Resource perspective and see for yourself.  Therefore, the only thing you need to invoke and run them from java is to have the .class files and the scala-library.jar on your classpath.  The converse is also true; Scala objects can just as easily invoke java objects by including them on the scala classpath. Now this is where the developer experience is not quite ideal with respect to the packaging scala artifacts to be used easily in Dynamic Web Projects for iterative development with WebLogic Server.  First of all, I could not find a non-custom way of exporting the Scala .class files into a jar file.  In order to package up my Scala Project into a jar with the IDE I had to: Right click on the project -> Export... -> General -> Archive File -> and select appropriate values as shown in multiple places. Is this really that big of a deal?  Well, it depends on how you use your IDE to develop.  In the normal process of doing Java web development in the IDE, I find it convenient to have a project with Java code, say a Utility project, which is automatically included in your Dynamic Web Project's classpath and packaged up in the EAR as a jar when I do an export or a deployment.  It doesn't appear that such a nice arrangement is possible using the default tooling.  Of course you can always create a custom ant builder yourself and attach this to your project's build activity, but there is some work involved.  Certainly this will be addressed as the Scala Plugin for Eclipse matures. Trying out some various alternatives, I was able to modify the .project xml file for the Scala project and add a Java nature and a java builder so that both .java source and .scala source were compiled into the same bin directory.  This seemed a little fragile and the build order had to be just right in order for both sets of .class files to be in the bin directory after the build.  I suspect that when the build order was reversed that the bin directory was being cleaned by one of the builders.  Here is the .project file if you feel like taking this approach. <?xml version="1.0" encoding="UTF-8"?><projectDescription><name>ScalaExamples</name><comment></comment><projects></projects><buildSpec><buildCommand><name>org.eclipse.jdt.core.javabuilder</name><arguments></arguments></buildCommand><buildCommand><name>ch.epfl.lamp.sdt.core.scalabuilder</name><arguments></arguments></buildCommand></buildSpec><natures><nature>ch.epfl.lamp.sdt.core.scalanature</nature><nature>org.eclipse.jdt.core.javanature</nature></natures></projectDescription> Mix Scala with a Dynamic Web ApplicationAfter deciding not to spend more time on the packaging issues I moved on to another basic concept, simply calling a Scala object from a JSP.  In this case there is a suitable example addressbook.scala on the Scala site that spits out an addressbook in Xhtml.  This example also showcases one of the Scala languages handy features of native XML support.  Check out the source.  In order to invoke this quickly from a JSP, I moved it to a package called examples and created a new function named toXhtml to the AddressBook class to return the Xhtml string since the example was meant to be called from a main method and needed the function to be callable from the JSP.def toXhtml(): String = page.toStringHere is the index.jsp<%@page import="examples.addressbook"%><%= addressbook.toXhtml() %>The steps are:Package the addressbook classes in a jar and place into WEB-INF/lib Copy the scala-library.jar into WEB-INF/lib (get this from the Scala SDK or from your plugin, mine is here: D:\eclipse3.3\eclipse\plugins\ch.epfl.lamp.sdt.compiler_2.6.9.RC412860\lib) Create the JSP Deploy to a server and invoke the jsp Here is the end result: SummaryThere is nothing really WebLogic Server specific to this, I could have just as easily deployed this to Tomcat., or WebLogic Event Server.  The point is that Scala actually is fairly easy to integrate into both tools and runtimes that most java developers will already be familiar with.  If you have thoughts on Scala, better integration with java IDE's, etc, drop a comment.

This was originally posted on my dev2dev blog February 6th, 2008. At the end of my previous post about the hype/buzz for alternative programming languages I promised an entry on my experimenting with S...

Paparazzi for Programming Languages

This was originally posted on my dev2dev blog February 4th, 2008. Have you noticed that there is a growing buzz about alternative programming languages in the blogosphere and online technical journals?  Is this simply just US-Weekly for technology selling the latest Brangelina gossip that will be forgotten next week or is there really a coming revolution to get out in front of or even catch up with? The Old Standbys PHP and Perl have been popular Internet languages for some time and there is a history of using these languages in conjunction with the WebLogic Server (See WLS information about PHP, ColdFusion, and CGI).   Even JavaScript  / ECMAScript is getting integrated into the JVM in Java 6. The New Popular Kids Lately a newer set of languages have been getting all the attention in both the Java world and the .NET world.  Of course you've heard about Ruby and Ruby on Rails unless you've been under a rock.  Java has responded with it's own scripting language, Groovy and rails like framework called Grails.  Presumably Groovy and Grails would be more applicable to enterprise developers because of Java roots and higher likelihood of being accessible to Java developers to learn quickly.  Secondly, because Groovy is interoperable with existing java code, it can run on your corporate application server standard, which is of the utmost importance for enterprise adoption.  There is also JRuby; so you can mix Java and Ruby and not have to give up WLS container provided services and all of those plentiful java API's you have lying around from existing applications, frameworks, and packaged applications.  Not to be left-out, functional programming fans have also have a reason to get excited with Scala and F#, which combine elements of OO languages with functional principles.  Even ERLang is getting some hype.  Why all the buzz and what to do about it? The rationale to use these alternate languages seems to vary, but the most substantive reasons seem to center around brevity, clarity (see the Fibonacci examples), and that they are better for taking advantage of concurrent programming on the growing number of multi-core architectures.  So as an enterprise Java developer and WebLogic Server user how are you to know which of these technologies is the most relevant?  In my humble opinion, it's too early to declare definitive winners.  I don't think that brevity alone can be responsible for a seismic shift.  I am personally more swayed by the multi-core / concurrent programming arguments, but I don't feel the urgency immediately.  I think these are technologies to monitor and dip your toe in, but not necessarily to dive all the way in unless you have an edge case that is in the sweet spot in one of the languages. I am definitely bullish on the value of the application server and the rock-solid foundation provided by WebLogic Server.  I feel that the new languages that will have the best synergy with existing Java assets will have the highest likelihood of success.  I've spent a limited amount of time playing with Scala this weekend and deployed an example in WLS.  Look for my write-up on this in an upcoming entry if you want to hear about my experiences.  If you have an opinion on future programming language adoption in the enterprise, please leave a comment.

This was originally posted on my dev2dev blog February 4th, 2008. Have you noticed that there is a growing buzz about alternative programming languages in the blogosphere and online technical journals? ...

Workshop, JPA, and DataSources

This was originally posted on my dev2dev blog January 25th, 2008.  BEA Workshop components are soon to be rebranded as the Oracle Eclipse Pack. One of my customers is evaluating JPA as a persistence framework for a new project and using Workshop 10.1 for development and WebLogic Server 10.0 MP1 for a target runtime.  They had some trouble figuring out how to configure JPA to use WebLogic managed DataSources instead of using a direct OpenJPA managed connection.  In this entry, I'll illustrate how to specify JNDI DataSources in persistence.xml. Default behavior is direct connection In Workshop 10.1, when you right click on a table in DbXplorer and select "Generate JPA Mapping...", and target a Web project with JPA facets, Workshop will add the connection information from DbXplorer to the persistence.xml file that uses the direction connection method.  Here's an example of the output for one class called Supplier.  Notice that the direct connection is used and the password is embedded in the file.  This might be ok for development, but this might raise some eyebrows if left unchecked for production. <?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://java.sun.com/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"version="1.0"><persistence-unit name="pu"><class>com.test.supplier.jpa.Supplier</class><properties><property name="openjpa.TransactionMode" value="local"/><property name="openjpa.ConnectionDriverName" value="oracle.jdbc.driver.OracleDriver"/><property name="openjpa.ConnectionURL" value="jdbc:oracle:thin:@localhost:1521:XE"/><property name="openjpa.ConnectionUserName" value="weblogic"/><property name="openjpa.ConnectionPassword" value="weblogic"/><property name="openjpa.jdbc.Schema" value="WEBLOGIC"/></properties></persistence-unit></persistence>Best practice - use container managed DataSourcesInstead of managing all of database connections separately in each application, it is a best practice to use container managed DataSources that are shared among applications.  Here are two data-sources I have configured in the WLS console. Using DataSources also has the added benefit of not requiring developers to have access to the database attributes, specifically the password.  It turns out that the Workshop 10.1 JPA plug-in does not directly support specifying the JNDI name of the WebLogic DataSource in the GUI.  Looking at the persistence XSD file or trying a code-completion in the persistence.xml file will show you that the persistent-unit element has a child element named jta-data-source that can be used for specifying the JNDI name.  In fact, there is a second element as well, non-jta-data-source, which is also required if you want transactions to work properly with XA compliant DataSources.  The OpenJPA documentation user-guide does an excellent job explaining this.Watch your stepThis is where I got tripped up.  Unfortunately, there is a bug in Eclipse WTP which prevents the XML Validator from working properly in Web projects.  Therefore, unless you are careful, you can accidentally place the DataSource elements in the incorrect place.  Code-completion still works in the xml document, but it does not prevent you from making a mistake.  In my case, I put the jta-data-source element after the class element.  This results in an error at runtime such as: persistence.xml [Location: Line: 8, C: 20]: org.xml.sax.SAXParseException: cvc-complex-type.2.4.a: Invalid content was found starting with element 'jta-data-source'. One of '{"http://java.sun.com/xml/ns/persistence":class, "http://java.sun.com/xml/ns/persistence":exclude-unlisted-classes, "http://java.sun.com/xml/ns/persistence":properties}' is expected.Once I put the data-source elements in the valid location, everything worked great at runtime (thank you Pinaki!).  Here is an example of a persistence.xml file that uses the two DataSources correctly and complies with the XSD.<?xml version="1.0" encoding="UTF-8"?><persistence xmlns="http://java.sun.com/xml/ns/persistence"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"version="1.0"><persistence-unit name="pu"><jta-data-source>OracleXADataSource</jta-data-source><non-jta-data-source>OracleDataSource</non-jta-data-source><class>com.test.supplier.jpa.Supplier</class><properties><property name="openjpa.jdbc.DBDictionary" value="oracle(DriverVendor=oracle)" /></properties></persistence-unit></persistence>ConclusionHopefully the JPA tooling in Workshop will incorporate the JNDI data-source connection in a future release and incorporate a fix for validating xml files in Web projects.  For more JPA blog entries, I highly encourage Pinaki's blog.  He's got lots of great JPA stuff.

This was originally posted on my dev2dev blog January 25th, 2008.  BEA Workshop components are soon to be rebranded as the Oracle Eclipse Pack. One of my customers is evaluating JPA as a persistence...

Hermes JMS - Open Source JMS Console

This was originally posted on my dev2dev blog January 2nd, 2008. The WebLogic Server Administration Console provides the ability to monitor and view JMS messages from 9.x onwards.  However it is a web-based tool that is optimized for configuration, not monitoring and development testing.  Looking at the contents of multiple messages requires multiple screen refreshes and it can not do some advanced JMS activities like copy messages from one queue to another very easily.  Hermes JMS is a handy open source project hosted by Sourceforge and built by Colin Crist that can be used to monitor, inspect, and interact with JMS Queues, Topics, and Messages.  Here's how Colin describes it on the website: HermesJMS is an extensible console that helps you interact with JMS providers making it easy to browse or search queues and topics, copy messages around and delete them. It fully integrates with JNDI letting you discover administered objects stored, create JMS sessions from the connection factories and use any destinations found. Many providers include a plugin that uses the native API to do non-JMS things like getting queue depths (and other statistics) or finding queue and topic names. It works with many of the popular JMS providers such as Active MQ, Arjuna MQ, Tibco EMS, Fiorano MQ, JBoss MQ, JORAM, OpenJMS, Oracle, Pramati, SAP, SeeBeyond ICAN, SeeBeyond JCAPS, Sonic MQ, WebLogic JMS, WebMethods, and WebSphere MQ. This post will explain how to get Hermes installed and configured for use with WebLogic JMS.  If you would like to see the setup with WebLogic as a web recording, go here, otherwise read on for the step-by-step.  If you work in the financial vertical, Hermes also has some capabilities with FIX messages that are worth checking out. Quick setup To install, get the installer from sourceforge and run “java –jar hermes-installer-1.12.jar” in the directory where you have placed the installer jar. Open the <HERMES_HOME>/bin/hermes.bat or hermes.sh in your favorite editor. Add the path to your WLS JVM at the beginning of the file right after the REM comments.  Note: When I tested with the WLS 10.3 Tech Preview, I had to use the Java 6 JVM that shipped with the tech preview, so if you run into issues in the "discovery" phase, be sure to use the same JVM with Hermes as the WLS JVM you want to connect to. set PATH=D:\bea922\jdk150_10\jre\bin set JAVA_HOME=D:\bea922\jdk150_10\jre Launch Hermes by calling the hermes.bat Right click on “sessions” and select “new -> New session…”. On the resulting prompt, go to the “providers” tab at the bottom and add a “group” called “weblogic92” and a “library” specifying your path to weblogic.jar. Select “Don’t Scan” when prompted. No go back to the “Sessions” tab. Enter a name for the session, in this case “examplesQCF”. In the “Connection Factory” section, select “weblogic92” for the loader (you may have to save and then edit the session to see the provider you just configured in the drop down for loader). Then select “BEA WebLogic” for the “Plug In” dropdown. Then add the properties as in the image below select “OK”. Right click on the newly created “examplesQCF” session and select Discover. It should find all of the available destinations and list them under the examplesQCF session. If you right click on the exampleQueue node under the session and select “Browse”, you should be able to see the contents of the queue. I have populated my exampleQueue with 3 messages. The first of which has a message payload of “Test Message”. Notice the headers are also displayed. Hermes can monitor multiple queues at once, auto-refresh, use selectors, delete messages, etc. Check out the user guide at http://www.hermesjms.com for more information and tutorials. Comments from dev2dev entry: ekhaskel, I haven't used the FIX and Hermes together myself, I'd encourage you to try the forums at hermesjms.org or reach out to Colin directly. james Posted by: jbayer on February 11, 2008 at 8:06 AM Hi, I downloaded this utility to try to analize FIX log. It looks very nice and powerful, but I didn't find how I may sort all messages by time. Now I can see all incoming messages first and all outgoing messages after this. It's very uncomfortable to analize log file by this way. Is it possible to see all messages sorted by time, so it will be possible to see server's answer to each request. Please advice. Regards Posted by: ekhaskel on February 9, 2008 at 3:05 PM Hi James, I've updated the WLS page with a link to here. The other way to do this - one that may also seem more familiar to many - is to create a context, browse it and then select the connection factory to use as the basis for a session. This JBoss tutorial shows you what I mean. Regards, Colin. Posted by: colincrist on January 10, 2008 at 5:20 AM

This was originally posted on my dev2dev blog January 2nd, 2008. The WebLogic Server Administration Console provides the ability to monitor and view JMS messages from 9.x onwards.  However it is a...

Using Workshop 10.1 with WebLogic Server 10.0 MP1

This was originally posted on my dev2dev blog December 21st, 2007 but should now be considered obsolete now that Workshop 10.2 is released and the Oracle Eclipse Pack will be released soon. Background Workshop for WebLogic 10.1 ships with WebLogic Server 10.0 GA bundled in the installer.  Since that time BEA has released Maintenance Pack 1 for WLS 10.0.  So when one of my customers was getting started with developing on WebLogic Server 10.0, I recommended that they start with Server 10.0 MP1 because it has about 7 months worth of bug fixes that the 10.0 GA bits don't have.  Now this customer also wanted to take advantage of all of the great features that first showed up in Workshop 10.1, such as JSF, JPA, Hibernate, Struts, Spring, Beehive tooling all nicely assembled in Eclipse.  After talking with Workshop product management, I realized that there are no plans to update the Workshop 10.1 installer to include the WebLogic Server 10.0 MP1 bits.  You can still use Workshop 10.1 to deploy to Server 10.0 MP1, but there are some caveats. Expectation:  I should just be able to update the WebLogic Server 10.0 GA instance to MP1 by using SmartUpdate.  Theoretically yes, but not in this case.  The WebLogic Server 10.0 GA bits that are included with the default Workshop 10.1 installation are there just to support Workshop and are not able to be upgraded because Workshop 10.1 has not been updated itself for MP1. Disclaimer:  Note that this configuration (deploying from Workshop 10.1 to Server 10.0 MP1) has not been explicitly tested by our support teams.  I've found most use-cases work just fine.  I've noted several gotchas below, but be aware that this has not gone through an extensive QA. The installation steps Workshop 10.1 Installer Choose the "complete" installation. *Updated 12/21/07* Do not choose the custom installation!  Choose "Complete".  It turns out that Workshop 10.1 does have dependences on the Server 10.0 GA bits, so it's best to leave the defaults selected and install both Workshop 10.1 and Server 10.0 GA into the same BEA Home.  You can still install Server 10.0 MP1 into a different BEA Home without its Workshop 10.0 MP1 components as I show further below.  One of the things that will not work if Workshop 10.1 is installed without Server 10.0 GA in its BEA Home is deploying an application with EJBs to WebLogic Server from Workshop.  Reference CR356168 with BEA Support if you encounter troubles in this regard.   Now install Server 10.0 MP1 into a new BEA_HOME directory. Select the custom installation, and make sure you install into a separate BEA_HOME directory from Workshop 10.1. Deselect the Workshop 10.0 components if you do not plan on using Workshop 10.0 MP1, but it doesn't harm anything other than take up disk space if you leave it selected. Post-installation Configuration At this point, I recommend changing the default JVM that Workshop will use to be the more recent Sun JDK that ships with Server 10 MP1.  I'll address this later, but it follows from the infamous serialVersionUID bug that has been around in the Sun JVM for awhile.  Open Workshop's ini file (mine is D:\Workshop10.1\workshop_10.1\workshop4WP\workshop4WP.ini) and point it to the updated JDK. Before: -vmD:/Workshop10.1/jdk150_06/jre/bin/javaw.exeetc, etc.After:-vmD:/bea100MP1/jdk150_11/jre/bin/javaw.exeetc, etc.Now you'll have both Workshop 10.1 and Server 10 MP1 installed on your machine, the next step is to configure Workshop 10.1 so that it is aware of the Server 10 runtime.  Go ahead and open a workspace and select Window->Preferences...->Server->Installed Runtimes.  Delete the existing 10.0 GA runtime and add the runtime for WebLogic Server 10 MP1.  Normally I wouldn't have to do this step, but since we installed Workshop and Server separately we have to tell Workshop where to find Server and where the correct library modules are located. After we set that we should see that WebLogic->J2EE Libraries is now populated with the 10.0 MP1 libraries:Note:  If you did not delete the 10.0 GA runtime, you'll see multiple copies of the libraries.  They are actually unique, which you can tell by highlighting one, clicking the edit button and noting that the implementation version is different, even though the specification version is the same. Now we're all set to develop and deploy as normal.  If you forgot to switch your JVM to the version that ships with WLS 10 MP1, which is jdk150_11, you will probably encounter the serialVersionUID error when you work with Beehive Service Controls.  Here is a a look at what that stack might look like, so you know to switch the JVM, delete your types-jar file from WEB-INF/lib, rebuild your controls in Workshop and then redeploy if you encounter it.<Dec 14, 2007 1:26:32 PM CST> <Error> <com.bea.control.servicecontrol.util.memento.ServiceClassMementoUtil> <BEA-000000> <com.bea.control.servicecontrol.util.memento.ServiceClassMementoUtil: Could not load the ServiceClassMemento from the following resource file: control/EchoServiceControlServiceClassMemento.ser.This is probably due to a versioning issue and if the developer was astute when they made the change then this should not be the reason. Another possibility is that this resource has become corrupt. The good news is a rebuild of your app should fix it.Throwable: java.io.InvalidClassException: javax.xml.namespace.QName; local class incompatible: stream classdesc serialVersionUID = 4418622981026545151, local class serialVersionUID = -9120448754896609940Stack Trace:java.io.InvalidClassException: javax.xml.namespace.QName; local class incompatible: stream classdesc serialVersionUID = 4418622981026545151, local class serialVersionUID = -9120448754896609940 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:546)

This was originally posted on my dev2dev blog December 21st, 2007 but should now be considered obsolete now that Workshop 10.2 is released and the Oracle Eclipse Pack will be released soon. Background Wo...

Using LDAP as a user-store for WebLogic Administrators

This was originally posted on my dev2dev blog December 13th, 2007.   Edited on 11/19/2008 based on feedback from a customer to add clarity for control flags in the authentication providers. One of my customers that has hundreds of WLS instances recently asked me about moving towards a centralized model for managing WebLogic Administrators.  Currently they use the file-based out-of-the-box embedded LDAP that ships with WebLogic Server as an Administrator store.  This is great for getting started quickly, but it means that each instance has it's own local user store for Administrators.  Therefore, when one of their Administrators leaves the company they have to go to each server and change the Administrator password.  Now that can be a headache!  I have previously posted on how to set up WebLogic Server for use with OpenLDAP so that LDAP users can be used for authentication for web apps, etc.  In this post, I'll discuss how to extend that to WebLogic Administration, so that centralized administration of WebLogic Administrators can be enabled via external LDAP. Review the documentation for Authentication Providers E-docs has some great detail on how to configure more than one Authentication Provider and how to configure LDAP Authentication Providers, and specifically addresses the case in which LDAP is the only Authentication Provider.  One thing that is important to highlight if you go down the path of only having LDAP as the sole Authentication Provider is that it introduces a point of failure into your WebLogic Servers, meaning that if your WLS instances get network partitioned from your LDAP server(s) or your LDAP server(s) goes down, your WLS instances will not boot.  You can partially guard against this by configuring LDAP fail-over, but to keep the flexibility, you may want to keep the Default Authenticator around for emergencies and keep that user/password isolated to a master Administrator.  There are two ways to enable someone to be a WebLogic Administrator: Add the user to the Administrators group in LDAP (which is included in the Admin global role by default) Add the user to the Admin global role (you can do this by group, explicit user, etc) As it is mentioned in the docs, your LDAP may already use the Administrators group for another purpose, or you may not want to put users in that group and give them Administrator access to all the domains in your environment.  In this case, the 2nd method allows you to be much more granular and even put users in groups that might correlate to their business unit.  So I could have an HRWebLogicAdmins group in LDAP for the Human Resources department, and when I create the domains for that department, make sure I add that group to the Admin Global Role.  If that approach is taken, users may be able to use their normal LDAP user and credentials instead of a special Administrative account that is shared because their personal user has group membership to HRWebLogicAdmins.  This provides you with an additional level of auditing since you are not using shared Administrator accounts. Configure your base domain Let's put this into practice.  First let's assume were starting from scratch with no domains at all.  We'll configure LDAP with it and confirm that we can have Administrators in LDAP, then create a domain template with LDAP preconfigured so that new domains don't have to do this LDAP setup at all.  I'm going to use WLS 10 MP1 for this, but the steps should be similar in other versions of WLS.  I'm using the same OpenLDAP configuration that I discussed in my previous post, so refer to that for more detail on this setup if you need it. Create a domain - D:\bea100MP1\wlserver_10.0\common\bin\config.cmd (sh) Keep the defaults, which will have weblogic/weblogic as your Administrator. Start the AdminServer and login with weblogic/weblogic.at http://localhost:7001/console Click the "Lock & Edit" button in the console and optionally then click the "Record" button if you are in WLS 10 or higher and want to record the WLST script Add the OpenLDAP Authenticator to your realm.  Remember to set the control flag of both the Default Authenticator and your LDAP Authenticator to OPTIONAL or SUFFICENT.  If you leave the control flag setting as is for the Default Authenticator, which is REQUIRED, then any user authenticating in the realm would need to be in embedded LDAP also, which is not what we want.  Restarting the server will be required for the security changes to take effect, even if the console doesn't remind you, so don't forget that step. Review the Admin role mapping to see that it maps to the users/groups you want.  In this example, I'm assuming that the using the Adminstrators group in LDAP is okay. Here is the default mapping for all users in the Admin role.  Notice that it includes all of the users in the Adminstrators group by default.  This is where I could add other groups.  Be aware that role changes you make are stored as XACML and have to be imported/exported. Now click "Activate Changes" and notice the name of the WLST script if you did a recording and the notice that we need to restart the server for the changes to take affect since we modified the security subsystem.  At this point we can shut the server down. Now let's review my LDAP configuration.  Using JXplorer I can both view and edit my OpenLDAP configuration.  Here are the settings that work with the LDAP config from my previous post:  Note that the password is "secret". Note that I added an Administrators group and added the jbayer user as a member of that group.  To add a group, just right click on "groups" and select "New" and go through the prompts. Ok, now I should be able to boot WLS with the jbayer user and login to the console as an Administrator.  Let's try both.  First I need to update the boot.properties file that is located in the domain's <Server_Name>/security directory.  In my case, that is:  D:\bea100MP1\user_projects\domains\open_ldap_domain3\servers\AdminServer\security Opening the file shows you that the username and password are encrypted, so now we need to replace the {3DES} encrypted values with plain text ones for my jbayer user.  The next time WLS boots, it will re-encrypt these values.  Note that we can also find out the domains encrypted values ourselves by using the encryption utility: D:\bea100MP1\user_projects\domains\open_ldap_domain3\bin>setDomainEnv.cmdD:\bea100MP1\user_projects\domains\open_ldap_domain3>java weblogic.security.Encrypt jbayer{3DES}yunUy+yVmfY=D:\bea100MP1\user_projects\domains\open_ldap_domain3>java weblogic.security.Encrypt weblogic{3DES}PmZxnuL1akG6MzWSRo/g3w==Now we can boot the domain.  If there is a problem, you'll see a stack trace that mentions the security sub-system, you'll probably have to change the boot.properties file back to the original values, weblogic/weblogic if you didn't change the defaults and see if you messed up anywhere. If there is no problem and the server goes to a RUNNING state, then we have booted the server as jbayer, which is in the Admin role because that user is in the Administrators group in OpenLDAP.  Now try logging into the console and that should work as well.  Here is my screen-shot showing the successful jbayer user login as Administrator to the console. Make it repeatable with WLST or a Domain TemplateDoing all of this configuration each time you want to setup a new domain can monotonous and prone to typing mistakes.  This is where using WLST or domain templates can come in very handy.  First let's review the .py file that was created during our WLST recording as we created the OpenLDAP Authenticator.  Mine was saved to my domain's base directory with the name Script1197502551016.py.  For more on WLST see my intro to WLST post and the command reference for documentation on WLST commands.cd('/SecurityConfiguration/open_ldap_domain/Realms/myrealm')cmo.createAuthenticationProvider('openLdapAuthenticator', 'weblogic.security.providers.authentication.OpenLDAPAuthenticator')cd('/SecurityConfiguration/open_ldap_domain/Realms/myrealm/AuthenticationProviders/openLdapAuthenticator')cmo.setGroupBaseDN('ou=groups, dc=bea, dc=com')cmo.setStaticGroupObjectClass('groupOfNames')cmo.setUserBaseDN('ou=people, dc=bea, dc=com')cmo.setUserObjectClass('inetOrgPerson')cmo.setPrincipal('cn=Manager,dc=bea,dc=com')setEncrypted('Credential', 'Credential_1197503008359', 'D:/bea100MP1/user_projects/domains/open_ldap_domain/Script1197502551016Config', 'D:/bea100MP1/user_projects/domains/open_ldap_domain/Script1197502551016Secret')cmo.setStaticGroupDNsfromMemberDNFilter('(&(member=%M)(objectclass=groupOfNames))')cmo.setUserFromNameFilter('(&(cn=%u)(objectclass=inetOrgPerson))')cmo.setGroupFromNameFilter('(&(cn=%g)(objectclass=groupOfNames))')cmo.setControlFlag('SUFFICIENT')cd('/SecurityConfiguration/open_ldap_domain/Realms/myrealm/AuthenticationProviders/DefaultAuthenticator')cmo.setControlFlag('SUFFICIENT')activate()I could simply use a script like this to configure my new domains to have LDAP support after they have been created.  However, I can go one step further and use the domain that has already been configured for LDAP and create a domain template using the Domain Template Builder D:\bea100MP1\wlserver_10.0\common\bin\config_builder.cmd.  Now when I create new Domains using the Config Wizard and base it off that template, authentication to OpenLDAP will be pre-configured.  Just launch the Domain Template Wizard, point it at the domain and follow all of the defaults.  I can even configure the Admin Role here to include other groups.One Last GotchaOne big gotcha that I encountered is that the new domains that I created based off that template still had the OpenLDAP password for the manager user set to the encrypted value of the first domain in the config.xml file in the new domain's config directory.  Each domain has a unique way of encrypting it's passwords so the encrypted values cannot be exchanged between domains.  I've highlighted the incorrect value below in the credential-encrypted element.  Make sure you replace that value with new domains correct {3DES} value that you can retrieve with technique illustrated earlier: java weblogic.security.Encrypt password.  I'm investigating whether this is working as designed or not as I expected the Config Wizard to take care of that for me.  <sec:authentication-provider xsi:type="wls:open-ldap-authenticatorType"><sec:name>openLdapAuthenticator</sec:name><sec:control-flag>SUFFICIENT</sec:control-flag><wls:propagate-cause-for-login-exception>false</wls:propagate-cause-for-login-exception><wls:user-object-class>inetOrgPerson</wls:user-object-class><wls:principal>cn=Manager,dc=bea,dc=com</wls:principal><wls:user-base-dn>ou=people, dc=bea, dc=com</wls:user-base-dn><wls:credential-encrypted>{3DES}68bCeqro3EA=</wls:credential-encrypted><wls:user-from-name-filter>(&amp;(cn=%u)(objectclass=inetOrgPerson))</wls:user-from-name-filter><wls:group-base-dn>ou=groups, dc=bea, dc=com</wls:group-base-dn><wls:group-from-name-filter>(&amp;(cn=%g)(objectclass=groupOfNames))</wls:group-from-name-filter><wls:static-group-object-class>groupOfNames</wls:static-group-object-class><wls:static-group-dns-from-member-dn-filter>(&amp;(member=%M)(objectclass=groupOfNames))</wls:static-group-dns-from-member-dn-filter></sec:authentication-provider>Hopefully this illustrates how LDAP can provide a way to manage WebLogic Administration in a way that is more scalable than having individual user stores in embedded LDAP when many WLS instances are involved.

This was originally posted on my dev2dev blog December 13th, 2007.   Edited on 11/19/2008 based on feedback from a customer to add clarity for control flags in the authentication providers. One of my...

Asynchronous Servlet Article Extras - Push Events

This was originally posted on my dev2dev blog December 5th, 2007. I just finished reading Francesco Marchioni's article entitled Using Asynchronous Servlets to Deal with Hung Threads and thought that I could add some information for those that want to explore this functionality more and see a working example of a chat room built with AJAX.  This is really about implementing virtual push event to web clients.  Starting with WLS 10, there is an out-of-the-box example that ships with WebLogic Server that illustrates using the Abstract Asynchronous Servlet to build a chat room.  In effect, it uses AJAX to create an event push (via a long poll).  So now when a client sends a message to the chat room, all the clients receive the message virtually instantly without constantly polling the server for new messages.  This technique has come to be known as Comet in AJAX terminology.  To read the details of the example, just go to <BEA_HOME>/wlserver_10.0/samples/server/docs/core/index.html and expand the tree as shown below.  To run it, just follow the directions which are very straight-forward. Also check the javadoc for the AbstractAsynchrounousServlet to get more information about the API. One neat thing to do is to run the example with both Firefox and IE at the same time and see messages sent by the IE client show up immediately in the Firefox client.  I have the Firebug plug-in installed and you can see how the XmlHttpRequest (XHR) is waiting for new chat messages to come in.  If no new messages arrive in 20 seconds, the AbstractAsynchServlet times out the request.  Then the client issues a new XHR and starts the process again. I've seen some fairly neat examples and demos built with the AbstractAsynchronousServlet in WebLogic Portal such as a dash-board portlet that sends out messages and alerts.  So if you have use-cases that would benefit from having events virtually pushed to web clients, consider using this approach as it is very effective and does not tie up threads on the server.

This was originally posted on my dev2dev blog December 5th, 2007. I just finished reading Francesco Marchioni's article entitled Using Asynchronous Servlets to Deal with Hung Threads and thought that...

WebLogic Scheduling - A polling approach to implement a DB event generator for ALSB

This was originally posted on my dev2dev blog November 21st, 2007.  ALSB has been rebranded as Oracle Service Bus. Scheduling tasks for Java environments seem to come up fairly often.  Often times cron or Windows's Scheduled Tasks might be used, but that's not necessarily ideal if your application servers are spread across multiple machines because your scheduling mechanism could now have a single point of failure on that particular OS instance.  In this post, I'll review a customer situation that is well-suited for a scheduled polling solution and discuss the various options that I researched in WebLogic to implement it. The Use Case - A Database Event Generator One of my customers recently purchased AquaLogic Service Bus (ALSB) and AquaLogic Data Services Platform (ALDSP).  One of their main use cases is to be able to monitor database tables for new records.  This particular customer has an aversion to database triggers, which is probably the most common solution to this type of problem.  Therefore, we need to rely on something external to the database to detect these events.  Unfortunately, this is not an out-of-the-box feature of either ALSB or ALDSP today, although it is a feature of WebLogic Integration (WLI).  One of the options for WLI's event generator is to use a query-based polling approach, which executes a select statement that returns new records, publishes the events, and updates each record to indicate it has been processed.  It does this on a schedule.  I thought that a similar approach could be implemented fairly easily in a regular J2EE application.  For example, a session bean method called on a regular basis that we could deploy to the ALSB server since it has WLS underneath the covers.  Timer Options in WebLogic Server So the question now becomes, what mechanism can be used to schedule the invocation of the session bean on a regular basis?  A key requirement is that the solution should work well in a clustered environment such that it will fail-over to another server in a cluster, yet doesn't redundantly execute on each server in the cluster.  I searched around and came up with several options for scheduling with timers in WebLogic. EJB 2.1 Timer Service Workshop Timer Control CommonJ Timer Manager EJB 2.1 Timer Service The EJB 2.1 Timer Service is supported in WLS 9.2 and WLS 10 and initially seemed like a good solution since it is a J2EE standard.  However, upon a little more investigation I ruled it out mainly because the timer object cannot be migrated from server to server.  Of course, it can take advantage of Whole Server Migration, but that is not currently implemented at this customer, and it has additional infrastructure requirements, such as a SAN, that add complexity.  Additionally, the Timer Service is not supported with WebLogic Clustering.  There are 2 possible compromises mentioned in the documentation, but neither one of those is ideal. Workshop Timer Control This mechanism is covered very well with a nice tutorial in the documentation and is very easy to develop.  However, this approach is also not designed to operate in a cluster with support for fail-over to another managed server.  Furthermore, using web-services may not be optimal with respect to reliability for once and only once messaging. CommonJ Timer Manager The CommonJ Timer and Work Manager specification was jointly developed between BEA and IBM to address the limitations of Threads and Timers when used in a managed container.  See the main page for the specification on dev2dev or review the documentation for additional detail and examples.  The WebLogic Job Scheduler functionality is specifically designed to work in a clustered environment and therefore, provides a solution that meets the main requirements. A Simple Prototype For this post, I'll discuss a simple prototype that I created that works well in a single-server environment.  Some of the details of how the Job Scheduler works will prevent this approach from being used without modification in a clustered environment, but I'll save those details for a subsequent posting. Event Generator Components StartupServlet and web.xml The init() method registers the TimerListener with the TimerManager that is configured web.xml, which also tells this servlet to start up automatically when the application starts.  The web.xml also has some other configuration components such as the sql to execute, how often to check for new rows, the max to process at one time etc.  By putting these details in web.xml, I can easily use a Deployment Plan to change these values later without changing my code.   The Here's how easy it is to create the TimerManager in web.xml:    <resource-ref>             <res-ref-name>timer/eventGeneratorTimer</res-ref-name>             <res-type>commonj.timers.TimerManager</res-type>             <res-auth>Container</res-auth>             <res-sharing-scope>Shareable</res-sharing-scope>     </resource-ref> The TimerManager javadoc discusses this is detail. TimerListener A normal TimerManager is configured on the environment.  The TimerListener’s responsibility is to invoke the SessionBean.  In this simple prototype, I had the StartupServlet implement the TimerListener interface itself.  This aspect of the prototype will need adjustment when moving to the JobScheduler, but this illustrates the concept nicely for a prototype. SessionBean The session bean responsibility is to query the database table for events by checking a processed column on the table (or using an association table).  For each new row that is found, mark it as processed and send the row id to a jms queue, which is presumably picked up later by an ALSB proxy or some other component.  By making this transactional we can ensure once and only once behavior if we use an XA database driver and XA enabled jms connection factory. JMS Queue The queues only responsibility is to hold messages containing row ids of db events.  Admittedly, this is not as sophisticated as the WLI solution, which can contain more data about the row, but we could always add more data later if necessary. Database Table For this scenario, I created a simple SHIPMENT table in the AQUA schema of my Oracle XE database.  The PROCESSED column is what will tell the Event Generator whether this row needs to be processed or not.  Since we'll be querying on that, we'd better have that indexed as well.  The assumption here is that some other process inserts these rows, and now we want to detect shipments and do something like send out an Advance Shipment Notice via ALSB. CREATE TABLE AQUA.SHIPMENT (     SHIPMENT_ID           NUMBER(38,0) NOT NULL,     SHIPMENT_DATE         TIMESTAMP(6) DEFAULT SYSDATE,     CUST_ID            NUMBER(38,0) DEFAULT 0,     PROCESSED        NUMBER(1,0) DEFAULT 0,     PRIMARY KEY(SHIPMENT_ID) ) CREATE INDEX AQUA.PROCESSED_IDX ON AQUA.SHIPMENT(PROCESSED) try it out My project code is posted here.  I used ALSB 2.6, which runs on WebLogic Server 9.2 MP1 as my server runtime.  I used Workshop 10.1 as my IDE as it has many improvements over the Workshop 9.2.1 that ships with ALSB 2.6.  You can use my code with Workshop 9.2.1, but the Eclipse projects will not be able to be imported without Eclipse version issues, so you'll just have to use the source files if you go that route and recreate the projects manually. You'll have to setup a datasource, jms connection factory, and jms queue in the WLS console.  Since I used an ALSB, I already had a connection factory, and just setup a queue and a datasource.  Once you have these setup, you'll need to update the annotations in the DBEventGeneratorSessionBean.java so the resource references match the names you used in the console. Once you deploy the application, you see see log statements like this, with new entries every 10 seconds: <timerExpired() with period 10000> <queryForEvents()> <queryForEvents() no events to process> <timerExpired() with period 10000> <queryForEvents()> <queryForEvents() no events to process> <timerExpired() with period 10000> <queryForEvents()> <queryForEvents() no events to process> To see if the event generator works, execute some SQL like this: DELETE FROM AQUA.SHIPMENT INSERT INTO AQUA.SHIPMENT(SHIPMENT_ID) VALUES(1) INSERT INTO AQUA.SHIPMENT(SHIPMENT_ID) VALUES(2) INSERT INTO AQUA.SHIPMENT(SHIPMENT_ID) VALUES(3) INSERT INTO AQUA.SHIPMENT(SHIPMENT_ID) VALUES(4) INSERT INTO AQUA.SHIPMENT(SHIPMENT_ID) VALUES(5) INSERT INTO AQUA.SHIPMENT(SHIPMENT_ID) VALUES(6) INSERT INTO AQUA.SHIPMENT(SHIPMENT_ID) VALUES(7) INSERT INTO AQUA.SHIPMENT(SHIPMENT_ID) VALUES(8) INSERT INTO AQUA.SHIPMENT(SHIPMENT_ID) VALUES(9) INSERT INTO AQUA.SHIPMENT(SHIPMENT_ID) VALUES(10) INSERT INTO AQUA.SHIPMENT(SHIPMENT_ID) VALUES(11) Now the log should show something like this: <timerExpired() with period 10000> <queryForEvents()> <queryForEvents() found 10 rows> <queryForEvents() updates complete> <queryForEvents() jms messages sent> <timerExpired() with period 10000> <queryForEvents()> <queryForEvents() found 1 rows> <queryForEvents() updates complete> <queryForEvents() jms messages sent> <timerExpired() with period 10000> <queryForEvents()> <queryForEvents() no events to process> This illustrates that we're checking for up to 10 new records every 10 seconds.  When you go look at your JMS Queue, it should now have 11 messages , each with a SHIPMENT_ID of one of the inserts you issued.  This is the part where we'd connect an ALSB proxy to the JMS queue, which could send an email, an ASN, etc.  That's an entry for another time.

This was originally posted on my dev2dev blog November 21st, 2007.  ALSB has been rebranded as Oracle Service Bus. Scheduling tasks for Java environments seem to come up fairly often.  Often times cron ...

Automate WLS Console Tasks with WLST

This was originally posted on my dev2dev blog October 25th, 2007. I do a fair amount of shoulder-surfing at some of my customer sites.  One of the fun parts of my job is to see how different organizations (and teams within an organization) go about their jobs and what types of processes they follow.  I've noticed frequently that it is common for developers that are doing code promotions, particularly from personal workstations to shared development environments, to use the WLS console to update their applications by using the point and click approach that takes several minutes and has multiple user interactions.  Once I see this happen twice in a span of 10 minutes because of a minor bug, I quickly realize that there is an optimization opportunity to use a script for this mundane deployment task that is usually done over and over again. Script it I'm not going to provide an all-encompassing WLST (WebLogic Scripting Tool) tutorial.  There are lots of other places to get more in-depth information for that including the documentation, numerous entries from Satya Ghattu's blog and code samples.  However, I will show an quick example of how to redeploy an application with the python based scripting language that ships with WLS.  WLST can do a whole lot more than this (automate domain creation, configuration, etc), but this should open the door on the possibilities, and you can be Alice in Wonderland yourself and see how deep the rabbit hold goes.  Let's start with the individual building blocks, then put them all together. Create Building Blocks Environment Setup - Just open a command prompt and run the <DOMAIN_HOME>/bin/setDomainEnv.cmd (sh) script.  This sets up all the environment variables for you. Start WLST - Just type java weblogic.WLST Connect to the Admin Server - Just use the connect command.  To figure how to do this, just type help().  Then you see that there is help on the common options by typing help('common').  The connect operation is one of the common operations, so for help on that specific operation type help('connect').  Of course there is a full command reference published online as well.  In the most basic OOTB situation, I was able to use this syntax:  connect( 'weblogic', 'weblogic', 't3://localhost:7001') Let's assume the application hasn't been deployed yet.  So the first step is to deploy the application - deploy('PortalEAR', 'D:/TEMP/wlst/PortalEAR.ear', targets='AdminServer') Start the application - startApplication('PortalEAR') Now let's assume you're going to deploy a new version of the application.  You could use the side-by-side deployment feature, but we'll save that for another time and just get the basics down first.  First, stop the existing application - stopApplication('PortalEAR') Now undeploy it - undeploy('PortalEAR') Repeat steps 4 and 5, this time pointing to the updated .ear file. Assemble the building blocks Once that all works, chain it all together, so you can do it all from one simple script: updatePortalEAR.cmd call D:\bea921\user_projects\domains\basic_portal_domain\bin\setDomainEnv.cmdcd d:\temp\wlstjava weblogic.WLST d:\temp\wlst\updatePortalEAR.pypauseupdatePortalEAR.pyexecfile('connect.py')execfile('stop_and_undeploy.py')execfile('deploy_and_start.py')execfile('disconnect.py')connect.pyprint 'connecting to admin server....'connect( 'weblogic', 'weblogic', 't3://localhost:7001', adminServerName='AdminServer' )stop_and_undeploy.pyprint 'stopping and undeploying ....'stopApplication('PortalEAR')undeploy('PortalEAR')deploy_and_start.pyprint 'deploying....'deploy('PortalEAR', 'D:/TEMP/wlst/PortalEAR.ear', targets='AdminServer')startApplication('PortalEAR')disconnect.pyprint 'disconnecting from admin server....'disconnect()exit()Hopefully this gives you a flavor of how WLST can automate tasks.  Not only can this save time, but it also can help ensure that consistent processes are applied across environments which can help prevent human error (such as forgetting to check a checkbox in a wizard).  Happy scripting!Here's the full output from executing my updatePortalEAR.cmd:  D:\TEMP\wlst>call D:\bea921\user_projects\domains\basic_portal_domain\bin\setDomainEnv.cmdInitializing WebLogic Scripting Tool (WLST) ...Welcome to WebLogic Server Administration Scripting ShellType help() for help on available commandsconnecting to admin server....Connecting to t3://localhost:7001 with userid weblogic ...Successfully connected to Admin Server 'AdminServer' that belongs to domain 'basic_portal_domain'.Warning: An insecure protocol was used to connect to theserver. To ensure on-the-wire security, the SSL port orAdmin port should be used instead.stopping and undeploying ....Stopping application PortalEAR.<Oct 25, 2007 4:29:33 PM CDT> <Info> <J2EE Deployment SPI> <BEA-260121> <Initiating stop operation for application, PortalEAR [archive: null], to AdminServer .>.Completed the stop of Application with status completedCurrent Status of your Deployment:Deployment command type: stopDeployment State : completedDeployment Message : no messageUndeploying application PortalEAR ...<Oct 25, 2007 4:29:38 PM CDT> <Info> <J2EE Deployment SPI> <BEA-260121> <Initiating undeploy operation for application, PortalEAR [archive: null], to AdminServer .>....Completed the undeployment of Application with status completedCurrent Status of your Deployment:Deployment command type: undeployDeployment State : completedDeployment Message : no messagedeploying ....Deploying application from D:\TEMP\wlst\PortalEAR.ear to targets AdminServer (upload=false) ...<Oct 25, 2007 4:29:51 PM CDT> <Info> <J2EE Deployment SPI> <BEA-260121> <Initiating deploy operation for application, PortalEAR [archive: D:\TEMP\wlst\PortalEAR.ear], to AdminServer .>...................Completed the deployment of Application with status completedCurrent Status of your Deployment:Deployment command type: deployDeployment State : completedDeployment Message : no messageStarting application PortalEAR.<Oct 25, 2007 4:30:50 PM CDT> <Info> <J2EE Deployment SPI> <BEA-260121> <Initiating start operation for application, PortalEAR [archive: null], to AdminServer .>.Completed the start of Application with status completedCurrent Status of your Deployment:Deployment command type: startDeployment State : completedDeployment Message : no messagedisconnecting from admin server....Disconnected from weblogic server: AdminServerExiting WebLogic Scripting Tool.<Oct 25, 2007 4:30:53 PM CDT> <Warning> <JNDI> <BEA-050001> <WLContext.close() was called in a different thread than the one in which it was created.>Press any key to continue . . .

This was originally posted on my dev2dev blog October 25th, 2007. I do a fair amount of shoulder-surfing at some of my customer sites.  One of the fun parts of my job is to see how...

Changing WebLogic Annotations on the Fly (more detail)

This was originally posted on my dev2dev blog August 30th, 2007. One of my customers asked me about a common use case:  they would like to change the value of a Java annotation in their deployment artifacts at deployment time without changing the code.  This way they can avoid having separate EAR files for each environment.  Using the same EAR file is very desirable because you know what you tested in QA is the same code that you are putting into production.  I'd consider that a best practice. In this case, assume we are using Beehive Service Control to invoke a web service.  The URL of that service changes depending one each environment (dev, qa, prod).  Since Beehive is heavily annotations based  and the URL endpoint of the web service is actually put into code, how can we change that URL for the various environments without building a separate EAR file for each environment?  The solution is a combination of deployment plans (JSR-88) and a Beehive annotation override.  It turns out that Chris Hogue has already blogged this and his steps apply to 9.x and 10.x versions of WLS.  His entry is very straight-forward, but I found that the WebLogic console interface was not as intuitive as Chris's post..  So I wrote up the steps I followed to get it working.  These steps will create a plan.xml and the Beehive annotation-overrides.xml files for you,.  Once you understand the mechanisms, you could script this and apply it to other WEB-INF or META-INF files and values that might change between environments and say goodbye to multiple EAR files. Here's Chris description of the steps to follow after deploying your EAR to WLS: Now say I've deployed it to the production server. After deploying it the first time I can go into the WLS console, locate the control, and change the value through a simple form. To find it in the console, navigate to Deployments > [your application] > Deployment Plan > Resource Dependencies. Then locate your control in the "Controls" tree to find the available settings. It should look something like this: I suggest you read Chris's full entry, but I'm going to get a little more granular with the instructions. First of all you need to be in a Change Session for this to take effect. Then you have to click on the “(No value specified)” label, and it will magically turn into a text box.  That was non-intuitive hang-up number 1 for me. Enter the value, BUT DO NOT LEAVE THE TEXT BOX.  In order for your value to take effect you have to hit the <ENTER> key to submit to the server while the cursor is still in the text box.  If you put that mouse anywhere else, let's say by trying to click the “Save” button, your changes will be lost, and the screen will refresh saying that the save was successful, but the Override Value will still say "(No value specified)".  This was my non-intuitive hang-up number 2. After hitting the enter key and the page loads and shows the value you typed in, then click the “Save” button.  I must admit user error on this one, I forgot to save once.  Don't miss this step. Now can activate your changes and update the application for it to take effect. For curiosity you can browse to the directory where your deployment plan is stored (you select the directory yourself).  Your plan.xml will refer to an annotations-overrides.xml file, which you will find in the web application directory as META-INF/annotations-overrides.xml.  Here's an example of mine.  Notice the override-value where I switch to port 7001 instead of 7011.  I hope this more detailed explanation of Chris's post helps avoid the hang-ups that I encountered. <?xml version='1.0' encoding='UTF-8'?><annotation-overrides xmlns="http://www.bea.com/2004/03/wlw/external-config/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><annotated-class><annotated-class-name>test.HelloWebServiceControl</annotated-class-name><component-type>Control Extension (JCX)</component-type><annotation><annotation-class-name>com.bea.control.ServiceControl$Location</annotation-class-name><array-member><member-name>urls</member-name><member-value>http://localhost:7011/WebServiceWEB/HelloWebService</member-value><override-value>http://localhost:7001/WebServiceWEB/HelloWebService</override-value><cleartext-override-value>http://localhost:7001/WebServiceWEB/HelloWebService</cleartext-override-value></array-member></annotation></annotated-class></annotation-overrides>

This was originally posted on my dev2dev blog August 30th, 2007. One of my customers asked me about a common use case:  they would like to change the value of a Java annotation in their deployment...

Using OpenLDAP with WebLogic Server

This was originally posted on my dev2dev blog August 12th, 2007. A customer I was working with this week had some difficulty using Active Directory in conjunction with WebLogic Server Security.  I've always used the Embedded LDAP server that ships with WLS as my user and group store since most of my work is just demos and prototypes, but I thought this would be an excellent opportunity to see what it is like to configure an external LDAP provider.  Since I don't have easy access to Active Directory, I decided to use OpenLDAP.  I am an LDAP newbie and was surprised at the lack of results that I received searching on google for my LDAP 101, but I was able to piece enough information together from wikipedia and other articles to get me going. Install and configure OpenLDAP OpenLDAP is typically used on *nix systems, but my laptop runs Windows XP.  I was able to find someone that makes a Windows Distribution and I retrieved version 2.2.29.  It's very straight forward to download and install it as a Windows Service.  Similar to Apache's httpd.conf file, the sldapd.conf in the base directory is the master configuration file. I had to change two things about my file.  At the top, I added support for additional schemas based on advice on an email thread.  It seems like it is very common to use the inetOrgPerson object class based off of my limited shoulder surfing at customer sites, so I added support for that and one other one named cosine. ## See slapd.conf(5) for details on configuration options.# This file should NOT be world readable.#ucdata-path ./ucdatainclude ./schema/core.schemainclude ./schema/cosine.schemainclude ./schema/inetorgperson.schemaAt the very bottom of the sldapd.conf file, you should see a few other things to configure.database bdb#suffix "dc=my-domain,dc=com"suffix "dc=bea,dc=com"rootdn "cn=Manager,dc=bea,dc=com"# Cleartext passwords, especially for the rootdn, should# be avoid. See slappasswd(8) and slapd.conf(5) for details.# Use of strong authentication encouraged.rootpw secret# The database directory MUST exist prior to running slapd AND # should only be accessible by the slapd and slap tools.# Mode 700 recommended.directory ./data# Indices to maintainindex objectClass eqSo what this section says is that OpenLDAP will use BDB as it's database and store the information in the data directory.  These are defaults.  This was helpful to know as I messed up my database a few times playing around with various settings and could always just stop OpenLDAP, delete the data directory and start OpenLDAP to start from a clean slate.  The default suffix for entries typically follows the domain name conventions, so in this case I used bea.com where the DC stands for Domain Component.  This site has additional definitions for the other LDAP abbreviations like CN (Common Name) and SN (Sir Name).  The default for the root user name is Manager and the password defaults to secret.  Of course in a real production setting you would want to encrypt this password, but for my demo purposes, this works fine.  Now I started the Windows Service, executed a netstat command and observed that I was now listening on the LDAP port of 389 and was up and running.Add Users and GroupsWhen you first start OpenLDAP, there is no user/group structure provided, you have to add those entries yourself.  LDAP uses the LDIF format to import and export entries into LDAP.    I was able to find some examples and modify them to have a user/group structure that worked for my example purposes.  Like I said, I'm an LDAP newbie, so do not consider this a recommended structure for your enterprise, but it worked for me to store both users and groups in a very basic way.  I'll show you a tool that you can use later to do this visually, but it's helpful to know what's going on under the covers so you understand what the tool is doing.dn: dc=bea,dc=comdc: beaobjectClass: topobjectClass: domaindn: ou=people,dc=bea,dc=comou: peopleobjectClass: topobjectClass: organizationalUnitdn:cn=jbayer,ou=people,dc=bea,dc=comobjectClass:inetOrgPersoncn:jbayersn:Bayeruid:jbayeruserPassword:weblogicdn: ou=groups,dc=bea,dc=comou: groupsobjectClass: topobjectClass: organizationalUnitdn: cn=groupA,ou=groups,dc=bea,dc=comobjectClass: topobjectClass: groupOfNamescn: groupAmember: cn=jbayer,ou=people,dc=bea,dc=comAbove are the contents of a file I called base.ldif.  Here I define two organization units, people and groups.  Under people I have a user single user named jbayer and under groups I have one group named groupA, of which jbayer is a member.  To import this into OpenLDAP, I just use the ldapadd command as shown below. C:\Program Files\OpenLDAP>ldapadd.exe -f base.ldif -xv -D "cn=Manager,dc=bea,dc=com" -w secretldap_initialize( <DEFAULT> )add dc: beaadd objectClass: top domainadding new entry "dc=bea,dc=com"modify completeadd ou: peopleadd objectClass: top organizationalUnitadding new entry "ou=people,dc=bea,dc=com"modify completeadd objectClass: inetOrgPersonadd cn: jbayeradd sn: Bayeradd uid: jbayeradd userPassword: weblogicadding new entry "cn=jbayer,ou=people,dc=bea,dc=com"modify completeadd ou: groupsadd objectClass: top organizationalUnitadding new entry "ou=groups,dc=bea,dc=com"modify completeadd objectClass: top groupOfNamesadd cn: groupAadd member: cn=jbayer,ou=people,dc=bea,dc=comadding new entry "cn=groupA,ou=groups,dc=bea,dc=com"Using an LDAP BrowserSince doing all this command line stuff isn't very visual, you can also use this Java LDAP Browser to view/modify OpenLDAP entries and to validate that your entries got imported correctly.  Dowload the tool and use connection settings similar to mine shown below (click the thumbnail to get a larger view), which should result in you being able to connect and browse the tree.  You can also use this tool to add and edit entries, but I won't cover that here.  Edocs also has instructions on how you can use this same tool to browse the Embedded LDAP server that comes with WLS.  Configure WebLogic ServerBy default, WebLogic Server uses an security realm called myrealm that uses the Embedded LDAP server configured with the Default Authenticator.  In order to add OpenLDAP as a source, you have to configure an additional Authentication Provider to the realm.  Here are the steps for configuring WLS 10, although the steps are similar with other WLS versions.Login to the WLS console - my example servier is at http://localhost:7001/console  with user weblogic and password weblogic Browse to Security Realms->myrealm Click on the Providers tab Browse to the Authentication section Click the Lock and Edit button Click the new button and select OpenLDAPAuthenticator and give it a name, I chose openLDAPAuthenticator Click on the newly created Authenticator and select the Provider Specific tab I changed the following settings from the provider specific defaults based on the values I loaded in the ldif file shown earlier: Group Base DN: ou=groups,dc=bea,dc=comStatic Group Object Class: groupOfNamesUser Base DN: ou=people,dc=bea,dc=comUser Object Class: inetOrgPersonPrincipal: cn=Manager,dc=bea,dc=comHost: localhostCredential: secretConfirm Credential: secretStatic Group DNs from Member DN Filter: (&(member=%M)(objectclass=groupOfNames))User From Name Filter: (&(cn=%u)(objectclass=inetOrgPerson))Group From Name Filter: (&(cn=%g)(objectclass=groupOfNames))One Major Gotcha - Setting the Default Authenticator to something other than "Required"Now you can save and Active the session.  WebLogic Server needs to be restarted for changes in the Authenticator to take effect, but before you restart there is one other change we have to make.  Authenticators have an attribute named Control Flag.  The value is either REQUIRED, REQUISITE, SUFFICIENT, or OPTIONAL.  See the help in the console for detailed explanation of these values.  The Default Authenticator has a default value of REQUIRED that should be changed to either SUFFICIENT or OPTIONAL in order for users that are only OpenLDAP to be able to login to with the WebLogic Security Framework without also having to be in Embedded LDAP.After restarting, log back into the console, browse to your realm and select the Users and Groups tab.  You should see the user you added.  If you select a user from OpenLDAP you should be able to change their password as well as see their group membership if everything is configured properly.  Secure a web applicationYou can try it out by creating a simple web app with a security-constraint element in web.xml entry as follows that defines a role named SecuredUser and uses it to protect all resources in the web app:<security-constraint><web-resource-collection><web-resource-name>restricted</web-resource-name><url-pattern>/*</url-pattern></web-resource-collection><auth-constraint><role-name>SecuredUser</role-name></auth-constraint></security-constraint><login-config><auth-method>BASIC</auth-method><realm-name>SecuredRealm</realm-name></login-config><security-role><role-name>SecuredUser</role-name></security-role>Then in your weblogic.xml define element to add an security-role-assignment element to a specific user.<wls:security-role-assignment><wls:role-name>SecuredUser</wls:role-name> <wls:principal-name>jbayer</wls:principal-name></wls:security-role-assignment>If you would rather use LDAP groups to specify the role assignment, which is much more likely to be the case, then you would use a section like this in your weblogic.xml.<wls:security-role-assignment><wls:role-name>SecuredUser</wls:role-name><wls:externally-defined/></wls:security-role-assignment>In this case, instead of explicitly naming all of the users you want in that role in each web applications deployment descriptors which is not a very good practice for an enterprise, the role SecuredUser will be assumed to be a Global Role defined in your realm's Roles and Policies -> Global Roles.  In the console, you can assign the Global Role SecuredUser to all users with membership in groupA for example.What if you want to find out additional LDAP attributes other than users and groups and use them in your applications?  In a subsequent post I plan on showing how to use an LDAP control to do that or use the Unified User Profile feature of WebLogic Portal to automatically stuff those values in the user profile.

This was originally posted on my dev2dev blog August 12th, 2007. A customer I was working with this week had some difficulty using Active Directory in conjunction with WebLogic Server Security.  I've...

Workshop 10.1, Maps, GeoRSS, REST and more

This was originally posted on my dev2dev blog July 26th, 2007.  Workshop has been rebranded as the Oracle Enterprise Eclipse Pack. First of all I have to gush about how cool Workshop 10.1 is.  Having the split-plane WYSIWYG JSP editor integrated with all of the WebLogic plug-ins is so great, and I can use it to deploy to 8.1, 9.2, and 10 servers, which is very helpful for me as many of my customers have a little of everything still deployed.  In my last post, I gave some examples of how I did a simple Google Maps mashup with Workshop using RSS and XMLBeans.  Well, in this post I wanted to discuss my experiences extending that example to use Yahoo Maps and Microsoft Virtual Earth as well.  I also discovered the GeoRSS format and used the Yahoo Geo-coding REST API. Code share example I promised to post my code to codeshare, and now all of my code is available here as a codesample.  The basic instructions are just to download Workshop 10.1, import the zipped projects into a workspace, and deploy them to a WLS 10 server instance that has the Workshop runtime.  Once you deploy, visit http://localhost:7001/MapsWAR and check it out. So my first foray into the maps world was to see if I could come up with a simple bean that could represent locations to plot on a map, regardless of which map service I used.  Each map service has their own way of doing things, but they all have some fairly basic starting examples.  I used a pageflow form to select which map service to select, and I demonstrate how to display some hard-coded locations on each map service, reusing the same map bean. Add RSS to the mix Now, hard-coding values is not very flexible, so I also integrated a RSS feed from Picasa that has a location attribute for each of my public web albums.  Using XMLBeans, I retrieve the RSS feed, parse out the location data, populate my maps bean, and display the album locations on the selected map service.  In each case I use the map service javascript to put the locations on the map, I do not have to know the lat/long coordinates, but I have to know some particulars about each map service's javascript api. GeoRss, Yahoo Geo-coding and REST Playing around with these map services I became aware that they all support GeoRSS.  Instead of having lots of proprietary knowledge on each of the map service's javascript api, I found that using GeoRSS you only have to supply the GeoRSS file, and then let the map service take care of the details.  The hang-up with this is that now I need to know the lat/long values in order to create the GeoRSS format.  Yahoo provides a REST based geo-coding service which makes this pretty easy.  Bill Roth has previously blogged about how to use it and even submitted his own codesample to codeshare.  So I start by retrieving the RSS file from Picasa, then for each album I parse out the City and State value from the description, then I submit a request to the Yahoo service and add the lat/long result back into the RSS feed.  Now what started out as a plain RSS feed now has GeoRSS elements in it.  Be aware that if you're running this server instance on a corporate site that you may have to configure your server to use a proxy since WLS will try and access yahoo services to invoke the geo-coding service.  Here is some relevant documentation for setting a proxy server for http requests outbound from WLS for 8.1, I believe it is similar for 9.2 and 10. I found Google's map service to be the most flexible with GeoRSS because you can put any GeoRSS file in the search form and have it plot the results.  Try it out. The map services All of the map services were pretty easy to use with examples, although I found Google's to be the most intuitive.  One of the downsides of Google's service however is that the api key is tied to a domain and port.  So in this case, if you run my example on localhost:7001 the Google Maps will work just fine.  However, if you change the URL such as using 127.0.0.1:7001, you'll get a javascript popup telling you that you need a new API key for that domain,   Yahoo also requires you to get a unique application id, but it does not appear to be tied to a particular domain and port.  Surprisingly, Microsoft does not require this at all.  Google, Yahoo and Microsoft definitely have some interesting APIs that I did not explore yet such as a Yahoo Maps Flash API , Virtual Earth SDK and a whole smattering of offerings from Google.  I find that the competition between the services is good because it is forcing them to innovate quickly to offer developers compelling features.

This was originally posted on my dev2dev blog July 26th, 2007.  Workshop has been rebranded as the Oracle Enterprise Eclipse Pack. First of all I have to gush about how cool Workshop 10.1 is.  Having...

Mashup the Enterprise: an example

This was originally posted on my dev2dev blog May 31st, 2007.  Since that time Picasa albums have included a lot of Map features directly into the web application. I recently attended the Dev2Dev Tech Days session in Chicago on May 16th.  It was a very enjoyable session with a good showing of BEA developers in the Chicago area.  If you missed the session, you can always download the slides.  It got me thinking about my first mashup experience.  It seems like everyone has the obligatory Google Maps demo, so I figured why not see what it would be like to do my own with some BEA tools like Workshop.  It was pretty easy.  Here's the first pass showing my list of photo albums that is clickable and linked to the push pins on the map.  Read on if you want to see how I built it. For those of you that haven't heard of it, Picasa is a very handy image organization application for the desktop (Windows, Mac and Linux) that was acquired by Google some time ago.  I'm a big fan and use it to organize all of my digital photos.  They recently introduced a new feature that allows you to post an online version of your albums which are hosted for free by Google.  Each album has meta data, such as the location it was taken, and I thought it would be be kind of cool to show the locations of my Picasa albums on a Google Map.  Each user gets an RSS feed (here is mine) that contains all of their albums and the meta data. In order to parse the RSS feed, I used Apache XML Beans.  BEA Workshop makes it extremely easy to do XML to Java binding.  For this example, I'm using BEA Workshop 9.2 MP1, but this should work equally well in 9.2 and 10.  Workshop 8.1 also has XML Beans support, but you wouldn't be able to use the Java 5 features in your code. Create an EAR project - Pretty much just an empty container for the Web and Utility projects. Create a Dynamic Web project - in the wizard, check the checkbox to add this project to the EAR you just created. Create a Utility project - XML Beans support is enabled by default, but I added the facet for the XML Beans builder so my XSD's put in the schemas directory would auto-generate XML Beans, don't forget to associate this with the EAR as well.  In the Utility project, add this RSS 2.0 XSD to the schemas directory, and the XML Beans classes should be automatically built. JTB EDIT 6/4/07 - I forgot to mention that I cleared out the targetNamespace and xmlns at the top of the schema to avoid an issue during parsing, namely that the PicasaWeb RSS feed doesn't include the Harvard namespace, so modify the schema to look like this at the top of the file: targetNamespace="" xmlns="" In the utility project, I created a simple java bean that will be used by the JSP for retrieving the information about my albums, and a simple class to parse the RSS URL into that bean.  Here's an example of some of that quick and dirty code. 1: //http://picasaweb.google.com/data/feed/base/user/jambay?category=album&alt=rss&hl=en_US&access=public 2: URL url = new URL(sRSS_URL); 3:  4: //make the url connection and parse the results into the xml bean 5: URLConnection urlConnection = url.openConnection(); 6: urlConnection.connect(); 7:  8: //this is one of the autogenerated classes that we get for free 9: //just by dropping in the xsd to the schemas directory 10: RssDocument rssDoc = RssDocument.Factory.parse( urlConnection.getInputStream() ); 11:  12: //get the generic info about the title, number of albums, etc 13: XmlObject o = rssDoc.getRss().getChannel().getTitle(); 14: XmlCursor c = o.newCursor(); 15: title = c.getTextValue(); 16: _log.debug( c.getTextValue() ); 17:  18: List<Item> items = rssDoc.getRss().getChannel().getItemList(); 19:  20: _log.debug( "There are " + items.size() + " albums" ); 21: numberOLocations = items.size();I think you get the idea.  So now all that's left to do is to put these locations on a map.  Google has some very easy instructions on their map API.  Sign up for an API key (or just use one for localhost:7001) and start by turning their most basic example into a JSP.  Here's the beginning of mine.  Notice that I use Apache Commons for escaping java script, this is necessary for the html that pops up when clicking on the push pins. 1: <%@ page language="java" contentType="text/html;charset=UTF-8" import="org.apache.commons.lang.StringEscapeUtils, google.maps.bean.IGoogleMapsBean, google.maps.bean.PicasaRSSBean"%> 2:  3: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 4: "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 5:  6: <% 1:  2:  3: String defaultRssLink = "http://picasaweb.google.com/data/feed/base/user/jambay?category=album&alt=rss&hl=en_US&access=public"; 4: PicasaRSSBean picasaRssBean = new PicasaRSSBean(); 5:  6: String rssLink = request.getParameter( "rssLink" ); 7: if( rssLink == null || ("").equals( rssLink.trim() ) ) 8: rssLink = defaultRssLink; 9:  10: picasaRssBean.initializePicasaRSS( rssLink ); 11:  12: IGoogleMapsBean googleBean = picasaRssBean;%> 7:  8: <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml"> 9: <head> 10: <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 11: <title><% 1: = googleBean.getTitle() %></title> 12:  13: <style type="text/css"> 14: v\:* { 15: behavior:url(#default#VML); 16: } 17: </style> 18: 19: <!-- this is the localhost:7001 Google Maps API key --> 20: <script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAA71qM4JtJh0mbvp5L8wvSSBRMlDO_sAYUHpd58UCyQxfNbq8wexS4U_-xDC1v8-rYvsV4XJbSKCsGJw" 21: type="text/javascript"></script>There are some other java script functions that you'll need to do everything, I'll post the full example to codeshare,  But essentially it involves Geocoding using some Google provided js functions, which puts a push pin on the map for each location.  So in the screen shot below, when the push pin or link is clicked, the map is centered on that location and the html preview of the album shows in a balloon.  Let me know what you think.

This was originally posted on my dev2dev blog May 31st, 2007.  Since that time Picasa albums have included a lot of Map features directly into the web application. I recently attended the Dev2Dev Tech...