Friday, November 26, 2010

Grails, Quartz and JavaMelody

Hi there!

It was just another day, just another app... And yet another Spring gotcha that took 4 hours of my life away...

Let's start from the beginning.

We wanted to add Quartz scheduler to our existing app. The application was monitored from the beginning using the grails-melody plugin. All was nice and dandy right up to the point where we wanted to have the jobs displayed in the monitoring page.

The reason it was not displayed was that the Spring thingy that creates the scheduler is not a straight up implementation of the basic usage of Quartz pattern but it added one nasty thing to it: whenever a job is created it is removed from the central registry. I can't stress that enough that the path of least resistance has been sooo broken here!

What added to the disaster was that the guys that created the Quartz plugin forgot to make the necessary configuration option available to turn the misfeature off.

Result: it's just impossible to see monitoring of jobs in a humane way!

Here's what you need to do to make it work again (nasty hack - you've been warned!):

1. in GrailsMelodyConfig.groovy add the following line:

javamelody.'quartz-default-listener-disabled' = true

2. in spring/resources.groovy copy the imports and the definition of the following beans:

quartzJobFactory, quartzScheduler

3. copy the loadQuartzConfig private method and the line "def config = loadQuartzConfig()" from the QuartzGrailsPlugin.groovy

4. add the exposeSchedulerInRepository = true setting to quartzScheduler

That does the trick but it's as ughly as it gets.

Here's a working example.

I've submitted a bug report to the guys that maintain the Quartz plugin so that they make the necessary extension so that the infernal exposeSchedulerInRepository parameter is configurable.

Have fun!

Sunday, November 14, 2010

FreePascal, C# and COM

Hi there!

I've been skipping updates of FreePascal lately and since I've received the note that version 2.4.2 was released I've decided to do some investigations on how's the progress of this project.

This time I've decided to check how does it look like to implement a COM server in FP, then to write a client for that server in FP as well and at the end to create a client in C#!

First of all I need to emphasize that the FreePascal compiler as well as it's base library came a long long way since I've last checked them. Great work, guys! I'm really impressed! All I wanted to do was absolutely possible and the general impression was that I'm working with the good old Delphi compiler!

Having that out of my chest let's get back to the task.

We'll need some GUIDs. You can create them online here.

Define an interface in FP:
type
IHello = interface
['{8576CE04-E24A-11D4-BDE0-00A024BAF736}']
procedure DisplayMessage1(S: PChar); safecall;
procedure DisplayMessage2(S: WideString); safecall;
end;

That was easy, right? Just 2 methods that take a string in various form and judging by the name of those they'll display a message somewhere. Let's implement those:
// I've not found where the "ShowMessage" is declared...
procedure ShowMessage(Msg: AnsiString);
begin
MessageBox(0, PChar(Msg), 'Information', MB_OK or MB_ICONINFORMATION);
end;

{ THelloImpl }

procedure THelloImpl.DisplayMessage1(Msg: PChar); safecall;
begin
ShowMessage('MESSAGE USING PCHAR [' + Msg + ']');
end;

procedure THelloImpl.DisplayMessage2(Msg: WideString); safecall;
begin
ShowMessage('MESSAGE USING WIDESTRING [' + Msg + ']');
end;

Again, no magic here...

Let's see how we can do the registration in the COM-subsystem:
const
CLASS_Hello: TGUID = '{8576CE02-E24A-11D4-BDE0-00A024BAF736}';

TComObjectFactory.Create(
ComServer,
THelloImpl,
CLASS_Hello,
'Hello',
'An example COM Object!',
ciMultiInstance,
tmApartment);

Here you see the call to TComObjectFactory.Create. If you want to know what the specific parameters mean look at the Delphi's documentation online.

Now the final thing left to implement are the Co-classes used to instantiate this object:
  CoHello = class
class function Create: IHello;
class function CreateRemote(const MachineName: String): IHello;
end;

[...]

{ CoHello }

class function CoHello.Create: IHello;
begin
Result := CreateComObject(CLASS_Hello) as IHello;
end;

class function CoHello.CreateRemote(const MachineName: String): IHello;
begin
Result := CreateRemoteComObject(MachineName, CLASS_Hello) as IHello;
end;

This way we'll have it easier to deal with the actual instances :)

Let's have some client code, shall we?
var
Hello: IHello;

begin
CoInitialize(0);

Hello := CoHello.Create;
Hello.DisplayMessage1('Hello, world! using COM from FreePascal or Delphi');
Hello.DisplayMessage2('Hello, world! using COM from FreePascal or Delphi');
end.

Important: if it's a console application the CoInitialize(0) does not happen automatically! If you'd have it in a VCL (as in GUI) application the call to Application.Initialize does this for you so you don't need to do that twice.

And there's the whole thing in FreePascal. Let's see now how we can reuse this COM object from C#!
using System;
using System.Runtime.InteropServices;

namespace Client.Net {
[Guid("8576CE04-E24A-11D4-BDE0-00A024BAF736")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IHello {
void DisplayMessage1(
[In, MarshalAs(UnmanagedType.LPStr)] string message
);
void DisplayMessage2(
[In, MarshalAs(UnmanagedType.BStr)] string message
);
}

[ComImport]
[Guid("8576CE02-E24A-11D4-BDE0-00A024BAF736")]
class Hello { }

class Program {
[STAThread]
public static void Main(String[] args) {
var hello = new Hello() as IHello;
hello.DisplayMessage1("Hello, world! using COM from C#");
hello.DisplayMessage2("Hello, world! using COM from C#");
}
}
}

This might require a few words of explanation.

First of all the way you create instances of COM objects in C# is by using the "new" keyword, just like any other instances you might have. To sort of "map" the actual COM class to a C# class you define an empty class with 2 attributes: ComImport and Guid. This allows the compiler to do some magic behind the scenes and do the actual instantiation of COM objects instead.
Next is the funky-looking declaration of an interface. It also has 2 attributes on it: the Guid and an information that this interface is just a descendant of IUnknown, so it comes with no type library. This means that the late binding is out of question.
Last but not least - the threading model. Since we've registered the COM object in FP's COM subsystem to use the tmApartment we need to have it compatible in C# code as well. That's what the "STAThread" attribute is for.

Well, this was a wild ride, let me tell you :) But it was well worth it. Now I have the managed and not managed worlds at my fingertips for free!

As usual here's a ready to run example. It's been compiled for .NET 4.0 so if you don't have it you can build it for 3.5 as well.

Have fun!

Wednesday, October 27, 2010

GUG Poland emerged!

Hi folks!

I'd like to let you know that the grails community has one more place to find answers! This time it's a discussion group for polish speakers, GUG Poland.

Come join and let's bring the community the best help we can!

Grails - custom view engine

Hi there!

Following the last post I was wondering how hard it is to actually create your own artificial view engine for your custom file format. The reason for that might be for example that you want to create Excel files from data returned by an action (like a list of people for example).

I'll assume that the view engine will be completely artificial which means it will not use any resources other than the model being passed on from controller.

Here are the steps one needs to do to make it happen:

1. Register your format so that it is recognized by the system.
2. Implement the ViewResolver and register it as a bean in beans.groovy
3. Implement the actual View and it's "render" method.

Not going into the details here's an example that works. After you run it navigate to http://localhost:8080/example/home/index to see the HTML representation and then to http://localhost:8080/example/home/index.example to see the custom format being rendered instead of the GSP page.

Hope it helps someone :)

Grails and rendering different content types

Hi there Grails freaks!

I've discovered something ground breaking (well, at least for me) with the way Grails renders views so I thought I'll share it with the class :)

Imagine you have a controller, say a PersonController for example. And there you have the "get" action that returns just enough data to render the view. Well times are different than what they used to be 3-4 years before and HTML is not the one and only output format we expect these days. There's JSON, plain text, ATOM, RSS - you name it! Back to the original thought...

Knowing that the JSON format for example looks different than the HTML one (no surprise there) it's kind of obvious the way it's being rendered will need to be different. So for example an HTML view will have everything embedded into an <html> element, then there will be a <body> item containing whatever needs to be rendered whereas the JSON version will most probably contain only the key-value map in JavaScript format.

So what's so ground breaking here? We all know there's this "render person as JSON" thingy, right? Do we really need anything else?

As a matter of fact we do. There are lots of examples where JSON generated this way will not cut it. For example you need the actual data wrapped into some outer object, maybe some additional "count"-like field for list is something you need... You name it!

