Announcement Announcement Module
Collapse
No announcement yet.
Generating finders Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Generating finders

    Hi,
    I'd like to generate a finder based on basename, row and column for my entity Foo.

    finder list --depth 3 --class ~.entities.Foo --filter basename,row,column

    With default settings I run out of memory like below. Having added more memory through 'export ROO_OPTS="-Xms256m -Xmx1950m"', it just eats CPU forever. What would be the correct way for me to find the findername and generate it?

    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2882)
    at java.lang.AbstractStringBuilder.expandCapacity(Abs tractStringBuilder.java:100)
    at java.lang.AbstractStringBuilder.append(AbstractStr ingBuilder.java:390)
    at java.lang.StringBuilder.append(StringBuilder.java: 119)
    at org.springframework.roo.addon.finder.DynamicFinder ServicesImpl.populateFinders(DynamicFinderServices Impl.java:259)
    at org.springframework.roo.addon.finder.DynamicFinder ServicesImpl.createFinders(DynamicFinderServicesIm pl.java:246)
    at org.springframework.roo.addon.finder.DynamicFinder ServicesImpl.getFindersFor(DynamicFinderServicesIm pl.java:51)
    at org.springframework.roo.addon.finder.FinderOperati ons.listFindersFor(FinderOperations.java:90)
    at org.springframework.roo.addon.finder.FinderCommand s.listFinders(FinderCommands.java:51)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.roo.support.util.ReflectionUti ls.invokeMethod(ReflectionUtils.java:191)
    at org.springframework.roo.bootstrap.ProcessManagerHo stedExecutionStrategy$1.callback(ProcessManagerHos tedExecutionStrategy.java:33)
    at org.springframework.roo.process.manager.internal.D efaultProcessManager.doTransactionally(DefaultProc essManager.java:131)
    at org.springframework.roo.process.manager.internal.D efaultProcessManager.execute(DefaultProcessManager .java:94)
    at org.springframework.roo.bootstrap.ProcessManagerHo stedExecutionStrategy.execute(ProcessManagerHosted ExecutionStrategy.java:31)
    at org.springframework.roo.shell.internal.AbstractShe ll.executeCommand(AbstractShell.java:128)
    at org.springframework.roo.shell.jline.JLineShell.pro mptLoop(JLineShell.java:158)
    at org.springframework.roo.bootstrap.Bootstrap.run(Bo otstrap.java:113)
    at org.springframework.roo.bootstrap.Bootstrap.main(B ootstrap.java:53)


    Cheers

    Nik

  • #2
    Hi Nik,

    I assume basename, row and column are field names in your Foo entity? How many other fields are there on the Foo entity? Depending on the number you could be looking at a very large number of possible combinations between the fields which can potentially lead to the memory problem here.

    Have you tried running your finder list command with a depth of 1 or 2 first (just to confirm there are no other issues)? Could you share the complete script of the application so we can take a closer look?

    Cheers,
    Stefan

    Comment


    • #3
      Hi Stefan,
      the Foo entity contains ~20 fields. With a depth of 2, the problem is the same, takes ages, and then a memory timeout. The only way I was able to make the finder was by creating a new entity with just those 3, and then copy that name and place, correctly edited, into the @RooEntity annotation in Foo.

      Cheers

      Nik

      Comment


      • #4
        It might be useful to log an enhancement request so that the finder calculator aborts if it finds too many combinations (eg 1000) and instead suggests you use the --filter option to fine-tune the conditions or fields of actual interest.

        Comment


        • #5
          Is there any way to log the generated SQL?

          I think the best way to improve finders performance would be to tune the queries up, I'm not sure if it would be a good feature for Roo (sorry if there is ). Following the 80-20 rule, the 80 percent of cases the dynamic finders work as is, but it will be useful a way to tune the finders up for the 20 percent of cases.

          Comment


          • #6
            Hi Nik,

            Indeed I think the finder addon in Roo help most users (80/20 rule), but there are limits. I am sure we can improve them here or there but in general you are right. We will be looking into developing a lucene-based addon soon which will give you a lot more options and flexibility.

            However, to suit your 20% use case right now, you can easily leverage the createQuery method on the entityManager which is available in each Roo managed entity by default:

            Code:
            Query q = entityManager.createQuery("SELECT Visit FROM Visit AS visit WHERE visit.description LIKE :description");        
            q.setParameter("description", description);
            This is an extract of a finder and you will see that you can write your own queries in exactly the same fashion.

            HTH
            -Stefan

            Comment


            • #7
              Moving Finder to domain entity .java to correct table/column names

              I have a related problem: the generated Finder code in .aj file is ignoring the @Column annotation on the corresponding field in the entity. It is also ignoring "table" attribute of @RooEntity annotation.

              Extract from entity's .java:
              @RooJavaBean
              @RooToString
              @RooEntity(identifierColumn = "SLCID", versionColumn = "JPA_VERSION", table = "SERVICELEVELCONTRACT", finders = { "findContractsByType", "findContractsBySlcNameLike" })
              public class Contract {

              @NotNull
              @Size(min = 3, max = 60)
              @Column(name = "SLCNAME")
              private String slcName;

              @Enumerated
              @Column(name = "SLCTYPE")
              private SlcType type;


              Extract from finder .aj:
              public static TypedQuery<Contract> Contract.findContractsByType(SlcType type) {
              if (type == null) throw new IllegalArgumentException("The type argument is required");
              EntityManager em = Contract.entityManager();
              TypedQuery<Contract> q = em.createQuery("SELECT Contract FROM Contract AS contract WHERE contract.type = :type", Contract.class);
              q.setParameter("type", type);
              return q;

              I tried moving the find method to .java so that I could correct the sql:

              public static TypedQuery<Contract> findContractsByType(SlcType type) {
              if (type == null) throw new IllegalArgumentException("The type argument is required");
              EntityManager em = Contract.entityManager();
              TypedQuery<Contract> q = em.createQuery("SELECT Contract FROM ServiceLevelContract AS contract WHERE contract.slctype = :type", Contract.class);
              q.setParameter("type", type);
              return q;
              }


              However, STS tells me that entityManager() is undefined method for type Contract.

              Do you have any suggestions on either
              - convincing Finder.aj to use @Column and @RooEntity information
              - how to reference entityManager in domain entity's .java

              Thanks in advance,
              Cynthia

              Comment


              • #8
                Originally posted by niklassaers View Post
                I'd like to generate a finder based on basename, row and column for my entity Foo.

                finder list --depth 3 --class ~.entities.Foo --filter basename,row,column

                With default settings I run out of memory like below. Having added more memory through 'export ROO_OPTS="-Xms256m -Xmx1950m"', it just eats CPU forever. What would be the correct way for me to find the findername and generate it?
                This might not be the "correct" way, but it works:

                http://forum.springframework.org/showthread.php?t=84828

                Comment


                • #9
                  Regarding my earlier post in this thread: Moving Finder to domain entity .java to correct table/column names

                  This is a non-issue.

                  I did not realize that EntityManager was mapping strings inside the query. When I looked inside the corresponding Entity.aj files, I saw that queries there also use "contract" instead of "servicelevelcontract". Since the ListView pages (in GWT GUI) are successfully retrieving data, I assume that finder methods also work. I just can't test finder methods on GWT GUI.

                  Comment

                  Working...
                  X