Saturday, February 18, 2012

JDBC Diagnosability


I'm working on an application that uses a cached ConnectionPool based on the latest Oracle JDBC driver on the WebLogic application server (version 10.3). Since the pool is not controlled by WebLogic, it is very difficult to use P6Spy or other tools to see what SQL the application is generating (I've not been able to find any way to use SQL inspection tools with the current connection configuration). SQLTrace will give statement information (including performance numbers), but will not give visibility to bind variables. Finally, if there are issues with JDBC objects on the Java side, SQLTrace is of little help.
This page offers configurable logging around JDBC operations, including bind variable visibility and column-level return value visibility. Sadly, you have to manually match up your bind variables with their respective positions in the statement, but at least bind variable values are available to you.
You'll know if you've successfully configured JDBC Diagnosability since you'll get a lot of red text appearing in the console (when using Eclipse at least) as soon as you begin to communicate with the database.
This document goes into greater detail.

Server side diagnostics

Below are the steps I took to get the debug information to print to the console. These instructions assume you are using startWebLogic.cmd to run WLS.
  1. Locate ojdbc*_g.jar in your WLS installation. There's one for JRE 5 and one for JRE6. I found these in %WLS_HOME%\wlserver_10.3\server\ext\jdbc\oracle\11g\
  2. Modify startWebLogic.cmd to place the jar at the front of the classpath:
    set CLASSPATH=C:\wls1032\wlserver_10.3\server\ext\jdbc\oracle\11g\ojdbc5_g.jar;%SAVE_CLASSPATH%
  3. Create OracleLog.properties and place it in a directory on the WLS instance. See the example at the bottom of this post. Unfortunately I've not found a good comprehensive explanation of this file, but I've thrown together something that works for console logging. Logging to a file is not working for me as of now.
  4. Modify WLS start script by adding -Doracle.jdbc.Trace=true and -Djava.util.logging.config.file=<OracleLog.properties>
    -Doracle.jdbc.Trace=true -Djava.util.logging.config.file=C:\wls1032\wlserver_10.3\server\ext\jdbc\oracle\11g\OracleLog.properties

JUnit diagnostics

If you've got a situation that you want to debug and that you can recreate using JUnits you're in a good place. Your test will typically take less time to run than any operation via the GUI and you don't need to undeploy, shut down, restart and redeploy to a server constantly.
In the Run Configurations view for your test class/method do the following:
  1. Add to VM arguments on the Arguments tab
    -Doracle.jdbc.Trace=true -Djava.util.logging.config.file=C:/wls1032/wlserver_10.3/server/ext/jdbc/oracle/11g/OracleLog.properties
  2. On the Classpath tab, click Add External JARs and locate your ojdbcX_g.jar file (where X is '5' or '6' per your JDK version), then click Up to make sure this comes before any other things in the User Entries selection
  3. Run your test using the Run Configuration you've modified.
OracleLog.properties example
# OracleLog.properties Copyright Oracle 2007

# Controls output of java.util.logging output for Oracle JDBC drivers

# See the Javadoc for OracleLog for more information.

# The OracleLog system uses the services of 
# java.util.logging.*  This file is a starting
# point for controlling that output via a properties
# file. Note that there is also a programatic interface 
# for java.util.logging which may be used as well. That
# would allow finer grained control and the ability to
# change the logging as the program runs.

# Copy this file to your runtime directory to use as a
# starting point. You should expect to change it to
# suit your needs. 

# To enable logging controlled by this file start your
# main java class with the swtiches

# -Doracle.jdbc.Trace=true 
# -Djava.util.logging.config.file=OracleLog.properties
# -Djava.util.logging.config.file=C:\wls1032\wlserver_10.3\server\ext\jdbc\oracle\11g\OracleLog.properties

# See also the file logging.properties in the jre/lib directory
# in your JDK installation and the JDK documentation.

# default file output is in user's home directory.
java.util.logging.FileHandler.pattern = C:\wls1032\wlserver_10.3\server\ext\jdbc\oracle\11g\app_jdbc.log
java.util.logging.FileHandler.limit = 500000
java.util.logging.FileHandler.count = 1
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter

# log to the console by default
handlers = java.util.logging.ConsoleHandler

# for sqlnet tracing uncomment the lines below
# oracle.jdbc.diagnostics.DemultiplexingLogHandler.pattern= jdbc_%s.trc
# oracle.jdbc.diagnostics.DemultiplexingLogHandler.formatter = java.util.logging.SimpleFormatter
# handlers = oracle.jdbc.diagnostics.DemultiplexingLogHandler

# default is to log everything generated. control what is generated below
java.util.logging.ConsoleHandler.level = ALL
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

# JDBC uses the following Levels. Levels lower than FINE produce output that
# may not be meaningful to users. Levels lower than FINER will produce very 
# large volumes of output.
# INTERNAL_ERROR  Internal Errors
# SEVERE          SQLExceptions
# WARNING         SQLWarnings and other invisible problems
# INFO            Public events such as connection attempts or RAC events
# CONFIG          SQL statements
# FINE            Public APIs
# TRACE_10        Internal events
# FINER           Internal APIs
# TRACE_20        Internal debug, sqlnet tracing (oracle.net.ns.level)
# TRACE_30        High volume internal APIs
# FINEST          High volume internal debug

