JspViewResolver doesn't work in java configuration - based spring applciation - java

I have only Java-based configuration in Spring Application. I have created user entity and Dao for finding / creating users.
The controller has two GET methods - one for user and one for users list and one POST method - for creating / editing a user.
After running at Tomcat 7 server it gives 404 error and message that 'The requested resource is not available.
Dispatcher servlet is configured in SpringWebAppInitializer.class:
public class SpringWebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(ApplicationContextConfig.class);
servletContext.addListener(new ContextLoaderListener(appContext));
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(DispatcherServlet.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
View resolver is defined in ApplicationContextConfig.class:
#Configuration
#ComponentScan("pl.wybornie.entity")
#EnableTransactionManagement
public class ApplicationContextConfig extends WebMvcConfigurerAdapter {
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
//other configuration beans...
}
Jsp files for userList and userForm are in WebContent project's folder under: /WEB-INF/pages/user/*.jsp
Controllers responsible for geting views are pasted below:
#Controller
#SessionAttributes({"user"})
public class UserController {
#Autowired
private UserDao userDao;
#RequestMapping(value = "/user_list.html", method = RequestMethod.GET)
public String list(Model model, HttpServletRequest request) {
model.addAttribute("userList", userDao.usersList());
return "user/userList";
}
#RequestMapping(value = "/create.html", method = RequestMethod.GET)
public String edit(#RequestParam(value="id", required=false) Long id, Model model) {
User user = userDao.findOrCreate(id);
model.addAttribute("user", user);
return "user/userForm";
}
#RequestMapping(method = RequestMethod.POST)
public String submitForm(#ModelAttribute("user") User user, BindingResult bindingResult, HttpServletRequest request, Model model) {
userDao.saveOrUpdate(user);
return "redirect:user_list.html";
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}

Your class should extend WebMvcConfigurerAdapter class.
#Configuration
#ComponentScan("pl.wybornie.entity")
#EnableWebMvc
public class ApplicationContextConfig extends WebMvcConfigurerAdapter{
}

Related

404Not Found error returned for Spring REST calls

I am trying to expose my existing web application through web services. For this I have created a REST controller to handle rest calls. I am not sure if I need to change the existing web configurations for web services to work. Below is the URL I am using to access the resources.
http://localhost:9090/HospitalProject/rest/patient/Solo100
#RestController
#RequestMapping("/rest/patient")
public class PatientRESTController {
#RequestMapping(path="/{name}", produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Patient> getPatientByName(#PathVariable("name") String name){
Patient patient = patientService.findPatient(name);
return new ResponseEntity<Patient>(patient, HttpStatus.OK);
}
}
public class ApplicationIntializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext springContext= new AnnotationConfigWebApplicationContext();
springContext.register(ApplicationConfig.class);
springContext.setServletContext(servletContext);
ServletRegistration.Dynamic dispatcherServlet = servletContext.addServlet("dispatcher", new DispatcherServlet(springContext));
dispatcherServlet.setLoadOnStartup(1);
dispatcherServlet.addMapping("/");
}
}
#Configuration
#ComponentScan(basePackages={"com.hp"})
#EnableWebMvc
public class ApplicationConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
return viewResolver;
}
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer){
configurer.enable();
}
}

Problems with controller mapping in Spring MVC

