Main Tutorials

Google App Engine + JSF 2 example

In this tutorial, we will show you how to develop and deploy a JSF 2.0 web application in Google App Engine (GAE) environment.

Tools and technologies used :

  1. JDK 1.6
  2. Eclipse 3.7 + Google Plugin for Eclipse
  3. Google App Engine Java SDK 1.6.3.1
  4. JSF 2.1.7
Note
This example is going to reuse this JSF 2.0 hello world example, modify it and merge it with this GAE + Java example.

1. New Web Application Project

In Eclipse, create a new Web Application project, named as “JSFGoogleAppEngine“.

generate a new web application GAE project

“Google Plugin for Eclipse” will generate a sample of GAE project structure.

2. JSF 2 Dependencies

To use JSF 2 in GAE, you need following jars

  1. jsf-api-2.1.7.jar
  2. jsf-impl-2.1.7.jar
  3. el-ri-1.0.jar

Copy and put it in “war/WEB-INF/lib” folder.

gae jsf2 dependency libraries

Right click on project folder, select “Properties“. Select “Java Build Path” -> “Libraries” tab, click “Add Jars” button and select above jars.

gae jsf2 java build path
Note
You need to put this el-ri-1.0.jar, otherwise, you will hit error message – Unable to instantiate ExpressionFactory ‘com.sun.el.ExpressionFactoryImpl’.

3. JSF Managed bean

3.1 Delete plugin generated JSFGoogleAppEngineServlet.java, you don’t need this.

3.2 Create a managed bean.

File : src/com/mkyong/HelloBean.java


package com.mkyong;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

import java.io.Serializable;

@ManagedBean
@SessionScoped
public class HelloBean implements Serializable {

	private static final long serialVersionUID = 1L;

	private String name;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

3.3 Create a new WebConfiguration.java.

JSF 2 is using “javax.naming.InitialContext” that’s not support in GAE.

To solve this, you need to get a copy of the JSF’s source code, clone the WebConfiguration.java, comment methods that are using “javax.naming.InitialContext” class, put it in “src/com/sun/faces/comfig/WebConfiguration.java“. Now, your newly created WebConfiguration.java class will overload the original WebConfiguration.java.

I don’t think GAE team will white-list this jar, just hope JSF’s team can fix this in future release.

4. JSF Pages

4.1 Create hello.xhtml page, accept a user input and pass it to helloBean.

File : war/hello.xhtml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html">

<h:head>
	<title>GAE + JSF</title>
</h:head>
<h:body>
	<h1>Google App Engine + JSF 2.0 example - hello.xhtml</h1>
	<h:form>
		<h:inputText value="#{helloBean.name}"></h:inputText>
		<h:commandButton value="Welcome Me" action="welcome"></h:commandButton>
	</h:form>
</h:body>
</html>

4.2 Create welcome.xhtml page, display the user input from hellobean.

File : war/welcome.xhtml


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html">

<h:head>
	<title>GAE + JSF</title>
</h:head>
<h:body bgcolor="white">
	<h1>Google App Engine + JSF 2.0 example - welcome.xhtml</h1>
	<h2>Welcome #{helloBean.name}</h2>
</h:body>
</html>

4.3 Delete the plugin generated index.html file, you don’t need this.

5. web.xml

Update web.xml, integrate JSF 2.

File : web.xml


<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

	<display-name>JavaServerFaces</display-name>

	<!-- GAE 1.6.3 cannot handle server side (JSF default) state management. -->
	<context-param>
		<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
		<param-value>client</param-value>
	</context-param>


	<!-- Change to "Production" when you are ready to deploy -->
	<context-param>
		<param-name>javax.faces.PROJECT_STAGE</param-name>
		<param-value>Development</param-value>
	</context-param>

	<!-- Welcome page -->
	<welcome-file-list>
		<welcome-file>faces/hello.xhtml</welcome-file>
	</welcome-file-list>