# Uncomment and/or change the levels for more detail
oracle.jdbc.level = FINEST
oracle.jdbc.connector.level = FINEST
oracle.jdbc.driver.level = FINEST
oracle.jdbc.internal.level = FINEST
oracle.jdbc.oci.level = FINEST
oracle.jdbc.oracore.level = FINEST
oracle.jdbc.pool.level = FINEST
oracle.jdbc.rowset.level = FINEST
oracle.jdbc.util.level = FINEST
oracle.jdbc.xa.level = FINEST
oracle.jdbc.xa.client.level = FINEST
oracle.jpub.level = FINEST
oracle.net.ns.level = FINEST
oracle.sql.level = FINEST

Version Control with Git

Updates: 11/21/2012 

I'm now using Git with a Subversion repository at work

About all I do to interact with Subversion are git svn rebase and git svn dcommit.  The first command I use to update my local master and the second to commit to the remote Subversion repository.  We create branches for just anything but the most minor change, rebase to the local master and commit to the Subversion repo from there.


git stash

My favorite find (and one which I didn't see mentioned in my edition of Pragmatic Version Control Using Git) is git stash.  git stash lets you throw changes in a locker and brings your current branch back to the last checkout state.  I use this all of the time, but one frequent use is to quickly test whether and/or which of my local changes is causing a test to fail or online functionality to get weird.  git stash list shows all of the stashes that you have, uh, stashed.  git stash apply brings changes back from the stash.

Git UI tools

At my new shop developers are all on Macs.  Some folks use GitX and others use SourceTree, but I've found the command line is quick and easy enough.  And I prefer the Eclipse file diff functionality to the diff mechanisms of either of the aforementioned GUIs.  Since Eclipse isn't in the loop with my local Git repo, I just compare with local history if I have  a large enough change I need to diff.



From 02/18/2012

I've worked quite extensively with CVS and Subversion.  With the latter I've actually set up and administered my own repositories.  But I never read much about either VCS outside of picking through http://svnbook.red-bean.com/ when I couldn't figure out how to do something.


I've been using Git on an off for about six months for a variety of non-work projects and figured it was time to understand what I was doing so that I could properly maintain branches and tags and conduct merges.  Enter Jon Loeliger's Version Control with Git for a good (albeit somewhat old -- 2009) overview.

Turning  local repo into an authoritative remote repo
I had a local repo that I wanted to share with my labmates.  The process involved cloning my local repo to another location

$ git clone --bare ./local_repo remote_repo.git
$ zip -r remote_repo.git.zip ./*
$ mv remote_repo.git.zip /gitpub/Depot
$ unzip remote_repo.git.zip

and then modifying my local repo to point to the new remote one

$ git remote add origin "//192.168.1.1/gitpub/Depot/remote_repo.git"
$ git remote update
$ git branch -a
  * master
  remotes/origin/master


Eclipse integration
Plugins
EGit seems to work pretty well.  I'm having some issues with pulls and fetches, from my repo that used to be the authoritative one, but the command line gets me what I need.  Push and synch are fine.

Diff local with remote repository

  • Right click on the project or a specific directory/file
  • Compare With -> Branch, Tag or Reference... -> Remote Tracking -> origin/master


User stuff
Indexes
I can modify a file, run git add and then continue to modify the file.  The index will not be updated with my local version of the file until I run git add again.

What I'm not used to from other VCSs is the fact that, from the command line, I can add a file (place changes in the index) and have  a different version of the file in the local repository.  With Subversion or CVS I just think of the repository version and my working version -- there's not a 'staged' version in any index.  When I execute a commit, only the changes that are in the index are committed -- the local directory file is not committed.

Diff local with remote repository

From the command line, git diff origin/master --name-status will give you the names of the different files and not clutter up the console with the differences themselves.


Fetch versus pull
I saw a pull described as "a fetch followed by a merge".


Admin stuff
Examine object (blob, tree, etc.) content.  This output could be the contents of a file or a directory.
git cat-file -p <dir_prefix><rest_of_SHA1_for_blob>


List files/directories in an object
git ls-files -s


Other resources
Pro Git

Find DOS-style short names in Windows: dir /x

Having recently begun working on Windows 7 I was disappointed to find that MSFT still has spaces in important directories (Program Files, for instance): this is often a cause of syntax issues, usually when running *sh scripts from Cygwin.


In most cases quoting the path name works, but not always.  I've found that the short style DOS directory name works in most cases where quotes fail.


C:\>dir /x
03/17/2011  08:42 PM                25              AUTOEXEC.BAT
05/05/2011  09:33 PM    <DIR>                       bea
07/19/2010  10:37 AM               211 BOOT_G~1.INI boot_GDISK32_copy.ini
08/26/2008  06:45 AM                 0              CONFIG.SYS
12/21/2011  10:39 PM    <DIR>          DOCUME~1     Documents and Settings
07/19/2010  10:19 AM    <DIR>                       DRIVERS
03/17/2011  08:42 PM                91 GPROLO~1.BAT gprologvars.bat
07/19/2010  10:44 AM    <DIR>                       Intel
02/04/2012  08:45 AM    <DIR>          PROGRA~1     Program Files
11/10/2011  08:40 AM    <DIR>          QUARAN~1     Quarantine
10/24/2010  09:23 PM    <DIR>                       TEMP
02/16/2012  07:58 PM    <DIR>                       WINDOWS