Spring MVC entry point - spring-mvc

I want my project to use more than one controller. My question is, how do I navigate from one controller to another and what should I do about having a standard home page for my users to land on? Should this be a separate "homeController"? I don't understand how this should work. The "Spring in Action" book doesn't go into enough details to explain this.
Thanks

You can use different Controllers (Java classes) with the #Controller annotation, depending on what you want to do is the URL associated with the method defined in the Controller, for example:
#Controller
public class HomeController {
#RequestMapping(value = "/home", method = RequestMethod.GET)
public ModelAndView home() {
//code to process for the /home url
}
// More code
}

In servlet-context.xml check
<context:component-scan base-package="com.domain.package.controller" />
And use
#Controller
In class you want to be controller.

You can use a dispatcher servlet to delegate to different controllers.
<servlet>
<servlet-name>your-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>your-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Now depending on your #RequestMapping bindings in your controllers, the DispatcherServlet will decide where to route requests.

Also please check the spring mvc showcase on github. https://github.com/SpringSource/spring-mvc-showcase

If your web is needs a common landing page like login.jsp you can do it like following way.
Configure you dispatcher servlet in web.xml as follows.
<servlet>
<servlet-name>public</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>public</servlet-name>
<url-pattern>/pub/*</url-pattern>
</servlet-mapping>
Then you should have a dispatcher servelt call public-servelt.xml where you handle the login requests for all users.It should contains configs like this.
<context:component-scan base-package="com.mycompany.web.controller.secure" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/pub/"
p:suffix=".jsp" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"
p:synchronizeOnSession="true" />
And then in your index.jsp where the common landing place of web app, put a jsp forward to hit above dispatcher servelt as follows.
<jsp:forward page="/pub/login" />
note : In your controller you need to have /login mapping in a get method as follows.
#RequestMapping(method = {GET, HEAD}, value = "/login")
public String loginHandler(.......){}
This is how normally achieve a common landing page through a spring controller.

Related

How to bypass certain url patterns not invoking dispatcher servelet in spring MVC

I declared below url pattern within servelet definition for handler mapping.
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Now i have some specific url with above '/' pattern (ex: /demo/), but i dont want to allow this request to get handled by dispatcher servlet (since i dont have any handler mapping in controller for this request).
Is there any similar prototype like mvc:resources ?
It would be very thankful if someone tells how to find out whether the declared resources are invoked properly or not?
I declared like this:
<mvc:resources mapping="/resources/**" location="/resources/MainTemplate/"/>
In jsp:
<link rel="stylesheet" href="/resources/css/components.css">
<script type="text/javascript" src="/resources/js/jquery-1.8.3.min.js"></script>
You can write an interceptor for the pattern you want and handle it there. Configure your interceptor as shown below for specific patterns. You can also exclude the url patterns you want from entering into the interceptor.
<mvc:interceptor>
<mapping path="/url_pattern/**"/>
<exclude-mapping path="/exclude/**"/>
..
</mvc:interceptor>

Spring mvc, why my controller not mapped

I defined my Dispatcher servlet's url mapping in web.xml like this:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
<url-pattern>/data/*</url-pattern>
</servlet-mapping>
my controller's method is annotated with:
#RequestMapping(value="/data/sys/CodeCatalogs")
when I request the url in browser I got 404 error, if I change the mapping to this:
#RequestMapping(value="/sys/CodeCatalogs")
the full url:
http://localhost:8080/cwe/data/sys/CodeCatalogs
it works, why? I am new to spring mvc, please help.
I tested url that contain no wildcard:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
<url-pattern>/data/*</url-pattern>
url-pattern>/test/foo</url-pattern>
</servlet-mapping>
then this request mapping will works:
#RequestMapping(value="/test/foo")
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
<url-pattern>/data/*</url-pattern>
</servlet-mapping>
In the preceding example, all requests starting with /data and anything which ends with *.do will be handled by the DispatcherServlet instance named dispatcher.
So for controller's method is annotated with:
#RequestMapping(value="/data/sys/CodeCatalogs")
http://localhost:8080/cwe/data/sys/CodeCatalogs - Does not match
http://localhost:8080/cwe/data/data/sys/CodeCatalogs - Does matches
URL passes from browser will be first matched against URL pattern specified and
then the URL specified in #RequestMapping.
For controller's method is annotated with :
#RequestMapping(value="/test/foo")
http://localhost:8080/cwe/test/foo - Matches since URL matches the exact pattern which is allowed as per Servlet Specification.
http://localhost:8080/cwe/data/test/foo - This will also match because of pattern /data/*
For an incoming request of the form /data/sys/CodeCatalogs, your servlet container will consume the /data/ portion before passing the pattern to your Spring servlet. So the controller will receive /sys/CodeCatalogs and hence this is why your second #RequestMapping works and the first does not.

Spring MVC behavior while co-existing with traditional web app servlets

We have an existing application not using Spring MVC. We decided to keep existing features as is and add Spring MVC in for any other new features through a url like "/admin/*.
so here is the web.xml mapping:
<servlet>
<servlet-name>springRouted</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc-config.xml</param-value>
</init-param>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springRouted</servlet-name>
<url-pattern>/admin/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ExistingServlet</servlet-name>
<url-pattern>existing.do</url-pattern>
</servlet-mapping>
Here in the ExistingServlet, there is a call to request.getRequestDispatcher().forward("/admin/...jsp"), somehow Spring will detect this fowarding and report an error that not able to find mapping for "/admin/...jsp". It seems calling request.getRequestDispatcher().forward("/admin/...jsp") will make servlet container to recheck the web.xml and reroute through Spring's DispatchServlet. is it true? I thought this kind of internal forward won't be intercepted by Spring's DispatchServlet
A RequestDispatcher will be resolved against the mappings you have in your deployment descriptor (web.xml) or other Servlet configuration, basically all servlet mappings.
When you do
request.getRequestDispatcher("/admin/...jsp");
The Servlet container finds the Servlet (or other resource) meant to handle that path and wraps it in a RequestDispatcher object. When you then perform RequestDispatcher#forward(..) on the returned object, you are executing the service() method of the Servlet that was previously found.
In your example, that would be the DispatcherServlet. If your DispatcherServlet is configured to handle a request to /admin/...jsp, then it will do so. If not, it will throw its own custom exception, responding to the HTTP request with a 404.
Here are some more details on how getRequestDispatcher() works.

HTTP 405 error when connecting to spring-security auto-generated log-in page

I cannot connect to the auto generated spring security log-in page. According to the documentation, including the following lines in your security-context.xml will have Spring generate an html log-in form and redirect the user to it when trying to connect to the specific URL:
<http auto-config="true" >
<intercept-url pattern="/management-console" access="ROLE_ADMIN"/>
</http>
<authentication-manager ... />
Here is the rest of my configuration. Web.xml:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:/context/applicationContext.xml <!-- I am importing my security-context.xml in here -->
<param-value>
</context-param>
<!-- Security Configuration -->
<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>/management-console</url-pattern>
</filter-mapping>
I have tried importing the security-context.xml directly in the web.xml, but I still see the error.
After deploying my application, I can connect to each my specified urls without issue. However, when I try to go to localhost:{port}/{appName}/management-console, the filter chain redirects me to /spring_security_login (as expected). However, I see an "HTTP Status 405 - Request method 'GET' not supported" error once I am forwarded and the following comes up on the console (spring-mvc is the name I gave to my servlet):
org.springframework.web.servlet.PageNotFound | No mapping found for HTTP request with URI [/InternalManagementViewer/spring_security_login] in DispatcherServlet with name 'spring-mvc' |
I have seen this error before when I miss declaring a POST/GET mapping in the controller. According to the documentation, I should not have to include such a method in my controller to handle the /spring_security_login mapping. From what I have read, spring is supposed to know to return the auto-generated log-in html page.
Just to see what happens, I declared a method in my controller to handle the /spring_security_login mapping. Since the function returns void (because I do not know the local view name of the generated html log-in page), it looks for the resource named "spring_security_login.jsp", which is not explicitly created in my project, and thus I get an "HTTP resource not found" error.
I'm stumped on this one and could really use a hand. Thanks a lot for taking a look.
Apply springSecurityFilterChain filter to all URLs:
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
springSecurityFilterChain is an entry point for all Spring Security features. So if this filter is not applied to some URL then you will not be able use Spring Security there (in this case handle /spring_security_login URL).

How to intercept all the requests for all the controller without HandlerInterceptor in Spring?

I have a requirement to intercept all the request in spring 2.5. I don't want to use HandlerInterceptor to intercept the request because it requires to configure it with every SimpleUrlHandlerMapping bean in the context files. Is there another way to intercept all the request without using HandlerInterceptor?
You could implement a filter and map it to the DispatcherServlet in web.xml. Then you should be able to intercept all request made to Spring MVC.
In short:
Create an implementation of javax.servlet.Filter
Add the filter to web.xml
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>mypackage.MyFilter</filter-class>
</filter>
and then map it to the DispatcherServlet (servlet-name should be the same that is defined for the Spring Dispatcher servlet.
<filter-mapping>
<filter-name>MyFilter</filter-name>
<servlet-name>DispatcherServlet</servlet-name>
</filter-mapping>
If you need access to the Spring ApplicationContext in the filter, use the static method
org.springframework.web.context.ContextLoader.getCurrentWebApplicationContext()

Resources