Widget Help - explicit call to Java from Javascript through custom widget

Hi everyone-

We’re in the early stages of developing a custom widget. We’re trying have a link in an external js lib explicitly call a java method that can end up in the server side of the widget and open a window or similar activity…

We can get into the client side of the widget from the javascript, but once there, how do we get the server side of the widget to do something? See example below


In our VSomeWidget.java…

public String displayWindow() {
  // How do we get from here to the server side of the widget to do something?
  return "SUCCESS";
}
   
public native void exportJS() /*-{
$wnd.displayWindow = this.@com.example.widgetmaster.client.ui.VSomeWidget::displayWindow();
}-*/;

Thank you for any assistance, examples or other information you can offer.

Dave

You will need two things to communicate the action to the server. The unique identifier on the client side of the component and a reference to the ApplicationConnection. You get them both from the updateFromUIDL() method. Here is an example.

In VSomeWidget.java…

private ApplicationConnection client;
private String PID;

public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
     this.client = client;
     this.PID = uidl.getId();
}

public String displayWindow() {

  // Calls server with the variable "open-window"
  client.updateVariable(PID, "open-window", true, true);
  return "SUCCESS";
}
   
public native void exportJS() /*-{
$wnd.displayWindow = this.@com.example.widgetmaster.client.ui.VSomeWidget::displayWindow();
}-*/;


In SomeWidget.java…

public void changeVariables(Object source, Map<String, Object> variables) {
	super.changeVariables(source, variables);
		
        // Handle the open window action
        if(variables.containsKey("open-window")){
           // Do open window stuff here...
        }
}

Hi John-
Thank you so much for taking the time with your code. Following your example, this compiled fine, but we’re getting a JS error:

I can return a value into my custom js using whereAreWe() if I return the string, but the update seems to fail. Similar code in onClick (from the Eclipse widget template) worked properly.

From VJamal.java

...
public void whereAreWe() {
    	 client.updateVariable(paintableId, "open-window", true, true);        
     }
     
public native void exportDirectionsToWhereWeAre() /*-{
        $wnd.whereAreWe = this.@com.example.widgetmaster.client.ui.VJamal::whereAreWe(); 
 }-*/;

From Jamal.java


	public void changeVariables(Object source, Map<String, Object> variables) {
		super.changeVariables(source, variables);

		// Variables set by the widget are returned in the "variables" map.

		if (variables.containsKey("open-window")) {
			((WidgetmasterApplication) this.getApplication()).addEchoWindow((String)variables.get("open-window"));
			System.err.println("************************************we made it");
			requestRepaint();
		}
		
	}

Any thoughts?

A couple of things I see when looking at the source:

client.updateVariable(paintableId, "open-window", true, true); 

Here, you are passing a boolean value (true) as the value of the “open-window” variable.

But on the server side, you are trying to cast that boolean into a string in

((WidgetmasterApplication) this.getApplication()).addEchoWindow((String)variables.get("open-window"));

If I now understood correctly, what you are trying to do is pass a string from the javascript method to the server? In that case you could change the code to something like this:


...
public void whereAreWe(String position) {
         // Send position to server
         client.updateVariable(paintableId, "open-window", position, true);       
}
    
public native void exportDirectionsToWhereWeAre() /*-{
        $wnd.whereAreWe = this.@com.example.widgetmaster.client.ui.VJamal::whereAreWe(Ljava/lang/String;);
}-*/;

Now in your javascript code you can pass the position by calling


window.whereAreWe("my current position");

Hi John-

Again, many thanks… At this point we’ve found our primary problem, which is our “client” and “paintableId” are both null when we call our whereAreWe() method.

So, a quick recap of what we know, then code:

  • we load information from our custom JS by clicking a vaadin button, which calls a method in our server-side widget and draws our timeline from inside updateFromUIDL()
  • we click an element in our custom JS and it fires the whereAreWe() method in VJamal.java succesfully
  • when we try to use client.updateVariable() we find that client and paintableId are null

VJamal.java Complete:

package com.example.widgetmaster.client.ui;

import com.vaadin.terminal.gwt.client.ApplicationConnection;
import com.vaadin.terminal.gwt.client.Paintable;
import com.vaadin.terminal.gwt.client.UIDL;
import com.google.gwt.dom.client.Document;
import com.google.gwt.user.client.ui.Widget;

/**
 * Client side widget which communicates with the server. Messages from the
 * server are shown as HTML and mouse clicks are sent to the server.
 */
public class VJamal extends Widget implements Paintable {

	public static final String CLASSNAME = "v-jamal";

	public static final String CLICK_EVENT_IDENTIFIER = "click";
	public static final String OPENWINDOW_EVENT_IDENTIFIER = "open-window";

	protected String paintableId;
	protected ApplicationConnection client;

	public VJamal() {
		
		super();
		exportDirectionsToWhereWeAre();
		setElement(Document.get().createDivElement());
		setStyleName(CLASSNAME);
		
	}


	public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
			
		if (client.updateComponent(this, uidl, true)) {
			return;
		}

		this.client = client;
		this.paintableId = uidl.getId();
		
		if(uidl.getBooleanAttribute("drawTimeline")){
			drawTimeline();
		}
		
	}

   
     private native void drawTimeline()/*-{ 
     			$wnd.Echo.Timeline.test(); 
     			
     			}-*/;
     
     private native void centerOn(String centerDate)/*-{ 
     			$wnd.Echo.Timeline.centerOn(centerDate); 
     			}-*/;
     
     public void whereAreWe() {
    	 	
    	 	if(this.client == null || paintableId == null){	 		
    	 		throw new RuntimeException("Missing: " + this.client + " : " + this.paintableId);
    	 	}
 
    	 	client.updateVariable(paintableId, OPENWINDOW_EVENT_IDENTIFIER, "", true); 
    	    
     }
    	    
	public native void exportDirectionsToWhereWeAre() /*-{
	
	   $wnd.whereAreWe = this.@com.example.widgetmaster.client.ui.VJamal::whereAreWe(); 
	}-*/;


 
}

Are we missing something basic?