JSF with Prettyfaces returning cached error page - jsf-2.2

I'm developing a web application using JSF 2.2 and tomcat 8, but I'm facing a weird problem...
For example, I have a home page which will call a managedbean, connect to databse and return response. Everything is working, but, if some error happens, it's going to redirect to my error page (500.xhtml, which I set up in my web.xml file).
After the error happens, I fixed the error, but I can't access the home page anymore, it always redirect me for my 500 page. If, i change the the home page for something like home?anything it call my managebean again and works. Also, if i change the server, from localhost to my ip or 127.1.0.0, it also makes the request again.
Following, my web.xml. Also, I'm using prettyfaces 3.4, don't know if it's related but...
Tomcat server.xml and web.xml is default config.
web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>JSF Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JSF Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>home.xhtml</welcome-file>
</welcome-file-list>
<context-param>
<param-name>com.sun.faces.defaultResourceMaxAge</param-name>
<param-value>3628800000</param-value> <!-- 6 weeks. -->
</context-param>
<context-param>
<param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
<param-value>true</param-value>
</context-param>
<mime-mapping>
<extension>xhtml</extension>
<mime-type>application/xml</mime-type>
</mime-mapping>
<mime-mapping>
<extension>jsp</extension>
<mime-type>application/xml</mime-type>
</mime-mapping>
<error-page>
<error-code>403</error-code>
<location>/error/403.xhtml</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/error/404.xhtml</location>
</error-page>
<error-page>
<error-code>405</error-code>
<location>/error/405.xhtml</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/error/500.xhtml</location>
</error-page>
<error-page>
<error-code>503</error-code>
<location>/error/503.xhtml</location>
</error-page>
Prettyfaces:
#RewriteConfiguration
public class ConfigurationProvider extends HttpConfigurationProvider {
#Override
public Configuration getConfiguration(final ServletContext context) {
return ConfigurationBuilder.begin()
.addRule(Join.path("/home").to("/"))
.addRule(Join.path("/home").to("/home.xhtml").withInboundCorrection())
.addRule(Join.path("/company").to("/company.xhtml").withInboundCorrection())
.addRule(Join.path("/portfolio").to("/portfolio.xhtml").withInboundCorrection())
.addRule(Join.path("/contact").to("/contact.xhtml").withInboundCorrection())
.addRule(Join.path("/admin/login").to("/admin/login.xhtml").withInboundCorrection())
.addRule(Join.path("/admin/recovery").to("/admin/recovery.xhtml").withInboundCorrection())
.addRule(Join.path("/403").to("/error/403.xhtml").withInboundCorrection())
.addRule(Join.path("/404").to("/error/404.xhtml").withInboundCorrection())
.addRule(Join.path("/405").to("/error/405.xhtml").withInboundCorrection())
.addRule(Join.path("/500").to("/error/500.xhtml").withInboundCorrection())
.addRule(Join.path("/503").to("/error/503.xhtml").withInboundCorrection());
}
#Override
public int priority() {
return 10;
}
}
Looking at firefox debugger, network tab shows there was a request to home page (which was cached) and the a redirect with 301 code to 500.
#EDIT
It seems to be something with prettyfaces.
I just remove it, and tested with chrome browser (without cache), after the error, i can access the page again. Then, I activate prettyfaces again, and the problem returned.
Any idea why that?

Related

My welcome-file is returning an empty page in Open Liberty

On Open Liberty 21.0.0.6., instead of presenting my welcome JSF page, my browser returns empty content when I point it to http://<host>:<port>/<ctxRoot>,
web.xml
<web-app id="WebApp_ID" version="4.0"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd">
<display-name>MyJSF</display-name>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
</web-app>
and a feature set of:
server.xml
<server>
<featureManager>
<feature>jaxrs-2.1</feature>
<feature>cdi-2.0</feature>
<feature>jpa-2.2</feature>
<feature>jdbc-4.3</feature>
<feature>jsf-2.3</feature>
<feature>mpHealth-3.0</feature>
</featureManager>
ADDITIONAL INFO
I also have some other stuff in my app like JPA and JAX-RS.
ROOT CAUSE - JAX-RS application with "/" application path
In my case the problem is that I had a JAX-RS Application configured to use: #ApplicationPath("/") which was colliding with my goal of having the "/" application path serve up the welcome-file.
SOLUTION
Move the JAX-RS app to its own path within the WAR, e.g:
import javax.ws.rs.core.Application;
#ApplicationPath("/api")
public class TestApp extends Application { }
THOUGHTS
This was easy to stumble into by taking an existing simple JAX-RS app using "/" as the app path, and then adding JSF to it. Then I thought I was having trouble with the JSF implementation.

