Quantcast

session closed after a service rolls back / "failed to lazily initialize a collection"

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

session closed after a service rolls back / "failed to lazily initialize a collection"

Richard Bradley

Hi,

 

I have a complex domain object which I want to update atomically based on a form POST. I still want validation to work, though.

I’ve put the update logic in a service so that the update is transactional.

As I understand it, the correct way to indicate that the changes should be rolled back is to throw a RuntimeException from the service, so that’s what I do if the changes fail validation.

Unfortunately, this seems to close the hibernate Session, which means that my views can’t access any child collection properties without a “failed to lazily initialize a collection” exception.

 

Is there anything I can do about this? Can I open a new session? Can I mark the changes for rollback without closing the session? Is there a better way to structure this?

 

The controller looks something like:

 

class FooController {

     def fooRepositoryService

 

     def save {

           def foo = Foo.get(params.id)

           try {

                fooRepositoryService.save(foo, params)

                flash.message = "Changes saved"

return redirect(action: "edit", id: foo.id)

} catch (FooRepositoryException e) {

render(view: "edit", model: [questionnaire: questionnaire])

}

}

}

 

And the service looks something like:

 

class FooRepositoryService {

     def save(Foo foo, def params) {

           foo.properties = params // (real code is more complex here)

          

           if (foo.validate() && foo.save(flush: true)) {

                return foo

           }

           throw new FooRepositoryException(“unable to save foo”)

     }

}

 

class FooRepositoryException extends RuntimeException {}

 

 

I’m using Grails 1.3.4.

 

Many thanks,

 

 

Rich


softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   

Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

RE: session closed after a service rolls back / "failed to lazily initialize a collection"

Richard Bradley

Hi,

 

Does anyone have any suggestions on this one?

 

Quick summary: Grails has session-in-view by default, and my views rely on that for lazily loaded properties. However, after a validation failure inside a Service save() method, rolling back the spring transaction causes the hibernate session to be closed, and no new one is automatically opened to replace it. This causes my views to error when I access lazily loaded properties while displaying the edit page with validation messages for the user to retry the transaction.

 

How can I re-open the session?

 

Thanks,

 

 

Rich

 

 

From: Richard Bradley [mailto:[hidden email]]
Sent: 09 September 2010 16:18
To: [hidden email]
Subject: [grails-user] session closed after a service rolls back / "failed to lazily initialize a collection"

 

Hi,

 

I have a complex domain object which I want to update atomically based on a form POST. I still want validation to work, though.

I’ve put the update logic in a service so that the update is transactional.

As I understand it, the correct way to indicate that the changes should be rolled back is to throw a RuntimeException from the service, so that’s what I do if the changes fail validation.

Unfortunately, this seems to close the hibernate Session, which means that my views can’t access any child collection properties without a “failed to lazily initialize a collection” exception.

 

Is there anything I can do about this? Can I open a new session? Can I mark the changes for rollback without closing the session? Is there a better way to structure this?

 

The controller looks something like:

 

class FooController {

     def fooRepositoryService

 

     def save {

           def foo = Foo.get(params.id)

           try {

                fooRepositoryService.save(foo, params)

                flash.message = "Changes saved"

return redirect(action: "edit", id: foo.id)

} catch (FooRepositoryException e) {

render(view: "edit", model: [questionnaire: questionnaire])

}

}

}

 

And the service looks something like:

 

class FooRepositoryService {

     def save(Foo foo, def params) {

           foo.properties = params // (real code is more complex here)

          

           if (foo.validate() && foo.save(flush: true)) {

                return foo

           }

           throw new FooRepositoryException(“unable to save foo”)

     }

}

 

class FooRepositoryException extends RuntimeException {}

 

 

I’m using Grails 1.3.4.

 

Many thanks,

 

 

Rich

 

softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   
Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB


softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   

Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

RE: session closed after a service rolls back / "failed to lazily initialize a collection"

burtbeckwith
I can't replicate this using code very similar to what you've shown. I'm getting the same session after the exception as before and it's still open. Create a small project that demonstrates the issue and create a JIRA issue with the project attached (run 'grails bug-report' to generate the project zip) and we'll take a look.

