Hey Brian,

Short answer, google stripernate and typeconversion, long answer below. 
(beware, this is detailed, but it's not difficult. It may seem like a bit of 
work upfront, but it's all straight forward code with no real trickery 
involved) Don't be scared of the length here, stripes is really nice to work 
with and this is actually a pretty complex situation if you think about, but 
the solution is elegant (I think) and works well.

Long answer, yes, that is a different problem then I thought you were asking 
the first time. What's happening is pretty simple; your object has those 
relationships in the database, but your form doesn't know anything about them. 
It simply knows what is in the form, it doesn't know you have a complex object 
behind the scenes with other relationships. There are several ways to attack 
this (none are that hard mind you).  

The basic idea behind the way to fix this is to tell stripes to load the object 
first, and then before binding (populate object from form values) and 
validation. So where you have the user being loaded simply on the first call, 
that will get you all the form values populated, but it will not save the rest 
of the objects state for later use. Everything in a bean goes away between 
calls. So, to fix it you need to load the object every time you want to refer 
too it! You can do this several ways. 

The easiest way (and I would say 'incorrect' way),  that would work for just 
this actionbean is to use @Before annotation on a method and load the user up 
by putting a hidden value on the form called userId or something and pulling it 
out of the request parameters:
um.load(Long.valueOf(context.getRequest().getParameter('userId'))  //or 
something similar
This isn't elegant, convenient, or robust, you can probably see several reasons 
why.

The next way involves several key areas of stripes. First is the automatic 
extension lookup for stripes; Extensions and using that to supply your own 
converter for your persisted classes: TypeConverters. Now, you could make a 
type converter for each of your @Entity classes, but that's almost as bad as 
the above solution, but not as bad and it's easy to add more classes. Stripes 
however should find them automatically and use them, so it's a step closer to a 
good solution.

But, for a generic approach, that catches all the entities, here's my logic:
First you need to make a generic EntityConverter to load any persistent object. 
Your converter needs access to something from your persistance layer, for 
example hibernate needs a SessionManager. This is tricky in 1.5, but believe is 
solved in 1.6. Short of it is you need to use @SpringBean and modify the 
TypeConverterFactory to inject springbeans automatically (details below). 
Here's my entire converter :
public class EntityConverter implements TypeConverter<Object>{
    Locale locale;
    @SpringBean("sessionFactory") private SessionFactory sessionFactory;
    public void setLocale(Locale locale) {
        this.locale = locale;
    }
    public Object convert(String input, Class<? extends Object> targetType, 
Collection<ValidationError> errors) {
        if(input != null && !"null".equals(input) && !("0".equals(input)) && 
targetType.isAnnotationPresent(Entity.class)){
            return sessionFactory.getCurrentSession().load(targetType, 
Long.parseLong(input));
        }else{
            return null;
        }
    }   
}

To go with this you also need your own TypeConverterFactory. I extend the 
default and override two methods; getInstance and init
In init() I use hibernates metadata to register all my entity classes to use 
the entity converter

The getInstance method is need for the bit of hackery that goes away in future 
version of stripes:
        TypeConverter tc = super.getInstance(convertClass, locale);
        SpringHelper.injectBeans(tc, getConfiguration().getServletContext());
        return tc;

This simply lets your type converters use @SpringBean and have them populated 
correctly as they are not managed by spring or within the typical lifecycle for 
stripes.

Assuming you have configured your stripes extensions package and the 
ConvertFactory lives in there it should find it automatically and start using 
it. Now, how does all this fix your problem??  :)

You can now pass object ID values right along and stripes will automatically 
convert and load your entities, so your call to 
um.getUser("id") is no longer needed, instead user would be passed in as a 
parameter:  /register?user=123 and it should get loaded automatically. 
For your wizard forms, you add a hidden value saying which user you are 
working; <s:hidden name="user" value="myid"/> This will get passed along and 
your user will appear as it should for every request.

This will work for any of your objects coming from anywhere as long it's saved 
and a valid id is passed in your object will get 'hydrated' before the form 
values are saved to it and you will see all the values you will expect. 
Essentially after the setup is done this becomes transparent for the rest of 
the app.

Hope this helps some and doesn't scare you away at all.    :) 

-Nick


On Apr 20, 2010, at 8:01 PM, Brian wrote:

