Unable to debug the Controller for Error - java

Why is that I can't debug the controller that handles the error page. What I've added is to print the exception message. I put breakpoints on that part.
It's successfully displayed the error.jsp. But the breakpoints were not recognized.
Here are my codes.
web.xml
<error-page>
<error-code>404</error-code>
<location>/404.htm</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/500.htm</location>
</error-page>
<error-page>
<location>/500.htm</location>
</error-page>
Controller.java
#RequestMapping("/500.htm")
public ModelAndView errorFound(HttpServletRequest request,
HttpServletResponse response, Exception ex) throws ServletException {
logger.error("ERROR FOUND --> ", ex);
return new ModelAndView("/common/error");
}
#RequestMapping("/404.htm")
public ModelAndView pageNotFound(HttpServletRequest request,
HttpServletResponse response, Exception ex) throws ServletException {
logger.error("PAGE NOT FOUND --> ", ex);
return new ModelAndView("/common/error");
}
I'm using Eclipse Neon.
Do you think the problem is with my IDE?
UPDATES:
1. Even if I deleted the above controller functions, still the error message was directed to error.jsp
2. codes: dispatcherservlet.xml
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
3. Im using Java 7, Apache 7, Spring 3.1.0

Suppose you put your jsp under /WEB-INF/jsp/ folder. Putting error code against jsp in web.xml directly show your error page. No need to redirect to any controller. So you do not include any controller mapped url to show the page.
In this case if your jsp reside in /WEB-INF/jsp/ then you can configure your web.xml in such that
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/404.jsp</location>
</error-page>
<error-page>
<error-code>500</error-code>
<location>/WEB-INF/jsp/500.jsp</location>
</error-page>
If you want to show your exception in page then you need to configure your Exception.class into generic one. Create a class using #ControllerAdvice and #EnableWebMvc.
What is ControllerAdvice annotation ?
From spring docs:
A controller advice allows you to use exactly the same exception handling techniques but apply them across the whole application, not just to an individual controller. You can think of them as an annotation driven interceptor.
Your Custom Exception handler class somehow look like
#ControllerAdvice
#EnableWebMvc
public class CustomExceptionHandler {
#ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception exception){
ModelAndView andView = new ModelAndView();
andView.addObject("exception",exception);
andView.setViewName("/common/error");
return andView;
}
}

Related

Handle 404 errors in Spring?

