You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@struts.apache.org by "CRANFORD, CHRIS" <Ch...@setech.com> on 2011/04/26 05:51:32 UTC

ModelDriven Entity Update

In a form; I have a select box defined as:
<s:select name="propertyOfModel.id" list="myListOfValues" listKey="id"
listValue="description" />

In the model I have the propertyOfModel annotated as @ManyToOne as
follows:
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="PROPERTY_ID",nullable=true,insertable=true,updatable=t
rue)
public PropertyOfModel getPropertyOfModel() {
  // ...
}

Now the form gets submitted to a Struts2 Action which implements model
driven and uses the prepare() method to setup the entity model before
setting the values from the form by querying the service tier for the
object by ID.  The problem is that when the interceptor sets the values
on the model for propertyOfModel.id; if the original propertyOfModel
object was null; then there is no issue but if the object wasn't null
when queried from the database, then I get a transient exception because
it is as if the original object is having it's primary ID changed.

How have others worked around this?  One option I explored was for
setting propertyOfModel object by it's id; I simply set a property on
the action called propertyOfModelId and then use the ID to query the
object from its associated service and then set the object instance or
set to null if ID was null.  

Any other alternatives?

Chris


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: ModelDriven Entity Update

Posted by Eric Lentz <Er...@sherwin.com>.
My solution looks like this:

        public Foo getModel() {
                foo = (Foo) session.get("Foo");
                if (foo == null) {
                        foo = new Foo();
                        session.put("Foo", foo);
                }
                return (foo);
        }

Then, someone selects a particular record in the form and I populate:
foo = facade.findById(fromForm.getId());
session.put("Foo", foo);

Now, when I do the save, the getModel set foo up so that when I call the 
save method, I have a Hibernate proxy enabled object that Hibernate knows 
that it needs to update versus adding a new record. I just have to rejoin 
it to the session.

If it was a new record, then the getModel gives me an instantiated Foo (or 
pull from DI, such as Spring) and save causes Hibernate to add a row.

Is this best practice? I don't know, but this is what I do. I suspect that 
there is a better (more Struts standard) place to put the object instead 
of the session?

- Eric



From:
"CRANFORD, CHRIS" <Ch...@setech.com>
To:
"Struts Users Mailing List" <us...@struts.apache.org>
Date:
04/25/2011 11:52 PM
Subject:
ModelDriven Entity Update




In a form; I have a select box defined as:
<s:select name="propertyOfModel.id" list="myListOfValues" listKey="id"
listValue="description" />

In the model I have the propertyOfModel annotated as @ManyToOne as
follows:
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="PROPERTY_ID",nullable=true,insertable=true,updatable=t
rue)
public PropertyOfModel getPropertyOfModel() {
  // ...
}

Now the form gets submitted to a Struts2 Action which implements model
driven and uses the prepare() method to setup the entity model before
setting the values from the form by querying the service tier for the
object by ID.  The problem is that when the interceptor sets the values
on the model for propertyOfModel.id; if the original propertyOfModel
object was null; then there is no issue but if the object wasn't null
when queried from the database, then I get a transient exception because
it is as if the original object is having it's primary ID changed.

How have others worked around this?  One option I explored was for
setting propertyOfModel object by it's id; I simply set a property on
the action called propertyOfModelId and then use the ID to query the
object from its associated service and then set the object instance or
set to null if ID was null. 

Any other alternatives?

Chris


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org




Re: Field Name Collision?

Posted by Chris Mawata <ch...@mathcove.net>.
That is how OGNL works --  the Model object is higher and has a property 
of the name userId so it is the first match.
Chris

On 4/26/2011 3:52 PM, Eric Lentz wrote:
> - Struts 2.2.1
> - Tomcat 6.0
> - JDK 1.5.0_22
> - Code example of the problem: http://pastebin.com/eyyJaBg4
> - Description:
> I have two fields in my action class: user and userId. The user variable
> is of type User, which also contains a userId. In both cases userId is of
> type String.
>
> While implementing SessionAware and ModelDriven...
>
> Happy path:
> If I pass a parameter in the URL as follows:
> http://localhost:8080/Context/test-list.action?user.userId=foo
>
> Then user.userId = "foo" when it gets to the action.
>
> Not-so-happy path:
> If I pass a parameter in the URL as follows:
> http://localhost:8080/Context/test-list.action?userId=foo
>
> Then user.userId = "foo" when it gets to the action.
>
> Note that in both cases, "foo" was assigned to user.userId, though I used
> different keys in the URL each time!
>
> - Work-around:
> If I change either one of the names to something that is unique to the
> other, then it works as one would expect.
>
> Am I doing something wrong?
>
> - Eric


