通过 GWT JSNI 传递 Java 对象时出错
Error when passing Java object through GWT JSNI
我有一个使用 Google JavaScript Chart API to show charts of Java objects. I convert my Java objects to JSON and hand them off to the JavaScript chart API through JSNI 的 GWT 项目,并且运行良好。
但现在我想更进一步,走另一条路:当我在图表内部单击时(我可以通过 Java 脚本侦听器检测到),我想发送 Java 对象回到我的 Java 代码。
我想我已经完成了 JSNI 指南中的所有操作,但是当我单击图表时,我在 JavaScript 控制台中收到一个错误,我什至不确定如何阅读:
SCRIPT5022: Exception thrown and not caught
File: eval code (21), Line: 5, Column: 7
__gwt_javaInvokes[2] =
function(thisObj, dispId,p0,p1) {
var result = __static(dispId, thisObj,p0,p1);
if (result[0]) {
throw result[1];
} else {
return result[1];
}
} function(thisObj, dispId,p0,p1) { var result = __static(dispId, thisObj,p0,p1); if (result[0]) { throw result[1]; } else { return result[1]; } }
这是我的 html 页面:
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="GwtTest.css">
<title>GWT Test</title>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript" language="javascript" src="gwttest/gwttest.nocache.js"></script>
</head>
<body>
</body>
</html>
唯一感兴趣的是我添加了 Google 图表 API 脚本标签。
这是我试图从 Java 传递到 Java 脚本,然后返回到 Java 的 Java 对象:
package com.example.client;
public class ChartData {
public String title = "test";
public String labelOne = "thingOne";
public String labelTwo = "thingTwo";
public String labelThree = "thingThree";
public int valueOne = 100;
public int valueTwo = 200;
public int valueThree = 300;
}
最后,这是我的 GWT 客户端 class:
package com.example.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsonUtils;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
public class GwtTest implements EntryPoint {
public void onModuleLoad() {
RootLayoutPanel rootPanel = RootLayoutPanel.get();
SimplePanel chartPanel = new SimplePanel();
chartPanel.getElement().setId("chartDiv");
chartPanel.setSize("500px", "500px");
Button button = new Button("Click Me");
button.addClickHandler(new ClickHandler(){
@Override
public void onClick(ClickEvent event) {
ChartData chartData = new ChartData();
String json = getChartJson(chartData);
JsArray<?> chartArrayData = JsonUtils.safeEval(json);
drawChart(chartArrayData, chartData);
}
});
VerticalPanel vp = new VerticalPanel();
vp.add(button);
vp.add(chartPanel);
rootPanel.add(vp);
loadChartLibrary();
}
private String getChartJson(ChartData chartData){
String json = "[";
json += "[\"time\", \"" + chartData.title + "\"]";
json += ",";
json += "[\"" + chartData.labelOne + "\"," + chartData.valueOne + "]";
json += ",";
json += "[\"" + chartData.labelTwo + "\"," + chartData.valueTwo + "]";
json += ",";
json += "[\"" + chartData.labelThree + "\"," + chartData.valueThree + "]";
json += "]";
return json;
}
private native void loadChartLibrary()/*-{
$wnd.google.charts.load('current', {packages: ['corechart']});
}-*/;
private native void drawChart(JsArray<?> dataArray, ChartData chartData)/*-{
var data = $wnd.google.visualization.arrayToDataTable(dataArray);
var chart = new $wnd.google.visualization.ColumnChart($wnd.document.getElementById('chartDiv'));
chart.draw(data, null);
$wnd.google.visualization.events.addListener(chart, 'select', selectHandler);
function selectHandler(e) {
var selectionArray = chart.getSelection();
if(selectionArray.length == 0){
}
else{
var row = selectionArray[0].row;
console.log(row);
this.@com.example.client.GwtTest::printChartData(Lcom/example/client/ChartData;I)(chartData, row);
console.log("here");
}
}
}-*/;
public void printChartData(ChartData chartData, int i){
System.out.println(i + ": " + chartData.valueThree);
}
}
如果您 运行 此代码,您应该会看到一个显示“单击我”的按钮。单击该按钮以显示图表。然后单击图表中的一个条。我希望这会在 printChartData()
函数中触发我的 Java 代码,但我在 Java 脚本控制台中收到错误消息。
我已将问题缩小到这段代码:
var row = selectionArray[0].row;
console.log(row);
this.@com.example.client.GwtTest::printChartData(Lcom/example/client/ChartData;I)(chartData, row);
console.log("here");
该行已正确打印到控制台,所以我知道我的 Java脚本正在运行。但是 "here"
永远不会打印到控制台,所以我知道错误在我的 JSNI 行中。
我的 JSNI 设置是否遗漏了什么? Java脚本错误是什么意思?
我认为问题在于在处理程序中使用 this
。您可能希望 this
成为 GwtTest
class 的实例,但在 Handler 内部使用它指向处理程序。这就是调用 this.@com.example.client.GwtTest::printChartData
失败的原因。
您可以在处理程序外部声明一个变量并赋值 this
,然后在处理程序内部使用它。
尝试:
var instance = this;
function selectHandler(e) {
var selectionArray = chart.getSelection();
if(selectionArray.length == 0){
}
else{
var row = selectionArray[0].row;
console.log(row);
instance.@com.example.client.GwtTest::printChartData(Lcom/example/client/ChartData;I)(chartData, row);
console.log("here");
}
}
ChartData
没有扩展 JavaScriptObject
,所以当你调用
时它会抛出一个 ClassCastException
printChartData
.
亚当也是对的。在处理程序中使用 this
不起作用...
这是一个示例,它是如何工作的,只需覆盖整个 GwtTest class..
public class GwtTest implements EntryPoint {
private ChartData chartData;
public void onModuleLoad() {
RootLayoutPanel rootPanel = RootLayoutPanel.get();
SimplePanel chartPanel = new SimplePanel();
chartPanel.getElement().setId("chartDiv");
chartPanel.setSize("500px", "500px");
Button button = new Button("Click Me");
button.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
chartData= ChartData.createJSO("Time", "Time");
for (int i = 0; i < 4; i++) {
RowData row = RowData.createJSO("label" + i, 100 + i);
chartData.add(row);
}
drawChart(chartData);
}
});
VerticalPanel vp = new VerticalPanel();
vp.add(button);
vp.add(chartPanel);
rootPanel.add(vp);
loadChartLibrary();
}
public static class ChartData extends JavaScriptObject {
protected ChartData() {
}
public static native ChartData createJSO(String chartname, String rowTypeDescriton) /*-{
return [ [ chartname, rowTypeDescriton ] ];
}-*/;
public final native RowData get(int index) /*-{
return this[index + 1];
}-*/;
public final native void add(RowData data) /*-{
this[this.length] = data;
}-*/;
}
public static class RowData extends JavaScriptObject {
protected RowData() {
}
public static native RowData createJSO(String label, int value) /*-{
return [ label, value ];
}-*/;
public final native String getLabelOne() /*-{
return this[0];
}-*/;
public final native int getValueOne() /*-{
return this[1];
}-*/;
}
private native void loadChartLibrary()/*-{
$wnd.google.charts.load('current', {
packages : [ 'corechart' ]
});
}-*/;
private native void drawChart(ChartData dataArray)/*-{
var self = this;
var data = $wnd.google.visualization.arrayToDataTable(dataArray);
var chart = new $wnd.google.visualization.ColumnChart($wnd.document
.getElementById('chartDiv'));
chart.draw(data, null);
$wnd.google.visualization.events.addListener(chart, 'select',
selectHandler);
function selectHandler(e) {
var selection = chart.getSelection();
for (var i = 0; i < selection.length; i++) {
var item = selection[i];
if (item.row != null) {
self.@com.example.client.GwtTest::printChartData(I)(item.row);
}
}
}
}-*/;
public void printChartData(int row) {
System.out.println(chartData.get(row));
}
}
我有一个使用 Google JavaScript Chart API to show charts of Java objects. I convert my Java objects to JSON and hand them off to the JavaScript chart API through JSNI 的 GWT 项目,并且运行良好。
但现在我想更进一步,走另一条路:当我在图表内部单击时(我可以通过 Java 脚本侦听器检测到),我想发送 Java 对象回到我的 Java 代码。
我想我已经完成了 JSNI 指南中的所有操作,但是当我单击图表时,我在 JavaScript 控制台中收到一个错误,我什至不确定如何阅读:
SCRIPT5022: Exception thrown and not caught
File: eval code (21), Line: 5, Column: 7
__gwt_javaInvokes[2] =
function(thisObj, dispId,p0,p1) {
var result = __static(dispId, thisObj,p0,p1);
if (result[0]) {
throw result[1];
} else {
return result[1];
}
} function(thisObj, dispId,p0,p1) { var result = __static(dispId, thisObj,p0,p1); if (result[0]) { throw result[1]; } else { return result[1]; } }
这是我的 html 页面:
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="GwtTest.css">
<title>GWT Test</title>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript" language="javascript" src="gwttest/gwttest.nocache.js"></script>
</head>
<body>
</body>
</html>
唯一感兴趣的是我添加了 Google 图表 API 脚本标签。
这是我试图从 Java 传递到 Java 脚本,然后返回到 Java 的 Java 对象:
package com.example.client;
public class ChartData {
public String title = "test";
public String labelOne = "thingOne";
public String labelTwo = "thingTwo";
public String labelThree = "thingThree";
public int valueOne = 100;
public int valueTwo = 200;
public int valueThree = 300;
}
最后,这是我的 GWT 客户端 class:
package com.example.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsonUtils;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
public class GwtTest implements EntryPoint {
public void onModuleLoad() {
RootLayoutPanel rootPanel = RootLayoutPanel.get();
SimplePanel chartPanel = new SimplePanel();
chartPanel.getElement().setId("chartDiv");
chartPanel.setSize("500px", "500px");
Button button = new Button("Click Me");
button.addClickHandler(new ClickHandler(){
@Override
public void onClick(ClickEvent event) {
ChartData chartData = new ChartData();
String json = getChartJson(chartData);
JsArray<?> chartArrayData = JsonUtils.safeEval(json);
drawChart(chartArrayData, chartData);
}
});
VerticalPanel vp = new VerticalPanel();
vp.add(button);
vp.add(chartPanel);
rootPanel.add(vp);
loadChartLibrary();
}
private String getChartJson(ChartData chartData){
String json = "[";
json += "[\"time\", \"" + chartData.title + "\"]";
json += ",";
json += "[\"" + chartData.labelOne + "\"," + chartData.valueOne + "]";
json += ",";
json += "[\"" + chartData.labelTwo + "\"," + chartData.valueTwo + "]";
json += ",";
json += "[\"" + chartData.labelThree + "\"," + chartData.valueThree + "]";
json += "]";
return json;
}
private native void loadChartLibrary()/*-{
$wnd.google.charts.load('current', {packages: ['corechart']});
}-*/;
private native void drawChart(JsArray<?> dataArray, ChartData chartData)/*-{
var data = $wnd.google.visualization.arrayToDataTable(dataArray);
var chart = new $wnd.google.visualization.ColumnChart($wnd.document.getElementById('chartDiv'));
chart.draw(data, null);
$wnd.google.visualization.events.addListener(chart, 'select', selectHandler);
function selectHandler(e) {
var selectionArray = chart.getSelection();
if(selectionArray.length == 0){
}
else{
var row = selectionArray[0].row;
console.log(row);
this.@com.example.client.GwtTest::printChartData(Lcom/example/client/ChartData;I)(chartData, row);
console.log("here");
}
}
}-*/;
public void printChartData(ChartData chartData, int i){
System.out.println(i + ": " + chartData.valueThree);
}
}
如果您 运行 此代码,您应该会看到一个显示“单击我”的按钮。单击该按钮以显示图表。然后单击图表中的一个条。我希望这会在 printChartData()
函数中触发我的 Java 代码,但我在 Java 脚本控制台中收到错误消息。
我已将问题缩小到这段代码:
var row = selectionArray[0].row;
console.log(row);
this.@com.example.client.GwtTest::printChartData(Lcom/example/client/ChartData;I)(chartData, row);
console.log("here");
该行已正确打印到控制台,所以我知道我的 Java脚本正在运行。但是 "here"
永远不会打印到控制台,所以我知道错误在我的 JSNI 行中。
我的 JSNI 设置是否遗漏了什么? Java脚本错误是什么意思?
我认为问题在于在处理程序中使用 this
。您可能希望 this
成为 GwtTest
class 的实例,但在 Handler 内部使用它指向处理程序。这就是调用 this.@com.example.client.GwtTest::printChartData
失败的原因。
您可以在处理程序外部声明一个变量并赋值 this
,然后在处理程序内部使用它。
尝试:
var instance = this;
function selectHandler(e) {
var selectionArray = chart.getSelection();
if(selectionArray.length == 0){
}
else{
var row = selectionArray[0].row;
console.log(row);
instance.@com.example.client.GwtTest::printChartData(Lcom/example/client/ChartData;I)(chartData, row);
console.log("here");
}
}
ChartData
没有扩展 JavaScriptObject
,所以当你调用
时它会抛出一个 ClassCastException
printChartData
.
亚当也是对的。在处理程序中使用 this
不起作用...
这是一个示例,它是如何工作的,只需覆盖整个 GwtTest class..
public class GwtTest implements EntryPoint {
private ChartData chartData;
public void onModuleLoad() {
RootLayoutPanel rootPanel = RootLayoutPanel.get();
SimplePanel chartPanel = new SimplePanel();
chartPanel.getElement().setId("chartDiv");
chartPanel.setSize("500px", "500px");
Button button = new Button("Click Me");
button.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
chartData= ChartData.createJSO("Time", "Time");
for (int i = 0; i < 4; i++) {
RowData row = RowData.createJSO("label" + i, 100 + i);
chartData.add(row);
}
drawChart(chartData);
}
});
VerticalPanel vp = new VerticalPanel();
vp.add(button);
vp.add(chartPanel);
rootPanel.add(vp);
loadChartLibrary();
}
public static class ChartData extends JavaScriptObject {
protected ChartData() {
}
public static native ChartData createJSO(String chartname, String rowTypeDescriton) /*-{
return [ [ chartname, rowTypeDescriton ] ];
}-*/;
public final native RowData get(int index) /*-{
return this[index + 1];
}-*/;
public final native void add(RowData data) /*-{
this[this.length] = data;
}-*/;
}
public static class RowData extends JavaScriptObject {
protected RowData() {
}
public static native RowData createJSO(String label, int value) /*-{
return [ label, value ];
}-*/;
public final native String getLabelOne() /*-{
return this[0];
}-*/;
public final native int getValueOne() /*-{
return this[1];
}-*/;
}
private native void loadChartLibrary()/*-{
$wnd.google.charts.load('current', {
packages : [ 'corechart' ]
});
}-*/;
private native void drawChart(ChartData dataArray)/*-{
var self = this;
var data = $wnd.google.visualization.arrayToDataTable(dataArray);
var chart = new $wnd.google.visualization.ColumnChart($wnd.document
.getElementById('chartDiv'));
chart.draw(data, null);
$wnd.google.visualization.events.addListener(chart, 'select',
selectHandler);
function selectHandler(e) {
var selection = chart.getSelection();
for (var i = 0; i < selection.length; i++) {
var item = selection[i];
if (item.row != null) {
self.@com.example.client.GwtTest::printChartData(I)(item.row);
}
}
}
}-*/;
public void printChartData(int row) {
System.out.println(chartData.get(row));
}
}