Here is the code I have for redirecting unmapped requests to 404 page
#RequestMapping("/**")
public ModelAndView redirect() {
ModelAndView mv = new ModelAndView();
mv.setViewName("errorPage");
return mv;
}
The above code works fine but the problem is with the web resources like css and js files
also go inside this redirect method and it is not loading any of the files. But i already have this code in my dispatcher servlet,but spring controller is not recognizing this resources mapping.
<mvc:resources mapping="/resources/**" location="/WEB-INF/web-resources/" />
so i tried some regex expression in the request mapping to negate the resources url something like this
#RequestMapping("/{^(?!.*resources/**)}**")
public ModelAndView redirect() {
ModelAndView mv = new ModelAndView();
mv.setViewName("errorPage");
return mv;
}
But this is not working as expected ..So if anyone could help it would be great :)
I found the solution to handle 404 (Unmapped links), I used a SimpleUrlHandlerMapping to do this.
I added the below code to my dispatcher servlet .xml
<!-- Here all your resources like css,js will be mapped first -->
<mvc:resources mapping="/resources/**" location="/WEB-INF/web-resources/" />
<context:annotation-config />
<!-- Next is your request mappings from controllers -->
<context:component-scan base-package="com.xyz" />
<mvc:annotation-driven />
<!-- Atlast your error mapping -->
<bean id="errorUrlBean" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/**">errorController</prop>
</props>
</property>
</bean>
<bean id="errorController" class="com.xyz.controller.ErrorController">
</bean>
com.xyz.controller.ErrorController class
public class ErrorController extends AbstractController {
#Override
protected ModelAndView handleRequestInternal(HttpServletRequest arg0,
HttpServletResponse arg1) throws Exception {
// TODO Auto-generated method stub
ModelAndView mv = new ModelAndView();
mv.setViewName("errorPage");
return mv;
}
}
I found the below reasons
#RequestMapping("/**") uses RequestHandlerMapping and
<mvc:resources mapping="/resources/**" location="/WEB-INF/web-resources/" />
uses SimpleUrlHandlerMapping
RequestHandlerMapping takes presedence over SimpleUrlHandlerMapping, so that was the reason all resources request went inside the redirect method in my case.
So i just changed the #RequestMapping("/**") request to SimpleUrlHandlerMapping by configuring that as a bean as given above in my dipatcher servlet and mapped it at the last and it solved the problem.
Also add the below code to your web.xml
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/error.jsp</location>
</error-page>
Now this simple solution can be used to redirect all unmapped requests i.e) 404 errors to an error page :)

Servlet pure forwarding issue [duplicate]

Java Servlet API can forward requests to another path within the same server (identical host:port). But, forwarding to a different host:port — like proxy do — is another story.
I've tried to do that with Jersey Client, adapting the ServletRequest — method, headers, mediatype and body — to a Jersey ClientRequest (with a different base uri), making the call, and adapting back the Jersey ClientResponse — method, headers, mediatype and body — to the ServletResponse.
Adapting those manually seems wrong to me.
Isn't there a pure Servlet API solution?
Or an HTTP client capable of adapting requests back and forth when changing the host:port?
HTTP-Proxy-Servlet does exactly what you need.
Quick configuration
pom.xml
<dependency>
<groupId>org.mitre.dsmiley.httpproxy</groupId>
<artifactId>smiley-http-proxy-servlet</artifactId>
<version>1.7</version>
</dependency>
web.xml
<servlet>
<servlet-name>solr</servlet-name>
<servlet-class>org.mitre.dsmiley.httpproxy.ProxyServlet</servlet-class>
<init-param>
<param-name>targetUri</param-name>
<param-value>http://solrserver:8983/solr</param-value>
</init-param>
<init-param>
<param-name>log</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>solr</servlet-name>
<url-pattern>/solr/*</url-pattern>
</servlet-mapping>
Spring Integration
see also: HTTP-Proxy-Servlet Issue #15
pom.xml
<dependency>
<groupId>org.mitre.dsmiley.httpproxy</groupId>
<artifactId>smiley-http-proxy-servlet</artifactId>
<version>1.7</version>
</dependency>
ServletWrappingControllerExt.java
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.ServletWrappingController;
public class ServletWrappingControllerExt extends ServletWrappingController
{
private String pathToStrip;
public void setPathToStrip(String pathToStrip)
{
this.pathToStrip = pathToStrip;
}
#Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception
{
final HttpServletRequest wrapper = new HttpServletRequestWrapper(request)
{
#Override
public String getPathInfo()
{
//Please note that getPathInfo returns null if DispatcherServlet is configured to track url-pattern "/"
//It should be configured to track url-pattern "/*". Below is a sample DispatcherServlet configuration
/*
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
*/
String path = super.getPathInfo();
if (path.startsWith(pathToStrip))
{
final int length = pathToStrip.length();
path = path.substring(length);
}
return path;
}
#Override
public String getServletPath()
{
return super.getServletPath();
}
};
return super.handleRequestInternal(wrapper, response);
}
}
Beans configuration
<bean id="myServletWrapper" class="ServletWrappingControllerExt">
<property name="pathToStrip" value="/solr"/>
<property name="servletClass" value="org.mitre.dsmiley.httpproxy.ProxyServlet" />
<property name="servletName" value="solr" />
<property name="initParameters">
<props>
<prop key="targetUri">http://solrserver:8983/solr</prop>
<prop key="log">true</prop>
</props>
</property>
</bean>
<bean id="myServletUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/solr/**" value-ref="myServletWrapper" />
</map>
</property>
<property name="order" value="1" />
</bean>
You should use javax.net.HttpURLConnection
Here is the psuedo code for that:
URL url = new URL("http://otherserver:otherport/url");
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
// set http method if required
connection.setRequestMethod("POST");
// set request header if required
connection.setRequestProperty("header1", "value1");
// check status code
if(connection.getResponseCode() == 200) {
InputStream is = connection.getInputStream();
//transfer is to the required output stream
} else {
//write error
}
As far as I understand You need to send requests from Servlet and get response from other server into yours, may be you need a HTTP Client (Overview) for that.
This question might also help you.

Spring 3 simple extentionless url mappings with annotation-based mapping - impossible?

