Mixing URIHandler & ParametersHandler - or accessing HttpRequest

Hello there !

I’ve got another question :slight_smile:

In one of my projects, I use a custom widget which (more or less) retreive a map from the server, and allow the user to interact with it (doing zoom, pans, etc.)

Getting the image is easy: I use an URIHandler and send back a DownloadStream filled with the byte array of my map.
But when I want my user to interact with the map, I am in trouble. I have to pass GET parameters to the servlet, and to be able to process them
before
sending back the image.

In other words, I would like to be able to contact my server an URL something like
http://server/application/GetMap?cmd=zoom&factor=1.5
, so that I can get the user command, process it, and then send back the zoomed map.

So, what I need server side is either a handler giving me at the same time the relative URI & the parameters Map, or even access to the HttpRequest object itself.

Is that in any way possible ?

Quentin.

Erf, never mind that topic…

The only thing is that there is an error in the documentation :stuck_out_tongue:

"The parameter handler is not called if there are no parameters. Parameter handler is called after the URI handler. "
http://itmill.com/documentation/itmill-toolkit-5-reference-manual/ch09s02.html

But in fact, the parameter handler is called
before
the URI handler (and it is much more logical that way !), as I found out while reading the service() method in the ApplicationServlet class :slight_smile:

So I’m able to process my parameters before sending back my image, so I’m happy ^^

Quentin.

Hehe, this is starting to work wonderfully for us, you’re already solving these problems on your own :slight_smile:

Thanks for the heads-up on the documentation error, we’ll be fixing that asap.

-Jouni

:slight_smile:

Anyway, some way to access the HttpServlet object would be a neat feature, in a future version… It is sometimes usefull to be able to manipulate the low level objects :slight_smile:

Quentin.

You can access HttpServletRequest. Add TransactionListener to your Application. transactionData parameter can be casted to javax.servlet.http.HttpServletRequest


public void transactionStart(Application application, Object transactionData) {
   HttpServletRequest request = (HttpServletRequest) transactionData;
   HttpSession sess = request.getSession();
   ...
}

Yes, the documentation seems to be wrong currently. Will fix and add some examples.

The order actually changed during the spring at some point, as the new order is, as you say, more logical.

Mauno > Oh great ! I didn’t knew that :slight_smile: Thank you very much !

Quentin.

Below is an example (possibly for the manual) for using both parameter and URI handlers to create dynamic content.


package com.itmill.toolkit.tests.book;

import java.awt.Color;

public class MyDynamicResource implements URIHandler, ParameterHandler {
    String                textToDisplay = "- no text given -";
    ByteArrayOutputStream imagebuffer   = null;

    /**
     * Handle the URL parameters and store them for the URI handler to use.
     */
    public void handleParameters(Map parameters) {
        // Get and store the passed HTTP parameter.
        if (parameters.containsKey("text"))
            textToDisplay = ((String[])parameters.get("text"))[0]
; 
    }

    /**
     * Provides the dynamic resource if the URI matches the resource URI. The
     * matching URI is "/myresource" under the application URI context.
     * 
     * Returns null if the URI does not match. Otherwise returns a download
     * stream that contains the response from the server.
     */
    public DownloadStream handleURI(URL context, String relativeUri) {
        // Catch the given URI that identifies the resource, otherwise let other
        // URI handlers or the Application to handle the response.
        if (!relativeUri.startsWith("myresource"))
            return null;
        
        // Create an image and draw some background on it.
        BufferedImage image = new BufferedImage (200, 200, BufferedImage.TYPE_INT_RGB);
        Graphics drawable = image.getGraphics();
        drawable.setColor(Color.lightGray);
        drawable.fillRect(0,0,200,200);
        drawable.setColor(Color.yellow);
        drawable.fillOval(25,25,150,150);
        drawable.setColor(Color.blue);
        drawable.drawRect(0,0,199,199);
        
        // Use the parameter to create dynamic content.
        drawable.setColor(Color.black);
        drawable.drawString("Text: "+textToDisplay, 75, 100);

        try {
            // Write the image to a buffer.
            imagebuffer = new ByteArrayOutputStream();
            ImageIO.write(image, "png", imagebuffer);

            // Return a stream from the buffer.
            ByteArrayInputStream istream = new ByteArrayInputStream(imagebuffer.toByteArray());
            return new DownloadStream (istream,null,null);
        } catch (IOException e) {
            return null;
        }
    }
}

When you use the class in an application, you must (obviously) share the same handler object with both handlers:


MyDynamicResource myresource = new MyDynamicResource();
mainWindow.addParameterHandler(myresource);
mainWindow.addURIHandler(myresource);

Calling
http://localhost:8080/tk5/book/myresource?text=Hello
produces:

.