Burt

> Hi,
>
> Does anyone have any suggestions on this one?
>
> Quick summary: Grails has session-in-view by default, and my views rely on that for lazily loaded properties. However, after a validation failure inside a Service save() method, rolling back the spring transaction causes the hibernate session to be closed, and no new one is automatically opened to replace it. This causes my views to error when I access lazily loaded properties while displaying the edit page with validation messages for the user to retry the transaction.
>
> How can I re-open the session?
>
> Thanks,
>
>
> Rich
>
>
> From: Richard Bradley [mailto:[hidden email]]
> Sent: 09 September 2010 16:18
> To: [hidden email]
> Subject: [grails-user] session closed after a service rolls back / "failed to lazily initialize a collection"
>
> Hi,
>
> I have a complex domain object which I want to update atomically based on a form POST. I still want validation to work, though.
> I've put the update logic in a service so that the update is transactional.
> As I understand it, the correct way to indicate that the changes should be rolled back is to throw a RuntimeException from the service, so that's what I do if the changes fail validation.
> Unfortunately, this seems to close the hibernate Session, which means that my views can't access any child collection properties without a "failed to lazily initialize a collection" exception.
>
> Is there anything I can do about this? Can I open a new session? Can I mark the changes for rollback without closing the session? Is there a better way to structure this?
>
> The controller looks something like:
>
> class FooController {
>      def fooRepositoryService
>
>      def save {
>            def foo = Foo.get(params.id)
>            try {
>                 fooRepositoryService.save(foo, params)
>                 flash.message = "Changes saved"
> return redirect(action: "edit", id: foo.id)
> } catch (FooRepositoryException e) {
> render(view: "edit", model: [questionnaire: questionnaire])
> }
> }
> }
>
> And the service looks something like:
>
> class FooRepositoryService {
>      def save(Foo foo, def params) {
>            foo.properties = params // (real code is more complex here)
>
>            if (foo.validate() && foo.save(flush: true)) {
>                 return foo
>            }
>            throw new FooRepositoryException("unable to save foo")
>      }
> }
>
> class FooRepositoryException extends RuntimeException {}
>
>
> I'm using Grails 1.3.4.
>
> Many thanks,
>
>
> Rich
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
>

