You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by George Christman <gc...@cardaddy.com> on 2014/03/17 15:18:50 UTC

How to handle form warnings?

Hi Guys, A new requirement has come up where I need to provide validation
warnings to the end user on form submission. As long as the user clicks
okay to the warning, they can continue on with the save. My current design
is as followed.

1. Submit ajax form "timesheet object"
2. Handle form validation errors server side and return to errors to UI
3. If no validation errors occur, process warning logic.
4. If warnings exist, temporarily persist timesheet object to
timesheetHolder obj
5. Return warnings to ui via ajax for the user to OK and acknowledge.
6. On warning submit, grab persisted timesheetHolder obj and copy property
values to timesheet object.
7. Save timesheet object.


Although in theory his should work, I continue to get the following
hibernate exception.

"a different object with the same identifier value was already associated
with the session"

Backend code looks something like this.

warning.java

@PageActivationContext
@Property
private TimeSheetEntity timesheet;

@Persist(PersistenceConstants.FLASH)
private TimeSheetEntity timeSheetHolder;

@Property
private WarningExample warningExample;

@InjectComponent
private Zone formZone, warningZone;

void onActivate() {
        if (timesheet== null) {
            timesheet= new TimeSheetEntity();
        }
 }

Object onValidateFromForm() throws IllegalAccessException,
InvocationTargetException {
        if (timesheet.getName() == null) {
            form.recordError("fix field");
        }

        if (!form.getHasErrors()) {
            timeSheetHolder = new TimeSheetEntity();
            BeanUtils.copyProperties(timeSheetHolder , timesheet);
            hasWarning = true;
        }

        if (hasWarning || form.getHasErrors()) {
            return formZone.getBody();
        }
        return null;
    }

@CommitAfter
    Object onSuccessFromForm() throws IllegalAccessException,
InvocationTargetException {

        if (timeSheetHolder != null) {
            BeanUtils.copyProperties(timesheet, timeSheetHolder);;
        }

        session.saveOrUpdate(timeSheetHolder);
        return linkSource.createPageRenderLinkWithContext(TimeSheet.class,
timesheet.getId());
    }


Warning form

Object onValidateFromWarningForm() {
        if (!warningExample.hasWarning) {
            warningForm.recordError("Form error");
            return warningZone.getBody();
        }

        return null;
    }

    Object onSuccessFromWarningForm() throws IllegalAccessException,
InvocationTargetException {
        return onSuccessFromForm();
    }

    public class WarningExample {

        private boolean hasWarning;

        public boolean isHasWarning() {
            return hasWarning;
        }

        public void setHasWarning(boolean hasWarning) {
            this.hasWarning = hasWarning;
        }
    }


warning.tml


<html t:type="layout" title="this is a warning" xmlns:t="
http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"
xmlns:p="tapestry:parameter">
    <div t:type="zone" t:id="formZone" id="formZone">
        <t:form t:id="form" zone="formZone">
            <t:errors/>
            <div class="form-group">
                <t:Label class="control-label" for="warning"/>
                <t:TextField t:id="warning" value="warning.name"/>
            </div>
            <t:submit t:id="save" value="save"/>
        </t:form>

        <t:if test="hasWarning">
            <div t:type="zone" t:id="warningZone" id="warningZone">
                <t:form t:id="warningForm" zone="warningZone">
                    <t:errors/>
                    <t:checkbox t:id="hasWarning"
value="warningExample.hasWarning"/>Notice 1
                    <t:submit t:id="saveWarning" value="save warning"/>
                </t:form>
            </div>
        </t:if>
    </div>
</html>



Has anybody done anything like this or have a better approach? Perhaps
there is a work around to my bug as well. Please let me know if anybody has
a suggestions.

Thanks

Re: How to handle form warnings?

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Mon, 17 Mar 2014 12:31:31 -0300, George Christman  
<gc...@cardaddy.com> wrote:

> Hi Thiago, I'm aware the hibernate piece is unrelated, however what I'm
> asking is storing my object in the user session the correct approach?

I wouldn't say it's the ideal solution, but I'd consider it a valid one.

> I'm really wondering if I'm using Tapestry properly to produce warnings.

As someone already said, wrap the form inside a Zone, have your form  
update this zone. Use the Errors component to show the validation errors.  
That's what I'd do.

> I don't want to just patch the issue with hibernate .merge if I'm not  
> doing
> something correctly with Tapestry first.

Session.merge() is actually more recommended than saveOrUpdate() anyway. I  
learned this the hard way. merge() completely solves the "a different  
object with the same identifier value was already associated with the  
session" problem.

-- 
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: How to handle form warnings?

