KiRo is a completely autonomous table soccer playing robot: using a camera it perceives the playing field and, dependend upon the current game situation, it decides how the rods under its control should be moved.Even better is that they commercialized it under the name StarKick. Now if you have a broadband connection go check out some video of what it's like to go up against a robotic foosball opponent. ;-)
Tuesday, May 31, 2005
Computers, Robotics and Foosball
What a fantastic combination. I'm surprised I didn't try to come up with that one myself ;-) Apparently I'm too late, the University of Freiburg's (German city of about 200,000) Computer Science Department has developed KiRo, the table soccer robot:
Thursday, May 26, 2005
Quicktime 7, H.264 and HDTV
Although H.264 was originally going to be one of those gotta-have-it features offered in the latest version of Mac OS X Tiger, Apple decided to give it away with Quicktime 7. Currently it's only available for Macs and not Windows ("Quicktime 7 for Windows Coming Soon") so you need a Mac to see it but it's worth checking out.
I still have an antenna in my attic for viewing over-the-air broadcasts (a.k.a., peasant-vision) so I'll be the first to admit that I'm a bit quality-picture challenged. But expectations aside, when I downloaded a couple of samples from Apple's HD Gallery I was very very impressed! The 1080p version of the Batman Begins trailer is just huge! My crappy VGA monitor can't even display that resolution (1920 x 816)!
So what's next from Apple? Well it's difficult (if not impossible) to predict. Apple was late to the whole MP3 thing when they introduced iTunes. They weren't the first with a portable hard drive based MP3 player, the iPod, and they weren't the first with an online music store either but look where they are now. They dominate. Microsoft has a Windows XP Media Center and both they and Sony with their next generation game boxes are vying for a spot in the living room. But Apple has the technology, the ingenuity and the ability to make products that resonate with consumers so I'd expect to see something from them that not only embraces the Mac and iLife (as digital hub) but goes beyond to make digital video simple and approachable to the masses.
[Update: I found this blog where the author goes into quite abit more depth. He sounds way more upbeat than me!]
I still have an antenna in my attic for viewing over-the-air broadcasts (a.k.a., peasant-vision) so I'll be the first to admit that I'm a bit quality-picture challenged. But expectations aside, when I downloaded a couple of samples from Apple's HD Gallery I was very very impressed! The 1080p version of the Batman Begins trailer is just huge! My crappy VGA monitor can't even display that resolution (1920 x 816)!
So what's next from Apple? Well it's difficult (if not impossible) to predict. Apple was late to the whole MP3 thing when they introduced iTunes. They weren't the first with a portable hard drive based MP3 player, the iPod, and they weren't the first with an online music store either but look where they are now. They dominate. Microsoft has a Windows XP Media Center and both they and Sony with their next generation game boxes are vying for a spot in the living room. But Apple has the technology, the ingenuity and the ability to make products that resonate with consumers so I'd expect to see something from them that not only embraces the Mac and iLife (as digital hub) but goes beyond to make digital video simple and approachable to the masses.
[Update: I found this blog where the author goes into quite abit more depth. He sounds way more upbeat than me!]
Tweaking log4j
Despite the inclusion of logging APIs into the JDK since 1.4, I still continue to use log4j for my logging needs. Generally I'll also use the commons logging API on top of log4j so that if I should ever change my mind and want to use the "built-in" logging facilities it will be easy.
My recent foray into production deployment highlighted one of the problems with my standard configuation. I have the typical log4j.properties file in the root of my source directory, and log4j is quite happy to find it there. The problem is that it eventually gets buried inside a JAR (Java ARchive) which is inside a WAR (Web Archive) when I build my application and therefore it's not very easy to change the logging parameters once my application is deployed. Specifically, the location of the generated log files is now essentially hard coded, which sucks for deployment.
Fortunately there's a way out of this. If you specify the location of a log4j.properties file in a Java system property called log4j.configuration, log4j will use that file instead of the one buried in your classpath. The only trick is to specify the location as a URL:
java -Dlog4j.configuration=file:/e:/log4j.properties ...
If you're using a Windows Service for starting an instance of Tomcat you can add a system property to the registry value found in HKEY_LOCAL_MACHINE/SOFTWARE/Apache Software Foundation/Procrun 2.0/Node1/Paramaeters/Java/Options where Node1 in my example is the name of your instance of Tomcat.
Secondly, if you're want to define the location relative to a Tomcat installation you can use a dynamic location like this within your log4j.properties file:
log4j.rootLogger=error, R
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=${catalina.base}/logs/MyApp.log
log4j.appender.R.MaxFileSize=200KB
log4j.appender.R.MaxBackupIndex=2
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=[%d{ISO8601}] %5p (%F:%L) - %m%n
Notice the ${catalina.base} expression. The nice thing about this in a clustered environment like I described yesterday is that you can use the same log4j.properties file for all the instances of Tomcat and can change the configuration for all of them all at once.
My recent foray into production deployment highlighted one of the problems with my standard configuation. I have the typical log4j.properties file in the root of my source directory, and log4j is quite happy to find it there. The problem is that it eventually gets buried inside a JAR (Java ARchive) which is inside a WAR (Web Archive) when I build my application and therefore it's not very easy to change the logging parameters once my application is deployed. Specifically, the location of the generated log files is now essentially hard coded, which sucks for deployment.
Fortunately there's a way out of this. If you specify the location of a log4j.properties file in a Java system property called log4j.configuration, log4j will use that file instead of the one buried in your classpath. The only trick is to specify the location as a URL:
java -Dlog4j.configuration=file:/e:/log4j.properties ...
If you're using a Windows Service for starting an instance of Tomcat you can add a system property to the registry value found in HKEY_LOCAL_MACHINE/SOFTWARE/Apache Software Foundation/Procrun 2.0/Node1/Paramaeters/Java/Options where Node1 in my example is the name of your instance of Tomcat.
Secondly, if you're want to define the location relative to a Tomcat installation you can use a dynamic location like this within your log4j.properties file:
log4j.rootLogger=error, R
log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=${catalina.base}/logs/MyApp.log
log4j.appender.R.MaxFileSize=200KB
log4j.appender.R.MaxBackupIndex=2
log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=[%d{ISO8601}] %5p (%F:%L) - %m%n
Notice the ${catalina.base} expression. The nice thing about this in a clustered environment like I described yesterday is that you can use the same log4j.properties file for all the instances of Tomcat and can change the configuration for all of them all at once.
Wednesday, May 25, 2005
Tomcat and IIS
I've been busy lately deploying my latest Java web application to production. It's been a bit of an adventure since I don't usually get to play the deployer role. Fortunately I already had my Ant script building the WAR (Web ARchive) file so I was only working on deploying to Tomcat 5.5.9. The twist is that I was deploying to four instances of Tomcat on two physical Windows 2003 servers fronted by the latest version of IIS.
The only reason IIS is involved at all is so that I could use the JK 1.2 Tomcat Connector to do the load balancing. This connector works as an ISAPI Filter and intercepts requests to my appliction (based on the URI) and forwards them on to an instance of Tomcat running my application. The connector does a weighted round robin load balancing and ensures that a request that is tied to a particular session on a particular Tomcat instance (from a previous request) is directed back to that same Tomcat instance.
But perhaps I'm a bit ahead of myself. Let's back up to the Tomcat installations. The first thing I wanted to accomplish was the sharing of the Tomcat JAR files among the various instances of Tomcat. By doing that, I know all Tomcat instances are running the same version and upgradable in one shot. The steps were:
Because this installation is on a Windows server I decided to follow the adage "When in Rome, do as the Romans do" and make my Tomcat instances run as Windows Services. Fortunately Tomcat is ready to go with a Tomcat5.exe and a batch script to create the registry entries call Service.bat. The only changes I had to make to the batch file were a few lines at the top to set some environment variables:
then I ran "Service.bat install Node1" and I now have a service that I can easily start and stop. You may want to change the service to "Automatic" to ensure that it gets restarted in the event of a server restart.
Now back to the Tomcat connector installation. I like keeping the redirector stuff separate from the tomcat installation so I created a directory called /tomcat-iis-connector that contains the following files:
The reg file contains some registry entries that the DLL uses at runtime to find your configuration information. Mine looks like this:
Now you have to actually tell IIS about the redirector DLL (notice the /jakarta/ prefix in the extension_uri entry in the reg file. This becomes important in a moment)
Now all you have to do is configure your workers.properties file. Mine looks like this:
And then in the cluster-tomcat-node1/conf/server.xml make sure you identify the server with the same name you used when defining the worker in workers.properties, in this case "node1". Without this the "sticky sessions" won't work.
At this point I've only described the installation of a single Tomcat instance, but in reality I have four tomcat instances. So you can imagine more tomcat-cluster-node directories and a few more entries in workers.properties and the addition of those worker names to worker.loadbalancer.balanced_workers:
Next you must define the URIs that should get redirected from IIS to Tomcat in the uriworkermap.properties file. Mine looks like this (of course you'll need to change the value of "mycontext" to the context of your app:
Normally, I would like IIS to serve all my static content but I use struts tags to specify the location of images and the JSTL c:url tag to dynamically generate URLs. These tags rewrite the URL and not only include the name of the context (which is configurable at deployment time) but also include the jsessionid in the URL when not using cookies. Unfortunately IIS can't figure out what to do with the jsessionid so your pages come back without CSS or images. Not only do they look pretty awful but if you use js files some functionality may not even work. So I just map everything to Tomcat. On the plus side, deployment is simpler with the single WAR file.
Finally restart IIS and hope everything works! :-)
The only reason IIS is involved at all is so that I could use the JK 1.2 Tomcat Connector to do the load balancing. This connector works as an ISAPI Filter and intercepts requests to my appliction (based on the URI) and forwards them on to an instance of Tomcat running my application. The connector does a weighted round robin load balancing and ensures that a request that is tied to a particular session on a particular Tomcat instance (from a previous request) is directed back to that same Tomcat instance.
But perhaps I'm a bit ahead of myself. Let's back up to the Tomcat installations. The first thing I wanted to accomplish was the sharing of the Tomcat JAR files among the various instances of Tomcat. By doing that, I know all Tomcat instances are running the same version and upgradable in one shot. The steps were:
- Unzip jakarta-tomcat-5.5.9.zip
- Rename jakarta-tomcat-5.5.9 to tomcat for simpler upgrading in the future (if only Windows had symbolic links)
- Create a directory called tomcat-cluster-node1 that looks something like this (the files in the subdirectories were copied from the standard Tomcat installation):
/tomcat (renamed from jakarta-tomcat-5.5.9)
/tomcat-cluster-node1 (The subirectories' files are copied from the tomcat
installation.)
/bin (contains service.bat)
/conf (contains catalina.policy, catalina.properties, context.xml,
server.xml, tomcat-users.xml, web.xml)
/Catalina
/localhost (contains manager.xml, host-manager.xml, myapp.xml)
/logs (empty)
/temp (empty)
/webapps (empty)
/work (empty)
Because this installation is on a Windows server I decided to follow the adage "When in Rome, do as the Romans do" and make my Tomcat instances run as Windows Services. Fortunately Tomcat is ready to go with a Tomcat5.exe and a batch script to create the registry entries call Service.bat. The only changes I had to make to the batch file were a few lines at the top to set some environment variables:
set CATALINA_BASE=E:\tomcat-cluster-node1
set CATALINA_HOME=E:\tomcat
set JAVA_HOME=E:\jdk1.5.0_03
then I ran "Service.bat install Node1" and I now have a service that I can easily start and stop. You may want to change the service to "Automatic" to ensure that it gets restarted in the event of a server restart.
Now back to the Tomcat connector installation. I like keeping the redirector stuff separate from the tomcat installation so I created a directory called /tomcat-iis-connector that contains the following files:
isapi_redirect.dll (downloaded from the jakarta site)
isapi_redirect.reg (see below)
uriworkermap.properties (start with a copy from the tomcat/conf directory)
workers.properties (ditto)
The reg file contains some registry entries that the DLL uses at runtime to find your configuration information. Mine looks like this:
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Jakarta Isapi Redirector\1.0]
"extension_uri"="/jakarta/isapi_redirect.dll"
"log_file"="e:\\tomcat-cluster-node1\\logs\\isapi.log"
"log_level"="error"
"worker_file"="e:\\tomcat-iis-connector\\workers.properties"
"worker_mount_file"="e:\\tomcat-iis-connector\\uriworkermap.properties"
Now you have to actually tell IIS about the redirector DLL (notice the /jakarta/ prefix in the extension_uri entry in the reg file. This becomes important in a moment)
- Open IIS Manager and create a new Web Site.
- Create a virtual directory called "jakarta". This name must be the same as the prefix from the extension_uri value in the registry, and it must be executable.
- Go to the "ISAPI Filters" tab of your website's properties dialog and add a filter that points to the isapi_redirect.dll
- In the "Web Sites" properties dialog's Service tab select the "Run WWW service in IIS5.0 isolation mode" checkbox.
- Disable session state for your website (Properties dialog->Home Directory tab-> Configuration...->Options tab). Just let Tomcat handle your session timeouts.
Now all you have to do is configure your workers.properties file. Mine looks like this:
workers.tomcat_home=E:\tomcat
workers.java_home=E:\jdk1.5.0_03
ps=
worker.node1.port=8009
worker.node1.host=localhost
worker.node1.type=ajp13
worker.node1.cachesize=10
worker.node1.cache_timeout=600
worker.node1.socket_keepalive=1
worker.node1.recycle_timeout=300
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=node1
worker.loadbalancer.sticky_session=1
worker.list=loadbalancer
And then in the cluster-tomcat-node1/conf/server.xml make sure you identify the server with the same name you used when defining the worker in workers.properties, in this case "node1". Without this the "sticky sessions" won't work.
<engine name="Catalina" defaulthost="localhost" jvmroute="node1">
At this point I've only described the installation of a single Tomcat instance, but in reality I have four tomcat instances. So you can imagine more tomcat-cluster-node directories and a few more entries in workers.properties and the addition of those worker names to worker.loadbalancer.balanced_workers:
worker.loadbalancer.balanced_workers=node1, node2, node3, node4
Next you must define the URIs that should get redirected from IIS to Tomcat in the uriworkermap.properties file. Mine looks like this (of course you'll need to change the value of "mycontext" to the context of your app:
/mycontext/*.jsp=loadbalancer
/mycontext/*.do=loadbalancer
/mycontext/*.exe=loadbalancer
/mycontext/*.jpg=loadbalancer
/mycontext/*.gif=loadbalancer
/mycontext/*.png=loadbalancer
/mycontext/*.css=loadbalancer
/mycontext/*.js=loadbalancer
/mycontext/*.jpeg=loadbalancer
/mycontext/*=loadbalancer
Normally, I would like IIS to serve all my static content but I use struts tags to specify the location of images and the JSTL c:url tag to dynamically generate URLs. These tags rewrite the URL and not only include the name of the context (which is configurable at deployment time) but also include the jsessionid in the URL when not using cookies. Unfortunately IIS can't figure out what to do with the jsessionid so your pages come back without CSS or images. Not only do they look pretty awful but if you use js files some functionality may not even work. So I just map everything to Tomcat. On the plus side, deployment is simpler with the single WAR file.
Finally restart IIS and hope everything works! :-)
Monday, May 09, 2005
Updating my Resumé
I recently decided to update my resumé and decided that instead of using a proprietary document format that I would use HTML. If you think about it, a resumé is a great document for HTML. There's no need for an index, foot notes or a table of contents and the elements that remain aren't very complicated either. You have a couple levels of headers, some bulleted lists, and maybe a paragraph or two.
My initial step was to take my RTF document and dump it in a WYSIWYG editor. I used Nvu. I kept everything plain vanilla (no fancy fonts, font styles or colours) and basically edited away. When I was done, I had a factually correct document. The HTML was pristine and wasn't mucked up with a bunch of tags describing appearance. But on the other hand it was an incredibly boring looking resumé. No one was going to give me any extra marks for style.
So I decided I'd spice things up with some CSS. I ditched the WYSIWYG editor and broke out my favourite code editor, jEdit. The first step was to make everything XHTML compliant. I put in the correct doctype, made everything lowercase, closed every tag, and put quotes around all attributes. Then once that was passing the W3C XHTML validator I added a style section to the header and started editing. (Normally I'd use an external CSS and link to it from my HTML but I figured I'd probably be e-mailing my resumé to people and didn't want them to have to worry about multiple files)
The one thing that I wanted to avoid was adding structure to my document just so that I could lay things out (i.e., I didn't want to add tables all over the place just for the sake of layout). Secondly, I wanted the document to still render properly if someone decided to turn off stylesheets entirely within their browser. So I introduced several div elements as containers so that I could style and position blocks of content. My document is pretty hierarchical so this was actually pretty simple and wasn't really breaking my rule about adding tags for layout. As I worked I needed to read a bit more about CSS topics I had only briefly touched on in the past (specifically, float, relative and absolute positioning). I also had to decide on some colours and fonts but I just used some of my favourite sites as templates for those choices.
In the end I have an XHTML/CSS standards-compliant document that looks good in Firefox, Mozilla, Camino, Internet Explorer, and Safari. The content and the visual appearance code is nicely separated, even if they are in the same document, and it serves as a nice little showcase for my appreciation for standards and my ability to apply them to a web application.
I got my first callback. Was it the content or the styling? Maybe a bit of both. ;-)
[Update: I forgot to mention that the Firefox "Web Developer" extension is a great tool for graphically viewing outlines around the structural element of your HTML document and for seeing what would happen if CSS, graphics, or other browser functionality were disabled]
My initial step was to take my RTF document and dump it in a WYSIWYG editor. I used Nvu. I kept everything plain vanilla (no fancy fonts, font styles or colours) and basically edited away. When I was done, I had a factually correct document. The HTML was pristine and wasn't mucked up with a bunch of tags describing appearance. But on the other hand it was an incredibly boring looking resumé. No one was going to give me any extra marks for style.
So I decided I'd spice things up with some CSS. I ditched the WYSIWYG editor and broke out my favourite code editor, jEdit. The first step was to make everything XHTML compliant. I put in the correct doctype, made everything lowercase, closed every tag, and put quotes around all attributes. Then once that was passing the W3C XHTML validator I added a style section to the header and started editing. (Normally I'd use an external CSS and link to it from my HTML but I figured I'd probably be e-mailing my resumé to people and didn't want them to have to worry about multiple files)
The one thing that I wanted to avoid was adding structure to my document just so that I could lay things out (i.e., I didn't want to add tables all over the place just for the sake of layout). Secondly, I wanted the document to still render properly if someone decided to turn off stylesheets entirely within their browser. So I introduced several div elements as containers so that I could style and position blocks of content. My document is pretty hierarchical so this was actually pretty simple and wasn't really breaking my rule about adding tags for layout. As I worked I needed to read a bit more about CSS topics I had only briefly touched on in the past (specifically, float, relative and absolute positioning). I also had to decide on some colours and fonts but I just used some of my favourite sites as templates for those choices.
In the end I have an XHTML/CSS standards-compliant document that looks good in Firefox, Mozilla, Camino, Internet Explorer, and Safari. The content and the visual appearance code is nicely separated, even if they are in the same document, and it serves as a nice little showcase for my appreciation for standards and my ability to apply them to a web application.
I got my first callback. Was it the content or the styling? Maybe a bit of both. ;-)
[Update: I forgot to mention that the Firefox "Web Developer" extension is a great tool for graphically viewing outlines around the structural element of your HTML document and for seeing what would happen if CSS, graphics, or other browser functionality were disabled]
Thursday, May 05, 2005
Foosball
Someone at our office brought in their own table about a month ago and I've found myself rediscovering the fun of foos. I've also found myself checking into the history of the game. I was quite surprised to learn that in foosball's heyday in the 70's people won cars (porche, corvettes) and quite a bit of money (there was a $1,000,000 tour at one point)!
I even started looking into possibly buying a table. I went down to the local dealer showroom (pool tables, foos tables, poker tables, video games etc) and the salesman there took some time to really show me what makes a good table and what the differences are as you move up in price. Quite the education (much more fun than C#). So I'm looking at a Tornado brand table. The Cyclone or the Storm. We'll see if my fascination with the game lasts long enough for me to plunk down the money...
So do you want to see an interesting video? Check this one out. It's for the Bonzini table not the Tornado. It's amazing to see how well someone can control a foosball.
I even started looking into possibly buying a table. I went down to the local dealer showroom (pool tables, foos tables, poker tables, video games etc) and the salesman there took some time to really show me what makes a good table and what the differences are as you move up in price. Quite the education (much more fun than C#). So I'm looking at a Tornado brand table. The Cyclone or the Storm. We'll see if my fascination with the game lasts long enough for me to plunk down the money...
So do you want to see an interesting video? Check this one out. It's for the Bonzini table not the Tornado. It's amazing to see how well someone can control a foosball.
NeoOfficeJ
I've been using OpenOffice for a couple of years now but the thing I dislike most about it, is that it runs under X11 and just doesn't look or feel like a Mac app. It looks all gray and Windows95-ish and worse, the command keys are all messed up. So I finally tried NeoOffice/J and I'm quite a bit happier. It still looks more like a Windows app than a Mac app BUT the menus are at the top where they should be and the command keys are correct. It's fast, the fonts look better, it has a double clickable application icon and it doesn't use X11. So far so good. And its free. :-)
PSync to the rescue
PSync is a little Perl command app written for Mac OS X that synchronizes two directories. Perfect for doing backups. I finally put my second drive to work as a backup volume. Now when the time is right I can upgrade to Mac OS X 10.4/Tiger and see for myself what all the good press is about.
Two weeks after my C# course
Well all that course really did for me was to get me to appreciate Java more. C# is a pretty good copy of Java but it seems that most of the differences/compromises from Java seem to be for supporting legacy Windows components. I don't think that's a bad thing necessarily but unless you have a huge pile of C++ or COM code lying around, I think the choice of Java or C# would be pretty difficult, especially if you're developing web apps. Afterall, why constrain yourself to one platform and one application server? Also having experienced the limitations of Visual Studio for a week, I know that code editing can be made way more efficient (yay Eclipse!).
I think the place where C#, .NET and Visual Studio shines is in the creation of rich client applications. Dot-NET leverages all the native Windows components so your apps look good and behave well. Rich client .NET apps, like Java apps, seem to take a little while to get going but once you're there you don't really know you're running a .NET app. I think if IBM ever gets their act together and make a decent SWT GUI editor then Java may (finally) be a contender on the Windows platform. But for now MS has this all to themselves
So what have I really done with my new knowledge? Well not much.
I think the place where C#, .NET and Visual Studio shines is in the creation of rich client applications. Dot-NET leverages all the native Windows components so your apps look good and behave well. Rich client .NET apps, like Java apps, seem to take a little while to get going but once you're there you don't really know you're running a .NET app. I think if IBM ever gets their act together and make a decent SWT GUI editor then Java may (finally) be a contender on the Windows platform. But for now MS has this all to themselves
So what have I really done with my new knowledge? Well not much.
- I wrote a little application to interface with iTunes (which has a pretty full fledged COM interface). It just grabs the song title and artist of the currently playing track and throws it on the clipboard. Handy for sending someone an instant message.
- I also tried out ADO.NET with Mono. Mono ships with a driver for PostgreSQL. So I wrote a little command line app to connect, execute a query, and print out the results. Not too exciting but pretty easy.
- I spoke with the instructor about Object Relational Mapping and without any prompting from me, he suggested NHibernate. He's using it on his current project and says it works quite well. I really dig Hibernate so it's good to hear that C# developers can benefit from this technology as well.
- I tried to create a GUI using Windows.Forms on my Mac. That was a bust. Apparently it's possible but you have to install a bunch of other junk. I just wasn't that interested.
Friday, April 15, 2005
C# Course day five
I installed the latest version of Mono on my Mac and the latest version of NAnt (an open source build tool) and managed to compile some of the Lab sample code from this course.
- System.Threading namespace for creating threads, mutexes, etc.
- Thread class takes a ThreadStart object in its constructor. A ThreadStart class is a delegate that points to the method you want to run in the thread. Call Thread.Start() to actually kick things off.
- There are foreground and background threads and a Thread.IsBackground property. An AppDomain will not close as long as there is one foreground thread.
- Signalling between threads can be done with the WaitHandle class.
- You can create thread local storage by putting an attribute on a static variable [ThreadStatic] public static in count;
- Visual Studio kinda sucks for working with Threads. Eclipse is better for this.
- You can call Thread.Abort() to abort a thread, however a magic ThreadAbortException will get thrown and rethrown out of any catch block unless you call ResetAbort().
- To Synchronize a method use [MethodImpl(MethodImplOptions.Synchronized}] I think its easier to use Java's synchronized keyword.
- Can use lock{...} to define a critical section.
- The Interlocked class's methods can create more optimized locking for simple operations on shared data like increment and decrement.
- Can use a Windows OS Mutex to lock across processes. A Mutex is more expensive to use.
- A ReaderWriterLock allows multiple reader or only one writer at a time.
- The Timer class uses a delegate to call a callback method on a particular interval
- There is a ThreadPool class that is handy for executing short running methods in the background with a normal priority.
- IOCompletionCallback is used for processing data in a thread from the pool after an IO operation.
- Use syntax like [DllImport (
, Entrypoint= to call externall DLL methods., CharSet= MyMethodName([...]); - tlbimp.exe is for importing a COM DLL.
- There are roughly 10-40 instructions called when going from/to .NET from/to COM, not including the data marshalling. It is expensive so be careful.
- SQL & Oracle clients are written all in managed code (kinda like JDBC drivers) & are much faster than going through OLE DB drivers
Thursday, April 14, 2005
C# Course day four
Wow. The Serialization and Remoting functionality in C# looks just like Serialization and RMI in Java.
- Serialization is marked with an attribute [Serializable]
- Have the option of Serializing to XML (with a SOAP flavour)
- Remoting has the option of using HTTP, XML & SOAP or a binary protocol. Unfortunately the XML option isn't very interoperable with frameworks other than .NET.
- use {WebService(Namespace=http://www.example.com/endpoint)] attribute for declaring web service
- use [WebMethod] attribute for declaring exposed methods
- Suggest creating a virtual directory in IIS before creating Web Service project in VisualStudio so that you can control where the IDE puts your files.
- Can use WSDL.exe to read a wsdl XML file exposed through IIS to generate client proxies.
- When adding reference in Visual Studio you can change a property of the reference to dynamic so that the URL is stored in a config file rather than in the C# code.
So to summarize:
- .NET Remoting isn't getting much attention from MS
- The Web Services available in Visual Studio are good for simple stuff without transactions, security, reliability, etc.
- WSE 2.0 (Web Services Extensions) introduces transactions etc but there isn't and IDE support
- WSE 3.0 still being defined
- Indigo a MS term for their technology to make "serious" web services with transactions, security, etc. commonplace and easy to build with Visual Studio (1-1.5 years away)
Wednesday, April 13, 2005
C# Course day three
- COM is done
- Classic VB (6) is done
- Big sell job on garbage collection. Commentary: It's good (I am a Java developer after all) and yes you can introduce bugs doing it manually but most of the time developers are quite capable of managing memory.
- GC does heap compaction to deal with memory fragmentation
- destructors/finalizers in C# look like ~ClassName(){} and are used for implicitly freeing resources. More important in C# than Java because of Windows' finite resource limitations (e.g., Fonts)
- Unreachable objects with finalizers are moved to freachable queue & finalizers are not called on GC thread. Finalize thread comes along and calls finalizers and then on second GC run the object is collected. Which all means objects with finalizers stay around longer. Secondly their generational flags are bumped up meaning they're more expensive to clean up (i.e., more exhaustive GC search required). Don't use finalizers if possible.
- C# idiom is to provide an explicit method for freeing finite resources as well as an implicit destructor. If using the explicit method then call GC.SuppressFinalize(object) to prevent the GC from duplicating the work. The explicit method should be an implementation of IDisposable. Eclipse's SWT suffers some of this same dispose problem because it uses native Windows resources. Ugh!
- Finalizers are not guaranteed to run (like Java) so avoid them if possible.
- A try-finally block for freeing allocated resources can be replaced with something like using(Resource r1 = new Resource()){}
- WeakReference class allows an object to be collected if memory is low. Used for something like caching.
- Can use the Windows Performance Monitor (i.e., perfmon) for viewing the CLR Memory. Pretty graphs... ;-)
- There is multiprocessor support but uses a different CLR DLL (i.e., Workstation and Server). All console apps run using the Workstation VM unless you make some config changes.
- An unsafe block is available for executing code and preventing the GC from moving objects around in memory. This is important for calling C DLLs for example. Looks like unsafe{}
- IO Streams are very similar to Java. Functionality is added to the basic stream using the Decorator pattern. And there are Reader and Writer classes for dealing with text. C#'s one major difference is that there is just Stream not InputStream and OutputStream. Instead you define read or write using constructor parameters.
- There is a File and a Directory class is C#. Java only has a File class with an isDirectory() method. The File class has some handy Factory methods for creating Streams.
- There is a utility Path class for manipulating path strings.
- FileSystemWatcher allows you to eliminate directory polling and receive events for things happening to a file or a directory.
- IsolatedStorage is a handy class for providing 10MB of storage on the local file system for applications started from an http address. The data is stored in "c:\Documents & Settings\
\LocalSettings\Application Data\Isolated Storage\". The only problem is that the directories in here are cryptically named. - CredentialCache class useful for getting the credentials of the current user.
iPod Shuffle on Windows XP (at last)
During my C# course I tried plugging my iPod shuffle into the USB port of my Windows XP machine and voila! It mounted like a hard drive without any trouble at all. I could drag and drop files onto it and even see all my MP3s. Very nice. Now if I can only figure out why my Windows machine at work can't see it I would be very happy.
Tuesday, April 12, 2005
C# Course day two
Not a single Java comment today. Amazing.
- System.Globalization for i18n (internationalization)
- String.Format does println kind-of functionality. The patterns are a bit different however "The value is {0,-10:f2}"
- Did my first lab with Visual Studio. Struggled a bit with the syntax differences. Things like defining Properties in an Interface, or operator overloading, overriding methods (stupid virtual/override keywords), and defining an explicit cast operator.
- Eclipse is a way better code editor than Visual Studio. Studio may have other advantages (like visual form editing) but Eclipse owns this one.
- Can use syntax like @"c:\folder\folder2\file.txt" so that you don't have to escape each back slash. Well maybe if MS used a forward slash in the first place this wouldn't be an issue ;-)
- C# supports regular expressions that are designed to be compatible with Perl 5.
- IComparable = Java's Comparable interface and IComparerer = Java's Comparator
- There is not equivalent of Java's Set collection in .NET. Seems like an odd omission
- Can use the indexing syntax of square brackets (e.g., collection[2] ) with both hashmaps and lists.
- ArrayList.ReadOnly(list) is an easy way to make an immutable collection
- System.Collections namespace contains a StringCollection that is specially tuned for dealing with strings.
- Can call delegates asynchronously with IASyncCallback
- Can use += and -= instead of the methods Combine() and Remove() respectively for multicast delegates.
Monday, April 11, 2005
C# Course day one
A day-by-day, blow-by-blow account of my Microsoft C# course. I'll update this particular entry throughout the day.
First of all, why would I attend a C# course when I've been a Java guy for so long... Well this just comes down to ensuring that I'm open to all technologies. I know people who talk poorly about technologies that aren't their favorite and usually they bash away without knowing what they're talking about. Personally I like to bash from a position of knowledge not ignorance. ;-)
Secondly, I already looked at C# about a month ago and was fairly happy with what I saw. I'm really only lacking some knowledge about the frameworks.
Finally, it's free. A company I worked for about two and a half years ago already paid for this so why not take advantage of it.
So now onto the course...
First of all, why would I attend a C# course when I've been a Java guy for so long... Well this just comes down to ensuring that I'm open to all technologies. I know people who talk poorly about technologies that aren't their favorite and usually they bash away without knowing what they're talking about. Personally I like to bash from a position of knowledge not ignorance. ;-)
Secondly, I already looked at C# about a month ago and was fairly happy with what I saw. I'm really only lacking some knowledge about the frameworks.
Finally, it's free. A company I worked for about two and a half years ago already paid for this so why not take advantage of it.
So now onto the course...
- 10:30 AM I've learned nothing so far. Boring.
- I've sat quietly through some Sun, Java bashing from the instructor no less. That was a bit irritating. That will definitely come up in my evaluation.
- 12:16 PM Namespaces usually take the form of CompanyName.Application.Layer (e.g., Sundog.Retail.Data)
- Can have multiple entry points in an app (many classes with Main methods) just need to specify which one in compiler settings
- csc.exe is the command line compiler
- a "module" is equivalent to a Java .class file
- an "assembly" is equivalent to a Java .jar file. Contains a Manifest file that specifies version and other meta data.
- ilasm.exe produces assemblies (not sure about this...)
- ildasm.exe is a disassembler to look at manifest and generated MSIL code. ".NET Reflector" is a 3rd party tool that disassembles into C#, VB, or Delphi. Obfuscator may be good for commercial .NET
- Can use ngen.exe to precompile assemblies into native code. Not always better.
- Application Domains are like separate processes for different applications in one VM. It's done programatically so usually used by app server not individual apps.
- Can create C# alias when multiple classes from multiple namespaces have the same name. e.g., using CSStringComp = CompCS.StringComponent;
- 4:11 PM ASP Output cache allows the reserving of previously generated output. If the data's not changing quickly, this may be useful. Also works with page fragments.
- .NET Framework around 24MB. How does that compare to Java. Everyone used to complain about how bit it was.
- App can be launched from HTTP or File server and execution rights are reduced unless app is signed. Very much like Java WebStart.
- No DLL Hell. Assemblies are typically deployed privately (in the same dir as the exe).
- There is a "Gloabl Assembly Cache" (GAC) in c:\windows\assembly which is shared and can contain multiple versions of assemblies.
- Assemblies must be signed to go into the GAC. Apps are compiled against a specific version. Versioning is much better handled in .NET than Java.
- Visual Studio has a Setup project that can be added to a solution to create an MSI file (MS Installer). Nice touch.
- Java got bashed a couple more times and I had to correct the instructor and let him know that autoboxing, enums and attributes are all part of Java and that the default behavior of virtual methods isn't necessarily a bad thing. Jeesh. I hope he shuts up now. ;-)
- C# has structs but the instructor and apparently MS discourages using them. You don't get a performance boost and they're less flexible. Use only when you're interfacing with legacy code.
- enums are also good for interfacing with legacy code. The [Flags] attribute can be used to assign bit values.
- The internal keyword marks something for use by classes in the same assembly. Not quite the same as the package scope in Java.
- Use Object.ReferenceEquals() instead of Equals() (unlike Java). Here == and Equals() should mean the same thing.
- Can overload operators (+,-,*,/,%,<,>,==, etc) in C# using something like static public bool operator == (Class obj1, Class obj2){[...]}
- ToString() is here too
- Instructor made a big deal that implementing a Singleton in Java was hard. Here's an article he was referencing. Basically you do this in C#: public static readonly ExampleClass Instance = new ExampleClass(); Well in Java you do private static ExampleClass instance = new ExampleClass(); and provide a static accessor.
- Instead of using ExampleClass.class in Java you use typeof(ExampleClass) in C#.
- Operators like is, as, and typeof for working with Types.
- generics will show up in .NET 2.0. Already there in Java 1.5, but Anders Hejlsberg (MS .NET Architect) suggests that the Java implementation isn't as good, primarily because Sun chose not to introduce new bytecodes in the VM to implement this functionality.
- Can implement two interfaces that specify the same signature by explicitly defining the name of the interface in the method implementation.
- pinvoke is the way to call "classic" DLLs. Looks much easier than JNI.
- For COM compatibility .NET objects can be exposed as COM objects and COM objects can show up as .NET classes. Very reminiscent of Delphi.
Thursday, April 07, 2005
Libraries
Apparently someone was dumping some older computer books by donating them to our local public library to sell. Well I happened along and picked up the "pickaxe" book Programming Ruby (1st edition), Learning the bash Shell, and Learning Python (the last two from O-Reilly) for the princely sum of $1.50! Sweet! BTW: bash is the default shell and both Python and Ruby are installed with Mac OS X. Naturally. ;-) Public Libraries truly are wonderful things!
Wednesday, April 06, 2005
Those Damn Liberals
Over the last few days the Canadian press has been talking about an American blogger dishing the details about Jean Brault's testimony at the Gomery Inquiry into the federal sponsorship scandal. So I went over to Google, did a little search and found the blog that the press was talking about. If some of that stuff is correct then the Liberal party and former prime minister Jean Chretian are going to have a lot to answer for. It must be nice to be Stephen Harper right now...
Hibernate lets me down...
Well the new version of Hibernate is out there and apparently version 3.0 has been seriously worked over by the Hibernate team. Specifically I'm referring to the brand-new ANTLR-based HQL/SQL query translator... but back to that in a second.
I generally keep up with the latest version of Hibernate and up until I tried 3.0 it was a no-brainer. You just downloaded it and everything just worked. Not this time:
First of all, the packages all changed from net.sf.hibernate to org.hibernate. While it's nice that the package reflects Hibernate's domain I don't think this change really needed to be inflicted on its users. TopLink did that to me when it changed hands from The Object People to WebGain and then to Oracle. It's a pain in the ass.
Secondly, "Since it is best practice to map almost all classes and collections using lazy="true", that is now the default." While I agree with the point, I was a little annoyed to discover that much of my second level caching stopped working. Easy enough to fix but still...
Thirdly, back to the new HQL/SQL Query translator. It fails to parse several of my existing queries. Damn. Worse is that the documentation says I can set the hibernate.query.factory_class property to use the ClassicQueryTranslatorFactory but that doesn't work either. So I'm forced to use native JDBC calls instead. That's what Hibernate is supposed to help me avoid!
Finally, Hibernate 3.0 has a "revamped Query API". This was my whole reason for trying Hibernate 3.0 and unfortunately when I use criteria.createCriteria() or criteria.createAlias() the alias for the joined table doesn't show up in my generated SQL!!
Agghhh! I still like Hibernate (most of it still works) and I'm going to stick with v3 but this was not what I've come to expect of the Hibernate team. It sounds like the HQL/SQL parser thing was the right choice but this release needed a little more time in the oven.
I generally keep up with the latest version of Hibernate and up until I tried 3.0 it was a no-brainer. You just downloaded it and everything just worked. Not this time:
First of all, the packages all changed from net.sf.hibernate to org.hibernate. While it's nice that the package reflects Hibernate's domain I don't think this change really needed to be inflicted on its users. TopLink did that to me when it changed hands from The Object People to WebGain and then to Oracle. It's a pain in the ass.
Secondly, "Since it is best practice to map almost all classes and collections using lazy="true", that is now the default." While I agree with the point, I was a little annoyed to discover that much of my second level caching stopped working. Easy enough to fix but still...
Thirdly, back to the new HQL/SQL Query translator. It fails to parse several of my existing queries. Damn. Worse is that the documentation says I can set the hibernate.query.factory_class property to use the ClassicQueryTranslatorFactory but that doesn't work either. So I'm forced to use native JDBC calls instead. That's what Hibernate is supposed to help me avoid!
Finally, Hibernate 3.0 has a "revamped Query API". This was my whole reason for trying Hibernate 3.0 and unfortunately when I use criteria.createCriteria() or criteria.createAlias() the alias for the joined table doesn't show up in my generated SQL!!
Agghhh! I still like Hibernate (most of it still works) and I'm going to stick with v3 but this was not what I've come to expect of the Hibernate team. It sounds like the HQL/SQL parser thing was the right choice but this release needed a little more time in the oven.
Cocoa Core Data
When Apple introduced the binding controllers in Panther (Mac OS 10.3) they eliminated a lot of the glue code people used to write to keep the model and view of their applications in sync. Now they're aiming to make the persistence of the model simple too with Core Data, a new framework in Tiger (Mac OS 10.4). This article on Apple's Developer Connection website explains it with a bit more detail. While it somewhat resembles Object Relational mapping it looks to be a file based persistence mechanism. The developers of Delicious Library had good things to say about Cocoa Bindings:
...so I'm hoping that Core Data will be equally well received and productive.
We rewrote everything in a day or two—I think we deleted over a thousand lines of code that just wasn’t needed any more.
...so I'm hoping that Core Data will be equally well received and productive.
Tuesday, March 22, 2005
SSH
Although I haven't written anything here about SSH before I have written e-mail to friends about the usefulness of this great Unix command line utility. Basically SSH stands for Secure SHell. It differs from your normal shell in that it uses encryption. Now while in and of itself encrypted communications is a good thing, the thing that has made SSH so fantastic is it's ability to tunnel TCP/IP ports over the SSH connection. What does that mean? Well I have access to my work computer via Citrix. From that machine, through a cygwin initiated SSH session back to my home computer I can tunnel traffic to various services around the network. Like what you ask? How about Oracle, SQL Server, Tomcat, IMAP Mail, CVS, etc. anything with a TCP/IP port.
Now finally I'd like to point out that you can do all this with Mac OS X out of the box by simply clicking a checkbox. But you can do a few more things to make things more secure. One of those things is to use public-key based encryption which relies on not just a password but a encrypted public key as well (i.e., something you have and something you know). Checkout this series of articles for more information. They're Mac-centric but the content is fairly generic.
Now finally I'd like to point out that you can do all this with Mac OS X out of the box by simply clicking a checkbox. But you can do a few more things to make things more secure. One of those things is to use public-key based encryption which relies on not just a password but a encrypted public key as well (i.e., something you have and something you know). Checkout this series of articles for more information. They're Mac-centric but the content is fairly generic.
Subscribe to:
Posts (Atom)