I'm using Spring 3, and trying to set up a simple web-app using annotations to define controller mappings. This seems to be incredibly difficult without peppering all the urls with *.form or *.do
Because part of the site needs to be password protected, these urls are all under /secure. There is a <security-constraint> in the web.xml protecting everything under that root. I want to map all the Spring controllers to /secure/app/.
Example URLs would be:
/secure/app/landingpage
/secure/app/edit/customer/{id}
each of which I would handle with an appropriate jsp/xml/whatever.
So, in web.xml I have this:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/secure/app/*</url-pattern>
</servlet-mapping>
And in despatcher-servlet.xml I have this:
<context:component-scan base-package="controller" />
In the Controller package I have a controller class:
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
#Controller
#RequestMapping("/secure/app/main")
public class HomePageController {
public HomePageController() { }
#RequestMapping(method = RequestMethod.GET)
public ModelAndView getPage(HttpServletRequest request)
{
ModelAndView mav = new ModelAndView();
mav.setViewName("main");
return mav;
}
}
Under /WEB-INF/jsp I have a "main.jsp", and a suitable view resolver set up to point to this. I had things working when mapping the despatcher using *.form, but can't get anything working using the above code.
When Spring starts up it appears to map everything correctly:
13:22:36,762 INFO main annotation.DefaultAnnotationHandlerMapping:399 - Mapped URL path [/secure/app/main] onto handler [controller.HomePageController#2a8ab08f]
I also noticed this line, which looked suspicious:
13:25:49,578 DEBUG main servlet.DispatcherServlet:443 - No HandlerMappings found in servlet 'dispatcher': using default
And at run time any attempt to view /secure/app/main just returns a 404 error in Tomcat, with this log output:
13:25:53,382 DEBUG http-8080-1 servlet.DispatcherServlet:842 - DispatcherServlet with name 'dispatcher' determining Last-Modified value for [/secure/app/main]
13:25:53,383 DEBUG http-8080-1 servlet.DispatcherServlet:850 - No handler found in getLastModified
13:25:53,390 DEBUG http-8080-1 servlet.DispatcherServlet:690 - DispatcherServlet with name 'dispatcher' processing GET request for [/secure/app/main]
13:25:53,393 WARN http-8080-1 servlet.PageNotFound:962 - No mapping found for HTTP request with URI [/secure/app/main] in DispatcherServlet with name 'dispatcher'
13:25:53,393 DEBUG http-8080-1 servlet.DispatcherServlet:677 - Successfully completed request
So... Spring maps a URL, and then "forgets" about that mapping a second later? What is going on?
Thanks.
I have exactly the same problem as you. The way to set 'alwaysUseFullPath' is pretty straightforward. My conf file is as following:
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"
p:order="3" > <!-- a higher value meaning greater in terms of sorting. -->
<property name="alwaysUseFullPath" value="true" />
<property name="interceptors">
<list>
<ref local="myInterceptor" />
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="alwaysUseFullPath" value="true" />
</bean>
Ah. As usual, found the answer after posting the question :-)
Changing the RequestMapping annotation to just /main fixes the problem. The documentation is not very clear on how all this is specified.
Put something like this in your #Configuration class:
#Bean(autowire = Autowire.BY_TYPE)
public AnnotationMethodHandlerAdapter handlerAdapter(){
final AnnotationMethodHandlerAdapter annotationMethodHandlerAdapter = new AnnotationMethodHandlerAdapter();
annotationMethodHandlerAdapter.setAlwaysUseFullPath(true);
return annotationMethodHandlerAdapter;
}

Spring MVC - jsp not rendering

I'm just starting with Spring MVC trying to create a new project, and came accross an issue for which no manual or tutorial seems to help...
I have set up a simple application with no logic, just trying to get Spring configured properly. The controller just returns the name of a view to be displayed, but the view resolver is not rendering the jsp, and returning a 404 error....
Any help is greatly appreciated.
My web.xml is:
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>openstats</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>openstats</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<display-name>OpenStats API Server</display-name>
</web-app>
An my openstats-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<context:component-scan base-package="org.openstats.api.controller"/>
<!-- Enable to request mappings PER METHOD -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
<!-- Enable annotated POJO #Controller -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<!-- Define the view resolver to use jsp files within the jsp folder -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"><value>org.springframework.web.servlet.view.JstlView</value></property>
<property name="prefix"><value>/jsp/</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean>
</beans>
The controller itself has no logic whatsoever, it's simply:
#Controller
public class ProductController {
#RequestMapping(value = "/products.do", method = RequestMethod.GET)
public ModelAndView listProducts(HttpServletRequest request) {
ModelAndView model = new ModelAndView("index");
return model;
}
}
The controller is reached, the issue is when attempting to render...
I set up log4j in debug, and this is part of what I get:
02:08:19,702 DEBUG
DispatcherServlet:1094 - Testing handler adapter
[org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#397b6074]
02:08:19,803 DEBUG
HandlerMethodInvoker:134 - Invoking
request handler method: public org.springframework.web.servlet.ModelAndView
org.openstats.api.controller.ProductController.listProducts(javax.servlet.http.HttpServletRequest)
02:08:19,833 DEBUG
DefaultListableBeanFactory:1367 -
Invoking afterPropertiesSet() on bean
with name 'index' 02:08:19,876 DEBUG
InternalResourceViewResolver:81 -
Cached view [index] 02:08:19,877 DEBUG
DispatcherServlet:1181 - Rendering
view
[org.springframework.web.servlet.view.JstlView:
name 'index'; URL [/jsp/index.jsp]] in
DispatcherServlet with name
'openstats' 02:08:19,877 DEBUG
JstlView:240 - Rendering view with
name 'index' with model {} and static
attributes {} 02:08:19,923 DEBUG
JstlView:234 - Forwarding to resource
[/jsp/index.jsp] in
InternalResourceView 'index'
02:08:19,926 DEBUG
DispatcherServlet:955 -
DispatcherServlet with name
'openstats' determining Last-Modified
value for [/api-server/jsp/index.jsp]
02:08:19,927 DEBUG
DispatcherServlet:1054 - Testing
handler map
[org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#440c4cee]
in DispatcherServlet with name
'openstats' 02:08:19,928 DEBUG
DefaultAnnotationHandlerMapping:179 -
No handler mapping found for
[/jsp/index.jsp] 02:08:19,929 DEBUG
DispatcherServlet:962 - No handler
found in getLastModified 02:08:19,937
DEBUG DispatcherServlet:781 -
DispatcherServlet with name
'openstats' processing request for
[/api-server/jsp/index.jsp]
02:08:19,938 DEBUG
DispatcherServlet:843 - Bound request
context to thread: GET
/api-server/products.do HTTP/1.1
My jsp folder is right within "webapp" and the index.jsp file exists.
Thanks in advance.
I do have the same problem with Spring 3.x.
Any progress so far?
EDIT:
I figured it out myself :-) I used the following servletmapping:
<servlet-mapping>
<servlet-name>spring-frontcontroller</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Editing the url-pattern to e.g. *.do fixes the problem of not rendering the JSP.
But this leaves the question how this is possible with your url-pattern.
Does your web.xml define index.jsp in the welcome-file-list, if so it may be getting overridden. Try changing the jsp name to products.jsp.
e.g.
#Controller
public class ProductController {
#RequestMapping(value = "/products.do", method = RequestMethod.GET)
public String handleRequest() {
return "products";
}
}
doesn't your .jsp and your .do conflict? since a file cannot end with both .jsp and .do .. therefore it will never resolve... so you should get rid of .jsp or change your url pattern to /*
Changing
import org.springframework.web.servlet.ModelAndView;
by
import org.springframework.web.portlet.ModelAndView;
Works in my case.

Introducing Spring MVC

I'd like to introduce Spring MVC to an application that has up till now used simple direct access to JSP files i.e www.example.com/login.jsp which contains the business logic and presentation details.
I'd like to strip out the business logic and keep only the presentation in the JSP. To do this, I've moved the jsp file from webapp/login.jsp to webapp/WEB-INF/jsp/login.jsp and then mapped all urls with the pattern *.jsp to Spring's DispatchServlet which goes to a Controller and then a view which (should) forward to /WEB-INF/jsp/login.jsp.
The web.xml looks like this:
<servlet>
<servlet-name>springapp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springapp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
springapp-context.xml
<bean id="urlFilenameViewController" class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>
/*.jsp=urlFilenameViewController
</value>
</property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"></property>
</bean>
However, the fundamental problem with this is that I'm mapping external URL requests ending in .jsp to internal web requests that also map to .jsp. The internal .jsp request then goes through the DispatchServlet for a second time which returns an error as it cannot find anything to handle the request:
WARN - DispatcherServlet.noHandlerFound(1077) | No mapping found for HTTP request with URI [/myapp/WEB-INF/jsp/login.jsp] in DispatcherServlet with name 'springapp'
Given that I cannot change the external URLs, is there a way to get round this issue when mapping external file types to the same internal file type?
We address this in our application by using a different pattern for request URLs (*.htm instead of *.jsp). This avoids the problem and it is good practice anyway because there may not be a 1-to-1 relationship between a URL and a JSP.
I suggest you:
map Spring MVC requests to a different pattern ( e.g *.do);
use a UrlRewriteFilter or your application server's url rewrite functionality to map *.jsp calls to *.do;
I'm not sure how to tell Spring to ignore its internal requests for JSP files, but intercept other JSP requests. Why don't you keep your old jsps, but just have them forward to a controller. E.g. "page.jsp":
<%# taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<c:redirect url="/page.htm" />
This way, you can keep your old URLs intact, but the only function is to redirect to the controllers.

Categories