How do you make invalid urls ending in .jsp use the spring 404 page?

404 pages are working properly across my site for all url's unless it ends in .jsp. In that case I get the generic jboss 404 page instead of my styled Spring 404 page.
I have the following in my web.xml:
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/error/404.jsp</location>
</error-page>
Edited with full web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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">
<servlet>
<servlet-name>mainServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mainServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/spring/root-context.xml,
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<welcome-file-list>
<welcome-file></welcome-file>
</welcome-file-list>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<error-page>
<error-code>400</error-code>
<location>/WEB-INF/error/400.jsp</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/WEB-INF/error/403.jsp</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/error/404.jsp</location>
</error-page>
<error-page>
<error-code>405</error-code>
<location>/WEB-INF/error/405.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/WEB-INF/error/error.jsp</location>
</error-page>
<context-param>
<param-name>defaultHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>
</web-app>
The problem is probably that your web.xml is pointing directly to your jsp pages instead of directing to a spring controller that can then point to the appropriate view.
I'd be curious to also see your rootContext.xml to see how you have your view resolver set up. Cause maybe spring is getting confused... There's only a couple ways that the App Container (JBoss) would end up handling the error, and that is if either the request doesn't even match the Spring context servlet or if there is no error handler for the error type generated (is it possible that the attempt to handle "asdlfasdf.jsp" ends up causing another type of exception that is not getting logged and then is getting tossed up to JBoss and handled as a 404?).
But so you have something to compare to - Here's how I have mine set up:
I have a single error.jsp page in my views directory and set up the view resolver similar to the following:
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
Then, I have a base PageController class that I extend for all my other "user facing" controller classes. That class has a method that handles the "/error/404", "/error/403" style error page patterns:
#RequestMapping(value = "/error/{code}")
public String errorPage(Principal principal, Model model, #PathVariable("code") int code) {
model.addAttribute("code", code);
return "error";
}
Then, I set up the web.xml similar to yours, only redirecting to the spring controller endpoints along with the appropriate code:
<error-page>
<error-code>404</error-code>
<location>/error/404</location>
</error-page>
<error-page>
<error-code>403</error-code>
<location>/error/403</location>
</error-page>
Now, I don't know if this is the best way, but it works really well for me. The web container routes those error types to the /error/code page which is just calling a controller method and then the controller method produces the error.jsp page (by returning the view name "error").
Since it puts the error code in the model, I have a single jsp that handles multiple error types, I just put a conditional that renders a different user message depending on the error code. In other words, "Page Not Found :(" vs "You aren't authorized to view this page!"
And then I do this in my spring security config to make sure an unauthenticated user can see the error page (you've probably got this part already since you can see the jsp pages):
<http pattern="/error/**" security="none" />
I combine this with the annotation style exception handlers to do all my server exception handling (handling data requests with a json error response and html/view requests with html error pages) because you can just annotate a controller method to handle Exception or RuntimeException. I'd recommend you check out this method as well because it is very powerful and makes it dramatically easier to log and handle exceptions gracefully:
#ExceptionHandler(Exception.class)
public ModelAndView exceptionHandler(Exception e){
ModelAndView modelAndView = new ModelAndView();
modelAndView.getModelMap().addAttribute("code", HttpStatus.INTERNAL_SERVER_ERROR);
modelAndView.setViewName("error");
logger.error("Error handling page request.", e);
return modelAndView;
}
This is also a good way to make sure you have a chance to log exceptions that go through your controllers without having to put exception handling into every single one.
I made two base classes... one for my page controllers and one for my rest data controllers. The base page controller return the jsp view that renders a nice error page for the user. The base rest data controller returns a json message with the error information in the model and then the jsp will print the full stack or just a generic error depending on if the server is running in development or production mode.

definition of url in web.xml and ajax

i have a problem mapping my url to reach the servlet class. i'm calling the servlet by getJSON function but the simple sysout doesnt work.
in my jsp i put:
$.getJSON('getMediaListByMediaType/options?dd=' + ddId + '&val=' + $('#mediaType:selected').text(), //some other codes here)
in my web.xml, i have the following:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<javaee:display-name>MediaScratch</javaee:display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>dropDownServlet</servlet-name>
<servlet-class>jp.co.aeonbank.servlets.LoadDropDownServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dropDownServlet</servlet-name>
<url-pattern>/getMediaListByMediaType/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>5</session-timeout>
</session-config>
as i checked in google developers' tool, it actually can get the correct url but says it is not found
http://IpAddressHere/ProjectNameHere/getMediaListByMediaType/options?dd=mediaNo&val=DVD-R
any idea why? thanks.
Resolved! I figured out that the reason why it cannot reach the servlet is beacuse the FilterMapping for struts2 catches all the url that's why servlet-mapping became useless. In order to prevent the process of entering in default struts2 filter, i have defined this piece of code on my struts.xml
<constant name="struts.action.excludePattern" value="/getMediaListByMediaType/.*"/>
Now it can successfully get the JSON from my servlet class.

JSF new website creation

I have a JSF project and I already have an index.xhtml page which is working fine. When I try to add another XHTML page, for some reason it is not connected to my session scoped managed bean. I add the code in my new page but it doesn't work like my index.xhtml. I even copy and pasted the code from index and it still does not work. Any thoughts?
Here is some of the code I have in my new page:
Amount: <h:inputText value="#{transactionBean.amount}" style="color: Yellow; background: Teal;"/>
Price <h:inputText value="#{transactionBean.pricePaid}" style="color: Yellow; background: Teal;"/
Here is my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 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_3_0.xsd">
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<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>
You've mapped the faces servlet on /faces/* instead of *.xhtml. This means that you need to include /faces path in the URL to get the faces servlet to run.
So, you should not open the page by
http://localhost:8080/SharePortfolioJSF/companies.xhtml
but instead by
http://localhost:8080/SharePortfolioJSF/faces/companies.xhtml
Much better, however, is to just use *.xhtml as URL pattern of the faces servlet, so that you don't need to fiddle with virtual paths.
<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>
<welcome-file-list>
<welcome-file>index.xhtml</welcome-file>
</welcome-file-list>
(note that your <session-timeout> of 30 minutes is the default already, just remove it)
From the comments:
Your second page isn't processed by the faces servlet. Your url pattern for the faces servlet is /faces/*. So all requests must contain the prefix /faces in order to get processed by the servlet.
It should work if you call your page with the following URL:
http://localhost:8080/SharePortfolioJSF/faces/companies.xhtml

RESTEasy Asynchronous HTTP with Spring MVC

Is there any handy way to use RESTEasy Asynchronous HTTP support (in my case on Tomcat 6) in conjunction with the Spring MVC framework. I've found useful articles on using RESTEasy with Spring, but none that cover asynchronous support, which appears to be a bit of a thorn at present, due to requring a different Servlet class depending on the container (Tomcat6CometDispatcherServlet for Tomcat, for example).
Thanks,
FB
I have created a sample app using Comet, Bayeux, Java, Maven and a Raphael JS frontend and wrote a blog post about it, you can use it as a base for your app, just wrapping the current service code in REST.
http://geeks.aretotally.in/thinking-in-reverse-not-taking-orders-from-yo
Hopefully it will help you.
For anybody interested, I ended up having to use the Tomcat6CometDispatcherServlet in preference to the Spring DispatcherServlet to get my application working.
I still have the Spring ContextLoaderListener in place to create the various beans within my Application Context, but have to use less than ideal means of accessing these from within my Controller classes, which are now JAX-RS annotated rather than Spring MVC annotated. (There are various articles a quick Google will uncover on accessing the Spring context programmatically.)
Here's a cleaned up version of my web.xml (nothing earth-shattering, but perhaps it will have some useful hints for somebody!):
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>myapp</display-name>
<description>My App</description>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>myapp.root</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<filter>
<filter-name>TrustedIPFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>TrustedIPFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>PollServlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.Tomcat6CometDispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PollServlet</servlet-name>
<url-pattern>/poll/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/WEB-INF/jsp/uncaughtException.jsp</location>
</error-page>
</web-app>

Resources