Hi there,
I am currently evaluating Vaadin 7 to see whether it is suitable for the upcoming project in my company.
I’ve made a very simple example, but I am not able to get this running on Google App Engine (GAE). Currently I’ve only tested this on the development server of the GAE.
This is my Root-Class:
package com.gettingmobile.ui.admin;
import com.vaadin.terminal.WrappedRequest;
import com.vaadin.ui.Root;
public class AdminRoot extends Root {
public AdminRoot() {
super("Test");
}
@Override
protected void init(WrappedRequest request) {
setContent(new TestPanel());
}
}
This is the TestPanel-class
package com.gettingmobile.ui.admin;
import com.vaadin.ui.Button;
import com.vaadin.ui.Panel;
public class TestPanel extends Panel {
public TestPanel() {
addComponent(new Button("Click me...", new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
getRoot().showNotification("Test");
}
}));
}
}
My web.xml looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
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">
<context-param>
<description>Vaadin production mode</description>
<param-name>productionMode</param-name>
<param-value>false</param-value>
</context-param>
<servlet>
<servlet-name>Admin App</servlet-name>
<servlet-class>com.vaadin.terminal.gwt.server.GAEApplicationServlet</servlet-class>
<init-param>
<description>Vaadin root</description>
<param-name>root</param-name>
<param-value>com.gettingmobile.ui.admin.AdminRoot</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Admin App</servlet-name>
<url-pattern>/admin/*</url-pattern>
<url-pattern>/VAADIN/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>Admin Interface</web-resource-name>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
</web-app>
The appengine-web.xml:
<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<application>getting-mobile</application>
<version>1</version>
<sessions-enabled>true</sessions-enabled>
</appengine-web-app>
And finally the persistence.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
<persistence-unit name="transactions-optional">
<provider>org.datanucleus.store.appengine.jpa.DatastorePersistenceProvider</provider>
<properties>
<property name="datanucleus.NontransactionalRead" value="true"/>
<property name="datanucleus.NontransactionalWrite" value="true"/>
<property name="datanucleus.ConnectionURL" value="appengine"/>
</properties>
</persistence-unit>
</persistence>
The TestPanel shows up correctly, but as soon as I click the button I get the “session expired” error box shown on the web site.
This is the output I get on the console. The IllegaleStateException is thrown when I click the button:
12.04.2012 09:29:28 com.google.apphosting.utils.jetty.AppEngineAuthentication$AppEngineUserRealm isUserInRole
INFO: Checking if principal test@example.com is in role admin
12.04.2012 09:29:28 com.vaadin.terminal.gwt.server.AbstractApplicationServlet checkProductionMode
WARNUNG:
=================================================================
Vaadin is running in DEBUG MODE.
Add productionMode=true to web.xml to disable debug features.
To show debug window, add ?debug to your application URL.
=================================================================
12.04.2012 09:29:28 com.google.appengine.api.datastore.dev.LocalDatastoreService init
INFO: Local Datastore initialized:
Type: Master/Slave
Storage: C:\source\playground\MobileServices\out\artifacts\MobileServices_war_exploded\WEB-INF\appengine-generated\local_db.bin
12.04.2012 09:29:28 com.google.appengine.api.datastore.dev.LocalDatastoreService load
INFO: The backing store, C:\source\playground\MobileServices\out\artifacts\MobileServices_war_exploded\WEB-INF\appengine-generated\local_db.bin, does not exist. It will be created.
12.04.2012 09:29:28 com.google.apphosting.utils.jetty.AppEngineAuthentication$AppEngineUserRealm isUserInRole
INFO: Checking if principal test@example.com is in role admin
12.04.2012 09:29:30 com.google.apphosting.utils.jetty.AppEngineAuthentication$AppEngineUserRealm isUserInRole
INFO: Checking if principal test@example.com is in role admin
12.04.2012 09:29:30 com.vaadin.terminal.gwt.server.GAEApplicationServlet service
WARNUNG: An exception occurred while servicing request.
java.lang.IllegalStateException
at org.mortbay.jetty.servlet.AbstractSessionManager$Session.getMaxInactiveInterval(AbstractSessionManager.java:849)
at com.vaadin.terminal.gwt.server.GAEApplicationServlet.service(GAEApplicationServlet.java:254)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:35)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:60)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.appengine.tools.development.BackendServersFilter.doFilter(BackendServersFilter.java:97)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:78)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:369)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
12.04.2012 09:29:58 com.google.appengine.api.datastore.dev.LocalDatastoreService$PersistDatastore persist
INFO: Time to persist datastore: 33 ms
If I instead do not derive my own Panel-class, but inline it directly in the AdminRoot like shown in the following code, then it works:
@Override
protected void init(WrappedRequest request) {
final Panel panel = new Panel();
panel.addComponent(new Button("Click me...", new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
getRoot().showNotification("Test");
}
}));
setContent(panel);
}