Spring #RequestMapping, 404 error - java

So, I'm trying to learn Spring Framework, but currently I'm stuck on this problem, for some reason my mappings don't work and when I try to access that address I'm getting a 404 error.
Can someone please clarify what I'm doing wrong (both in usage of spring classes and the source of the problem I have described above)?
I'm configuring spring using the example shown in this video: YouTube Video, the code is basically the same, the only difference is package name and the location of the JSP file (could this be the source of my problem?).
The project was made in IntelliJ Idea and is attached to the following link (Google Drive): Project Link
As my servlet container I'm using Tomcat8 (tried both 9 and 8.5, no cigar).
HomeController.java
package com.demo.spring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
package com.demo.spring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Created by ARTERC on 1/16/2017.
*/
#Controller
public class HomeController {
#RequestMapping("/")
public String home() {
return "home";
}
}
WebInit.java
package com.demo.spring.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
#Configuration
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{RootConfig.class};
}
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{WebConfig.class};
}
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
WebConfig.java
package com.demo.spring.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#EnableWebMvc
#ComponentScan("com.demo.spring")
public class WebConfig extends WebMvcConfigurerAdapter{
#Bean
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/");
resolver.setSuffix(".jsp");
return resolver;
}
}
home.jsp path: /web/home.jsp

Okay, so I found the solution.
Add war plugin to pom.xml
Fix web resource directory path (was webapp) Image Link

Related

Spring on Wildfly not rendering index.html when root URL hit

Due to project requirements I have to deploy a Spring application to a server incapable of running Tomcat and only capable of running WildFly. When I had a very simple project running on Tomcat and the root URL was hit (localhost:8080) it rendered my index.html. Since migrating to WildFly and refactoring the structure of my project, localhost:8080 no longer renders the index.html but I can still reach other URLs.
I've tried to implement a jboss-web.xml file under BrassDucks/src/main/webapp/WEB-INF/jboss-web.xml like this:
<jboss-web>
<context-root>Brass-Ducks</context-root>
</jboss-web>
Where Brass-Ducks is the artifactID but to no avail.
Consider my ApplicationConfig.java
package brass.ducks;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class ApplicationConfig extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(ApplicationConfig.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(applicationClass);
}
private static Class<ApplicationConfig> applicationClass = ApplicationConfig.class;
}
#RestController
class GreetingController {
#RequestMapping("/hello/{name}")
String hello(#PathVariable String name) {
return "Hello, " + name + "!";
}
}
and consider my Controller.java
package brass.ducks.application;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/")
public class Controller {
#RequestMapping("/greet")
#ResponseBody
public String greeting() {
return "Hello, there.";
}
}
And finally should it be relevant, my folder structure:
localhost:8080/greet returns "Hello, there" and localhost:8080/hello/name returns "Hello name". How can I fix this?
Depending on your exact configuration something along the lines of this should work:
#Controller
public class LandingPageController {
#RequestMapping({"/","/home"})
public String showHomePage(Map<String, Object> model) {
return "/WEB-INF/index.html";
}
}
This is going to explicitly map / to index.html.

Spring MVC - Load bean definitions from appContext.xml programatically