Posted by George Christman <gc...@cardaddy.com>.
Hi Thiago, I'm aware the hibernate piece is unrelated, however what I'm
asking is storing my object in the user session the correct approach? I'm
really wondering if I'm using Tapestry properly to produce warnings. I
don't want to just patch the issue with hibernate .merge if I'm not doing
something correctly with Tapestry first.


On Mon, Mar 17, 2014 at 11:10 AM, Thiago H de Paula Figueiredo <
thiagohp@gmail.com> wrote:

> On Mon, 17 Mar 2014 11:18:50 -0300, George Christman <
> gchristman@cardaddy.com> wrote:
>
>  Hi Guys,
>>
>
> Hi!
>
>
>  Although in theory his should work, I continue to get the following
>> hibernate exception.
>>
>> "a different object with the same identifier value was already associated
>> with the session"
>>
>
> This is unrelated to Tapestry.
>
>          session.saveOrUpdate(timeSheetHolder);
>>
>
> Try this instead: timeSheetHolder = session.merge(timeSheetHolder);
>
>
> --
> Thiago H. de Paula Figueiredo
> Tapestry, Java and Hibernate consultant and developer
> http://machina.com.br
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>


-- 
George Christman
www.CarDaddy.com
P.O. Box 735
Johnstown, New York

Re: How to handle form warnings?

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Mon, 17 Mar 2014 11:18:50 -0300, George Christman  
<gc...@cardaddy.com> wrote:

> Hi Guys,

Hi!

> Although in theory his should work, I continue to get the following
> hibernate exception.
>
> "a different object with the same identifier value was already associated
> with the session"

This is unrelated to Tapestry.

>         session.saveOrUpdate(timeSheetHolder);

Try this instead: timeSheetHolder = session.merge(timeSheetHolder);


-- 
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: How to handle form warnings?

Posted by Lance Java <la...@googlemail.com>.
> Works perfectly
Great!

> and is stateless
Music to my ears :)

Re: How to handle form warnings?

Posted by George Christman <gc...@cardaddy.com>.
Yup, I'm using 5.4 in all my apps with the exception of one older one, so
no problem there.

Okay, for anybody else that may run into this situation, here is my demo
code. This is a main form with two separate ajax warnings chained together
with validation. The main form is injected as a block but set to display
none with css. Works perfectly an is stateless :)

Thanks Everyone.


Warning.java

public class Warning {

    @Component(id = "form")
    private Form form;

    @Component(id = "formWarning")
    private Form formWarning;

    @PageActivationContext
    @Property
    private Computer computer;

    @InjectComponent
    private Zone formZone, formWarningZone;

    @Inject
    private PageRenderLinkSource linkSource;

    @Inject
    private Session session;

    @Inject
    private AjaxResponseRenderer ajaxResponseRenderer;

    @Inject
    private Block warningBlock, notificationBlock;

    @Property
    private Block activeWarningBlock;

    @Property
    private boolean triggerWarning, triggerNotification, triggerValidation;

    @Property
    private boolean hasWarnings, hasValidationErrors;

    private boolean notificationEvent, warningEvent;

    void onActivate() {
        if (computer == null) {
            computer = new Computer();
        }
    }

    void onValidateFromForm() throws IllegalAccessException,
InvocationTargetException {
        //Handle validation main form.
        if(computer.getName() == null) {
            form.recordError("computer can not be null");
        } else if(form.getHasErrors()) {
            hasValidationErrors = true;
            ajaxResponseRenderer.addRender("formZone", formZone);
        }

        if(triggerWarning && form.isValid()) {
            form.recordError("trigger warning block");
            hasWarnings = true;
            activeWarningBlock = warningBlock;
            ajaxResponseRenderer.addRender("formWarningZone",
formWarningZone);
        }

    }

    void onValidateFromFormWarning() throws IllegalAccessException,
InvocationTargetException {
        //Generate Serverside Validation Errors
        if(triggerValidation && warningEvent) {
            formWarning.recordError("warning validation test");
        } else if(triggerValidation && notificationEvent) {
            formWarning.recordError("notification validation test");
        }

        //Return proper warning block
        if(formWarning.getHasErrors()) {
            hasValidationErrors = true;
            activeWarningBlock = warningEvent ? warningBlock :
notificationBlock;
        }

        //Produce Notification Warning
        if(formWarning.isValid() && triggerNotification) {
            formWarning.recordError("tigger notification block");
            activeWarningBlock = notificationBlock;
        }

        //Render formWarning zone if validation or warnings exist
        if(formWarning.getHasErrors()) {
            hasWarnings = true;
            ajaxResponseRenderer.addRender("formWarningZone",
formWarningZone);
        }

    }