To get around this here's the revelation: you create not one but as many views as you need but add the extension to their names, for example for the "get" action of "person" controller you'd have get.gsp for the HTML view of the thing and a "get.js.gsp" view for the JSON representation!

Of course one always needs to remember to set the content type properly:

<%@ page contentType="text/javascript"%>

I have no idea if this works with any other version of Grails other than 1.3.5 (this is what I've tested) but this feature is so nice it will allow for effortless rendering of different types of results with no pollution in controller code.

Here is an example project that does what I've described. Once you've got it up and running navigate to http://localhost:8080/example/home/index and http://localhost:8080/example/home/index.js to see the results.

Have fun!

Sunday, October 24, 2010

Git adventures

Hi there folks!

I've been trying really hard (with success!) to get Git (the revision control system from Linus) to work the way I like it.

So the first thing I tried was to clone a remote repository from git hub. That was pretty easy. git clone URL and the repo was cloned. Piece of cake.

Next thing (since I like to mess around) was to create a repo from scratch. No surprise here - git init folder_name and I was done. Working with the new repo did show some surprises... First, the git add required me to specify something to work with. With Mercurial or Bazaar this was not the case so I was surprised to see an error message but I figured out it pretty quickly.

Next thing - commit.
Well, if you worked with Subversion, Mercurial and Bazaar you'd be pretty used to the "ci" abbreviation. Unfortunately it's not working in Git and you have to specify the whole command name... Same thing goes for "status".

Using TortoiseGit under Windows didn't bring much surprise - it was as I'd be using Subversion which means plain and simple.

Last but not least came the problem of sharing my work and creating a "central" (the most important) repository. Had I known this would be so f..ing difficult I'd not start with it at all...

First, there's a "git-daemon" thingy that should take care of the "server" part. Well, it does and exporting (making publicly available) a repository was not a nightmare. One needs to remember that a repo is not automatically available via this daemon but first after creating a tag file in .git subdirectory called "git-daemon-export-ok". That was not intuitive but I can live with it. Google did help.
My anger started when I wanted to push something to the newly cloned and modified repo. It turns out it's not that simple because the "git-daemon" thingy is supposed to be read-only!
After hours of fighting with stupid error messages that the connection was suddenly dropped... Very counterintuitive! But I thought it's not the end of the world and looked further.
I've finally stumbled upon a post describing that git is actually allows interoperability using SSH protocol. So I've cloned the repo using different url (username@host:/path), done the same changes again, checked them in and tried to push. Well... It didn't work either. The repo had to be marked as "bare" - whatever that means. If you've come across this term anywhere else please drop me a note - I have no fricken idea what it means.
So I've "marked" the repo as "bare" in the config file. And again I was not able to push any changes because the repo was empty (surprise! an empty repo cannot be served!!!). After doing some foobar changes to it and committing them on the server I was finally able to push my local changes.

It all sounds like a piece of cake once you know what to do, but attacking the problem head on for the first time is simply a pain in the ass to figure it out.

To summarize:
- you cannot server r/w repo using git protocol. You need to use SSH or other protocol that supports authentication.
- you have to have at least one checkin in the server version of the repository before you're able to push chages from remote clients.
- you need to create "git-daemon-export-ok" for the repo to be picked up by "git-daemon" or else!
- you need to set the "bare" config option to "true" or else!

I hope this will help someone. Have fun!

Tuesday, October 12, 2010

Grails, GORM, Teradata and no primary key

Hi,

I've stumbled upon a problem which is most probably a very common one though I couldn't find any clear answer right away... Mapping to so called natural keys with GORM.

Imagine you have a badly designed table without surrogate key acting as unique primary key. To map such a table in GORM you need to compose the ID of a mapped class using a composed key, that's obvious:
static mapping = {
id composite: [ 'reportId', 'managerId' ]
}

Since there's no restriction telling the database that the fields have to have values then if at least one of the fields contains null what you'll get in return is a null in a list where you'd expect your domain objects!!!

I have no idea if this is a bug but I surely believe that this is a design error in the database.

The fix for that (an ugly like hell one) is to add as much fields that always have values and remove those columns that can have nulls in them.

But I strongly recommend that you do add the surrogate, required (or better yet auto-populated) primary index.


Have fun!