I've been pulling my hair for hours on this one.
I am setting up a new Spring MVC REST servlet and I've been trying to avoid XML definitions this time and do it programatically.
To the problem: I am looking for a way to load bean definitions from applicationContext.xml while still having #ComponentScan(...) enabled (#Autowire/context.getBean(...) works in the latter).
I looked through the google trying countless combinations (I think, but I may have missed something) and found something that could help:
https://www.mkyong.com/spring/spring-mixing-xml-and-javaconfig/
... only it doesn't (#ImportResource("classpath*:applicationContext")).
Please bear in mind that following declarations to #ImportResource fail the deployment of artifact (built with Gradle) with no log whatsoever:
"applicationContext"
"classpath:applicationContext"
The application context is located just next to 'java' folder (Gradle folder structure [src/main/java]):
My root config:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ImportResource;
import org.springframework.stereotype.Controller;
#Configuration
#ImportResource("classpath:applicationContext.xml")
#ComponentScan(
basePackages = { "com.storfoome.backend" },
excludeFilters = {#Filter(classes = { Controller.class }, type = FilterType.ANNOTATION)}
)
public class ServiceRootConfig {
}
My web config:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#EnableWebMvc
#Configuration
#ComponentScan(
basePackages = { "com.storfoome.backend" },
useDefaultFilters = false,
includeFilters = { #Filter(classes = { Controller.class }, type = FilterType.ANNOTATION) }
)
public class ServiceWebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("*/resources/**").addResourceLocations("/resources/");
}
}
My servlet initializer:
import com.storfoome.backend.framework.rest.config.ServiceRootConfig;
import com.storfoome.backend.framework.rest.config.ServiceWebConfig;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class SofomeServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
private static final String DEFAULT_SERVLET_MAPPING = "/sofome/*";
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { ServiceRootConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] {ServiceWebConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[] { DEFAULT_SERVLET_MAPPING };
}
}
The bean with #Autowire from XML declared bean:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component("autowireTest")
public class AutowireTest {
#Autowired
private SofomePropertyResource propertyResource;
public void printProperty() {
System.out.println(propertyResource.getProperty("helloWorld"));
}
public AutowireTest() {
}
private String test;
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
}
My applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="sofomeProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath*:sofome.properties</value>
</list>
</property>
</bean>
</beans>
So, while I was posting this I also resolved this. So for anyone whould would be struggling with this.
Everything related to Java code in the question is correct apparently.
The thing was, with Gradle and it's "war" plugin. So, it looks into 'resource' folder by default for everything not *.java [citation needed].
I moved the applicationContext.xml to 'resource/config', launched Gradle build process (NOTE: I do not have any custom script written for WAR generation. Just "apply plugin: 'war'"):

Static files can not found Spring MVC + Thymeleaf