signature.asc (205 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

RE: session closed after a service rolls back / "failed to lazily initialize a collection"

Richard Bradley
In reply to this post by Richard Bradley

Thanks, Burt,

 

For some reason I didn’t get your email; I’ve only just found it in the forums.

 

I’ve been able to reproduce this in a small project.

 

I’ve attached a zip to http://jira.codehaus.org/browse/GRAILS-6743

 

Thanks for your help,

 

 

Rich

 

 

From: Burt Beckwith

Sent: Sep 16, 2010

 

I can't replicate this using code very similar to what you've shown. I'm getting the same session after the exception as before and it's still open. Create a small project that demonstrates the issue and create a JIRA issue with the project attached (run 'grails bug-report' to generate the project zip) and we'll take a look. 

Burt 

 

 



softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   

Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

From: Richard Bradley [mailto:[hidden email]]
Sent: 16 September 2010 14:15
To: [hidden email]
Subject: [grails-user] RE: session closed after a service rolls back / "failed to lazily initialize a collection"

 

Hi,

 

Does anyone have any suggestions on this one?

 

Quick summary: Grails has session-in-view by default, and my views rely on that for lazily loaded properties. However, after a validation failure inside a Service save() method, rolling back the spring transaction causes the hibernate session to be closed, and no new one is automatically opened to replace it. This causes my views to error when I access lazily loaded properties while displaying the edit page with validation messages for the user to retry the transaction.

 

How can I re-open the session?

 

Thanks,

 

 

Rich

 

 

From: Richard Bradley [mailto:[hidden email]]
Sent: 09 September 2010 16:18
To: [hidden email]
Subject: [grails-user] session closed after a service rolls back / "failed to lazily initialize a collection"

 

Hi,

 

I have a complex domain object which I want to update atomically based on a form POST. I still want validation to work, though.

I’ve put the update logic in a service so that the update is transactional.

As I understand it, the correct way to indicate that the changes should be rolled back is to throw a RuntimeException from the service, so that’s what I do if the changes fail validation.

Unfortunately, this seems to close the hibernate Session, which means that my views can’t access any child collection properties without a “failed to lazily initialize a collection” exception.

 

Is there anything I can do about this? Can I open a new session? Can I mark the changes for rollback without closing the session? Is there a better way to structure this?

 

The controller looks something like:

 

class FooController {

     def fooRepositoryService

 

     def save {

           def foo = Foo.get(params.id)

           try {

                fooRepositoryService.save(foo, params)

                flash.message = "Changes saved"

return redirect(action: "edit", id: foo.id)

} catch (FooRepositoryException e) {

render(view: "edit", model: [questionnaire: questionnaire])

}

}

}

 

And the service looks something like:

 

class FooRepositoryService {

     def save(Foo foo, def params) {

           foo.properties = params // (real code is more complex here)

          

           if (foo.validate() && foo.save(flush: true)) {

                return foo

           }

           throw new FooRepositoryException(“unable to save foo”)

     }

}

 

class FooRepositoryException extends RuntimeException {}

 

 

I’m using Grails 1.3.4.

 

Many thanks,

 

 

Rich

 

softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   
Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

 

softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   
Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB


softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   

Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

RE: session closed after a service rolls back / "failed to lazily initialize a collection"

Richard Bradley

Hi,

 

Has anyone had a chance to have a look at this? I’ve put a repro case on JIRA at http://jira.codehaus.org/browse/GRAILS-6743

 

Quick summary: Grails has session-in-view by default, and my views rely on that for lazily loaded properties. However, after a validation failure inside a Service save() method, rolling back the spring transaction causes the hibernate session to be closed, and no new one is automatically opened to replace it. This causes my views to error when I access lazily loaded properties while displaying the edit page with validation messages for the user to retry the transaction.

 

How can I re-open the session?

 

Thanks,

 

 

Rich

 

 



softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   

Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

From: Richard Bradley [mailto:[hidden email]]
Sent: 20 September 2010 18:29
To: [hidden email]
Subject: [grails-user] RE: session closed after a service rolls back / "failed to lazily initialize a collection"

 

Thanks, Burt,

 

For some reason I didn’t get your email; I’ve only just found it in the forums.

 

I’ve been able to reproduce this in a small project.

 

I’ve attached a zip to http://jira.codehaus.org/browse/GRAILS-6743

 

Thanks for your help,

 

 

Rich

 

 

From: Burt Beckwith

Sent: Sep 16, 2010

 

I can't replicate this using code very similar to what you've shown. I'm getting the same session after the exception as before and it's still open. Create a small project that demonstrates the issue and create a JIRA issue with the project attached (run 'grails bug-report' to generate the project zip) and we'll take a look. 

Burt 

 

 

 

softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   
Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

From: Richard Bradley [mailto:[hidden email]]
Sent: 16 September 2010 14:15
To: [hidden email]
Subject: [grails-user] RE: session closed after a service rolls back / "failed to lazily initialize a collection"

 

Hi,

 

Does anyone have any suggestions on this one?

 

Quick summary: Grails has session-in-view by default, and my views rely on that for lazily loaded properties. However, after a validation failure inside a Service save() method, rolling back the spring transaction causes the hibernate session to be closed, and no new one is automatically opened to replace it. This causes my views to error when I access lazily loaded properties while displaying the edit page with validation messages for the user to retry the transaction.

 

How can I re-open the session?

 

Thanks,

 

 

Rich

 

 

From: Richard Bradley [mailto:[hidden email]]
Sent: 09 September 2010 16:18
To: [hidden email]
Subject: [grails-user] session closed after a service rolls back / "failed to lazily initialize a collection"

 

Hi,

 

I have a complex domain object which I want to update atomically based on a form POST. I still want validation to work, though.

I’ve put the update logic in a service so that the update is transactional.

As I understand it, the correct way to indicate that the changes should be rolled back is to throw a RuntimeException from the service, so that’s what I do if the changes fail validation.

Unfortunately, this seems to close the hibernate Session, which means that my views can’t access any child collection properties without a “failed to lazily initialize a collection” exception.

 

Is there anything I can do about this? Can I open a new session? Can I mark the changes for rollback without closing the session? Is there a better way to structure this?

 

The controller looks something like:

 

class FooController {

     def fooRepositoryService

 

     def save {

           def foo = Foo.get(params.id)

           try {

                fooRepositoryService.save(foo, params)

                flash.message = "Changes saved"

return redirect(action: "edit", id: foo.id)

} catch (FooRepositoryException e) {

render(view: "edit", model: [questionnaire: questionnaire])

}

}

}

 

And the service looks something like:

 

class FooRepositoryService {

     def save(Foo foo, def params) {

           foo.properties = params // (real code is more complex here)

          

           if (foo.validate() && foo.save(flush: true)) {

                return foo

           }

           throw new FooRepositoryException(“unable to save foo”)

     }

}

 

class FooRepositoryException extends RuntimeException {}

 

 

I’m using Grails 1.3.4.

 

Many thanks,

 

 

Rich

 

softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   
Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

 

softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   
Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

 

softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   
Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB


softwire        
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]   

Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL 

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB

Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

