Saturday, January 29, 2011

Moving to new server...

Due to the move of server from one physical location to another resources on this page (meaning examples linked to posts, etc.) will not be available until some time next week. Sorry for the inconvenience.

Tuesday, January 25, 2011

Setting up SQL Server 2008 Express to work with Grails

If you'll find yourself in need to configure a SQL Server database connection for your next grails application and you'd like to use the Express edition for development here's how you can do it:

1. Change login mode:
a) open regedit
b) navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQLServer
c) change the value of LoginMode from 1 (windows authorization) to 2 (mixed mode)

2. Enable TCP/IP connectivity:
a) open the SQL Server Configuration Manager (this one comes with the SQL Server itself)
b) click on "SQL Server Network Configuration / Protocols for SQLEXPRESS
c) right-click on TCP/IP and select "Enable"
d) double-click on TCP/IP, go to second tab (IP Addresses"), scroll down to the bottom of the property list and in the "IP All" section fill in the blank "TCP Port" with 1433

3. Restart SQL Server:
a) select SQL Server Services
b) in the list to the right select SQL Server (SQLEXPRESS)
c) right-click it and select "Restart"

The next step requires any form of ability to execute SQL statements against the server. What I used was the Visual Web Developer 2010 and its "Database connections" view.

4. Enable "sa" user:
a) ALTER LOGIN sa ENABLE
b) ALTER LOGIN sa WITH PASSWORD = ''

5. Create a database:
a) Create database your_database_name_here

6. Download and install the JDBC driver for Microsoft SQL Server (you just need the sqljdbc4.jar in your lib folder)

7. Configure your DataSource.groovy:
driverClassName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"
dialect = "org.hibernate.dialect.SQLServerDialect"
url = "jdbc:sqlserver://localhost:1433;databaseName=your_database_name_here"
username = "sa"
password = "your_password_as_defined_in_4b"

With all that in place everything should work just fine :)

You might wonder why I've decided to mess around in windows registry instead of using proper tools (like the SQL Server Management Tools or whatever..). The answer is quite simple: It felt like a total overkill to install this humongous tool just to set one property :)

Saturday, January 22, 2011

Handling exceptions in Grails

If you ever find yourself in need to provide custom exception handling in your application but you need to do more than just show the view (send an email for example) there's a really simple way to do it. It consists of 2 steps (of which the documentation mentions only one and remains completely silence about the other one):

1. Create a mapping in UrlMappings.groovy:
"500"(controller: 'errors')

2. Create a controller that will handle it:
class ErrorsController {
def index = {
def exception = request.exception
// do some processing here
}
}


It's very unfortunate that the request.exception is not mentioned in the right spot in Grails documentation. It leads to confusion that the actual exception instance is available only in views which is clearly not the case.

Friday, January 21, 2011

Grails FAQ

This one you definitely have to look at :)

https://fbflex.wordpress.com/2011/01/11/grails-interview-questions/

Not because you're looking for a job, not because you recruit someone... simply because it's good stuff and you most likely don't know all of it by heart.

Thursday, January 20, 2011

Why JSF is the most used framework

Today I've stumbled upon an article supposedly written by one of the developers of JSF standards.

http://www.zeroturnaround.com/blog/ed-burns-on-why-jsf-is-the-most-popular-framework/

Before I'll go any further I need to make it clear: I hate JSF! Yes, this is my personal opinion, my personal choice. I don't encourage you to do so as well - maybe it's good for you and saves you tons of hours of work - it didn't do so for me.

I'd like to point out that JSF is in my opinion a failed attempt to reproduce ASP.NET WebForms technology. Where WebForms succeeded (component market, easy design, easy event-driven programming model) JSF has failed miserably...

JSF is neither easy nor standard (if you look from a broader point of view and not keep your head in the Java box). I think JSF has the one and only advantage that allows inexperienced web application developers to stay inexperienced and not use core web technologies (HTML, CSS and EcmaScript). This is the reason why JSF is so damn popular - and so damn evil. Once you step into it there's no going back. You're stuck with it!

