RequestFactory proxies stuck in RequestContext edit context

253 views
Skip to first unread message

Jesse Hutton

unread,
Aug 13, 2011, 9:47:05 AM8/13/11
to google-we...@googlegroups.com
I have a entity proxy A that contains a collection of relations (List<B>), which corresponds to a standard @OneToMany association in JPA. My edit view of proxy A contains a HasDataEditor<B> implementation managing the list of associations. The form also allows an arbitrary number of new B proxies to be added as relations. When adding a new B, I have a popup form that implements Editor<B>, which I use to edit the properties of the new instance. When that form is confirmed, I flush its editor driver, and add the proxy instance to the HasDataEditor<B> list in the main form. In this way, new B instances are only created on the server when A is persisted and the object graph is sent along with the request. In order for this to work, I have to use the RequestContext that is managing edits of A when I create new B proxy instances. And it works great if the B instances I instantiate can always be submitted in a valid state.

The problem I'm having is that once I create a new proxy B in the RequestContext managing A, I can't seem to remove it. For example, if I click the "Create new B" button and then close the popup form immediately, the new proxy created for adding the aborted B is stuck in the RequestContext. Even though B is never added to the HasDataEditor<B> element in the form for A, it will be submitted as part of the set of objects being edited by the RequestContext. This can lead to a state where the form for A cannot be submitted due to validation errors from lingering (ostensibly discarded) B instances.

What would work for me is a way to remove proxies from a RequestContext's map of editedProxies. I was also thinking that using RequestContext appending instead of editing everything in the same context might be a work around... Does anyone know of another way to work around this issue?

Jesse

Alex opn

unread,
Jun 20, 2012, 11:54:53 AM6/20/12
to google-we...@googlegroups.com
I know it's a pretty old thread but I just stumbled upon http://code.google.com/p/google-web-toolkit/issues/detail?id=6685 in my code. Are there any news about a patch for this or other suggestions how to work around this except the ones in the bug report? I just began to really love the editor framework in combination with RF but then I discovered this nasty bug which imo is a pretty big problem : /

Thomas Broyer

unread,
Jun 20, 2012, 12:05:46 PM6/20/12
to google-we...@googlegroups.com


On Wednesday, June 20, 2012 5:54:53 PM UTC+2, Alex opn wrote:
I know it's a pretty old thread but I just stumbled upon http://code.google.com/p/google-web-toolkit/issues/detail?id=6685 in my code. Are there any news about a patch for this or other suggestions how to work around this except the ones in the bug report?

The idea is to avoid sending to the server those proxies that you no longer use, instead of removing them from the RequestContext.
The ability to remove proxies from a given RequestContext would probably be needed in other cases, but as I said on the issue tracker, this is not as easy as it sounds.

Alex opn

unread,
Jun 20, 2012, 12:37:36 PM6/20/12
to google-we...@googlegroups.com
Alright, thanks for the update on this! I think then I'll have to live with that one for the moment, because I don't feel like I could fix this myself somehow.

Anton Mityagin

unread,
Apr 16, 2015, 2:24:02 PM4/16/15
to google-we...@googlegroups.com, jesse....@gmail.com

I think I've found a workaround.

A key of it is to ignore validation after entity was deleted in another context.
To do that you need implement some interface in proxies which can be deleted.
something like:
public interface IgnoreValidator
{
    boolean isIgnore();
    
    void setIgnore(boolean ignore);
}

and after delete operation set to all unfrozen beans setIgnore(true)
something like this:

void delete(final List<ENTITY> list)
{
    List<ENTITY> toDelete = new ArrayList<>();
    for(ENTITY entity : list)
    {
        if (entity.wasSaved()) 
        {
            // send to server only saved entities
            // no need to delete unsaved
            toDelete.add(entity);
        }
    }

    RequestContext request = getNewRequestContext();

    request.delete(toDelete).fire(new Receiver<Void>()
    {
        @Override
        public void onSuccess(Void response)
        {
            // set ignore validation to all unfrozen beans
            for(ENTITY e : list)
            {
                if (e instanceof IgnoreValidator)
                {
                    AutoBean<ENTITY> bean = AutoBeanUtils.getAutoBean(e);
                    if (!bean.isFrozen())
                    {
                        ((IgnoreValidator)e).setIgnore(true);
                    }
                }
            }
        }
    });
}

Also you need to replace default validator by your validator.
Just create 3 classes:

ValidationProvider:
MyValidationProvider which extends HibernateValidator

ValidatorFactory:

ValidatorFactoryDecorator implements ValidatorFactory

Validator:
ValidatorDecorator implements Validator

Your MyValidationProvider must create your ValidatorFactoryDecorator which accepts super.buildValidatorFactory(configurationState) as delegate.

Your ValidatorFactoryDecorator must return ValidatorDecorator which accepts delegate.getValidator() as delegate.

Your validator must decorate default validator and dispatch all method calls to default validator expect method validate.
this method may be implemented something like this:
 
@Override
public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups)
{
    if (object instanceof IgnoreValidator)
    {
        IgnoreValidator deletable = (IgnoreValidator)object;
        if (deletable.isIgnore())
        {
            return Collections.emptySet();
        }
    }

    return delegate.validate(object, groups);
}
thus you will not perform validation those objects that do not need to be validated

do not forget add 
META-INF/validation.xml
and
META-INF/services/javax.validation.spi.ValidationProvider

META-INF must be in
ROOT
|_META-INF -- don't put validation.xml here
|_WEB-INF
    |__ classes
           |_META-INF
                |__validation.xml

in META-INF/services/javax.validation.spi.ValidationProvider just add one line - full name of your MyValidationProvider 


After you had implemented this.
You will be able to edit proxy A and proxies B in one RequestContext.
and safety delete proxies B in another RequestContext.
After you had fired delete request your B proxies will be marked to ignore validation.
and you can fire save request for A proxy.

I've checked this workaround.
It's seems worked.

Can someone can point any invisible problems of this solution?
Reply all
Reply to author
Forward
0 new messages