Seaside, Omnibase, OmnibaseSupport - markDirty failing

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Seaside, Omnibase, OmnibaseSupport - markDirty failing

wilkesj
I'm learning to use Seaside with Omnibase and am having some issues.
I'm getting a "ODBError: Object is not persistent or is a part of
composite persistent object" when calling markDirty on an object.

Here is the setup for the app.
I'm using a custom Session class, BLGSession, which is a subclass of
ODBSSession.
I have one domain object, BLGPost, and two components.  One for
listing posts, BLGPostList, and another for creating and editing them,
BLGPostEdit.

BLGPost inherits from ODBSPersistentObject.  It has a body attribute
with the following setter:

BLGPost>>body: anObject
        body := anObject.
        self markDirty.

The edit component is causing the problem.  When I call it to modify
the body attribute of a Post I get the "not persistent" message.

BLGPostEdit>>post
        ^ post isNil
                ifTrue: [post := BLGPost new]
                ifFalse: [post]

BLGPostEdit>>renderContentOn: html
        html form:
                [html paragraph:
                        [html label for: 'post_title'; with: 'Title'.
                        html break.
                        html textInput on: #title of: self post].
                html paragraph:
                        [html label for: 'post_body'; with: 'Body'.
                        html break.
                        html textArea on: #body of: self post].
                html submitButton callback: [self answer: self post]].

I've tried many variations and permutations of this, but can't seem to
get this to work.  Anything obvious that I'm missing?  Is my approach
off?

Thanks,
Wilkes
_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Seaside, Omnibase, OmnibaseSupport - markDirty failing

BrunoBB
Wilkes Joiner escribió:

>I'm learning to use Seaside with Omnibase and am having some issues.
>I'm getting a "ODBError: Object is not persistent or is a part of
>composite persistent object" when calling markDirty on an object.
>  
>
This is because that object it was not make persistent.
I mean, that do not receive the #makePersistent: message.
Example:

bank := Bank new.
accout := Account new.
bank addAccount: account.
transaction makePersistent: bank.
transaction commit.

So, "bank" is a persistent object but "account" is a part of composite
persistent object.
After recover "bank" from repository you can not send #markDirty to
"account".
Only bank can receive #markDirty.

What to do ?

bank := Bank new.
accout := Account new.
bank addAccount: account.
transaction makePersistent: bank;
        makePersistent: account.  " NOW Account is a main persistent
object (NOT a part of composite persistent object) "
transaction commit.

Regards Bruno

_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Seaside, Omnibase, OmnibaseSupport - markDirty failing

wilkesj
That is true, but BLGPost inherits from ODBSPersistentObject which
takes care of this for me, or at least tries to.  I changed it to
raise an error if it can't, just for debugging.  I think that there is
a problem with this, but I can't figure out what it is.  If I create
the objects in a workspace, I can modify them without any problems.

Creating in the workspace.
BLGDatabase current execute:
        [|post posts|
        post := BLGPost new.
        post title: '1'; body: 'body'.
        posts := (OmniBase root at: #BLGPost).
        posts add: post; markDirty.
        post title: '2';].

When updating inside Seaside, I need to pass the post
asPersistentReference.  So I tried changing the post accessor to this

BLGPostEdit>>post
        ^ post isNil
  ifTrue:
                        [BLGDatabase current execute:
                                [post := BLGPost new asPersistentReference]]
                ifFalse: [post]

Didn't help.  I'm pretty sure that the problem is the way I am
creating new objects in Seaside.  I just have no idea how to fix it.

Thanks,
Wilkes


On 2/19/06, Bruno BB (st) <[hidden email]> wrote:

> Wilkes Joiner escribió:
>
> >I'm learning to use Seaside with Omnibase and am having some issues.
> >I'm getting a "ODBError: Object is not persistent or is a part of
> >composite persistent object" when calling markDirty on an object.
> >
> >
> This is because that object it was not make persistent.
> I mean, that do not receive the #makePersistent: message.
> Example:
>
> bank := Bank new.
> accout := Account new.
> bank addAccount: account.
> transaction makePersistent: bank.
> transaction commit.
>
> So, "bank" is a persistent object but "account" is a part of composite
> persistent object.
> After recover "bank" from repository you can not send #markDirty to
> "account".
> Only bank can receive #markDirty.
>
> What to do ?
>
> bank := Bank new.
> accout := Account new.
> bank addAccount: account.
> transaction makePersistent: bank;
>         makePersistent: account.  " NOW Account is a main persistent
> object (NOT a part of composite persistent object) "
> transaction commit.
>
> Regards Bruno
>
> _______________________________________________
> Seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Seaside, Omnibase, OmnibaseSupport - markDirty failing

Dmitry Dorofeev
In reply to this post by wilkesj
I have played with OmnibaseSupport and got it to work with some pain.
Shortly it requires quite serious planning how you store and fetch  
objects from OmniBase.

Notes:
1. you should understand that ODBSSession creates separate omnibase  
transaction for EACH HTTP request and commit it
automatically. That may result in surprises when you fetch data from  
omnibase in one HTTP request, but try to update it (markDirty) in  
another.
That means that you commit object which is alien for current omnibase  
transaction.

2. To avoid surprises EVERY saved object in omnibase (which was sent  
markPersistent) must be derived from  ODBSPersistentObject AND
every time you fetch object from omnibase add asPersistenceReference.

example:
posts := (OmniBase root at: #BLGPost) asPersistenceReference.

example 2.
let's say we have an OrderedCollection (persistent) stored in  
OmniBase at 'col' key.
Our collection contains persistent objects.

objs := (OmniBase root at: 'col') "WRONG"
objs := (OmniBase root at: 'col') asPersistentReference "May be  
Wrong, as markDirty sent to elements later may result in troubles"
objs := (OmniBase root at: 'col') values do: [:v| v  
asPersistentReference] "Ok to markDirty any obj, but we can not alter  
the collection anymore :-("

Seems we need special collections to support persistence references  
provided by omnisupport
or probably it is something i missed in the package ?

Hope my post saves you hours of debugging :-)

Also consider to use alternative approach: "One OmniBase transaction  
per Seaside session".
You can do it without OmniSupport staff, but you need to use checkout  
instead of commit, and do manual unlock of object marked dirty
after checkout. So I feel there is no easy way to do OmniBase +  
Seaside things.

Is my experience deserve an article about OmniBase strategies with  
Seaside to be published ?

-Dmitry.

On 19.02.2006, at 17:37, Wilkes Joiner wrote:

> I'm learning to use Seaside with Omnibase and am having some issues.
> I'm getting a "ODBError: Object is not persistent or is a part of
> composite persistent object" when calling markDirty on an object.
>
> Here is the setup for the app.
> I'm using a custom Session class, BLGSession, which is a subclass of
> ODBSSession.
> I have one domain object, BLGPost, and two components.  One for
> listing posts, BLGPostList, and another for creating and editing them,
> BLGPostEdit.
>
> BLGPost inherits from ODBSPersistentObject.  It has a body attribute
> with the following setter:
>
> BLGPost>>body: anObject
> body := anObject.
> self markDirty.
>
> The edit component is causing the problem.  When I call it to modify
> the body attribute of a Post I get the "not persistent" message.
>
> BLGPostEdit>>post
> ^ post isNil
> ifTrue: [post := BLGPost new]
> ifFalse: [post]
>
> BLGPostEdit>>renderContentOn: html
> html form:
> [html paragraph:
> [html label for: 'post_title'; with: 'Title'.
> html break.
> html textInput on: #title of: self post].
> html paragraph:
> [html label for: 'post_body'; with: 'Body'.
> html break.
> html textArea on: #body of: self post].
> html submitButton callback: [self answer: self post]].
>
> I've tried many variations and permutations of this, but can't seem to
> get this to work.  Anything obvious that I'm missing?  Is my approach
> off?
>
> Thanks,
> Wilkes
> _______________________________________________
> Seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Seaside, Omnibase, OmnibaseSupport - markDirty failing

stephane ducasse
Is my experience deserve an article about OmniBase strategies with  
Seaside to be published ?

Yes! Yes!


_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Seaside, Omnibase, OmnibaseSupport - markDirty failing

Lukas Renggli
In reply to this post by wilkesj
> I'm learning to use Seaside with Omnibase and am having some issues.
> I'm getting a "ODBError: Object is not persistent or is a part of
> composite persistent object" when calling markDirty on an object.

If I were you, I would try with GOODS or Magma to get started in
Seaside, else it is very likely that you get frustrated soon.

OmniBase is very powerful, but together with Seaside it is simply
painful. It took me months to fully understand when objects are
commited, when they need to be marked persistent, when they need to be
manually proxied (asPersistentReference), when they are automatically
proxied, how they are transfered from one transaction to the other,
etc ...

Cheers,
Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch
_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Seaside, Omnibase, OmnibaseSupport - markDirty failing

Lukas Renggli
In reply to this post by Dmitry Dorofeev
> 2. To avoid surprises EVERY saved object in omnibase (which was sent
> markPersistent) must be derived from  ODBSPersistentObject AND
> every time you fetch object from omnibase add asPersistenceReference.

That's not really necessary, but it makes life slightly easier.

> Seems we need special collections to support persistence references
> provided by omnisupport
> or probably it is something i missed in the package ?

ODBSBTree, ODBSTreeSet are useful collections that are included with
OmniSupport.

Cheers,
Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch
_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Seaside, Omnibase, OmnibaseSupport - markDirty failing

wilkesj
In reply to this post by Lukas Renggli
On 2/19/06, Lukas Renggli <[hidden email]> wrote:
> OmniBase is very powerful, but together with Seaside it is simply
> painful. It took me months to fully understand when objects are
> commited, when they need to be marked persistent, when they need to be
> manually proxied (asPersistentReference), when they are automatically
> proxied, how they are transfered from one transaction to the other,
> etc ...


I got this working.  I learned a couple of things.  Executing the
following raises "ODBError: Object is not persistent or is a part of
composite persistent object"

|postRef|
postRef := nil.

BLGDatabase current execute:
        [postRef := BLGPost new asPersistentReference].

BLGDatabase current execute:
        [postRef title: 't1'; body: 'b1'; markDirty]

However this does not:
|postRef|
postRef := nil.

BLGDatabase current execute:
        [postRef := BLGPost new asPersistentReference].

BLGDatabase current execute:
        [postRef title: 't1'; body: 'b1'; makePersistent; markDirty]

Since my component answers with a new Post, I just broke it up into a
create component and an edit component. The method that calls the
create sends the makePersistent to the Post before adding it to the
persistent OrderedCollection.

BLGPostList>>newPost
        | post |
        post := self call: (BLGCreatePost new).
        post makePersistent.
        self listing
                add: post;
                markDirty.

There is quite a bit more to say about this and I'll try to get
something together after doing more complex stuff.

Thanks for everyones help,
Wilkes
_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Seaside, Omnibase, OmnibaseSupport - markDirty failing

Dmitry Dorofeev
Hi,

Glad to see you managed to get it sorted, but still would say that
you didn't get 100% clue how it works :-)

see below.

Wilkes Joiner wrote:

>
>
> I got this working.  I learned a couple of things.  Executing the
> following raises "ODBError: Object is not persistent or is a part of
> composite persistent object"
>
> |postRef|
> postRef := nil.
>
> BLGDatabase current execute:
> [postRef := BLGPost new asPersistentReference].
>
> BLGDatabase current execute:
> [postRef title: 't1'; body: 'b1'; markDirty]
>
> However this does not:
> |postRef|
> postRef := nil.
>
> BLGDatabase current execute:
> [postRef := BLGPost new asPersistentReference].

You can safely leave it as

BLGDatabase current execute:
  [postRef := BLGPost new].

or even
        postRef := BLGPost new
as here is no OmniBase operations at all.


>
> BLGDatabase current execute:
> [postRef title: 't1'; body: 'b1'; makePersistent; markDirty]

finally it is the same as
BLGDatabase current execute:
  [BGLPost new title: 't1'; body: 'b1'; makePersistent]

You don't need to markDirty on objects which just made Persistent ;-)
this will work as well:

BLGDatabase current execute: [
        post := BGLPost new.
        post makePersistent.
        post title: 't1'; body: 'b1'.
]

>
> Since my component answers with a new Post, I just broke it up into a
> create component and an edit component. The method that calls the
> create sends the makePersistent to the Post before adding it to the
> persistent OrderedCollection.
>
> BLGPostList>>newPost
> | post |
"hope you don't use transactions and omnibase calls in BLGCreatePost component
-Dmitry."

> post := self call: (BLGCreatePost new).
> post makePersistent.
> self listing
> add: post;
> markDirty.
>
> There is quite a bit more to say about this and I'll try to get
> something together after doing more complex stuff.
>
> Thanks for everyones help,
> Wilkes
> _______________________________________________
> Seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Seaside, Omnibase, OmnibaseSupport - markDirty failing

wilkesj
On 2/20/06, Dmitry Dorofeev <[hidden email]> wrote:
> Hi,
>
> Glad to see you managed to get it sorted, but still would say that
> you didn't get 100% clue how it works :-)

Certainly not a 100%, but I getting closer ;)

> see below.
>
> Wilkes Joiner wrote:
> >
> >
> > I got this working.  I learned a couple of things.  Executing the
> > following raises "ODBError: Object is not persistent or is a part of
> > composite persistent object"
> >
> > |postRef|
> > postRef := nil.
> >
> > BLGDatabase current execute:
> >       [postRef := BLGPost new asPersistentReference].
> >
> > BLGDatabase current execute:
> >       [postRef title: 't1'; body: 'b1'; markDirty]

Above is what I was originally trying to do by using a single
component for creates and edits.

> > However this does not:
> > |postRef|
> > postRef := nil.
> >
> > BLGDatabase current execute:
> >       [postRef := BLGPost new asPersistentReference].
>
> You can safely leave it as
>
> BLGDatabase current execute:
>         [postRef := BLGPost new].
>
> or even
>         postRef := BLGPost new
> as here is no OmniBase operations at all.
>
>
> >
> > BLGDatabase current execute:
> >       [postRef title: 't1'; body: 'b1'; makePersistent; markDirty]
>
> finally it is the same as
> BLGDatabase current execute:
>         [BGLPost new title: 't1'; body: 'b1'; makePersistent]
>
> You don't need to markDirty on objects which just made Persistent ;-)
> this will work as well:
>
> BLGDatabase current execute: [
>         post := BGLPost new.
>         post makePersistent.
>         post title: 't1'; body: 'b1'.
> ]

Correct, but I'm using as subclass of ODBSSession which wraps every
request inside a transaction.  I was just trying to mimic that
behavior in a workspace, and discover why markDirty fails on a
persistent object that spans multiple transactions.

> >
> > Since my component answers with a new Post, I just broke it up into a
> > create component and an edit component. The method that calls the
> > create sends the makePersistent to the Post before adding it to the
> > persistent OrderedCollection.
> >
> > BLGPostList>>newPost
> >       | post |
> "hope you don't use transactions and omnibase calls in BLGCreatePost component
> -Dmitry."
> >       post := self call: (BLGCreatePost new).
> >       post makePersistent.
> >       self listing
> >               add: post;
> >               markDirty.

Since using ODBSSession puts every request inside an Omnibase
transaction, I am.  But as I gain a better understanding of how
Omnibase and OmnibaseSupport work, I don't think it will be a problem,
but that is a naive assumption at this point.

Thanks,
Wilkes
_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Seaside, Omnibase, OmnibaseSupport - markDirty failing

Lukas Renggli
In reply to this post by wilkesj
> BLGDatabase current execute:
>         [postRef := BLGPost new asPersistentReference].

I would do the following, since #asPersistentReference on a non
persistent object answers self:

BLGDatabase current execute:
      [postRef := BLGPost newPersistent asPersistentReference].

Cheers,
Lukas

--
Lukas Renggli
http://www.lukas-renggli.ch
_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Seaside, Omnibase, OmnibaseSupport - markDirty failing

Günther Schmidt
In reply to this post by stephane ducasse
Stephane,

did you actually publish something on the subject?

Günther

stephane ducasse schrieb:
> Is my experience deserve an article about OmniBase strategies with
> Seaside to be published ?
>
> Yes! Yes!

_______________________________________________
Seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside