Spring MVC 4 controllers not called - java

EDIT: I realized I made a mistake in my ComponentScan as a lot of commenters pointed out, I changed it but it is still not working (still 404).
I have a project and I'm using all annotations-based configuration. Here is the configuration files:
WebConfig.java
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "src.controller")
public class WebConfig extends WebMvcConfigurerAdapter{
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
WebInitializer.java
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[] { "/" };
}
}
I also have a persistence config but I don't think that's relevant to this problem. Anyways, here is my root path controller:
AuthorController.java
#Controller
#RequestMapping({"/authors", "/"})
public class AuthorController {
#Autowired
AuthorService authorservice;
#RequestMapping(method=RequestMethod.GET)
public String getAuthors(ModelMap model){
System.out.println("----------called--------------"); //not printed
List<Author> authors = authorservice.getAllAuthors();
model.addAttribute("authors", authors);
return "authors";
}
}
The controller never gets called and I end up getting a 404 error.

Can you tell the name of the package to which 'AuthorController' belongs ? I think issue is with #ComponentScan(basePackages = "src"). Here you should add package name of the controller classes.
#ComponentScan(basePackages = "com.sample.app")
#ComponentScan(basePackages = "com.sample.*")
#ComponentScan(basePackages = "com.*")
All the above are valid entries for ComponentScan annotation.

The basePackages property of #ComponentScan annotation doesn't represent the folder where your java code is. It represents the root package of java classes where Spring should scan for Spring beans.
So, if you have your controllers in com.myapp.web.controllers then configure it as follows:
#ComponentScan(basePackages = "com.myapp.web.controllers")

Related

JavaConfig Spring Web Flow returns 404 not found (JSP)

I have been trying out the Java Configuration feature of Spring Web Flow 2.4 by modifying an existing project from xml configuration to JavaConfig. The XML version works, but JavaConfig doesn't. Every time I try to start the flow with URL http://localhost:8080/sia_p219_ch08_spring_web_flow_order_pizza_customer_flow_complete/pizza , it returns 404. There are no exceptions. The console show no "no request mapping found for..." message. The webpage shows The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
The project is hosted on github, the working XML version is here.
I think the problem is the request URL doesn't call the pizza flow (/WEB-INF/flows/pizza/pizza-flow.xml).
Here are some code snippets:
WebAppInitializer:
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { WebConfig.class };
}
#Override
// map DispatcherServlet to /
protected String[] getServletMappings() {
return new String[] { "/" };
}
RootConfig:
#Configuration
#Import({WebFlowConfig.class})
public class RootConfig {}
WebFlowConfig:
#Configuration
#ComponentScan({"pizza"})
public class WebFlowConfig extends AbstractFlowConfiguration {
static{
System.out.println("WebFlowConfig loaded");
}
#Autowired
private WebConfig webMvcConfig;
#Bean
public FlowDefinitionRegistry flowRegistry() {
return
getFlowDefinitionRegistryBuilder(flowBuilderServices())
.setBasePath("/WEB-INF/flows")
.addFlowLocationPattern("/**/*-flow.xml")
.build();
}
#Bean
public FlowExecutor flowExecutor(){
return getFlowExecutorBuilder(flowRegistry()).build();
}
#Bean
public FlowBuilderServices flowBuilderServices() {
return getFlowBuilderServicesBuilder()
.setViewFactoryCreator(mvcViewFactoryCreator())
.setDevelopmentMode(true)
.build();
}
#Bean
public MvcViewFactoryCreator mvcViewFactoryCreator() {
MvcViewFactoryCreator factoryCreator = new MvcViewFactoryCreator();
factoryCreator.setViewResolvers(Collections.singletonList(this.webMvcConfig.viewResolver()));
factoryCreator.setUseSpringBeanBinding(true);
return factoryCreator;
}
}
WebConfig
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
static{
System.out.println("WebConfig loaded");
}
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/flows/");
resolver.setSuffix(".jsp");
return resolver;
}
// configure static content handling
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
The flow definition files and JSPs are fine and you can see them on github if you want.
Thanks a lot, any help is greatly appreciated.
What I've found so far that the configuration definitely lacks this part of configuration in WebFlowConfig (take a look at the documentation page for integration with Spring MVC for details):
#Bean
#Autowired
public FlowHandlerAdapter flowHandlerAdapter(FlowExecutor flowExecutor) {
FlowHandlerAdapter flowHandlerAdapter = new FlowHandlerAdapter();
flowHandlerAdapter.setFlowExecutor(flowExecutor);
return flowHandlerAdapter;
}
#Bean
#Autowired
public FlowHandlerMapping flowHandlerMapping(FlowDefinitionRegistry flowDefinitionRegistry) {
FlowHandlerMapping flowHandlerMapping = new FlowHandlerMapping();
flowHandlerMapping.setFlowRegistry(flowDefinitionRegistry);
flowHandlerMapping.setOrder(0);
return flowHandlerMapping;
}
Also remove mvcViewFactoryCreator definition and setViewFactoryCreator call from the flowBuilderServices bean definition as well. It works for me.

