Flex 4, Java, Spring, and Hibernate in Flash Builder 4

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: 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.

Last week I posted a screencast that walks through the basics of connecting a Flex 4 application to a Java / Spring back-end with the new Data Wizards in Flash Builder 4. Here is a new video that extends beyond just simple RPC method calls and adds Hibernate for persistence. Let me know what you think.


(Open full-size video in a new window)

This entry was posted in Flex, Hibernate, Java, Spring. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.
  • http://martinzoldano.blogspot.com martin zoldano

    Thanks James for the screen-cast, cool stuff!, I like the data binding form wizard, one thing less in my wishlist, now if I could only encourage Adobe to have flash builder 4 work on linux :( , ya there are some tweaks but not quite there yet, what’s the outcome from the survey they run last month? (I participated :)
    Cheers, and thanks again for the post.

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

    Thanks Martin for doing the survey. Still no word on FB for Linux support. Sorry.

    • Anand

      hi!! can you please post a screen-cast for connecting FB4 with Granite-DS 2.2 from scratch with GDS flex plugin for grails because lots of people have not been able to link GD with fB4 and grails please if you can do it… i really need it.

  • Raihaan Cassim

    Hi,

    Thanks for these two screencasts. Quite informative.

    Any chance of perhaps doing something that demonstrates the use of role-based security?

    Thanks

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

    Hi Raihaan,

    That would be cool. I’ll add it to my list of screencasts I want to create!

    -James

  • http://sebastien-arbogast.com Sébastien Arbogast

    +1 for a screencast with basic security. It’s the only thing I miss to really take Flex 4 for a ride on my new project.

  • Ignacio Cases

    James, thank you very much for these nice screencast. I will try to mavenize it.
    +1 for security screencast.

    -Ignacio

  • http://sebastien-arbogast.com Sébastien Arbogast

    FYI, I created a Grails plugin based on your screencasts: http://grails.org/plugin/blazeds

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

    @Sébastien That’s awesome! Thanks for posting that!

  • Martin

    Is the source available so I don’t have to type all the config files again?

    Thanks, great screencast!

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

    Hi Martin,

    Most of the configuration should be here:
    http://www.jamesward.com/downloads/springFlex-server.zip

  • salim

    Thanks James for the cast. Just wondering if the limitations we have always had with flex-hibernate lazy loading objects have been eliminated. These examples are great and they prove the concept but it would great to have a real world example with lazy loading integrated with the flex front end. Is there any such example today?

    Thanks again.

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

    Hi salim,

    You could extend the regular code generators to support lazy loading. By default lazy loading is not addressed. Everything needs to be eager. Hopefully some open source projects will crop up that deal with this.

    -James

  • http://sebastien-arbogast.com Sebastien Arbogast

    You should check out something called dpHibernate on Google Code. I don’t know if it works because I personnally prefer to use DTO’s anyway. But it might be what you are looking for.

  • Mark Spritzler

    I am sorry, it is a really nice screencast for a cool product. But I had to stop watching because of the bad practices that you are showing in the video on Spring and a layered architecture. Just a couple of comments

    1) context:component-scan automatically includes context:annotation-config
    2) Services should not access the database directly, so injecting or writing queries in a service class is tightly coupling your code. (Yes it is a simple example, but people will take that as the way they should go)
    3) Since you created this in 2010, HibernateTemplate is no longer beneficial. You get all the benefits just injecting the sessionFactory into your Repository (again not Services), and then called getCurrentSession to get access to the Session object.

    That is about as far as I could watch.

    Now it looks like you had to do a lot of configuration to set things up. In another video I saw from a while ago, you only needed Springs DispatcherServlet in the web.xml and you also didn’t have to declare all the services to access them from a Flex Widget. Has this changed since then, or do we have to do it the long way like in your video? I hope it is much easier than that.

    Thanks, and please excuse my “meanness” I don’t mean to be mean, and I would love to see more of your screencasts.

    Mark

  • Mark Spritzler

    One thing about the lazy loading with Hibernate.

    When developing using Hibernate, fetching should be use case dependent. You map everything as lazy loading, and based on the use case, you set the query you want to run to eager fetch everything you need for the page. Nothing more, nothing less.

    If you had a fix on the client side to leave the Session open, you are probably going to be degrading performance because of the subsequent calls back to the server to load the next bits of data that has been lazy loaded. If you have eager fetched in the query, then the client side would already have all the data that it needed and not need the extra remote calls. So while, the up front query might be slightly slower, the speed you gain from less server side calls would outweight the gain you got from lazy loading.

    LazyLoadingException is the most common exception in Hibernate, especially when you don’t consider the request and what fetching strategy is being used. While, it is simple to keep it all use case driven, it is a good example of why Hibernate has a really big learning curve. It is much more than just the mapping that is necessary to understand to use Hibernate effectively.

    Mark

  • Mark Spritzler

    Wow, three comments in a row.

    OK, I see why you had more configuration. Your video is just hooking Flex to Spring, but not using the latest Spring Integration with BlazeDS. In which you only need to have the Spring Dispatcher Servlet in your web.xml, etc. So I apologize for last paragraph in my first comment. I mean I apologize for it all, as I am not trying to be negative, just wanted to make sure it is using best practices so that everyone adopts this way of integrating Flex, BlazeDS, and Spring.

    Mark

  • Mark Spritzler

    OK, ignore my lazy loading comment too. I see now that the problem is even if you get just the data you need for the UI, it might include associations that aren’t needed for the UI, and that Flex will traverse the entire object graph, including those that aren’t needed for the UI in that Use Case.

    Thanks

    Mark

  • yuanqixun

    Hello James Ward, Thanks for your article. I have successfully deploy a flex+spring+blazeds project., and it can work normally, but when I refresh the Data/Service view in flash builder. I catch a error that the service can’t find in the configure file. Yes it can’t find from the services-config.xml because of we useing annotation and I have to delete the service from the Data/service view and so can recompile project. Do you meet the problem? how to resolve it?

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

    Hi yuanqixun,

    That seems like a bug. Can you file it: http://bugs.adobe.com/

    Thanks.

    -James

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

    Hi Mark,

    Thanks for you feedback! This is really helpful. The lazy loading thing is a challenge to work around. Here is an article that walks through a strategy for dealing with that:
    http://ria.dzone.com/articles/flex-hibernate-integration

    As far as the HibernateTemplate, can you point me to an example that shows the right way to do it?

    The extra config in the web.xml is needed for FB to connect to BlazeDS and query it’s services. I don’t think the latest Spring BlazeDS Integration does that for you. Correct me if I’m wrong.

    Thanks again for your feedback.

    -James

  • kemal turhan

    It is very good stuff about flex, hibernate and spring i have ever seen. I have tried to run this stuff, but i could’nt. It would be very nice if this stuff is published as a full tutorial.

  • http://tech-o-maniac.co.nr/ Job

    Thanks again for another great guide. Only thing that was different for me was the generated code. I got services:Foo instead of foo:foo like yours. Hence, I had to change a few things to get it to work:

  • Sam

    Hello James,
    I got your guide almost working , so if I test operation it is fine, however running the application on the browser gives me the following error, any thoughts why this is happening:

    “Detected duplicate HTTP-based FlexSessions, generally due to the remote host disabling session cookies. Session cookies must be enabled to manage the client connection correctly.
    null”

    -sam

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

    @Sam I haven’t seen that before. But it looks like others have had that issue before:
    http://www.bing.com/search?setmkt=en-US&q=%22Detected+duplicate+HTTP-based+FlexSessions%22

  • wldandan

    Hi,James
    So great. I have one question about channel configuration in flex side.
    In your video, the barList.mxml declared the channelSet, when I remove the channelset, the flex side will throw exception.
    Can we ignore the AMF channel in client side?

    • fabien

      @wldandan: You can remove config from mxml code, but keep at least service declaration as:

      <services:Foo id="fooService"
      fault="Alert.show(event.fault.faultString+'\n'+event.fault.faultDetail)"
      showBusyCursor="true"/>

      (removing all channel configuration)

      Then, you have to add these lines into services-config.xml (in springFlex-server Project):

          <services>
              <default-channels>
                  <channel ref="my-amf"/>
              </default-channels>
          </services>

      (removing <services/>)

      Fabien from Paris, France.

      • wldandan

        Hi, fabien
        Thanks for your sample. It is great.

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

    @wldandan You need to provide some way / channel for the Flex application to connect to the server. The easiest is the AMF channel.

  • Pingback: Flash Builder 4 Data Wizards with Java / Spring

  • nidhi nautiyal

    Hi

    thanks for a very informative article ..
    i want to know can i display some link as a column in datagrid which will point to some attachment (.pdf,ms excel,ms word etc ) on remote filesystem ?

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

      For sure! You can put a link in the DataGrid that makes a request for the file download.

  • igor

    James, when i connect to a service the follow tag does not exist:
    Service Name

    I can only see the follow tags:
    Service Package
    Data Types Package

    Why this difference happen between us?

  • Ricardo

    did not leave the tag that I’m doubtful
    here it is
    s: AMFChannel uri = “http://localhost:8080/messagebroker/amf

    Excellent tutorial, thank you for contributing to community Flex

  • Ricardo

    Hello, I have two queries regarding work that way … The first doubt is when I finish my project and put it on a server the code
    s: AMFChannel uri = "http://localhost:8080/messagebroker/amf
    no way I put it in a variable not to be changing all the time?

    If Monday is when I connect the data / service to and appear once more attributes in Java class, data / service will not auto update, bringing me the attribute of the java class for me? Or every time I need to create a data / service new to when this happens?

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

      You need to externalize URLs for real production apps. You can do this manually or use a Flex Framework like Swiz to help you do this.

      You can refresh the data services when they change. That should re-introspect the Java classes and update the ActionScript objects.

  • Garry

    Hi James,
    I am facing few problem, when I am trying to work as per your tutorials.
    1. Tomcat – Please let me know- Do I need to download any plug-in for eclipse? I have configure the setting in Tomcat Preferences, even my added manager password also, added into my tomcat package. When I am starting it, through Eclipse, it’s showing everything in same way as I start tomcat directly, but I am not able to look at http://localhost:8080/ as I can when I run directly.

    2. I have downloaded BlazeDS (blazeds-bin-4.0.0.14931 as well as blazeds_bin_3-0-0-544) but I am not getting the same files as you are getting. I have only 12 Files. That’s why I am not able to annotate my service as well.

    Can you please help me on these issues?
    Thanks
    Garry

  • http://www.licream.net licream

    首先我非常感谢你这教程,在网上找了很多这方面的整合demo.还是你的最简单容易懂.
    期待你能做一部hibernate +spring +flex +spring scurity +Cairngorm .haha.我是不是太贪心了啦.

  • Vito

    Thanks man! Great example! And thanks for the dependencies!

  • http://www.webappsolution.com Tim McGee

    Great article James, thanks!

    A question concerning FB4 standalone. I’ve hooked this install up for using WTP but I don’t have any server definitions. When I try to create a server, there’s nothing there. Downloading server definitions brings back a bunch of them but not Tomcat. I did download a plugin and it’s giving me a Tomcat menu option, but it doesn’t work with the server perspective as usual for Eclipse and WTP.

    Has anyone successfully used FB4 standalone, WTP, and Tomcat like you would with an Eclipse, FB4 Plugin, WTP, and Tomcat?

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

      I’d recommend that you install Eclipse, then install FB as a plugin, and then WTP. FB standalone doesn’t have everything in it that some plugins need.

      • http://www.webappsolution.com Tim McGee

        Thanks, yeah that’s what I’m finding.

      • George

        Hello James,

        I’m trying to follow your tutorial but I cannot make the example work.
        So when I try to setup the flex project in the last step when I need to configure the J2EE server I do not get to configure the root folder and the root URL but instead I get to configure the context Root, content folder and the Blaze ds war file location. Why is that? And how could I make it work?

        Thanks in advance!

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

          I’m not sure why this isn’t working for you. You might want to try and go through my Refcard to make sure you haven’t missed a step:
          http://www.jamesward.com/2010/06/14/flex-4-hibernate-3-and-spring-3-integration/

          Otherwise email me so I can work with you on figuring out what is wrong. jaward at adobe dot com

          • George

            Ok thanks James for the replay it was my mistake I have checked in the flex project creation wizard the Create combined Java/Flex project using WTP check box :)
            But still in the last step when I hit the Validate Configuration button this message appears “Cannot access the web server. The server may not be running, or the web root folder or root URL may be invalid.”
            First I thought I can go on because someone said on a site that it might not function correctly but when I try after the flex project is created to connect to Blaze Ds service I check the no password is required and this appears “Error executing RDS command Status Code 403:forbidden”
            By the way the Tomcat server is up and running and the springFlex-server project is deployed on it(this project contains the Blaze Ds in it right?).

            Thanks again for your help!
            And great work!

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

            Is your RDSServlet uncommented in your web.xml file?

          • George

            Sorry for the last post. The RDSServlet is uncommented.

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

            It should look like:

            <servlet>
            <servlet-name>RDSDispatchServlet</servlet-name>
            <servlet-class>flex.rds.server.servlet.FrontEndServlet</servlet-class>
            <init-param>
            <param-name>messageBrokerId</param-name>
            <param-value>_messageBroker</param-value>
            </init-param>
            <init-param>
            <param-name>useAppserverSecurity</param-name>
            <param-value>false</param-value>
            </init-param>
            <load-on-startup>10</load-on-startup>
            </servlet>

            Does it?

          • George

            Yes.
            RDSDispatchServlet
            RDSDispatchServlet
            flex.rds.server.servlet.FrontEndServlet

            When the Tomcat starts up the log shows this message
            INFO: Initializing Spring FrameworkServlet ‘dispatcherServlet’

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

            Do you get an error when you navigate to:
            http://localhost:8080/app/CFIDE/main/ide.cfm

            (Replace the port and context root with your values.)

  • Mehdi

    Hello Mister Ward,thanks for all your amazing tutorials they are really helpful.
    I have a problem though,when i try to create a new Flex project with BlazeDs and Glassfish v3 i get the same error than George : “Cannot access the web server. The server may not be running, or the web root folder or root URL may be invalid.”

    I followed this tutorial to create my web app : http://sujitreddyg.wordpress.com/2009/04/07/setting-up-blazeds/

    What can i do please ?
    I am desperate,i can’t find an answer.

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

      Can’t you ignore that error and continue with the new project wizard? Or are you getting the error somewhere else?

  • Mehdi

    Thanks for your answer Mr Ward,that’s what i did at first but i wasn’t able to run the project.
    It’s working now thanks to your source code,i was a little panicked yesterday and i didn’t see it before posting my message.

  • Ricardo

    Hello, how are you?
    Here in the company we are creating several applications that shared the same model, dao, services …

    Packages are created outside of the applications containing the three Java classes and then generate the jars of these packages and places them in applications like lib …

    But on flex application is not seeing the services that are within the lib folder in a jar …
    I go in Flex 4 Date / Services, BlazeDS and when I select the service is not it …. does anyone know if there’s no way to do this? or how can it be done?

    I have looked on google but found nothing, imagine put date / Services with Jar, apaece much nothing to do with my problem … if anyone can help me??

  • Adi

    Hi James,

    We want to integrate maven / any other cli script as a post build event to our BlazeDS web service project in order to generate the ActionScript classes for services and value objects. Do you know of a way to do so?

    Thank you,
    Adi

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

      Sadly there isn’t a way to do this with the Flash Builder Data Wizards. There are some other tools out there that will do this from an Ant / Maven build. One option is the GAS tool in GraniteDS. I hope that helps.

  • Ricardo

    Hello, how are you?

    I have a class in Java that calls student but it extends a class Person …

    public class Person (

    private TipoPessoa TipoPessoa;
    private String name;
    private Gender gender;
    private TipoCPF tipoCPF;

    )

    public class Student extends Person (

    private String ra;
    private DadosContato dadosContato;
    private Address enderecoCob;
    )

    The problem is that in Flex using the Data / Services RDS does not work that way .. when command “import classes VO student looks like this:
    [ExcludeClass]
    public class extends _Super_Usuario flash.events.EventDispatcher implements com.adobe.fiber.valueobjects.IValueObject
    (
    model_internal static function
    initRemoteClassAliasSingle (cz: Class): void
    (

    Can anyone help me?

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

      Hi Ricardo,

      I feel like there is an open bug for this but I can’t find it. Can you file one:
      http://bugs.adobe.com/

      Thanks.

  • Kemal

    Hi, James
    I will be very happy if you suggest a solution about displaying a clob database field inside a flex aplication using your tutorial framework (Flex 4, Java, Spring, and Hibernate in Flash Builder 4)

    thanks.

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

      What type of data does the clob contain?

      • Kemal

        Image data(jpeg or bmp) i meant.

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

          Sure! Just turn the clob into a bytearray. Then in flex set the source property of an image to the bytearray.

  • karthikeyan M

    Hi,
    Nice Works !
    Can i get the source of the sample projects that your are explaining , along with dependencies.

  • Aj

    Hello Mr. James Ward,
    I am trying one Spring, Hibernate, Flex4 and BlazeDs integration sample. I am getting the below error
    “No destination with id ‘deptService’ is registered with any service.”
    I am using the Annotation method the expose the “deptService” eg.
    @Service(“deptService”)
    @RemotingDestination(channels = { “my-amf” })
    in flex i am trying to access the service

    **************************
    service-config.xml is like this
    ***************************

    org.hibernate.dialect.MySQLDialect
    update

    Please help me to resolve this issue. I am running out of all ideas.
    Thanks in advance.
    Aj

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

      Is the component-scan in the Spring config finding the bean?

      • Aj

        Thanks a lot for your reply.
        I debugged further and come to know that component-scan in the Spring config is not finding the bean. The setSessionFactory method is not called.
        @Autowired
        public void setSessionFactory(SessionFactory sessionFactory) {
        System.out.println(“Autowired method…”);
        template = new HibernateTemplate(sessionFactory);
        }
        I am coping the contents of app-config.xml and my “deptService” is defined under “org.mycompany.db.departmentDao.DeptDAO”

        org.hibernate.dialect.MySQLDialect
        update

        Thanks in advance,
        Aj

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

          And your component-scan is set to “org.mycompany.db.departmentDao”?

          • Aj

            Hello Mr. James Ward,

            Thanks a lot for reply.

            Yes,the component-scan is set to “org.mycompany.db.departmentDao”.
            To test the component-scan i have create the a java file and from main i have tested and it is working.

            if i add the “org.springframework.web.context.ContextLoaderListener” in web.xml then my @Autowired function is called but now i am getting the below error

            ” log4j:ERROR LogMananger.repositorySelector was null likely due to error in class reloading, using NOPLoggerRepository.”

            Please help me.
            Thanks in advance.
            Aj

  • Aj

    I have solved the problem. Thanks for your help.

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

      Great! What was the problem?

      • Aj

        I have added an extra channel in my DeptDAO as given below and i was handling only one channel in my code.
        @RemotingDestination(channels={“my-amf”,”my-secure-amf”})

        Then i tried running the application from ecplice and in eclipse i was able to see the error that i am not handling or using the “”my-secure-amf”. Then i have removed the “”my-secure-amf” channel from the DeptDAO and now it is working fine
        @RemotingDestination(channels={“my-amf”})

        Could you please send any good sample link for spring security.

        Thanks,
        Aj

  • Eradj1

    I try to make flex-4-java-spring-hibernate with BlazeDS. I followed the tutorial in the video, I also made the source located here. I followed the video to this page. I also followed that of page ” http://content.screencast.com/users/jlward4th/folders/Default/media/98f61331-617a-4ac3-87d2-9aeccf317813/springFlex1.mp4?downloadOnly=true” .
    But I have two errors :
    1- when I start the Tomcat server :
    <>

    2- when I continue despite that and I try to connect to the service with BlazeDS : <>

    Please help me to configure the project.
    Thanks in advance.
    Eradj1.

  • Eradj1

    errors:

    1 – INFO: Initializing Spring FrameworkServlet ‘dispatcherServlet’
    [BlazeDS]No login command was found for ‘Apache Tomcat/6.0.14′. Please ensure that the login-command tag has the correct server attribute value, or use ‘all’ to use the login command regardless of the server.
    [BlazeDS]Endpoint ‘my-amf’ created with security:

    2- Network is unreachable: connect

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

      I don’t think those are errors that are causing any problems. Maybe there is something else missing? What is telling you that the network is unreachable?

  • http://www.orsisperu.com HalleyR

    Hello Mr Edwards

    Thanks for the tutorials and to share their knowledge, I have a problem when I create my flash project builder and I click on the button to validate the routes I get the error:

    Can not access the web server. May Not Be The server running, or the web root folder or root URL May Be invalid.

    I have tried to overcome this problem and build the project, but when I connect my data service by flash builder throws me the error:

    RDS Server message:
    RDS Error executing command. Status Code: 404 Reason: not executing

    I have checked my web.xml and if they are uncommented the lines of the RDS here I put the code in my web.xml

    Springmvc_crud
    BlazeDS Spring Integration Application

    contextConfigLocation

    /WEB-INF/spring/*-config.xml

    springSecurityFilterChain
    org.springframework.web.filter.DelegatingFilterProxy

    springSecurityFilterChain
    /*

    flex.messaging.HttpFlexSession

    org.springframework.web.context.ContextLoaderListener

    flex
    org.springframework.web.servlet.DispatcherServlet
    1

    RDSDispatchServlet
    RDSDispatchServlet
    flex.rds.server.servlet.FrontEndServlet

    useAppserverSecurity
    false

    messageBrokerId
    _messageBroker

    10

    RDSDispatchServlet
    /CFIDE/main/ide.cfm

    flex
    /messagebroker/*

    index.jsp


    <!--

    Flex Messaging WorkManager
    wm/MessagingWorkManager
    com.ibm.websphere.asynchbeans.WorkManager
    Container
    Shareable

    -->

    The truth is not to do not found a solution to this problem, please if you can help would be very grateful

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

      The RDSDispatchServlet must not be configured properly. Have you gone through the Refcard and followed all of the steps for setting this up?

      • http://www.orsisperu.com HalleyR

        Hi James Ward

        If I look down the blazeds of the page there is a war adobe preconfigured blazeds spring is the one I’m using will not let me connect to spring when I click on flash dating service builder, could you give me an email to send my config files? or where I can upload it so you can see if you can, really do not know what else to try to redo everything but still I get the same error

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

          Maybe you can ask on http://www.StackOverflow.com since I can’t think of any other place to get help.

  • Manoj Kumar Garwa

    HI, I am new guy with flash builder 4.I am trying to connect flex application through java using blazeds as shown in your video but still getting a problem.when i connect by clicking on Data->Connect to BlazeDS.it ask for username and password so i clicked on No Password Required and than OK.after click on ok it shows following error:
    RDS Server Message
    Error executing RDS Command.Status Code 500, Reason : Internal Server Error.

    I have already replaced web.xml of BlazeDS to web.xml of my working directory by setting useAppserverSecurity to false and uncommented to RDS server declaration and mapping.

    can you pls solve this problem

  • Kiran

    Hello James, Firstly thanx a lot for the awesome artice which enabled even beginners like me to integrate flex 4 with spring service . Right now is there any possibility to modify the data in the database as soon as i fire an event over the datagrid . I added a checkbox and when ever its clicked i wanted to update the db but am failing to do it ..

    Thanx,
    Kiran

  • http://lifuming.com Enjoy

    Hello James,

    How to solve this problem!!

    [BlazeDS]Exception occurred during serialization: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: org.accp.pjo.User.roles, no session or session was closed

    thanks