SSH Tunnel in OS X
Open tunnel:
$ ssh -L 8080:remote-host:80 -f -C -q -N me@myserver.com
Close tunnel:
$ ps -aux | grep ssh
$ kill {pid}
A coder’s daily explorations through PHP, Java, CSS, JavaScript, Linux, OS X, Apache, Tomcat, and everything else.
Open tunnel:
$ ssh -L 8080:remote-host:80 -f -C -q -N me@myserver.com
Close tunnel:
$ ps -aux | grep ssh
$ kill {pid}
Here is how I configured Quartz to work with Spring and Hibernate. I’m using the Quartz JDBC Job Store which stores and retrieves the job settings from a database instead of a static configuration.
I use the SchedulerFactoryBean to manager the Quartz Scheduler lifecycle.
spring-servlet.xml
... <!-- Quartz --> <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="applicationContextSchedulerContextKey" value="applicationContext"/> <property name="configLocation" value="classpath:quartz.properties"/> </bean> ...
The Quartz settings are stored in a quartz.properties file so that they can be unique to each instance of the web application. This setup requires that quartz.properties be on the classpath. This file defines the JDBC connection for Quartz to use.
quartz.properties
... org.quartz.dataSource.myDS.jndiURL=java:comp/env/jdbc/MyDS org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate org.quartz.jobStore.dataSource=myDS org.quartz.jobStore.tablePrefix=JB_ org.quartz.jobStore.useProperties=true
MyBaseJob
public abstract class MyBaseJob extends QuartzJobBean
{
private transient ApplicationContext applicationContext = null;
public ApplicationContext getApplicationContext()
{
return applicationContext;
}
public void setApplicationContext(ApplicationContext applicationContext)
{
this.applicationContext = applicationContext;
}
}
Each of my job classes extend MyBaseJob, overriding executeInternal. The jobs can use the applicationContext to lookup Spring service beans. In my environment these service beans extend HibernateDaoSupport.
protected void executeInternal(JobExecutionContext ctx) throws JobExecutionException
{
MyServiceManager sm = applicationContext.getBean("myServiceManager"); // lookup Spring service bean
...
}
Periodically I need to replace a string in multiple files on Linux. I find myself looking up this command or a variant every time.
grep -rl OLDSTRING *.FILEEXTENSION | xargs perl -pi~ -e 's/OLDSTRING/NEWSTRING/'
My setup is a single Fedora Core 6 server running Apache 2.2.4 (with mod_ssl and mod_proxy) and Tomcat 5.
With mod_ssl the following virtualhost is setup using an SSL certificate from GoDaddy. Notice the SSLCertificateChainFile /etc/httpd/conf/ssl.crt/gd_intermediate_bundle.crt reference. This intermediate certificate comes from GoDaddy and is required. I didn’t catch this at first and couldn’t understand what my web browser was unhappy about. When I called GoDaddy support they told me my certificate was setup correctly and worked in all of there “off-site” test browsers. They were no help, so I continued to dig around and finally found the answer.
The mod_proxy lines pass all requests to the Tomcat instance listening on port 9014.
/etc/httpd/conf.d/ssl.conf
<virtualhost>
DocumentRoot /var/www/html/
ServerName myserver.com:433 SSLEngine on
SSLCertificateFile /etc/httpd/conf/ssl.crt/myserver.crt
SSLCertificateKeyFile /etc/httpd/conf/ssl.key/myserver.key
SSLCertificateChainFile /etc/httpd/conf/ssl.crt/gd_intermediate_bundle.crt
SetEnvIf User-Agent ".*MSIE.*"
nokeepalive ssl-unclean-shutdown
downgrade-1.0 force-response-1.0
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
CustomLog logs/ssl_request_log
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
ProxyPreserveHost On
ProxyPass / http://localhost:9014/
ProxyPassReverse / http://localhost:9014/
SetEnv proxy-nokeepalive 1
</virtualserver>
For the Tomcat setup, a proxy connector is configured to listen on port 9014 and to proxy port 443 requests (SSL). The communication between Apache and Tomcat is not secure, but this is not a concern since this communication is local to the server. Finally, compression is turned on for several common mime-types.
server.xml
... <Connector acceptCount="100" connectionTimeout="60000" disableUploadTimeout="true" port="9014" redirectPort="8944" scheme="https" proxyPort="443" compression="on" compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript"/> ...
In migrating from Tomcat 5.0 to Tomcat 5.5, one of my custom Struts plugins started failing on startup with the following exception:
org.apache.commons.digester.Digester startElement SEVERE: Begin event threw exception java.lang.ClassNotFoundException: com.mikwat.struts.config.AuthorizationActionConfig
The root of the problems appears to be that the Digester defaults to using the same ClassLoader that loaded it and whichever ClassLoader this is, it doesn’t have access to my webapp class com.mikwat.struts.config.AuthorizationActionConfig.
After Googling around, I eventually came across this post regarding a similar problem loading the Quartz plugin: Mailing list archives.
The solution is to call setUseContextClassLoader(true) on the Digester object which forces it to use the ClassLoader found by calling Thread.currentThread().getContextClassLoader().
We recently switched to Google Apps at work and I have been looking for a way to import my existing email, which was stored on an IMAP server, into Gmail. The answer became clear when I came across Mark Lyon’s GMail Loader (GML), but it was much simpler than I thought. Rather than use GML, all I had to do was move my email from their IMAP folders into the Inbox. Then, I configured Gmail to Get mail from other accounts under Settings » Accounts.
This only works for POP3, which was available on my old mail server, but requires that all email be moved to the Inbox. Gmail downloads 200 messages at a time and checks for mail every hour, so the process can take a long time. Filters, SPAM, and virus checks are performed on each message, so check your Spam folder periodically for misdirected messages. There are several settings that allow you to automatically Archive and label incoming messages. See Google’s Help Center for more information.
So, although GML looks interesting and powerful, using Gmail’s built-in POP3 fetcher was the best solution for me.
The other day it dawned on me that my hobby website, My Cycling Log, has a large international audience and that I should cater more to them. My Cycling Log is basically exactly what its name suggests: an online cycling log. It’s a place for cyclists to log their rides, share their achievements with their friends and the world, and organize themselves into groups. The site is constantly evolving largely driven by user feedback.
My first step in making My Cycling Log friendlier for international users was to implement user-specific timezones. This is a no brainer. PHP handles timezones quite elegantly using the date_default_timezone_set function.
The second step is to internationalize the text. An article on IBM’s website lays it out very clearly: How to internationalize PHP apps. I’m still looking for translators, but I will update this post once I begin the process.
Problem: Occasionally I get the following JDBC error from MSSQL:
The log file for database 'db_example' is full. Back up the transaction log for the database to free up some log space.
Solution:
BACKUP LOG db_example WITH TRUNCATE_ONLY
DBCC SHRINKFILE(db_example_log, 2)
If ‘db_example_log’ is not the logical name of the logfile, the 2nd command will fail. The correct logical name can be found by running the following statements:
USE db_example;
SELECT * FROM sysfiles;
Problem: I have a web application running under Tomcat using the Oracle ADF framework. When the application is installed as a service under Windows, it outputs cache files in mass to \WINDOWS\system32\ Needless to say, this doesn’t make the system administrators happy.
Solution Under Linux: This problem is avoided by starting the application with a working directory of <application.root>\temp Then, these ADF cache files get dumped there. The following snip-it does the trick:
pushd "$CATALINA_BASE"/temp > /dev/null
exec "$EXECUTABLE" start "$@"
popd > /dev/null
CATALINA_BASE: <application.root>
EXECUTABLE: <tomcat.home>/bin/catalina.sh
Solution Under Windows: Unknown at this point, please provide feedback.
After having some site performance and availability problems, I began investigating ways to monitor web servers. There are lots of sites offering various services, here’s what I’ve settled on.
1. Broadband Reports offers both free and paid services. Their Line Monitoring tool provides a continuous response time graph shown below by sending out pings every 10 minutes. The Line Monitoring tool costs approximately $1 per week. It also provide the ability to setup a HTTP ping to a specific URL.


2. mon.itor.us is a free web site monitor tool. As far as simplicity in setup, mon.itor.us couldn’t be easier. Their website serves as a dashboard with drag-and-drop modules for each of your sites. These modules can also be included in your OS X dashboard, Google Personal, Netvibes, etc. Another nice feature is the ability to be notified when your sites are unavailable. Alerts can be sent to an email address, IM account, or cellphone. The main problem with mon.itor.us is in its ping frequency, which is currently between 30-45 minutes. According to their parent site Monitis they are rolling out a Bronze plan ($10 per month) that will ping every 5 minutes and provide some advanced features.