IntelliJ IDEA not detect spring configuration (with annotation)

I'm trying little spring project and encounter a problem if i use xml configuration file (web.xml and spring-servlet.xml) everything is fine. If i use java annotation the problem come up :(
I'm so confuse why intellij idea not showing my web views in my webapp folder.
Not show jsp file (pressed Ctrl + space)
And cannot resolve any variable name in my controller class Cannot resolve var name
### Controller CLASS ###
#Controller
public class HomeController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(ModelMap modelMap) {
modelMap.addAttribute("message", "Hello, from java class");
return "welcome";
}
}
Configuration Class
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.toskbilisim")
public class HomeConfiguration extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
#Bean
public MessageSource messageSource(){
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
}

swagger for spring: No mapping found

I am trying to make a documentation of my API with swagger.
My REST API is written with the help of spring and typical Controller looks like:
#Controller
#RequestMapping("/mymapping")
public class ParameterController {
#Autowired
Mydao myDao;
/**
* GET list
*
* #return The resulting string
*/
//produces replaced accept-header
#RequestMapping(value="/Parameter", method=RequestMethod.GET, produces={MediaType.APPLICATION_JSON_UTF8_VALUE, "application/ld+json"})
public #ResponseBody List<String> getAllParameters() {
List<String> params= myDao.getAllParameters();
return params;
}
}
To configurate the Swagger I followed the instruction here:
added a package in Maven
created a configuration Java class SwaggerConfig (I use only Java-configuration for Spring)
added resource Handlers to the existing class extending WebMvcConfigurerAdapter
added packages "io.swagger" and "springfox.documentation" to the #ComponentScan annotation of the same class extending WebMvcConfigurerAdapter
But each time when I call http://localhost:8080/spring-security-rest/api/v2/api-docs I receive
16:43:43,370 WARN qtp1072754634-13 servlet.PageNotFound:1136 - No mapping found for HTTP request with URI [/spring-security-rest/api/v2/api-docs] in DispatcherServlet with name 'org.springframework.web.servlet.DispatcherServlet-437a7f13'
The system searches the path /spring-security-rest/api/v2/api-docs among the controllers' mappings. And does not find it.
What did I forget?
Thank you in advance.
I solved mine by placing the SwaggerConfig Java Class in the same package where I had a the class with #SpringBootApplication.
Heres a suggestion:
Typically this is due to improper use of component scan. You can read more about component scan here (read the 2 questions fully :) )
Click here for the 2 questions
my SwaggerConfig class look like this:
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket beerMapApi() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(regex("/api.*"))
.build()
.pathMapping("/")
.apiInfo(apiInfo());
}
#Bean
public UiConfiguration uiConfig() {
return UiConfiguration.DEFAULT;
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("title")
.description("description")
.version("0.1")
.build();
}
}
and this is how my WebMvcConfigurerAdapter.addResourceHandlers looks:
#Configuration
#EnableWebMvc
#ComponentScan({ "com.something.server.controller" })
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
registry
.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/jsp/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}

spring conditional feature enabling

