<?xml version='1.0' encoding='UTF-8'?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/'><id>tag:blogger.com,1999:blog-26632145</id><updated>2008-01-28T14:52:42.378+11:00</updated><title type='text'>One Man Band</title><link rel='alternate' type='text/html' href='http://manichord.com/blog/'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default'/><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://manichord.com/blog/atom.xml'/><author><name>Maksim Lin</name></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>14</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-26632145.post-5674132689793250824</id><published>2008-01-28T14:46:00.000+11:00</published><updated>2008-01-28T14:52:42.413+11:00</updated><title type='text'>...and that is why you fail</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://upload.wikimedia.org/wikipedia/en/thumb/4/4d/Yoda-ep2.jpg/190px-Yoda-ep2.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 200px;" src="http://upload.wikimedia.org/wikipedia/en/thumb/4/4d/Yoda-ep2.jpg/190px-Yoda-ep2.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;On the weekend I helped my brother setup a new antenna for his house. Now sure we bought a brand new length of co-ax cable, mast-amp, splitter, connectors and only slightly used (my old) antenna. when I had mounted the antenna and run the first length of cable down from it through the roof, instead of wiring it up straight to the splitter, I first took the whole length, put (temporarily) a connector on the other end and tried it out by hooking it up to his tv. Sure enough only 2 of the 5 channels worked! Lucky I thought, not having yet used the splitter, I now only had 1,2,3, 4!! components to test: antenna, cable, amp, connectors. Yep, even though I thought I was being clever by doing some testing - I was already too late! and infact was trying to test which 1 or more of 4 different components had failed.&lt;br /&gt;To cut a longish story sort, I ended up doing a quick bypass of the masthead amp (which in this case happened to be the most complex component in the system) by virtue of sitting on the roof and holding the 2 pieces of coax together and sure enough the tv started getting all the channels. Now as usual, it was a bit of a painful lesson as it meant I wasted hours and ended up having to climbup onto the roof and ceiling space mutliple times, when of course I could easily have done a unit test of the amp while safely on the ground.&lt;br /&gt;So why didn't I test the amp to start with? Well it was made by someelse who should know what they are doing and I just *assumed* that they tested it thoroughly before giving it to us.&lt;br /&gt;After that, what I ended up doing was testing as much as possible each run of co-ax that I put in, because since even though the components (coax, connectors) were quite simple and not likely to fail, my use of them (I dont do cable runs for a living) was prone to error so deserved testing. But what if I had been unlikly with the cable and had got a batch with a break in it? Well I had my multi-meter with me, so I could easily have done a continuity test as well but of course I didn't since as I said I didn't think about testing all the components individually at the start, but rather half way through, by which time it was even too late to be able to test some components like the cable in isolation.&lt;br /&gt;&lt;br /&gt;The moral of this story: version 1.6.1 Helma now comes with the jala unit testing framework out of the box and unless you want to spend a lot of times climbing up and down ladders, I suggest we all start using it.</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2008/01/and-that-is-why-you-fail.html' title='...and that is why you fail'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=5674132689793250824&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/5674132689793250824'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/5674132689793250824'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-1322905273167524945</id><published>2007-08-28T14:12:00.000+10:00</published><updated>2007-08-28T14:16:16.072+10:00</updated><title type='text'>topic of the week</title><content type='html'>&lt;a href="http://www.dehora.net/journal/2007/08/phat_data.html"&gt;the need to go cold-turkey for our RDBMS addiction&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;some think the answer looks a bit like &lt;a href="http://www.infoq.com/news/2007/08/mnesia"&gt;this&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I really wish it was as easy as a &lt;a href="http://labs.google.com/papers/bigtable.html"&gt;java lib implementing this&lt;/a&gt;.</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2007/08/topic-of-week.html' title='topic of the week'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=1322905273167524945&amp;isPopup=true' title='1 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/1322905273167524945'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/1322905273167524945'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-1800858252500254471</id><published>2007-07-06T13:56:00.000+10:00</published><updated>2007-07-07T12:22:02.898+10:00</updated><title type='text'>the downside</title><content type='html'>I think &lt;a href="http://eddiesguy.blogspot.com/2007/06/creating-my-own-personal-hell.html"&gt;this guys&lt;/a&gt; biggest problem is he has a crap manager, I have a great one and it sure helps!</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2007/07/downside.html' title='the downside'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=1800858252500254471&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/1800858252500254471'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/1800858252500254471'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-2686427732205827583</id><published>2007-07-06T09:06:00.000+10:00</published><updated>2007-07-23T09:01:19.973+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='helma'/><title type='text'>"Simplicity" aka Maks's guide to Javascript for Java programmers Part I</title><content type='html'>Javascript (hence forth JS) in its current v1.5 (Ecma262 ) incarnation is a great small, powerful scripting language. A lot of Java developers seem to now be realising this (I'm a convert of about a year now) and given the similarities between the 2 languages might get tripped up.&lt;br /&gt;Also its very easy for new comers to get confuse between what's in the JS &lt;span style="font-style: italic;"&gt;language &lt;/span&gt;and what is provided by the web browsers that host the JS runtime that most people use JS in (but not all! Actionscript in Flash is a implementation of Ecmascript and you can use JS very nicely on the &lt;a href="http://helma.org/"&gt;&lt;span style="font-style: italic; font-weight: bold;"&gt;server-side&lt;/span&gt;&lt;/a&gt;)&lt;br /&gt;So here is my attempt at slightly damping down the learning curve.&lt;br /&gt;&lt;br /&gt;Lets start with the basics:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Almost everything is an Object.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;Objects&lt;/span&gt; are essentially Maps (i.e. collections of name, value pairs)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The name, value pairs are an objects &lt;span style="font-style: italic;"&gt;properties&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;There are &lt;span style="font-weight: bold;"&gt;NO&lt;/span&gt; classes.&lt;/li&gt;&lt;/ul&gt;How can you have objects without classes? Well do your Java Map objects have a class? No they are just simply a Map, whether you stick an Address, CORBA or String objects in a map its all the same, a Map is a Map and in JS a object is an object.&lt;br /&gt;&lt;br /&gt;BUT objects do have a prototype. An objects prototype is really just a special key in the object that points to another object, where the JS interpreter will look for a property requested for the current object but not found in the current object. If this sounds a bit a simple form of inheritance - it is, BUT just don't get carried away and start thinking its the &lt;span style="font-style: italic;"&gt;same&lt;/span&gt; as inheritance in Java.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;There are only a few built-in data types: Object, Array, Number, String, Function.&lt;/li&gt;&lt;/ul&gt;If you are paying attention, you would have noticed that the last data type was "Function". That is because functions (ie executing blocks of code) are an actual data type in JS and are in fact objects (remember almost everything is an object). What this means is that you can have functions as stand-alone entities. In Java of course there is not even the concept of a function - the only code you can have is methods which are inextricably bound to a Class and objects of that class.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Objects have methods&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Now we're back to more familiar ground. Because you could have an object property that points to a function object. this gives you a function tied closely to an object, aka a method. Again JS methods are simliar to Java ones (they get an implicit "this" reference) but again don't assume they are exactly the same.&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Everything (almost) is an object. Hence there are &lt;span style="font-weight: bold;"&gt;no&lt;/span&gt; "primitives" like Javas int, bool, etc. This means that is if you have a numeric literal, its a literal Number object and you can do stuff like:&lt;br /&gt;(42.1).toFixed(1)&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Objects can have a constructor function.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Again this is similar but &lt;span style="font-weight: bold;"&gt;not&lt;/span&gt; ths same as Java.&lt;br /&gt;&lt;br /&gt;In fact the truth is that JS is a "&lt;span style="font-style: italic;"&gt;new&lt;/span&gt;" &lt;span style="font-style: italic; font-weight: bold;"&gt;operator&lt;/span&gt; that will create a new "plain" object and then pass it to the function you give it as the argument to "new", calling that function with the newly created object as its &lt;span style="font-style: italic;"&gt;context &lt;/span&gt;(which just means the newly created object is set to "this" for the function call)&lt;br /&gt;So a line of JS like this:&lt;br /&gt;&lt;code language="javascript"&gt;&lt;br /&gt;var me = new Person();&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;in psuedo code is something like:&lt;br /&gt;&lt;br /&gt;make a new object&lt;br /&gt;call a function named "Person" with the "this" reference set to the new object&lt;br /&gt;set the prototype property of the new object to point to the Person function object&lt;br /&gt;assign the new object to the variable "me"&lt;br /&gt;&lt;br /&gt;So really there is nothing special about the function Rectangle except that we have written it with a view to using as a constructor but any function object can be called as an argument to the new operator - its just that it only makes sense for those that actually do something useful with their "this" reference - like initialising some properties, eg:&lt;br /&gt;&lt;code language="javascript"&gt;&lt;br /&gt;function Rectangle (firstName, lastName) {&lt;br /&gt;this.firstName = firstName;&lt;br /&gt;this.lastName = lastName;&lt;br /&gt;}&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Global variable are really just properties of the Global object&lt;/li&gt;&lt;/ul&gt;This might sound liek a minor point, but it actually matters alot when we get to  discussing scope in a minute because the global object is responsible for the global scope.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Functions can have local variables.&lt;/li&gt;&lt;/ul&gt;This might seem like a no brainer but its interesting because local variables are actually properties of a special object called the "call object" which is passed to every function when its called. In fact function parameters are also properties of this call object. Hmm, elegant but nothing special right, well lets get to the next bit...&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Functions have lexical scope.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Lexical scope? what the?&lt;br /&gt;Lexical scope just means scope of where functions are defined, not where they are called. Ok that doesn't help much, so maybe this will:&lt;br /&gt;&lt;br /&gt;Remember that call object I just talked about? well its actually the start of a "chain" (ie. ordered list) of objects that gets passed to a function to set its scope. So when you try to reference a variable in a function, JS looks through this chain to find the variable you are referring to. So what other objects are in this chain after the call object? Well its all the previous call objects.&lt;br /&gt;So for a function defined in the global scope, its just the Global object.&lt;br /&gt;And for a function called from with another function its just the Global object! That's right, because as I said at the start, lexical scope is about where the function is &lt;span style="font-style: italic; font-weight: bold;"&gt;defined &lt;/span&gt;not where its called from. This means that this magic "scope chain" is set-up when the JS interpreter sees the &lt;span style="font-style: italic;"&gt;definition &lt;/span&gt;of a function and is not changed when a function is actually called somewhere down the track!&lt;br /&gt;Which brings us  to:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Function can be defined &lt;span style="font-style: italic; font-weight: bold;"&gt;within&lt;/span&gt; other functions. &lt;/li&gt;&lt;/ul&gt;Now things can get a bit interesting with lexical scope. Because when you define a function inside another function, the inner function has in it the call object of the containing function. And so now the scop e chain of the inner function has its call object, the containing functions call object and then the global object (and so on if you have mor then 1 level of nesting). And remember this happens at function "&lt;span style="font-weight: bold;"&gt;definition time"&lt;/span&gt;  not function execution time.&lt;br /&gt;Well see if this helps:&lt;br /&gt;&lt;code language="javascript"&gt;&lt;br /&gt;function a() {&lt;br /&gt;var x = 2;&lt;br /&gt;&lt;br /&gt;  function b() {&lt;br /&gt;       var y = 3;&lt;br /&gt;       return y +  2;&lt;br /&gt;  }&lt;br /&gt;return  b;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var func = a();&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;code language="javascript"&gt;a = null;&lt;/code&gt;&lt;br /&gt;&lt;code language="javascript"&gt;&lt;br /&gt;alert("The answer is:"+ func());&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;Whack that in a html page and what do you think you will get? Yep 5! But stop and think about it for a second - b() is defined inside a()  but it uses a property belonging to a when its called in the alert box after a() has already returned &lt;span style="font-style: italic; font-weight: bold;"&gt;and after we set a to null&lt;/span&gt;, so it not even defined in the global scope any more !&lt;br /&gt;But if you remember that b()'s scope chain is setup at "definition time" it all makes perfect sense! Since at definition time b() got a()'s call object added to its scope chain (which contains the property/value "x = 2") and it keeps that scope chain forever (or at least til we reload the web page :-)&lt;br /&gt;Now to finish off belabouring this point, keep in mind that the objects in the scope chain (for the most part) are just JS objects. So for instance there's no reason why we can't change the values of their properties, say by using var x as a counter...&lt;br /&gt;&lt;br /&gt;&lt;code language="javascript"&gt;&lt;br /&gt;function a() {&lt;br /&gt;var x = 0;&lt;br /&gt;&lt;br /&gt;  function b() {&lt;br /&gt;   return x++;&lt;br /&gt;  }&lt;br /&gt;return  b;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;var func = a();&lt;br /&gt;a = null;&lt;br /&gt;alert("The first answer is:"+ func());&lt;br /&gt;alert("The second answer is:"+ func());&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So essentially var x in the call object of b()'s scope change is a lone "relic" of a()'s existence when the definition of b() was first processed but because all references to a() function object are gone, the x that b() is seeing in its scope chain is its own "private" variable, which brings us to:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Functions are closures&lt;/li&gt;&lt;/ul&gt;Which as we now now, simply means functions are not only data, but are "self-contained" keeping the scope they had when they were defined  not matter what happens afterwards during the execution of the code.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Because functions are actually objects they can themselves have properties.&lt;/li&gt;&lt;/ul&gt;An important example of this is the "special" prototype property I mentioned earlier that all objects get. When a new object is created, its prototype property is set to the prototype property of the "constructor" function object. And the prototype property of a function is usually initialised by JS to a plain, empty object. However you can then set anything you like on it:&lt;br /&gt;&lt;code language="javascript"&gt;&lt;br /&gt;function Person() {&lt;br /&gt;...&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;mrJS = new Person("Brendan", "Eich");&lt;br /&gt;&lt;br /&gt;Person.fullName = function() { return (this.firstName+" "+this.lastName);}&lt;br /&gt;&lt;br /&gt;alert("JS Creator: "+mrJS.fullName());&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Yep you read that right, since JS looks up property names it can't find in the current object, in the object assigned to its prototype property (and then if it can't find it there, in its prototype object, and so on) and at the time the property is used, you can assign properties to a prototype and all the objects which reference that object as their prototype will see the new property.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;There are some handy predefined objects, with handy methods: eg.  Date, Math&lt;/li&gt;&lt;/ul&gt;You don't get anything like Java's rich class library in JS, but there are quite a few handy methods in these objects which are defined by default in the global scope.&lt;br /&gt;And since JS is intended to be used as an embedded scripting language its assumed that the host environment (eg, &lt;a href="http://www.getfirefox.com/"&gt;web-browser&lt;/a&gt;, &lt;a href="http://helma.org/"&gt;web-server&lt;/a&gt;) will provide the required objects with lots of useful methods defined.&lt;br /&gt;&lt;br /&gt;Well that's about it for quick run through, of course there's lots more and the best place to find it is &lt;span style="font-style: italic;"&gt;the&lt;/span&gt; JS book, &lt;a href="http://www.oreilly.com/catalog/jscript5/"&gt;with the big rhino on the front&lt;/a&gt;.</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2007/07/simplicity-aka-makss-guide-to.html' title='&quot;Simplicity&quot; aka Maks&apos;s guide to Javascript for Java programmers Part I'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=2686427732205827583&amp;isPopup=true' title='1 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/2686427732205827583'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/2686427732205827583'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-7362852913551225839</id><published>2007-05-11T11:27:00.000+10:00</published><updated>2007-08-29T14:13:11.678+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='helma'/><title type='text'>(Helma + H2) == "to easy"</title><content type='html'>So I'd come across &lt;a href="http://www.h2database.com/html/frame.html"&gt;H2&lt;/a&gt;, the pure java sql rdbms engine written by Thomas Mueller (the original author of hsqldb) and had been menaing to give it a go, but never got past just firing it up and having a few quick clicks in the webbrowser based admin (which was pretty impressive all by itself!)&lt;br /&gt;But then the other day I was working on the windows partition of my laptop and needed a db for a &lt;a href="http://helma.org/"&gt;Helma&lt;/a&gt; app and couldn't be bothered downloading and installing the current win32 mysql package so decided to see if I could quickly get up and running with H2 instead. I was also thinking it would be good to have a quick and easy DB for a rapid prototyping and in memory db for testing of my helma webapps, so it was all worth spending a little time on and if it didn't work out I could always go through installing mysql.&lt;br /&gt;&lt;br /&gt;But boy did it work out. H2 is a fantastic app, with alot of thought put into it. Not only is it easy to get up and running, but its very well documented and has a a lot of nice features such as a batch file that not only starts the dbserver running with web-console enabled, but also puts a little icon in your system tray &lt;span style="font-weight: bold;"&gt;and&lt;/span&gt; opens up a new browser window all ready for you to login!&lt;br /&gt;The experience gets even better once you login with a nice ui that includes sql syntax auto-completion, history &lt;span style="font-weight: bold;"&gt;AND&lt;/span&gt; unbelievably editable tables of results! This puts to shame many of the dedicated java/native sql clients I've used in the past.&lt;br /&gt;&lt;br /&gt;And what about using it with helma? (the whole point of the exercise), well that was a piece of cake, just drop the h2.jar into helmas lib/ext folder, restart helma, pop the connection details into my applications db.properties and hey presto!&lt;br /&gt;&lt;br /&gt;But you want more? well for just $0 more, you get the full DB *embedded* inside your helma server.&lt;br /&gt;Yep that's right, since H2 has an "embedded" as well as client/server mode, all you need to do is shutdown the H2 server (right click on the systray icon), change the connection URL in your helma apps db.properties from say:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;jdbc:h2:tcp://localhost/col&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;TO:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;jdbc:h2:/data/h2/col&lt;/code&gt;&lt;/pre&gt;and bam! your H2 db is now running in the same JVM process as helma (very handy on a cheap, strapped for RAM webserver for example).&lt;br /&gt;&lt;br /&gt;But wait there's more! Yes how would you like to still have that nice web interface into the embedded DB? not possible you say, since now H2 is not running in a separate JVM - but in fact the H2 docs tell you exactly what to do&lt;a href="http://www.blogger.com/post-create.g?blogID=26632145#1"&gt;[1]&lt;/a&gt;, you just need to fire up H2's webserver when your app starts, so in your apps Global folder:&lt;br /&gt;functions.js:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;function onStart() {&lt;br /&gt; writeln("H2 web server started by"+app.name);&lt;br /&gt; app.data.h2WebServer = Packages.org.h2.tools.Server.createWebServer(null);&lt;br /&gt; app.data.h2WebServer.start();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;function onStop() {&lt;br /&gt; writeln("H2 web server stopped by"+app.name);&lt;br /&gt; app.data.h2WebServer.stop();&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;Then in your browser, goto http://localhost:8082/ and there's H2's web console waiting for you admin-ing pleasure!&lt;br /&gt;&lt;br /&gt;If you've got more then 1 app in your helma server, you won't want to start a new h2 webserver for each one, so in that case just make a new empty helma app, call it maybe &lt;span style="font-style: italic;"&gt;h2admin&lt;/span&gt;, pop the above code in there and your done&lt;a href="http://www.blogger.com/post-create.g?blogID=26632145#2"&gt;[2]&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Now that's what I call RAD!&lt;br /&gt;I wonder if the rails crowd will even believe me without a funky screencast demo...&lt;br /&gt;&lt;br /&gt;&lt;a name="1"&gt; [1]&lt;/a&gt; &lt;span style="font-size:85%;"&gt;Well actually the H2 docs tell you about how to fire up a DB in a servlet to be accessed by multiple webapps in the same tomcat container, but with a bit of lateral thinking and a quick look at h2.bat I got the idea.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a name="2"&gt; [2]&lt;/a&gt; &lt;span style="font-size:85%;"&gt;Of course this way H2 is running its own webserver alongside helma's one and I a nice future project would be to 'port' the admin web ui to be a helma app :-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Update: &lt;/span&gt;I'm now confident (crazy?) enough to use this on the test server, but by default the H2 web console won't accept connections for machines other than localhost, so to get  this to work you need to use this code instead:&lt;br /&gt;&lt;/span&gt;&lt;pre&gt;&lt;code&gt;function onStart() {&lt;br /&gt;   writeln("H2 web server started by "+app.name);&lt;br /&gt;   var args = java.lang.reflect.Array.newInstance(java.lang.String, 2);&lt;br /&gt;   args[0] = "-webAllowOthers";&lt;br /&gt;   args[1] = "true";&lt;br /&gt;   app.data.h2WebServer = Packages.org.h2.tools.Server.createWebServer(args);&lt;br /&gt;   app.data.h2WebServer.start();&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2007/05/helma-h2-to-easy.html' title='(Helma + H2) == &quot;to easy&quot;'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=7362852913551225839&amp;isPopup=true' title='1 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/7362852913551225839'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/7362852913551225839'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-8851041115429836155</id><published>2007-01-05T09:26:00.000+11:00</published><updated>2007-07-23T09:09:34.650+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>Maks' guide to LDAP for Busy Java developers</title><content type='html'>So maybe like me, you're a busy java webapp developer (isn't everybody these days?)  who just got told/decided for yourself that instead of creating yet another app for which users need to remember a username/password pair, that you will instead do the Right Thing and connect up to your company/organisations central LDAP (or ActiveDirectory) .&lt;br /&gt;And (again like me) you might even need to have cause to setup your own LDAP server either for testing or some other reasons you can't use the existing AD setup in your org.&lt;br /&gt;So instead of replicating the tedious hours of frustration that I've spent - let me give you a quick run down of the pertinent facts you need to get up and running.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;First the obligatory intro to LDAP:&lt;/strong&gt;&lt;br /&gt;its basically a tree of objects. Each object belongs to 1 or more  "classes". Classes are just sets of compulsory and optional attributes. Attributes a just name-value pairs (think java properties files).&lt;br /&gt;&lt;br /&gt;So getting a bit more specific, if you have a person class that has the compulsory attributes "firstname" and "lastname" and then another class called orgPerson that has a compulsory attribute "email" then you can have an object that has "belongs" to both classes and so will always have a firstname, lastname and email.&lt;br /&gt;eg.&lt;br /&gt;&lt;pre&gt;firstname: homer&lt;br /&gt;lastname: simpson&lt;br /&gt;email: hsimpson@springfield.com&lt;br /&gt;&lt;/pre&gt;Of course the above classes (and attributes) are made up, but are pretty close to the real thing, as in LDAP you can have any class you like, all you need to do is define a schema for it (just like with relational DBs really).  Handily, most LDAP server implementations seem to come with a whole bunch of predefined classes (not sure if they are actually a standard or just convention)  for users, groups, etc.&lt;br /&gt;&lt;br /&gt;Now the whole tree bit is just as easy, its basically just made up of objects (usually belonging to specific 'container' style classes) forming, well, a tree.  Now 'container' style classes are ones such as "o" (organisation), "ou" (organizational unit), etc. There is also "dc" which is normally used when creating a tree based on DNS names (eg. www.springfield.com)&lt;br /&gt;&lt;br /&gt;Now the only slightly wierd thing about LDAP is the way the naming syntax works, its all about commas. So to say the homer belongs to the staff group at the springfield site of the bruns power company you would write:&lt;br /&gt;uid=homer, ou=users, ou=springfield, o=burnspower&lt;br /&gt;&lt;br /&gt;this is assuming that the homer object has am attribute called "uid" that identifies it (its "Relative Distinguished Name" in LDAP speak)  and that you've already defined the "users", "springfield" and "burnspower"  org units and org respectively. And how would you do that, well you could use a &lt;a href="http://jxplorer.org"&gt;LDAP &lt;/a&gt;&lt;a href="http://jxplorer.org"&gt;GUI tool&lt;/a&gt; to connect to your LDAP server or write ldif files (which are basically serialised text versions of parts of the LDAP directory tree) to define them,&lt;br /&gt;eg.&lt;br /&gt;&lt;pre&gt;dn: o=burnspower&lt;br /&gt;objectClass: top&lt;br /&gt;objectClass: organization&lt;br /&gt;o: burnspower&lt;br /&gt;&lt;br /&gt;dn: ou=springfield,o=burnspower&lt;br /&gt;objectClass: top&lt;br /&gt;objectClass: organizationalUnit&lt;br /&gt;ou: springfield&lt;br /&gt;&lt;br /&gt;dn: ou=users, ou=springfield,o=burnspower&lt;br /&gt;objectClass: top&lt;br /&gt;objectClass: organizationalUnit&lt;br /&gt;ou: users&lt;br /&gt;&lt;/pre&gt;As you can see, you just define each object one after the other, and with the "dn" (Distinguished Name")  you set the "path" of the object in the tree, just like you would if you were creating a series of nested folders on your PCs filesystem.&lt;br /&gt;&lt;br /&gt;Now this brings us nicely to doing some real work, like actually setting up the LDAP server.  Basically while there are a few different commercial and open source LDAP servers out there, basically ignore all the rest and use OpenLDAP. Even though it might me slow and chunky, it is the lest painful way to go if you've just got a linux box and not much time or patience.&lt;br /&gt;Often OpenLDAP will be part of the default OS install or just a few clicks/commands away using your package manager of choice.&lt;br /&gt;Once you do have it installed and configured (for OpenLDAP usually just means setting a couple of options in the &lt;span style="white-space: pre;font-family:monospace;" &gt;/etc/openldap/slapd.conf)&lt;/span&gt;, use something like the above ldif files to set up your basic  directory structure and then you can just go start plonking your users in there (again using wither ldif files or via GUI) . The main thing you need to decide is what class(es) you want to use for your user objects  - for myself I've found inetOrgPerson had all the attributes I needed.&lt;br /&gt;eg.&lt;br /&gt;&lt;pre&gt;dn: uid=homer ou=users, ou=springfield, o=burnspower&lt;br /&gt;objectClass: inetOrgPerson&lt;br /&gt;objectClass: organizationalPerson&lt;br /&gt;objectClass: person&lt;br /&gt;objectClass: top&lt;br /&gt;cn: Homer Simpson&lt;br /&gt;displayName: HomerSimpson&lt;br /&gt;givenName: Homer&lt;br /&gt;mail: homer.simpson@burnspower.com&lt;br /&gt;mobile: 122 333 4567&lt;br /&gt;sn: Simpson&lt;br /&gt;uid: homer&lt;br /&gt;userPassword:: adlr0912384nq4o358ndfadasl&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-style: italic;"&gt;Note1: &lt;/span&gt;the user has both the inetOrgPerson and organizationalPerson classes in a kinda inheritance way to pickup all the attributes we want to use.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Note2:&lt;/span&gt; the above userPassword attribute is how my gui ldap browser exported the ldif file, but I suspect that the correct way to specify them (for OpenLDAP) at least is:&lt;br /&gt;{CRYPT}AF387HED3SDA&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Note3:&lt;/span&gt; all the above password binaries are just random typing on my part and so dont match :-)&lt;br /&gt;&lt;br /&gt;Setting up groups is also pretty straight forward, the 2 handy classes you want are groupOfNames and groupOfUniqueNames. Note that both have attributes which let you specify the  members of the group  by having multiple  instances of that attribute,&lt;br /&gt;eg.&lt;br /&gt;&lt;pre&gt;dn: cn= Managers,ou=groups,ou=springfield,o=burnspower&lt;br /&gt;objectClass: groupOfUniqueNames&lt;br /&gt;objectClass: top&lt;br /&gt;cn: Managers&lt;br /&gt;description: the bosses&lt;br /&gt;uniqueMember: uid=monty, ou=users, ou=springfield, o=burnspower&lt;br /&gt;uniqueMember: uid=smithers, ou=users, ou=springfield, o=burnspower&lt;br /&gt;&lt;/pre&gt;And that about covers it from the LDAP side of things.&lt;br /&gt;&lt;br /&gt;Now we can actually get to the java side and setup a single authentication service.&lt;br /&gt;Basically LDAP has lots of different ways to do authentication, most of which seem very complicated and are definitely overkill my mine and most small installs, so I'll just stick to the simple ones:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Method 1.&lt;/span&gt;&lt;br /&gt;First of you need to know that in LDAP-speak logging into to an LDAP server is called 'binding'. When you "bind" to the server, you can do it as a particular user as long as you specify the users "DN" as the login.&lt;br /&gt;You also give the password and the LDAP server goes looking for the password attribute for the object given you specified in the DN (eg. uid=homer ou=users, ou=springfield, o=burnspower) and if the bind is successful you know the user is authenticated and hooray, you're done! Once you have bound to the server, you can then also grab all the users details (email, lastname, whatever) using the supplied DN to lookup the user object for yourself.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Method 2.&lt;/span&gt;&lt;br /&gt;Another way to do it is to use an "admin" users login to bind to the LDAP server, fetch the user object for the given DN and then compare the password attribute in your app code. You might want to do this for instance if you need to check which groups a user belongs to but the user themselves dont have permission to access the groups part of the directory tree (I forget to mention that you can set permissions for users to read/write (or not) any part of the tree - again just like you do with a filesystem). So you bind to the LDAP server as an 'admin' user which does have permission to go looking up the groups (or whatever) part of the directory tree.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Security Side Note:&lt;/span&gt;&lt;br /&gt;One thing  should point at this stage is that while the LDAP protocol itself is binary (bit wierd to find that out in this age of internet text protocols - at least its defined in some RFCs)  its still all sent in the clear, so the usual modius operandi is to do all the LDAP connections over SSL so that people don't go snooping on your passwords in the net traffic.&lt;br /&gt;&lt;br /&gt;Anyway, now that we've covered the connecting to server and authenticating theory, the actual java code (for method 1) is a walk in the park:&lt;br /&gt;&lt;pre&gt; &lt;code class="Java"&gt;&lt;br /&gt;     public boolean authenticate(String username, String password) {&lt;br /&gt;&lt;br /&gt;     String userSuffix = ",ou=users,ou=springfield ,o=burnspower";&lt;br /&gt;     String userRDNPrefix = "uid=";&lt;br /&gt; &lt;br /&gt;     String hostname = "ldap.burnspower.com";&lt;br /&gt;      String port = "389";&lt;br /&gt;&lt;br /&gt;     String userRDN = userRDNPrefix+username;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;     Hashtable env = new Hashtable();&lt;br /&gt;     env.put(Context.INITIAL_CONTEXT_FACTORY,&lt;br /&gt;         "com.sun.jndi.ldap.LdapCtxFactory");&lt;br /&gt;     env.put(Context.PROVIDER_URL, "ldap://"+hostname+":"+port+"/");&lt;br /&gt;&lt;br /&gt;     env.put(Context.SECURITY_AUTHENTICATION, "simple");&lt;br /&gt;     env.put(Context.SECURITY_PRINCIPAL, userRDN+userSuffix);&lt;br /&gt;     env.put(Context.SECURITY_CREDENTIALS, password);&lt;br /&gt;&lt;br /&gt;     // Create the initial context&lt;br /&gt;     try {&lt;br /&gt;         DirContext ctx = new InitialDirContext(env);&lt;br /&gt;     } catch (AuthenticationException ae) {&lt;br /&gt;         System.out.println("Invalid Login");&lt;br /&gt;         return false;&lt;br /&gt;     } catch (NamingException e) {&lt;br /&gt;         e.printStackTrace();&lt;br /&gt;         return false;&lt;br /&gt;     }&lt;br /&gt;     return true;&lt;br /&gt; }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;And voila! one less set of passswords for your users to remember.</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2007/01/maks-guide-to-ldap-for-busy-java.html' title='Maks&apos; guide to LDAP for Busy Java developers'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=8851041115429836155&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/8851041115429836155'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/8851041115429836155'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-116493260279083226</id><published>2006-12-01T11:19:00.000+11:00</published><updated>2007-07-23T09:01:19.974+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><category scheme='http://www.blogger.com/atom/ns#' term='helma'/><title type='text'>top 10 reasons I dont use rails</title><content type='html'>So after a very nice dinner catching up with an old friend, I got asked why don't I use rails for my next webapp project. I replied about how I keep meaning to learn rails (and even bought &lt;a href="http://www.apress.com/book/bookDisplay.html?bID=10178"&gt;a book to read&lt;/a&gt;) but that I'm more comfortable sticking to &lt;a href="http://helma.org"&gt;helma&lt;/a&gt; (the javascript-based app server framework I'm using).&lt;br /&gt;But this got me thinking, apart from my inherent laziness, why aren't I using rails?&lt;br /&gt;Well heres my top 10 reasons after a bit more thinking about it:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;helma is implemented on top of a standard java servlet container (Jetty) so I get to reuse all my existing j2ee knowledge/experience and techniques (eg. mod_jk connector to apache)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;it uses standard java technologies (eg. JDBC) so again same as above&lt;/li&gt;&lt;li&gt;it can directly and very easily use any java library and at this point, its arguable java has surpassed even C as the library lingua-franca, especially for things you do for webdev&lt;/li&gt;&lt;li&gt;Using Java libraries means if something goes wrong I get a java exception trace which is helpful (since I mainly use oss java libs which come with source) unlike the less helpful: "Segmentation Fault" that you would get with using C libs with rails&lt;/li&gt;&lt;li&gt;Another thing about being able to use Java libs is that its really easy to write my own, wrap up/modify existing ones, etc. which I definitely can't do with C libs (my C coding days are a long way behind me)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I only need learn 1 new language for both the client and server side programming tasks. Its arguable the Ruby is a nicer/better lang then JS but JSs simplicity really appeals to me (warts &amp;amp; all)&lt;/li&gt;&lt;li&gt;While they are hardly alike (except for having a common first name) I find javascript syntax at least close enough to javas' to feel quite comfortable and not get a mental 'jarring' that happens every time I try to read ruby code&lt;br /&gt;&lt;/li&gt;&lt;li&gt;JS is also becoming a very popular language and while ruby isn't exactly hard to learn for java programmers, JS is certainly better for me at my current work where the only other tech people are web designers with only JS or AS (actionscript) knowledge&lt;/li&gt;&lt;li&gt;performance with helma is excellent, especially with jetty and the rhino JS engine that uses "under the hood" and the memory footprint is excellant too. Now I've only heard here say about rails (rubys) poor performance but thats enough to put me off, especially since with helma I know I can always fall back on using standard java profiling tools and optimising the frameworks underlying code (got know chance to do that with rails ruby interpreter written in C)&lt;/li&gt;&lt;li&gt;Even though its not the "out of the box" templating system, I can use Velocity templates with helma in a fairly nice way (and its such a simple integration that I've taken over maintaining it from the original author and have stated adding some small enhancments of my own). As far as I understand, rails goes down the whole nasty "code in pages" road (ala JSP) and that leads to no place I want to be.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;well they aren't really in any particular order of importance but for me they are pretty compelling reasons to stick with helma and only read a rails book in my (very limited) spare time.&lt;br /&gt;now there are downside compared wit what I already know about rails:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;no scaffolding&lt;br /&gt;&lt;/li&gt;&lt;li&gt;no builtin unit testing&lt;/li&gt;&lt;li&gt;no builtin support for db migrations&lt;/li&gt;&lt;/ul&gt;but so far none of these are deal breakser for me and in fact I'm slowly working on adding those features to helma myself.&lt;br /&gt;And another one of the down sides to using helma vs rails is the huge community (comprised of a fair few j2ee refugees) that has sprung up around rails. I certainly don't feel the need for that with helma but I think it would be nice not to be off on my own little island - so I'm finally going to set aside a bit of time and write up a short series of helma "intro" articles here - which if they work out ok, might even form the basis of a nice little book: 'server side js: web development with helma" :-)</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2006/12/top-10-reasons-i-dont-use-rails.html' title='top 10 reasons I dont use rails'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=116493260279083226&amp;isPopup=true' title='2 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/116493260279083226'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/116493260279083226'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-116005270243314276</id><published>2006-10-05T22:42:00.000+10:00</published><updated>2007-07-23T09:09:11.624+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>Better fonts in Ubuntu - full stop</title><content type='html'>Now I'm the first to admit I dont have the best eye sight in the world, but ever since i started using ubuntu and even going back to the days I was using fedora even I've noticed that the fonts in Gnome have always been "fuzzier" and looked worse then similiar sized fonts in windows XP. This has been very clear on my laptop where LCD subpixel rendering makes a difference.&lt;br /&gt;&lt;br /&gt;Today I finally got really sick of them and despite all the posts on various blogs and forums going on about how its just peoples imaginations and fonts on Ubuntu/linux/gnoe really do look better then winXP or that its just a matter of twiddling with the Gnome font settings I just went ahead and installed 3 packages based on some recent pathces to the releavant libaries. I found the deb packages &lt;a href="http://diego.aureal.com.pe/archives/2006/05/25/better-font-rendering-on-my-lcd-yes-in-linux/"&gt;here&lt;/a&gt;&lt;br /&gt;and thanks to this very nice person my fonts finally look decent in ubuntu (gnome). At last!&lt;br /&gt;&lt;br /&gt;Now I just need to figure out how to make patched debs based on ubuntu's latest sources since the update manager now keeps trying to replace the versions I just installed with "newer" packages which of course don't have the patches and rtunr my destop to it former ugliness.</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2006/10/better-fonts-in-ubuntu-full-stop.html' title='Better fonts in Ubuntu - full stop'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=116005270243314276&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/116005270243314276'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/116005270243314276'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-115979357018880830</id><published>2006-10-02T22:23:00.000+10:00</published><updated>2007-07-23T09:10:15.359+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>sad, sad world</title><content type='html'>So I just finished reading a very &lt;a href="http://ftp.squeak.org/docs/OOPSLA.Squeak.html"&gt;interesting article&lt;/a&gt; about the building of squeak - an implementation of the smalltalk language. One of the key points of the article I thought was that the authors got a big productivity boost by actually writing the squesk vm in smalltalk (or actually a subset of it). And then they converted into C for compiling to get good performance. Which is fair enough, I reckon C seems to be a more popular byte-code the JVM or CLR byte codes :-)&lt;br /&gt;No lets have a look at the Java world, as far as I know, out of all the JVM out there, there's a grand total of 1 that is actually written in Java. But even then, JikesVM is a nightmare to build with wierd dependencies and some kind of code-generation in the build too. Can anyone even tell me why they ned code generation for a VM? Ok it is meant as a research VM rather then a production one, but I havn't heard of any of the C-based JVMs doing this.&lt;br /&gt;So anyways, obviously all the Java community believes in Java being a superior language that they all went and wrote their VMs in...C!&lt;br /&gt;Now Im not sure how the mono crowd do with their VM, but at least their new VB compiler is &lt;a href="http://tirania.org/blog/archive/2006/Aug-19-1.html"&gt;self hosting&lt;/a&gt; as is their &lt;a href="http://www.mono-project.com/CSharp_Compiler"&gt;C# compiler&lt;/a&gt;.&lt;br /&gt;Of course their is some hope, may OSS projects are now switching to using Eclipses Java compiler which is written in Java.&lt;br /&gt;But no decent small JVM in Java along the lines of &lt;a href="http://jamvm.sourceforge.net/"&gt;JamVM&lt;/a&gt;.&lt;br /&gt;And then theres the lovely &lt;span style="font-style:italic;"&gt;monolithic&lt;/span&gt; gnu classpath. Which must be credited with doing well to implement the now enormous "standard" java class library but is about as modular as a obelisk and weighing in at around 8MB!! is hardly light-weight let alone suitable for use in embedded or small device applications. Even worse it is absolutely riddled with native code dependancies, which while good for quickly implementing the huge Sun-created APIs does not exactly make it easy to port.&lt;br /&gt;Now you might be expecting me to say that I've had enough and am just going to write my own - well I would if I had a bit more time, but for now I'm just going to put up with it all and see if I can just get JamVM up and running nicely on my 770 but if I get really adventerous I might even  try cutting classpath down to a proper (J2ME CLDC 1.1) size.&lt;br /&gt;On the other han, my love affair with javascript script continues and I note there are no self-hosting implementations of it either...</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2006/10/sad-sad-world.html' title='sad, sad world'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=115979357018880830&amp;isPopup=true' title='1 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/115979357018880830'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/115979357018880830'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-115029138007487307</id><published>2006-06-14T22:38:00.000+10:00</published><updated>2007-07-23T09:09:11.624+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>a dapper world</title><content type='html'>well now that dapper has gone final (aka Ubuntu version 6.06 has been released) I've installed it on my laptop. Unfortunately I've been too busy to test the beta's or 'flight' versions hat have been released during it development cycle so I have only myself to blame that I need to use the following work around to get suspend working (found on &lt;a href="http://desrt.mcmaster.ca/macbook.xhtml"&gt;this blog entry&lt;/a&gt;):&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;One thing about sleep: vbetool needs to save and restore your video state in order to have working video on resume.  Currently, on Macbooks this is broken.  This is caused by a mistake: the vbesave init script comes before the acpi init script.  This means that laptop-detect will report to vbesave that you are not on a laptop and vbesave will not save your vbestate.  Matthew Garrett is working on a fix, but in the mean time a workaround is to edit /usr/sbin/laptop-detect and insert a line 'exit 0' right after the #!/bin/sh (always report that we're a laptop).&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Not pretty, but since I'm pretty sure my laptop should infact be running inlaptop mode, I think its ok for now.&lt;br /&gt;&lt;br /&gt;also to get my funky special acer keys to work (especially the little flashing "you've got mail" light) I needed to do the following:&lt;br /&gt;$ sudo -s &lt;br /&gt;# echo "acerhk" &gt;&gt; /etc/modules &lt;br /&gt;# exit&lt;br /&gt;&lt;br /&gt;Well, at least its supposed too. My keys work, but no flashing light yet...&lt;br /&gt;&lt;br /&gt;[Update] Bah, dont know whta happened at first, but a reboot later and my you-have-mail blinken light is going strong once more.&lt;br /&gt;Now I just need to figure out how to get my new rt2500 wifi card working with NetworkManager, but thats a story for another day...</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2006/06/dapper-world.html' title='a dapper world'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=115029138007487307&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/115029138007487307'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/115029138007487307'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-114921299168389062</id><published>2006-06-02T11:16:00.000+10:00</published><updated>2007-07-23T09:01:19.974+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>fight the future</title><content type='html'>According Javascripts creator (Brendan Eich) blog this is the future of JS:&lt;br /&gt;http://developer.mozilla.org/presentations/xtech2006/javascript/&lt;br /&gt;&lt;br /&gt;Well if thats the future JS, I'm buying a tardis and staying in the past.&lt;br /&gt;I'm definitely in the camp that would like to have the current bugs fixed but have the core language left well alone. &lt;br /&gt;To explain why I think this way, I should give some background: &lt;br /&gt;I've been a Java programmer (mainly J2EE) for the last 6 odd years and its only recently (triggered by all the ajax hype and being sick of the huge bloated ediface that J2EE has become) that I've taken the time to learn Javascript and discovered what a wonderful little language it is. And I use "little" in a very positive sense, its one of the things that really attracted me to it, unlike much more complex languages like Java or even complex scripting languages (perl, python). &lt;br /&gt;Infact I'm now so firmly on the JS bandwagon using it not only for browser client-side work, but also server side via the brillant &lt;a href="helma.org"&gt; Helma Webapp framework/server&lt;/a&gt;.&lt;br /&gt;Having now done close to 5 months of solid JS server side development, including almost work on over a dozen small apps (2 already in production use) I really am appreciating the power of using a scripting language to do web development "in the small" as well as the simpliticity and yes, &lt;emph&gt;elegance&lt;/emph&gt; of JS. &lt;br /&gt;Now of course there is no reason why I can't just stick with the current javascript "1" for my server-side coding even if Mozilla and others push ahead with JS2, but one of the other big reasons I like using JS is that I now only need to use &lt;strong&gt;1&lt;/strong&gt; language for both server and client side coding (with only the occasional drop into Java for a bugfix or using a 3rd party lib, since Helma is written in Java).&lt;br /&gt;Now the above are all just &lt;emph&gt;personal&lt;/emph&gt; reasons for leaving JS as is, but here is a more pragmatic one:&lt;br /&gt;for good or bad, I belive a lot of JS's popularity comes from its small size and simplicity, its an easy language to learn and use, yet is still powerful and flexible enough to handle a amazing variety of tasks. &lt;br /&gt;&lt;strong&gt;But&lt;/strong&gt; its still a scripting language and as such it should not be used  where its not the best solution - "programming in the large" is one such place scripting languages do not belong. For that is why we have Java and with Rhino we can have the best of both worlds, using each language for the tasks that suit it best. Making JS2 a 'a Java/Python lite" and trying to get it to work for programming in the large is just not going to work, what you will get is a new language which will no longer be suitable for the quick, simple programming "in the small" tasks that its used for now.&lt;br /&gt;Of course I doubt this little rant and others like it will have any effect on stopping JS2, since it seems that its being strongly pushed by Brendan and alot of the big powers in the web browser world, but you never acheive anything without trying...</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2006/06/fight-future.html' title='fight the future'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=114921299168389062&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/114921299168389062'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/114921299168389062'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-114911801761320135</id><published>2006-06-01T09:15:00.000+10:00</published><updated>2007-07-23T09:09:54.829+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript'/><title type='text'>the little things</title><content type='html'>here's something I learnt the hard way a couple days ago and thought I'd better put it here so I don't forget it next time:&lt;br /&gt;Javascript event handlers (eg. onclick) execute a whole block of javascript, not just necessarily 1 statement. This is easy to forget if all you are doing is calling a function (eg. verifyDelete()) and want to use the return value of the functions as return value of the event handler ( because if you give a event handler a return value of 'false' it won't execute the action it was called on - ie. a lcik on a link won't actually cause the browser to load that link).&lt;br /&gt;&lt;br /&gt;Thus, this &lt;strong&gt;doesn't&lt;/strong&gt; work:&lt;br /&gt;&lt;br /&gt;&amp;lt;a href="delete" onclick="verifyDelete();"&amp;gt; Delete Me &amp;lt;/a&amp;gt;&lt;br /&gt;&lt;br /&gt;while this &lt;strong&gt;does:&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;a href="delete" onclick="&lt;strong&gt;return&lt;/strong&gt; verifyDelete();"&amp;gt; Delete Me &amp;lt;/a&amp;gt;&lt;br /&gt;&lt;br /&gt;Yes the return statement is important, since even though I'm doing just one function call in the onlcik handler definition, I could quite as easily have written 100 statements (seperated by semicolons) so without the return thres no way for the onlcik handler to know what the return value from my block of code is.</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2006/06/little-things.html' title='the little things'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=114911801761320135&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/114911801761320135'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/114911801761320135'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-114637255119285602</id><published>2006-04-30T14:28:00.000+10:00</published><updated>2007-07-23T09:09:34.651+10:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><title type='text'>email the hard way</title><content type='html'>So I needed email server (MTA) capability for a feature on the personal project I'm working on.&lt;br /&gt;I figured that I had a few choices:&lt;br /&gt;- use sendmail (default on linux) or one of its alternatives (postfix, exim, etc)&lt;br /&gt;- use a different thirdparty MTA, preferably a Java-based one&lt;br /&gt;- use a "managed service" like fastmail, who I already use very happily for my inbox/IMAP&lt;br /&gt;&lt;br /&gt;Fastmail would probably have been the easiest path, but I decided I might want to have more control and my VPS service gives me a much bigger bandwith allocation then fastmail would. Having decided o do it myself, I was very hesitant to use the notorious sendmail (its just scary to be able to write   a book of hundreds pages long about an app that does a relatively simple job) or even its supposed 'simplier' alternatives like postfix, so I hunted around for a simple Java based one and found James (from apache) ZeroToaster, a cheap commercial java app and &lt;a href="http://www.ericdaugherty.com/java/mailserver/"&gt;JES&lt;/a&gt;, pretty much the same thing, but open source.&lt;br /&gt;&lt;br /&gt;So I of course went with JES and the initial out-of-the-box experience was excellant, 30 min &amp; I was up and running send/receiving emails, and that included changing my DNS MX records.&lt;br /&gt;&lt;br /&gt;Unfortunately after running it for a few hours it got into a nasty loop of repeatedly throwing an exception trying to deliver a malformed email it received (yes I had spam start coming in &lt;span style="font-style:italic;"&gt;within  minutes!&lt;/span&gt; of starting it up).&lt;br /&gt;But this is where the power of oss does shine, being a nice simple app (the reason I avoided James like the plague) I grabbed the src-code zip, found the offeneding code and added some code to put aside malformed emails and fixed a null pointer bug in the shutdown code for good measure! &lt;br /&gt;&lt;br /&gt;So probably for less tha a couple of hours of work I now have a working light MTA, with just enough features that I need and a resoanble confidence that I can fix other problems that might turn up. The only downside is that the sourceforge project for JES seems to have been abandoned for over a year, so for now I've just imported the code into my own subversion repo.&lt;br /&gt;&lt;br /&gt;Still need to come up with a little wrapper to start it via rc script.&lt;br /&gt;And I've found on JES's maillist that someones had success with compiling it with GCJ, with excellant results in terms of memory footprint and performance, so theres something else to look into.&lt;br /&gt;&lt;br /&gt;[Update] Doh! Just found a patch on the sroucforge project page that fixes the problem I found with malformed emails (actually bounce mails with an empty address).</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2006/04/email-hard-way.html' title='email the hard way'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=114637255119285602&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/114637255119285602'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/114637255119285602'/><author><name>Maksim Lin</name></author></entry><entry><id>tag:blogger.com,1999:blog-26632145.post-114595243245472104</id><published>2006-04-25T17:13:00.000+10:00</published><updated>2006-04-25T18:21:25.186+10:00</updated><title type='text'>D.I.Y.</title><content type='html'>So, I finally admitted that I don't have time to whip up even a quick personal blogging app, especially since I wanted to document it as I went, along the lines of the 15min blog app screencast that the &lt;a href="http://www.rubyonrails.org"&gt;rails crowd has on their website&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So I decided that if I was going to use a ready made blog app, rather than doing it myself, I'd at least try to go the whole web app route and rather than installing an app on my laptop or on my server, I'd use a web service style app and decided to try Google's Blogger, since I remembered it has the option of publishing to your web server and not just using their website.&lt;br /&gt;Well so far, (its only my first post) so far, so good: all I had to do was create a directory in my public html directory on my server, plugged-in my sftp login and all done. I did have one hiccup when I changed the ftp path but didn't realise I also needed to change the 'archive' path, but apart from that its a nice looking, clean, easy to use interface.&lt;br /&gt;&lt;br /&gt;I still plan to make my own blog app when I get a bit more spare time, but for now Blogger looks good and I can keep working on my current project (more details on that soon) and have somewhere to write my thoughts on it.&lt;br /&gt;&lt;br /&gt;PS. Oh and just found it has a &lt;span style="font-style:italic;"&gt;very&lt;/span&gt; nice spell checke, but one which ironically doesn't recognise words like 'Blogger' and 'blog' and no well to choose British over US spelling, but oh well no one can be perfect - I'm still very happy with it, well done Blogger &amp; Google.</content><link rel='alternate' type='text/html' href='http://manichord.com/blog/2006/04/diy.html' title='D.I.Y.'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=26632145&amp;postID=114595243245472104&amp;isPopup=true' title='0 Comments'/><link rel='replies' type='application/atom+xml' href='http://manichord.com/blog/atom.xml' title='Post Comments'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/114595243245472104'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/26632145/posts/default/114595243245472104'/><author><name>Maksim Lin</name></author></entry></feed>