warning: Creating default object from empty value in /home/pulsar/webroot/htdocs/modules/taxonomy/ on line 33.

Combined Access Log Format for a proxed Tomcat

If you need to let your Tomcat write access logs while being proxied by Apache's mod_proxy using the combined format, you will soon notice the lack of the client IP address. Pretty useless if you would like to get some access statistics for that particular instance.

Fortunately the Apache's mod_proxy will add some extra headers with the missing information to each request. Just set up your Log-Configuration in Tomcat as follows:

  1. <Context>
  2. <Valve
  3. className="org.apache.catalina.valves.AccessLogValve"
  4. prefix="access_log"
  5. pattern="%{X-Forwarded-For}i %l %u %t &quot;%r&quot; %s %b &quot;%{Referer}i&quot; &quot;%{User-Agent}i&quot;"
  6. rotatable="false"/>
  7. </Context>

Please note that I'm rotating the Tomcat logs using logrotate. Therefore the "rotatable" attribute is set to "false" above. Just in any case, here is the logrotate config for my setup:

  1. /home/tomcat/logs/*_log
  2. {
  3. weekly
  4. rotate 48
  5. create 640 tomcat www-data
  6. sharedscripts
  7. postrotate /etc/init.d/tomcat restart
  8. endscript
  9. compress
  10. }

How to set Nullable Types via Reflection on Properties in C# / .NET

Here is a Code-Snippet from a generic CSV -> Object Importer/Mapper I wrote. At some point I ran into an issue with Nullable types / values which I had to set (and convert) based on strings from the CSV file.

  1. public virtual void HandlePropertyAssignment(PropertyInfo pi,
  2. string propertyValue,
  3. T instance)
  4. {
  5. try
  6. {
  7. if (
  8. pi.PropertyType.GetGenericArguments() != null &&
  9. pi.PropertyType.GetGenericArguments().Length > 0 &&
  10. pi.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))
  11. )
  12. {
  13. Type genericType = pi.PropertyType.GetGenericArguments()[0];
  14. pi.SetValue(instance, Convert.ChangeType(propertyValue, genericType), null);
  15. }
  16. else
  17. {
  18. pi.SetValue(instance, Convert.ChangeType(propertyValue, pi.PropertyType), null);
  19. }
  20. }
  21. catch (System.Exception ex)
  22. {
  23. throw new DAOException(String.Fromat("Could not convert {0} to property {1} of type {2}",
  24. propertyValue,pi.Name,pi.PropertyType),ex);
  25. }
  26. }
Note: T is a Generic Type.

How to access Excel files via ADO.NET

The C# snippet below will dump ALL sheets of a given Excel file (c:\test.xls) onto the console. It took me a while to figure out how to access sheets within a Excel file which names I don't know - so here it is:

  1. String connectionString =
  2. "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\test.xls;Extended Properties=\"Excel 8.0;HDR=YES;\"";
  3. DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OleDb");
  4. try
  5. {
  6. using (OleDbConnection connection = new OleDbConnection(connectionString))
  7. {
  8. connection.Open();
  9. DataRowCollection rows = connection.GetSchema("Tables").Rows;
  10. foreach (DataRow row in rows)
  11. {
  12. string sheetName = row["TABLE_NAME"] as string;
  13. Console.WriteLine("************************************************************************");
  14. Console.WriteLine("Dumping Sheet: "+sheetName);
  15. Console.WriteLine("************************************************************************");
  16. using (DbCommand command = connection.CreateCommand())
  17. {
  18. string[] restrictions = { null, null, sheetName, null };
  19. DataRowCollection columns = connection.GetSchema("Columns", restrictions).Rows;
  20. string[] columnNames = new string[columns.Count];
  21. for (int i=0; i<columns.Count; i++)
  22. {
  23. columnNames[i] = columns[i]["COLUMN_NAME"] as string;
  24. }
  25. Console.Write("Columns in Sheet: ");
  26. foreach (string s in columnNames)
  27. {
  28. Console.Write(s);
  29. Console.Write(" ");
  30. }
  31. Console.WriteLine("");
  33. command.CommandText = "SELECT * from [" + sheetName + "]";
  34. using (DbDataReader dr = command.ExecuteReader())
  35. {
  36. while (dr.Read())
  37. {
  38. foreach (string columnName in columnNames)
  39. {
  40. Object fieldValue = dr[columnName];
  41. Console.WriteLine("'" + columnName + "' : " + "'" + fieldValue + "'");
  42. }
  43. Console.WriteLine("------------------------------------------------------------------------");
  44. }
  45. }
  46. }
  47. }
  48. }
  49. }
  50. catch (Exception e)
  51. {
  52. Console.Write(e.StackTrace);
  53. }

To be honest - I did not expect it to be that easy. I guess I spent too much time developing Java applications.

XEN on 32 Bit with 8 GB Ram Odyssey

Last week I've ordered a new shiny root server at hetzner. A nice 8gb Server begging me to install XEN on its virgin 750GB Raid HD. Hell yeah, but wait, I need to run 32 Bit XEN-Guests on that one. After a quick glance at the current Debian XEN packages I decided not to install the 64 bit variant of Debian as the Domain-0. Unfortunately Debian is still stuck at 3.0.x which doesn't allow 32-on-64 setups (which I have found no documentation for anyway).

Ok, 32 bit it is. To my very disappointment I had to discover the lack of PAE extensions in the XEN-Kernel. But why-o-why is the hypervisor package flagged with PAE extensions but not the kernel? So, what now? One option has been to go with a XEN Setup from the sources. For obvious reasons I'd rather like to have a distribution run solely on official stable packages.

I’ve always wanted to take a look at Debian's younger brother - Ubuntu. Thank god Hetzner did offer easy and convenient image-base setup for various Linux distributions, including Ubuntu 7.10. Setup and first XEN steps went like a breeze. Soon I have found myself running XEN on 32 Bit with full PAE support being able to address all of my tiny little ram bits. YAY!

Time to migrate some XEN-U guests to the new machine. Fortunately the old server was also located at the same collocation center, so the copy process did not take too long. The fun did not last any longer though. The very first boot of the guest OS resulted in a frozen console. No login. WTF!? After fiddling with various Kernel options and googling myself into madness I have found some very interesting facts.


Push To Sync 1.2Push To Sync 1.2


Directory synchronization utility. Copies contents of directory A into a directory B. That's it.

Key Facts

  • It's is Freeware
  • Meant to be a "Portable App" (just an exe file, no setup required)
  • has been designed to synchronize a source directory (with sufolders) with a target directory
  • Only copies what is really needed. Updates older files, copies new ones and skips newer and identical.
  • Will let you pause or abort the copy process in the middle of a 30gb big file. Of course you can resume copying a big file in a new session.
  • Is fault tolerant. Unaccessable files such as the Recycler or system files in your profile directory will not abort the entire copy operation. Failed transactions will get logged so you can investigate missing files afterwards.

Current Status

Right now PushToSync is still in development and may (read: will) contain bugs or issues which might (read: will) drive you crazy. To put it simple: you loose data - you don't bitch and moan over here. Bugreports are VERY appreciated though!


1.2 2008-07-27, Second Release

  • [Feature] Time prediction based on average transfer speed 
  • [Feature] Shows the current transfer speed using a nice looking graph
  • [Bugfix] Fixed some issues with file timestamp handling when synchronizing to a linux samba share.

1.1 2007-11-09, Initial Release

Imprint Datenschutzerklärung