Grails BlazeDS 4 Integration Plugin

One of the main goals I’ve been pursuing for a few months is the integration of Grails with Flex 4. I need to rework ConferenceGuide‘s administration backend to make it more ergonomic so that we can cover more events, and ever since I discovered Flex 4 niceties, I couldn’t think of doing that with anything else. The problem is that none of the existing plugins suited my needs. All of them cover Flex 3 only, some of them introduce a lot of complexity for CRUD generation, some of them use GraniteDS instead of BlazeDS, and the simplest plugin, grails-flex has never gone further than the experimental stage. I did a lot of experiments, talked a lot about it on Grails mailing lists, until Tomas Lin kindly explained to me that maybe I was approaching it the wrong way. I wanted a plugin that would set up a complete environment for Flex developement right in the middle of my Grails application. And I wanted that because I wanted to avoid using Flash Builder (you know… Eclipse… ierk!), mainly because the only advantage of Flex Builder 3 over IntelliJ Idea was the visual designer. But he was right, I was wrong. Flash Builder 4 DOES change everything. It does include a lot of very interesting features that greatly improve Flex development productivity, especially when it comes to integration with backend technologies. And for those features, I can only admit that IntelliJ is not up to par yet. I’m still gonna use it for the Grails part, but Flash Builder will be my environment of choice for Flex 4.

So, once I learnt more about Flex 4, BlazeDS 4 and Flash Builder 4 beta 2, it was time to reconsider my approach and develop a much simpler Grails plugin so that any Grails application could be used in combination with Flash Builder. I just released grails-blazeds plugin to do just that. Here is how it works:

  1. Install grails-blazeds plugin: “grails install-plugin blazeds”. This plugin copies a couple of configuration files into your application and imports all of the required libraries, including BlazeDS 4 and Spring-BlazeDS integration 1.5, both in nightly snapshot versions, since they have not been officially released yet
  2. Create a service to be exposed to your Flex application over AMF, or choose an existing one
  3. Add @RemotingDestination annotation to your service class, and @RemotingInclude annotation to all of the methods in this service that you wish to expose
  4. Edit web-app/WEB-INF/flex-servlet.xml (created when you installed the plugin): uncomment the context:component-scan element and set the base-package corresponding to your service class
  5. Make sure your exposed service methods don’t use Groovy classes, either as argument or return types. This is a known limitation I’m still working on, but if there are some Groovy classes here, Flash Builder doesn’t manage to generate ActionScript counterparts.
  6. Run your Grails application using “grails run-war” instead of “grails run-app”. Once again this is a known limitation: Flash Builder BlazeDS data connection plugin relies on a classical web app layout and doesn’t understand Grails dynamic layout (that is until someone manages to create a Grails data connection wizard for Flash Builder 4)
  7. In Flash Builder 4 beta 2, create a new Flex project with a J2EE server. Here are what your parameters shoud look like, “conferenceguide” being the name of my Grails application and “sarbogast” being my home directory:

  8. Click “Data” menu, then “Connect to BlazeDS…”
  9. In the “Authentication required” dialog box that appears, check “no password required” box, and click OK
  10. You should see your service appear, and you can select it and click Finish.
  11. Your service should appear in the Data/Services view. You can then compose your user interface and drag and drop your service methods to the relevant components to connect them with your Grails backend.
  12. Don’t forget to configure a channelset on your service:
    <adminservice:AdminService id="adminService" fault="Alert.show(event.fault.faultString + 'n' + event.fault.faultDetail)" showBusyCursor="true">
    	<adminservice:channelSet>
    		<s:ChannelSet>
    			<s:AMFChannel uri="http://localhost:8080/conferenceguide/messagebroker/amf"/>
    		</s:ChannelSet>
    	</adminservice:channelSet>
    </adminservice:AdminService>
    

And there you go. Special thanks to James Ward, whose screencasts really helped me get it right. Now the only thing that this plugin misses, beyond the 2 known limitations, is integration with Spring Security, but this is just a start.

Enjoy!