RE: session closed after a service rolls back / "failed to lazily initialize a collection"

burtbeckwith
Sorry, I meant to look at that but haven't yet. I think what's happening is that the session is open but the object is detached from it. This was added a while back so when validation fails, the object is detached so its changes don't get persisted.

If you have a problem with an application-level constraint that doesn't have a corresponding database constraint (e.g. inList or blank, but not nullable/unique/etc.) then because of the Open Session In View interceptor, if the instance isn't detatched then since it's dirty its changes get pushed by Hibernate and since there's no problem at the database level it succeeds, causing unexpected updates. So the sensible fix is to detach it to keep that from happening.

But in your case since the collection isn't initialized before validation, once it's detached it will blow up when referenced from the GSP. One fix would be to initialize the collection before validation. This makes sense if you know you'll be displaying the collection regardless, but it's a little expensive otherwise.

Burt

> Hi,
>
> Has anyone had a chance to have a look at this? I've put a repro case on JIRA at http://jira.codehaus.org/browse/GRAILS-6743
>
> Quick summary: Grails has session-in-view by default, and my views rely on that for lazily loaded properties. However, after a validation failure inside a Service save() method, rolling back the spring transaction causes the hibernate session to be closed, and no new one is automatically opened to replace it. This causes my views to error when I access lazily loaded properties while displaying the edit page with validation messages for the user to retry the transaction.
>
> How can I re-open the session?
>
> Thanks,
>
>
> Rich
>
>
>
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
> From: Richard Bradley [mailto:[hidden email]]
> Sent: 20 September 2010 18:29
> To: [hidden email]
> Subject: [grails-user] RE: session closed after a service rolls back / "failed to lazily initialize a collection"
>
> Thanks, Burt,
>
> For some reason I didn't get your email; I've only just found it in the forums.
>
> I've been able to reproduce this in a small project.
>
> I've attached a zip to http://jira.codehaus.org/browse/GRAILS-6743
>
> Thanks for your help,
>
>
> Rich
>
>
> From: Burt Beckwith
> Sent: Sep 16, 2010
>
> I can't replicate this using code very similar to what you've shown. I'm getting the same session after the exception as before and it's still open. Create a small project that demonstrates the issue and create a JIRA issue with the project attached (run 'grails bug-report' to generate the project zip) and we'll take a look.
>
> Burt
>
>
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
> From: Richard Bradley [mailto:[hidden email]]
> Sent: 16 September 2010 14:15
> To: [hidden email]
> Subject: [grails-user] RE: session closed after a service rolls back / "failed to lazily initialize a collection"
>
> Hi,
>
> Does anyone have any suggestions on this one?
>
> Quick summary: Grails has session-in-view by default, and my views rely on that for lazily loaded properties. However, after a validation failure inside a Service save() method, rolling back the spring transaction causes the hibernate session to be closed, and no new one is automatically opened to replace it. This causes my views to error when I access lazily loaded properties while displaying the edit page with validation messages for the user to retry the transaction.
>
> How can I re-open the session?
>
> Thanks,
>
>
> Rich
>
>
> From: Richard Bradley [mailto:[hidden email]]
> Sent: 09 September 2010 16:18
> To: [hidden email]
> Subject: [grails-user] session closed after a service rolls back / "failed to lazily initialize a collection"
>
> Hi,
>
> I have a complex domain object which I want to update atomically based on a form POST. I still want validation to work, though.
> I've put the update logic in a service so that the update is transactional.
> As I understand it, the correct way to indicate that the changes should be rolled back is to throw a RuntimeException from the service, so that's what I do if the changes fail validation.
> Unfortunately, this seems to close the hibernate Session, which means that my views can't access any child collection properties without a "failed to lazily initialize a collection" exception.
>
> Is there anything I can do about this? Can I open a new session? Can I mark the changes for rollback without closing the session? Is there a better way to structure this?
>
> The controller looks something like:
>
> class FooController {
>      def fooRepositoryService
>
>      def save {
>            def foo = Foo.get(params.id)
>            try {
>                 fooRepositoryService.save(foo, params)
>                 flash.message = "Changes saved"
> return redirect(action: "edit", id: foo.id)
> } catch (FooRepositoryException e) {
> render(view: "edit", model: [questionnaire: questionnaire])
> }
> }
> }
>
> And the service looks something like:
>
> class FooRepositoryService {
>      def save(Foo foo, def params) {
>            foo.properties = params // (real code is more complex here)
>
>            if (foo.validate() && foo.save(flush: true)) {
>                 return foo
>            }
>            throw new FooRepositoryException("unable to save foo")
>      }
> }
>
> class FooRepositoryException extends RuntimeException {}
>
>
> I'm using Grails 1.3.4.
>
> Many thanks,
>
>
> Rich
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

