I am new to Spring MVC. I went through the basic and everything works fine. Then when I try to hook up Spring MVC to my current project, the Controller did not get called.
Here is my servlet-context.xml
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory-->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="net.nelnet.quikstage.webapp.controller" />
And here is my Controller
package net.nelnet.quikstage.webapp.controller;
#Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
#RequestMapping(value = "/")
public String home(Locale locale, Model model) {
logger.info("Welcome! you are under Home Section "+ locale.toString());
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
return "/WEB-INF/views/home.jsp";
}
}
I separate my project into One parent and two sub-projects. I was trying to implement Spring MVC into one of the sub-projects. I am not sure weather the project structure cause the problem
Thank you guys. my spring config file is fine and no error on server startup. Actually I found the problem. By default, <resources mapping="/resources/**" location="/resources/" />, it doesn't like resource to be empty when there is "**" either delete the '**' or put something under the folder will solve the problem
Related
This question has been asked a lot of times, even after going through all the solutions i wansn't able to get hibernate validator working.
Controller class:-
#RequestMapping(value={"/setReg"},method={RequestMethod.GET,RequestMethod.POST})
public ModelAndView setRegistration( #Valid #ModelAttribute("userDetails") UserDetails userDetails,BindingResult bindingResult){
logger.info("setRegistration :Entry");
if(bindingResult.hasErrors()){
logger.info("binding success");
logger.info(userDetails.getUser_first_name());
logger.info("validation not working");
}
else{
logger.info("binding failure");
}
logger.info("setRegistration :Exit");
return null;
}
servlet-context:-
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<context:component-scan base-package="com.xmith.services"/>
<context:component-scan base-package="com.xmith.dao"/>
<context:component-scan base-package="com.xmith.models"/>
<context:component-scan base-package="com.xmith.sweb" />
<context:annotation-config/>
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
dependency:-
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.1.Final</version>
</dependency>
validation class:-
public class UserDetails {
private String user_id;
#Size(min=3,max=7,message="user first name must have max length 7")
private String user_first_name;
private String user_last_name;
private String user_age;
private String user_email;
private String user_password;
Note:-
in above code i am trying to validate "user_first_name"(min=3,max=7,message="user first name must have max length 7"), however when i enter input more than 7 it still sets "user_first_name".
output:---
17:33:12.399 [http-bio-8080-exec-1] DEBUG org.hibernate.validator.resourceloading.PlatformResourceBundleLocator - ValidationMessages not found.
17:33:12.401 [http-bio-8080-exec-1] DEBUG org.hibernate.validator.resourceloading.PlatformResourceBundleLocator - ContributorValidationMessages not found.
17:33:12.403 [http-bio-8080-exec-1] DEBUG org.hibernate.validator.resourceloading.PlatformResourceBundleLocator - org.hibernate.validator.ValidationMessages found.
17:33:12.417 [http-bio-8080-exec-1] INFO com.xmith.sweb.HomeController - setRegistration :Entry
17:33:12.418 [http-bio-8080-exec-1] INFO com.xmith.sweb.HomeController - binding success
17:33:12.418 [http-bio-8080-exec-1] INFO com.xmith.sweb.HomeController - qwertyuiiii
17:33:12.418 [http-bio-8080-exec-1] INFO com.xmith.sweb.HomeController - validation not working
17:33:12.418 [http-bio-8080-exec-1] INFO com.xmith.sweb.HomeController - setRegistration :Exit
What am i missing here?
my boolean logic was wrong as pointed by – JB Nizet
I am using Spring MVC and Tiles.
When I try to use spring prefix "redirect:" for the redirection I get a servlet exception
- "Could not resolve view...".
Controller
RequestMapping("/SUPPORT.lz")
public String generateSupportView(HttpServletRequest request)
{
String url="http://"+request.getServerName()+":"+request.getServerPort()+"/APP";
AuthenticatedUser user = getUser();
/*
* Check if a user has the role for the page he is trying to access. If
* not redirect him to default page (home page).
*/
if (user.getRoles() != null && !user.getRoles().contains(new Role(0, Role.RoleType.SUPPORT)))
{
return "redirect:"+url;
}
return "support.tiles";
}
dispatcher-servlet.xml
<bean id="tilesViewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver"
p:order="1"
p:viewNames="*.tiles"
p:viewClass="org.springframework.web.servlet.view.tiles2.TilesView"/>
<bean id="nontilesViewResolver"
class="org.springframework.web.servlet.view.XmlViewResolver"
p:order="2"
p:location="/WEB-INF/app-nontiles-views.xml"/>
<bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles2.TilesConfigurer"
p:definitions="/WEB-INF/app-tiles.xml"/>
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource"
p:basename="i18n"/>
Solution-
I added internal view resolver in disaptacher servlet.xml and issue got resolved.
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:order="3">
</bean>
I have a bean as follows:
<bean id="myBean" class="MyBeanClass">
<constructor-arg value="\WEB-INF\myfile.dat"/>
</bean>
In the bean's contructor, I need to build the file's full path. To do that, I have to first find the app's root path first.
Thanks and regards.
Update
Per Michael-O's suggestion, here is my solution (so easy).
Spring bean:
<bean id="myBean" class="MyBeanClass">
<constructor-arg value="/myfile.dat"/> <!--under WEB-INF/classes-->
</bean>
Java:
public MyBeanClass(String path) throws Exception {
ClassPathResource file = new ClassPathResource(path);
lookup = new LookupService(file.getFile().getPath(), LookupService.GEOIP_MEMORY_CACHE);
}
Michael, thanks!!!
Use Spring's Resource class in your bean and spring will do the rest for you.
After seeing #curious1's edit, there is a better solution to his answer. Please do not use that. Go with this one:
beans.xml:
<!-- START: Improvement 2 -->
<context:annotation-config />
<bean id="service" class="LookupService">
<constructor-arg value="classpath:/myfile.dat"/> <!--under WEB-INF/classes-->
<constructor-arg>
<util:constant static-field="LookupService.GEOIP_MEMORY_CACHE"/>
</constructor-arg>
</bean>
<!-- END: Improvement 2 -->
<!-- Spring autowires here -->
<bean id="myBean" class="MyBeanClass" />
<!-- START: Improvement 1 -->
<bean id="myBean" class="MyBeanClass" />
<constructor-arg value="classpath:/myfile.dat"/> <!--under WEB-INF/classes-->
</bean>
<!-- END: Improvement 1 -->
Java:
public MyBeanClass(Resource path) throws Exception {
lookup = new LookupService(path.getInputStream(), LookupService.GEOIP_MEMORY_CACHE);
}
This is source-agnostic, does not rely on files and is the Spring way.
Edit 2: Rethinking my code, it can be even better:
public class MyBeanClass {
#Autowired
LookupService service;
}
and configure LookupService in your beans.xml.
Maybe you should consider using:
getClass().getClassLoader().getResourceAsStream()
inside constructor. This will use your classpath, so you "WEB-INF\myfile.dat", will be visible. Next think is use resource directory to put all resources in one directory (default: under root directory in WAR file)
I am currently using Spring MVC 3.x,
and using the freemarker view resolver.
Recently i have been wondering about the execution time that it takes for a view to translate into html before getting sent back as a response. I would like to do tunings if things are slow in this area, which is why i need some numbers.
In plain freemarker mode, i can actually do the simple System.currentTimeMillis() between these to find out the execution time :
long start = System.currentTimeMillis();
// this could be slow or fast depending on the caching used
Template temp = cfg.getTemplate(ftlName);
...
temp.process(model, myWriter); // depends on the writer
System.out.printf("done in %s ms", System.currentTimeMillis() - start);
But how do i do this when with spring mvc's freemaker view rendering ?
You might consider extending org.springframework.web.servlet.view.freemarker.FreeMarkerView and configuring FreeMarkerViewResolver with your custom logging view implementation.
Logging view implementation could look like this:
public class LoggingFreeMarkerView extends FreeMarkerView {
private static final transient Log log = LogFactory.getLog(LoggingFreeMarkerView.class);
#Override
protected void doRender(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
long start = System.currentTimeMillis();
super.doRender(model, request, response);
log.debug("Freemarker rendered " + request.getRequestURI() + " in " + (System.currentTimeMillis() - start) + " ms");
}
}
And wire the view resolver with new class:
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver" autowire="no">
<property name="viewClass" value="com.example.LoggingFreeMarkerView" />
<property name="cache" value="false" /> <!-- cache disabled for performance monitoring -->
<property name="prefix" value="" />
<property name="suffix" value=".ftl" />
<property name="contentType" value="text/html;charset=utf-8" />
<property name="exposeRequestAttributes" value="true" />
<property name="requestContextAttribute" value="base" />
</bean>
You are going to calculate just on server side merging template with data,Main problem is when freemarker executing on page ,As you know freemarker built on top of jsp page so you should bring code to jsp side to calculate execution time,
As my experience according to data size load time in freemarker is different.
if else condition also is too slow compare to jstl!
I can recommend thymeleaf for spring that allowing templates to be working prototypes on not xml style .
Hi I used Internal resource view resolver and my structure of jsp are like
jsp/adm, jsp/icon, jsp/iload, like
and my annotation based controller will return string value based on condition
my problem is jsp uder sub-folder is not resoled but it is under jsp folder is working
could any one please help me in this
he is my code:`
<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>
my controller code is
#RequestMapping("/icrl")
public String search() throws Exception
{
setMenuName(CommonConstants.ICRL);
return "pgiCRL";
}
#RequestMapping("/searchCodes")
public String searchCodes() throws Exception
{
String key=getSearchKey();
String query=getQuery();
Map<String, Object> searchKeys = new HashMap<String, Object>();
ArrayList<String> list=new ArrayList<String>();
if(query!=null||!query.isEmpty()){
searchKeys.put(CommonConstants.DIAGICD9, getDiaICD9());
searchKeys.put(CommonConstants.DIAGICD10, getDiaICD10());
searchKeys.put(CommonConstants.DIAGNOSIS, getDiagnosis());
searchKeys.put(CommonConstants.PROCEDURE, getProcedure());
searchKeys.put(CommonConstants.SURGICAL, getSurgical());
searchKeys.put(CommonConstants.SURGICAL9, getSurICD9());
searchKeys.put(CommonConstants.SURGICAL10, getSurICD10());
searchKeys.put(CommonConstants.REVENUE, getRevenue());
list= (ArrayList<String>) iCRLService.getSearchCodeList(query,searchKeys);
}
setSuggestions(list);
return CommonConstants.SUCCESS;
}
my view is depending on condition it may be success page and failure page so i need to fix the return value in controller because that is dynamic.
Thanks in advance
You need to define the subfolder name in the returning string value.
For Example, if your page "pgiCRL" is in admin subfolder then return "admin/pgiCRL".