Flash Builder 4 Data Wizards with Java / Spring

UPDATE 1: Flash Builder 4, BlazeDS 4, and Spring 1.0.3 have all been release so you no longer have to use beta or nightly builds of these products. Use the production versions!

UPDATE 2: I’ve done a second part to this screencast that combines Flex 4, Flash Builder 4, Spring 3, BlazeDS 4, and Hibernate 3.

UPDATE 3: A Refcard on Integrating Spring 3 and Flex 4, which I co-authored, is now available! It provides a step-by-step tutorial for setting up everything I show in the video below.

Connecting a Flex 4 application to a Java / Spring back-end couldn’t be easier in Flash Builder 4′s new Data Wizards. I’ve recorded a screencast that shows how to set up the web application project, configure Spring & BlazeDS, and then build a Flex 4 application that connects to the Java / Spring back-end. Check it out and let me know what you think.

(Open full-size video in a new window)

This entry was posted in BlazeDS, Flex, Java, Spring. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.
  • Julien C

    Hi James,

    Thanks a lot for the videos and all your answers.

    I’d like to declare the (default) channel only through xml configuration files or with annotations (not in my flex code). Is-it possible ?

  • Vicky Gupta

    Hi James,

    First of all thanks for providing such a wonderful tutorial.

    I used your tutorial and made few applications. They are working perfectly fine on local system. while opening the application , I found following swf files get downloaded:
    1) framework_4.1.0.16076.swf (1022kb)
    2) spark_4.1.0.16076.swf (492kb)
    3) sparkskins_4.1.0.16076.swf (69kb)
    4) textLayout_1.1.0.604.swf (257kb)

    The size of these files comes close to 2.0 MB and this makes the loading of page very slow.

    Is there any work around for it ?

    Please help !

    Thanks,
    Vicky

    • http://www.jamesward.com James Ward

      These are the Flex Framework RSLs. They will be loaded into the Flash Player cache and then they shouldn’t have to be loaded again. You can turn off the use of the RSLs and you may reduce the load time but the dependencies will not be cached.

  • http://www.zigmacomunicacion.com César Rodríguez

    I just wanna say… Great men, very usefull it was a really big help to undestand BlazeDS, thanks

  • RBK

    Hi James,

    Appreciate your efforts in helping the community.

    I tried the tutorial & it’s working.

    However when I try to a pass a reference objects to the server from flex, I have to call the event handler twice to get the result from the server for the first time. After first time it works normally. (In below case I have to click the button twice in the first time. Is there anything wrong with code?

    Below is the event handler method. Appreciate your help.

    protected function newGame_btn_clickHandler(event:Event):void
    {
    //calling the fooservice.sayHello method
    getGame.token = fooService.sayHello();

    //assign the Game object retruned from the fooservice to the game variable
    game = getGame.lastResult;

    //assign the gameID attrubute of ‘game’ object to gameID variable
    gameID = game.gameID;

    //assign the gameID variable to the string variable msg.
    msg = gameID.toString(10);

    //assign the value of msg variable to the lable
    gameID_lbl.text = msg;
    }

    • http://www.jamesward.com James Ward

      The call to the fooService is asynchronous. So you have to wait for a result event until you can get the data. You can’t access the lastResult right after you made the call.

      • RBK

        Thanks for the clarification James.

        So, what would the best way to avoid this?
        1. Use a timer and access the result property after a while
        or
        2. Use something like JMS to update the client.

        Cheers,
        RBK.

        • http://www.jamesward.com James Ward

          Option 3 – Use an event. getGame will dispatch an event when the response comes back. An event handler can be assigned to call a function which then would read the data. If you are using a CallResponder MXML Declaration then it might look something like:

          <s:CallResponder id="getGame" result="handleGetGameResult(event)"/>

          And in the Script block:

          private function handleGetGameResult(event:ResultEvent):void
          {
            // now you can access data via event.result
          }

          I hope that helps.

          • RBK

            Thanks James.

  • RBK

    Hi James,

    I defined a java object with private attributes and public setters/getters. Then I shared it with Flex.

    However when I try to access the value using the getter method, it doesn’t allow me to do that.

    Instead it allows me to access the value by directly accessing the attribute name.

    Appreciate your support to fix this.

    Cheers,
    RBK.

  • SEW

    Hi James,

    Let me just say thanks for your site, I have learned most of what I know about Flash Builder 4 with BlazeDS from you.

    I’m using the following frameworks.

    Spring 3.0.5 with Annotations
    Blazed 1.0.3

    But I stuck on a AMF issue that I can not seem to figure out. I have POJOs and AS4 Classes defined to matach. I’ve run into a problem when sending a Class that needs to be mapped to a POJO, it works great when I call the first method within the POJO, but when I call another method in that same POJO that also requires that Object, I get the Flash error that the service can not be called.

    I turned on the logging for BlazeDS and what I’ve noticed on the failed calls is that the object is defined as (Object #3).

    The returned Error

    faultDetail = “The expected argument types are (com.group.entity.Group) but the supplied types were (flex.messaging.io.amf.ASObject) and converted to (null).”

    What am I doing wrong? I always create a new RemoteObject for each request with a new AMF Channel.

    I can swap back and forth as to which method I call first, but once I call one of them, the other fails with the same error.

    Please let me know your thoughts on this.

    Thanks

    • http://www.jamesward.com James Ward

      Looks like you need to specify the RemoteClass metadata in your AS object so that there is a mapping between it and the Java object.

      • SEW

        Hi James,

        I have it defined as:

        [RemoteClass(alias="com.group.entity.Group")]
        public class Group {…

        I have two services defined in the POJO that require the ‘Group’ object to be passed in.
        createGroup(Group grp) and createUserLinkedGroup(Group grp)

        They both work, but you can not call both in the same instance of the program. So if I call createGroup, I can use it as many times as I want with out issue, but if I then try to use createUserLinkedGroup it fails. If I reload the Flex app, I can then use createUserLinkedGroup without a problem, but createGroup will no longer work.

        I’m baffled over this and not sure where else to look to solve this problem.

  • SEW

    Hi James,

    I have another question for you regarding Data Wizards.

    I started my application using the Data Wizard to generate the connections to my Java Beans. But I eventually ripped this all out as I was struggle with the objects being returned. No matter what I did, all Objects being returned using the calls generated by the Data Wizard were ASObjects. This makes it very frustrating to use as there is no context help and pulling an Object out of a component like a DataGrid to pass to another call required instantiating a new Bean and copying each element from the ASObject into the bean.

    Once I moved to the manual setup of my beans, they have been mapping correctly and saved me a lot of work.

    So my question to you is, was I doing something wrong? because I don’t really see any advantage of using the Data Wizard unless you have a simple application that requires no custom coding.

    Thanks
    SEW

    • http://www.jamesward.com James Ward

      The data wizards can save time creating the typed value objects and service stubs. But many times I just hand code everything.

      • SEW

        Have you run into the same problem with the objects returned from a POJO not mapping to a AS typed object? I agree the Data Wizard speeds this process up, but why it doesn’t map to the objects it creates seems broken to me. I’ll have to go back and look, but I don’t recall seeing any RemoteClass definitions in the Wizard generated classes.

    • SEW

      Could this be related to Spring and Annotations?

      I just switched from @Repository to @Service and now both calls fail with the error.

      faultString = “Cannot convert type flex.messaging.io.amf.ASObject with remote type specified as ‘null’ to an instance of class com.group.entity.Group”

      Class Definition:

      @Repository("GroupDao")
      @RemotingDestination
      public class GroupDaoImpl implements GroupDao {

      • SEW

        Sorry this was suppose to be attached to the issue related to the Bean Mapping.

        • http://www.jamesward.com James Ward

          What does your service call (the Java method you are calling) and the value object you are serializing look like?

          • SEW

            Here are the objects

            Group.java

            public class Group {

            public String userId;
            public int grpId;
            public int appId;
            public String name;
            public int type;
            public int admin;
            public String cmnt;
            public String updateDate;
            public String updateId;
            }

            Here are the two methods I call

            @Autowired
            private Permissions perms;

            @RemotingInclude
            public void createGroup(Group group) {
            String sql = "INSERT INTO groups (grp_app_id, grp_name, grp_type, grp_cmnt, grp_update_date, grp_update_nt_id) values(?,?,?,?,CURRENT_TIMESTAMP,?)";

            this.simpleJdbcTemplate.update(sql, group.getAppId(), group.getName(), group.getType(), group.getCmnt(), perms.getUserId());
            }

            @RemotingInclude
            public void createUserLinkedGroup(Group group) {
            String sql = "INSERT INTO user_group_xref (user_accts_usr_nt_id, groups_grp_id, group_admin, update_date, update_nt_id) values(?,?,?,CURRENT_TIMESTAMP,?)";

            this.simpleJdbcTemplate.update(sql, group.getUserId(), group.getGrpId(), group.getAdmin(), perms.getUserId());
            }

          • SEW

            Sorry, I think you wanted the AS Object not the Java Object.


            [RemoteClass(alias="com.uhg.dsec.group.entity.Group")]
            public class Group {

            public var userId:String;
            public var grpId:int;
            public var appId:int;
            public var name:String;
            public var type:int;
            public var admin:int;
            public var cmnt:String;
            public var updateDate:String;
            public var updateId:String;

            public function Group()
            {
            }
            }

          • http://www.jamesward.com James Ward

            Maybe it’s package name mismapping? The error says “com.group.entity.Group” and the RemoteClass metadata says “com.uhg.dsec.group.entity.Group”.

          • SEW

            Sorry about that, I was removing the two nodes to mask that information and in my haste I forgot to remove them in the last post. The package names are correct.

            You have to remember these service work, they only have issues after you have already called one of them, then the other will not work and visa-versa.

            This appears to happen for all my custom classes that I pass in, but there seems to be no problem with the native types like String, int, Boolean. I have tested this out by overloading a couple of the methods and all works fine, so I may have to remove the custom classes and pass all the arguments in using native types. Its not the preferred way, but at least I can start moving forward again.

          • http://www.jamesward.com James Ward

            Hmm… I’m not sure what could be happening. Is this on the method call or the method return that you are having the problem? Using the network monitor and by setting breakpoints on the server you should be able to verify that the objects being sent to the server are the correct type.

          • SEW

            Here are the logs captured from BlazeDS

            Working Call:

            [BlazeDS]Serializing AMF/HTTP response
            Version: 3
            (Message #0 targetURI=/10/onResult, responseURI=)
            (Externalizable Object #0 'DSK')
            (Externalizable Object #1 'flex.messaging.io.ArrayCollection')
            (Array #2)
            [0] = (Typed Object #3 'com.group.entity.Group')
            appId = 14
            admin = 0
            userId = null
            name = "All"
            cmnt = ""
            updateId = ""
            type = 1
            updateDate = "2011-02-13 19:04:26.0"
            grpId = 22
            [1] = (Typed Object #4 'com.group.entity.Group')
            appId = 14
            admin = 0
            userId = null
            name = "Junk"
            cmnt = ""
            updateId = ""
            type = 2
            updateDate = "2011-02-18 13:42:54.0"
            grpId = 34
            [2] = (Typed Object #5 'com.group.entity.Group')
            appId = 14
            admin = 0
            userId = null
            name = "TEST5"
            cmnt = null
            updateId = ""
            type = 2
            updateDate = "2011-02-04 08:41:23.0"
            grpId = 21
            1.298054574052E12

            Here is a faild one, as you can see the Object is not mapping to Group as it did in the first call.


            [BlazeDS]Deserializing AMF/HTTP request
            Version: 3
            (Message #0 targetURI=null, responseURI=/15)
            (Array #0)
            [0] = (Typed Object #0 'flex.messaging.messages.RemotingMessage')
            operation = "createUserLinkedGroup"
            source = null
            destination = "GroupDao"
            timestamp = 0
            headers = (Object #1)
            DSId = "DBCC224A-9D0D-D08F-CA28-B8E74B119509"
            DSEndpoint = "my-amf"
            body = (Array #2)
            [0] = (Object #3)
            updateId = null
            userId = ""
            updateDate = null
            grpId = 34
            type = 0
            appId = 14
            name = null
            cmnt = null
            admin = 2
            clientId = null
            messageId = "A4033263-DDD1-953B-8147-3A1886F36B93"
            timeToLive = 0

            [BlazeDS]Serializing AMF/HTTP response
            Version: 3
            (Message #0 targetURI=/15/onStatus, responseURI=)
            (Typed Object #0 'flex.messaging.messages.ErrorMessage')
            headers = (Object #1)
            rootCause = (Typed Object #2 'flex.messaging.messages.ErrorMessage')
            headers = (Object #3)
            rootCause = null
            body = null
            correlationId = null
            faultDetail = null
            faultString = "Cannot convert type flex.messaging.io.amf.ASObject with remote type specified as 'null' to an instance of class com.group.entity.Group"
            clientId = null
            timeToLive = 0.0
            destination = null
            timestamp = 1.298054809362E12
            extendedData = null
            faultCode = "Client.Message.Deserialize.InvalidType"
            messageId = "DBD5E1C2-F22B-3BB3-C83A-41F86C81A4C2"
            body = null
            correlationId = "A4033263-DDD1-953B-8147-3A1886F36B93"
            faultDetail = "The expected argument types are (com.group.entity.Group) but the supplied types were (flex.messaging.io.amf.ASObject) and converted to (null)."
            faultString = "Cannot invoke method 'createUserLinkedGroup'."
            clientId = "DBD5E1C2-F20E-93D7-7CD6-88932156A4AF"
            timeToLive = 0.0
            destination = "GroupDao"
            timestamp = 1.298054809362E12
            extendedData = null
            faultCode = "Server.ResourceUnavailable"
            messageId = "DBD5E1C2-F21D-EE99-79B2-6F248662616E"

          • http://www.jamesward.com James Ward

            What does the AS code look like that calls createUserLinkedGroup?

          • SEW

            Heres the RemoteClass that setups up the RemoteObject


            public class RemoteCalls {

            private static var init:Boolean = false;
            private static var cs:ChannelSet = new ChannelSet();
            private static const AMF_ID:String = "my-amf";
            private static const AMF_END_POINT:String = "messagebroker/amf";
            private static const REQUEST_TIMEOUT:int = 60;

            public static function getRemoteObject(destination:String, event:Function, error:Function, showBusyCursor:Boolean=false):RemoteObject {
            if(!init)
            cs.addChannel(getAmfChannel());

            var service:RemoteObject = new RemoteObject();
            service.channelSet = cs;
            service.destination = destination;
            service.showBusyCursor = showBusyCursor;

            service.addEventListener(ResultEvent.RESULT, event);
            service.addEventListener(FaultEvent.FAULT, error);

            return service;
            }

            public static function getAmfChannel():AMFChannel {
            if(!init)
            checkProtocol(); // Find out if we are HTTPS or HTTP

            var conf:RemoteConfig = RemoteConfig.getInstance();

            var amfChannel:AMFChannel = null;
            if(conf.isHttps()) {
            amfChannel = new SecureAMFChannel(AMF_ID, AMF_END_POINT);
            } else {
            //amfChannel = new AMFChannel(AMF_ID, conf.protocol + conf.server + conf.context + AMF_END_POINT);
            amfChannel = new AMFChannel(AMF_ID, AMF_END_POINT);
            }
            amfChannel.requestTimeout = REQUEST_TIMEOUT;

            return amfChannel;
            }
            }

            Here is the code that makes the call for createUserLinkedGroup. The group object is passed into this Module from the parent when the user selects a row in a DataGrid. The user can then update two fields and submit the update.


            public var grp:Group;

            grp.grpId = grpListingDG.selectedItem.grpId;
            grp.admin = adminList.selectedItem.data;

            var service:RemoteObject = RemoteCalls.getRemoteObject("GroupDao", resultSaveHandler, faultHandler);

            service.createUserLinkedGroup(grp);

          • http://www.jamesward.com James Ward

            That all seems fine. You are passing a Group to createUserLinkedGroup on the client. But for some reason when the call reaches the server it’s no longer a group, but (Object #3). I think there are only two possible reasons for this:
            1) The Group object doesn’t have the correct RemoteClass metadata.
            2) It’s not the right Group object. Perhaps there is some collision with the spark.components.Group class.

        • wooseok
          • SEW

            Thanks wooseok,

            This solved my problem, it never occurred to me that this issue could be related to loading modules.

          • http://www.jamesward.com James Ward

            Wow! Thanks wooseok! I’ve heard of strange problems with AMF serialization of types loaded through modules, but I’ve never experienced it myself.

          • wooseok

            Congratulations SEW! :)
            I’m korean and not so good at writing english.
            Anyway, i wanted to share my experience about the same problem that i solved.

            I always thanks to james sharing many useful informations.

          • liu

            hi wooseok,i have the same problem,but i can’t access the web,pls give me a email about the solution,TKS.

  • Sandeep Chatterjee

    I need help on spring security and flex integration

  • FZR

    Your comment is awaiting moderation.

    hello James when i try to connecte my project flex to my database in mysql ,I have a detailed thread in this tutorial : http://sujitreddyg.wordpress.com/2009/06/01/building-flex-application-for-blazeds-remoting-service-using-flash-builder-4/ . it gives this error :

    RDS Server Message:

    Error executing RDS command. Status Code : 500, Reason : Servlet internal error.

    Thank you a lot… hope taht you have an idea or a suggestion… I lost so much time on this issue!

    I work with JEE, flex plugin…

    • http://www.jamesward.com James Ward

      That usually means that there is a problem on the server side. You should be getting an error in Tomcat. Find that error and let me know what it is.

      • FZR

        But when I try with a simple flex project with Java classes it works fine on tomcat server…

        i use BlaseDS to connecte my connection class java (to connect to MySql database) and my interface flex, and I added RDS sevlet in my web.xml
        but it still gives me this error … Have you please any idea what’s the problem if it not in TOMCAT !!!
        Thank you very much ^^

        • http://www.jamesward.com James Ward

          Maybe you need to turn up the logging verbosity in Tomcat and BlazeDS so you can see the cause of the error.

  • mat

    Hi everyone!
    I’m using BlazeDS and Tomcat to developp a project in FlexBuilder. When i launch my program in FB, everything works fine. As soon as i try to run it in a stand alone mode (exporting a .war and copying it in my webapps directory), nothing happends (deployment works good but after, no ouputs in tomcat console)…. so i tried to call my amf channel in my web browser using url http://localhost:8080/myProject/messagebroker/amf and i got this message in my Tomcat console “[WARN] [CONFIGURATION] HttpFlexSession has not been registered as a listener in web.xml for this application so no events will be dispatched to flexSessionAttreibute or FlexSessionBindingListeners. To correct this, register flex.messaging.HttpFlexSession as a listener in web.xml”
    I added

    flex.messaging.HttpFlexSession
    ” in my web.xml.
    But it did’nt changes anything … I ‘ve googled it but did’nt find any answers to fix this :(
    Do you have any ideas to help me??
    Thks.
    Mat

    • http://www.jamesward.com James Ward

      If you are using the Flash Player Debugger then you should be able to get an error message out of your Flex application. That should give you more details as to what is happening.

  • Yahya

    Coulld you please publish the source code of the project ?

  • james

    hi, is there any address to download the videos ?
    because I am from asian ,the speed is slow .

  • laksu

    Hi James,

    I am new to Flex and trying to come up with a very basic application with Spring on the server side. I followed your refcard from DZone.

    I have the following hello.mxml from the refcard.

    I am getting:
    Parse error: ” is not allowed to follow ”. hello.mxml /hello/src line 6 Flex Problem

    When I remove the … element then I get:

    Description Resource Path Location Type
    Could not resolve to a component implementation. hello.mxml /hello/src line 5 Flex Problem
    Replacing 2009 with 2010 or 2011 solves the latter one but cannot resolve the first one.
    I must be missing something very basic here.

    I am using
    FlashBuilder 4.0.1
    Flex SDK 4.1

    • laksu

      Sorry, the source lines did not make it to here.
      It has to be something related with my FlashBuilder/Flex configuration anyhow. Not specific to the examples presented here.
      Thanks for the walkthrough/refcard.

  • Kiran

    Hello James,

    The example which was here was working earlier. But i have moved my apps to Jboss 5 from 4.2.3 and it stopped working . Are there any necessary configurations i need to do with jboss 5 to get this working ??

    • http://www.jamesward.com James Ward

      Shouldn’t be anything special. Any errors?

  • Alon

    Hi James,
    Great Videos!!
    I’m building a multiplayer game for Facebook with the use of Flex as client side and Java as server side.
    Are java,spring,hibernate,blazeDS the right approach to setting up a server for a game which means that it needs to handle clients request to create a game table/join a game table/chat/access MySQL for saved data about the user and the logic of the game? is it’s the right approach, from where should I start or how should I start ?
    Thanks!

  • http://RegardingSpringflexintgration Salini

    Hi,

    Can you please share a simple source code which intgrate with spring and flex.
    And I want to run in eclipse with flex 4.5 builder and latest blaze ds and spring 3+, and application server can be JBoss or Weblogic.

    Thanks in advance.
    Regards,
    Salini

  • Vijay

    Hi james,

    I am try to create web application by following your tutorial. But when I start tomcat its throwing 2 types of exception
    1.)
    org.springframework.web.servlet.FrameworkServlet initServletBean
    SEVERE: Context initialization failed
    org.springframework.beans.factory.CannotLoadBeanClassException: Error loading class [org.springframework.flex.core.ExceptionTranslationAdvice] for bean with name ‘org.springframework.flex.core.ExceptionTranslationAdvice#0′ defined in null: problem with class file or dependent class; nested exception is java.lang.NoClassDefFoundError: org/aopalliance/aop/Advice

    2.)
    org.apache.catalina.core.StandardContext loadOnStartup
    SEVERE: Servlet threw load() exception
    javax.servlet.ServletException: Unable to find MessageBroker, ensure that if messageBrokerId is set for the MessageBrokerServlet the RDS FrontEndServlet has a matching init-param value

    Please help me.. thank you

  • Marthasibretti

    Hi James!  Great Tutorial! I’m using FlashBuilder IDE, Eclipse , Flex4, BlazeDs, Hibernate and Spring annotation.
    My problem is the service
    [BlazeDS]11/25/2011 [ERROR] [Message.General] Exception when invoking service ‘(none)’: flex.messaging.MessageException: No destination with id ‘userServiceImpl’ is registered with any service.

    And my configuration is:
    @Service

    @RemotingDestination(channels={“channel-amf”})
    public class UserServiceImpl implements UserService {

     

     
    My flex-servlet.xml

      

    flex.remoting.xml

    And service-config.xml

    false

    true
    4

         
    Thanks! I’m very confused!Martha
    flex.remoting.xml

    And service-config.xml

    false

    true

    4

         

    Thanks! I’m very confused!
    Martha

  • Pulakesh

    Hi James,
    I am new to Flex. I have a chart application and the data service is based on http service.
    I want to pass the http service url from an external source. The main idea is to make the url configurable. It can be the wrapper html or an xml file where I can change the http service url any time I want without modifying the flex code.



  • View James Ward's profile on LinkedIn