I am working on exception handling in our Application. I used try catch blocks to catch the exceptions occured in my code and i also could handle the time out exceptions by writing a listener and registering the listener in "faces-config.xml".
But i am facing problems in catching unexpected errors like "NullPointerException" in constructor or error Codes 500, 400 etc.
i used the tags in the "web.xml"
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/sc00/ErrorPage.jsp</location>
</error-page>
I tried many ways to handle the exceptions, can any one help me in finding out a solution. The error i am getting when i try to handle these exceptions is as follows.
I am using JSF 1.2 and the server is websphere 8
The Console shows the Following Exception.
com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0014E: Uncaught service() exception root cause Faces Servlet: javax.servlet.ServletException
E com.ibm.ws.webcontainer.servlet.ServletWrapper service SRVE0068E: An exception was thrown by one of the service methods of the servlet [/sc00/ErrorPage.jsp] in application [MembershipEligibilityScreensEAR]. Exception created : [java.lang.RuntimeException: FacesContext not found
My Error Page is in /WebContent/sc00/ErrorPage.jsp, ErrorPage.jsp has no backing bean associated with it.
Many solutions asked me to look at the URL path of Faces Servlet, In My web.xml the servlet-mapping is a follows
<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>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
all the paths in my faces-config.xml refer to /FolderName/JspName and they work fine and they work fine even in Navigation.xml.
How can i navigate it to ErrorPage.jsp, Is there any way so that i can write a listener to this kind of problem
Sorry for posting too many redundant questions, i am new to JSF and i don't know the rules of StackOverflow, I apologize for the problem i have caused.
any solution would be appreciated.
java.lang.RuntimeException: FacesContext not found
That will happen when you're requesting a JSP page containing JSF components through an URL which doesn't match the URL pattern of the FacesServlet (who is the one responsible for creating the FacesContext).
You need to change the error page location to match the URL pattern of the FacesServlet as definited in web.xml. Based on your duplicate questions on the subject, this is among others *.faces, so setting the error page location as follows should do, exactly as I suggested in a comment on your first question on the subject.
<location>/sc00/ErrorPage.faces</location>
Related
In Spring MVC, people typically build a Dispatcher Servlet that controls the other Servlets. The pipeline includes a request to web.xml which is then routed to a dispatcher of class org.springframework.web.servlet.DispatcherServlet. The URL pattern can be / or *.htm* to ensure that all requests go there.
The question is: in this pattern, what is even the purpose of web.xml? One would think that it is just useless overhead. I mean, if you're not going to use another dispatcher... or are you?
Basically in a regular Java app context will be fetched in some self-created main method, means main method is your starting point. Application will run from the main and will go other methods after.
public class FooClass{
public static void main(String[] args) {
//some code
}
But in the Spring web app,
the starting point is actually web.xml. It start from here, then flow goes to the other defined classes and methods
For example, when you write these codes, you basically give the order to the web application that you should start from here
Kind of you define your starting point. Think that it is main method in normal Java
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-mvc-validation-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
And in second part you give order to dispatcher that start from here. It means you give a url-pattern -starting point. You can give anything in here but "/" this is the common use
<!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
I hope it is clear. Else ask for more explanations.
I have a problem with configuration ( or basic understanding how things work at background). I create a JAVAEE project by checking Web application and ReSt api checkbox ( in intellij with glassfish 5.0). I have sample code below which web methods work but welcome page does not work. My web.xml and sample web service methods are below.
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>test</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
**<url-pattern>/ *</url-pattern>**
</servlet-mapping>
#Path("/RestTest")
public class TestString {
#Context
ServletContext context;
#GET
#Path("insertdb/{param1}/{param2}")
#Produces(MediaType.APPLICATION_JSON)
public Object writeToDb( #PathParam("param1") String param1
,#PathParam("param2") String param2){
try{
String password= context.getInitParameter("DbPassword");
Class.forName("org.mariadb.jdbc.Driver");
Connection dbCon = DriverManager.getConnection(
"jdbc:mariadb://xxx/testdb", "root", password);
PreparedStatement stmt=dbCon.prepareStatement(
"INSERT INTO TestTable VALUES(?,?)");
stmt.setString(1,param1);
stmt.setString(2,param2);
stmt.executeUpdate();
dbCon.close();
return "Success";
}catch(SQLException | ClassNotFoundException ex){
return ex.toString();
}
}
#GET
#Path("sum/{sum1}/{sum2}")
#Produces(MediaType.TEXT_HTML)
public String calculateSum(#PathParam("sum1") int param1
,#PathParam("sum2") int param2){
return ""+(param1 + param2);
}
If i change this line url-pattern "/*" to "/"
then welcome page is accessible but not methods.
Thus what i want is, having a welcome page which i will use for documentation for my web services(i dont want SOAP) and web methods must work by adding / to base url. How can i achieve that and what is difference between /* and /
See here for explanation of differences:
What is url-pattern in web.xml and how to configure servlet
Generally for a rest api it is best to use a path specific to all rest calls, for instance http://localhost/mywebapp/rest/...
Something like:
<servlet-mapping>
<servlet-name>jersey-servlet/servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
You only want jersey serving particular URLs when it is bundled in a WAR that also includes html pages.
To answer your question, difference between "/" and "/*"
A mapping that contains the pattern "/" matches a request if no other pattern matches. This is the default mapping. The servlet mapped to this pattern is called the default servlet. The default mapping is often directed to the first page of an application. Example :
Both requests will display same contents from index.jsp
http://myhost.com/index.jsp
and
http://myhost.com/
Now, a mapping that contains "/*" overrides all other servlets, including all servlets provided by the servlet container such as the default servlet and the JSP servlet. Whatever request you fire, it will end up in that servlet. This is thus a bad URL pattern for servlets.
Possible solution for your issue
Change the URL pattern to specific instead of default pattern.
<servlet>
<servlet-name>webservice</servlet-name> //servlet name
<servlet-class>com.rest.MyRestServlet</servlet-class> //servlet class
</servlet>
<servlet-mapping>
<servlet-name>webservice</servlet-name> //servlet name
<url-pattern>/RestTest/*</url-pattern> //all webservice request
</servlet-mapping>
All the web service request are accessible through
http://myhost.com/RestTest/
You may also be interested to look
What is URL-pattern in web.xml and how to configure servlet
Basics of Java Servlet
Servlet configuration and url-pattern
As you highlighted, your problem revolves around those four lines:
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
As Jim Weaver mentioned, it's a matter of url-pattern.
Solution(s)
You may consider three solutions (from the most-preferred to least-preferred):
dedicated REST URL: the easiest way is to have a dedicated url-pattern such as /rest/* for your web services. You can benefit some assets such as url hierarchy or you can easily implement a security framework over it.
URL rewriting may be an option and this answer suggests some library. I haven't tested those libraries myself
Page redirection can be an option to go around REST filtering but in the specific case of having the url-pattern at /*, I have to say I'm not sure if it's working for the reason I'll explain in next section
now a bit of explanation of what happened
Why setting the url-pattern at /* prevent from accessing the welcome page?
Actually, it's not only the welcome page that is not accessible: it's all the resources under the defined url-pattern. Whatever get in touch with REST stays with REST... Here is the schema taken from JSR 339 Appendix C:
With a GlassFish 5.0, I guess you're using JAX-RS 2.1 (JSR 370) but the sections I'm quoting have the same content
Without entering into detail, it is visible that only ContainerRequest Filters are executed in the process. Especially, it's worthy to notice that after Request Matching, requests are not forwarded to any servlet in a sense that standard resources are not reachable, unless specified by the REST method.
It's also worthy to highlight the fact the servlet filters are executed beforehand (leveraging this point is absolutely vital for managing security for example). I did not find back the source proving this point but I know it's somewhere on the web ^^.
Request matching is defined at section 3.7.2. In a nutshell, it is in three steps where the first one is the most important for your question, especially at step D:
Identify a set of candidate root resource classes matching the request
c. ...
d. If [the set of classes whose path matches the request URL] is empty then no matching resource can be found, the algorithm terminates and an implementation MUST generate a NotFoundException (404 status) and no entity
e. ...
highlights are mine.
The two last steps are
Obtain a set of candidate resource methods for the request
Identify the method that will handle the request
TL;DR
What happened when you set <url-pattern>/*<url-pattern> and tries to access to your welcome page (or any page actually):
Your server receives the GET request
If there are filters (such those from a security framework), there are executed
REST enters the scene
Pre Match filters are executed (none if your case)
Fetch your root resources classes (in your example, all classes in the test package)
Find if one of those class match the request URL
None are found, a 404 status is returned
To avoid unnecessary URL conflicts, the best options would be having a dedicated URL for your REST methods
If you mention in web xml like following all the request receive by 'Jersey Web Application' servlet. so request to index.jsp also redirect to 'Jersey Web Application' servlet
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
To avoid this add some prefix to the url to separate rest request like following
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>rs/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JAX-RS REST Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
for my
<servlet>
<display-name>JAX-RS REST Servlet</display-name>
<servlet-name>JAX-RS REST Servlet</servlet-name>
<servlet-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</servlet-class>
Servlet i.e the entry point of my app. In many examples I see everyone gives some path in the URL pattern but in my case I am just using /*. Is this ok? Or using some path in it has some benefits? Like faster URL matching? i.e the request if for the web service or so?
Firstly, it is not incorrect to have a /*.
If you have only one listener processing all incoming requests then what you have is absolutely fine. If you have multiple listeners/services processing different url patterns then of course, you will have different mappings for different url patterns.
I prefer to add a full url pattern like /path1/xyz/* if i know the pattern instead of /* so you i dont need to modify this mapping when i add another mapping/listener to process a different url pattern.
The servlet config looks like this -
<servlet>
<servlet-name>smart</servlet-name>
<servlet-class>SuperSmart</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>smart</servlet-name>
<url-pattern>/dumb</url-pattern>
</servlet-mapping>
Its said that all these aliases are for security. I get that. But why do we have to map it to a servlet-name first and then to the servlet-class ? Why can't the server find the url pattern and directly map it to the servlet-class ?
The aim of this is that the servlet could be referenced by more than one mapping, so you can map one servlet to more than one url (or pattern) and not just one.
The name is sort of like and "ID" that tells the container which <servlet> part goes with which <servlet-mapping> part (as well as ties it to other parts of the XML config in container specific XML files)
You can have multiple url patterns tied to the same servlet name.
I agree it seems ugly, but it's an attempt to keep the servlet config DRY, as servlet-name can be used in filter-mappings as well as servlet-mappings.
In servlet spec 3.0 you can annotate the servlets themselves which is neater.
It was designed that way to allow other components, such as filters, can access it. Filters can either be associated with a Servlet by using the <servlet-name> style:
<filter-mapping>
<filter-name>Image Filter</filter-name>
<servlet-name>ImageServlet</servlet-name>
</filter-mapping>
I have been thinking, how is it possible for me to send an email when a particular HTTP Error code happens
in my Spring MVC Web app.
Please take a look at my web.xml configuration. It works fine and redirects me to the particular error page.
<web-app ...>
<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/pages/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/pages/500.jsp</location>
</error-page>
</web-app>
But what I want is, I want to send email or logged the occurence of this particular error. I was told in my earlier question
that this type of error does not get handled by my controller hierarchy.
Any thoughts please?
For some reason, I did something like this. It works as for my case. Can you comment on what I did?
In my web.xml, I edited my location tag to forward it to my controller.
<!-- Error Pages -->
<error-page>
<error-code>404</error-code>
<location>/errorEncountered.htm</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/errorEncountered.htm</location>
</error-page>
In My controller, this is where I send an email.
#Controller
#RequestMapping("/errorEncountered.htm")
public class ErrorHandlerController {
private MailService mailService;
#RequestMapping(method = RequestMethod.GET)
public String handleGet(HttpServletRequest request) {
// The Servlet spec guarantees this attribute will be available
Throwable exception = (Throwable) request
.getAttribute("javax.servlet.error.exception");
.
.
.
mailService.sendMail();
}
}
}
Any criticism?
For 4nn (client side) errors, your best bet is to configure the access logs at servletcontainer level. In case of Tomcat, you can do this in flavor of a Valve. It's more or less a kind of Filter which is to be plugged at servletcontainer level rather than at webapp level. You can find more detail in the Apache Tomcat Configuration Reference. You'll need to turn on and configure the Access Log Valve. This will only write to a logfile, but you can just extend org.apache.catalina.valves.AccessLogValve and add some code which sends a mail in case of a 404. To get it to run, just put that class in Tomcat's classpath and specify it as className in Valve configuration.
For 5nn (server side) errors, you can create and put a Filter on an url-pattern of /* which does basically the following in doFilter() method.
try {
chain.doFilter(request, response);
}
catch (ServletException | IOException e) {
mail(e);
throw e;
}
Sending email on Http Error Code might be too late in the process to find why the error happened. A better thing to do for us was sending emails on exceptions. We might not want to do that for every exception, as that would be overwhelming.
To do this we extend SimpleMappingExceptionResolver. This Resolver is then required to be initialized with the context.
MyExceptionResolver extends SimpleMappingExceptionResolver
{
#Autowire
MailService mailService;
protected ModelAndView getModelAndView(String viewName, Exception ex, HttpServletRequest request)
{
//Depending on exception resolve to view name, either 404 or server crash report
//Also send emails for specific exception types.
}
}
Spring wiring:
<bean class="x.y.z.MyExceptionResolver"/>
Also, we can do exception handling with aspects. You can look up the aspects documentation for this.
When using the web.xml, Spring will not be first in line for a request (also depending on your <url-pattern>s).
What you can do is write a custom servlet that extends HTTPServlet.
In that servlet you can write the code for sending the email in the doGet() method that you over-ride from HttpServlet.
Edit your web.xml <url-pattern> to go to that servlet when the error occurs.
If its a error code 404, you know already that the problem relates to a page not found.
Cool.