    @CommitAfter
    Object onSuccess() throws IllegalAccessException,
InvocationTargetException {
        session.saveOrUpdate(computer);
        return linkSource.createPageRenderLinkWithContext(Warning.class,
computer.getId());
    }

    public void onWarningEvent() {
        this.warningEvent = true;
    }

    public void onNotificationEvent() {
        this.notificationEvent = true;
    }

}

Computer.class

public class Computer implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;

    getters/setters
}

Warning.tml

<html t:type="layout" title="Warning Demo" xmlns:t="
http://tapestry.apache.org/schema/tapestry_5_1_0.xsd"
xmlns:p="tapestry:parameter">
    <div t:type="zone" t:id="formZone" id="formZone">
        <t:form t:id="form" zone="formZone">
            <t:if test="hasValidationErrors"><t:errors/></t:if>
            <t:checkbox value="triggerWarning"/> Trigger Warning<br/>
            <t:delegate to="block:formBlock"/>
            <t:submit t:id="save" value="save"/>
        </t:form>
    </div>

    <div t:type="zone" t:id="formWarningZone" id="formWarningZone">
        <t:if test="hasWarnings">
            <t:form t:id="formWarning" zone="formWarningZone">
                <t:if test="hasValidationErrors"><t:errors/></t:if>
                <t:delegate to="activeWarningBlock"/>
            </t:form>
        </t:if>
    </div>

    <t:block t:id="warningBlock">
        Review Warnings<br/>
        <t:checkbox value="triggerValidation"/> Trigger Validation<br/>
        <t:checkbox value="triggerNotification"/> Trigger Notification<br/>
        <div style="display:none">
            <t:delegate to="block:formBlock"/>
        </div>
        <t:submit t:id="warningAccect" value="Accept Warning"
t:event="warningEvent"/>
    </t:block>

    <t:block t:id="notificationBlock">
        Review Notifications<br/>
        <t:checkbox value="triggerValidation"/> Trigger Validation<br/>
        <div style="display:none">
            <t:delegate to="block:formBlock"/>
        </div>
        <t:submit t:id="notificationAccept" value="Accept Notification"
t:event="notificationEvent"/>
    </t:block>

    <t:block t:id="formBlock">
        <div class="form-group">
            <t:Label class="control-label" for="computer"/>
            <t:TextField t:id="computer" value="computer.name"/>
        </div>
    </t:block>

</html>




On Mon, Mar 17, 2014 at 4:46 PM, Lance Java <la...@googlemail.com>wrote:

> > I believe Lance's #2 is only true for 5.4
> Yes, good point. George has mentioned previously that he's using 5.4 so
> should be OK.
>



-- 
George Christman
www.CarDaddy.com
P.O. Box 735
Johnstown, New York

Re: How to handle form warnings?

Posted by Lance Java <la...@googlemail.com>.
> I believe Lance's #2 is only true for 5.4
Yes, good point. George has mentioned previously that he's using 5.4 so
should be OK.

Re: How to handle form warnings?

Posted by Bob Harner <bo...@gmail.com>.
I believe Lance's #2 is only true for 5.4 (since
https://issues.apache.org/jira/browse/TAP5-1808)

On Mon, Mar 17, 2014 at 2:45 PM, Lance Java <la...@googlemail.com> wrote:
> 1. If you use a block you can use a delegate to render it in the 2
> scenarios.
>
> 2. Tapestry does not redirect after post for errors, it forwards instead.
> So anything you've done in your validate is available in your render.
>
>
> On 17 Mar 2014 18:35, "George Christman" <gc...@cardaddy.com> wrote:
>>
>> I see, so form 2 is essentially a replica of form 1 accept all the fields
>> are hidden? If that is the case, two final questions, 1 is there a simpler
>> way to setup all them fields? This is a time sheet with probably 50/75
>> fields. Lastly, when you return form 2, how do you return the object
>> without persisting or losing the values? Sorry lance, just trying to wrap
>> my head around a new approach and get out of the current rut.
>>
>>
>> On Mon, Mar 17, 2014 at 2:25 PM, Lance Java <lance.java@googlemail.com
>>wrote:
>>
>> > No :)
>> >
>> > Form1 contains the fields. Warnings cause form1's submit to FAIL.
>> >
>> > Form2 is displayed when showing the errors/warnings from form1. Form2
> has a
>> > hidden section with ALL of the fields (and values) from form1. Form2's
>> > submit button is likely to be labelled "accept". Clicking the "accept"
>> > button posts form2. The validation of form2 ignores warnings.
>> >  On 17 Mar 2014 18:03, "George Christman" <gc...@cardaddy.com>
> wrote:
>> >
>> > > I agree, I try to avoid it as much as I can. I'm not sure I understand
>> > what
>> > > you are doing, are you saying when form 2 is displayed and the submit
>> > > action is clicked, you would then resubmit form 1 along with form 2?
>> > >
>> > >
>> > > On Mon, Mar 17, 2014 at 1:49 PM, Lance Java <lance.java@googlemail.com
>> > > >wrote:
>> > >
>> > > > As always, I try to avoid persist. I was suggesting hidden (or
>> > disabled)
>> > > > fields in form2 so the values are passed in both submits (thus
>> > > eliminating
>> > > > the need for @Persist)
>> > > >
>> > > > Form2 is not displayed initially, it is displayed when showing the
>> > > warnings
>> > > >
>> > >
>> > >
>> > >
>> > > --
>> > > George Christman
>> > > www.CarDaddy.com
>> > > P.O. Box 735
>> > > Johnstown, New York
>> > >
>> >
>>
>>
>>
>> --
>> George Christman
>> www.CarDaddy.com
>> P.O. Box 735
>> Johnstown, New York

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: How to handle form warnings?

