URL pattern servlet mapping - spring-mvc

I created hello world example using Spring MVC, but there is one thing I didn't understand in servlet URL mapping, I did the following in web.xml:
<servlet>
<servlet-name>HelloWeb</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloWeb</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>
now if I want to call the following controller:
#Controller
#RequestMapping("/hello")
public class HelloWorld {
#RequestMapping(method = RequestMethod.GET)
public String printWelcome(ModelMap model){
model.addAttribute("message","hello world");
return "index";
}
}
it will work using the following link:
http://localhost:8080/test/hello
but when I change the servlet url-pattern to "/*" and try:
http://localhost:8080/hello
it doesn't work, shouldn't it match my servlet ? as * matches everything

When you register a servlet with "/*" then it will override all the servlet mappings if there are any. Hence it should be avoided. This overrides default servlet mapping as well hence all default url handling also overridden and hence any specific url matching fails. In your case it is /hello.
With your case, initially you registered with /test/* this registered all your URL's with /test and hence they got identified.

It doesn't work for /* because, you have not registered/created a controller for that pattern.
It worked for http://localhost:8080/hello because, you have controller #RequestMapping("/hello")
Just change the RequestMapping to #RequestMapping("/") for url-pattern /*

Related

Character-encoding Spring MVC

I am having trouble with Turkish characters...In my JSP pages, there is no problem... but, when an alert come from Java side, Turkish character(ŞşİığĞüÜç...) seems like that (ı,?,ü,ç,Å,...)
In JSP pages, I use this code and ı can solve Turkish character problem
<%# page contentType="text/html;charset=UTF-8" language="java"%>
in Spring MVC config, I tried a lot of way but I didn't succeed... For example In my mvc config class, I set my MessageSource like that;
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(0);
return messageSource;
}
In this program, I try to reset password and I typed unregister email address..Finally I am getting exception and this following is exception code blog.
#Autowired
private MessageSource messages;
...
#ExceptionHandler({ UserNotFoundException.class })
public ResponseEntity<Object> handleUserNotFound(final RuntimeException exception, final WebRequest request) {
logger.error("404 Status Code", exception);
final GenericResponse bodyOfResponse = new GenericResponse(messages.getMessage("message.userNotFound", null, request.getLocale()), "UserNotFound");
return handleExceptionInternal(exception, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
In my messages_tr_TR.properties file,
...
message.userNotFound=Kullanıcı Bulunamadı
...
but In JSP pages this alert shows like that;
Kullanıcı Bulunamadı
How can I solve this problem..
Comment follow-up, you can set the encoding in your response header as well. An example if you're returning json would be
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.add("Content-Type", "application/json; charset=utf-8");
return handleExceptionInternal(exception, responseHeaders, HttpStatus.NOT_FOUND, request);
In web.xml:
<jsp-config>
<!-- global JSP configuration -->
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Put the actual text in the handler method (temporarily). Does it now look right? Is your messages file correctly saved as UTF-8? Also, I can't tell if you're using JSON or not...

Spring-mvc servlet mapping, is it possible to have "/" for servlet 1 and "/server/" for servlet 2?

Currently I have the following web.xml config:
<servlet>
<servlet-name>Website</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Website</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>Server</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Server</servlet-name>
<url-pattern>/server/</url-pattern>
</servlet-mapping>
As for two example controllers:
#Controller
public class ApiRequests {
protected final Logger logger = Logger.getLogger(ApiRequests.class);
#RequestMapping(value = "api.json", produces = {"application/json"}, method = RequestMethod.GET)
#ResponseBody
public String handleActionJson(final HttpServletRequest request){
return "{test: 'blaat'}";
}
}
And
#Controller
#RequestMapping("/")
public class IndexController {
#RequestMapping("*.html")
public void showIndex(){
}
}
Now my problem is that when I try to call the /server/api.json url, the server won't give the json response, instead it gives me the following error:
PageNotFound:1108 - No mapping found for HTTP request with URI [/WorldDefense/server/api.json] in DispatcherServlet with name 'Website'
Which basically means its trying to search for /server/api.json in the Website servlet instead of the Server serlvet, as for my question: would it be possible to get this setup to work? (So /server/ to map to the Server servlet and all the other url combinations to the Website servlet)
Edit 1
I updated the code to reflect the changes as suggested by Costi Ciudatu but it still doesn't work. I removed the #RequestMapping("/server") and now only have the #RequestMapping at the handleActionJson method. Both resulting in these errors:
10:57:26,046 WARN PageNotFound:1108 - No mapping found for HTTP request with URI [/WorldDefense/server/server/api.json] in DispatcherServlet with name 'Website'
10:57:40,509 WARN PageNotFound:1108 - No mapping found for HTTP request with URI [/WorldDefense/server/api.json] in DispatcherServlet with name 'Website'
Mappings according to the tomcat log:
Server-servlet
11:03:49,655 INFO RequestMappingHandlerMapping:178 - Mapped "{[/api.json],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[]}" onto public java.lang.String com.world2.worlddefense.server.controllers.ApiRequests.handleActionJson(javax.servlet.http.HttpServletRequest)
11:03:50,125 INFO RequestMappingHandlerMapping:178 - Mapped "{[/api.json],methods=[GET],params=[],headers=[],consumes=[],produces=[application/json],custom=[]}" onto public java.lang.String com.world2.worlddefense.server.controllers.ApiRequests.handleActionJson(javax.servlet.http.HttpServletRequest)
Website-servlet
11:03:50,380 INFO RequestMappingHandlerMapping:178 - Mapped "{[//*.html],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public void com.world2.worlddefense.website.controllers.IndexController.showIndex()
11:03:50,381 INFO RequestMappingHandlerMapping:178 - Mapped "{[/login],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.world2.worlddefense.website.controllers.TempTestController.showTest()
You can define multiple DispatcherServlets in the same web.xml and map them as you wish. However, the servlet mapping should not be reflected in the #RequestMapping of your controllers. Your controllers always map to paths relative to the servlet mapping; in your case, I think you could get that JSON response if you tried /WorldDefence/server/server/api.json...
If you want different controllers to be associated with the two dispatchers, you only need to make sure that the proper controllers are loaded in the corresponding application context: Website-servlet.xml and Server-servlet.xml in case you stick with this convention.
Long story short, your mapping for ApiRequests should be '/', not '/server' and that controller should only be included in the "Server" dispatcher context.
As a side note, since 3.2.x, the .json extension is handled by the ContentNegotiationManager, so your controller should return some domain object which will be transparently marshaled by the Spring HttpMessageConverter mechanism and will thus be able to produce media types other than JSON with no effort.

URL mapping problems using Spring MVC

I have a very basic setup which I am trying to get working.
web.xml
<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>/site/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
mvc-dispatcher-servlet.xml
<context:component-scan base-package="com.blabla.controller" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/pages/" p:suffix=".jsp"
p:viewClass="org.springframework.web.servlet.view.JstlView" />
In the controller
#Controller
#RequestMapping(value = "/site")
public class SearchController {
#RequestMapping(value = "welcome", method = RequestMethod.GET)
public String test() {
return "test";
}
This is the problem that I have:
I would like to write /site/* as url-pattern in my web.xml, but when I do that I get
WARNING: No mapping found for HTTP request with URI [/site/welcome] in DispatcherServlet with name 'mvc-dispatcher'
When I write /site/welcome in full, everything works, but I dont want this because I dont want to add every page manually to the web.xml
And when I write "/*" as url-pattern i get the error message:
WARNING: No mapping found for HTTP request with URI [/WEB-INF/pages/test.jsp] in DispatcherServlet with name 'mvc-dispatcher'
which I guess makes sense because the the location of the jsp is included in the pattern.
So how do you do it: how can you be sufficiently vague in your url pattern without the problems I just had?

How do I integrate Sitemesh 3 with Spring MVC 3?

I am trying to use Sitemesh 3 to control the decoration of JSP output from a Spring MVC application.
When I hit the application it seems that Sitemesh is making a request to the Spring servlet to try and retreive its decorator file. This may, or may not be correct behaviour but it is causing me all many of headaches.
My understanding of Sitemesh 3 is that it does its work after Spring, ie on the Response object.
The error I'm getting in the browser is a 404 and in the logs (config/code follows):
INFO: Server startup in 1367 ms
DEBUG: org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name
'springiness' processing GET request for [/clientmanager/]^M
DEBUG:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -
Looking up handler method for path /^M
DEBUG: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -
Returning handler method [public java.lang.String
uk.co.hermes.HomeController.home(java.util.Locale,org.springframework.ui.Model)]^M
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Returning
cached instance of singleton bean 'homeController'^M
DEBUG: org.springframework.web.servlet.DispatcherServlet - Last-Modified value for
[/clientmanager/] is: -1^M
INFO : uk.co.hermes.HomeController - Welcome home! The client locale is en_GB.^M
DEBUG: org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking
afterPropertiesSet() on bean with name 'home'^M
DEBUG: org.springframework.web.servlet.DispatcherServlet - Rendering view
[org.springframework.web.servlet.view.JstlView: name 'home'; URL [/WEB-
INF/jsp/home.jsp]] in DispatcherServlet with name 'springiness'^M
DEBUG: org.springframework.web.servlet.view.JstlView - Added model object 'serverTime'
of type [java.lang.String] to request in view with name 'home'^M
DEBUG: org.springframework.web.servlet.view.JstlView - Forwarding to resource [/WEB-
INF/jsp/home.jsp] in InternalResourceView 'home'^M
DEBUG: org.springframework.web.servlet.DispatcherServlet - Successfully completed
request^M
DEBUG: org.springframework.web.servlet.DispatcherServlet - DispatcherServlet with name
'springiness' processing GET request for [/clientmanager/WEB-
INF/decorators/mainDecorator.html]^M
DEBUG:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -
Looking up handler method for path /WEB-INF/decorators/mainDecorator.html^M
DEBUG:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -
Did not find handler method for [/WEB-INF/decorators/mainDecorator.html]^M
WARN : org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request
with URI [/clientmanager/WEB-INF/decorators/mainDecorator.html] in DispatcherServlet
with name 'springiness'^M
DEBUG: org.springframework.web.servlet.DispatcherServlet - Successfully completed request^M
I suspect it's a problem in my web.xml and how I've defined the mappings(URLs):
<servlet>
<servlet-name>springiness</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springiness</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<filter>
<filter-name>sitemeshfilter</filter-name>
<filter-class>uk.co.hermes.filters.SitemeshFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemeshfilter</filter-name>
<!-- leaving SitemeshFilter class to decide which responses it should decorate -->
<url-pattern>/*</url-pattern>
</filter-mapping>
My custom filter:
public class SitemeshFilter extends ConfigurableSiteMeshFilter {
private Logger log = LoggerFactory.getLogger(SitemeshFilter.class);
/**
* See http://wiki.sitemesh.org/display/sitemesh3/Configuring+SiteMesh+3
*/
#Override
protected void applyCustomConfiguration(SiteMeshFilterBuilder builder) {
log.debug("** hit the sitemesh filter");
// apply this decorator (template) to the path defined...
builder.addDecoratorPath("/*", "/WEB-INF/decorators/mainDecorator.html");
// ... when the response type matches one of these
builder.setMimeTypes("text/html", "application/xhtml+xml", "application/vnd.wap.xhtml+xml");
}
}
WEB-INF/
|-jsp
|-home.jsp
|-decorators
|-mainDecorator.html
And my super simple Controller:
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! The client locale is {}.", locale);
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "home";
}
Since no one has posted actual content, here you go:
in pom.xml add:
<dependency>
<groupId>org.sitemesh</groupId>
<artifactId>sitemesh</artifactId>
<version>3.0.0</version>
</dependency>
in WEB-INF/web.xml † add:
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>org.sitemesh.config.ConfigurableSiteMeshFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
in WEB-INF/sitemesh3.xml add:
<sitemesh>
<mapping path="/*" decorator="/WEB-INF/decorator1.jsp"/>
</sitemesh>
in WEB-INF/decorator1.jsp add:
<html>
<head>
...
</head>
<body>
<sitemesh:write property='body'/>
</body>
</html>
† put this below your Spring Security Filter Chain if using Spring Security.
Here is another blog that shows the integration between Sitemesh 3 and Spring MVC
In my case, I used this little tutorial to make it works.

