Monday, November 29, 2010

Grails, plugins and tags with templates

Hi all,

If you've wondered if it's possible to render a view from a tag I rush to say it is absolutely possible. You just use the render method and specify the template to be rendered like in this example:
class ExampleTagLib {
def example = { attr, body ->
out << render(template: '/tags/example')
}
}

Ok, that was easy. However things get a little bit more interesting when we try to do the same thing from within a plugin. The problem here is that the render method tries to find the view to be rendered in the application and not in the plugin.
The remedy to this problem is simple: you need to append the plugin name as a parameter to the render method like this:
class ExampleTagLib {
def example = { attr, body ->
out << render(template: '/tags/example', plugin: 'example-plugin')
}
}

Here you can find a ready-to-run example.

Have fun!

Friday, November 26, 2010

STS and Grails - running JUnit tests from IDE

Hi folks!

Have you been wondering how to run JUnit 4 tests under STS so that the the tests are recognized and executed properly?

junit.framework.AssertionFailedError: No tests found in

I guess most of you writing tests for your Grails application have seen this one under Idea or STS. The IDE just doesn't see the right tests by itself... But there's hope!

Here's a definition of a class that when used in conjunction with the @RunWith annotation allows the IDE to run those test properly:
package com.aplaline.example.test;

import org.codehaus.groovy.grails.test.GrailsTestTargetPattern;
import org.codehaus.groovy.grails.test.junit4.runner.GrailsTestCaseRunner;

@SuppressWarnings("rawtypes")
public class GrailsJUnit4Runner extends GrailsTestCaseRunner {
public GrailsJUnit4Runner(Class testClass) {
super(testClass, new GrailsTestTargetPattern[0]);
}
}

And here's an example test that uses it:
package com.aplaline.example

import grails.test.*

import org.junit.Test;
import org.junit.runner.RunWith;
import com.aplaline.example.test.GrailsJUnit4Runner;

@RunWith(GrailsJUnit4Runner)
class CalculatorServiceTests extends GrailsUnitTestCase {
@Test
void canAddTwoNumbers() {
// given
def service = new CalculatorService()

// when
def actual = service.sum(1, 2)

// then
assert actual == 3
}
}

See - that wasn't hard, was it?

I hope it'll help you out test your code more efficiently :)

Have fun!!!

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!