Posted by Lance Java <la...@googlemail.com>.
1. If you use a block you can use a delegate to render it in the 2
scenarios.

2. Tapestry does not redirect after post for errors, it forwards instead.
So anything you've done in your validate is available in your render.


On 17 Mar 2014 18:35, "George Christman" <gc...@cardaddy.com> wrote:
>
> I see, so form 2 is essentially a replica of form 1 accept all the fields
> are hidden? If that is the case, two final questions, 1 is there a simpler
> way to setup all them fields? This is a time sheet with probably 50/75
> fields. Lastly, when you return form 2, how do you return the object
> without persisting or losing the values? Sorry lance, just trying to wrap
> my head around a new approach and get out of the current rut.
>
>
> On Mon, Mar 17, 2014 at 2:25 PM, Lance Java <lance.java@googlemail.com
>wrote:
>
> > No :)
> >
> > Form1 contains the fields. Warnings cause form1's submit to FAIL.
> >
> > Form2 is displayed when showing the errors/warnings from form1. Form2
has a
> > hidden section with ALL of the fields (and values) from form1. Form2's
> > submit button is likely to be labelled "accept". Clicking the "accept"
> > button posts form2. The validation of form2 ignores warnings.
> >  On 17 Mar 2014 18:03, "George Christman" <gc...@cardaddy.com>
wrote:
> >
> > > I agree, I try to avoid it as much as I can. I'm not sure I understand
> > what
> > > you are doing, are you saying when form 2 is displayed and the submit
> > > action is clicked, you would then resubmit form 1 along with form 2?
> > >
> > >
> > > On Mon, Mar 17, 2014 at 1:49 PM, Lance Java <lance.java@googlemail.com
> > > >wrote:
> > >
> > > > As always, I try to avoid persist. I was suggesting hidden (or
> > disabled)
> > > > fields in form2 so the values are passed in both submits (thus
> > > eliminating
> > > > the need for @Persist)
> > > >
> > > > Form2 is not displayed initially, it is displayed when showing the
> > > warnings
> > > >
> > >
> > >
> > >
> > > --
> > > George Christman
> > > www.CarDaddy.com
> > > P.O. Box 735
> > > Johnstown, New York
> > >
> >
>
>
>
> --
> George Christman
> www.CarDaddy.com
> P.O. Box 735
> Johnstown, New York

Re: How to handle form warnings?

Posted by George Christman <gc...@cardaddy.com>.
I see, so form 2 is essentially a replica of form 1 accept all the fields
are hidden? If that is the case, two final questions, 1 is there a simpler
way to setup all them fields? This is a time sheet with probably 50/75
fields. Lastly, when you return form 2, how do you return the object
without persisting or losing the values? Sorry lance, just trying to wrap
my head around a new approach and get out of the current rut.


On Mon, Mar 17, 2014 at 2:25 PM, Lance Java <la...@googlemail.com>wrote:

