I have a JSF application with a Servlet Filter configured for a urlPattern of /faces/*.
I want to hide a JSP from faces context so that it won't go through the Servlet Filter.
So I kept it under WebContent folder of my project as WebContent/Error.jsp and declared like the following in the web.xml:
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/Error.jsp</location>
</error-page>
But my Error.jsp never gets picked up. Instead I see 404 Page not found error.
To be more clear, I want my Error.jsp page URL to be:
http://localhost:8080/myappname/Error.jsp
But it is only reachable by:
http://localhost:8080/myappname/faces/Error.jsp
The same is the case when I declare any view-id in the faces-config.xml. Where do I keep the error JSP if I want to hide it from faces context?
Based on the information given so far, it looks as it should just work fine. You don't have a <dispatcher>ERROR</dispatcher> on the filter, so the filter should not be invoked at all whenever the NPE is thrown.
Apparently the NPE got wrapped up in another exception because it's been thrown at an illogical place such as bean's constructor instead of a normal bean action method. In such case, JSF would rethrow it as a ManagedBeanCreationException. The container would get it instead of the NPE and thus won't be able to locate the error page. In the container's default HTTP 500 error page, you should read the topmost exception of the stacktrace in order to determine the right exception to define an error page for.
Please keep in mind that runtime exceptions like NPEs are developer errors (bugs!), not production errors and that they should be fixed ASAP. I'd personally just use a global HTTP 500 error page for this kind of bugs:
<error-page>
<status-code>500<status-code>
<location>/errors/generic.jsp</location>
</error-page>
For more specific, real production exceptions, you can always declare a more specific error page:
<error-page>
<exception-type>com.example.YourDatabaseAccessException</exception-type>
<location>/errors/database.jsp</location>
</error-page>
<error-page>
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/errors/sessionexpired.jsp</location>
</error-page>
If you define a filter and declear that in your web.xml, all the request will go through that filter, unless you define the filter mapping.
I think you can define a filter mapping in your web.xml as following:
<filter>
<filter-name>URLFilter</filter-name>
<filter-class>the filter class in your source code</filter-class>
</filter>
<filter-mapping>
<filter-name>URLFilter</filter-name>
<url-pattern>/some pages</url-pattern>//skip error.jsp here
</filter-mapping>
this is not tested, but just an inspiration.
edit: you can find out more from Oracle site
To me it doesn't sound like the Faces filter has anything to do with this issue. Can you reach http://localhost:8080/myappname/Error.jsp with the filter completely disabled? If not, then perhaps there is some issue with the Error.jsp file itself?
It's hard to say without seeing the code itself.
Related
As a simple example, take a page that renders to JSP, and has an web.xml error-page attribute as a catch all exception:
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/WEB-INF/error/exceptions/throwable-layout.jsp</location>
</error-page>
Now, in the view, suppose we attempt a method that doesn't exist:
${requestScope.getBadVar()}
What happens is the output of the view terminates and the error page is then inserted immediately at the point of where the exception was thrown.
I understand this is tricky because the servlet has already started writing out the output stream and now it needs to be started from scratch, is there any way that this is possible?
I'm currently mapping error codes in web.xml and so far it looks like this:
<error-page>
<error-code>404</error-code>
<location>/errorHandler?code=404</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/errorHandler?code=500</location>
</error-page>
Do I have to map every single error code manually or is there more automatic way? I'd like to have something like this:
<error-page>
<error-code>*</error-code>
<location>/errorHandler?code=*</location>
</error-page>
That's possible, according to the documentation of oracle. It depends on whether you are using servlet 2.5 (not supported) or 3.0 (supported).
I would recommend you to use plain html for the error codes.
The reason behind this, is these pages will be shown when something is going very wrong. Full list of status codes
Generic solution example: moreinfo with onehippo
From security perspective it is not recommended to give information what went wrong in the application: https://blog.whitehatsec.com/error-handling-in-java-web-xml/
The javadoc of the javax.servlet.AsyncContext interface says:
In the event that an asynchronous operation has timed out, the
container must run through these steps:
Invoke, at their onTimeout method, all AsyncListener instances registered with the ServletRequest on which the asynchronous
operation was initiated.
If none of the listeners called complete() or any of the dispatch() methods, perform an error dispatch with a status code
equal to HttpServletResponse.SC_INTERNAL_SERVER_ERROR.
If no matching error page was found, or the error page did not call complete() or any of the dispatch() methods, call complete().
But I couldn't find the meaning of "error dispatch" anywhere.
In fact there was an Apache bug that exclaimed the same. (In their exact words: "I haven't seen the def. of 'error dispatch', too")
But of course, there must be a clear definition for this and how to use it.
Does anyone know?
Dispatches made by the container during exceptions/errors are called error dispatches. These are usually dispatches to error pages. There is no way to directly do an error dispatch as I know it.
A request that has come through an error dispatch will have dispatcher type set to DispatcherType.ERROR. (In the servlet's service method code, you can get the dispatch type using getDispatcherType())
The following six request scoped attributes will also be set in error dispatches.
"javax.servlet.error.exception"
"javax.servlet.error.exception_type"
"javax.servlet.error.message"
"javax.servlet.error.request_uri"
"javax.servlet.error.servlet_name"
"javax.servlet.error.status_code"
So if you have an error page to which the container redirects errors, you know you can read those six attributes for more information.
http://docs.oracle.com/javaee/6/api/javax/servlet/DispatcherType.html
http://docs.oracle.com/javaee/6/api/javax/servlet/RequestDispatcher.html
You can setup an error dispatch by using tag in deployment descriptor (web.xml). For example if you added an error-page tag for 404 error code, then the container will dispatch to that page when a page not found error occurs. In that error page, you can use code like request.getAttribute("javax.servlet.error.message") to retrieve details about the error. Example ...
web.xml :
<web-app>
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
</web-app>
error.jsp :
<!DOCTYPE html>
<html>
<head>
<title>404 Error</title>
</head>
<body>
The page was not found. You requested <%= request.getAttribute("javax.servlet.error.message") %> but it was not found. Sorry.
</body>
</html>
In the above sample application, if a client requested page is not found or you use response.sendError("404", "...") somewhere, the container will do an error dispatch to error.jsp.
The JSP error handling mechanism (using "errorPage" and "isErrorPage" page directives) also applies here.
Another information which is not directly related to the question but which I have seen not clearly mentioned in almost all places, including the answer above is that the error dispatch is technically NOT "redirect", it's rather internal forward. For beginners this might seem confusing as its usually written all over as "container does the redirect to the error page". So the moment your container sees an http error code / uncaught exception being sent by any of the resource it begins to look into the web xml to see if there are any handler defined and if present then it appropriately forwards the request to that resource using a request dispatcher. Then obviously all the information mentioned in the above answer applies.
If some one however wants to do an redirect, they can do so in filter or servlet or from anywhere they have response object available.
(Should be an easy one-)
How can I redirect all urls of the pattern yada*.js into a my specific jsp.
will this addition to my web.xml work:
<servlet-mapping>
<servlet-name>MySpecific.jsp</servlet-name>
<url-pattern>yada*.js</url-pattern>
</servlet-mapping>
or perhaps I must use javax.servlet.filter for that purpose?
I'd drop those files in a folder called /yada and then use an url-pattern of /yada/*.
If you don't want to do that, then hand-determining it in a filter is indeed the only resort.
Update: as per your update, you actually have a second question which wasn't directly obvious from your initial question: "How to declare a JSP file as a servlet?". The answer is: use <jsp-file> instead of <servlet-class>.
<servlet>
<servlet-name>foo.jsp</servlet-name>
<jsp-file>/foo.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>foo.jsp</servlet-name>
<url-pattern>/foo/*</url-pattern>
</servlet-mapping>
Nevertheless, as stated in the comments, this is not the best practice. This smells to raw Java code in a JSP file which you should avoid to all extent.
Depending on the server the things that you can put in url-pattern are very limited.
Two are valid:
an absolute path (no wildcards)
*.ext
So that specification is not matching. I'd use a filter indeed.
PS: don't forget to specify <%page sourceEncoding=... contentType=... %> in the generating JSP :). And content-type should include charset=xxxxx
I need to have a default error JSP page which is shown when an exception is thrown by the servlet, and that page will show the stacktrace..
How do I do that?? is there a right technique (provided by the API) or I have to do it manually?? I mean, sending the exception thrown as an attribute and then dealing with it by myself??
Thanks
You can configure the exception type and the JSP page to handle in web.xml, e.g:
<error-page>
<exception-type>UnhandledException</exception-type>
<location>UnhandledException.jsp</location>
</error-page>
There's an Oracle article here on the subject:
http://www.oracle.com/technology/sample_code/tech/java/codesnippet/servlets/HandlingServletExceptions/HandlingServletExceptions.html