Spring MVC application deploying multiple times in tomcat - java

I have application with spring mvc annotation configuration. In my local environment(IDE) it is working perfectly. When i deployed in prod(tomcat 8.5) my application listener calling multiple times. Because of this my executor tasks, schedulers calling multiple times.
AppWebAppInitializer.java
package com.app.config;
public class AppWebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(AppMvcConfig.class);
servletContext.addListener(new ContextLoaderListener(ctx));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("appServlet",new DispatcherServlet(ctx));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
dispatcher.setAsyncSupported(true);
servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE)); //uses cookies instead of jsessionId in the url.
}
}
AppMvcConfig.java
package com.app.config;
#Configuration
#EnableWebMvc
#EnableScheduling
#EnableCaching
#ComponentScan("com.app")
#Import({
AppPropertyInitConfig.class,
AppSecurityConfig.class,
WebSocketConfig.class
})
public class AppMvcConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware{
private ApplicationContext applicationContext;
#Value("${app.upload.dir}")
private String uploadDir;
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
ApplicationStartupListener.java
package com.app.listener;
#Component
public class ApplicationStartupListener {
private final Logger logger = LoggerFactory.getLogger(ApplicationStartupListener.class);
#Autowired
private LookupHolder lookupHolder;
#EventListener
public void handleContextRefreshEvent(ContextRefreshedEvent event) {
logger.info("ApplicationStartupListener initializing lookups");
Runnable lookupInitRunnable = () -> lookupHolder.init(); //initialize the lookups
new Thread(lookupInitRunnable).start();
}
}
In above code ApplicationStartupListener.java --> handleContextRefreshEvent() calling multiple times. As well as my spring default schedules also calling multiple times
In my application i don't have web.xml

Related

How to enforce Tomcat to accept DispatcherServlet url mapping, configured programmaticaly?

I'm running a hello-world Spring WebMVC sample of 3 classes: WebApplicationInitializer, WebMvcConfigurer and simple controller with a single request handler method.
Inside WebApplicationInitializer 'onStartup(ctxt)' the DispatcherServlet instance is mapped to '/app/*' URL pattern and reflected in ctxt.context.context.servletMapping value as {*.jspx=jsp, /app/*=dispatcher, *.jsp=jsp, /=default} in runtime.
But for unknown reason GET e.g. 'http://localhost:8080/app/sht' is dispatched to Tomcat's DefaultServlet! In runtime the request's context servlet mapping(request.request.applicationMapping.mappingData.context.servletMapping) value states that onStartup() configuration is lost: {*.jspx=jsp, *.jsp=jsp, /=default}
Could you please assist in configuring Spring properly? Thanks!
Spring 5.2.2; Tomcat 9.0.30, running under Eclipse.
public class WebbAppInitializer implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext context) throws ServletException{
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.setServletContext(context);
dispatcherContext.register(SpringWebConfig.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = context.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/app/*");
}
}
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = { "cool.videoservice.controller" })
public class SpringWebConfig implements WebMvcConfigurer{
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setViewClass(JstlView.class);
bean.setPrefix("/WEB-INF/view/");
bean.setSuffix(".jsp");
return bean;
}
}
#Controller
public class IndexController{
#GetMapping("/sht")
public String greeting(#RequestParam(name="name", required=false, defaultValue="World") String name, Model model) {
model.addAttribute("name", name);
System.out.println("Oh, yeah!!!!!!");
return "index";
}
}

Can not call interceptor when using #AutoConfigureAfter(WebMvcAutoConfiguration.class) and annotation-driven

While implementing the interceptors in my spring boot application I came across a weird problem which is as follows:
My Application class code:
#Import(CommonConfig.class)
#EnableAsync
#SpringBootApplication
#EnableSwagger2
#EnableScheduling
#EnableSpringDataWebSupport
#ImportResource({ "classpath:META-INF/applicationContext.xml" })
#AutoConfigureAfter(WebMvcAutoConfiguration.class)
public class Application extends SpringBootServletInitializer {
private static final Logger LOG = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
.......
................
}
#Bean
public TokenInterceptor intializeTokenInterceptor() {
System.out.println("Adding interceptors");
return new TokenInterceptor();
}
#Bean
public WebMvcConfigurerAdapter adapter() {
return new WebMvcConfigurerAdapter() {
#Override
public void addInterceptors(InterceptorRegistry registry) {
System.out.println("Adding interceptors");
registry.addInterceptor(intializeTokenInterceptor()).addPathPatterns("/**");
super.addInterceptors(registry);
}
};
}
}
Inside my application-context I have mentioned tag (mvc:annotation-driven) as I need this for initializing my bean classes.
Now, if I test my application by removing the annotation-driven tag, my interceptors are getting called. However, if I keep this tag, my interceptors are not getting called, (which I believe is overriding the implementation of WebMvcConfigurerAdapter bean from WebMvcAutoConfiguration.class somehow).

Restful App with Spring MVC - Ambiguous handler methods error

I'm trying to build a Restful webapp using Spring MVC 4.
But I'm got this error "Ambiguous handler methods mapped for HTTP".
In my controller I have this endpoints:
GET /people/
GET /people/{id}
POST /people/
DELETE /peope/{id}
PUT /people/{id}
I think this error occurs because I have something wrong in my configuration.
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.myapp.rest.controller" })
public class MVCConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/site/**").addResourceLocations("/WEB-INF/site/**");
}
}
And this
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext)
throws ServletException {
WebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
"DispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
}
private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("com.myapp.config");
return context;
}
}
Thank you all

Why doesnt my Spring Security authentication work?

I have the following configuration placed in /src/main/java/com/dog/bootstrap:
#EnableWebSecurity
#Configuration
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
System.out.println("hello");
auth.inMemoryAuthentication()
.withUser("user")
.password("password")
.roles("USER");
}
}
and I am loading it as follows:
public class WebInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.scan("com.dog.bootstrap");
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(dispatcherContext));
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher =
container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
Set<String> mappingConflicts = dispatcher.addMapping("/");
if (!mappingConflicts.isEmpty()) {
throw new IllegalStateException("'dispatcher' could not be mapped to '/' due " +
"to an existing mapping.");
}
}
My controller:
#Controller
public class DogController {
#RequestMapping(value = {"/dog"}, method = RequestMethod.GET)
#ResponseBody
public String getSource(#PathVariable("domain") String domain) throws Exception {
return "dogs";
}
}
When I startup my app, I do see hello being printed, so configure(AuthenticationManagerBuilder auth) is being called. However, none of my endpoints are requiring me to enter a login page. When I go to localhost:8080/dog it outputs dogs without asking me to authenticate myself.
You're not actually including the filter chain, as described in the last step of this guide. Try adding this default initializer, which maps to /*:
#Component public class SecurityWebApplicationInitializer
extends AbstractSecurityWebApplicationInitializer {
}

ApplicationContext is null for web application

We're building a web application and after the HttpServer is started I'm trying to load some items from the database into memory. The best way I know how to utilize the service layer for this is to use the following class:
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext applicationContext;
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
public void setApplicationContext (ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
}
It is continuously null.
public static void main(String[] args) throws IOException {
final HttpServer server = HttpServer.createSimpleServer(".", 8181);
WebappContext ctx = new WebappContext("Socket", "/");
//enable annotation configuration
ctx.addContextInitParameter("contextClass", "org.springframework.web.context.support.AnnotationConfigWebApplicationContext");
ctx.addContextInitParameter("contextLocation", "com.production");
//allow spring to do all of it's stuff
ctx.addListener("org.springframework.web.context.ContextLoaderListener");
//serve static assets
StaticHttpHandler staticHttpHandler = new StaticHttpHandler("src/main/web");
server.getServerConfiguration().addHttpHandler(staticHttpHandler, "/");
//deploy
ctx.deploy(server);
//NULL
WorkflowService workflowService = (WorkflowService) ApplicationContextProvider.getApplicationContext().getBean("workflowService");
server.start();
The service classes are annotated with #Service and my configuration class is...
#Configuration
#ComponentScan(basePackages = {
"com.production"
})
#PropertySource(value= {
"classpath:/application.properties",
"classpath:/environment-${MYAPP_ENVIRONMENT}.properties"
})
#EnableJpaRepositories("com.fettergroup.production.repositories")
#EnableTransactionManagement
public class Config {
...
#Bean
public ApplicationContextProvider applicationContextProvider() {
return new ApplicationContextProvider();
}
}
I believe something about this application using the grizzly WebContext is what is at the root of the issue. But I'm unsure what to do about it. I've done some Googling and it seems the solution I'm using should work...
contextLocation Init Parameter should be contextConfigLocation

Categories