Internet Explorer 9…. wow?
Okay, so you'll never make a IE convert out of me. I think I speak for the web developer community as a whole when I give Internet Explorer and Microsoft a great big middle finger salute.
HOWEVER! After downloading the Internet Explorer 9 Platform Preview, I got the shock of my life. An Internet Explorer that is taking a DECENT effort in supporting web standards that are almost as old as myself?! Could this be?!
Seriously, their new SVG implementation is amazing. HTML5 support. Hardware accelerated Javascript processing and DOM rendering. CSS3? BORDER-RADIUS SUPPORT?! This is certainly not the Internet Explorer I've come to love to hate.
Of course, I can easily dismiss all of this with the simple statement "5 f*****g years too late, chump". However I can't bring myself to do so, when I am continually reminded of the fact that this family of browsers still makes up a stupid amount of the market today. Yes, IE share is slipping, but I truly wonder if we'll ever see that glorious day where IE drops below 40-50% market share. If the migration of standard consumer PCs ensures that we see a good portion of users running on IE9 rather than the joke we've come to call IE7, or the slightly less humerous joke we've come to call IE8 ... well, that's certainly the lesser of two evils isn't it?
Unfortunately, from what I've read, IE9 probably won't be around for another year or so. So in the meantime, I'll continue to burn baby animals on the IE altar, hoping the gods of Microsoft will hear my pleas for my mortal webapplication to function correctly in their worthless POS software (I ain't talking about no point of sale here either).
Hopefully in that time they'll improve their laughable ACID3 score. Then again, maybe not. Best not to make people too happy, might start putting their faith in you or something ...
How to access Facebook API from Chrome Extension
So following on from my previous post, I decided I wanted to try two new things at once: Facebook API and a foray into developing a Google Chrome extension. With the notification API that will (hopefully) twig on in other major browsers, I'm writing an extension that will display a desktop notification when a Facebook notification is received. All that will be required is for Chrome to be running.
Step 1 was to play around with Chrome extensions. I haven't worked with plugins/extensions in any other browser, but I have to say.... Google NAILED this. It's so intuitive and straightforward. So easy to debug, so much power. I love you Google.
Anyway. Step 2 was where things got interesting - connecting to Facebook via the Javascript API and Facebook Connect. This proved to be quite complex. Facebook Connect has this fascination with the whole cross domain communication channel (XD for shortness) nonsense. Basically, this requirements essentially means to use the Javascript API you need to be hosting it on a standard web server to be able to add the xd_receiver.html file in a public-facing area where Facebook can see it.
After digging around the site for a while, I came across their fancy new Open Source Javascript SDK, I couldn't help but notice this didn't make a mention of the XD setup anywhere, so I assumed perhaps I might be able to work with this system better. As it happens, my suspicions were correct. The new JS library has some crazy voodoo magic set up so that an XD file isn't required, there's some kind of "XD proxy" running on the Facebook servers which will send login session data along the line to the JS library, using either document.postMessage or some Flash workaround thingy (not really sure how that works, don't particularly care.)
I immediately tried to use it in a Chrome extension, but alas! There was a few issues. I came up with workarounds for both though.
Issue #1 - the API does the following in the constructor:
_domain: {
api : window.location.protocol + '//api.facebook.com/',
cdn : (window.location.protocol == 'https:'
? 'https://s-static.ak.fbcdn.net/'
: 'http://static.ak.fbcdn.net/'),
www : window.location.protocol + '//www.facebook.com/'
},
Great! That would be fantastic if our chrome extension was running on http, but the protocol when running from options or background.html pages is "chrome-extension://". So when the API went to make with the server side communications, it was trying to remote to chrome-extension://api.facebook.com, which of course is not really gonna work.
My solution to this was to just fudge it by putting the following snippet in before using the FB lib anywhere:
FB._domain = {
api : 'https://api.facebook.com/',
cdn : 'https://s-static.ak.fbcdn.net/',
www : 'https://www.facebook.com/'
};
With that change, the API won't have any more tantrums when trying to phone home. Easy!
Issue #2 - Facebook Connect is still broken.
This one was the biggie. Essentially, even though the new API does some cool hocus pocus with XD, it's still referencing the "origin domain" in the request, this original domain is of course just going to be the extension URL, which is not terribly useful, as Facebook will freak out when it gets a request coming from an invalid URL. I tried fudging the origin to a valid domain (dodgy I know, I was getting desperate). Interestingly, Facebook was fine with this, but of course when the request came back to the browser and the XD proxy tries to postMessage() the session data back, the browser freaks out as it looks like an XSS attack.
There might be other ways around this drama, but I opted for what I feel to be a fairly elegant solution.
Essentially, I opted to "pretend" I'm something of a desktop application trying to authenticate with Facebook application (which is true in a sense, I suppose). This Developer Wiki page gave me some insight into how to authenticate my application with the FB user the old-fashioned way.
The idea is this: popup the login/app-authenticate page manually with a special URL, setting the return URL to a random dummy Facebook page they have running for desktop app clients: http://www.facebook.com/connect/login_success.html. When the user visits the login page, once they have logged in and allowed the app access (or if they are already logged in and have already allowed the app), they are redirected to a page that has the session data in the querystring encoded in JSON. Login achieved.
So I set about doing this in my extension, simple enough to start with:
var win = window.open("http://www.facebook.com/login.php?api_key=
Great! If I was a *real* desktop application and I was running a Webkit/IE/whatever browser instance as some kind of evil overlord, I could just detect when the browser redirects to login_sucess.html, grab the querystring, parse the session data out of it, and be on my merry way! I'm running in a browser though, so how about I just access the child window that I opened with window.open, access the location.search property and parse that? "NO", says the magical little pixies living inside the browser, "That would be against my strict Same Origin Policy (SOP, kinda like ... sop story, teehee)!!!".
Fair enough. There was an easy enough workaround though, I just embedded a content script via the Extension to sniff out the session data when it became available, and send it to the main extension. Like so:
Add the trigger for the content script to the extension manifest.json file:
"content_scripts": [
{
"matches": ["http://www.facebook.com/connect/login_success.html*"],
"js": ["prototype.js", "intercept_session.js"]
}
],
I threw prototype in there just for convenience sake, as you'll see in the next step.
Then intercept_session.js looks like this:
var params = window.location.search.toQueryParams();
if(!params.session) return;
var session = JSON.parse(params.session);
chrome.extension.sendRequest({message: "setSession", session: session}, function() {
window.close();
});
What this code does is parse the querystring (using Prototype), then check if the session data is present. If it is, parse the JSON into the session object and send it off to the extension Background Page via the extension message passing system to be saved.
The background page simply has this:
var session = null;
if(localStorage.session)
{
session = JSON.parse(localStorage.session);
}
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
if(!request.message)
return;
switch(request.message)
{
case "setSession":
{
localStorage.session = JSON.stringify(request.session);
session = request.session;
sendResponse();
break;
}
case "getSession":
{
sendResponse(session);
break;
}
}
});
Again, pretty straightforward stuff. I'm using the groovy new HTML5 local storage to remember the session data even if the browser is closed. The message handler simply listening for a session to be passed to it. When a session is provided, it will save it to local storage and a local variable. The getSession functionality is so other areas of your chrome extension can retrieve the session as needed (for example if you have a popup and want to query FB from there or something). You could obviously use this session anywhere as needed.
And that's that! From here you can make API calls to your hearts content. There's obviously some important things left out here, stale checking of the session when the background page loads up for example. Also, requesting extended permissions is not covered here, but it's pretty much the same as how the login deal works anyway. You would just update the login_success.html intercept script to check if this was a response for extended permissions, and check the querystring to ensure the permissions were supplied.
I've cooked up a quick little demonstration of this stuffs. Click here to install a demo extension that will add a button to the right of your address bar, which will show some clickable icons of 5 of your friends in a popup. You can also see the code for this extension here.
Time for me to go finish this extension!
Shiny Desktop Notifications from Google Chrome
So I was dicking around in Google Calendar the other day, updating settings and trolling for any cool new Labs stuff to enable... Anyway, I made some changes and clicked submit. I was provided with the ol' yellow InfoBar that asked me for permission to allow something to ... blah blah blah. I was a on a Google site and I have pretty much entrusted my soul to Google already - so I didn't bother reading it before clicking Allow.
Imagine my surprise when a sexy little desktop notification popped up in the bottom right of my screen! Intrigued, I did a bit of Googling, there's a couple of news posts about it, but nothing substantial... other than the design doc hosted on dev.chromium.org.
It's currently only available in the developer channel of Google Chrome. If you're running the dev channel, then check out the example below:
For those interested, that code that powers this little example can be found here.
Very cool stuff. There are so many places this would come in handy. Super Facebook notifications, anyone?
PDF eh?
So I've been working on this little contract project for a good few months. One of the biggest outcomes of the system is for it to compile a PDF containing some 250+ odd pages of data that the system maintains. This PDF is in print-ready format, complete with bleed+trim, header and footer, and other page-by-page design elements. The generated PDF is incorporated into a book that is published annually. Essentially the PDF I'm generating makes up most of the "meat" of the book.
It's been a pretty interesting experience. Since the system I developed for the client is written in Java, I needed a Java-based library to work with. I evaluated what was already out there ... iText, FOP and the like. Most of them seemed great, but I wasn't confident I'd get the job done with these. I was especially concerned with FOP, as it seemed to be somewhat stateless, I needed alot of control over the output of the PDF, things like being able to calculate widths and heights of text blocks on the fly, specific setups of margins that I can change at will (because this is a book PDF I needed to change margins on odd/even pages to compensate for book spine) etc.
In the end I settled for a pretty obscure library called Java FPDF. I was confident with this choice because I've worked a fair bit with the original PHP library - FPDF. I actually used the original library to complete a similar task to the one at hand... albeit a far simpler version.
It came with a few bugs out of the box (MultiCell with borders or fill was broken, there was a simple fix however), I also refactored the original codebase a little bit, some silly things were being done like imagedata being loaded as byte[] data and then put inside a String.
The only major complication I ran into with this library was when I realized that it didn't have support for embedded fonts like the original library does. I ended up coding this support in and writing a little utility PHP script that converts the original FPDF font definition files into a JFPDF readable one. This complication ended up being quite educational however, as I had to plumb the murky depths of the PDF file specification to understand how font files are embedded and referenced.
I'm planning on packaging up the changes and improvements I made to the Java FPDF library in hopes that it will benefit someone else.
As for the original task, I've almost completed the initial revision ready for client review. I have no doubt there will be many tweaks and improvements requested but I can't wait to see the end result in a tangible form. I actually got to handle one of the books that was outputted by the previous PHP project I mentioned before. It was a pretty amazing feeling to hold something physical that resulted from my long nights of caffeine-driven code-jockeying. I know this project is going to be even more rewarding than that experience due to how much more complex and refined this upcoming book output system is. I guess this is what it feels like to ship a boxed product. Haha.
Next stop ... working on projects that I haven't severely under-quoted on. Profitable projects AHOY!
iPhone says hello
So I bit the bullet lat weekend and got an iPhone. I must say, I'm not in the least disappointed. This device easily meets all the expectations I had of it, and then some.
From a hardware perspective the unit is rock solid, I haven't had any issues with the performance of the device. The battery life, or rather the shortness of it, took me by surprise somewhat. However this being my first smartphone I'm probably just not used to the demands constant 3g connectivity and a large touchscreen have on the poor battery.
The OS and general usability of it are nothing short of fantastic. I didn't need to read any kind of manual or even a "Get Started" guide to get the hang of everything. Initially the onscreen keyboard vexed me, but I wasn't fully aware of how it worked. After getting the hang of it my typing speed went through the roof, to the point where I'm already typing faster than I do with t9 input.
Of course my favourite aspect of the iPhone is the third party apps. I've got apps that let me connect to my windows work pc using RDP, translate text, convert currencies, do my net banking, and the list goes on. As it happens, I'm writing this blog entry using the fantastic WordPress2 app.
With all the exciting cloud based apps popping up and the steadily increasing support developers are affording mobile devices, I can't wait to see what 2010 brings for my iPhone to tickle my nerd fancy. As much as I hate you Apple, thanks for a device that just works!
IE + AJAX == Caching???
So I'm finishing up a fairly straightforward web booking system for a firm I'm working for. Everything is just about done so of course the final (and much dreaded) task is to make sure everything looks pretty, and works! Numerous CSS hacks and several hot showers rocking back and forth with blood-shot eyes later .... I now have the site looking fairly consistent in all the major browsers.
The system also has some AJAX mixed in for good measure, with standard HTML fallbacks if the client-side code falls over (you know, 'cos I have little faith in myself ...). Internet explorer was giving me some bizarre results with these AJAX methods, so I went digging.
As it happens, it was the same ol' story, Internet Explorer aggressively caches practically anything it can. This isn't necessarily a bad thing, but as usual Firefox, Chrome, Safari etc don't exhibit the behaviour.
I have actually run into this issue in several other projects, the way I generally solved it was to just generate some "entropy" in the request URL querystring to ensure IE fetched the data properly each time. This time I Google'd and looked a little deeper.
As it happens, caching HTTP GET requests is actually considered the "right" thing to do, so Internet Explorer actually chose this time to stick to standards and shove it in the face of everyone else. Somewhat ironic, considering they seem to go out of their way to do the complete opposite most of the time.
The solution is to just make POST requests to your endpoint, it seems to eliminate any caching IE thinks it should be doing. This has been posted all over the net already of course, but I felt to reiterate it because it's such an obvious solution to a very frequent and frustrating issue!
Hibernate Annotations Eager Fetching Woes
So I've been working on a moderately complicated Java EE project utilizing Spring + Hibernate + GWT lately. I ran into an issue lately that got me more frustrated than I have been in quite a while.
The project is primarily all about information modelled for a particular industry in Australia. There's a decent amount of information stored. There's a handful of root entities that have lots of Set's of other entities. The semantics in the way this data is administered via GWT and RPC mechanisms persuaded me to opt for fetching all information in the main entities EAGERly. I didn't notice it at first but once I the MySQL database started with fill with data I noticed that latency and memory usage in the app was climbing exponentially.
Another bizarre issue was that calling list() on the root entities would return large amounts of duplicates. After Googling I found out this was because of the @CollectionOfElements and @OneToMany entity mappings I was using. Furthermore, some of the root entities were referenced by other root entities, and when loading the assosciation between the two root entities, I'd be getting horrendous lag followed by a painful java.lang.OutOfMemory exception.
For other reasons I had completely ruled out reverting back to LAZY loading mechanisms on the data, so I had to spend a few hours trying to fix the problem. The godsend was a comment made by "Andrey Trubin" at this URL: http://stackoverflow.com/questions/1093153/hibernate-collectionofelements-eager-fetch-duplicates-elements
As it happens, annotating all @CollectionOfElements and @OneToMany fields with @Fetch(FetchMode.SELECT) eliminated all my headaches. It might have a bit of a performance hit on your data loading, but in my case this was neglible to actually having a data access layer that works
Hope this helps someone!
ATL/MFC dependancies in Visual Studio 2008 Express
Apparently, the Express versions of Visual Studio like to pretend there's no such thing as ATL or MFC. There's an easy workaround however.
First, download the Platform SDK at http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en
You can deselect most of the components, just install the build environment for the Core Platform SDK. Add the PSDK\Include\atl and PSDK\Include\mfc directories to your build path in VC2008Exp.
Finally, follow the instructions at this URL: http://www.codeproject.com/KB/wtl/WTLExpress.aspx from step 4 onwards.
Windows Media Player Plugin Wizard with VC2008Express
So I couldn't figure out how to get the Windows Media Player Plugin Wizard that ships with the Windows SDK to show up in Visual C++ 2008 Express. I was following the instructions found @ http://msdn.microsoft.com/en-us/library/aa969509(VS.85).aspx but it still wasn't showing.
My problem is I was putting the wmpwiz files in C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcprojects and not C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\Express\VCProjects. Someone's probably going to tell me I'm stupid, and you know what? They're probably right.
Also to get the Wizard working, use the wmpwiz2005.vsz file, and change the second line from
Wizard=VsWizard.VsWizardEngine.8.0
to
Wizard=VsWizard.VsWizardEngine.9.0
Windows 7 eh ….
Damnit. I can't find anything about Windows 7 to hate
Have been using it for a few days now. From the initial bootup everything was incredibly smooth. All my hardware was fine (including my USB wireless adapter), didn't need to install software or drivers for anything.
It runs beautifully, I don't have concrete numbers obviously but it really feels just as smooth and responsive as a vanilla installation of WinXP. Compatbility has been fine, I haven't come across any applications I use frequently that aren't working or exhibiting odd behaviour. I love the new taskbar while it is a big change I found it very natural and intuitive straight away, without needing to read any tips or tricks, or seek help.
While not really important or relevant, I must say I'm thoroughly enjoying the desktop background slideshows, some amazing art and the LAST place I would expect to find it is on a vanilla Microsoft Windows installation. Fantastic
The Windows Virtual Machine beta is ok, but it's just that, a beta. It's still pretty rough around the edges and there's plenty of kinks to be ironed out. Also Windows Media Player 12 was a bit dodgy, it didn't want to remember my media library everytime I closed it down. Beyond that I really haven't had any issues.
Dear Microsoft, thank you for designing an operating system that works!
