Почему приложение GWT не отображается?
Обновление: я собираюсь добавить награду к этому вопросу. Я добавил весь исходный код проекта в GitHub здесь:
https://github.com/doctrang/gwt-activities-places-mvp-example
Я решил переименовать мой SimpleModule
в WebModule
; так что, хотя во всех моих фрагментах кода ниже, модуль GWT называется SimpleModule
или же simplemodule
, в моем последнем коде вы увидите модуль с именем WebModule
а также webmodule
соответственно - но они 1 в одном!
Примечание: я понимаю, что у меня может быть не все настроено идеально, и может быть какой-то мертвый код (SimpleModule.css
и т. д.), который вообще не используется, но это мое самое первое приложение GWT, и я просто хочу его запустить и запустить!
Я экспериментирую с моим первым приложением GWT (2.5.1) и пытаюсь получить очень простой пользовательский интерфейс для отображения, используя рекомендованную среду Places & Activity (для управления историей), а также использую базовую архитектуру MVP.
Для простоты я поместил весь код Java внутри SimpleModule.java
(точка входа). Как только я получу это доказательство концепции, я разложу SimpleModule.java
на большее количество классов.
Моя цель - загрузить приложение GWT, когда пользователь заходит на мою домашнюю страницу (me.example.com). Из-за этого я создаю SimpleModule implements EntryPoint
, а затем переименовал страницу хоста из SimpleModule.html
в index.html
(так что когда пользователи переходят на me.example.com или me.example.com/index.html, они SimpleModule
).
Структура каталогов моей WAR:
war/
hosts/
simplemodule/
SimpleModule.css
WEB-INF/
classes/
lib/
deploy/
web.xml
simplemodule/
css/
font/
gwt/
img/
js/
prettify/
clear.cache.gif
hosted.html
simplemodule.nocache.js
img/
mylogo.jpg
index.html
А также index.html
:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" language="javascript" src="simplemodule/simplemodule.nocache.js"></script>
</head>
<body>
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled in order for this application to display correctly.
</div>
</noscript>
</body>
</html>
А также web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
<servlet>
<servlet-name>greetServlet</servlet-name>
<servlet-class>com.myapp.server.GreetingServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>greetServlet</servlet-name>
<url-pattern>/simplemodule/greet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>remoteLogging</servlet-name>
<servlet-class>com.google.gwt.logging.server.RemoteLoggingServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>remoteLogging</servlet-name>
<url-pattern>/simplemodule/remote_logging</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
А также SimpleModule.java
:
public class SimpleModule implements EntryPoint {
private EventBus eventBus = new SimpleEventBus();
private PlaceController placeController = new PlaceController(eventBus);
private PlaceHistoryMapper placeHistoryMapper;
private PlaceHistoryHandler placeHistoryHandler;
private Place defaultPlace;
private ActivityMapper activityMapper;
private ActivityManager activityManager;
private LoginDisplay loginDisplay = new LoginDisplay();
@Override
public void onModuleLoad() {
bootstrap();
RootPanel.get().add(loginDisplay);
activityManager.setDisplay(loginDisplay);
placeHistoryHandler.register(placeController, eventBus, defaultPlace);
placeHistoryHandler.handleCurrentHistory();
}
private void bootstrap() {
placeHistoryMapper = new PlaceHistoryMapper() {
@Override
public String getToken(Place arg0) {
return "home";
}
@Override
public Place getPlace(String arg0) {
return defaultPlace;
}
};
placeHistoryHandler = new PlaceHistoryHandler(placeHistoryMapper);
defaultPlace = new Place() {};
activityMapper = new ActivityMapper() {
@Override
public Activity getActivity(Place arg0) {
return new LoginActivity();
}
};
activityManager = new ActivityManager(activityMapper, eventBus);
}
public class LoginDisplay extends SimplePanel {
private LoginDisplayUiBinder uiBinder = GWT
.create(LoginDisplayUiBinder.class);
public LoginDisplay() {
super();
uiBinder.createAndBindUi(this);
}
}
public interface LoginDisplayUiBinder extends UiBinder<Widget, LoginDisplay> {
// ???
}
public class LoginActivity extends AbstractActivity {
@Override
public void start(AcceptsOneWidget panel,
com.google.gwt.event.shared.EventBus eventBus) {
panel.setWidget(loginDisplay);
}
}
}
А также LoginDisplay.ui.xml
:
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui">
<g:HTMLPanel>
<img src="img/mylogo.jpg" />
<hr/>
<form action="doStuff" method="post" class="form-horizontal"
id="someForm" accept-charset="utf-8">
<div class="control-group">
<label for="username" class="control-label">
Username:
</label>
<div class="controls">
<input name="username" type="text" value="" id="username"/>
</div>
</div>
<div class="control-group">
<label for="password" class="control-label">
Password:
</label>
<div class="controls">
<input name="password" type="password" value="" id="password"/>
</div>
</div>
<div class="control-group">
<div class="controls">
<input type="button" class="btn-danger" value="Login"/>
</div>
</div>
</form>
</g:HTMLPanel>
</ui:UiBinder>
Обновление: и SimpleModule.gwt.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.1//EN"
"http://google-web-toolkit.googlecode.com/svn/tags/2.5.1/distro-source/core/src/gwt-module.dtd">
<module rename-to='simplemodule'>
<inherits name='com.google.gwt.user.User'/>
<!-- Configure logging. -->
<inherits name="com.google.gwt.logging.Logging"/>
<set-property name="gwt.logging.logLevel" value="FINEST"/>
<set-property name="gwt.logging.enabled" value="TRUE"/>
<set-property name="gwt.logging.consoleHandler" value="ENABLED"/>
<set-property name="gwt.logging.developmentModeHandler" value="DISABLED" />
<set-property name="gwt.logging.popupHandler" value="DISABLED" />
<set-property name="gwt.logging.systemHandler" value="DISABLED" />
<set-property name="gwt.logging.firebugHandler" value="DISABLED" />
<set-property name="gwt.logging.simpleRemoteHandler" value="DISABLED" />
<!-- GWT-Bootstrap. -->
<inherits name ="com.github.gwtbootstrap.Bootstrap"/>
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<entry-point class='com.myapp.client.SimpleModule'/>
<source path='client'/>
<source path='shared'/>
</module>
Источник веб-страницы после запуска сервера:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" language="javascript" src="simplemodule/simplemodule.nocache.js"></script>
</head>
<body height="100%" width="100%">
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled in order for this application to display correctly.
</div>
</noscript>
</body>
</html>
Когда я запускаю это в режиме Dev (цель Ant, которая вызывает Java на com.google.gwt.dev.DevMode
), Я получаю инструмент Dev Mode, запускающийся без ошибок. Когда я выбираю "Запустить приложение", я получаю пустую веб-страницу. Когда я открываю Firebug и выискиваю ошибки, я ничего не вижу.
Что не так с моей настройкой??? Почему я не вижу простой логотип с полями для входа под ним? Заранее спасибо!
Изменить: мое последнее обновление. Я следовал советам @Raphael (унаследовал модули Place и Activity и добавил @UITemplate
аннотация к LoginDisplayUiBinder
), Я получаю ярлык "Здравствуйте, GWT!" печать в мой браузер!!! Затем я изменил мой onModuleLoader()
способ выглядеть так:
@Override
public void onModuleLoad() {
bootstrap();
// RootPanel.get().add(new Label("Hello, GWT!"));
RootPanel.get().add(loginDisplay);
activityManager.setDisplay(loginDisplay);
// Connect the PlaceController to the EventBus, and set the
// defaultPlace as our first place in history.
placeHistoryHandler.register(placeController, eventBus, defaultPlace);
placeHistoryHandler.handleCurrentHistory();
}
И теперь я получаю следующее исключение:
onModuleLoad() threw an exception
Exception while loading module com.dummylandapp.client.WebModule. See Development Mode for details.
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at com.google.gwt.dev.shell.ModuleSpace.onLoad(ModuleSpace.java:406)
at com.google.gwt.dev.shell.OophmSessionHandler.loadModule(OophmSessionHandler.java:200)
at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:526)
at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
at java.lang.Thread.run(Thread.java:679) Caused by: com.google.web.bindery.event.shared.UmbrellaException: Exception caught: Exception caught: (HierarchyRequestError) @com.google.gwt.dom.client.Node::appendChild(Lcom/google/gwt/dom/client/Node;)([JavaScript object(15)]): Node cannot be inserted
at the specified point in the hierarchy
at com.google.web.bindery.event.shared.SimpleEventBus.doFire(SimpleEventBus.java:203)
at com.google.web.bindery.event.shared.SimpleEventBus.fireEvent(SimpleEventBus.java:88)
at com.google.gwt.place.shared.PlaceController.goTo(PlaceController.java:156)
at com.google.gwt.place.shared.PlaceHistoryHandler.handleHistoryToken(PlaceHistoryHandler.java:192)
at com.google.gwt.place.shared.PlaceHistoryHandler.handleCurrentHistory(PlaceHistoryHandler.java:118)
at com.dummylandapp.client.WebModule.onModuleLoad(WebModule.java:66) ... 9 more Caused by: com.google.gwt.event.shared.UmbrellaException: Exception caught: (HierarchyRequestError) @com.google.gwt.dom.client.Node::appendChild(Lcom/google/gwt/dom/client/Node;)([JavaScript object(15)]): Node cannot be inserted
at the specified point in the hierarchy
at com.google.gwt.activity.shared.ActivityManager.onPlaceChange(ActivityManager.java:168)
at com.google.gwt.place.shared.PlaceChangeEvent.dispatch(PlaceChangeEvent.java:70)
at com.google.gwt.place.shared.PlaceChangeEvent.dispatch(PlaceChangeEvent.java:1)
at com.google.gwt.event.shared.GwtEvent.dispatch(GwtEvent.java:1)
at com.google.web.bindery.event.shared.EventBus.dispatchEvent(EventBus.java:40)
at com.google.web.bindery.event.shared.SimpleEventBus.doFire(SimpleEventBus.java:193) ... 14 more
6 ответов
Деятельность и места - это благородное понятие, которое никогда не взлетит из-за присущей ему сложности. Пытаться gwtp
(Платформа GWT) вместо этого. Ты никогда не вернешься. Вы можете запустить рабочие примеры MVP за считанные минуты, и GWT P имеет все управление историей / закладки, которые есть у A&P, с гораздо более простым API для понимания и кодирования.
Поверьте мне, GWTP - это путь для всех приложений MVP.
Проблема здесь:
public class LoginDisplay extends SimplePanel {
private LoginDisplayUiBinder uiBinder = GWT
.create(LoginDisplayUiBinder.class);
public LoginDisplay() {
super();
uiBinder.createAndBindUi(this);
}
}
Вы создаете свой виджет, но никогда не добавляете его на панель:
uiBinder.createAndBindUi(this);
Пытаться:
this.add(uiBinder.createAndBindUi(this));
Обратите внимание, что вы также можете поместить интерфейс uiBinder в LoginDisplay
Класс, как это необходимо только здесь (делает ваш код более понятным):
public class LoginDisplay extends SimplePanel {
public interface LoginDisplayUiBinder extends UiBinder<Widget, LoginDisplay> {}
public LoginDisplay() {
super();
LoginDisplayUiBinder uiBinder=GWT.create(LoginDisplayUiBinder.class);
this.add(uiBinder.createAndBindUi(this));
}
}
Вы используете Place и Activity в своем проекте, но ваш модуль не наследует их. Добавьте следующие строки в WebModule.xml
:
<inherits name='com.google.gwt.place.Place'/>
<inherits name='com.google.gwt.activity.Activity'/>
Кроме того, вы должны добавить UiTemplate
аннотации к вашему интерфейсу UiBinder, если шаблон представления не имеет того же имени, что и его включающий класс. В вашем случае GWT ищет WebModule.ui.xml
при попытке создать LoginDisplayUiBinder
,
@UiTemplate("LoginDisplay.ui.xml")
public interface LoginDisplayUiBinder extends UiBinder<Widget, LoginDisplay> {}
Обновить
Ваше новое исключение вызвано этим:
RootPanel.get().add(loginDisplay);
activityManager.setDisplay(loginDisplay);
Вы добавляете форму входа в систему в первый раз и устанавливаете ее в качестве основного дисплея для вашего ActivityManager
, Дисплей panel
Аргумент вашей деятельности в их методе начала:
void start(AcceptsOneWidget panel, com.google.gwt.event.shared.EventBus eventBus);
В вашем случае, когда вы запускаете событие изменения страницы (с помощью placeHistoryHandler.handleCurrentHistory();
), LoginActivity
постараюсь добавить LoginDisplay
к себе вызывает Exception
:
panel.setWidget(loginDisplay);
Простое исправление, которое вы можете сделать, это создать другой SimplePanel
и установите его в качестве основного дисплея:
final SimplePanel mainPanel = new SimplePanel();
RootPanel.get().add(mainPanel);
activityManager.setDisplay(mainPanel);
У вас есть файл yourapp.gwt.xml? Если так, пожалуйста отправьте это. Если нет, это причина. Подробнее об этом в документации GWT. Потому что, похоже, вам не хватает <entry-point class='com.myapp.MyEntryPointClass' />
Поскольку это загрузит ваше приложение без каких-либо проблем, запустите ваш HTML-файл, однако код не будет выполнен, оставив вам не измененный HTML-файл, который вы предоставляете.
Как вы строите это приложение?
1) Используете ли вы Eclipse для этой или какой-либо другой IDE? Когда я попытался использовать другую среду IDE (поэтому без плагина) с файлами ANT, я не мог заставить GWT работать должным образом.
2) Вы оставили весь сервлет GreetingService там, вы уверены, что это не доставляет вам хлопот?
Я всегда запускаю свои приложения с одним и тем же именем проекта, одним и тем же именем модуля и одной и той же HTML-страницей.
Как это:
Проект: SimpleModule
XML: SimpleModule.gwt.xml
Содержит это:
в заключение
SimpleModule.html
Вам не нужно переименовывать его в index.html.
Когда gwt компилирует, скажем, вы запускаете его в Tomcat, ему не нужен index.html, он распознает SimpleModule.html в качестве индекса.
Надеюсь, это поможет.
Вы должны поместить свою ошибку журнала, чтобы быть более ясным, и я рекомендую srart новый проект. Посмотрите, как это работает, и проанализируйте, чего вам не хватает.
Не забудьте также и про web.xml.