RE: session closed after a service rolls back / "failed to lazily initialize a collection"

Richard Bradley
Thanks, that would be great.

You're right, the only current fix is to manually initialize the collection during validation. That's what I'm doing now. This seems problematic to me because it means that my services have to "know" which collections will be required by the views on validation failure, which breaks encapsulation, and it means that if I fail to correctly identify which collections will be needed, I'll get 500 errors during validation, so it's fragile.

My services currently look something like:

class ComplexModelRepositoryService {
    def save(ComplexModel complexModel, def params) {
        ... update complexModel here ...

        if (complexModel.validate()) {
            if (complexModel.save(flush: true)) {
                return complexModel
            }
        } else {
            // FIXME:see http://jira.codehaus.org/browse/GRAILS-6743
            [complexModel.someProperty, complexModel.otherProperty].each {
                it?.someCollection?.each {
                    Hibernate.initialize(it.yetAnotherCollection)
                }
            }
        }
        // set the id back to 0 for currently saved complexModels which are about to
        // become transient again when this transaction is rolled back:
        if (complexModelWasSavedDuringThisTransaction) {
            complexModel.id = null
        }
        throw new ComplexModelRepositoryException("unable to save complexModel")
    }
}

-----Original Message-----
From: Burt Beckwith [mailto:[hidden email]]
Sent: 28 September 2010 21:20
To: [hidden email]
Subject: Re: [grails-user] RE: session closed after a service rolls back / "failed to lazily initialize a collection"

Sorry, I meant to look at that but haven't yet. I think what's happening is that the session is open but the object is detached from it. This was added a while back so when validation fails, the object is detached so its changes don't get persisted.

If you have a problem with an application-level constraint that doesn't have a corresponding database constraint (e.g. inList or blank, but not nullable/unique/etc.) then because of the Open Session In View interceptor, if the instance isn't detatched then since it's dirty its changes get pushed by Hibernate and since there's no problem at the database level it succeeds, causing unexpected updates. So the sensible fix is to detach it to keep that from happening.

