The Blazing Grail – Part 2
Hopefully you read the “into” to this short series. If not go ahead. I’ll wait . . .
Ok, so to begin at the beginning, let’s create a new Grails project. (I’m assuming you’re at least a little familiar with Grails. If not then read the Quick Start article; that should be enough to get you started.)
If you’re an Eclipse user (like me) then you can import this project right into Eclipse. The groovy plugin would probably be helpful and I’ve been pointed to the SpringSource Tool Suite (with the Grails extension) as a good tool to use (it’s what I’m currently using). Notepad2 is working pretty well for me right now too though.
From here you could either use Sébastien’s plugin which will install a nightly snapshot of BlazeDS4 and Spring-Blaze.
This is what I suggest doing. If you do you can skip the next little bit where I explain how to do it by hand.
If you’re familiar with setting up these libraries then this is probably redundant. I wasn’t (I’m not a server guy remember) so I had to figure it out on my own. (This is a good read to help you along). Keep in mind that everything that follows can be accomplished by typing the above command (except you can’t pick the version of the libs that you use) so the only reason I would say to do it is to know what happens behind the scenes or to use Blaze 3 instead of 4.
First you’ve got to get the BlazeDS jars and drop them in your /project/libs folder. I just downloaded the latest binary distro, unzipped the .war and grabbed all of the included JARs and dropped them in.
Then I grabbed the latest release of spring-flex and likewise unpackaged it and dropped the included .jar in my libs folder.
Next you have to modify the web.xml file to get things setup. But wait . . . there isn’t a web.xml file anywhere! What to do . . .
That will create a /templates folder in your /project/src folder. Inside of that you’ll find /war/web.xml which you can edit. Grails takes this file and modifies it to create the web.xml file that actually get’s deployed.
To that you will need to add:
<listener>
<listener-class>flex.messaging.HttpFlexSession</listener-class>
</listener>
…
<servlet>
<servlet-name>flex</servlet-name>
<display-name>Spring-Flex Dispatcher Servlet</display-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
…
<servlet-mapping>
<servlet-name>flex</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>
…
Next, to your project/web-app/WEB-INF/ folder add a flex-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:flex="http://www.springframework.org/schema/flex"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/flex
http://www.springframework.org/schema/flex/spring-flex-1.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<flex:message-broker>
<flex:remoting-service default-channels="my-amf"/>
</flex:message-broker>
<context:annotation-config />
<context:component-scan base-package="" />
</beans>
Lastly create the folder /project/web-app/WEB-INF/flex and drop in a services-config.xml file that looks like this:
<services-config>
<services/>
<security>
<login-command class="flex.messaging.security.TomcatLoginCommand" server="Tomcat"/>
</security>
<channels>
<channel-definition id="my-amf" class="mx.messaging.channels.AMFChannel">
<endpoint url="http://{server.name}:{server.port}/{context.root}/messagebroker/amf"
class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
</channels>
<logging>
<target class="flex.messaging.log.ConsoleTarget" level="Info">
<properties>
<prefix>[BlazeDS] </prefix>
<includeDate>false</includeDate>
<includeTime>false</includeTime>
<includeLevel>false</includeLevel>
<includeCategory>false</includeCategory>
</properties>
<filters>
<pattern>Endpoint.*</pattern>
<pattern>Service.*</pattern>
<pattern>Configuration</pattern>
</filters>
</target>
</logging>
<system/>
</services-config>
And at this point you should be on par with what the plugin got you.
Now that we’re all together now lets move on . . .
So let’s create a service that can be called.
That will create the file /project/grails-app/services/com/pbking/AmfService.groovy Open that file and make it look like this (or some variance):
import org.springframework.flex.remoting.RemotingDestination;
import org.springframework.flex.remoting.RemotingInclude;
@RemotingDestination
class AmfService {
boolean transactional = true
@RemotingInclude
def getSomeString()
{
return "Peanut Butter is Awesome"
}
}
You also have to change the /project/web-app/WEB-INF/flex-servlet.xml file to have this:
If you wanted to use XML configuration instead of annotations you could drop the @stuff in the service, get rid of the two context: nodes and instead do this in the flex-servlet.xml file:
<flex:remoting-destination/>
</bean>
And . . . that’s it! Your server is ready to connect to with your Flex client! just type
to get your server fired up. If you are using the plugin and plan to use FlashBuilder 4′s data connection plugin then you’ll have to use
instead. It’s not quite ready for this so I don’t use it yet.
Now you just need a Flex client to do some communicatin’. There are a dozen ways to get this connection made and I’m not about to discuss the pros and cons of each here. I have my favorite and if you ever hire me you’ll find out what that is. ;) But below is about the SIMPLEST Flex4 application that will do the deed.
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/halo">
<fx:Declarations>
<s:RemoteObject id="ro"
endpoint="http://localhost:8080/blazing-ahead-plugin/messagebroker/amf"
destination="amfService"
result="resultLabel.text = event.result.toString();"/>
</fx:Declarations>
<s:VGroup>
<mx:Button label="call" click="ro.getSomeString();" />
<mx:Label id="resultLabel" />
</s:VGroup>
</s:Application>
And that, my friends, is that. Make go forth and make some kick-ass Grails backends for your Flex applications.
Here are a couple of assets that might save you a bit of typing (or copy-pasting as the case may be).
In the next post I’ll talk about where I spent most of my time . . integrating Spring Security!
Thanks for your series of posts, really awesome. Can’t wait for the next article. One question: is it possible to return ‘GORM objects’ in the service which then can be used on the flex side ? Have a great day.
It sure is possible; that’s the whole benefit right? As I understand there are some lazy-loading issues that might crop up. And the FlexBuilder 4 Data Connection Wizard doesn’t understand them. So you could either deal with them as generic objects or create the Classes on the Flash side by hand. There are tools in the GraniteDS plugin that does that for you as well as the Flex Grails Scaffolding. But not this way. Not yet anyway.
Right! – I’m definitely going to ‘play’ with this on the weekend. Again, thanks for your work.
Hi Jason,
Thanks for posting this AWESOME how-to. (I put a cross-link to it on the Grails Blazeds plugin’s page on grails.org, btw.) I have a question for you though (perhaps the answer is obvious but it’s alluding me right now):
My services aren’t returning strongly typed, AS3 classes marked by bindable. I’d read some where (I think on Sebastien’s blog) that this currently is expected behavior. But in your response to Mark’s original inquiry about returning “GORM” objects you allude that this is currently possible with Blazeds and Flashbuilder 4. Mind enlightening me on this?
Thanks,
Tami
Good reading…
Would you care to post some Flash (not Flex) client example?
Very nice post, Jason. Congratulations.
I was wondering what should I do to configure the grails application to send messages to flex client with this blazeDS plugin. Could you help me on it?
Thanks