I have a spring application which is a starting project. I used Thymeleaf as template engine. But i have problem which is i can not reach to the static files such as CSS or javascript. This is my file structure for this application.
This is the configuration file for Thymeleaf engine. And i also tried to add resource handling which is : SpringBoot with Thymeleaf - css not found
package com.ggk.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.thymeleaf.spring4.SpringTemplateEngine;
import org.thymeleaf.spring4.view.ThymeleafViewResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
#Configuration
#EnableWebMvc
#ComponentScan("com.ggk")
public class ThymeleafConfig extends WebMvcConfigurerAdapter {
#Bean
public ServletContextTemplateResolver servletContextTemplateResolver() {
ServletContextTemplateResolver servletContextTemplateResolver = new ServletContextTemplateResolver();
servletContextTemplateResolver.setPrefix("/WEB-INF/templates/");
servletContextTemplateResolver.setSuffix(".html");
servletContextTemplateResolver.setTemplateMode("HTML5");
servletContextTemplateResolver.setCacheable(false);
return servletContextTemplateResolver;
}
#Bean
#Autowired
public SpringTemplateEngine springTemplateEngine(ServletContextTemplateResolver servletContextTemplateResolver) {
SpringTemplateEngine springTemplateEngine = new SpringTemplateEngine();
springTemplateEngine.setTemplateResolver(servletContextTemplateResolver);
return springTemplateEngine;
}
#Bean
#Autowired
public ThymeleafViewResolver thymeleafViewResolver(SpringTemplateEngine springTemplateEngine) {
ThymeleafViewResolver thymeleafViewResolver = new ThymeleafViewResolver();
thymeleafViewResolver.setTemplateEngine(springTemplateEngine);
return thymeleafViewResolver;
}
}
here is my index.html adding css files.
<link rel="stylesheet" href="../css/animate.css" th:href="#{/css/animate.css}" type="text/css"/>
I guess you cannot view the static resources directly via chrome as well, like:
http://<domain_name>:<port>/<context_root>/css/animate.css
I think it gives you a 404 error. If this is the case, that means your app needs a configuration to serve static resources. Basically you need to add a ResourceHandler to your config. See following link for an example:
https://stackoverflow.com/a/30663486/878361
In summary you need to:
extend WebMvcConfigurerAdapter (which you've already done)
override addResourceHandlers method and add your resource locations like follows:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
Move css and images to webapp.

How can this code work without #EnableMVC?

I have this code:
package biz.tugay.springJuly18.config;
/* User: koray#tugay.biz Date: 18/07/15 Time: 15:09 */
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
#SuppressWarnings(value = "unused")
public class MyWebAppInnit extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{RootConfigClass.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{ServletConfigClass.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
}
and the ServletConfig.class
package biz.tugay.springJuly18.config;
/* User: koray#tugay.biz Date: 18/07/15 Time: 15:10 */
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#ComponentScan(basePackages = "biz.tugay.springJuly18.web")
public class ServletConfigClass {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver =
new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
}
and finally a Controller:
package biz.tugay.springJuly18.web;
/* User: koray#tugay.biz Date: 18/07/15 Time: 12:53 */
import biz.tugay.springJuly18.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class MyWeb {
#Autowired
private MyService myService;
#RequestMapping("/test")
public ModelAndView helloWorld() {
ModelAndView mv = new ModelAndView();
mv.addObject("message", myService.sayHello());
mv.setViewName("koko");
return mv;
}
}
When I deploy this to Tomcat and go to /test I will be redirected to koko.jsp . So why does this work without #EnableWebMvc?
According to this answer here it should not?
Here is RootConfig.java
package biz.tugay.springJuly18.config;
/* User: koray#tugay.biz Date: 18/07/15 Time: 15:10 */
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan(basePackages = "biz.tugay.springJuly18.service")
public class RootConfigClass {
}
The DispatcherServlet has two fields
/** List of HandlerMappings used by this servlet */
private List<HandlerMapping> handlerMappings;
/** List of HandlerAdapters used by this servlet */
private List<HandlerAdapter> handlerAdapters;
whose values decide how a request will be handled (among other things). These fields are initialized and populated with values when the DispatcherServlet is initialized by the container. The values come from the context configuration you specify. If your context configuration doesn't provide at least one value of the appropriate type, the DispatcherServlet uses some defaults.
These defaults are included in a file named DispatcherServlet.properties which is in the same package as DispatcherServlet.
For HandlerMapping, the values (class names) are
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
The javadoc of AnnotationMethodHandlerAdapter states
Implementation of the HandlerAdapter interface that maps handler
methods based on HTTP paths, HTTP methods and request parameters
expressed through the RequestMapping annotation.
In other words, this implementation also uses methods annotated with #RequestMapping.
However, AnnotationMethodHandlerAdapter is deprecated
in Spring 3.2 in favor of RequestMappingHandlerAdapter
#EnabledWebMvc instead registers a RequestMappingHandlerAdapter, which is much more sophisticated.

ViewResolver using Java annotation

Is it possible in Spring 3.1.1 to configure a view resolver using Java annotations?
I am done with all configurations using Java annotations, but I am stuck at view resolver.
Code
package com;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import com.*;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
import org.springframework.web.servlet.view.JstlView;
#Configuration
#ComponentScan("com")
public class AppConfig
{
{
//Other bean declarations
}
#Bean
public UrlBasedViewResolver urlBasedViewResolver()
{
UrlBasedViewResolver res = new InternalResourceViewResolver();
res.setViewClass(JstlView.class);
res.setPrefix("/WEB-INF/");
res.setSuffix(".jsp");
return res;
}
}
I used this code and ran the application, but it's not returning the appropriate view. However, if I configure a viewresolver in the app-servlet.xml file, it works fine.
Your class should extend WebMvcConfigurerAdapter class. please have a look at below example
#Configuration
#ComponentScan(basePackages="com")
#EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter{
#Bean
public ViewResolver getViewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
I tested your scenario with Spring 4.3.4 and it is working ok.
I would suggest double checking packages you scan and that AppConfig is properly provided.
I am attaching all files starting from your AppConfig. Yet it is good to extend WebMvcConfigurerAdapter. The source code attached is not ideal, it s simplistic and only to try to reproduce the problem you have reported.
Starting from AppConfig:
package com;
import org.springframework.context.annotation.*;
import org.springframework.web.servlet.view.*;
#Configuration
#ComponentScan("com")
public class AppConfig {
#Bean
public UrlBasedViewResolver getViewResovler() {
UrlBasedViewResolver urlBasedViewResolver = new UrlBasedViewResolver();
urlBasedViewResolver.setViewClass(JstlView.class);
urlBasedViewResolver.setPrefix("/WEB-INF/jsp/");
urlBasedViewResolver.setSuffix(".jsp");
return urlBasedViewResolver;
}
}
Then:
package com;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { AppConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
Finally:
package com;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class MainController {
#RequestMapping("/")
public ModelAndView asdf() {
return new ModelAndView("ABC");
}
}
The problem with the above is that the DispatcherServlet.initViewResolvers get's called before the bean getViewResolver is defined and it cannot find the bean so it never adds the view resolver.
If you move the bean definition into an xml definition, it get's picked up. For some reason the MvcConfiguration class you have defined does not trigger a DispatcherServlet refresh if there are no ViewResolvers defined in the XML.

Categories