Grails
  1. Grails
  2. GRAILS-8422

Allow the specification of ids in findOrSaveWhere

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0-RC2, 2.0-RC3, 2.0.1
    • Fix Version/s: 2.2-RC3
    • Component/s: Persistence
    • Labels:
    • Environment:
      Java 6.0.29, Win 7

      Description

      Trying to achieve the following:

      I have:

      class Entry {
        String value
      
        static mapping = {
          id generator:'assigned'
        }
      ...
      }
      

      Now I'd like to do the following:

      Entry entry = Entry.findOrSaveWhere(id:key, value:value);
      

      But this raises:

      org.springframework.orm.hibernate3.HibernateSystemException: ids for this   
      class must be manually assigned before calling save() 
      

      This is probably due to the fact that "id generator:'assigned'" for
      the Entry class but it is a bit strange that the id cannot be specified in the
      constructor (not sure if this holds in general). Please improve this.

      If it worked, it would really improve readability and potentially even
      avoid an additional save() which is required when doing:

      Entry entry = Entry.findOrCreateWhere(id:key, value:value)
      entry.id = key
      entry.save()
      

        Issue Links

          Activity

          Fat Zopilot created issue -
          Graeme Rocher made changes -
          Field Original Value New Value
          Fix Version/s 2.0.1 [ 13005 ]
          Fix Version/s 2.1 [ 12801 ]
          Burt Beckwith made changes -
          Summary Allow the specification of ids in the constructor Allow the specification of ids in findOrSaveWhere
          Description Trying to achieve the following:

          I have:

          class Entry{
            String value;

            static mapping = {
              id generator:'assigned'
            }
          ...
          }

          Now I'd like to do the following:
          Entry entry = Entry.findOrSaveWhere(id:key, value:value);

          But this raises:
          org.springframework.orm.hibernate3.HibernateSystemException: ids for this
          class must be manually assigned before calling save()

          This is probably due to the fact that "id generator:'assigned'" for
          the Entry class but it is a bit strange that the id cannot be specified in the
          constructor (not sure if this holds in general). Please improve this.

          If it worked, it would really improve readability and potentially even
          avoid an additional save() which is required when doing:

          Entry entry = Entry.findOrCreateWhere(id:key, value:value);
          entry.id = key;
          entry.save();
          Trying to achieve the following:

          I have:

          {code}
          class Entry {
            String value

            static mapping = {
              id generator:'assigned'
            }
          ...
          }
          {code}

          Now I'd like to do the following:
          {code}
          Entry entry = Entry.findOrSaveWhere(id:key, value:value);
          {code}

          But this raises:
          {code}
          org.springframework.orm.hibernate3.HibernateSystemException: ids for this
          class must be manually assigned before calling save()
          {code}

          This is probably due to the fact that "id generator:'assigned'" for
          the Entry class but it is a bit strange that the id cannot be specified in the
          constructor (not sure if this holds in general). Please improve this.

          If it worked, it would really improve readability and potentially even
          avoid an additional save() which is required when doing:

          {code}
          Entry entry = Entry.findOrCreateWhere(id:key, value:value)
          entry.id = key
          entry.save()
          {code}
          Jeff Scott Brown made changes -
          Assignee Jeff Brown [ brownj ]
          Hide
          Jeff Scott Brown added a comment -

          Fat,

          Can you take a look at the attached project and let me know if this works for you. This is an RC3 app but I see the same behavior in RC2.

          Note that BootStrap is invoking findOrSaveWhere twice.

          Let me know if this works for you.

          Thanks for the help.

          Show
          Jeff Scott Brown added a comment - Fat, Can you take a look at the attached project and let me know if this works for you. This is an RC3 app but I see the same behavior in RC2. Note that BootStrap is invoking findOrSaveWhere twice. Let me know if this works for you. Thanks for the help.
          Jeff Scott Brown made changes -
          Attachment grails8422.zip [ 17121 ]
          Hide
          Jeff Scott Brown added a comment -

          Fat,

          One scenario that might lead to a problem is if the value of your key variable is null. That would probably lead to the exception you mentioned.

          Show
          Jeff Scott Brown added a comment - Fat, One scenario that might lead to a problem is if the value of your key variable is null. That would probably lead to the exception you mentioned.
          Hide
          Fat Zopilot added a comment -

          Jeff,

          Your project works without any problems. Meanwhile, I found the following:
          If a domain object constructor is invoked with an id inside a service methods that is called via RPC (using the GWT plugin, don't know whether other remote services are affected as well), the id stays null and must be set via setId();
          That's why the findOrSaveWhere method fails there as well.
          All these services extend RemoteServiceServlet. Other services don't seem to be affected. Do you have an idea why this is happening?

          Show
          Fat Zopilot added a comment - Jeff, Your project works without any problems. Meanwhile, I found the following: If a domain object constructor is invoked with an id inside a service methods that is called via RPC (using the GWT plugin, don't know whether other remote services are affected as well), the id stays null and must be set via setId(); That's why the findOrSaveWhere method fails there as well. All these services extend RemoteServiceServlet. Other services don't seem to be affected. Do you have an idea why this is happening?
          Hide
          Jeff Scott Brown added a comment -

          Fat,

          To help be clear about what situations are problematic, can you attach the simplest app that demonstrates the problem you are seeing?

          Thanks for the help.

          Show
          Jeff Scott Brown added a comment - Fat, To help be clear about what situations are problematic, can you attach the simplest app that demonstrates the problem you are seeing? Thanks for the help.
          Hide
          Fat Zopilot added a comment -

          Hm, I fear it won't be that simple as it involves remoting. Have you seen similar tests/apps already in the test suites (testing some remoting related stuff) that could be extended?

          Show
          Fat Zopilot added a comment - Hm, I fear it won't be that simple as it involves remoting. Have you seen similar tests/apps already in the test suites (testing some remoting related stuff) that could be extended?
          Hide
          Fat Zopilot added a comment - - edited

          OK, just updated your project to show the issue. It uses GWT for remoting. Best way to get it running is a grails war first (to compile the GWT JS), then simply run it and open the index page. This will trigger a remote call to SomeService where a new Entry with assigned id is generated (which fails). Suggest to consider it a bug now...

          Show
          Fat Zopilot added a comment - - edited OK, just updated your project to show the issue. It uses GWT for remoting. Best way to get it running is a grails war first (to compile the GWT JS), then simply run it and open the index page. This will trigger a remote call to SomeService where a new Entry with assigned id is generated (which fails). Suggest to consider it a bug now...
          Fat Zopilot made changes -
          Attachment grails8422.zip [ 17139 ]
          Fat Zopilot made changes -
          Status Open [ 1 ] Edit [ 10000 ]
          Affects Version/s 2.0-RC3 [ 13019 ]
          Environment Java 6.0.29, Win 7
          Hide
          Jeff Scott Brown added a comment -

          Fat,

          I don't see any calls to findOrSaveWhere in the project you attached.

          Show
          Jeff Scott Brown added a comment - Fat, I don't see any calls to findOrSaveWhere in the project you attached.
          Hide
          Jeff Scott Brown added a comment -

          There is a service which looks like this:

          grails-app/services/com/demo/SomeService.groovy
          package com.demo
          
          class SomeService {
          
              static expose = [ 'gwt:com.demo.GWTApp' ]
          
              void serviceMethod() {
                  Entry entry = new Entry(value: 'whatever', id: 16l);
                  entry.save();
              }
          }
          

          Is that the problematic code?

          Show
          Jeff Scott Brown added a comment - There is a service which looks like this: grails-app/services/com/demo/SomeService.groovy package com.demo class SomeService { static expose = [ 'gwt:com.demo.GWTApp' ] void serviceMethod() { Entry entry = new Entry(value: 'whatever', id: 16l); entry.save(); } } Is that the problematic code?
          Hide
          Jeff Scott Brown added a comment -

          Fat,

          I can now reproduce the problem. Thanks for the info.

          Show
          Jeff Scott Brown added a comment - Fat, I can now reproduce the problem. Thanks for the info.
          Burt Beckwith made changes -
          Workflow Grails2 [ 70912 ] jira [ 71587 ]
          Status Edit [ 10000 ] Open [ 1 ]
          Burt Beckwith made changes -
          Workflow jira [ 71587 ] Grails2 [ 80344 ]
          Peter Ledbrook made changes -
          Last Reviewed 01/Jan/10
          Peter Ledbrook made changes -
          Workflow Grails2 [ 80344 ] jira [ 88271 ]
          Peter Ledbrook made changes -
          Workflow jira [ 88271 ] Grails2 [ 96483 ]
          Graeme Rocher made changes -
          Fix Version/s 2.0.2 [ 13064 ]
          Fix Version/s 2.0.1 [ 13005 ]
          Fat Zopilot made changes -
          Status Open [ 1 ] Edit [ 10000 ]
          Issue Type Improvement [ 4 ] Bug [ 1 ]
          Affects Version/s 2.0.1 [ 13005 ]
          Raviteja made changes -
          Status Edit [ 10000 ] Open [ 1 ]
          Jeff Scott Brown made changes -
          Issue Type Bug [ 1 ] Improvement [ 4 ]
          Graeme Rocher made changes -
          Fix Version/s 2.0.3 [ 13094 ]
          Fix Version/s 2.0.2 [ 13064 ]
          Graeme Rocher made changes -
          Fix Version/s 2.0.4 [ 13099 ]
          Fix Version/s 2.0.3 [ 13094 ]
          Graeme Rocher made changes -
          Fix Version/s 2.1 [ 13117 ]
          Fix Version/s 2.1-RC1 [ 12801 ]
          Graeme Rocher made changes -
          Fix Version/s 2.1 [ 13125 ]
          Fix Version/s 2.1-RC2 [ 13117 ]
          Jeff Scott Brown made changes -
          Fix Version/s 2.2 [ 13093 ]
          Fix Version/s 2.0.4 [ 13099 ]
          Graeme Rocher made changes -
          Fix Version/s 2.1 [ 13125 ]
          Graeme Rocher made changes -
          Fix Version/s 2.3 [ 13311 ]
          Fix Version/s 2.2-RC1 [ 13093 ]
          Hide
          Stefan Hojer added a comment - - edited

          This bug seems to be fixed by GRAILS-1984. (Grails 2.2-RC1)

          It is sufficient to mark the id as "bindable:true" to allow assignment in constructor / findOrSaveWhere / findOrCreateWhere.

          Example:

          class Entry {
            String value
          
            static constraints = {
              id bindable: true
            }
          
            static mapping = {
              id generator: 'assigned'
            }
          }
          
          Show
          Stefan Hojer added a comment - - edited This bug seems to be fixed by GRAILS-1984 . (Grails 2.2-RC1) It is sufficient to mark the id as "bindable:true" to allow assignment in constructor / findOrSaveWhere / findOrCreateWhere. Example: class Entry { String value static constraints = { id bindable: true } static mapping = { id generator: 'assigned' } }
          Jeff Scott Brown made changes -
          Link This issue is related to GRAILS-1984 [ GRAILS-1984 ]
          Jeff Scott Brown made changes -
          Status Open [ 1 ] Closed [ 6 ]
          Fix Version/s 2.2 [ 13324 ]
          Fix Version/s 2.3 [ 13311 ]
          Resolution Fixed [ 1 ]
          Hide
          Serge P. Nekoval added a comment -

          Hmm. It is not fixed in 2.2.1, still an issue...

          Show
          Serge P. Nekoval added a comment - Hmm. It is not fixed in 2.2.1, still an issue...

            People

            • Assignee:
              Jeff Scott Brown
              Reporter:
              Fat Zopilot
            • Votes:
              1 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Last Reviewed:

                Development