For this question, say, we have a MVC configuration class:
#Configuration
public class MvcConfig extends WebMvcConfigurationSupport {
#Bean
public ViewResolver viewResolver() {
return new InternalResourceViewResolver();
}
// bla-bla
}
I have several bean definitions as usual in a configuration class. The question is while enabling some features such as #EnableCaching, #EnableMBeanExport, #EnableAspectJAutoProxy, how can i control enabling process of those features, ie:
#Configuration
// #EnableCaching instead of this
public class MvcConfig extends WebMvcConfigurationSupport {
#Autowired
SomeResource someResource;
#Bean
public SomeBean someBean() {
if(someResouce.someEvaluation(someParam)) {
enableCaching(); // is that enabling possible?
}
}
#Bean
public ViewResolver viewResolver() {
return new InternalResourceViewResolver();
}
// bla-bla
}
NOTE: I'm using spring 3.2.x

Combining Spring MVC 3.2 with Coda Hales metrics

i am trying to combine a Spring Web Application (completed Annotation Based configuration, no xml configuration) with metrics 3.0.
I am running the application inside a jetty.
This is my current configuration for the default DispatcherServlet:
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[] { "/" };
}
#Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
return new Filter[] { characterEncodingFilter };
}
}
This is the WebConfig:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.rebuy.silo.amqpredelivery")
#EnableJpaRepositories(basePackages = "com.rebuy.silo.amqpredelivery.domain")
#EnableAspectJAutoProxy
#EnableTransactionManagement
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
#Override
public void configureMessageConverters(
List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter();
jacksonConverter.setObjectMapper(objectMapper());
converters.add(jacksonConverter);
super.configureMessageConverters(converters);
}
#Bean
public ObjectMapper objectMapper() {
SimpleDateFormat format = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ssXXX");
format.setTimeZone(TimeZone.getTimeZone("GMT+1"));
ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(format);
return mapper;
}
}
I want to add these two Servlets:
https://github.com/codahale/metrics/blob/master/metrics-servlets/src/main/java/com/codahale/metrics/servlets/HealthCheckServlet.java
https://github.com/codahale/metrics/blob/master/metrics-servlets/src/main/java/com/codahale/metrics/servlets/MetricsServlet.java
What is the best way to do this? I think there should be some spring magic to make this extremly easy to do! But I was not able to find it :(
Thanks in advance
Björn
You can follow this codebase https://github.com/spiritedtechie/metrics-examples.
Or use this library called metrics-spring http://ryantenney.github.io/metrics-spring/
If you are using Spring and Metrics you should also be using #RyanTenney's Metrics-Spring module. It will simplify your Java config and make your Metrics usage much cleaner.
Take a look at the code behind the MetricsServlet and HealthCheckServlet. In my opinion its easier to just write your own Spring Controller to do the same thing than to figure out how to embed and wrap those old servlets.
Its easy!
Create a metrics specific config:
#Configuration
#EnableMetrics
public class MetricsConfig extends MetricsConfigurerAdapter {
#Override
public void configureReporters(MetricRegistry metricRegistry) {
registerReporter(ConsoleReporter
.forRegistry(metricRegistry)
.build()).start(5, TimeUnit.MINUTES);
}
}
And include it from your existing config by adding:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.rebuy.silo.amqpredelivery")
#EnableJpaRepositories(basePackages = "com.rebuy.silo.amqpredelivery.domain")
#EnableAspectJAutoProxy
#EnableTransactionManagement
#Import({MetricsConfig.class})
public class WebConfig extends WebMvcConfigurerAdapter {
...
The above config changes make it trivial to inject a MetricRegistry in any Spring component. All the MetricsServlet does is send the registry in response to the request. That is really easy to accomplish in a simple controller. For example:
#Controller
public class AdminMetricsController
{
#Autowired
MetricRegistry metricRegistry;
#RequestMapping(value = "/admin/metrics/", produces = {APPLICATION_JSON_VALUE})
public #ResponseBody MetricRegistry getMetrics(final HttpServletResponse response)
{
response.setHeader("Cache-Control", "must-revalidate,no-cache,no-store");
return metricRegistry;
}
}
A HealthCheckRegistry can be injected in a similar way and another method added which would respond to /admin/health/ or whatever url you wanted.
Take a look at the following answer. It explains how to register a Servlet via JavaConfig:
Spring JavaConfig: Add mapping for custom Servlet

Categories

Resources