容器标签的名称如何重要?

时间:2012-01-16 01:10:54

标签: java google-app-engine gwt ant

我正在编写一个GWT / GAE(Java)应用程序。 GWT附带的自动生成的hello word示例生成如下代码:

<table align="center">

  <tr>
    <td colspan="2" style="font-weight:bold;">Please enter your name:</td>
  </tr>

  <tr>
    <td id="nameFieldContainer"></td>
    <td id="sendButtonContainer"></td>
  </tr>

在客户端Java(对JavaScript)中,它访问HTML元素,如下所示:

final Button sendButton = new Button("Send");
final TextBox nameField = new TextBox();
nameField.setText("GWT User");

我添加了一个容器字段,以表明我可以使用HTML元素以编程方式添加链接:someStuffContainer。我还通过调用RPC服务来添加另一个要填写的字段:logoutUrlContainer。 (是的,我知道现在有一种更简单的方法可以做到这一点:GWT/GAE(Java): when combined with GAE, app.yaml / web.xml user authentication and login/logout not really working。我只是想看看我是否可以让它发挥作用。)注意someStuffContainer只是为了让它成为一个受控制的实验:通过在服务器端生成的注销链接,将填充该URL的URL的程序性添加分开;这将在下面相关。

  <tr colspan="2">
    <td id="someStuffContainer"></td>
  </tr>
  <tr colspan="2">
    <td id="logoutUrlContainer"></td>
  </tr>

在客户端Java(对JavaScript)中,我这样做了:

// make it clear that we can add something to the page
final HTML someStuffHTML = new HTML
  ("<a href=https://www.google.com/search?q=zap>some stuff 3</a>");

// provide the user with a logout URL; FIX: do this by just
// providing a link to a generic logout servlet, rather than by
// proactively creating the logout link here.
final HTML userStatusHTML = new HTML();
GWT.log("userStatusService.getStatus()");
userStatusService.getStatus
  ("/", new AsyncCallback<UserStatusServiceResponse>() {

    public void onFailure(Throwable caught) {
      GWT.log("userStatusService.onFailure()");
      LogUtil.logThrowable(caught);
    }

    public void onSuccess(UserStatusServiceResponse result) {
      GWT.log("userStatusService.onSuccess()");
      if (result.loggedIn) {
        userStatusHTML.setHTML("<a href=\""+ result.logOutUrl+
                              "\">log out</a>");
      } else {
        // FIX: we should actually redirect to the base page
        userStatusHTML.setHTML("<a href=\""+ result.logInUrl+
                              "\">log in</a>");
      }
    }
  });

RootPanel.get("someStuffContainer").add(someStuffHTML);
RootPanel.get("logoutUrlContainer").add(userStatusHTML);

这一切都起作用,程序化HTML显示并点击注销URL会将用户注销。 (要查看此工作,您必须在另一个选项卡中打开注销URL;如果您转到另一个页面,GWT devmode插件会变得怪异;它似乎进入一种状态,它只是抱怨应用程序需要重新编译并且你不能超出那种状态。此外,你必须点击重新加载app引擎才能要求你再次登录;如果你已经注销并且客户端仍然在运行,你可以继续使用该应用程序,除非在您正在检查用户的服务器端是否已登录。)

在我看来,容器字段“logoutUrlContainer”的名称根本不重要。因此,在签入之前我以为我会清理代码并将其重命名为更通用的内容,这反映了我可能将该容器用于更通用的用户状态窗口小部件的事实。所以我将“logoutUrlContainer”重命名为“userStatusContainer”;我在.html和客户端Java(编译为JavaScript)中重命名了它。现在,该行不是工作,而是获得空指针异常:

RootPanel.get("logoutUrlContainer").add(userStatusHTML);

我是一位经验丰富的编码员:我确信要复制并粘贴,以便匹配字符串。我使用emacs中的搜索功能进行了检查。我用ant clean来清理整个项目。我使用grep来查找整个项目中的任何二进制文件(例如类文件),这些文件可能已被ant clean遗漏,并且某种程度上仍包含旧名称。我重新启动了服务器,杀死了包含应用程序的浏览器选项卡等。我反复做了所有这些。我一再得到空指针异常。我想我一遍又一遍地做了所有这些,至少一个小时。请注意someStuffContainer始终工作的整个时间;不知怎的,RootPanel.get()总是找到它,而没有找到userStatusContainer。最后,在绝望中我只是再次命名容器字符串。它立即起作用。我签到了。

到底发生了什么事?蚂蚁干净缺少什么?这是我的蚂蚁清洁目标,我扩展自己:

  <target name="clean" description="Cleans this project">
    <delete  dir="gwt-unitCache" failonerror="false" />
    <delete  dir="war/myapp" failonerror="false" />
    <delete  dir="war/WEB-INF/classes" failonerror="false" />
    <delete  dir="war/WEB-INF/lib" failonerror="false" />
    <delete  dir="war/WEB-INF/deploy" failonerror="false" />
    <delete file="war/WEB-INF/appengine-web.xml" failonerror="false" />
    <delete file="war/WEB-INF/web.xml" failonerror="false" />
  </target>

我不删除所有war / WEB-INF的唯一原因是我使用可选的app.yaml来配置Java Google App Engine,而不是自己编辑.xml文件。

我的蚂蚁清洁目标是否遗漏了什么?这种体验真的让我不想使用GWT。


更新:我想我知道发生了什么:javascript正在重新编译,但我从未想过GWT开发插件会允许页面被缓存。后来我更改了欢迎文件列表,旧的欢迎文件仍然显示。研究配置文件,我想不出任何可行的方法。最后我点击重新加载并显示新文件。

无论如何,缓存可以解释此问题中报告的错误。我不知道GWT正在做什么允许页面被缓存,尤其是在devmode中。您认为在成为网络开发人员15年后,我可能已经考虑过这个问题。但是我无法想象人们如何通过缓存效果如此草率,特别是在开发框架中。


我正在运行OS X 10.6.8(x86)的最新版本。 我的浏览器是Chrome:16.0.912.63(Official Build 113337) $ java -version java版“1.6.0_29” Java(TM)SE运行时环境(版本1.6.0_29-b11-402-10M3527) Java HotSpot(TM)64位服务器VM(内置20.4-b02-402,混合模式) 我正在使用gwt-2.4.0。

1 个答案:

答案 0 :(得分:0)

  

它似乎进入一种状态,它只是一直抱怨应用程序需要重新编译,你不能超出该状态

这与您正在调试的事实有关,因此Dev模式用更新的版本覆盖了一些已编译的文件,当您没有重新编译(并且正在以dev模式启动应用程序)时,它注意到丢失文件和停止。如果要使用开发模式,请将?gwt.codesvr=...附加到新页面的URL,它也将以开发模式运行该页面。或编译应用程序,不要使用任何具有开发模式的页面(加载该模块 - 其他模块都可以)。

我怀疑如果你将这个后缀添加到网址,你的整个问题就会消失 - 如果RootPanel.get("some-id")与html网页不匹配,你看到的NPE归因于RootPanel.get返回null,并且add被调用为null。