Like it or not the browser is a viewer that uses all 3 domain specific languages to achieve what it does so what you can do is either learn yet another DSL (the facelets DSL in this case) to do the job or you can simply go through the effort of learning the core ones which will pay off in the next and next and next web application projects no matter what technology you'll use (besides JSF of course)
To my liking it is unbearably sad that people dismiss the simple ideas and take a shot at frameworks like JSF. I wonder when the era will come with something else will replace JSF like WebServices are being replaced with REST.

Funny thing is that Ed draws a hard line between client-side-only frameworks (jQuery, Flex...) because they don't fit into his agenda but at the same time asks if "Wicket, Grails? Play? Echo2? Tapestry? Stripes?" will fulfill the goals that JSF is supposed to. It's funny because there's for example no Grails application that wouldn't use either Prototype or jQuery (or anything else for client-side programming). Funny :)

One final note: "jQuery+REST"? If you know what the author meant with it please leave a comment and explain it to me.

Sunday, January 16, 2011

Keep your data local

"Keep your data local" - said once a good friend of mine. It didn't mean much to me until some time last week when I was given a task to optimize a .NET application that used way to much memory.

Keeping the story short: if you want to keep your data local use an embedded database like SQLite, SQL Server CE or Firebird Embedded and don't keep all your data in memory at once. Split the process into 3 parts (populate data, process the data, send updates on user's demand) and don't even think about using DataSet for anything that's larger than say 10000 records. It's way to bloated to use it on those amounts of data.

So, if you think that sorting and filtering within a DataView is faster because there's no network overhead and no additional disk IO please be advised that it is way slower than reading records on demand from any of the embedded databases mentioned above and uses a mere fraction of memory by comparison.

And btw - SQLite rules, but its lack of locking on record level is very much annoying...

Tuesday, January 11, 2011

Old times...

Today I've been browsing through my old applications and libraries. You know... the kind of code you'd never look back at :)

It's funny that after all those years (3 to be exact) when I look at the code it still looks nice and fresh. I must have known what I was doing :D

Jokes aside here's a story to think about:

Imagine a project involving 2 to 3 developers, based on bad assumptions and lack of a good idea. This project went on and on for years (2 years to be exact). The idea was simple: take an application that used Pervasive's BTRV API and make it work under some RDBMS. Like I said it took many developers (for this kind of idea to come true) and many years... And in the end it didn't work... In the mean time (since I'm the kind of guy that 'knows better') I've decided to do a little spike and to see how much effort it'd take to create something like that but in a more, let's say, clever fasion. As it turned out it took me 3 days to get the whole idea to run in read-only mode (I never got so far to implement the update operations even though everything is ready to do them). 3 days!!! I mean, are people really so blinded by the fact that they don't want to do rewrites that it forces them to spend years of wasted work and hundreds of kilos of dollars just not to say they've made a mistake???

Man that was really fun to look at again and to remember those old times...

Monday, January 10, 2011

camelCase for human beings

Reading lots of characters glued together is a very good thing for the compiler. Human beings tend to prefer spaces rather than a set of lowercase characters separated with uppercase characters to distinguish words. It's just how we were taught since we were very young...

In case of unit test in Groovy we can actually name our tests with spaces! Here's an example:
import org.junit.Test

class ExampleTests {
@Test void 'This test verifies nothing but is a good example'() {
assert 1 == 1
}
}
When later on you're reading the name of the test that failed it's a whole lot easier than to read the same in camelCase.

Converting camelCase to human text

I thought I'll give a string an additional method so that whenever I have a camelCase string I can convert it easily to something that's easier to read:
String.metaClass.humanify = {
def r = ""

delegate.eachWithIndex { c, i ->
if (i == 0) r += c.toUpperCase()
else if (c in 'A'..'Z') r += ' ' + c.toLowerCase()
else r += c
}

return r
}

From now on it's easy to read camelCase when it's humanized :D

Sunday, January 9, 2011

Testing sending emails with Grails

If you'll ever find yourself in need to test some mail sending piece of code in Grails be advised that there are 2 ways of doing it (both options work only in integration tests!)

The grails-mail way

Once you have your piece of code in place what you can do is to set the
grails.mail.disabled=true
setting in Config.groovy and skip sending emials entirely. You can then use the return value from mailService.sendMail call to inspect what would have been sent to the server.

The "all-the-way-through" way

If you'd like to see if everything really goes through to the mail server you can always use Dumpster. It's a very elegant library giving you basically 3 things:

  • A SimpleSmtpServer.start() method

  • The SimpleSmtpServer instance as a result of the method call above

  • SimpleSmtpServer.stop()
So what you can do is to start the server at the beginning of your test, send the mail simply to localhost:25 (assuming you don't have sendmail listening on the same port of course) and shut it down after you're done with it.

To sort of enable Dumpster in your tests either add the dumbster-1.6.jar to your lib folder or add the following dependency to BuildConfig.groovy
dependencies {
test 'dumbster:dumbster:1.6'
}
Make sure you enable repoCentral()!

Here's how easy it is to use Dumpster to test sending emails in a grails integration test:
import org.junit.Test
import com.dumbster.smtp.SimpleSmtpServer

class ExampleIntegrationTests {

def mailService

@Test void willReceiveEmail() {
def server = SimpleSmtpServer.start()

mailService.sendMail {
to "someone@some-server.com"
from "me@server.it"
body "This is the body"
}

server.stop()

assert server.receivedEmail.toList().size() == 1

// a little dump to see what's in the email :)
server.receivedEmail.each { println it }
}
}
Check out the Dumpster examples for more. I like it!

Final warning

A word of caution related to the grails-mail plugin: in version 1.0-SNAPSHOT you need to manually add a repository for the required dependencies to be properly resolved. In general I recommend using version 0.9 because it works out-of-the-box. To do that either specify the version while installing the plugin like this:
grails install-plugin mail 0.9
or if you've already installed it in the default version you can always edit the application.properties file and change the plugin version there.

Saturday, January 8, 2011

Grails, IDEs and productivity

Disclaimer

The following opinion might do you harm, offend you or your colleagues or might seem like a talk of a crazy man. Below way of proceeding with daily job is just one of many, probably as many as there are developers out there.

You have been warned!

It all started a long time ago

A long time ago there was Turbo Pascal. It had (as for those old times) an amazing IDE where you could write and debug code and if you made a typo the IDE would tell you immediately that you made a mistake. It had yet another property: it was blazing fast even on those old PCs.

Microsoft VisualStudio, Delphi and Java IDEs

After some time the era of graphical user interfaces kicked in. Environment for programmers started to grow and grow and grow... Especially those for Java. What they brought to the table was supposedly productivity enhancements. One would code faster by use of wizards, code completion, squiggly lines and other "gooye" goodness...

Everything comes for a price

Since those IDEs at the very beginning were quite simple they started fast. PCs were getting faster and faster every year so even if the startup time was around 20 seconds it'd still not be a problem because the next year it'd be down to 3-4 seconds and life would be good again.
The only problem with that was that the next year's release had even longer startup time and this tendency didn't seem to stop until today.

Rational developer point of view

Imagine a situation where all you need is to change 2 lines of code, run the tests and be done with it. What would it take to do this in an IDE like Eclipse or NetBeans and how would this look like when using a less sophisticated tool like let's say TextMate.

Eclipse

Ok, so let's start Eclipse. It's actually a good thing it starts so long because I can go and make myself a coffee before it's ready to work. Oh! but wait! Starting is not everything! Since those brainiacs that created Eclipse thought that it's actually better to delay loading stuff you don't need at first it is actually not only the startup time but you need to add to this a long long time for every window to pop up the first time. Not to mention that the PC I'm running on is quite a powerful one (2 64 bit cores @ 2.8GHz each, fast HDD, lots of ultra fast RAM) Well, most games (and those were the applications that demanded the most of hardware) work like a charm.
Code completion, the biggest hype of all the features in modern IDEs, seems to work only with dull, very formal languages. There's a reason for that: dynamic languages tend to change the behavior of existing code in runtime so there's no way to properly predict what will happen in this particular place in code.
Take Ruby or Groovy for example. Eclipse is doing a pretty good job in giving you hints on what's available but it still is not powerful enough to support some of the nice features like Mixins for example.

NetBeans 6.9.1

The story with that one is exactly the same as Eclipse but worse. Imagine to wait for over 40 seconds just for the list to appear so that you can choose what you want to call. NIGHTMARE!!!

Visual Web Developer 2010

One nice thing about this IDE is that it is focused on one task, and one task only: building web applications. To that end there's no Windows Forms designer built in to slow down the IDE when I don't need it. There's also this one and only (best of breed my friends) JavaScript editor that recognizes extension patterns in many libraries (like ExtJS or jQuery) and provides intelli-sense for them. Let me tell you: it's a F1 car to work with JS!
Unfortunately many of the other things from Eclipse and NetBeans still apply. Startup time is longer and longer with every version and PCs just don't catch up with it.

The worst nightmare: Delphi

Imagine saying that Eclipse, or even NetBeans, starts in no time by comparison. The Delphi 2009 startup time was around 1.5 minutes!!! I mean come on, guys! What were you thinking when you allowed such a piece of crap to see the light of the day?

TextMate to the rescue

These days it is very common for the actual tooling support to come together with a particular library. Take Ruby on Rails or Grails for example. All you need to do is to install the thing and have an editor with contextual text highlighting so that you can see better what's going on. Hell, you can even code directly in the browser!
I took TextMate as a general-purpose example but the same holds true for most of the other plain text editors. Vi, Vim, Emacs (ok, that one is a hardcore one :)), Gedit, Midnight Commander's editor, Far Manager 2 with Colorer plugin... You name it! And like I mentioned before, the code completion itself once you're productive in a platform will only slow you down.
You might say: and what about debugging? Well, as the good uncle Bob said "you don't! what you should do is to create unit tests to see if it all works as expected". But that's a topic for a completely different post...

Is it really all lost?

Ok, so let's give the IDEs some credit they deserve. I do use them, from time to time, when what I need is to do some refactoring, especially to rename classes in files. The process is just too cumbersome to do it manually. I've seen people do some pretty amazing things with Java code in Eclipse too. I guess at some point it becomes like a second skin for you... I prefer to go "naked" :)