---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Re: Field Name Collision?

Posted by Eric Lentz <Er...@sherwin.com>.
> - Struts instantiates the User object (in my case) by default.
> - ModelDriven places the object I choose at the top of the stack.
> - Because my object is at the top of the stack, it gets selected instead 

> of the object that Struts creates by default.

I think I answered my own questions here stepping though the code. I don't 
think Struts is instantiating unless it needs to. Thanks for the answers. 
I think I see how this is all working now. I'm not sure how I feel about 
it, but at least I understand.

- Eric

Re: Field Name Collision?

Posted by Eric Lentz <Er...@sherwin.com>.
> I don't use ModelDriven myself, but as I understand it, it places the 
Model
> Object at the top of the Value Stack, which would make userid be a 
reference
> to an attribute in the Model Object, not in the Action.  When you use
> user.userid, it's because it's trying to find the user attribute in the
> Model Object (on the top of the Value Stack), which fails so it goes a 
step
> down the stack to the Action, where it finds a user attribute to use.
> 
> So, it appears Struts is functioning exactly as designed.
>   (*Chris*)

Thanks for the explanation.

Are these correct statements about how Struts and ModelDriven works?

- Struts instantiates the User object (in my case) by default.
- ModelDriven places the object I choose at the top of the stack.
- Because my object is at the top of the stack, it gets selected instead 
of the object that Struts creates by default.


- Eric

Re: Field Name Collision?

Posted by Dave Newton <da...@gmail.com>.
Oh, duh!
On Apr 26, 2011 4:20 PM, "Chris Pratt" <th...@gmail.com> wrote:
> I don't use ModelDriven myself, but as I understand it, it places the
Model
> Object at the top of the Value Stack, which would make userid be a
reference
> to an attribute in the Model Object, not in the Action. When you use
> user.userid, it's because it's trying to find the user attribute in the
> Model Object (on the top of the Value Stack), which fails so it goes a
step
> down the stack to the Action, where it finds a user attribute to use.
>
> So, it appears Struts is functioning exactly as designed.
> (*Chris*)
>
> On Tue, Apr 26, 2011 at 12:55 PM, Dave Newton <da...@gmail.com>
wrote:
>
>> Doubt you're doing anything wrong; I'd expect it's how OGNL does its
>> lookup but haven't confirmed that.
>>
>> Dave
>>
>> On Tue, Apr 26, 2011 at 3:52 PM, Eric Lentz <Er...@sherwin.com>
>> wrote:
>> > - Struts 2.2.1
>> > - Tomcat 6.0
>> > - JDK 1.5.0_22
>> > - Code example of the problem: http://pastebin.com/eyyJaBg4
>> > - Description:
>> > I have two fields in my action class: user and userId. The user
variable
>> > is of type User, which also contains a userId. In both cases userId is
of
>> > type String.
>> >
>> > While implementing SessionAware and ModelDriven...
>> >
>> > Happy path:
>> > If I pass a parameter in the URL as follows:
>> > http://localhost:8080/Context/test-list.action?user.userId=foo
>> >
>> > Then user.userId = "foo" when it gets to the action.
>> >
>> > Not-so-happy path:
>> > If I pass a parameter in the URL as follows:
>> > http://localhost:8080/Context/test-list.action?userId=foo
>> >
>> > Then user.userId = "foo" when it gets to the action.
>> >
>> > Note that in both cases, "foo" was assigned to user.userId, though I
used
>> > different keys in the URL each time!
>> >
>> > - Work-around:
>> > If I change either one of the names to something that is unique to the
>> > other, then it works as one would expect.
>> >
>> > Am I doing something wrong?
>> >
>> > - Eric
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
>> For additional commands, e-mail: user-help@struts.apache.org
>>
>>

Re: Field Name Collision?

Posted by Chris Pratt <th...@gmail.com>.
I don't use ModelDriven myself, but as I understand it, it places the Model
Object at the top of the Value Stack, which would make userid be a reference
to an attribute in the Model Object, not in the Action.  When you use
user.userid, it's because it's trying to find the user attribute in the
Model Object (on the top of the Value Stack), which fails so it goes a step
down the stack to the Action, where it finds a user attribute to use.

