Monday 27 May 2013

Hiding Javascript validation errors in Eclipse Juno

So you are working on a project that includes some third party Javascript libraries, and your editor is Eclipse (I'm on Juno, but no doubt this issue affects Indigo or even farther back...) - anyhow, you import the .js file into your nice clean project and bang! The Problems tab shows errors in the script

For example, I get errors with libraries like jquery.mobile-1.3.1.min.js
Syntax error on token "Invalid Regular Expression Options", no accurate correction available
and handlebars.js (1.0.0.rc4) raises three
Syntax error on token ",", delete this token
Syntax error on token ")", ( expected
Syntax error on token "]", delete this token
and of course the problem is not "real" - it is just Eclipse's implementation of the Javascript validator.

So if you are a braver coder than me you could edit these files and fix the issues and hope that doesn't break any other part of the library :/  OR you can suppress the errors in Eclipse.

However you don't want to suppress all Javascript validation because then you wouldn't see your own errors! (And I make plenty).  So here is how to exclude just the third party libraries...

1. You want to keep all your third party librarries in a different path to your own .js files - I use a js directory, below that I have a lib directory where jquery et al go.  So thats a path like
<PROJECT>/WebContent/js/lib/*
2. Right click on the Project, navigate thus Properties -> Javascript -> Include Path.

3. Click the Source tab, expand your WebContent node so you can see "Excluded".

4. Select Excluded, click the Edit button, then add an Exclusion pattern of
 js/lib/*
then click Finish, OK, then do a new build if one doesn't kick off automatically.

Now you should have no more phantom error reports from the third party libraries.

Thursday 16 May 2013

How to kill all database connections from your SQL Server restore database script.

So when I'm building an app, especially before launch, I like to have scripts that completely drop and rebuilds my local, local test, and production databases from the relevant DDL files, then add data where needed.

Then I write .bat scripts so I can invoke the same set of scripts for each environment.

This works great except sometimes the DROP DATABASE statement fails due to a lingering connection:
Msg 3702, Level 16, State 4, Server SOURCECRAFT-PC\LOCALDB#C12079B7, Line 13
Cannot drop database "databasename" because it is currently in use.
Msg 1801, Level 16, State 3, Server SOURCECRAFT-PC\LOCALDB#C12079B7, Line 2
Database 'databasename' already exists. Choose a different database name.
Sometimes, maddeningly, you have to close your server connection from SQL Server Management Studio and exit Visual Studio 2012 before whatever connection will let go - which is not terribly productive.

The solution is to add this before your DROP DATABASE script. It quietly kills any lingering connection you might have, allowing your script to work as it should every time, and crucially allowing you to leave Visual Studio 2012 and SQL Server Management Studio open while you drop and recreate your database.
USE [master]
GO
-- this is to kill any connections lingering, like Visual Studio
ALTER DATABASE [databasename]
SET OFFLINE WITH ROLLBACK IMMEDIATE
ALTER DATABASE [databasename]
SET ONLINE
GO
-- real script begins here...
DROP DATABASE [databasename]
GO

Hope that helps you out just a little.

Tuesday 14 May 2013

Fixing Twitter OAuth 401 errors due to server time

So if you're like me, your Twitter app (youpickedafinetimetoleaveme.com) had been happily authorizing user access tokens and secrets via OAuth against Twitter since forever, then all of a sudden bang! You start getting stack traces all over your browser with an Exception a bit like this:

"oauth.signpost.exception.OAuthNotAuthorizedException: Authorization failed (server replied with a 401). This can happen if the consumer key was not correct or the signatures did not match."
(For the record, I'm using the excellent Signpost OAuth Java library to handle the low level OAuth functionality, but this error would happen regardless how you handle your OAuth authorizations...)

Now I have a guilty little secret to share. A while back, Twitter updated their API, and there was all this fuss about legacy apps breaking, and well, you know what - mine didn't break, so I ignored all of that, did nothing and went about my day. Until now. Seeing this error happen I thought my laziness had come home to roost. Not an uncommon feeling. So I went and updated the aforementioned Signpost, along with JTwitter and Scribe (it's a long story), and updated some code, and tests pass and it works on my machine just fine, but you know what - when I uploaded it to production it didn't fix a thing.

The actual problem is kinda implied in that last part of the Exception message - "...the signatures did not match". It turns out my Debian server clock time was incorrect. Twitter will 401 an OAuth attempt if the signature is not correct - and sender machine DateTime is part of that check. Local clock was fine.

To check if this is your problem, from the server command line type

date

and if that date doesn't look right, this is probably your problem. Even if it isn't, having your server in sync can only be a good thing, right? Press on to see how to update your server clock on Debian.

Turns out more recent distributions of Debian have some issue that prevents clock sync from the server hardware - so they generally drift out of time unless you are running something that keeps it in sync via NTP. So the solution to this problem is simples:  update your server clock.

Here's how I did that, from command line on the server machine:

1. Install ntp to keep the machine in sync, and ntpdate as a manual sync utility 

sudo aptitude update 
sudo aptitude install ntp 
sudo aptitude install ntpdate


2. Check the current server date

date

3. Sync via a remote time server

sudo ntpdate pool.ntp.org


4. Check the current server data again, it should be different now, dare we say it - correct?

date


5. Lastly, set ntp started on your machine

/etc/init.d/ntp start


And you're done.