> Thanks again Nick for all your help. Unfortunately after trying your 
> suggestion of adding the taglib it still doesn't work. This should be simple. 
> The problem is that the object that I'm loading at the start of the wizard 
> has nested pre-populated relationships...eg, a User has a Zipcode. It's these 
> nested relationships and any other fields not on the page that seem to get 
> dropped from step to step. Ideally what I would have hoped would work is that 
> the User object would get populated at the start and only any changes would 
> get submitted through the wizard, the original values that are not affected 
> would stay the same. Unfortunately this doesn't seem to be the way it works 
> at all.
> 
> Anyone else got any ideas? I would have really thought it's a pretty common 
> use case.
> 
> Thanks again,
> Brian
> 
> On 20 Apr 2010, at 22:15, Nick Stuart <nstu...@speranzasystems.com> wrote:
> 
>> You're right, just reading the docs on the Wizard Form page it doesn't 
>> mention it, but I've always used the tag when doing some simple wizard 
>> forms. You can find the documentation for the tag at: stripes:wizard-fields
>> 
>> Also reading the wizard forms it references the bugzooky example which I 
>> know, unless it has change recently, is out of date so isn't always the best 
>> to go by. From reading the docs it seems like the @Wizard tag and 
>> stripes:form tag should auto-magically figure out that it's a part of a 
>> wizard and add the fields to the page. Check out the rendered page and see 
>> if there are a bunch of hidden fields on it from the first form (there 
>> should be!). The tag above should forcefully put them there if the magic 
>> isn't happening. 
>> 
>> Again, I'm not terribly sure it does, or SHOULD, happen automatically, as I 
>> always use the tag. Any other stripers have ideas here?
>> 
>> -Nick
>> 
>> On Apr 20, 2010, at 4:50 PM, Brian McSweeney wrote:
>> 
>>> Hi Nick,
>>> 
>>> thanks a million for the reply. I don't see anything about that in the docs 
>>> on the site...
>>> 
>>> http://www.stripesframework.org/display/stripes/Wizard+Forms
>>> 
>>> could you tell me where I can find better info about wizards in here?
>>> 
>>> cheers,
>>> Brian
>>> 
>>> 
>>> On Tue, Apr 20, 2010 at 8:54 PM, Nick Stuart <nstu...@speranzasystems.com> 
>>> wrote:
>>> Do you the the <s:wizardFields/> tag in the form for step 2? (forgive me if 
>>> it's not the correct name, but it's something like that).
>>> 
>>> Thats key for the wizard to work correctly...
>>> 
>>> -Nick
>>> On Apr 20, 2010, at 2:59 PM, brian.mcswee...@gmail.com wrote:
>>> 
>>> > Hi guys,
>>> >
>>> > I'm new to stripes and I'm trying to do what should be super easy. I'm 
>>> > trying to use a multipage wizard to edit an existing object.
>>> > This must be a pretty regular pattern. I've tried using startEvent and 
>>> > saving the user that is retrieved from the database as follows.
>>> > However the values of "user" don't get persisted between steps in the 
>>> > wizard...i've searched at length on the forums and found another
>>> > relevant entry that was never answered....
>>> >
>>> > http://www.mail-archive.com/stripes-users@lists.sourceforge.net/msg02020.html
>>> >
>>> > this should be simple surely, I'm new to stripes and want to give it a 
>>> > proper go...but already not being able to do this is worrying...
>>> >
>>> > thanks for any help, my code is below
>>> >
>>> > brian
>>> >
>>> > @Wizard(startEvents="begin")
>>> > @UrlBinding("/register")
>>> > public class RegisterActionBean extends BaseActionBean {
>>> >
>>> > protected final Log log = LogFactory.getLog(getClass());
>>> > private UserManager um;
>>> >
>>> > /** Setter to allow the UserManager to be injected. */
>>> > @SpringBean
>>> > protected void setUserManager(UserManager um) {
>>> > this.um = um;
>>> > }
>>> >
>>> > @ValidateNestedProperties({
>>> > @Validate(field="password", required=true, 
>>> > minlength=5,maxlength=20,expression="${this eq confirmPassword}")
>>> > })
>>> > private User user;
>>> > private String confirmPassword;
>>> >
>>> > /* Getters and setters for user and confirmPassword */
>>> > @DontValidate
>>> > @DefaultHandler
>>> > public Resolution begin() {
>>> > // for the moment just get one user from the database
>>> > User user = (User)um.getUser("123");
>>> > this.setUser(user);
>>> > return new ForwardResolution("/WEB-INF/jsps/edit1.jsp");
>>> >
>>> > }
>>> >
>>> > public Resolution gotoStep2() throws Exception {
>>> > // do some more logic here if necessary
>>> > return new ForwardResolution("/WEB-INF/jsps/edit2.jsp");
>>> > }
>>> >
>>> > public Resolution gotoStep3() throws Exception {
>>> > // do some more logic here if necessary
>>> > um.save(user);
>>> > return new ForwardResolution("/WEB-INF/jsps/editsuccess.jsp");
>>> > }------------------------------------------------------------------------------
>>> > _______________________________________________
>>> > Stripes-users mailing list
>>> > Stripes-users@lists.sourceforge.net
>>> > https://lists.sourceforge.net/lists/listinfo/stripes-users
>>> 
>>> 
>>> ------------------------------------------------------------------------------
>>> 
>>> _______________________________________________
>>> Stripes-users mailing list
>>> Stripes-users@lists.sourceforge.net
>>> https://lists.sourceforge.net/lists/listinfo/stripes-users
>>> 
>>> 
>>> 
>>> 
>>> -- 
>>> -----------------------------------------
>>> Brian McSweeney
>>> 
>>> Technology Director
>>> Smarter Technology
>>> web: http://www.smarter.ie
>>> phone: +353868578212
>>> -----------------------------------------
>>> 
>>> ------------------------------------------------------------------------------
>>> _______________________________________________
>>> Stripes-users mailing list
>>> Stripes-users@lists.sourceforge.net
>>> https://lists.sourceforge.net/lists/listinfo/stripes-users
>> 
>> ------------------------------------------------------------------------------
>> _______________________________________________
>> Stripes-users mailing list
>> Stripes-users@lists.sourceforge.net
>> https://lists.sourceforge.net/lists/listinfo/stripes-users
> ------------------------------------------------------------------------------
> _______________________________________________
> Stripes-users mailing list
> Stripes-users@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/stripes-users

Attachment: smime.p7s
Description: S/MIME cryptographic signature

------------------------------------------------------------------------------
_______________________________________________
Stripes-users mailing list
Stripes-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/stripes-users

Reply via email to