setInterval, never ever forget the second argument.
Wednesday, May 28, 2014
Friday, December 21, 2012
Getting the connection (with some AOP too!)
Abstract
If you need the raw OracleConnection so you can use End-to-End Metrics and you're using a JNDI data source from WebSphere, you need to jump through a few hoops.The Details
Some up-front info: the project I'm on is running some old software so I'm not sure how relevant any of this is to anyone but me. We are using Spring 2.0.6, Hibernate 3.2.5, WebSphere 6.x and Oracle 10g...Anyways, we wanted to implement Oracle's End-to-End metrics so that we could have a better way to see what each user is doing on the system and where potential problems might lie in relation to the database. We also wanted the code to be as non-intrusive as possible - adding new code everywhere would be a total pain.
I decided to use AOP which allow us the ability to attach code anytime a method on a DAO is called. It works quite well, even with Spring 2.0.
Back to the original idea, here's the code to get the OracleConnection:
import org.hibernate.jdbc.ConnectionWrapper;
import com.ibm.ws.rsadapter.jdbc.WSJdbcConnection;
import com.ibm.ws.rsadapter.jdbc.WSJdbcUtil;
import oracle.jdbc.OracleConnection;
Connection conn = session.connection();
org.hibernate.jdbc.ConnectionWrapper cw = (ConnectionWrapper) conn;
WSJdbcConnection connws = (WSJdbcConnection) cw.getWrappedConnection();
OracleConnection oc = (OracleConnection) WSJdbcUtil.getNativeConnection(connws);
With session being the Hibernate session (I added the imports so you wouldn't have to look for them later).
Now that you have the OracleConnection, you can easily add the code for the metrics:
String[] metrics = new String[OracleConnection.END_TO_END_STATE_INDEX_MAX];
metrics[OracleConnection.END_TO_END_MODULE_INDEX] = module;
metrics[OracleConnection.END_TO_END_ACTION_INDEX] = action;
metrics[OracleConnection.END_TO_END_CLIENTID_INDEX] = userName;
oc.setEndToEndMetrics(metrics, (short) 0);
Now that the hard stuff is out of the way, let's throw in some AOP. Using Spring's AOP XMLNS makes this quite easy. Basically we will define our Aspect bean and then configure it as a before-type aspect.
<bean class="com.djs.OracleMetricsAspect" id="metricsAdvice" />
<aop:config>
<aop:aspect ref="metricsAdvice">
<aop:before method="addMetrics" pointcut="execution(* com.djs..*DAOImpl*.*(..))" />
</aop:aspect>
</aop:config>
This will run the metricsAdvice before any method that's executed in any class that's contains DAOImpl in it's name.
So now that we have that finished, here's the addMetrics method that's run in the OracleMetricsAspect class:
public void addMetrics(final JoinPoint joinPoint) {
try {
if (joinPoint.getTarget() instanceof HibernateDaoSupport) {
HibernateTemplate ht = ((HibernateDaoSupport) joinPoint.getTarget()).getHibernateTemplate();
ht.execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
String[] metrics = new String[OracleConnection.END_TO_END_STATE_INDEX_MAX];
String className = joinPoint.getTarget().getClass().getName();
String module = className.substring(className.lastIndexOf(".") + 1);
if (module.length() > 48) {
metrics[OracleConnection.END_TO_END_MODULE_INDEX] = module.substring(0, 48);
} else {
metrics[OracleConnection.END_TO_END_MODULE_INDEX] = module;
}
String action = joinPoint.getSignature().toShortString();
if (action.length() > 29) {
metrics[OracleConnection.END_TO_END_ACTION_INDEX] = action.substring(0, 29) + "(" + joinPoint.getArgs().length + ")";
} else {
metrics[OracleConnection.END_TO_END_ACTION_INDEX] = action + "(" + joinPoint.getArgs().length + ")";
}
metrics[OracleConnection.END_TO_END_CLIENTID_INDEX] = SecurityUtils.getUserName(); // this is implementation specific
try {
Connection conn = session.connection();
ConnectionWrapper cw = (ConnectionWrapper) conn;
WSJdbcConnection connws = (WSJdbcConnection) cw.getWrappedConnection();
OracleConnection oc = (OracleConnection) WSJdbcUtil.getNativeConnection(connws);
oc.setEndToEndMetrics(metrics, (short) 0);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return null;
}
});
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}Since all of our DAOs extend Spring's HibernateDaoSupport, we have access to the HibernateTemplate. And from there we can get the Hibernate session. And from the JoinPoint, we have access to the class name and method that's being called so we can use that for the module and action for the Oracle metrics. Below is a screenshot of what the DBAs see in OIM:
Hope I didn't miss anything.
Have fun coding!
Tuesday, March 27, 2012
JSP EL reserved word
You probably shouldn't use class as a variable name in JSP EL. WebSphere 8 doesn't seem to like it.
Friday, March 02, 2012
Sitemesh Excludes
If you don't want Sitemesh to decorate a page, use the
excludes tag in your decorators.xml file. It will save you a lot of headaches.I was using this with version 2.4.2.
Wednesday, December 07, 2011
Double-tap on Mobile Safari
This map is zoom-able to 4 levels deep and contains pins for specific locations. Tapping/clicking on these pins will either bring up a list of options (if pins overlap) or go directly to another page. As you can tell, I'm also using jQuery.
Here's what I came up with:
$('#map').bind('touchstart', function(e) {
if ($(e.target).hasClass('disclosure') || $(e.target).parent().hasClass('disclosure') || (e.target.src && e.target.src.toLowerCase().indexOf('disclosure') > 0)) {
map.jumpToPage(e);
return false;
}
$('#flyover').hide();
var oe = e.originalEvent;
if (oe.touches.length == 1) {
var tap = { at: new Date().getTime(), x: oe.touches[0].pageX, y: oe.touches[0].pageY, shortDelay: $(e.target).hasClass('pin') };
if (!$('#map').data('firstTap') || ((tap.at - $('#map').data('firstTap').at) > 500)) {
$('#map').data('firstTap', tap);
} else {
var firstTap = $('#map').data('firstTap');
if ((tap.at - firstTap.at) <= (tap.shortDelay ? 300 : 500)) {
$('#map').data('lastTap', tap);
}
}
}
e.preventDefault();
}).bind('touchend', function(e) {
var f = $('#map').data('firstTap');
var l = $('#map').data('lastTap');
setTimeout(function() {
var f1 = $('#map').data('firstTap');
var l1 = $('#map').data('lastTap');
if (f1 && !l1 || f1 && l1 && (f1.at > l1.at)) {
map.showPopUp({ pageX: f1.x, pageY: f1.y, target: e.target, stopPropagation: function() {} });
}
}, 301);
if ((f && l && (l.at > f.at)) && map.getZoom() < 4 && !map.isZooming()) {
map.zoomIn((l.x - $('#map').offset().left), (l.y - $('#map').offset().top));
}
});
#map is the main map element, #flyover is the list of items to display if necessary.Here's how the code works:
For "touchstart":
- When the map is first tapped, the first thing we check for is if it was a list item (has a class of
disclosure). If it is, go to that page.
- Make sure the
#flyoveris hidden. This is the root element for the pop-up.
- Get
originalEventfrom jQuery sinceedoesn't contain the actual touch events.
- Only continue if it was a single-touch event.
- Create
tapobject that contains all the pertinent data we want to keep.
- If this was the first time we've tapped on the map or it's been more than a half a second, save
firstTap.
- Otherwise, we compare
firstTapto the currenttapand if it's been less than 300ms for a pin or 500ms for the map, we savetapaslastTap.
- Retrieve
firstTapandlastTap.
- In
setTimeout, ifl1doesn't exist or is older thanf1, we run theshowPopUpafter 301ms. This is a specific scenario for when a user taps on a pin. A single-tap should show a pop up, but a double-tap will zoom in.
- Finally, we zoom in on the map if
firstTapis beforelastTapand the map isn't zoomed all the way in or in the midst of zooming-in.
Tuesday, September 08, 2009
A couple of pics from Sundays race
Middle of the pack as usual: 12 out of 20 for my age group, 36 out of 62 Cat3 overall.
Thursday, August 13, 2009
DINO 2009 Race #3 - Versailles State Park
Wow. Where to start? So, the race was finally able to go on after being postponed for two weeks due to excessive amounts of rain. It probably wouldn't have been a huge problem since the sun came out each weekend but since one of the trails was only built a couple of weeks prior, the rain turned it into a soupy, slippery, dangerous mess. Suffice it to say that it was a good idea to postpone the event.
An interesting day for us as well. After what was a good morning we ended up leaving quite a bit later than I wanted. This resulted in my starting with the 40+ group which was 2 minutes back from my class. Not really a problem since I'm not yet ready to stand on the podium.
The trails at the park are pretty amazing. HMBA is, again, to be commended on their trail building, especially when you consider that all or most of it is volunteer work. The trails also integrate some of the unique features of the park, including what's called the Waterfall:
As you can see, this is just exposed rock and the trail follows along a natural ledge. Pretty amazing but can be quite slippery.
Since I'm not much for planning, I didn't give much thought to making sure I was fueled up for the race. This was evident about halfway through when I felt like I was going to bonk. Luckily, I seem to have a good size reserve since I made it through to the end. I even passed somebody right before the finish line! I finished 10th out of 12 in my age group (wow, top ten!) and 21st out of 31 for Cat3 (results). Even with my 2-minute deficit, it doesn't change my results at all.
Overall, I thought it was a good race that could have been better had I done a better job of planning and preparing. This weekend is race #6 at France Park. I have to redeem myself since I DNFd last year. And I'll have a bigger cheering section, my mom and sister will be there!
Saturday, June 20, 2009
DINO 2009 Race #3 - Frank Park, Fort Wayne
Although I don't show up on the results (the person running the computer missed me as I was riding by but the backup didn't), I did end up 25th overall for Cat3 men, 12th out of 14 for my age group.
As usual, the second half of the race is always my better half. There are several short but somewhat steep climbs on the trail that, if you're not ready, will require you to get out of the saddle and hike it. Basically, the first lap I had to hike it, the second I was able to stay in the saddle.
Overall, I thought the course was really nice. It's been a very wet Spring in Indiana but the trail, except for a few soft spots, was very nice.
Since the family and I will be on vacation, we won't be attending race #4 at Muscatatuk Park. But we will be at Versailles State Park for #5.
Thursday, June 11, 2009
Grrrrrr...... DBAs...
<rant>
This is a work related post so be prepared. Why is it that DBAs still don't know the layout of the schema even though they've been working on it for 2 years? I find that I'm constantly reminding them how the damn thing works.
</rant>
Monday, June 01, 2009
DINO 2009 Race #2 - Brown County State Park
Yesterday was DINO Race #2 and what a day it was. Temps in the mid to low 70s and low humidity. And excellent day to race.
And a pretty good weekend to go camping. Yes, Dana and I took the kids camping at the State Park. It was at times a bit hectic but overall a lot of fun and the kids seemed to enjoy it, especially the s'mores.
Anyways, here's the race results:
Overall
Last year: 68/80
This year: 55/70
Age group
Last year: 30/32
This year: 22/25
Time
Last year: 1:10:17
This year: 1:01:52
Doesn't seem like much of an improvement until you consider that I shaved off over 8 minutes on my time. I would attribute this to the condition of my bike more than any improvement in fitness. The differences on my bike from last year to this year are significant. A working suspension fork, new bar and stem, new brakes, wheels, tires and crankset. The bike is much easier to control and smoother on the trail.
Also, there's something to say about pre-riding the course. I remembered that there was a steep climb early on and was able to stay in the front pack, but I forgot that there's a second one right before you enter the woods. I ended up walking up the last 100 feet or so and lost any advantage I had from the first climb. Also, on the Aynes Loop, there's a sustained climb for what seems like a mile or more and I had to do some walking for that as well.
Because my suspension fork worked this year, it was a more enjoyable race on the downhills. And if my fitness was a little better I might have enjoyed the uphills. Eh, maybe not...
Up next is Franke Park in the Fort Wayne. The course looks to be very fast with some short, steep uphills. I can't wait!
Tuesday, April 14, 2009
Friday, April 10, 2009
I hate the rain
So, what was to be the highlight of my week has been canceled due to the weather. Our wetter than normal (so far) April has turned the bike trails into soup. Funny thing was, I was on the trail yesterday and it was 95% dry.
I guess I shouldn't be too surprised. Prior to this week, I had been commuting by bike 4 out of 5 days a week. But this week started out with a chance for snow, then rain, a nice day yesterday (60 and sunny) and now rain again. Other than riding the trails yesterday, I hadn't been on the bike all week. Still sucks though.
Also, I was going to be debuting my new duds. The extremely thoughtful wife picked up some new riding gear. I have now have a long-sleeve Oakley jersey, a Zoic short-sleeve jersey and Zoic mountain bike shorts. Ok, so I wore the Oakley jersey and shorts yesterday - couldn't go out looking like a total doofus. Oh, and they were very nice - puts all of my old stuff to shame. Thank you honey!
All of this means I have to wait another 3 weeks for the next race. Hopefully this year it'll be a little warmer and a lot less windy at Winona Lake.
Friday, February 27, 2009
For a little color...
I can't recommend this site highly enough for the monthly collections of desktop backgrounds. They usually post these on one of the last days of the month and the collection for March 2009 is outstanding as far as I'm concerned.
March backgrounds from Smashing Magazine
The site also has excellent articles on web design as well.
Saturday, February 14, 2009
Musings...
I'm not sure how I like the winter season here in Indiana. When I lived in Michigan, especially in the UP, there was a definite start and stop to winter. Once winter started, you knew it was there to stay. Here in Indiana, the average daily temperature for January is 34 degrees. That means it can be winter during the week and spring on the weekend. I don't mind the part where I don't have to shovel the driveway much, but it can screw with your brain if you're not used to it.
But spring is on the way and that means bike riding. The DINO Series gets started earlier this year with the Tuneup on the second weekend of April instead of the last. And I can't wait.
Have you seen the cover of the March 2009 Bicycling magazine? I think I may have found my new road bike. I haven't really thought about much about getting a Giant but this one looks quite nice. I haven't ridden one since I had my brothers old steel Rincon. I rode that around Marquette quite a bit along Lakeshore Blvd.
Other things I've been thinking about are getting some new bike shorts and possibly a new jersey. All my stuff is as old as my bike is and it sure would be nice to get something more in fashion. I really like the Mountain Tee (long or short sleeve) from Performance. What I'm trying to figure out though is, would that jersey still go with regular bike shorts? Or would I need to get something like their Mesa short. I'll have to think about that.
Tomcat Tip: Tabs in TLD files
When you're writing your own JSP EL functions and putting the function signature in the TLD file, make sure it does not include tabs. Tomcat doesn't like it.
Tuesday, November 25, 2008
Cloth Bags
Thursday, November 06, 2008
Thursday, October 16, 2008
Interesting articles...
So apparently somebody DID want to do something about the '70s energy crisis.
Dr Shlomo argues that the idea of a Jewish nation is a myth invented little more than a century ago.




