Sunday, May 17, 2009

Monitor detailed SQL transactions issued by Hibernate

Hibernate help us translate access to Java objects from HQL to native SQL and automatically take care of object relationships, which saves developers lots of time, but at the same time, hide lots of details, such as how cross table queries are created, how tables are related and, very important, what data parameters are used for each prepared statetment is called.
To show SQL commands generaeted by Hibernate, we can normally use Hibernate config:
true
With this setting, Hibernate dumps all SQL it executed against DB as below:


Hibernate: select device0_.iid as iid1_0_, device0_.iname as iname1_0_, device0_.iip as iip1_0_, device0_.iinfourl as iinfourl1_0_, device0_.istate as istate1_0_, device0_.irecordState as irecordS6_1_0_, device0_.idevlocation as idevloca7_1_0_ from ieai_device device0_ where device0_.iid=?


However, if you want to see what exact value is passed into the SQL statement, and further more, what result was returned from the SQL command, we need to do more.
Basically we need to set log4j settings of the follow two Hibernate classes into DEBUG:

org.hibernate.SQL
org.hibernate.Type


So the log4j.properties file will have the following settings:

log4j.logger.org.hibernate.SQL=DEBUG,console
log4j.logger.org.hibernate.type=DEBUG,console


Then Hibernate will dump debug information as below:

76033 [DEBUG] AbstractBatcher.log(): - select device0_.iid as iid1_0_, device0_.iname as iname1_0_, device0_.iip as iip1_0_, device0_.iinfourl as iinfourl1_0_, device0_.istate as istate1_0_, device0_.irecordState as irecordS6_1_0_, device0_.idevlocation as idevloca7_1_0_ from ieai_device device0_ where device0_.iid=?
Hibernate: select device0_.iid as iid1_0_, device0_.iname as iname1_0_, device0_.iip as iip1_0_, device0_.iinfourl as iinfourl1_0_, device0_.istate as istate1_0_, device0_.irecordState as irecordS6_1_0_, device0_.idevlocation as idevloca7_1_0_ from ieai_device device0_ where device0_.iid=?
76033 [DEBUG] NullableType.nullSafeSet(): - binding '3' to parameter: 1
76043 [DEBUG] NullableType.nullSafeGet(): - returning 'Device3' as column: iname1_0_
76044 [DEBUG] NullableType.nullSafeGet(): - returning '192.168.0.12' as column: iip1_0_
76044 [DEBUG] NullableType.nullSafeGet(): - returning 'http://www.infolexllc.com/site/' as column: iinfourl1_0_
76047 [DEBUG] NullableType.nullSafeGet(): - returning '1' as column: istate1_0_
76047 [DEBUG] NullableType.nullSafeGet(): - returning '2' as column: irecordS6_1_0_
76048 [DEBUG] NullableType.nullSafeGet(): - returning 'test device location' as column: idevloca7_1_0_


If you are a newbie in Hibernate, you will be amazed to see what is going on underneath by Hibernate, either in a positive and encouraging way or a very bad negative way.

Cheers!

Wednesday, May 13, 2009

Customize Eclipse JVM in Mac

On Windows, we can change eclipse.ini under eclipse folder to put extra parameters for JVM.
On Mac, the ini file is located at:
eclipse/Eclipse.app/Contents/MacOS/eclipse.ini

Monday, May 4, 2009

How to bing dyanmic IP to a subdomain

We have a server with dedicated IP address in my company's headquarter. There're a couple of branches at other locations. We need to setup servers in each branch and allow accessing to those servers through dedicated subdomain name. But we do not have static IP for those branches, so it's not possible to bind any IP in our DNS server at headquarter.

If you have the same need as we are, here's what we did to resolve the problem.

Basically we need to setup DNS Update service at branch site to perform remote DNS update to headquarter to update IP of subdomains used by branch site periodically, so headquarter's DNS will always know the correct IP of each branch server.

For example, our main domain is infolexllc.com, and we need to setup a branch server at New York which will be called ny.infolexllc.com, here's what we do at servers at both ends (both CentOS 5.X):

At branch site(where only dynamic IP is available):
1. Install NS Update:
yum install bind-utils

2. Create folder to hold related files and scripts:
mkdir /root/nsupdate
cd /root/nsupdate

3. create key files for NS update
dnssec-keygen -a HMAC-MD5 -b 512 -n USER ny.infolexllc.com
Kny.infolexllc.com.+157+47223

4. You should have two new files created under the current folder:
Kny.infolexllc.com.+157+47223.key  Kny.infolexllc.com.+157+47223.private

5. create a new shell file: donsupdate.sh:

Make sure you change value of the script based-on your own environment.
6. Open the newly generated key file Kny.infolexllc.com.+157+47223.key
ny.infolexllc.com. IN KEY 0 3 157 QLwMCWdqUJ/ZOsOsdF4Dj/mYD2XwmqSrPL540JE3dwG7FXZwrJulOp16 Y0SySnfOo7+5s1mhZhUiAHxVOSoXnQ==

Remember the key string started from QlwMC.. all the way to the ending ==

On headquarter server:

7. Modify named comnfiguration to allow remote DNS update from ny.infolexllc.com

