If I try:
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
I get this error:
No mapping found for HTTP request with URI [/sample/WEB-INF/jsp/person.jsp]
If I try just / as <url-pattern> then everything works fine.
My url : http://localhost:8080/sample/person
Why is this happening? What is the preferred way of doing this configuration in web.xml?
My app-servlet.xml has :
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
You mapped /* (every request to your app) to your servlet called 'app'. The InternalResourceViewResolver than looks (internally) for '/person' inside '/WEB-INF/jsp/person.jsp'. This way you can access your views, while the scripts are secured inside WEB-INF, which is not accessible from the url (public).
/* means every public request to your web-app. It means for your jsp it should be public accessed, since it is in WEB-INF and not public it will give error.
If you use only / it means server took the request and the web-app processes it internal without any public access.
Related
I've been experimenting with Java Servlets for web applications, in this application I was able to hit a Servlet and correctly load a .jsp page, having done this I have moved onto Spring MVC. I've run into a problem where my servlet controller class is called, however it will not load the view.
I've ruled out an the resources not being visible, because it worked correctly with a plain java servlet. I've also read just about every resource/tutorial out there in an effort to attempt to identify the problem without any luck, my problem remains the same. In addition in an effort to trouble-shoot I've added an error page tag () in order to see if when I attempt to hit my page, it would correctly redirect me, but its unable to find the page specified for 404 errors.
Can anyone identify what I've missed?
Web.xml
Variations: Changed url-pattern, init-params, context config location etc.
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/LoginServlet-servlet.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
LoginServlet-servlet.xml
Variations: I've tried moving the declarations into different positions as has been suggested on other posts, to no result. In addition typically I've had the prefix set to /WEB-INF/jsp/
<context:component-scan base-package="plan.route.server" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<context:annotation-config/>
<mvc:annotation-driven />
LoginServlet.java
Variations: Different requestMapping path, marking the methods not the class, returning string from methods, returning ModelAndView class
package plan.route.server;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
#Controller()
#RequestMapping("/")
public class LoginServlet extends org.springframework.web.servlet.mvc.AbstractController {
#RequestMapping(method = RequestMethod.GET)
public String forwardTo() {
return "index";
}
#Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)
throws Exception {
return new ModelAndView("login", "login", "login");
}
}
Project setup
Variations: different locations for the servlet xml, .jsp files etc
Can anyone see what I've missed? all I'm trying to do, despite all the variations is load a .jsp page.
Edit: The following error is displayed after my java servlet method is called:
WARNING: No mapping found for HTTP request with URI [/Root/Login] in DispatcherServlet with name 'LoginServlet'
I see one thing that is wrong and is the jsp configuration in LoginServlet-servlet.xml, try change prefix value as follows:
<context:component-scan base-package="plan.route.server" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<context:annotation-config/>
<mvc:annotation-driven />
With your configuration Spring is not able to find jsp file, because you specified the wrong path. You have to be folder specific, in your case you have jsp files in /WEB-INF/jsp folder.
EDIT:
I configured your project in my workspace and it works. Try to remove this lines from web.xml:
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/LoginServlet-servlet.xml</param-value>
</init-param>
And your Controller class should be like this:
#Controller
#RequestMapping("/")
public class LoginServlet{
#RequestMapping(method = RequestMethod.GET)
public ModelAndView forwardTo(ModelMap model) {
return new ModelAndView("login", "login", "login");
}
}
And pay attention on how you invoke the controller:
http://localhost:8080/Root/
This is the correct way to call the controller because you named your project Root and the controller is listening to "/" path. I used port 8080 because you tagged the question with tomcat, and this is the default tomcat port, if you use another one change it with the one you use.
In LoginServlet-servlet.xml file try
<property name="prefix" value="/WEB-INF/jsp/"/>
instead of
<property name="prefix" value="/" />
With your current project setup
LoginServlet-servlet.xml
<context:component-scan base-package="plan.route.server" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<context:annotation-config/>
<mvc:annotation-driven />
LoginServlet.java
#Controller
#RequestMapping("/")
public class LoginServlet {
#RequestMapping(method = RequestMethod.GET)
public String forwardTo() {
return "index";
}
#RequestMapping(value="/login", method = RequestMethod.GET)
public String forwardToLogin() {
return "login";
}
}
This should work
I have faced the problem when decided to create a web-app without JSPs, but using only HTML-pages which are under directory WEB-INF/pages.
I've made the view resolver:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="WEB-INF/pages/"/>
<property name="suffix" value=""/>
</bean>
Also I've imported all the resources in WEB-INF/pages:
<mvc:resources mapping="/**" location="WEB-INF/pages/"/>
My controller have the following view:
#PreAuthorize("isAuthenticated()")
#RequestMapping("/")
public String indexPage() {
return "redirect:/index.html";
}
It works fine for mapping "/" (redirects to login page if not authenticated), but it is not secured for url "/index.html" due to importing of this page as static resource (but it will not work at all if not import it).
Finally, I found the solution. Maybe, it will be interesting to anybody. The main servlet mapping that I had, had url-pattern: /**
And that was my problem. As I understood the main servlet in someway intercepted viewResolver even if it had such configuration: <bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/"/>
<property name="suffix" value=".html"/>
</bean>
When I make the configuration of servlet make as the next one:
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
everything became ok.
i dont know why you want to do that ..... as putting pages under web-inf is a wrong practice.......
also the container cant access the static contents that are under web-inf folder. I have faced exactly same problem see resource problem post.
what i have found from googling is you can access dynamic resources under web-inf folder but not the static. I have tried even regestring all the static contents (ie. css, js,html, etc) in xml at the first place but nothing worked. finally i moved my pages out and it worked with no configuration ....
so try moving the resources out of web-inf and under webcontent
tell me if you got some extras on this.
thanks.
I'm building very basic mvc application with Spring. It has one controller that should invoke validation on request body. The problem is that if I define the mapping in web.xml it stops finding the right controller, but when I modify the servlet application context Spring star making some new bindings on the fly but this time annotation based validation is ignored. How can I controll mappings in web.xml while still invoking annotation based validation?
Here are the details:
The controller:
#Controller
#RequestMapping("/api")
public class UserActionsController {
#RequestMapping(value="/choice", method = RequestMethod.POST)
public #ResponseBody NameValue addUserChoice(#Valid #RequestBody NameValue action)
{
return action;
}
}
This is the servlet application context:
<mvc:annotation-driven/>
<context:component-scan base-package="com.my.package" />
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
</map>
</property>
<property name="defaultContentType" value="application/json" />
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
</list>
</property>
</bean>
Web xml:
<servlet>
<servlet-name>action-api</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action-api</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
The configuration above is working. The problem starts when I try to change web.xml so the controller will only be responsible for "/api/*". I change it to <url-pattern>/api/*</url-pattern>. In that case Spring cannot find the right controller.
(DispatcherServlet:819) - DispatcherServlet with name 'action-api' processing POST request for [/api/choice]
(RequestMappingHandlerMapping:209) - Looking up handler method for path /choice
(RequestMappingHandlerMapping:219) - Did not find handler method for [/choice]
(PageNotFound:1080) - No mapping found for HTTP request with URI [/api/choice] in DispatcherServlet with name 'action-api'
(DispatcherServlet:913) - Successfully completed request
Modifying the servlet application context helps, Spring now able to find the controller, but validation is not invoked anymore.
<bean
class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="alwaysUseFullPath" value="true" />
<property name="messageConverters">
<util:list id="beanList">
<bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
</util:list>
</property>
</bean>
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="alwaysUseFullPath" value="true" />
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="alwaysUseFullPath" value="true" />
</bean>
Here is the log:
(DispatcherServlet:819) - DispatcherServlet with name 'action-api' processing POST request for [/api/choice]
(RequestMappingHandlerMapping:209) - Looking up handler method for path /choice
(RequestMappingHandlerMapping:219) - Did not find handler method for [/choice]
(DefaultAnnotationHandlerMapping:124) - Mapping [/api/choice] to HandlerExecutionChain with handler [com.my.package.controller.UserActionsController#1f86dbd] and 1 interceptor
(HandlerMethodInvoker:638) - Reading [com.my.package.model.NameValue] as "application/json" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter#2059ef]
(HandlerMethodInvoker:173) - Invoking request handler method: public com.my.package.model.NameValue com.citypath.dima.controller.UserActionsController.addUserChoice(com.my.package.model.NameValue)
(AnnotationMethodHandlerAdapter:1037) - Written [com.my.package.model.NameValue#166685b] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter#2059ef]
(DispatcherServlet:957) - Null ModelAndView returned to DispatcherServlet with name 'action-api': assuming HandlerAdapter completed request handling
(DispatcherServlet:913) - Successfully completed request
Looks like Spring making some binding on the fly, but this time validators are ignored.
I need to have 2 controllers for, say '/api' and '/something'. How can I define it in web.xml so Spring will be able to locate them and to invoke validation?
Thanks.
Spring #Controllers URLs are always interpreted relative the the Spring Dispatcher Servlet that handles them. So if you map the dispatcher servlet to /api/* in web.xml then the URL to your controller above is /api/api/choice
So you can configure two spring dispatcher servelts in web.xml one mapped to /api in the web.xml and one mapped to /somethingelse in web.xml then you can just remove /api from the #RequestMappings
In my app I am using a single Dispatcher Servlet for api and UI and I use public static final String called URL in my various API controllers to build up the paths to the various resources exposed by the API. Below is an example from my API.
#Controller
#RequestMapping(CompanyPermissionsResourceController.PATH)
public class CompanyPermissionsResourceController extends BaseApiController
{
public static final String PATH = CompanyResourceController.PATH + "/permissions";
Are you sure you are making post request to /api/choice?
#RequestMapping(value="/choice", method = RequestMethod.POST)
Try Changing to
#RequestMapping(value="/choice", method = RequestMethod.GET)
public #ResponseBody NameValue addUserChoice(#Valid #RequestBody NameValue action)
{
return action;
}
I don't think it works like this. Put all the path /api/choice at method level.
I've got a spring-security setup in my web-app. I want to replace some messages of spring security with my custom messages i.e.
Instead of Bad Credentials I want AbstractUserDetailsAuthenticationProvider.badCredentials to have value invalid username or password, please try again
This is my spring setup :
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/messages/messages"/>
<!-- Tried this as well <property name="basename" value="/WEB-INF/messages/messages.properties"/> -->
<property name="cacheSeconds" value="0" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
And I have created folder in the WEB-INF called messages. Inside this folder there is file called messages.properties. Inside this file is one line :
AbstractUserDetailsAuthenticationProvider.badCredentials=invalid username or password, please try again
What am I doing wrong here?
Update :
This servlet-context is defined in the web xml :
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</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>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Problem solved, moved the messageSource bean definition to another context.
Everything looks right. Try to get the message using spring message tag in order to check if the problem is with your configuration or with the security message:
<spring:message code="AbstractUserDetailsAuthenticationProvider.badCredentials" />
If this does work, problem is not with your configuration (that looks fine for me).
Anyway, try to put your messages files in the classpath (source folder) and this:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages/messages"/>
<property name="cacheSeconds" value="0" />
<property name="defaultEncoding" value="UTF-8" />
</bean>
Also, check that the bean is being declared in a application context file that Spring is aware of.
I'm using Spring 3 and i don't know how to map somepage.htm to somepage.jsp without a controller.
That is: if i go to somepage.htm, i want it to show me the jsp. But of course without redirect. I dontw want anyone to see ".jsp" only ".htm"
<servlet>
<servlet-name>Training01</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Training01</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
The way to do is to use the <mvc:view-controller..> tag in combination with a view resolver.
See here for more documentation:
The <mvc:view-controller..> tag maps urls to views. So if you want to map the relative url /login to a view names login you would do it by adding the following line to you webmvc-context.xml file:
<mvc:view-controller path="/login" view-name="login" />
Of course to get this to work you'll have to have a view resolve - something that maps logic names to specific views - setup in your context. In your case since you are using straight jsps for you view layer you'll want to add something like this to your configuration:
<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"/>
</bean>
So with this setup if you had a jsp login.jsp located in you /WEB-INF/jsp directory then you would be able to directly reference that jsp from the url www.myapp.com/mycontenxtroot/login
See here for some more info on view resolvers:
You might be interested in UrlRewriteFilter. This is the approach I would recommend. If you're serious about clean URLs you'll likely need it at some point anyway.
On the other hand, if it's a one-off, a minimal controller might be easier:
#Controller
public class Somepage {
#RequestMapping("/somepage")
public String handler() {
return "somepage.jsp";
}
}