But in your case since the collection isn't initialized before validation, once it's detached it will blow up when referenced from the GSP. One fix would be to initialize the collection before validation. This makes sense if you know you'll be displaying the collection regardless, but it's a little expensive otherwise.

Burt

> Hi,
>
> Has anyone had a chance to have a look at this? I've put a repro case on JIRA at http://jira.codehaus.org/browse/GRAILS-6743
>
> Quick summary: Grails has session-in-view by default, and my views rely on that for lazily loaded properties. However, after a validation failure inside a Service save() method, rolling back the spring transaction causes the hibernate session to be closed, and no new one is automatically opened to replace it. This causes my views to error when I access lazily loaded properties while displaying the edit page with validation messages for the user to retry the transaction.
>
> How can I re-open the session?
>
> Thanks,
>
>
> Rich
>
>
>
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
> From: Richard Bradley [mailto:[hidden email]]
> Sent: 20 September 2010 18:29
> To: [hidden email]
> Subject: [grails-user] RE: session closed after a service rolls back / "failed to lazily initialize a collection"
>
> Thanks, Burt,
>
> For some reason I didn't get your email; I've only just found it in the forums.
>
> I've been able to reproduce this in a small project.
>
> I've attached a zip to http://jira.codehaus.org/browse/GRAILS-6743
>
> Thanks for your help,
>
>
> Rich
>
>
> From: Burt Beckwith
> Sent: Sep 16, 2010
>
> I can't replicate this using code very similar to what you've shown. I'm getting the same session after the exception as before and it's still open. Create a small project that demonstrates the issue and create a JIRA issue with the project attached (run 'grails bug-report' to generate the project zip) and we'll take a look.
>
> Burt
>
>
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
> From: Richard Bradley [mailto:[hidden email]]
> Sent: 16 September 2010 14:15
> To: [hidden email]
> Subject: [grails-user] RE: session closed after a service rolls back / "failed to lazily initialize a collection"
>
> Hi,
>
> Does anyone have any suggestions on this one?
>
> Quick summary: Grails has session-in-view by default, and my views rely on that for lazily loaded properties. However, after a validation failure inside a Service save() method, rolling back the spring transaction causes the hibernate session to be closed, and no new one is automatically opened to replace it. This causes my views to error when I access lazily loaded properties while displaying the edit page with validation messages for the user to retry the transaction.
>
> How can I re-open the session?
>
> Thanks,
>
>
> Rich
>
>
> From: Richard Bradley [mailto:[hidden email]]
> Sent: 09 September 2010 16:18
> To: [hidden email]
> Subject: [grails-user] session closed after a service rolls back / "failed to lazily initialize a collection"
>
> Hi,
>
> I have a complex domain object which I want to update atomically based on a form POST. I still want validation to work, though.
> I've put the update logic in a service so that the update is transactional.
> As I understand it, the correct way to indicate that the changes should be rolled back is to throw a RuntimeException from the service, so that's what I do if the changes fail validation.
> Unfortunately, this seems to close the hibernate Session, which means that my views can't access any child collection properties without a "failed to lazily initialize a collection" exception.
>
> Is there anything I can do about this? Can I open a new session? Can I mark the changes for rollback without closing the session? Is there a better way to structure this?
>
> The controller looks something like:
>
> class FooController {
>      def fooRepositoryService
>
>      def save {
>            def foo = Foo.get(params.id)
>            try {
>                 fooRepositoryService.save(foo, params)
>                 flash.message = "Changes saved"
> return redirect(action: "edit", id: foo.id)
> } catch (FooRepositoryException e) {
> render(view: "edit", model: [questionnaire: questionnaire])
> }
> }
> }
>
> And the service looks something like:
>
> class FooRepositoryService {
>      def save(Foo foo, def params) {
>            foo.properties = params // (real code is more complex here)
>
>            if (foo.validate() && foo.save(flush: true)) {
>                 return foo
>            }
>            throw new FooRepositoryException("unable to save foo")
>      }
> }
>
> class FooRepositoryException extends RuntimeException {}
>
>
> I'm using Grails 1.3.4.
>
> Many thanks,
>
>
> Rich
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com<http://www.softwire.com/> | E-mail : [hidden email] <mailto:[hidden email]>
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email



