<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-4351958588700821968</id><updated>2011-07-07T16:27:08.196-07:00</updated><category term='OSCache'/><category term='JBoss'/><category term='JMX'/><category term='profiles'/><category term='cache'/><category term='J2EE scaling'/><category term='iBatis'/><category term='monitoring'/><category term='maven2'/><category term='SVN'/><category term='OpenSymphony'/><category term='JDBC'/><category term='data sources'/><title type='text'>Jeff Hair (jshair)</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jshair.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://jshair.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jeffrey S. Hair</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://bp2.blogger.com/_blzwBE2Y-Iw/Rv1RFOuDmyI/AAAAAAAAAAM/CT1C2NIrF7E/s320/Jeff+Thumbnail.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-4351958588700821968.post-5441718458821624293</id><published>2009-12-23T17:48:00.000-08:00</published><updated>2009-12-23T17:50:12.933-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='monitoring'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><category scheme='http://www.blogger.com/atom/ns#' term='JMX'/><title type='text'>Monitoring in JBoss</title><content type='html'>While at a client site or within a testing environment, have you ever started to wonder how many users are on the application? How is your application running with regards to memory (heap size)? Are you close to using all of the database connections in the connection pool? For answers to some questions, maybe your application container provides a status (tomcat) or monitoring screen (WebLogic).&lt;br /&gt;&lt;br /&gt;To facilitate recording of these statistics when using JBoss, JBoss has included the ability to &lt;a href="http://wiki.jboss.org/wiki/JBossMonitoring"&gt;log/monitor JMX Mbean values&lt;/a&gt;. And it's not difficult to install. Once values are being logged, you no longer have to continue refreshing the JMX console to see the values updated.&lt;br /&gt;&lt;br /&gt;For installing and monitoring of your web application(s), perform the following steps:&lt;ol&gt;&lt;li&gt;Copy monitor XML files into $JBOSS/server/&lt;span style="font-style: italic;"&gt;server_name&lt;/span&gt;/deploy&lt;/li&gt;&lt;li&gt;Copy $JBOSS/docs/examples/jmx/logging-monitor/lib/logging-monitor.jar into $JBOSS/server/&lt;span style="font-style: italic;"&gt;server_name&lt;/span&gt;/lib&lt;/li&gt;&lt;li&gt;Create monitor XML files to monitor JMX MBeans (samples below)&lt;/li&gt;&lt;/ol&gt;And there you have statistics being saved in a log file...ready for you to parse and create pretty little graphs for the rest of the world to read and understand. For our deployments, we used these logs to track &amp;amp; monitor the following items. As a side affect of monitoring, you also get to see the peak usage times and potentially performance / memory related issues.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;DB connections&lt;/li&gt;&lt;ul&gt;&lt;li&gt;In use&lt;/li&gt;&lt;li&gt;Available&lt;/li&gt;&lt;li&gt;Max Connections In Use&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;JVM activity&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Heap size&lt;/li&gt;&lt;li&gt;Threads&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;For additional reading or research on monitoring within JBoss, check out the following links:&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.blogger.com/post-edit.g?blogID=4351958588700821968&amp;amp;postID=4969625338547003460#%20http://wiki.jboss.org/wiki/JBossMonitoring"&gt;JBoss Monitoring&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.onjava.com/pub/a/onjava/excerpt/jboss_dev_notebook_chap8/index.html"&gt;Managing and Monitoring JBoss&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div&gt;&lt;b&gt;DB Connection Monitoring Sample&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;Here's the XML necessary to monitor a JDBC connection pool (XML comments omitted)&lt;br /&gt;&lt;pre class="brush:xml"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE server PUBLIC&lt;br /&gt;"-//JBoss//DTD MBean Service 4.0//EN"&lt;br /&gt;"http://www.jboss.org/j2ee/dtd/jboss-service_4_0.dtd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;server&amp;gt;&lt;br /&gt;&amp;lt;mbean code="org.jboss.services.loggingmonitor.LoggingMonitor"&lt;br /&gt;      name="jboss.monitor:type=LoggingMonitor,name=MY-DSMonitor"&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;attribute name="Filename"&amp;gt;${jboss.server.home.dir}/log/my-ds.log&amp;lt;/attribute&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;attribute name="AppendToFile"&amp;gt;false&amp;lt;/attribute&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;attribute name="RolloverPeriod"&amp;gt;DAY&amp;lt;/attribute&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;attribute name="MonitorPeriod"&amp;gt;10000&amp;lt;/attribute&amp;gt;&lt;br /&gt;&lt;br /&gt;   &amp;lt;attribute name="MonitoredObjects"&amp;gt;&lt;br /&gt;      &amp;lt;configuration&amp;gt;&lt;br /&gt;         &amp;lt;monitoredmbean name="jboss.jca:name=MY-DS,service=ManagedConnectionPool"&lt;br /&gt;                         logger="jca.my-ds"&amp;gt;&lt;br /&gt;            &amp;lt;attribute&amp;gt;InUseConnectionCount&amp;lt;/attribute&amp;gt;&lt;br /&gt;            &amp;lt;attribute&amp;gt;AvailableConnectionCount&amp;lt;/attribute&amp;gt;&lt;br /&gt;            &amp;lt;attribute&amp;gt;ConnectionCreatedCount&amp;lt;/attribute&amp;gt;&lt;br /&gt;            &amp;lt;attribute&amp;gt;ConnectionDestroyedCount&amp;lt;/attribute&amp;gt;&lt;br /&gt;            &amp;lt;attribute&amp;gt;MaxConnectionsInUseCount&amp;lt;/attribute&amp;gt;&lt;br /&gt;         &amp;lt;/monitoredmbean&amp;gt;&lt;br /&gt;      &amp;lt;/configuration&amp;gt;&lt;br /&gt;   &amp;lt;/attribute&amp;gt;&lt;br /&gt;&lt;br /&gt;  &amp;lt;depends&amp;gt;jboss.jca:name=MY-DS,service=ManagedConnectionPool&amp;lt;/depends&amp;gt;&lt;br /&gt;&amp;lt;/mbean&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;/server&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4351958588700821968-5441718458821624293?l=jshair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jshair.blogspot.com/feeds/5441718458821624293/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4351958588700821968&amp;postID=5441718458821624293' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/5441718458821624293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/5441718458821624293'/><link rel='alternate' type='text/html' href='http://jshair.blogspot.com/2009/12/monitoring-in-jboss.html' title='Monitoring in JBoss'/><author><name>Jeffrey S. Hair</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://bp2.blogger.com/_blzwBE2Y-Iw/Rv1RFOuDmyI/AAAAAAAAAAM/CT1C2NIrF7E/s320/Jeff+Thumbnail.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4351958588700821968.post-6338729944173579908</id><published>2009-12-18T06:13:00.000-08:00</published><updated>2009-12-23T17:50:53.441-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iBatis'/><category scheme='http://www.blogger.com/atom/ns#' term='OSCache'/><category scheme='http://www.blogger.com/atom/ns#' term='OpenSymphony'/><category scheme='http://www.blogger.com/atom/ns#' term='cache'/><title type='text'>Utilizing OpenSymphony Caching (OSCache) with iBatis</title><content type='html'>&lt;b&gt;Background&lt;/b&gt;&lt;div&gt;My current project is ramping up to be deployed into a centrally hosted data center to be accessed by a large volume of users. In past deployments, we could expect, at most, 200-300 users to be logged into our web application. When translating that number to active users, we can expect somewhere in the range of 25 to 100 active users at any given point in time.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With deployment into a centrally hosted environment, our anticipated user base significantly increases to be approximately 1000 concurrent, active users. With this large number of users, we wanted to investigate caching frequently accessed objects.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The major area in our web application that currently utilizes caching is at the DAO level. Our DAOs are leveraging &lt;a href="http://ibatis.apache.org/java.cgi"&gt;iBatis&lt;/a&gt; and already using &lt;a href="http://ibatis.apache.org/java.cgi"&gt;iBatis&lt;/a&gt; in-memory cache implementation. Moving to a centrally hosted environment, the application will be clustered. Thus, supporting fail-over and high availability. However, using the &lt;a href="http://ibatis.apache.org/java.cgi"&gt;iBatis&lt;/a&gt; cache, we risk the possibility that users see different objects depending upon their assigned clustered instance and when the iBatis cache is refreshed. To synchronize cache flushing across the cache, we decided to investigate incorporating a distributed caching mechanism. With iBatis supporting &lt;a href="http://www.opensymphony.com/oscache/"&gt;OSCache&lt;/a&gt;, we decided to start there.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Implementation&lt;/b&gt;&lt;/div&gt;&lt;div&gt;As mentioned previously, &lt;a href="http://ibatis.apache.org/java.cgi"&gt;iBatis&lt;/a&gt; documentation refers to using &lt;a href="http://www.opensymphony.com/oscache/"&gt;OSCache&lt;/a&gt; for distributed caching within a clustered environment. Assuming you are using maven to build your project, configuring &lt;a href="http://ibatis.apache.org/java.cgi"&gt;iBatis&lt;/a&gt; to use &lt;a href="http://www.opensymphony.com/oscache/"&gt;OSCache&lt;/a&gt; is extremely easy and well documented.&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Modify the project's pom.xml to include oscache.jar (2.4) as a dependency&lt;/li&gt;&lt;li&gt;Identify and modify the sqlMap / DAO that you wish to use oscache. change cacheModel type to be "OSCACHE"&lt;/li&gt;&lt;li&gt;Optionally include an oscache.properties file on the class path. Within development or continuous integration (CI) environments, this file does not need included as default properties will be applied. Deployment in production or other test areas can include the file.&lt;/li&gt;&lt;/ol&gt; For configuration options and settings including clustering instructions, refer to &lt;a href="http://www.opensymphony.com/oscache/"&gt;OSCache&lt;/a&gt; web site. The clustering option sends a flush event that causes all caches within the cluster to be flushed. Currently, &lt;a href="http://www.opensymphony.com/oscache/"&gt;OSCache&lt;/a&gt; can be configured to send flush events via JMS or &lt;a href="http://javagroups.sourceforge.net/"&gt;JavaGroups&lt;/a&gt; (multi-cast). All of the settings are nicely documented.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.opensymphony.com/oscache/wiki/Configuration.html"&gt;http://www.opensymphony.com/oscache/wiki/Configuration.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.opensymphony.com/oscache/wiki/Clustering.html"&gt;http://www.opensymphony.com/oscache/wiki/Clustering.html&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4351958588700821968-6338729944173579908?l=jshair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jshair.blogspot.com/feeds/6338729944173579908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4351958588700821968&amp;postID=6338729944173579908' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/6338729944173579908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/6338729944173579908'/><link rel='alternate' type='text/html' href='http://jshair.blogspot.com/2009/12/utilizing-opensymphony-caching-oscache.html' title='Utilizing OpenSymphony Caching (OSCache) with iBatis'/><author><name>Jeffrey S. Hair</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://bp2.blogger.com/_blzwBE2Y-Iw/Rv1RFOuDmyI/AAAAAAAAAAM/CT1C2NIrF7E/s320/Jeff+Thumbnail.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4351958588700821968.post-7608113264301007685</id><published>2009-04-07T07:24:00.000-07:00</published><updated>2009-12-23T17:53:21.952-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SVN'/><title type='text'>Retrieving a list of changes for a release in SVN</title><content type='html'>Recently for our project, we needed to review the list of SVN commits on a branch. I'm sure there are several ways that possibly even include dates. For our purposes, we wanted to review the entire list and used the following command:&lt;br /&gt;&lt;br /&gt;svn log --stop-on-copy –v https://host/svn/project/branches/project-0.8.0902.1&lt;br /&gt;&lt;br /&gt;And sha-bam, a nice, lengthy report showing the status of the changes committed to this branch.&lt;br /&gt;&lt;br /&gt;Thanks goes to one of our many, in-house, resident SVN experts!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4351958588700821968-7608113264301007685?l=jshair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jshair.blogspot.com/feeds/7608113264301007685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4351958588700821968&amp;postID=7608113264301007685' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/7608113264301007685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/7608113264301007685'/><link rel='alternate' type='text/html' href='http://jshair.blogspot.com/2009/04/retrieving-list-of-changes-for-release.html' title='Retrieving a list of changes for a release in SVN'/><author><name>Jeffrey S. Hair</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://bp2.blogger.com/_blzwBE2Y-Iw/Rv1RFOuDmyI/AAAAAAAAAAM/CT1C2NIrF7E/s320/Jeff+Thumbnail.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4351958588700821968.post-1810342867906148797</id><published>2008-08-05T05:27:00.000-07:00</published><updated>2009-12-23T17:51:29.449-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='J2EE scaling'/><title type='text'>Having to scale a web application?</title><content type='html'>In a recent sprint planning meeting, solution owners unveiled how a new customer would be using our web application. Of course, it's a web application and, as such, needs to support many, concurrent users. Up until now, we were looking for our application to support approximately roughly 500 users; probably not concurrent, but potentially.&lt;br /&gt;&lt;br /&gt;With learning how the new client will use the application, we may blow those numbers out of the water, both overall users as well as concurrent. So, how do you program and application to support large, very large volumes of users? Will the application scale if we cluster the web application servers? Will performance decrease with more users? Can we just throw a bigger machine with more CPU &amp; memory to handle the load?&lt;br /&gt;&lt;br /&gt;I'm a big believer in the fact that scalability needs to be designed from the get-go and then monitored. While some items may not be implemented immediately due to project constraints, scalability needs to be considered from day 1 and the code watched and reviewed to ensure new designs, code, etc will not adversely affect scalability and potentially performance.&lt;br /&gt;&lt;br /&gt;Two articles were published in TSS on scaling JEE applications that "hit the nail on the head". If you're faced with having to support volumes of users, these articles are &lt;span style="font-weight:bold;"&gt;a must read&lt;/span&gt; as the writer had (has?) the opportunity to pound on application to test their ability to scale under heavy load AND to analyze why they failed or succeeded.&lt;br /&gt;&lt;br /&gt;If you're not having to program for scalability now, the articles are still an excellent read &amp; resource!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.theserverside.com/tt/articles/article.tss?track=NL-461&amp;ad=647740&amp;l=ScalingYourJavaEEApplications&amp;asrc=EM_NLN_3990095&amp;uid=2717934"&gt;Scaling Your Java EE Applications - Part 1&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.theserverside.com/tt/articles/article.tss?track=NL-461&amp;ad=647740&amp;l=ScalingYourJavaEEApplicationsPart2&amp;asrc=EM_NLN_3990096&amp;uid=2717934"&gt;Scaling Your Java EE Applications Part 2&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4351958588700821968-1810342867906148797?l=jshair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jshair.blogspot.com/feeds/1810342867906148797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4351958588700821968&amp;postID=1810342867906148797' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/1810342867906148797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/1810342867906148797'/><link rel='alternate' type='text/html' href='http://jshair.blogspot.com/2008/08/having-to-scaling-web-application.html' title='Having to scale a web application?'/><author><name>Jeffrey S. Hair</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://bp2.blogger.com/_blzwBE2Y-Iw/Rv1RFOuDmyI/AAAAAAAAAAM/CT1C2NIrF7E/s320/Jeff+Thumbnail.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4351958588700821968.post-855934789388396258</id><published>2008-07-01T11:17:00.000-07:00</published><updated>2009-12-23T17:53:49.957-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SVN'/><title type='text'>SVN Merge (Trunk to Branch)</title><content type='html'>Ever have code changes that need to be pushed into a branch? Or merged back into HEAD or the trunk?&lt;br /&gt;&lt;br /&gt;Recently (today), I had the need to merge code changes from HEAD into a newly created branch. Given the fact that my changes spanned a couple of weeks (no lectures, please, as I was on vacation :D), I could not remember all of the lines that were changed in 9 files. I didn't want to blindly copy the files into the branch as I might (shouldn't really) overwrite another developers changes.&lt;br /&gt;&lt;br /&gt;After a quick google search and a read of a &lt;a href="http://jakescruggs.blogspot.com/2008/01/svn-merge-from-trunk-to-branch.html"&gt;short blog posting&lt;/a&gt;, I had found a quick path forward. For the same reasons that caused the Jake to write a blog, I'm also writing this so that I can easily find it.&lt;br /&gt;&lt;br /&gt;I checked in my files into HEAD and got the revision number (7200). Then I changed directories to the directory of the branch and ran the following command:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  svn merge -r 7199:7200 https://phlcvs01/svn/netcds/trunk .&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you want to preview the changes, specify '--dry-run' which causes SVN to list the changes that will occur. Using '-r 7199:7200' causes subversion to only grab the differences between those revisions. Upon executing the command, 'svn stat' shows the modified files that you need to check into the branch.&lt;br /&gt;&lt;br /&gt;Simple and easy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4351958588700821968-855934789388396258?l=jshair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jshair.blogspot.com/feeds/855934789388396258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4351958588700821968&amp;postID=855934789388396258' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/855934789388396258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/855934789388396258'/><link rel='alternate' type='text/html' href='http://jshair.blogspot.com/2008/07/svn-merge-trunk-to-branch.html' title='SVN Merge (Trunk to Branch)'/><author><name>Jeffrey S. Hair</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://bp2.blogger.com/_blzwBE2Y-Iw/Rv1RFOuDmyI/AAAAAAAAAAM/CT1C2NIrF7E/s320/Jeff+Thumbnail.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4351958588700821968.post-2400105602950682395</id><published>2008-03-17T16:53:00.000-07:00</published><updated>2009-12-23T17:53:09.077-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='iBatis'/><category scheme='http://www.blogger.com/atom/ns#' term='JDBC'/><category scheme='http://www.blogger.com/atom/ns#' term='data sources'/><title type='text'>Supporting Multiple DBs using iBatis</title><content type='html'>I previously wrote about configuring multiple data sources within JBoss. When writing SQL, you may undoubtedly encounter cases where SQL is not ANSI 92 compliant. In other words, you have DB specific SQL statements. Maybe it's because of performance reasons. Maybe it's because the difference in handling sequential columns. How can you write, configure, &amp;amp; deploy the application without having specific SQL statements being handled in your Java code?&lt;br /&gt;&lt;br /&gt;We encountered this issue on our current project and created an elegant, but simple solution.&lt;br /&gt;&lt;br /&gt;Using &lt;a href="http://ibatis.apache.org/"&gt;iBatis&lt;/a&gt; for our Java to DB mapping framework, all of our SQL statements were contained within XML files. With the potential requirement to support multiple databases (SQL Server &amp;amp; at least Oracle), we wanted a way to reuse the statements that were compliant across both databases.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 1:&lt;/b&gt;&lt;br /&gt;Within the MappedStatements XML files, we appended the DB name. For example, for Oracle specific SQL, the name would be 'getSomethingData-Oracle'. If the SQL was DB neutral, we omitted the DB designation. How do we modify the app to determine the appropriate SQL for the database at runtime?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 2:&lt;/b&gt;&lt;br /&gt;Like good little programmers, we created a BaseDao class from which all concrete DAOs extended. Upon initialization of a DAO, our BaseDao class retrieved the connection meta data and determined the connected DB. Now, we know the runtime DB. But how do we choose the appropriate SQL?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 3:&lt;/b&gt;&lt;br /&gt;We modified BaseDao to extend org.springframework.orm.ibatis.support.SqlMapClientDaoSupport providing our code the ability to retrieve a MappedStatement from the XML files. This class extension gives our code the ability to check for the existence of a MappedStatement - be it DB specific or non-DB specific.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Step 4:&lt;/b&gt;&lt;br /&gt;Finally, within the concrete DAO classes, we called 'checkMappedStatement' when attempting to retrieve any MappedStatement. The BaseDao class handles retrieving the appropriate SQL for the runtime DB - be it specific or generic.&lt;br /&gt;&lt;br /&gt;The concrete DAOs would retrieve the SQL from iBatis using the following construct. If DB specific SQL existed within the MappingStatement XML files for the runtime DB, that SQL would be returned.&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;getSqlMapClientTemplate().queryForList(checkMappedStatement("getSomethingData"));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Below is our simple BaseDao class. Quite simple.&lt;br /&gt;&lt;pre class="brush:java"&gt;&lt;br /&gt;public class BaseDaoiBatis extends SqlMapClientDaoSupport {&lt;br /&gt; private static final Logger log = Logger.getLogger(BaseDaoiBatis.class);&lt;br /&gt; private String dbProduct = null;&lt;br /&gt;&lt;br /&gt; protected String checkMappedStatement(String id) {&lt;br /&gt;     MappedStatement ms;&lt;br /&gt;     String statementId = id;&lt;br /&gt;&lt;br /&gt;     try {&lt;br /&gt;         ms = ((SqlMapClientImpl) getSqlMapClient()).getMappedStatement(id + "-" + getDbProduct());&lt;br /&gt;&lt;br /&gt;         // Look for DB specific SQL. If found, return DB specific mapping id&lt;br /&gt;         if (ms != null) {&lt;br /&gt;             statementId = id + "-" + dbProduct;&lt;br /&gt;         }&lt;br /&gt;     }&lt;br /&gt;     catch (SqlMapException sme) {&lt;br /&gt;        // If not found, use default SQL mapping&lt;br /&gt;        log.debug("DB-specific SQL not found, using default SQL mapping");&lt;br /&gt;     }&lt;br /&gt;&lt;br /&gt;     return statementId;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;  private void initDbProduct() {&lt;br /&gt;      DatabaseMetaData dbMetaData;&lt;br /&gt;      Connection conn = null;&lt;br /&gt;&lt;br /&gt;      try {&lt;br /&gt;          conn = getSqlMapClientTemplate().getDataSource().getConnection();&lt;br /&gt;          dbMetaData = conn.getMetaData();&lt;br /&gt;&lt;br /&gt;          log.info("Database product name is '" + dbMetaData.getDatabaseProductName() + "'");&lt;br /&gt;&lt;br /&gt;          if (dbMetaData.getDatabaseProductName().indexOf("SQL Server") &gt; 0) {&lt;br /&gt;              dbProduct = "MSSQLServer"&lt;br /&gt;          } else if (dbMetaData.getDatabaseProductName().indexOf("Oracle") &gt; 0) {&lt;br /&gt;              dbProduct = "Oracle"&lt;br /&gt;          } else {&lt;br /&gt;              dbProduct = dbMetaData.getDatabaseProductName();&lt;br /&gt;          }&lt;br /&gt;&lt;br /&gt;          log.info("Using " + dbProduct + " XML statements...");&lt;br /&gt;      }&lt;br /&gt;      catch (Exception e) {&lt;br /&gt;          log.error("Exception occurred obtaining database information", e);&lt;br /&gt;      }&lt;br /&gt;      finally {&lt;br /&gt;          if (conn != null) {&lt;br /&gt;              try {&lt;br /&gt;                  conn.close();&lt;br /&gt;              } catch (SQLException e) {&lt;br /&gt;                  log.error("SQLException thrown when closing connection");&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4351958588700821968-2400105602950682395?l=jshair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jshair.blogspot.com/feeds/2400105602950682395/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4351958588700821968&amp;postID=2400105602950682395' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/2400105602950682395'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/2400105602950682395'/><link rel='alternate' type='text/html' href='http://jshair.blogspot.com/2007/12/supporting-multiple-dbs-using-ibatis.html' title='Supporting Multiple DBs using iBatis'/><author><name>Jeffrey S. Hair</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://bp2.blogger.com/_blzwBE2Y-Iw/Rv1RFOuDmyI/AAAAAAAAAAM/CT1C2NIrF7E/s320/Jeff+Thumbnail.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4351958588700821968.post-9146249299876471486</id><published>2007-12-12T17:40:00.000-08:00</published><updated>2009-12-23T17:51:50.587-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maven2'/><category scheme='http://www.blogger.com/atom/ns#' term='profiles'/><title type='text'>Good use of maven2 profiles</title><content type='html'>As my previous blog eluded to, I work on a project that has to support multiple databases. Having continuous integration servers is key to ensuring the quality of your software across multiple databases. We have successfully supported multiple database almost from the inception of the project. Starting with SQL Server (client mandated) and PostgreSql, we're now moving to Oracle.&lt;br /&gt;&lt;br /&gt;Our CI environment will run tests against the multiple DBs as necessary. But how can I run integration tests against the different databases, easily, to ensure my code changes work on supported DBs?&lt;br /&gt;&lt;br /&gt;Enter, maven profiles.&lt;br /&gt;&lt;br /&gt;In my development environment, I have 3 profiles declared just for this project. The first is declared with 'activeByDefault' set to true. All of the generic or common settings for my project are found in this profile. Samples of the settings include my log4j file location, web application home directories (JBoss in our case), and overall maven settings (tests on/off).&lt;br /&gt;&lt;br /&gt;The second and third profiles include information specific database information. One profile runs against SQL server and another against Oracle. Both of these profiles are activated by a specified environment variable on the maven command line.&lt;br /&gt;&lt;br /&gt;How does this help with testing? If I have a DB instance for both SQL server &amp; Oracle already set to go, I can simply run maven specifying my environment and have integration tests executed against the DB of my choice.&lt;br /&gt;&lt;br /&gt;mvn -Denv=ENV1 install&lt;br /&gt;&lt;br /&gt;vs&lt;br /&gt;&lt;br /&gt;mvn -Denv=ENV2 install&lt;br /&gt;&lt;br /&gt;It doesn't get much simpler than that!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4351958588700821968-9146249299876471486?l=jshair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jshair.blogspot.com/feeds/9146249299876471486/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4351958588700821968&amp;postID=9146249299876471486' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/9146249299876471486'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/9146249299876471486'/><link rel='alternate' type='text/html' href='http://jshair.blogspot.com/2007/12/good-use-of-maven2-profiles.html' title='Good use of maven2 profiles'/><author><name>Jeffrey S. Hair</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://bp2.blogger.com/_blzwBE2Y-Iw/Rv1RFOuDmyI/AAAAAAAAAAM/CT1C2NIrF7E/s320/Jeff+Thumbnail.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4351958588700821968.post-1679971968668401595</id><published>2007-12-07T14:58:00.000-08:00</published><updated>2009-12-23T17:52:21.177-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JDBC'/><category scheme='http://www.blogger.com/atom/ns#' term='JBoss'/><category scheme='http://www.blogger.com/atom/ns#' term='data sources'/><title type='text'>JBoss: Configuring Data Sources</title><content type='html'>Configuring data sources in JBoss is quite simple but documentation may be a little difficult to find. Hopefully, this will demonstrate HOW simple it really is.&lt;br /&gt;&lt;br /&gt;First, let's say that you have a web application (or some other application) that is expecting a data source to be present in JNDI. Maybe you have designed the application that needs to support multiple databases (kudos to you). Or maybe the application will be deployed into multiple environments and you do not want to force clients to configure the data source your way with your connection information. Whatever the reason, the data source configured within the container and handed to your application.&lt;br /&gt;&lt;br /&gt;Next comes the real easy steps. To configure the data source in jboss, you need to perform 2 steps.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Drop the JDBC driver jar file into the JBoss classpath. If you're running the 'default' server under JBoss, drop the jar file in $JBOSS_HOME/server/default/lib. JBoss will pick it when the server starts. Here are 2 links to JDBC driver jars:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://jdbc.postgresql.org/"&gt;PostgreSql&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://jtds.sourceforge.net/"&gt;SQL Server&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Oracle drivers are located under the Oracle installation directory. For 10g, look under C:\oracle\product\10.2.0\db_1\jdbc\lib.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create the data source XML file in the deploy directory. Once again, if you're running the 'default' server, create the XML file in $JBOSS_HOME/server/default/deploy. Upon startup, JBoss will load this DS file and configure the data source according to the XML file. Sample XML files for the different DBs are located in the $JBOSS_HOME/docs/examples/jca directory.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Sample Oracle DS&lt;pre&gt;&lt;br /&gt;&amp;lt;datasources&amp;gt;&lt;br /&gt;  &amp;lt;local-tx-datasource&amp;gt;&lt;br /&gt;    &amp;lt;jndi-name&amp;gt;COP-DS&amp;lt;/jndi-name&amp;gt; &lt;br /&gt;    &amp;lt;connection-url&amp;gt;jdbc:oracle:thin:@localhost:1521:ORCL&amp;lt;/connection-url&amp;gt; &lt;br /&gt;    &amp;lt;driver-class&amp;gt;oracle.jdbc.driver.OracleDriver&amp;lt;/driver-class&amp;gt; &lt;br /&gt;    &amp;lt;user-name&amp;gt;user&amp;lt;/user-name&amp;gt; &lt;br /&gt;    &amp;lt;password&amp;gt;password&amp;lt;/password&amp;gt; &lt;br /&gt;    &amp;lt;valid-connection-checker-class-name&amp;gt;org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker&amp;lt;/valid-connection-checker-class-name&amp;gt; &lt;br /&gt;    &amp;lt;exception-sorter-class-name&amp;gt;org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter&amp;lt;/exception-sorter-class-name&amp;gt; &lt;br /&gt;    &amp;lt;min-pool-size&amp;gt;2&amp;lt;/min-pool-size&amp;gt; &lt;br /&gt;    &amp;lt;max-pool-size&amp;gt;5&amp;lt;/max-pool-size&amp;gt; &lt;br /&gt;    &amp;lt;metadata&amp;gt;&lt;br /&gt;      &amp;lt;type-mapping&amp;gt;Oracle9i&amp;lt;/type-mapping&amp;gt; &lt;br /&gt;    &amp;lt;/metadata&amp;gt;&lt;br /&gt;  &amp;lt;/local-tx-datasource&amp;gt;&lt;br /&gt;&amp;lt;/datasources&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Sample SQL Server DS&lt;pre&gt;&lt;br /&gt;&amp;lt;datasources&amp;gt;&lt;br /&gt;  &amp;lt;local-tx-datasource&amp;gt;&lt;br /&gt;    &amp;lt;jndi-name&amp;gt;COP-DS&amp;lt;/jndi-name&amp;gt;&lt;br /&gt;    &amp;lt;connection-url&amp;gt;jdbc:jtds:sqlserver://localhost:1433/cop&amp;lt;/connection-url&amp;gt;&lt;br /&gt;    &amp;lt;driver-class&amp;gt;net.sourceforge.jtds.jdbc.Driver&amp;lt;/driver-class&amp;gt;&lt;br /&gt;    &amp;lt;user-name&amp;gt;affor&amp;lt;/user-name&amp;gt;&lt;br /&gt;    &amp;lt;password&amp;gt;password&amp;lt;/password&amp;gt;&lt;br /&gt;    &amp;lt;check-valid-connection-sql&amp;gt;select 1&amp;lt;/check-valid-connection-sql&amp;gt;&lt;br /&gt;    &amp;lt;min-pool-size&amp;gt;2&amp;lt;/min-pool-size&amp;gt;&lt;br /&gt;    &amp;lt;max-pool-size&amp;gt;10&amp;lt;/max-pool-size&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;metadata&amp;gt;&lt;br /&gt;       &amp;lt;type-mapping&amp;gt;MS SQLSERVER2000&amp;lt;/type-mapping&amp;gt;&lt;br /&gt;    &amp;lt;/metadata&amp;gt;&lt;br /&gt;  &amp;lt;/local-tx-datasource&amp;gt;&lt;br /&gt;&amp;lt;/datasources&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt; &lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;BEWARE:&lt;/span&gt; The data source file must be name with '-ds.xml'. That's a dash and &lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;NOT&lt;/span&gt;&lt;/span&gt; an underscore. That little character cost me a few hours of troubleshooting only to be identified by another person.&lt;br /&gt;&lt;br /&gt;For more detailed information or for other DB configurations, visit the &lt;a href="http://wiki.jboss.org/wiki/Wiki.jsp?page=ConfigDataSources"&gt;JBoss wiki on data sources&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4351958588700821968-1679971968668401595?l=jshair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jshair.blogspot.com/feeds/1679971968668401595/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4351958588700821968&amp;postID=1679971968668401595' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/1679971968668401595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/1679971968668401595'/><link rel='alternate' type='text/html' href='http://jshair.blogspot.com/2007/12/jboss-configuring-data-sources.html' title='JBoss: Configuring Data Sources'/><author><name>Jeffrey S. Hair</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://bp2.blogger.com/_blzwBE2Y-Iw/Rv1RFOuDmyI/AAAAAAAAAAM/CT1C2NIrF7E/s320/Jeff+Thumbnail.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-4351958588700821968.post-3317007222701740028</id><published>2007-09-29T19:05:00.000-07:00</published><updated>2007-09-29T19:57:36.036-07:00</updated><title type='text'>ESB diagramming</title><content type='html'>Bear with me on my first blog!&lt;br /&gt;&lt;br /&gt;On my current project, I recently found myself having to diagram the architecture of an ESB to demonstrate how applications, our own included, would connect to existing services as well as expose services for others to consume. The diagrams were for both developers and managers to understand how the ESB was going to be the 'glue' that integrates existing systems and provide the ability to make composite applications by integrating services in ways only previously imagined.&lt;br /&gt;&lt;br /&gt;Typically, I use Visio to diagram and was going to start using UML but felt that it just was too low level. Class diagrams would be way too low level giving a view into one application. Deployment diagrams are great but I don't feel they are able to depict an SOA/ESB environment very well, from a high level, showing multiple services across disparate, distributed systems.&lt;br /&gt;&lt;br /&gt;After googling, I found another &lt;a href="http://blogs.ittoolbox.com/eai/business"&gt;architect's SOA blog&lt;/a&gt; regarding &lt;a href="http://blogs.ittoolbox.com/eai/business/archives/esb-and-soa-visio-stencils-16916"&gt;ESB &amp;amp; SOA Visio Stencils.&lt;/a&gt; After trying the EAI stencils, I registered for &lt;a href="http://www.oreilly.com/catalog/esb/esb_icons.csp"&gt;Sonic's ESB Icon  and Diagram library&lt;/a&gt; stencils. Having read David Chappell's book &lt;a href="http://www.amazon.com/Enterprise-Service-Bus-David-Chappell/dp/0596006756"&gt;Enterprise Service Bus&lt;/a&gt; several years ago, the blog &amp;amp; Visio stencils re-opened some old, locked brain cells reminding me of how well the book and diagrams depict an ESB architecture. The icons are a little big but can be reduced in size (or the entire picture reduced). If you work with ESBs, in an SOA, or plan to,  this book should definitely be part of your personal library!&lt;br /&gt;&lt;br /&gt;When needing to drill down into the details of an implementation on the ESB, other diagrams may be better suited (i.e. UML, EAI, BPMN, etc).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4351958588700821968-3317007222701740028?l=jshair.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jshair.blogspot.com/feeds/3317007222701740028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=4351958588700821968&amp;postID=3317007222701740028' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/3317007222701740028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/4351958588700821968/posts/default/3317007222701740028'/><link rel='alternate' type='text/html' href='http://jshair.blogspot.com/2007/09/diagramming-esbs.html' title='ESB diagramming'/><author><name>Jeffrey S. Hair</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='26' src='http://bp2.blogger.com/_blzwBE2Y-Iw/Rv1RFOuDmyI/AAAAAAAAAAM/CT1C2NIrF7E/s320/Jeff+Thumbnail.jpg'/></author><thr:total>0</thr:total></entry></feed>
