Thursday, April 16, 2015

Re: RequestFactory proxies stuck in RequestContext edit context


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?


On Saturday, August 13, 2011 at 4:47:05 PM UTC+3, Jesse Hutton wrote:
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

--
You received this message because you are subscribed to the Google Groups "Google Web Toolkit" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-web-toolkit+unsubscribe@googlegroups.com.
To post to this group, send email to google-web-toolkit@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment