Problems using handleURI

Hi

First of all things, thank you very much for all your work with ITMill - a truly superb framework, alas not known enough.

Anyway.
I have some troubles using handleURI.

In my application, I have a GWT widget embedding a map, based on OpenLayers. When I click on my map, for example to select a feature on a layer, I’ve got a Javascript function sending and receiving informations from a distant server.
I want to transmit those informations (contained in a javascript variable) to my server.

After reading the doc, I tried to add an URIHandler to my main window.
My Javascript function make an Ajax call to my application.

On my handling function, I am able to retrieve my JS variable without any problem.
Trouble is… I can do nothing with it.
I would like to display that information processed by my server in a Label that I would add in my main window.

My functions are called, I can trace them using the standard output… but nothing happen in my application :frowning:

What am I doing wrong ?

Excerpt from my source code:

public class MainApplication extends Application {
    private Window main;

    public void init() {
        main = new Window("OpenLayer Integration Test");
        setMainWindow(main);
        final MainPanel mainPanel = new MainPanel();
[...]

        main.addURIHandler(this);

        main.addComponent(mainPanel);
    }

    public DownloadStream handleURI(URL url, String context) {
        main.showNotification("Handle URI: " + context); // I have a notification on the first call, when the window is initialized, but nothing after
        System.out.println("Context: " + context); // When my JS function fire, this do write a trace in my default log output
[...]

    }
}

I am using ITMill Toolkit 5, the last public release as far as I can tell.

Thank you very much for your help :slight_smile:

Quentin.

After watching my HTTP trafic, when I send my request using an Ajax POST, I get an HTML response.
I do not know why, nor if it can help…

Received response:[code]

IT Mill Toolkit 5
[/code]Maybe it is because the JS function firing the call is located in my GWT widget embedding my map ?

I really do not have any clue of what is happening :frowning:

Quentin.

[quote=QuentinAstegiano]
Hi

First of all things, thank you very much for all your work with ITMill - a truly superb framework, alas not known enough.
[/quote] Thanks. We try to do our best to make it known better. Feel free to recommend it to others.

[quote]
I want to transmit those informations (contained in a javascript variable) to my server.
[/quote]Ok. One way to do that is to create a new client-side widget to do client-server communications, but I suppose sending it directly from your JavaScript and using the URIHandler at server-side, as you have tried to do, should also work. Making a custom GWT widget is perhaps a bit heavy task compared to the alternative way. I’m not exactly sure what obstacles you might have there though.

[quote]
After watching my HTTP trafic, when I send my request using an Ajax POST, I get an HTML response.
[/quote]It looks like the response contains the usual initial page. My first quess is the way how the server side tracks the sessions using cookies. The direct JavaScript post might not include all the information needed for tracking the session. I’ll have to check how that works.

Ok, there’s one huge problem in passing the variable with a custom Ajax call that bypasses the Toolkit’s Ajax communications. You might be able to pass the variable value to the server using handleURI, but that doesn’t really do anything, because the server response would not update the client-side so you could not have any UI feedback from the call.

So, I recommend doing the client-server communication in the standard way by implementing a GWT widget and a server-side component to pass the variable to the server. The ColorPicker demo provides a really simple example of passing one variable to the server. It should be well documented in the manual. Since you already have a GWT widget, you can probably do the communications easiest by inheriting it, as is done in ColorPicker.

Thank you for your response :slight_smile:

Before reading it, I did a few more tests, and weird things happened.

The only thing I added was… A button. Doing nothing related to my functions.

When I fire my JS Ajax call, the “server side” function are correctly called; I can see trace in my log. But nothing happen “client side”, even though, well, it should and it say it does.
But when I click on my not-related-button, the missing events happens all at once client side ?!

It look like everything is ok, and the only problem is that the client state is not refreshed after my call. Can I force the client to “refresh” himself ?
I tried to add call to “main.requestRefresh()”, but it changed nothing (and I’m not really sure of what this function is doing ^^).
Considering your last response, and as you said, the server response does not update the client side, I guess the answer is “no”, but, eh, I prefer be sure :slight_smile:

New version of my code:


public class MainApplication extends Application {

    private Window main;

    public void init() {
        main = new Window("OpenLayer Integration Test");
        main.addURIHandler(this);
        setMainWindow(main);
        final MainPanel mainPanel = new MainPanel();

        final Button button = new Button("Any news ?");
        final Label label = new Label();
        button.addListener(new Button.ClickListener() {

            public void buttonClick(Button.ClickEvent arg0) {
                label.setCaption("There is news"); // Right after this event happen, my handleURI notification happen client side !
            }
        });

        main.addComponent(mainPanel);
        main.addComponent(label);
        main.addComponent(button);
    }

    public DownloadStream handleURI(URL url, String context) {
        main.showNotification("Handle URI: " + context);
[...]

    }
}

I will try to use the GWT widget, but it may be a bit tricky in my case.
The JS function making the Ajax call is a callback function, called in response to an event depending on another server… Integrating that with GWT may be, err, quite though ^^

Thank you again for your time :slight_smile:

Quentin.

That is exactly what I expect would happen. All UI updates to the client-side are transmitted in the
response
to an Ajax request made by the client-side engine of the Toolkit. If you make an Ajax call from your own JavaScript and handle it with handleURI(), you can change the server state, but the UI is updated only after you have a regular Ajax request by the client-side engine.

If you are using Firebug or something similar, you can see what happens normally. When you click a button, the client-side engine makes an Ajax request to the server with the button event. The response contains all the UI changes caused by the event. To have effect, the client-side must handle that response. That’s really what the purpose of the client-side engine is.

Well, yes, by making the client-side engine make an empty request to the server, but that would be making two server requests for one event, which does not really make sense.

requestRefresh()? Normally, when you click a button managed by the client-side engine, it uses the ApplicationConnection object to communicate with the server. Clicking on the button queues a status variable change to the object and sendPendingVariableChanges() sends the queued variables in a XmlHttpRequest. …and gets any UI changes in the response.

Yes, that can not work. The notification would not be shown in the browser, because it is not communicated to the client-side in the custom Ajax request that you make.

It should be possible to integrate IT Mill Toolkit with any JavaScript code in the client-side. I’ll have to look how to do that. But in any case, the proper way to do it is through the client-side framework.

Making a custom GWT widget with custom JavaScript is documented in http://code.google.com/webtoolkit/documentation/com.google.gwt.doc.DeveloperGuide.UserInterface.html#CreatingCustomWidgets , though the documentation there is not very good.

Well ok, if you want to go with the easy but dirty way, you could have the client-side engine of IT Mill Toolkit poll the server periodically. While the UI changes are not updated in the handleURI() call, they will be when you poll the server. That should make your program work right away.

Currently the easiest way to do polling is use ProgressIndicator. You can make the component invisible with a single CSS line. See Forum article http://forum.itmill.com/posts/list/345.page for info for using the ProgressIndicator. I wrote about it in the Manual as well, but it’s not in the web site yet.

Anyhow, I’ll have to examine the issue further at some point and write something about integration with JavaScript in the Manual. You need to make a custom GWT widget that provides an interface to JavaScript. I think it’s done as a JNI interface. It’s also possible that we could write a generic API that a JavaScript program could use.

The problem is as Marko describes it:

1.1. custom javascript sends update to server
1.2. server reacts, updates (serverside) ui
1.3. but the updates are not drawn on the client, since the custom javascript does not know how to do that
2.1. pressing the button causes the (itmill/gwt) client to send a button click event to the server
2.2. the server reacts and updates the ui
2.3. the server returns UI changes, including the ones caused earlier by the custom javascript call to the (itmill/gwt) client, which updates the clientside ui

There are several ways to tackle this problem, including Markos ProgressIndicator suggestion. Making a new component would be the most robust and “proper” way.

We’re definitely going to improve js<->gwt<->toolkit integration, making it easier to communicate with ‘custom’ javascript (i.e. javascript API).
An easy improvement that would allow you to get this ‘simple’ case working would be to publish some sort of refreshFromServer() -method that you could call from javascript.

Best regards,
Marc

Quentin,

I implemented a forceSync() function that should solve your problem; the client exposes this function to javascript, so you can call it to synchronize the client with the server.

In practice:
after your JS Ajax call returns, call itmill.forceSync()

itmill.forceSync();

This function should be available in the next nightly build, and the FeatureBrowser will contain a minimal example as well.

Best regards,
Marc

Wow !
You rocks :slight_smile:

Thank you very much for the time you put into helping me.

I’m currently making test using a GWT widget, but this is, well… quite complicated.

I’ll test your solution as soon as possible.

Thank you again !

Quentin.

Err…

You’re going to hate me :slight_smile:

I’ve downloaded the nightly build (itmill-toolkit-5.0.0_trunk_20080118.jar, right ?). But I’ve got a bug with it :frowning:

There seems to be a problem with the communications between the client & the server.
After having some bugs, I’ve set up a simple test:

[code]
public class MainApplication extends Application {

private Window main;

public void init() {
    main = new Window("OpenLayer Integration Test");
    setMainWindow(main);
    
    Button button = new Button("test");
    button.addListener( new Button.ClickListener() {

        public void buttonClick(Button.ClickEvent arg0) {
            main.showNotification("Test");
            System.out.println("Test");
        }
    });
    main.addComponent(button);
    
}

}
[/code]When I click the button, I’ve got the following exception:

java.lang.ArrayIndexOutOfBoundsException: 1
        at com.itmill.toolkit.terminal.gwt.server.CommunicationManager.handleVariables(CommunicationManager.java:487)
        at com.itmill.toolkit.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:274)
        at com.itmill.toolkit.terminal.gwt.server.ApplicationServlet.service(ApplicationServlet.java:394)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:196)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:263)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:584)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
        at java.lang.Thread.run(Thread.java:619)

I’ve cleaned my installations and rebuilt default & personal widgets. No problem occurs during the build, the app launch without problems, my panels & widgets appears. The problem only occurs when the client send an event to the server, it seems.

Am I doing something wrong here ?

Sorry to bother you like that, and thank you for your help :slight_smile:

Quentin.

EDIT Some more details:

  • From Firebug, request POST parameters:
changes=PID28_state_btrue
  • Headers:

[code]
Response Headers

Server Apache-Coyote/1.1
Content-Length 1884
Date Mon, 21 Jan 2008 10:22:14 GMT

Request Headers

Host localhost:8084
User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071231 Firefox/2.0.0.11 Flock/1.0.5
Accept text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,/;q=0.5
Accept-Language en-us,en;q=0.7,fr;q=0.3
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 300
Connection keep-alive
Content-Type application/x-www-form-urlencoded; charset=utf-8
Referer http://localhost:8084/OpenLayerITMill/ITMILL/widgetsets/com.masa.openlayers.itmill.widgets.map.MapWidgetSet/8D8F9B3DE12FDC36DAF65358A95990F6.cache.html
Content-Length 26
Cookie JSESSIONID=5498B0B6F275862EA3D5FF582F23683C
Pragma no-cache
Cache-Control no-cache
[/code]I’m not sure to understand why the response header refer to “com.masa.openlayers.itmill.widgets.map.MapWidgetSet” as this button do not, in any way, refer to this widget…

Hmm…

I could not reproduce this (quickly anyway), but I’m guessing: the application seems to be using your custom WidgetSet (“com.masa.openlayers.itmill.widgets.map.MapWidgetSet”) which is probably not compiled after the IT Mill Toolkit update (OR something is cached too well). If my guess is correct, you’re using an old client with a new server - try recompiling your “MapWidgetSet” and see if that helps.

(A new version will very seldom cause this kind of problem, but some variable naming changes in the current nightly might actually break communication with an old client in the way you describe.)

And, don’t worry, we won’t hate you - we know some of these problems are hard to figure out without in-depth knowledge of how the Toolkit works. You’re helping to get that knowledge on to this forum :slight_smile:

Hope this helps!
//Marc

\o/ It’s working :slight_smile:

You where totally right.
My widget was not rebuilt with the right library (a reference to the previous jar I stupidly missed in my ant build file), and thus didn’t worked.

Now, everything seems to be working smoothly.

Thank you very much for your help :slight_smile:

Quentin.

Err…

Ok, I’ve got something working, and hit a wall two minutes after.

So.
I can retrieve my URL calls, no prob. I’m sync with the client, no prob.
Trouble is… I want to use that request to send parameters to the server - kinda huge parameters, forcing me to use POST request.

But in my handleURI function, the only thing I have is the requested URL, and not the request - and so my POST parameters are kinda lost in space somewhere.

Any thought on an easy way for me to get them ? Using GET is a no-no, as the parameters may be quite a big chunk of data (retrieved from another server, but that is another story ^^).

Quentin.

EDIT: Hmmm ok. After some research to understand what handleURI was REALLY doing, I finally understood that even GET parameters are not accessible at this point.
Is there any way to access the original request object ?

You can implement a ParameterHandler (http://toolkit.itmill.com/demo/doc/api/com/itmill/toolkit/terminal/ParameterHandler.html) instead of the URI handler. You instantiate the handler and add it to the main window with addParameterHandler().

Notice that the parameter handler is for a window, not the application. See WebContent/WEB-INF/src/com/itmill/toolkit/demo/Parameters.java in the Toolkit installation package.

If you want to use some other URL but the base URL for the application to send the request, you have to handle it a bit differently. There’s no combined URIhandler and parameter handler. The URIhandler is, however, always called before the parameter handler, so you could store the URI in the URIhandler and use it in the parameter handler. Another way is to create another Window object that has a particular URL (use setName()). So, if your base URL is http://localhost:8080/myproject/myapp/, and create a new window with setName(“foobar”), the window URL should be http://localhost:8080/myproject/myapp/foobar/ .

Thank you once again, you solved my problems :slight_smile:

Sorry for the time it took, but, well, now it work, I can pass data from my client to my ITMill app and request a resync after the data is processed, it’s very nice :slight_smile:

Quentin.

Hi Quentin,

Is there a document to follow for the integration with OpenLayer?

Regards,

Rachmat