Hi Tapestry committers/experts (in particular)

I while back I posted that I had found a classloader issue within one of my services when casting a Zone to a Zone.

I realise that what I'm trying to do isn't quite the 'tapestry recommended approach', but since some of my pages update many zones, it is a chore and a mess to inject all of them.

So what I have come up with is a helper service which locates arbirary tapestry components based on their component id and then calls ajaxResponseRenderer.addRender for me.

I know it's not for everyone, but it means instead of:

@InjectComponent
private Zone zoneOne;
@InjectComponent
private Zone zoneTwo;
@InjectComponent
private Zone zoneThree;
@Inject
private AjaxResponseRenderer ajaxResponseRenderer;

void onHandleSomething()
{
    ajaxResponseRenderer.addRender(zoneOne);
    ajaxResponseRenderer.addRender(zoneTwo);
    ajaxResponseRenderer.addRender(zoneThree);
}

can be simplified to

@Inject
private AjaxHelper ajaxHelper;

void onHandleSomething()
{
    ajaxHelper.addRender(this, "zoneOne");
    ajaxHelper.addRender(this, "zoneTwo");
    ajaxHelper.addRender(this, "zoneThree");
}

In very complex pages (such as in my project) this becomes convenient.

I originally came up with this approach in tapestry 5.1.0.x when there wasn't an ajaxResponseRenderer, instead the ugly MultiZoneUpdate so I have adapted my old approach to the new architecture (which by the way is MUCH nicer!).

The implementation of AjaxHelper is:

public class AjaxHelperImpl implements AjaxHelper
{
    @Inject
    private AjaxResponseRenderer ajaxResponseRenderer;

    @Override
    public void addZoneUpdate(Object container, String zoneId)
    {
        // idealImplementation(container, zoneId);
        workaroundImplementation(container, zoneId);
    }

    private void idealImplementation(Object container, String zoneId)
    {
        Zone zone = (Zone) getEmbeddedComponent(container, zoneId);
        ajaxResponseRenderer.addRender(zone);
    }

    private void workaroundImplementation(Object container, String zoneId)
    {
        Component zone = getEmbeddedComponent(container, zoneId);
        Object body = ReflectionUtils.invokeMethod(zone, "getBody");
        ajaxResponseRenderer.addRender(zoneId, body);
    }

private Component getEmbeddedComponent(Object container, String componentId)
    {
        Component containerComponent = (Component) container;
return containerComponent.getComponentResources().getEmbeddedComponent(componentId);
    }
}

Please take note of the method "idealImplementation". This is how I expected to be able to implement the functionality, however a ClassCastException is thrown casting the Component to a Zone. The object being cast is definitely a zone but it turns out that there is a classloader conflict in that the Zone of the returned object seems to come from the Plastic classloader, while the type I'm trying to cast it to comes from the standard classloader.

The only way I have found to workaround this situation is to avoid the cast altogether, which involves using reflection.

Is this expected behaviour?

Thanks, Paul.

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

Reply via email to