	<!-- JSF mapping -->
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Map these files with JSF -->
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>/faces/*</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.jsf</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.faces</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.xhtml</url-pattern>
	</servlet-mapping>

</web-app>
Note
GAE do not support server side state management, so, you need to define “javax.faces.STATE_SAVING_METHOD” to “client“, to avoid of this “View /hello.xhtml could not be restored” error message in GAE production environment.

6. Enable Session in GAE

Update appengine-web.xml, enable session support, JSF need this.

File : appengine-web.xml


<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application></application>
  <version>1</version>

	<sessions-enabled>true</sessions-enabled>

</appengine-web-app>

7. Directory Structure

Review final directory structure.

final directory structure

8. Run on Local

Right click on the project, run as “Web Application”.

URL : http://localhost:8888/hello.jsf

local output

Click on the button.

local output

10. Deploy on GAE

Update appengine-web.xml file, add your App Engine application ID.

File : appengine-web.xml


<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application>mkyong-jsf2gae</application>
  <version>1</version>

	<sessions-enabled>true</sessions-enabled>

</appengine-web-app>

Select project, click on Google icon, “Deploy to App Engine“.

deploy on GAE

URL : http://mkyong-jsf2gae.appspot.com/hello.jsf

gae production output

Download Source Code

Due to large file size, all JSF and GAE jars are excluded.

Download – JSF2-GoogleAppEngine-Example.zip (42 KB)

References

  1. JSF and GAE compatible issues
  2. JSF 2 configuration on Google App
  3. Google App Engine with JSF 2 + CDI
  4. Getting start with Google App and JSF
  5. JSF 2.0 hello world example
  6. Oracle : JavaServer Faces development tutorial

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
31 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Chesare
8 years ago

Thank you very much , very good publication

karaujo
9 years ago

Did you tried call ws with cliente certificate on Java AppEngine?

Aloka Za
9 years ago

Thanks for this tuto, but i hava one question : how navigation-rules works with this config?, there is no faces-config.xml???

Béla Boda
9 years ago

Thanks for Your efforts 🙂

remo
10 years ago

it works!!, thank you very much!!!!!

Vladimir
10 years ago

Hi,
I tried to run this example but it doesn’t work. Can anyone help me?

My problem is (maybe):

Caused by: com.google.apphosting.utils.config.AppEngineConfigException: Invalid appengine-web.xml(C:\Users\user\workspace\JSFGoogleAppEngine\war\WEB-INF/appengine-web.xml) – appengine-web.xml does not contain a element.
See http://code.google.com/appengine/docs/java/config/appconfig.html#Using_Concurrent_Requests for more information.

Kasper R. Thomsen
10 years ago

Hey – absolutely great tutorial even though it’s a year old 😉

I tried to add the newest JSF jars, but this didn’t seem to work, so after going back to version 2.1.7 everything worked.

However my content assist doesn’t work inside the xhtml files. Did you run into this problem by any chance and perhaps have a solution for this problem?

This is only a problem when combining JSF and GAE – it’s working nicely in standard JSF projects.

I’m really bad at remembering the different tags, so I’d appreciate if my content assist would work 😉

Sanyog Barve
10 years ago

Hi Kasper R. Thomsen,

I am struggling with the setup from quite long time.

Just to bother you, can you please share your test project with all jar’s and code on GDrive etc.

Thanks in advance.

Kasper R. Thomsen
10 years ago
Reply to  Sanyog Barve

Hi Sanyog,

Here it is – https://bitbucket.org/darwind/jsf-2-on-gae/overview – just pull the zip file or clone the repo.

Sanyog Barve
10 years ago

Hi,

Please ignore, error resolved. Thanks

Carl C
10 years ago
Reply to  Sanyog Barve

What was the resolution, please?

Sanyog Barve
10 years ago

Hi Kasper R. Thomsen,

Thanks for the help. Little more help is required from your side.
I am still getting the same error while running the application.Can you please help me with this, unable to google this too. PFA Console Log.

SEVERE: Critical error during deployment:
com.sun.faces.config.ConfigurationException: java.util.concurrent.ExecutionException: javax.faces.FacesException: java.net.URISyntaxException: Illegal character in opaque part at index 29: jar:file:/D:/Software/Eclipse Workspace/JsfOnGae/war/WEB-INF/lib/jsf-impl-2.1.7.jar!/META-INF/mojarra_ext.taglib.xml

—————————————————————————
16 May, 2013 8:10:15 AM com.google.apphosting.utils.jetty.JettyLogger info
INFO: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
16 May, 2013 8:10:15 AM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
INFO: Successfully processed D:\Software\Eclipse Workspace\JsfOnGae\war\WEB-INF/appengine-web.xml
16 May, 2013 8:10:15 AM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
INFO: Successfully processed D:\Software\Eclipse Workspace\JsfOnGae\war\WEB-INF/web.xml
16 May, 2013 8:10:15 AM com.google.apphosting.utils.jetty.JettyLogger info
INFO: jetty-6.1.x
16 May, 2013 8:10:16 AM com.sun.faces.config.ConfigureListener contextInitialized
INFO: Initializing Mojarra 2.1.7 (SNAPSHOT 20120206) for context ”
16 May, 2013 8:10:16 AM com.sun.faces.spi.InjectionProviderFactory createInstance
INFO: JSF1048: PostConstruct/PreDestroy annotations present. ManagedBeans methods marked with these annotations will have said annotations processed.
16 May, 2013 8:10:17 AM com.sun.faces.config.ConfigureListener contextInitialized
SEVERE: Critical error during deployment:
com.sun.faces.config.ConfigurationException: java.util.concurrent.ExecutionException: javax.faces.FacesException: java.net.URISyntaxException: Illegal character in opaque part at index 29: jar:file:/D:/Software/Eclipse Workspace/JsfOnGae/war/WEB-INF/lib/jsf-impl-2.1.7.jar!/META-INF/mojarra_ext.taglib.xml
at com.sun.faces.config.ConfigManager.getConfigDocuments(ConfigManager.java:662)
at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:362)
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:225)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:224)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:191)
at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:239)
at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:146)
at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:173)
at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)
at com.google.appengine.tools.development.DevAppServerMain.(DevAppServerMain.java:120)
at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:96)
Caused by: java.util.concurrent.ExecutionException: javax.faces.FacesException: java.net.URISyntaxException: Illegal character in opaque part at index 29: jar:file:/D:/Software/Eclipse Workspace/JsfOnGae/war/WEB-INF/lib/jsf-impl-2.1.7.jar!/META-INF/mojarra_ext.taglib.xml
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at com.sun.faces.config.ConfigManager.getConfigDocuments(ConfigManager.java:648)
… 20 more
Caused by: javax.faces.FacesException: java.net.URISyntaxException: Illegal character in opaque part at index 29: jar:file:/D:/Software/Eclipse Workspace/JsfOnGae/war/WEB-INF/lib/jsf-impl-2.1.7.jar!/META-INF/mojarra_ext.taglib.xml
at com.sun.faces.config.configprovider.MetaInfFaceletTaglibraryConfigProvider.pruneURLs(MetaInfFaceletTaglibraryConfigProvider.java:146)
at com.sun.faces.config.configprovider.MetaInfFaceletTaglibraryConfigProvider.getResources(MetaInfFaceletTaglibraryConfigProvider.java:99)
at com.sun.faces.config.ConfigManager$URITask.call(ConfigManager.java:1177)
at com.sun.faces.config.ConfigManager$URITask.call(ConfigManager.java:1146)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at com.sun.faces.config.ConfigManager.getConfigDocuments(ConfigManager.java:638)
… 20 more
Caused by: java.net.URISyntaxException: Illegal character in opaque part at index 29: jar:file:/D:/Software/Eclipse Workspace/JsfOnGae/war/WEB-INF/lib/jsf-impl-2.1.7.jar!/META-INF/mojarra_ext.taglib.xml
at java.net.URI$Parser.fail(URI.java:2809)
at java.net.URI$Parser.checkChars(URI.java:2982)
at java.net.URI$Parser.parse(URI.java:3019)
at java.net.URI.(URI.java:578)
at com.sun.faces.config.configprovider.MetaInfFaceletTaglibraryConfigProvider.pruneURLs(MetaInfFaceletTaglibraryConfigProvider.java:144)
… 26 more
16 May, 2013 8:10:17 AM com.google.apphosting.utils.jetty.JettyLogger warn
WARNING: Failed startup of context com.google.appengine.tools.development.DevAppEngineWebAppContext@1d13272{/,D:\Software\Eclipse Workspace\JsfOnGae\war}
java.lang.RuntimeException: com.sun.faces.config.ConfigurationException: java.util.concurrent.ExecutionException: javax.faces.FacesException: java.net.URISyntaxException: Illegal character in opaque part at index 29: jar:file:/D:/Software/Eclipse Workspace/JsfOnGae/war/WEB-INF/lib/jsf-impl-2.1.7.jar!/META-INF/mojarra_ext.taglib.xml
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:292)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:224)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:191)
at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:239)
at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:146)
at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:173)
at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)
at com.google.appengine.tools.development.DevAppServerMain.(DevAppServerMain.java:120)
at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:96)
Caused by: com.sun.faces.config.ConfigurationException: java.util.concurrent.ExecutionException: javax.faces.FacesException: java.net.URISyntaxException: Illegal character in opaque part at index 29: jar:file:/D:/Software/Eclipse Workspace/JsfOnGae/war/WEB-INF/lib/jsf-impl-2.1.7.jar!/META-INF/mojarra_ext.taglib.xml
at com.sun.faces.config.ConfigManager.getConfigDocuments(ConfigManager.java:662)
at com.sun.faces.config.ConfigManager.initialize(ConfigManager.java:362)
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:225)
… 18 more
Caused by: java.util.concurrent.ExecutionException: javax.faces.FacesException: java.net.URISyntaxException: Illegal character in opaque part at index 29: jar:file:/D:/Software/Eclipse Workspace/JsfOnGae/war/WEB-INF/lib/jsf-impl-2.1.7.jar!/META-INF/mojarra_ext.taglib.xml
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at com.sun.faces.config.ConfigManager.getConfigDocuments(ConfigManager.java:648)
… 20 more
Caused by: javax.faces.FacesException: java.net.URISyntaxException: Illegal character in opaque part at index 29: jar:file:/D:/Software/Eclipse Workspace/JsfOnGae/war/WEB-INF/lib/jsf-impl-2.1.7.jar!/META-INF/mojarra_ext.taglib.xml
at com.sun.faces.config.configprovider.MetaInfFaceletTaglibraryConfigProvider.pruneURLs(MetaInfFaceletTaglibraryConfigProvider.java:146)
at com.sun.faces.config.configprovider.MetaInfFaceletTaglibraryConfigProvider.getResources(MetaInfFaceletTaglibraryConfigProvider.java:99)
at com.sun.faces.config.ConfigManager$URITask.call(ConfigManager.java:1177)
at com.sun.faces.config.ConfigManager$URITask.call(ConfigManager.java:1146)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at com.sun.faces.config.ConfigManager.getConfigDocuments(ConfigManager.java:638)
… 20 more
Caused by: java.net.URISyntaxException: Illegal character in opaque part at index 29: jar:file:/D:/Software/Eclipse Workspace/JsfOnGae/war/WEB-INF/lib/jsf-impl-2.1.7.jar!/META-INF/mojarra_ext.taglib.xml
at java.net.URI$Parser.fail(URI.java:2809)
at java.net.URI$Parser.checkChars(URI.java:2982)
at java.net.URI$Parser.parse(URI.java:3019)
at java.net.URI.(URI.java:578)
at com.sun.faces.config.configprovider.MetaInfFaceletTaglibraryConfigProvider.pruneURLs(MetaInfFaceletTaglibraryConfigProvider.java:144)
… 26 more
16 May, 2013 8:10:17 AM com.google.apphosting.utils.jetty.JettyLogger info
INFO: Started [email protected]:8888
16 May, 2013 8:10:17 AM com.google.appengine.tools.development.DevAppServerImpl start
INFO: The server is running at http://localhost:8888/
16 May, 2013 8:10:17 AM com.google.appengine.tools.development.DevAppServerImpl start
INFO: The admin console is running at http://localhost:8888/_ah/admin

Sanyog Barve
10 years ago

Dear Sir,
Getting this error while running the application.

java.lang.NoClassDefFoundError: com/sun/faces/context/ApplicationMap

Log for reference –

5 May, 2013 6:56:07 PM com.google.apphosting.utils.jetty.JettyLogger info
INFO: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
5 May, 2013 6:56:07 PM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
INFO: Successfully processed D:\Software\Eclipse Workspace\jsfgwt\war\WEB-INF/appengine-web.xml
5 May, 2013 6:56:07 PM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
INFO: Successfully processed D:\Software\Eclipse Workspace\jsfgwt\war\WEB-INF/web.xml
5 May, 2013 6:56:08 PM com.google.apphosting.utils.jetty.JettyLogger warn
WARNING: failed com.google.appengine.tools.development.DevAppEngineWebAppContext@13d1402{/,D:\Software\Eclipse Workspace\jsfgwt\war}: java.lang.NoClassDefFoundError: com/sun/faces/context/ApplicationMap
5 May, 2013 6:56:08 PM com.google.apphosting.utils.jetty.JettyLogger warn
WARNING: failed JettyContainerService$ApiProxyHandler@a1aa85: java.lang.NoClassDefFoundError: com/sun/faces/context/ApplicationMap
5 May, 2013 6:56:08 PM com.google.apphosting.utils.jetty.JettyLogger warn
WARNING: Error starting handlers
java.lang.NoClassDefFoundError: com/sun/faces/context/ApplicationMap
at com.sun.faces.config.InitFacesContext$ServletContextAdapter.getApplicationMap(InitFacesContext.java:297)
at com.sun.faces.util.Util.getApplicationMap(Util.java:144)
at com.sun.faces.util.Util.getPatternCache(Util.java:160)
at com.sun.faces.util.Util.split(Util.java:629)
at com.sun.faces.config.WebConfiguration.getOptionValue(WebConfiguration.java:290)
at com.sun.faces.config.WebConfiguration.(WebConfiguration.java:139)
at com.sun.faces.config.WebConfiguration.getInstance(WebConfiguration.java:194)
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:163)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:224)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:205)
at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:249)
at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:157)
at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply(DevAppServerMain.java:333)
at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)
at com.google.appengine.tools.development.DevAppServerMain.(DevAppServerMain.java:269)
at com.google.appengine.tools.development.DevAppServerMain.main(DevAppServerMain.java:245)
Caused by: java.lang.ClassNotFoundException: com.sun.faces.context.ApplicationMap
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at com.google.appengine.tools.development.IsolatedAppClassLoader.loadClass(IsolatedAppClassLoader.java:207)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
… 26 more
5 May, 2013 6:56:08 PM com.google.appengine.tools.development.DevAppServerImpl start
INFO: The server is running at http://localhost:8888/
5 May, 2013 6:56:08 PM com.google.appengine.tools.development.DevAppServerImpl start
INFO: The admin console is running at http://localhost:8888/_ah/admin

Klaus
11 years ago

Thanks for this tutorial – works great!
I’ve just one minor issue left after following it:

http://localhost:8888/hello.jsf looks perfect,
but
http://localhost:8888/hello.xhtml doesn’t interpret the facelets. According to the servlet-mappings (from your code above) both should work, right? Trying around I get all file-extensions working, but not .xhtml .

Oh, just got the idea about trying it out at http://mkyong-jsf2gae.appspot.com/hello.xhtml – same problem there.
Any ideas?

But anyway, even thoug my preferred file ending is .xhtml I’m fine going for anything else. Big thanks for this example!

Klaus
11 years ago
Reply to  Klaus

Found the answer in http://stackoverflow.com/questions/10668117/google-app-engine-jsf-facelets-why-not-xhtml-as-a-url-pattern

Following is required in the appengine-web.xml for .xhtml-files to be not interpreted as static content:

<static-files>
    <exclude path="/**.xhtml" />
</static-files>
Krasen
11 years ago

those with javax.faces-2.1.7.jar or higher have to gate javax.faces source and from there to get the WebConfiguration.java and package path. Mine is com.sun.faces.config. So i comment these two methods and also comment their usage. It was only to rows

cheg3
11 years ago

I would like to know if this works with latest versions of gae and jsf. Thanks.

James
11 years ago

i am getting this error when i click the welcome me button “Unable to find matching navigation case with from-view-id ‘/hello.xhtml’ for action ‘welcome’ with outcome ‘welcome”
please help me

GC
11 years ago

where do I find el-ri-1.0.jar

Andre
11 years ago

Hello! great tutorial!

I’m facing a issue when I go Run As > Web Application (localhost), its the following exception:

Jan 9, 2013 12:43:08 AM com.google.apphosting.utils.jetty.JettyLogger info
INFO: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
Jan 9, 2013 12:43:08 AM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
INFO: Successfully processed C:\workarea\workspaces\olecram\teste\war\WEB-INF/appengine-web.xml
Jan 9, 2013 12:43:08 AM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
INFO: Successfully processed C:\workarea\workspaces\olecram\teste\war\WEB-INF/web.xml
Jan 9, 2013 12:43:11 AM com.google.apphosting.utils.jetty.JettyLogger warn
WARNING: EXCEPTION
java.lang.ClassNotFoundException: com.google.api.server.spi.SystemServiceServlet
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at com.google.appengine.tools.development.IsolatedAppClassLoader.loadClass(IsolatedAppClassLoader.java:176)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

seems to be related with SDK I’m using… appengine-java-sdk-1.6.3.1

Why its happening? =/

thanks
André

David
11 years ago

Hi mkyong

I’m new to JSF on GAE and I followed your great tutorial step by step by simply reproducing what you have done. It works perfectly in local using Eclipse, but It doesn’t work on GAE as you can see at http://primaprovadavide.appspot.com/hello.jsf.

When the “welcome me” button is pressed, when the page “welcome” is shown the bean misses its value.
Please can you give me an opinion in what could be wrong?

Thanks in advance
David

Shilendra
11 years ago

I am using this link for google app engine with jsf so i am getting this error when i run the on eclipse so give the desire solution

Error is
java.lang.ClassNotFoundException: javax.faces.webapp.FacesServlet
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
at com.google.appengine.tools.development.IsolatedAppClassLoader.loadClass
(IsolatedAppClassLoader.java:207)
at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
at org.mortbay.util.Loader.loadClass(Loader.java:91)
at org.mortbay.util.Loader.loadClass(Loader.java:71)
at org.mortbay.jetty.servlet.Holder.doStart(Holder.java:73)
at org.mortbay.jetty.servlet.ServletHolder.doStart(ServletHolder.java:242)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:685)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:140)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:224)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at com.google.appengine.tools.development.JettyContainerService.startContainer
(JettyContainerService.java:197)
at com.google.appengine.tools.development.AbstractContainerService.startup
(AbstractContainerService.java:241)
at com.google.appengine.tools.development.DevAppServerImpl.start
(DevAppServerImpl.java:148)
at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply
(DevAppServerMain.java:310)
at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)
at com.google.appengine.tools.development.DevAppServerMain.
(DevAppServerMain.java:249)
at com.google.appengine.tools.development.DevAppServerMain.main
(DevAppServerMain.java:225)

Sep 06, 2012 10:58:55 AM com.google.appengine.tools.development.ApiProxyLocalImpl log
SEVERE: javax.servlet.ServletContext log: unavailable
javax.servlet.UnavailableException: javax.faces.webapp.FacesServlet
at org.mortbay.jetty.servlet.Holder.doStart(Holder.java:79)
at org.mortbay.jetty.servlet.ServletHolder.doStart(ServletHolder.java:242)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:685)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:140)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:224)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at com.google.appengine.tools.development.JettyContainerService.startContainer
(JettyContainerService.java:197)
at com.google.appengine.tools.development.AbstractContainerService.startup
(AbstractContainerService.java:241)
at com.google.appengine.tools.development.DevAppServerImpl.start
(DevAppServerImpl.java:148)
at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply
(DevAppServerMain.java:310)
at com.google.appengine.tools.util.Parser$ParseResult.applyArgs(Parser.java:48)
at com.google.appengine.tools.development.DevAppServerMain.
(DevAppServerMain.java:249)
at com.google.appengine.tools.development.DevAppServerMain.main
(DevAppServerMain.java:225)

Sep 06, 2012 10:58:55 AM com.google.apphosting.utils.jetty.JettyLogger warn
WARNING: failed Faces Servlet: java.lang.NullPointerException
Sep 06, 2012 10:58:55 AM com.google.apphosting.utils.jetty.JettyLogger warn
WARNING: Failed startup of context
com.google.appengine.tools.development.DevAppEngineWebAppContext@1dc94ea
{/,C:\Documents and Settings\Shilendra Sharma\workspace\Shilu\war}
java.lang.NullPointerException
at java.lang.Class.isAssignableFrom(Native Method)
at org.mortbay.jetty.servlet.ServletHolder.doStart(ServletHolder.java:256)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:685)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:140)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:224)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
at com.google.appengine.tools.development.JettyContainerService.startContainer
(JettyContainerService.java:197)
at com.google.appengine.tools.development.AbstractContainerService.startup
(AbstractContainerService.java:241)
at com.google.appengine.tools.development.DevAppServerImpl.start
(DevAppServerImpl.java:148)
at com.google.appengine.tools.development.DevAppServerMain$StartAction.apply
(DevAppServerMain.java:310)
at com.google.appengine.tools.util.Parser$ParseResult.applyArgs
(Parser.java:48)
at com.google.appengine.tools.development.DevAppServerMain.
(DevAppServerMain.java:249)
at com.google.appengine.tools.development.DevAppServerMain.main
(DevAppServerMain.java:225)

so any one help me for it work properly

Sujay
11 years ago

Thanks for the tutorial Mkyong. I am new to jsf and as yet I have not figured out which part of the code handled the “welcome” action generated by the ‘Welcome Me” button to change the page to welcome.xhtml. Would you be able to clarify that?

raskanskyz
11 years ago

Thanks a lot for ALL your tuts, they are very helpful!!
one short question, after following this tut i was able to run the project on localhost, but after trying to deploy it on Google App Engine i get error 500:
http://raskanskyjsftest.appspot.com/

am I the only one facing this problem?

Keith
11 years ago

Thanks for the tutorial but when i run on the server, it got failure because it requires the tag in the appengine-web.xml so I added it in. The page was loaded but the text box and button didn’t get render

I am using jsf-api and jsf-impl 2.1.9 from com.sun. so is there any something wrong will my configuration

p.m.verma
11 years ago

Thanks a lot for your tutorial..
would u please to upload (google apps engine + jsf 2.0 + Spring bean) example that contains CRUD Operation.

thank you very much.

Rene
11 years ago

Great, please add support to jpa to this project…thanks advance

EHarpham
11 years ago

Hi thanks for the great amount of resources on your site. I followed this tutorial however I am using app engine 1.6.5, JDK 1.7 and the javax.faces-2.1.7.jar.

I get the following error:

//...
WARNING: Error starting handlers
java.lang.VerifyError: Expecting a stackmap frame at branch target 36 in method com.sun.faces.config.WebConfiguration.getServletContextName()Ljava/lang/String; at offset 10
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Unknown Source)
	at com.google.appengine.tools.development.agent.runtime.RuntimeHelper.checkRestricted(RuntimeHelper.java:69)
	at com.google.appengine.tools.development.agent.runtime.Runtime.checkRestricted(Runtime.java:64)
	at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:163)
	at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548)
	at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
	at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1250)
	at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517)
	at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:467)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
	at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
	at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
	at org.mortbay.jetty.Server.doStart(Server.java:224)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50)
	at com.google.appengine.tools.development.JettyContainerService.startContainer(JettyContainerService.java:196)
	at com.google.appengine.tools.development.AbstractContainerService.startup(AbstractContainerService.java:239)
	at com.google.appengine.tools.development.DevAppServerImpl.start(DevAppServerImpl.java:146)
	at com.google.appengine.tools.development.gwt.AppEngineLauncher.start(AppEngineLauncher.java:97)
	at com.google.gwt.dev.DevMode.doStartUpServer(DevMode.java:509)
	at com.google.gwt.dev.DevModeBase.startUp(DevModeBase.java:1068)
	at com.google.gwt.dev.DevModeBase.run(DevModeBase.java:811)
	at com.google.gwt.dev.DevMode.main(DevMode.java:311)

May 07, 2012 4:05:53 AM com.google.appengine.tools.development.DevAppServerImpl start
INFO: The server is running at http://localhost:8888/
May 07, 2012 4:05:53 AM com.google.appengine.tools.development.DevAppServerImpl start
INFO: The admin console is running at http://localhost:8888/_ah/admin

Any help would be greatly appreciated.

Thanks

Spidi
11 years ago

Great job!

Brumla
11 years ago

Many thanks for this tutorial!