Servlet url pattern - java.lang.NullPointerException in servlet Context

my servlet performs three tasks:
When it receives a message "resourceupdate" stores the requested resource (an HTML page) to an object sharedClient.
When it receives an asynchronous get (querystring indicated by "t = UPDATE") adds the object sharedClient this request pending.
When it receives a delivery_resource (indicated by pathinfo myServlet/sharedsessionID - eg. myServlet/8439jfndofsd93jcanjc) performs the dispatch of the resource.
this is my Web.xml:
<servlet>
<description></description>
<display-name>MyServlet</display-name>
<servlet-name>MyServlet</servlet-name>
<servlet-class>it.package.MyServlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/MyServlet/*</url-pattern>
</servlet-mapping>
I keep all the active SharedClients in this way:
ConcurrentHashMap<String, SharedClient> hmClients = (ConcurrentHashMap<String, SharedClient>) this.getServletConfig().getServletContext().getAttribute("sharedClients");
And I get the SharedClient with a specific SharedSessionID in this way:
SharedClient targetClient = hmClients.get(ssid);
now the problem:
until I do a resourceupdate servlet works fine, but when i do a delivery_resource (to a path of type myServlet/sharedsessionID) the servlet is unable to obtain the sharedClient reference, and I get a Null Pointer Exception.
if (resourceUri!=null) {
String ssid = resourceUri.substring(1);
ConcurrentHashMap<String, SharedClient> hmClients = (ConcurrentHashMap<String, SharedClient>) this.getServletConfig().getServletContext().getAttribute("sharedClients");
if (hmClients.containsKey(ssid)) {
SharedClient targetClient = hmClients.get(ssid);
if (targetClient.getParticipantSession().containsKey(session)) {
IoUtils.copy(targetClient.streamSnapshot(), response.getOutputStream());
}
} else System.out.println("hmClient do not contains ssid"); //always in this branch
From this time also the long polling with asynchronous get are not completed successfully.
If i do not do a delivery_resource to a path of type myServlet/sharedsessionID after the update the asynchronous get continue to function properly.
Thanks to all.
ok, i resolved.
i need to write
#WebServlet(urlPatterns = {"/myServlet/*"}, asyncSupported=true)
before myServlet declaration.

Resources