Open /etc/named.conf
Find zone "infolexllc.com" {
Insert the following section in the configuration file before the zone:
key ny.infolexllc.com.{
algorithm hmac-md5;
secret "QLwMCWdqUJ/ZOsOsdF4Dj/mYD2XwmqSrPL540JE3dwG7FXZwrJulOp16 Y0SySnfOo7+5s1mhZhUiAHxVOSoXnQ==";
};

Insert the following lines at end of the infolexllc.com zone:
allow-update {
key ny.infolexllc.com. ;
};

Restart DNS server:
/etc/init.d/named restart


Now the headquarter DNS server should allow remote DNS update from ny.infolexllc.com

On branch server:
8. Test DNS update script:
run
donsupdate.sh

You should see messages like below:

Detected IP address is:123.123.123.123
IP has been changed or one hour has been passed, save the flag and do update...
Creating key...
before getaddrinfo()
Outgoing update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 0
;; flags: ; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
;; UPDATE SECTION:
ny.infolexllc.com. 0 ANY A
ny.infolexllc.com. 84600 IN A 123.123.123.123


Reply from update query:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: 25321
;; flags: qr ; ZONE: 0, PREREQ: 0, UPDATE: 0, ADDITIONAL: 1
;; TSIG PSEUDOSECTION:
ny.infolexllc.com. 0 ANY TSIG hmac-md5.sig-alg.reg.int. 123123123123 300 16 ABCabcABCabc123+12aBcde== 25321 NOERROR 0


The status: NOERROR indicates a succeful update.
If you see any other error in status, go check /var/log/messages on head quarter server to find clue.

9. Test the new domain:
ping ny.infolexllc.com

You should see the new domain can be resolved to the dynamic IP currently assigned to branch server.

10. Once update script is working, you can create a cron job on branch server to run the script every 10 minutes. The script itself will check if IP has not been changed in the past hour, it will skip remote update.

I've done this for our branch servers several times. It works very well so far. I hope this set up can help resolving your problem. Feel free to let me know f you have any feedback or question.

Cheers!

Thursday, April 23, 2009

How to match lines that does not start with certain string(s)

I had a task to parse a huge log file and needed to pick up only those lines started with certain strings like:
CPU_ALL
ZZZZ
etc.

So I fired up Eclipse, opened the file, and opened Find/Replace dialog box. In the dialog, I tried to replace:
^\b(?!CPU_ALL)(?!ZZZZ)\w+\b.*$

with
Blank

So Eclipse find all strings that does not start with CPU_ALL nor ZZZZ and replaced those lines with space.

I was able to do another Replace of ^\n$ with Blank, so all blank lines got removed. But some how Eclipse complaint I had incompatible end of lines. So I opened the text file with my favorite text editor Notepad++ and ran its "Remove blank lines" plugin to get the job done.

The key here is
(?!CPU_ALL)

which matches string that does not start with "CPU_ALL".
And another
(?!ZZZZ)
right after allows me to exclude another string.

Cheers!

Monday, March 23, 2009

How to write a servlet filter

Since you can call HttpServletResponse.getWriter() only once, it is a little bit tricky to add more output in servlet filter, because it is very likely your call to getWriter to be failed.

Come examples about filter can be found at:
http://download.oracle.com/docs/cd/A97329_03/web.902/a95878/filters.htm

Monday, March 16, 2009

Tips on svnmailer

svnmailer is a great tool to help admin monitor changes made in SVN repositories.
There're zillions of nice articles/docs on how to config it. So I won't bother adding one more here.
Only a couple of tips that I hope can help myself and you trouble-shooting it:

1. To remove =3D kind of characters in email
Looks like the current version of svnmailer (1.08x) and Python 2.4.3 will generate characters like =3D to replace special character = in the notification email. This is caused by the default encoding used by svnmailer (quoted-printable). The quick fix is to set it to utf8.
To apply the quick fix, open mailer.conf file, put the following setting in [defaults] section:

mail_transfer_encoding = 8bit

2. To test svnmailer without really committing anything into the repository:
After your configured svnmailer, you probably want to test the settings, but do not want to really commit anything into the repository. A quick command, which was actually suggested by svnmailer doc, is:

sudo -u apache ./post-commit [Repo Path] [Ver No.]

e.g.:

sudo -u apache ./post-commit /var/svn/2009 55

will send notification of change 55 of repository /var/svn/2009 to the designated email address.

Cheers!

Monday, February 23, 2009

Nagios killed all web sites created by virtualmin

I have a bunch of domains running on a Linux box. They are managed by VirtualMin. Each site has its own user name, group and home folder.
For example, site www.infolexllc.com under VirtualMin has user name and groups infolex as well as home folder /home/infolex.
The document root of the site is /home/infolex/public_html.
Everything was working great until I installed Nagios, hoping it could help me monitor status of my server.
But after Nagios was installed, all my sites on this server became unaccessible. when I pointed my browser to:
http://www.infolexllc.com
I got 403 error saying there's no permission to access the site.

I remember I ran into similar issue on a client's server before. So I found log I wrote down about two years ago. Looks like Nagios somehow removed user apache from group apache. Therefore, Apache server lost access right to website's document root which was owned by apache.apache.

So I guess similar thing must happened to my server also. I checked owner of /home/infolex/public_html, it's infolex.infolex.

I check groups apache belongs to, they are:
apache, nagois, nagiocmd


So I added apache back top group infolex by:
/usr/sbin/usermod -a -G infolex apache


I did the same to all other virtual hosts on the same server.

Then restart Apache. Everything is back to work!

I'm still having problem with Nagois itself so far. Will post more if I ran into anything worth to share.

About Me

Li Ma
President/CEO of Ideal Technologies Inc. Ideal Technologies Inc is a US-based IT company providing professional software development services to our clients all over the world.
View my complete profile