softwire
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]
Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

RE: session closed after a service rolls back / "failed to lazily initialize a collection"

Richard Bradley
In reply to this post by burtbeckwith
Does anyone have any further suggestions on this thread?

http://grails.1312388.n4.nabble.com/session-closed-after-a-service-rolls-back-failed-to-lazily-initialize-a-collection-td2533057.html

Basically, we've been putting all our databinding + saving logic inside services, so that we have transactionality. This works well, except that on validation failure, rolling back the transaction from within a service causes the Hibernate session to be closed.

This means that all our views which rely on open-session-in-view to display child collections will throw errors when trying to redisplay the model after a validation failure, unless we manually initialise the model in the session before throwing an exception.

I'm actually a bit surprised that no-one else has this issue.

 * Is it uncommon to use services for saving changes from a user form? If so, how do others enforce transactionality of user form changes?
 * Maybe it is uncommon to have views which display child collections on validation failure? Does this mean that my models are too complex? We seem to have a great many pages which have this problem.
 * Perhaps others avoid this issue by using Command objects which do validation outside of a service, so by the time the data gets to the service, you know that you can't have a validation failure?

There's an example project which demonstrates the issue at http://jira.codehaus.org/browse/GRAILS-6743

Thanks,


Rich


softwire
Richard Bradley
Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
Web : www.softwire.com | E-mail : [hidden email]
Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL

Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

RE: session closed after a service rolls back / "failed to lazily initialize a collection"

burtbeckwith
It doesn't cause the session to be closed, it causes the invalid instance to be discarded, which disconnects it from the session. The current best option seems to be to initialize the collections before validating if you plan on accessing the collections from a GSP.

Burt

> Does anyone have any further suggestions on this thread?
>
> http://grails.1312388.n4.nabble.com/session-closed-after-a-service-rolls-back-failed-to-lazily-initialize-a-collection-td2533057.html
>
> Basically, we've been putting all our databinding + saving logic inside services, so that we have transactionality. This works well, except that on validation failure, rolling back the transaction from within a service causes the Hibernate session to be closed.
>
> This means that all our views which rely on open-session-in-view to display child collections will throw errors when trying to redisplay the model after a validation failure, unless we manually initialise the model in the session before throwing an exception.
>
> I'm actually a bit surprised that no-one else has this issue.
>
>  * Is it uncommon to use services for saving changes from a user form? If so, how do others enforce transactionality of user form changes?
>  * Maybe it is uncommon to have views which display child collections on validation failure? Does this mean that my models are too complex? We seem to have a great many pages which have this problem.
>  * Perhaps others avoid this issue by using Command objects which do validation outside of a service, so by the time the data gets to the service, you know that you can't have a validation failure?
>
> There's an example project which demonstrates the issue at http://jira.codehaus.org/browse/GRAILS-6743
>
> Thanks,
>
>
> Rich
>
>
> softwire
> Richard Bradley
> Tel : 020 7485 7500 ext 230 | Fax : 020 7485 7575
> Web : www.softwire.com | E-mail : [hidden email]
> Addr : 325 Highgate Studios, 53-79 Highgate Road, London NW5 1TL
>
> Softwire Technology Limited. Registered in England no. 3824658. Registered Office : 13 Station Road, London N3 2SB
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>     http://xircles.codehaus.org/manage_email
>
>
>

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

RE: session closed after a service rolls back / "failed to lazily initialize a collection"

Richard Bradley
This post has NOT been accepted by the mailing list yet.
I'm just replying to this old thread to say that the issue has been fixed in grails.

See https://github.com/grails/grails-doc/commit/253a59050e12b69b84084e985f28e3a0eca39d62 for full details, including several possible options for working around the problem.

Thanks all,


Rich
Loading...