There are similar topics, but they all use xml configuration files. The reason why I'm writing this question is that I'm using annotations.
I experience problems running my app:
getting “WARN org.springframework.web.servlet.PageNotFound - No
mapping found for HTTP request with URI …” when trying to setup
Spring servlet
getting error 404 when trying to run it on server
Here is my code (package and imports are skipped):
1) initializer
public class WebInitializer implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx =
new AnnotationConfigWebApplicationContext();
ctx.register(AppConfig.class);
ctx.setServletContext(servletContext);
ServletRegistration.Dynamic servlet =
servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.addMapping("/");
servlet.setLoadOnStartup(1);
}
}
2) app config
#Configuration
#ComponentScan("ua.kiev.prog")
#EnableWebMvc
public class AppConfig {
#Bean
public EntityManager entityManager() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("AdvJPA");
return emf.createEntityManager();
}
#Bean
public AdvDAO advDAO() {
return new AdvDAOImpl();
}
#Bean
public UrlBasedViewResolver setupViewResolver() {
UrlBasedViewResolver resolver = new UrlBasedViewResolver();
resolver.setPrefix("/WEB-INF/pages/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
resolver.setOrder(1);
return resolver;
}
#Bean
public CommonsMultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
}
3) controller
#Controller
#RequestMapping("/Advertisement")
public class MainController {
#Autowired
private AdvDAO advDAO;
#RequestMapping("/")
public ModelAndView listAdvs() {
return new ModelAndView("index", "advs", advDAO.list());
}
#RequestMapping(value = "/add_page", method = RequestMethod.POST)
public String addPage(Model model) {
return "add_page";
}
#RequestMapping(value = "/search", method = RequestMethod.POST)
public ModelAndView search(#RequestParam(value="pattern") String pattern) {
return new ModelAndView("index", "advs", advDAO.list(pattern));
}
// more code goes here
}
The controller is mapped to /Advertisement, so app should be available at URL localhost:8080/Advertisement/ but it isn't. When I change mapping in annotation to "/" - it becomes available at localhost:8080/Advertisement/. How can it be?
And when I change it back to "/Advertisement" - the same probleb accurs (error 404 and exception "No mapping found for HTTP request with URI …")
So, where I've made a mistake in my code?
Or maybe the problem is in Eclipse/TomCat/Maven?
Source - https://github.com/KostyantynPanchenko/prog.kiev.ua.lesson09.adv
You should change mapping
#Controller
#RequestMapping("/")
public class MainController {
#Autowired
private AdvDAO advDAO;
#RequestMapping("/Advertisement")
public ModelAndView listAdvs() {
return new ModelAndView("index", "advs", advDAO.list());
}
The mistake that a mapper used the value from the annotation to match the request URL, and it can't match the last slash. Note, it should not happen in the above code.
How are you running the application? Atleast in tomcat each deployed application is served from specific context path. Context path is determined from the base file name, more on that here.
So if you're deploying Advertisement.war all requests to the app will be served from localhost:8080/Advertisement/ even though you're declaring the DispatcherServlet and Controller to /

AuthenticationCredentialsNotFoundException with Basic Authentication with Spring Rest Service

I got AuthenticationCredentialsNotFoundException running my Spring Rest Service which should be secured with basic authentication. This leads to HTTP 500 instead of the expected 403.
Anything missing in the configuration?
My Spring security config:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("bill").password("abc123").roles("USER");
}
}
My Spring config:
#Configuration
#ComponentScan(basePackages = {"com.dummy"})
#EnableWebMvc
#Import({MySecurityConfig.class})
public class MySpringConfig extends WebMvcConfigurerAdapter implements WebApplicationInitializer {
#Override
public void onStartup(final ServletContext servletContext) throws ServletException {
final AnnotationConfigWebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
final ServletRegistration.Dynamic dispatcher = servletContext.addServlet("springDispatcher",
new DispatcherServlet(context));
dispatcher.setLoadOnStartup(0);
dispatcher.addMapping("/");
}
private AnnotationConfigWebApplicationContext getContext() {
final AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(MySpringConfig.class);
return context;
}
}
My secured Controller:
#RestController
#RequestMapping("/dummy")
public class MyController {
#PreAuthorize("hasRole('USER')")
#RequestMapping(method = RequestMethod.POST)
public HttpEntity<?> doSomething() {
return new ResponseEntity<>(HttpStatus.CREATED);
}
}
My failing Test (actual: 500, expected: 403):
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(classes = MySpringConfig.class)
public class MyControllerTest {
#Autowired
protected WebApplicationContext context;
protected MockMvc mvc;
#Before
public void setUp() throws Exception {
new TestContextManager(getClass()).prepareTestInstance(this);
this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
}
#Test
public void doDummy_not_authorized_403() throws Exception {
final MockHttpServletResponse response = this.mvc.perform(post("/dummy")).andDo(MockMvcResultHandlers.print()).andReturn().getResponse();
assertThat(response.getStatus(), equalTo(403));
}
}

Getting 404 status spring 4 mvc with tomcat

