Announcement Announcement Module
Collapse
No announcement yet.
Why does the controller call findAllFoos() on every request? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Why does the controller call findAllFoos() on every request?

    Ok, I don't understand what's going on..
    I've created a bean that maps a table and a controller.
    Now when I access the the page created to insert a new object of that type
    I find that the controller invoke the automatic generated code populateFoo() that does a findAllFoos on the table, loading 14.000 rows and object in memory with a catastrofic result in response performance and used resources.
    Why does spring roo needs to do so?
    There is something I don't understand in the logic behind this. Could anyone explain me?
    thanks!

  • #2
    The Controller is used in all the actions related to Foo and the way the methods are being exposed is that the @ModelAtttribute's in the FooController_Roo_Controller.aj are probably being called in any of the actions (Creation, update, etc) and the populateFoos is meant to be used in the list page.

    By default Roo does not take into account situations like yours and now you need to learn how to customize it.

    Now, being relatively new to Roo myself I can think of two suggestions: Add a findAll method to Foo or add a populateFoo method to the FooController.java (where the query do not really return all Foo's).

    Oh, and I don't think the title of your post helps to being answered sooner.

    Comment


    • #3
      Originally posted by madth3 View Post
      I don't think the title of your post helps to being answered sooner.
      Good point; I've renamed it to help others who might be wondering the same thing.

      The situation is that the scaffolded controllers contain this method (using the Pet class from clinic.roo as an example):
      Code:
      @ModelAttribute("pets")
      public Collection<Pet> PetController.populatePets() {
          return Pet.findAllPets();
      }
      As explained in the Spring MVC doco, the effect of this annotation is that each time the controller handles a request, Pet.findAllPets() is called and the resulting list is added to the implicit UI model under a key of "pets". This happens regardless of whether the request handling method actually needs a list of Pets in the model.

      If you run the bundled clinic.roo script and examine the generated project, you'll find that the only Pet controller method that needs a list of Pets is the "list" method, which populates that model attribute itself anyway. So for the petclinic application at least, the populatePets() method is useless; you can push it in and make it return null and the application still works fine (faster, if anything). The reason we create it in the first place (and admittedly this is a bit of a brute force approach) is that if you add a new Pet field to the Pet class, for example:

      Code:
      field reference --class ~.domain.Pet --fieldName sibling --type ~.domain.Pet
      ... then the create(),createForm(), update(), and updateForm() methods all need the list of pets that's provided by the populatePets() method, since they don't populate this attribute themselves.

      In a nutshell, by doing the simplest thing that works, Roo is generating some code that doesn't scale well to large numbers of rows, as you've found. I've logged ROO-2514 to improve the default controller code; please vote for it if you think it's important.

      Comment


      • #4
        Yeah sorry for the title post, frustration and hurry lend to a poor title.
        However resolved that issue adding populateMethods=false to @RooWebScaffold annotation and managing myself the populating methods (copyng the useful ones).

        I think REAL applications that don't work with empty tables does really need a smarter default approach to this problem. Even delete.jspx call every @ModelAttribute on the controller!
        The search pages too (even those that don't use none of the fields mapped by @ModelAttribute methods ).
        Create a controller for every type of interrogation to have a good resource utilization it seems a bit too much to me.

        However there are other problems like why input.tagx has min, max, decimalMin, decimalMax if it don't use these values? It's a bit confusing..

        Had to use a regex to get it working. And to have an immediate feedback from the dojo widget I had to repeat the regex in the input tag, It does not
        get it from the annotated field.

        Also added a trim and uppercase parameter to input.tagx to pass them to the dojo widjet, that have these features, so why don't use it? To fall back gracefully for
        non javascript active browser?

        To solve the problem that if I specify in a field in a bean that map a city, the default generated code simply load 12000 city beans with a populate, and put all on the page. 8D
        So I had to modify select.tagx to support a dojox.data.QueryReadStore binded to the filtering select, create a controller for the ajax request that populates the input
        choices with only a few and update the list re-quering the server as the user input chars in the field. To avoid the load of an entire JPA bean with all his background (JPA, EntityManager, other field beans) for every occurence i had to create a query that populate a view bean with only id and description, the only useful data during editing choice.
        (hint: --> spring roo needs something like @RooViewBean( id, description) )

        A few more requests, but a lot more responsiveness and less resource for the application.
        I think there is a missing prospective in Spring Roo. How to create a good application that can scale up better for very common problems.
        Last edited by Macs; Jun 17th, 2011, 09:14 AM.

        Comment


        • #5
          Originally posted by Macs View Post
          To solve the problem that if I specify in a field in a bean that map a city, the default generated code simply load 12000 city beans with a populate and put it on the page. 8D
          So I had to modify select.tagx to support a dojox.data.QueryReadStore binded to the filtering select, create a controller for the ajax request that populates the input
          choces with only a few and update the list requering the server as the user input chars in the field. To avoid the load of an entire JPA bean with all his background (JPA, EntityManager, other field beans) for every occurence i had to create a query that populate a view bean with only id and description, the only useful data during editing choice.
          If you're at liberty to share the source code for all this, e.g. as a blog/forum post and/or a ZIP file of a sample project, I'm sure other people in the same boat would find it useful.

          Comment


          • #6
            Is it possible to use DWR to send request and get response? Any hint?

            Comment


            • #7
              Originally posted by Andrew Swan View Post
              If you're at liberty to share the source code for all this, e.g. as a blog/forum post and/or a ZIP file of a sample project, I'm sure other people in the same boat would find it useful.
              when I'm done with some of the work I'll post something

              Comment


              • #8
                I have made two significant improvements as ROO-2514:
                • Roo only creates "populateXxx" methods for domain types that are persistent fields of the form backing type (e.g. PetController no longer has a populatePets() method that uselessly calls Pet.findAllPets(), because the Pet entity does not have a Pet field), and
                • the "populateXxx" methods return null (instead of querying the db) for any request that is not a "show form" request.
                This should vastly reduce the number of database queries. As stated in the above ticket, any requests for further enhancements should be logged as a new improvement.

                Comment

                Working...
                X