So, it appears Struts is functioning exactly as designed.
  (*Chris*)

On Tue, Apr 26, 2011 at 12:55 PM, Dave Newton <da...@gmail.com> wrote:

> Doubt you're doing anything wrong; I'd expect it's how OGNL does its
> lookup but haven't confirmed that.
>
> Dave
>
> On Tue, Apr 26, 2011 at 3:52 PM, Eric Lentz <Er...@sherwin.com>
> wrote:
> > - Struts 2.2.1
> > - Tomcat 6.0
> > - JDK 1.5.0_22
> > - Code example of the problem: http://pastebin.com/eyyJaBg4
> > - Description:
> > I have two fields in my action class: user and userId. The user variable
> > is of type User, which also contains a userId. In both cases userId is of
> > type String.
> >
> > While implementing SessionAware and ModelDriven...
> >
> > Happy path:
> > If I pass a parameter in the URL as follows:
> > http://localhost:8080/Context/test-list.action?user.userId=foo
> >
> > Then user.userId = "foo" when it gets to the action.
> >
> > Not-so-happy path:
> > If I pass a parameter in the URL as follows:
> > http://localhost:8080/Context/test-list.action?userId=foo
> >
> > Then user.userId = "foo" when it gets to the action.
> >
> > Note that in both cases, "foo" was assigned to user.userId, though I used
> > different keys in the URL each time!
> >
> > - Work-around:
> > If I change either one of the names to something that is unique to the
> > other, then it works as one would expect.
> >
> > Am I doing something wrong?
> >
> > - Eric
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
> For additional commands, e-mail: user-help@struts.apache.org
>
>

Re: Field Name Collision?

Posted by Dave Newton <da...@gmail.com>.
Doubt you're doing anything wrong; I'd expect it's how OGNL does its
lookup but haven't confirmed that.

Dave

On Tue, Apr 26, 2011 at 3:52 PM, Eric Lentz <Er...@sherwin.com> wrote:
> - Struts 2.2.1
> - Tomcat 6.0
> - JDK 1.5.0_22
> - Code example of the problem: http://pastebin.com/eyyJaBg4
> - Description:
> I have two fields in my action class: user and userId. The user variable
> is of type User, which also contains a userId. In both cases userId is of
> type String.
>
> While implementing SessionAware and ModelDriven...
>
> Happy path:
> If I pass a parameter in the URL as follows:
> http://localhost:8080/Context/test-list.action?user.userId=foo
>
> Then user.userId = "foo" when it gets to the action.
>
> Not-so-happy path:
> If I pass a parameter in the URL as follows:
> http://localhost:8080/Context/test-list.action?userId=foo
>
> Then user.userId = "foo" when it gets to the action.
>
> Note that in both cases, "foo" was assigned to user.userId, though I used
> different keys in the URL each time!
>
> - Work-around:
> If I change either one of the names to something that is unique to the
> other, then it works as one would expect.
>
> Am I doing something wrong?
>
> - Eric

---------------------------------------------------------------------
To unsubscribe, e-mail: user-unsubscribe@struts.apache.org
For additional commands, e-mail: user-help@struts.apache.org


Field Name Collision?

Posted by Eric Lentz <Er...@sherwin.com>.
- Struts 2.2.1
- Tomcat 6.0
- JDK 1.5.0_22
- Code example of the problem: http://pastebin.com/eyyJaBg4
- Description:
I have two fields in my action class: user and userId. The user variable 
is of type User, which also contains a userId. In both cases userId is of 
type String.

While implementing SessionAware and ModelDriven...

Happy path:
If I pass a parameter in the URL as follows:
http://localhost:8080/Context/test-list.action?user.userId=foo

Then user.userId = "foo" when it gets to the action.

Not-so-happy path:
If I pass a parameter in the URL as follows:
http://localhost:8080/Context/test-list.action?userId=foo

Then user.userId = "foo" when it gets to the action.

Note that in both cases, "foo" was assigned to user.userId, though I used 
different keys in the URL each time!

- Work-around:
If I change either one of the names to something that is unique to the 
other, then it works as one would expect.

Am I doing something wrong?

- Eric