Conclusion

When you go to see a doctor and tell him that when you bang your head against the wall then the head begins to hurt what he'll most probably say is "Don't do it". So if you'll ever find yourself complaining about the speed of your IDE try some alternate approach. You'll be amazed what productivity boost it will bring after just a few days of "getting used to". Remember: chemistry doesn't happen over night :)

Grails, Camel and adding routes at runtime

Since it's been of some interest on the net to figure out how to add routes at runtime to Camel provided by the grails-routing plugin here's an example of how it might be implemented:
import org.apache.camel.builder.*
import org.apache.camel.model.*

class HomeController {
// 1
def camelContext

def index = {
// 2
println camelContext.routes.size()
// 3
if (camelContext.routes.size() == 0)
// 4
camelContext.addRouteDefinitions(
new MyRouteBuilder().routeDefinitions
)
render text: camelContext.routes.size().toString(), contentType: "text/plain"
}

def send = {
// 5
sendMessage("seda:input", "Hello, world! from dynamically added rotue")
render text: "sent", contentType: "text/plain"
}
}

// 6
class MyRouteBuilder extends RouteBuilder {
// need to override this to make RouteBuilder inheritance happy
void configure() { 
} 

// generate a new route
List getRouteDefinitions() {
[ from("seda:input").to("stream:out") ]
}
}

1 - Make the CamelContext instance available


the def camelContext makes the bean of class CamelContext available for us in this controller

2 - Debugging


For debugging purposes we're printing out to console how many routes are defined. The first time it will print 0 as there are no routes defined yet.

3 - Check if the route has already been added


We don't want to add the same route over and over again, right? :)

4 - Adding a new route


Using an instance of MyRouteBuilder get a new route definition and stuff it into the current set of routes.

5 - The send action


In this action we'll test the newly created route to see if it works

As you can see the only odd thing is that MyRouteBuilder doesn't do anything in configure since it's not required. We're inheriting from RouteBuilder only to have access to specific DSL methods (like the from one in this example).

To try it out make sure you have no other routes defined in your application, fire up the /home/index and note the number of routes printed out to console and displayed on the page. The first one should read 0 and the second one (since it's evaluated after the new route has been added) should read 1.
Then navigate to /home/send and observe in console a nice message received on seda:input and forwarded to stream:out

EDIT on 21 January 2012

There's a better way of doing this sort of things that works with all kind of routes:
def index = {
    if (camelContext.routes.size() == 0) {
        camelContext.addRoutes(new RouteBuilder() {
            @Override void configure() {
                from("seda:input")
                    .filter({ it.in.body.contains('from') })
                    .to("stream:out")
            }
        });
    }
    render text: camelContext.routes.size().toString(), contentType: "text/plain"
}


Hope this will help :)

Friday, January 7, 2011

Groovy/Grails DSL testing

Today I faced a usual task of testing a controller action that utilizes the withCriteria call to fetch some data from the database. Usually what I do in situation like this is I write an integration test, have the database mocked using in-memory instance of HSQLDb and all is nice and dandy.

This time I didn't have the luxury to have the database in place. I will not bore you why that is the case - it simply is. What I didn't want to do was to just let the thing be untested so I've decided to create a ultra-minimalistic framework for testing such DSLs in Groovy.

First of all, it all bases on the assumption that you don't care about the actual results the DSL brings. What you do care about is the fact that certain parts of the DSL have been called in a particular order and with proper arguments. To put this in context: you don't care that the withCriteria DSL will be in reality transformed into SQL but you do care that what you wrote will be as you expect it to be.

So the following class has emerged:
package groovy.test

class DSLTester {
static mock(clazz, method, result) {
def tester = new DSLTester()
clazz.metaClass.static."${method}" = { Closure dsl ->
dsl.delegate = tester
dsl.resolveStrategy = Closure.DELEGATE_FIRST
dsl()
return result
}
return tester
}

def result = []

def methodMissing(String name, args) {
result << [ name: name, args: args.toList() ]
}
}

What it does is it executes the closure passed on as the DSL to whatever static method we decide to test and catches all the missing calls as if they were proper DSL calls. You might find the args.toList() part to be a little bit strange. This is to allow use simple comparison in tests - read on to find how.

To give you an example first let's define the Person class:
class Person {
String firstName
String lastName
}

With that in hand let's create a home controller that will just print all the people ordered by firstName:
class HomeController {
def index = {
def people = Person.withCriteria {
order "lastName"
}

[ people: people ]
}
}

To test the withCriteria closure let's utilize the DSLTester class:
import groovy.test.DSLTester
import grails.test.ControllerUnitTestCase
import org.junit.Test

class HomeControllerTests extends ControllerUnitTestCase {
void testExecuteDSL() {
def mock = DSLTester.mock(Person, 'withCriteria', [])
def actual = controller.index()
assert mock.result == [ [ name: 'order', args: [ 'lastName' ] ] ]
}
}

As you can see the only assertion that I make here is that the order will be properly set to 'lastName' which is what we wanted in the first place.

There's tons of ways you could improve this. You could for example come up with a nice way to verify expected methods have been called with the proper arguments instead of declaring a huge list with hashes containing everything. Sky is the limit :)

The main motivation behind this sort of test is to provide means to test only your code and to test it in complete isolation. It might be perfectly understandable that since the code that uses withCriteria has such a strong dependency on the database that testing it in isolation makes no sense. I however like to keep things isolated :)

Thursday, January 6, 2011

Story of one Grails plugin

It's been one of those days where I felt like I need to create a spike app just to prove things are simple in Grails. A friend of mine is preparing a presentation about using NOSQL databases in applications and since it's pretty darn simple to use MongoDB in Grails I've decided to put together a sample that will utilize this datastore.

It all started soooo simple...

grails create-app example
grails uninstall-plugin hibernate
grails install-plugin mongodb
grails create-domain-class Person
grails create-controller Person
grails create-controller Home

Then I've edited the domain class to have 2 properties firstName and lastName, added scaffolding to the PersonController... Basically the Grails 101 stuff...
The HomeController was also pretty simple. Just the index action that returned the [ people: Person.list() ] map and the view that rendered a table to present this data...

Then the geek kicked in...


I thought: now wouldn't it be nice to have the table sortable? Well, sortable but the sorting itself should be done using Ajax - now that'd be cool :)

Right tool for the job - jQuery


When I think "Ajax" it's as if I'd be thiking jQuery at the same time. For me there's nothing else. Period :)

To do that I first needed to extract the part that rendered <tbody> to a separate template _rows.gsp. Then another action, rows was needed to return sorted list of rows instead. That was again dead simple with GORM:
render template: 'rows', model: [ 
people: Person.list(sort: params.key, order: params.order)
]

Then the actual client-side jQuery magic happened:
$("th").click(function() {
var key = $(this).attr("column");
var order = $(this).attr("order");
$(this).siblings()
.removeClass("order-desc")
.removeClass("order-asc")
.removeAttr("order");
if (order == "desc") {
$(this).attr("order", "asc")
.removeClass("order-desc")
.addClass("order-asc");
} else {
$(this).attr("order", "desc")
.removeClass("order-asc")
.addClass("order-desc");
}
$(this).parents("table").find("tbody")
.load("${createLink(controller: 'home', action: 'rows')}?order=" +
order + "&key=" + key);
});

It's all basic stuff... Nothing to be proud of...

Geeky thinking part 2


A simple idea to turn the code above into a jQuery plugin turned out to be the hardest part. First of all, authoring jQuery plugin is not as simple as I'd like it to be. I'm more of a "File - new" person than "Google, google, google..." one. So after I've finally found out how to create such a plugin I was pretty much exhausted.
But what if it'd be really simple? Something along the line of "File - new" or (in the case of Grails) "grails create-jquery-plugin my-plugin"???

And so I've created the jquery-plugin-authoring Grails plugin. From now on whenever I see that part of my application just fits like a jQuery plugin I simply create one. The template leads me every step of the way (the initialization, default values for options, a method to override them, a list of possible messages my plugin can respond to).

And life is simple again :)

End result


I love to see my results be better than someone else's. In this case comparing what it takes to do all that in pure Java having to glue together Hibernate in Entity Manager mode to use Hades, wiring it all with spring beans and adding the web application part with Wicket seems like tons of work by comparison. In fact It took me about 4 hours from the very beginning to the point where I've had the plugin released, used and all was nice and dandy. Grails rule!

I wonder how much time it'd take to do the same in Ruby on Rails? If any of you could perform such an experiment and share the result it'd be really great!

Monday, January 3, 2011

Grails,CXF plugin and .NET

As promised here's a follow up on the WebService interoperability between Grails using Apache CXF plugin and .NET.

First let's create a simple example project and install the grails-cxf plugin:
grails create-app example
grails install-plugin cxf

Next let's create a service:
grails create-service example

This has created 2 files:
grails-app/services/example/ExampleService.groovy
and
test/unit/example/ExampleServiceTests.groovy

The first one is the one we need to modify so let's get to it:
package example

import javax.jws.*

@WebService(serviceName="ExampleService", name="Example")
class ExampleService {

static expose = [ 'cxfjax' ]

@WebMethod(operationName="sayHello")
String sayHello(@WebParam(name="name") String name) {
"Hello ${name}!"
}
}