I am doing little project using Spring+Hibernate. When I deploy my war and get 404 status all the time. I have checked some answers about it, but I didnt find my mistake. I tried to switch between / and /*, it didnt help. Tomcat doesnt show any errors in logs. Thanks in advance.
My WebConfig class
#Configuration
#EnableWebMvc
#ComponentScan({"controller", "dao"})
#EnableTransactionManagement
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public DataSource dataSource() {
SimpleDriverDataSource ds =
new SimpleDriverDataSource(org.h2.Driver.load(), "jdbc:h2:~/testdb", "sa", "sa");
return ds;
}
#Bean
#DependsOn("dataSource")
public LocalSessionFactoryBean sessionFactoryBean() {
LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSource());
sessionFactoryBean.setPackagesToScan("entity");
sessionFactoryBean.setHibernateProperties(hibernateProperties());
return sessionFactoryBean;
}
private Properties hibernateProperties() {
Properties p = new Properties();
p.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
p.setProperty("hibernate.hbm2ddl.auto", "update");
p.setProperty("hibernate.hbm2ddl.import_files_sql_extractor", "org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor");
p.setProperty("hibernate.show_sql", "true");
p.setProperty("hibernate.format_sql", "true");
return p;
}
#Bean
#DependsOn("sessionFactoryBean")
public PlatformTransactionManager transactionManager() {
SessionFactory sessionFactory = sessionFactoryBean().getObject();
HibernateTransactionManager tm = new HibernateTransactionManager(sessionFactory);
return tm;
}
#Bean(name = "viewResolver")
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
My WebAppInitializer class
public class SpringWebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(WebConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
"SpringDispatcher", new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
}
}
My Controller class
#Controller
public class MainController {
#Autowired
IDisksDao d;
#RequestMapping("/")
#Transactional
#ResponseBody
public String hello() {
return "hi";
}
#RequestMapping("disks/")
#Transactional
#ResponseBody
public ModelAndView getDisks() {
ModelAndView model = new ModelAndView("disks");
model.addObject("disks", d.getAllDisks() );
return model;
}
#RequestMapping("u/disks/{id}")
#Transactional
#ResponseBody
public List<Disk> getUserDisks(#PathVariable int id) {
return d.getAllUserDisks(id);
}
}
My project structure

Spring - Thymeleaf - 404 Error

I'm worked with Spring in the past on a big project, but I've never started a Spring MVC web app from scratch.
Well that's what I'm currently doing now for practice as I have a project coming up that will require it.
I was successfully able to make a simple Spring MVC Web App that used .JSP pages (using annotations, no XML).
I wanted to use Thymeleaf though and started my conversion process to that.
Well now I'm getting a 404 Error and my HomeController class isn't even being hit it seems like.
I get no errors in the Console output.
I've Google search, read through tutorials, and code samples. Second pair of eyes would be nice. Thanks! :)
Note: going from .JSP to Thymeleaf the only changes made was the addition of the ThymeleafConfig class. I don't see how it went from working to not working.
Here's my code:
WebInit.java
public class WebInit implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
// Creates the root application context
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(ServletConfig.class);
appContext.setDisplayName("REPLACE ME");
appContext.setConfigLocation("com.demo.config");
// Creates the Spring Container shared by all Servlets and Filters
servletContext.addListener(new ContextLoaderListener(appContext));
// Further configures the servlet context
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
"dispatcher", new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
dispatcher.setAsyncSupported(true);
dispatcher.addMapping("/");
}
}
ServetConfig.java
#Configuration
#Import(WebConfig.class)
#ImportResource({/*"classpath:META-INF/spring/persistence-context.xml"*/})
public class ServletConfig {
}
WebConfig.java
#Configuration
#ComponentScan("com.illinois.dnr")
#EnableAspectJAutoProxy
#EnableWebMvc
#Import({ThymeleafConfig.class})
public class WebConfig extends WebMvcConfigurerAdapter {
// Maps resources path to webapp/resources
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations(
"/resources/");
}
// Provides internationalization of messages
#Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
source.setBasename("messages");
return source;
}
}
Thymeleaf.java
#Configuration
public class ThymeleafConfig {
#Bean
public ServletContextTemplateResolver templateResolver() {
ServletContextTemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setOrder(1);
return resolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
return engine;
}
#Bean
public ThymeleafViewResolver thymeleafViewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
return resolver;
}
}
HomeController.java
#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 = "/dnr", 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";
}
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String loginPage(Locale locale, Model model) {
logger.info("Login");
return "login";
}
#RequestMapping(value = "/home", method = RequestMethod.POST)
public String login(#Validated User user, Model model) {
model.addAttribute("userName", user.getUserName());
logger.info("User");
return "user";
}
#RequestMapping(value = { "/", "/welcome**" }, method = RequestMethod.GET)
public ModelAndView welcomePage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security Hello World");
model.addObject("message", "This is welcome page!");
model.setViewName("hello");
logger.info("Hello");
return model;
}
#RequestMapping(value = "/admin**", method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security Hello World");
model.addObject("message", "This is protected page - Admin Page!");
model.setViewName("admin");
logger.info("admin");
return model;
}
#RequestMapping(value = "/dba**", method = RequestMethod.GET)
public ModelAndView dbaPage() {
ModelAndView model = new ModelAndView();
model.addObject("title", "Spring Security Hello World");
model.addObject("message", "This is protected page - Database Page!");
model.setViewName("admin");
logger.info("dba");
return model;
}
}
I'm not sure if it helps but you can simplified WebInit by extendsAbstractAnnotationConfigDispatcherServletInitializer instead of implements WebApplicationInitializer. Otherwise Thymeleaf configuration seems ok to me (suppose it's called). I'm giving here working skeleton of config so you can experiment with it.
WebApplicationInitializer
public class WebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
WebConfig
#Configuration
#EnableWebMvc
#ComponentScan("com.kreuzman")
public class WebConfig {
#Bean
public ITemplateResolver templateResolver() {
TemplateResolver resolver = new ServletContextTemplateResolver();
resolver.setPrefix("/templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode("HTML5");
resolver.setCacheTTLMs(0l);
return resolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
return engine;
}
#Bean
public ViewResolver thymeleafViewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setCharacterEncoding("UTF-8");
return viewResolver;
}
}
What page are you trying to hit? Does that html page exist in /WEB-INF/views/?
Is it a JSP page? you need to exclude all pages that are not going to be resolved by ThymeleafViewResolver. I also noticed you didn't set the ThymeleafViewResolver to first in the order.
Like so
#Bean
public ThymeleafViewResolver thymeleafViewResolver()
{
String[] excludedViews = new String[]{
"login", "logout"};
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
/*
* This is how we get around Thymeleaf view resolvers throwing an error instead of returning
* of null and allowing the next view resolver in the {#see
* DispatcherServlet#resolveViewName(String, Map<String, Object>, Locale,
* HttpServletRequest)} to resolve the view.
*/
resolver.setExcludedViewNames(excludedViews);
resolver.setOrder(1);
return resolver;
}

Categories