On May 4, 2006, at 12:52 PM, Apache wrote:

Hi there,

I have to dynamically create image based on some data stored in user session. And the question is: how can I do it with Tapestry 4.0? I've tried to find some answers by searching previous posts but all I find is either Tapestry3-based or I can't see how can I properly access some persistent (stored in the session) attributes...

One way is to create an Asset and a EngineService. This allows you to put a link in the html with parameters that can call back into your page which then streams out the image data (as jpeg, gif, bmp, or what have you). That is what Howard suggested to me. Its much easier to do in Tapestry 4.

Basically I have 2 classes and an interface. The following is the important parts of the classes, if you need more details, let me know and I will send you the files. This implementation if for Tapestry 4. It is similar in Tapestry 3 but there is more plumbing one needs to do. You can see an implementation of a service in the Tapestry example Workbench in the Chart package.

class ImageAsset implements IAsset {
public ImageAsset(IEngineService aImageService, ImageProvider aImageProvider, Object [] aParameters) {
        imageService = aImageService;
        imageProvider = aImageProvider;
        parameters = aParameters;
    }
...
   public String buildURL() {
        ILink link = imageService.getLink(false, this);
        return link.getURL();
    }
...
public static void getImageData(BufferedImage image, WebResponse response) throws IOException {
...
   }
}


class ImageService implements IEngineService {
...
   public void service(IRequestCycle cycle) throws IOException {

        String pageName = cycle.getParameter(ServiceConstants.PAGE);
        String idPath = cycle.getParameter(ServiceConstants.COMPONENT);
        IPage page = cycle.getPage(pageName);
        IComponent component = page.getNestedComponent(idPath);

        try {

((ImageProvider) component).generateImage(response, linkFactory.extractListenerParameters(cycle));
        }
        catch (ClassCastException ex) {
            exceptionReporter.reportRequestException(
"Component " + component.getExtendedId() + " does not implement ImageProvider.",
                    ex);
        }
        catch (Throwable ex) {
exceptionReporter.reportRequestException("Error creating Image stream.", ex);
        }

    }

    public ILink getLink(boolean post, Object parameter) {

        Defense.isAssignable(parameter, ImageAsset.class, "parameter");
        ImageAsset imageAsset = (ImageAsset) parameter;
        IComponent component = imageAsset.getComponent();

        Map<String, Object> parameters = new HashMap<String, Object>();

        parameters.put(ServiceConstants.SERVICE, getName());
parameters.put(ServiceConstants.PAGE, component.getPage ().getPageName()); parameters.put(ServiceConstants.COMPONENT, component.getIdPath()); parameters.put(ServiceConstants.PARAMETER, imageAsset.getImageParameters());

return linkFactory.constructLink(this, false, parameters, true);
    }

}

interface ImageProvider {
void generateImage(WebResponse response, Object[] parameters) throws Exception;
}


The ImageAsset class is used by the page to provide a link on the HTML like <img jwcid="@Image" image="ognl:workflowImageAsset" title="Workflow" alt="Workflow" />


The page implements ImageProvider and provides the ImageAsset like so:

    @InjectObject("service:App.Image")
    public abstract IEngineService getImageService();

    public IAsset getWorkflowImageAsset() {
return new ImageAsset(getImageService(), this, new Object[] {getEvents()});
    }

public void generateImage(WebResponse response, Object[] parameters) throws Exception {
        List bmEvents = (List) parameters[0];
        try {
            BMWorkflow workflow = BMWorkflow.createWorkflow(bmEvents);
            BufferedImage image = workflow.createImage(1000, 200);
            ImageAsset.getImageData( image, response);
        } catch (QueryException e) {
            recordError(e);
        }
    }

And in the hivemodule.xml one puts the service definition

<service-point id="Image" interface="org.apache.tapestry.engine.IEngineService">
        <invoke-factory>
            <construct class="image.ImageService">
<set-object property="exceptionReporter" value="infrastructure:requestExceptionReporter"/> <set-object property="response" value="infrastructure:response"/> <set-object property="linkFactory" value="infrastructure:linkFactory"/>
            </construct>
        </invoke-factory>
    </service-point>

Hope this helps you on your way.

---
Erik Husby
Senior Software Engineer
Broad Institute of MIT and Harvard
Rm. 2192, 320 Charles St, Cambridge, MA 02141-2023
mobile: 781.354.6669, office: 617.258.9227
email: [EMAIL PROTECTED] AIM: ErikAtBroad

Reply via email to