As you can see I've added every possible bit of information to customize the generated WSDL. With all that in place we can get the description of this service (WSDL) at http://localhost:8080/example/services/example?wsdl. Let's use that to create a .NET client. This time from command-line:
SET PATH=%PATH%;"C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin"
wsdl.exe http://localhost:8080/example/services/example?wsdl

In the first line we're expanding the system path so that all the tools are available from anywhere. In the second line we're generating a client for the web service we've created in Grails. Simple enough, right?

Let's create a simple console application and use this newly generated client:
Program.cs:
using System;

public class Progra {
public static void Main(String[] args) {
Console.WriteLine(new ExampleService().sayHello("John"));
}
}

Let's compile everything from command-line:
set PATH=%PATH%;C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319
csc *.cs

Again, no magic here. Once you've compiled everything run the application and bum! Everything works as expected :)
My guess is that CXF plugin didn't work just right out of the box because of some problems with default naming that CXF is using when auto-generating WSDL. With all the annotations in place everything seems to be working just fine.

I hope this will help someone. In case you'd like to fiddle with it yourself here's the example. in src/csharp you'll find the sources for the client along with a batch file to compile them.

Unfortunately when it comes to a more advanced scenario, like for example returning an array of domain objects from a service method the CXF plugin still fails to produce good enough WSDL to work with .NET. This is the case where XFire plugin shines best!

FYI: the same trick does not work with Axis2 plugin. The naming is all whacko. Things like this$dist$set$2 and urn:this$dist$get$2 hurt the WSDL code generator so much it spits nothing out but a load of warnings.

Have fun!

Sunday, January 2, 2011

JavaEE 6 + Metro WebServices

Following the post about WebServices with Grails here's a short summary of my attempt to make Java's EE 6 WebServices work with .NET. It's quite a basic example but as history shows even the simplest examples might not work (as it is the case with Axis2).

Setup

So here's a definition of a Hello WebService:
package com.aplaline.integration.webservices;

import javax.jws.*;

@WebService(name="Hello", serviceName="HelloService")
public class HelloService {
@WebMethod
public String sayHello(@WebParam(name="name") String name) {
return "Hello " + name + "!";
}
}

As you can see there's no magic here. Let's see how NetBeans' configuration option look like for this guy:



Surprisingly enough there's mentioning of a .NET version! Let's see how this works. I'll be using VWD 2008 SP1 to test it:



Let's add a web reference to this web site:



Now let's create a blank Default.aspx page and add some code to call that web service:
Default.aspx:
[...]
<form id="form1" runat="server">
<div>
<table>
<tr>
<td><asp:Label ID="Label1" runat="server" Text="Enter name" /></td>
<td><asp:TextBox ID="input" runat="server" /></td>
</tr>
<tr>
<td align="right" colspan="2"><asp:Button ID="Button1" runat="server"
onclick="Button1_Click" Text="Click me" /></td>
</tr>
<tr>
<td colspan="2"><asp:Label ID="output" runat="server" /></td>
</tr>
</table>
</div>
</form>
[...]
Default.aspx.cs:
[...]
protected void Button1_Click(object sender, EventArgs e)
{
output.Text = new localhost.HelloService().sayHello(input.Text);
}
[...]

Results

As it turns out it works out of the box properly.



For the kicks of it let's try and consume the same web service from PHP 5.3:
<?php
$client = new SoapClient("http://localhost:8080/WebServices/HelloService?wsdl");
var_dump($client->sayHello(array("name" => "John")));
>
There's a little inconvenience when calling web services from PHP in that the parameters need to be passed as an array instead of simply specifying their value. In the long run it's kind of healthy because different webservice stacks tend to handle things differently and putting the proper context into the whole thing.



This is the first pleasant surprise since I've started to work on the web-service interoperability between .NET and Java. It looks like things are definitely going in the right direction :)

Here's the Java project for reference.
Here's the .NET website for reference.

Have fun!