> No :)
>
> Form1 contains the fields. Warnings cause form1's submit to FAIL.
>
> Form2 is displayed when showing the errors/warnings from form1. Form2 has a
> hidden section with ALL of the fields (and values) from form1. Form2's
> submit button is likely to be labelled "accept". Clicking the "accept"
> button posts form2. The validation of form2 ignores warnings.
>  On 17 Mar 2014 18:03, "George Christman" <gc...@cardaddy.com> wrote:
>
> > I agree, I try to avoid it as much as I can. I'm not sure I understand
> what
> > you are doing, are you saying when form 2 is displayed and the submit
> > action is clicked, you would then resubmit form 1 along with form 2?
> >
> >
> > On Mon, Mar 17, 2014 at 1:49 PM, Lance Java <lance.java@googlemail.com
> > >wrote:
> >
> > > As always, I try to avoid persist. I was suggesting hidden (or
> disabled)
> > > fields in form2 so the values are passed in both submits (thus
> > eliminating
> > > the need for @Persist)
> > >
> > > Form2 is not displayed initially, it is displayed when showing the
> > warnings
> > >
> >
> >
> >
> > --
> > George Christman
> > www.CarDaddy.com
> > P.O. Box 735
> > Johnstown, New York
> >
>



-- 
George Christman
www.CarDaddy.com
P.O. Box 735
Johnstown, New York

Re: How to handle form warnings?

Posted by Lance Java <la...@googlemail.com>.
No :)

Form1 contains the fields. Warnings cause form1's submit to FAIL.

Form2 is displayed when showing the errors/warnings from form1. Form2 has a
hidden section with ALL of the fields (and values) from form1. Form2's
submit button is likely to be labelled "accept". Clicking the "accept"
button posts form2. The validation of form2 ignores warnings.
 On 17 Mar 2014 18:03, "George Christman" <gc...@cardaddy.com> wrote:

> I agree, I try to avoid it as much as I can. I'm not sure I understand what
> you are doing, are you saying when form 2 is displayed and the submit
> action is clicked, you would then resubmit form 1 along with form 2?
>
>
> On Mon, Mar 17, 2014 at 1:49 PM, Lance Java <lance.java@googlemail.com
> >wrote:
>
> > As always, I try to avoid persist. I was suggesting hidden (or disabled)
> > fields in form2 so the values are passed in both submits (thus
> eliminating
> > the need for @Persist)
> >
> > Form2 is not displayed initially, it is displayed when showing the
> warnings
> >
>
>
>
> --
> George Christman
> www.CarDaddy.com
> P.O. Box 735
> Johnstown, New York
>

Re: How to handle form warnings?

Posted by George Christman <gc...@cardaddy.com>.
I agree, I try to avoid it as much as I can. I'm not sure I understand what
you are doing, are you saying when form 2 is displayed and the submit
action is clicked, you would then resubmit form 1 along with form 2?


On Mon, Mar 17, 2014 at 1:49 PM, Lance Java <la...@googlemail.com>wrote:

> As always, I try to avoid persist. I was suggesting hidden (or disabled)
> fields in form2 so the values are passed in both submits (thus eliminating
> the need for @Persist)
>
> Form2 is not displayed initially, it is displayed when showing the warnings
>



-- 
George Christman
www.CarDaddy.com
P.O. Box 735
Johnstown, New York

Re: How to handle form warnings?

Posted by Lance Java <la...@googlemail.com>.
As always, I try to avoid persist. I was suggesting hidden (or disabled)
fields in form2 so the values are passed in both submits (thus eliminating
the need for @Persist)

Form2 is not displayed initially, it is displayed when showing the warnings

Re: How to handle form warnings?

Posted by George Christman <gc...@cardaddy.com>.
If I'm understanding you correctly, that is exactly how I'm doing it. I'm
using two forms inside a single zone. If warnings exist when form 1 is
submitted, I persist the timesheet object and show form 2 in a modal box.
When form 2 is submitted assuming no errors, I'm returning the onSuccess
method of form 1 and from the form 2's onSuccess method. I'm then setting
the timesheet object with the previously persisted object followed by a
save. Would you persist the object before showing form 2?

I could be wrong, but I'm getting my new timesheet object / existing
timesheet object with onActivate. onActivate is called by both forms and
I'm wondering if that might be the cause of my "a different object with the
same identifier value was already associated
with the session" error.


On Mon, Mar 17, 2014 at 12:19 PM, Lance Java <la...@googlemail.com>wrote:

> Have you considered having 2 forms?
> If form1 succeeds without warnings, the save happens
>
> If form1 submits with warnings, form2 is shown (fields are hidden /
> disabled). Form2 does not check for warnings when it is saved.
>



-- 
George Christman
www.CarDaddy.com
P.O. Box 735
Johnstown, New York

Re: How to handle form warnings?

Posted by Lance Java <la...@googlemail.com>.
Have you considered having 2 forms?
If form1 succeeds without warnings, the save happens

If form1 submits with warnings, form2 is shown (fields are hidden /
disabled). Form2 does not check for warnings when it is saved.