I've created a web application that opens up pages inside an iFrame on the main page. Each iFrame is viewable via a tab on the page and uses JSF2.2 with Mojarra view state beans to populate the page.
This works fine when I open up something under 10 tabs; but when I try to open up more, the beans that held the first pages are destroyed and get recreated when I make any calls to the bean thus losing any prior changes the user may have made.
I'm using Apache Tomcat 7 with Catalina, and this issue is happening on my XP and Windows Server 2008 machines.
This is my current 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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>SCMPage</display-name>
<filter>
<filter-name>IEFilter</filter-name>
<filter-class>com.Filter.IEFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>IEFilter</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>server</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<listener>
<listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>
<context-param>
<description>Location of the Config file for the web application and the engine</description>
<param-name>configFile</param-name>
<param-value>C:\Users\ravil7148084\workspace\SCMPage\config.properties</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.numberOfViewsInSession</param-name>
<param-value>30</param-value>
</context-param>
<context-param>
<param-name>com.sun.faces.numberOfLogicalViews</param-name>
<param-value>30</param-value>
</context-param>
</web-app>
I've also tried setting this environment variable thinking that it might be a memory limit on tomcat's end, but it didn't make a difference
set JAVA_OPTS=-Dfile.encoding=UTF-8 -Xms128m -Xmx1024m -XX:PermSize=64m -XX:MaxPermSize=256m
Any help would be appreciated!
You've there just a severe design error. To include server side page fragments, you're using 90's style iframes instead of true server side include components. Each iframe has its own view state and won't reuse the main document's view state. Just replace all those <iframe> things by <ui:include> and world should be well.
See also:
How to include another XHTML in XHTML using JSF 2.0 Facelets?
com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews
Related
I'm trying to integrate Spring-Security 5.1.4.RELEASE in an already working JSF 2.2-Primefaces 6.1 APP in order to securize it.
When I try to access to the protected page "logged.xhtml" spring triggers and takes me to the login page "login.xhtml", so Spring seems to work fine.
The problem is that once I have configured Spring all Primefaces p:commandLink stop working (and some "Action" methods in other Primefaces components). The JSF Sun components ( xmlns:h="http://java.sun.com/jsf/html" ) like "h:outputLink" continue working but a h:commmandButton with f:ajax fails too.
I don't see why the Primefaces components or the JSF ones with f:ajaxare broken...
This is my faces-config.xml:
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
<resource-bundle>
<base-name>messages</base-name>
<var>msg</var>
</resource-bundle>
<message-bundle>messages</message-bundle>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>en</supported-locale>
<supported-locale>es</supported-locale>
</locale-config>
</application>
This is my WEB.XML:
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Production</param-value>
</context-param>
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
This is my security initializer:
public class SecurityWebInitializer extends AbstractSecurityWebApplicationInitializer{
}
This is my security configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser(User.withDefaultPasswordEncoder().username("admin").password("1234").roles("ADMIN").build());
auth.inMemoryAuthentication().withUser(User.withDefaultPasswordEncoder().username("usu").password("1234").roles("NORMAL").build());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/logged.xhtml").authenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login.xhtml").defaultSuccessUrl("/logged.xhtml").failureUrl("/error.xhtml")
.permitAll()
.and()
.logout().logoutUrl("/logout")
.permitAll();
}
}
EDIT:
After checking the browser console I see that every time I press any Primefaces link/button the following error appears:
XHR POST localhost:8080/springtest/index.xhtml [HTTP/1.1 403 Forbidden 2ms]
I believe that there is a problem with the permissions but after reviewing my SecurityConfig file I don't see the problem.
The following line should restrict the access to the protected page:
.antMatchers("/logged.xhtml").authenticated()
And this line should allow ALL trafic in the rest of pages:
.anyRequest().permitAll()
What I'm doing wrong?
Any suggestion?
Thanks in advance!
PS: let me know whether you need any further information about the project
I want to answer this question in case someone else needs it:
When using TEMPLATES for composing a JSF page ALWAYS put the "csrf" token in every single form on it. It is not enough putting the token in one place.
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
When I right click index.xhtml and go to "Run On Server" I get a 404 error.
Below I will show my web.xml, as well as some of the error messages I get. This is just a basic hello world app, nothing special yet.
My index.xhtml is in the webcontent folder.
Using eclipse luna and tomcat 8. JSF 2.2
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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>SpecificationGeneratorDataEntryTool</display-name>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>resources.application</param-value>
</context-param>
<context-param>
<description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<context-param>
<description>
This parameter tells MyFaces if javascript code should be allowed in
the rendered HTML output.
If javascript is allowed, command_link anchors will have javascript code
that submits the corresponding form.
If javascript is not allowed, the state saving info and nested parameters
will be added as url parameters.
Default is 'true'</description>
<param-name>org.apache.myfaces.ALLOW_JAVASCRIPT</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<description>
If true, rendered HTML code will be formatted, so that it is 'human-readable'
i.e. additional line separators and whitespace will be written, that do not
influence the HTML code.
Default is 'true'</description>
<param-name>org.apache.myfaces.PRETTY_HTML</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>org.apache.myfaces.DETECT_JAVASCRIPT</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<description>
If true, a javascript function will be rendered that is able to restore the
former vertical scroll on every request. Convenient feature if you have pages
with long lists and you do not want the browser page to always jump to the top
if you trigger a link or button action that stays on the same page.
Default is 'false'
</description>
<param-name>org.apache.myfaces.AUTO_SCROLL</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
</web-app>
Error output:
SEVERE: Exception sending context initialized event to listener instance of class org.apache.myfaces.webapp.StartupServletContextListener
java.lang.NoClassDefFoundError: org/apache/commons/digester/Digester
at org.apache.myfaces.config.impl.digester.DigesterFacesConfigUnmarshallerImpl.<init>(DigesterFacesConfigUnmarshallerImpl.java:44)
SEVERE: Exception sending context initialized event to listener instance of class org.apache.myfaces.webapp.StartupServletContextListener
java.lang.NoClassDefFoundError: org/apache/commons/digester/Digester
SEVERE: Exception sending context destroyed event to listener instance of class org.apache.myfaces.webapp.StartupServletContextListener
java.lang.IllegalStateException: No Factories configured for this Application. This happens if the faces-initialization does not work at all - make sure that you properly include all configuration settings necessary for a basic faces application and that all the necessary libs are included. Also check the logging output of your web application and your container for any exceptions!
If you did that and find nothing, the mistake might be due to the fact that you use some special web-containers which do not support registering context-listeners via TLD files and a context listener is not setup in your web.xml.
A typical config looks like this;
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
at javax.faces.FactoryFinder._getFactory(FactoryFinder.java:305)
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:225)
at org.apache.myfaces.context.servlet.FacesContextImplBase.getApplication(FacesContextImplBase.java:169)
at org.apache.myfaces.webapp.AbstractFacesInitializer._dispatchApplicationEvent(AbstractFacesInitializer.java:329)
at org.apache.myfaces.webapp.AbstractFacesInitializer.destroyFaces(AbstractFacesInitializer.java:364)
at org.apache.myfaces.webapp.StartupServletContextListener.contextDestroyed(StartupServletContextListener.java:167)
at org.apache.catalina.core.StandardContext.listenerStop(StandardContext.java:4906)
at org.apache.catalina.core.StandardContext.stopInternal(StandardContext.java:5545)
at org.apache.catalina.util.LifecycleBase.stop(LifecycleBase.java:221)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:149)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
if 404 error means resource is not found that means your first welcome page is not load please check the name of servlet class in xml and please proper path in welcome-file
I have a JSF Primefaces Web App that has needs to be redirected to Login page when the session expires.
if (session == null)
{
response.sendRedirect(request.getContextPath() + "/Login.xhtml?faces-redirect=true");
}
But after the time out, the page is not redirecting and if I do a refresh, it redirects with the redirect=true. How can I overcome this?
My directory structure is
-Login.xhtml
-app/index.xhtml
-app/settings.xhtml
Below is my web.xml :
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
<session-config>
<session-timeout>
1
</session-timeout>
</session-config>
<filter>
<filter-name>NoCacheFilter</filter-name>
<filter-class>com.web.app.NoCacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>NoCacheFilter</filter-name>
<url-pattern>/app/*</url-pattern>
</filter-mapping>
I was going through one of the books on JSF (JavaSever Faces - Introduction by Example) and I found the following excerpt
Prior to JSF 2.0, in order to enable the JSF servlet to translate the XHTML page, you needed to ensure that the
web.xml file contained a servlet element indicating the javax.faces.webapp.FacesServlet class and its associated
servlet-mapping URL. Since the release of JSF 2.0, if using a Servlet 3.x container, the FacesServlet is automatically
mapped for you, so there is no requirement to adjust the web.xml configuration.
I decided to try it out, but did NOT work and getting 404 error.
web.xml
<!-- Commenting this out in Glassfish server based on the book's guidelines -->
<!--
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
-->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>faces/index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
Prior to moving to Glassfish 4.x I already had this working on Tomcat 8.
The weird part is as soon as I uncomment the FacesServlet mapping in deployment desriptor everything works great and I do not get 404.
Is Glassfish 4.x a Servlet 3.x container?
Am I doing something wrong or are the book guidelines incorrect?
<?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_3_0.xsd" version="3.0">
<display-name>basic setup</display-name>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.faces</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/index.faces</welcome-file>
</welcome-file-list>
It should be accessed from domain like www.example.com without showing www.example.com/basicsetup.
It would be wise to go through Tomcat 7 server documentation on the issue, especially the following part, recited below for you (emphasis mine:
The Context element represents a web application, which is run within a particular virtual host. Each web application is based on a Web Application Archive (WAR) file ...
The web application used to process each HTTP request is selected by Catalina based on matching the longest possible prefix of the Request URI against the context path of each defined Context.
You may define as many Context elements as you wish. Each such Context MUST have a unique context name within a virtual host. The context path does not need to be unique (see parallel deployment below). In addition, a Context must be present with a context path equal to a zero-length string. This Context becomes the default web application for this virtual host, and is used to process all requests that do not match any other Context's context path.
So, to sum it up: you need to have <Context path="" ... /> defined as described here.
You can find the needed details in the answer to HOWTO set the context path of a web application in Tomcat 7.0 question.