19 comments

  1. Looks very nice. I’ll have to look into this over the weekend. I’ve been procrastinating about trying to get a decent setup for developing Flex on Grails.

    I have to disagree with you though on the Flash Builder being better than IntelliJ though. 😉

    1. Note that I still prefer IntelliJ over any Eclipse-based IDE, but what Adobe has done for Data-Driven Development in Flash Builder is very impressive and I just hope Jetbrains will build the same functionality into IntelliJ when Flex 4 will be available in final version.

  2. Hi,

    I’ve installed your Blazeds plugin and when I ran grails run-war I got:

    [groovyc] org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, C:estudoesbagrails-appservicesbrcomproximatiesbaContactService.groovy: 3: unable to resolve class RemotingDestination , unable to find class for annotation
    [groovyc] @ line 3, column 1.
    [groovyc] @RemotingDestination
    [groovyc] ^
    [groovyc] C:estudoesbagrails-appservicesbrcomproximatiesbaContactService.groovy: 6: unable to resolve class RemotingInclude , unable to find class for annotation
    [groovyc] @ line 6, column 3.
    [groovyc] @RemotingInclude
    [groovyc] ^

    What would I do to fix it? Any idea?

    Besta regards

  3. Those annotations are part of the libraries imported by the plugin so they should be on your classpath. Just make sure you added the corresponding import statements in your class:

    import org.springframework.flex.remoting.RemotingDestination
    import org.springframework.flex.remoting.RemotingInclude

  4. This has been an awesome help. Thanks a lot! I have tried all of the other Grails/Blaze plugins and this definitely is the best I have found.

    I tried to take this further and integrate SpringSecurity. I found this which helped me get it ALMOST working. I was able to secure a channel like so:

    However I wasn’t able to secure a service using annotations.

    import org.codehaus.groovy.grails.plugins.springsecurity.Secured;
    import org.springframework.flex.remoting.RemotingDestination;
    import org.springframework.flex.remoting.RemotingInclude;

    @RemotingDestination
    @Secured(‘ROLE_ADMIN’)
    class AmfService {

    boolean transactional = true

    @RemotingInclude
    def getString() {
    return “Superman could kick Batman’s ass”
    }
    }

    No matter how I tried it I was able to go right through and hit the service without logging in. Have you been able to successfully use annotations?

    I am definitely a Flash/Flex guy but I am finding development with Grails to be JUST the kind of back-end stack I don’t mind working in. But I’m definitely a n00b and it is quite likely I am just annotating it wrong or something simple. If I can get security locked down I think I’ll have a REALLY nice system to work with right out of the box!

    1. As far as I’m concerned, I managed to get authentication working, but not authorization. Access is denied as long as I’m not logged in, but once logged in, I have access to everything, whatever my roles and the ones specified by @Secured. From what I remember when I was trying, it seems that @Secured annotations are not seen in compiled classes or something like that. My plan was to wait for a next release of Spring Security plugin, which is apparently under work.

  5. So far I haven’t been able to use [security:intercept-methods] XML for authorization either. I may just have to use a number of different channels and lock each channel down with different security levels. That sure does feel like a hack though . . .

  6. For what it’s worth, I got authorization working. this thread helped me to figure it out, but essentially the key is to code to an Interface. I’ve gotten XML-based authorization to work; haven’t tried @Secured yet but I have high hopes.

    A blog post is forthcoming. I’m super stoked to be where I am with this and definitely wouldn’t be without you! Thanks a ton.

    -Jason

  7. You’re very welcome. I’ll try to combine your forthcoming post and the latest developments with BlazeDS4 and Spring BlazeDS integration 1.0.3 in a more robust version of the grails-blazeds plugin. Please let me know when your post is ready.

  8. Thank you Sébastien. You did a very good job.
    But do you think the famous “lazy-loading” problem has been
    resolved by your method? If no, do you think it could be possible to resolve it integrating it with dphibernate? or graniteds ? how?
    Merci beaucoup,
    Kwame

  9. Sebastien,
    In Ward’s blog, you mentioned hitting the “not available in the specified location” problem.
    And then apparently a solution?

    I’m doing a similar dynamic service registration and am getting that message.
    [Same basic FB4, Spring-Flex-1.5.0; no Grails, but I do classload and register the service on-the-fly]
    Can you offer any indication of what is the underlying problem?

    Did you find a solution? or is this the #5 restriction?
    Is RDS fundamentally limited?

    Any insight you can offer will be appreciated.

    1. The problem is that the BlazeDS stub generator in Flash Builder seems to rely on a very classical web layout. So as soon as you try to combine things dynamically at runtime, it loses its marks. The only solution would be to write another extension to Flash Builder like some guys did it for PHP. But the problem is that this process seems to be completely undocumented (I didn’t find any documentation anyway). For Grails it was just easier to use run-war instead of run-app to make the app look like it has a classical layout. Doing so, I lose some productivity but I do that just once when I need to regenerate stubs, and then I go back to run-app. Now if your layout is more specific, I guess we’ll have to wait for Adobe to come up with a better solution, something more robust that works outside of the basic demonstration scenarios. HTH

  10. Sebastien,
    thanks for the info; for me the problem is that the dynamic service classes are not only in the wrong directory, they are not on the classpath. They are loaded by their own classloader, so there is no hope of explaining to RDS how to find them. So I must run/deploy the dynamic services as standalone apps, whenever I want/need the RDS code generation.
    I may be motivated to use my own template and code generator…

Leave a Reply to Simone Cancel reply