can not start spring mvc 4 application without web.xml - spring

I am trying to deploy spring mvc 4 web application without web.xml file using #Configuration annotation only.
I have
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("*.html");
}
private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation("ge.dm.icmc.config.WebConfig");
return context;
}
}
and my WebConfig.java class looks like :
#Configuration
#EnableWebMvc
#ComponentScan(basePackages="ge.dm.icmc")
public class WebConfig{
}
But when I try to start the application, I see in log :
14:49:12.275 [localhost-startStop-1] DEBUG o.s.w.c.s.AnnotationConfigWebApplicationContext - Could not load class for config location [] - trying package scan. java.lang.ClassNotFoundException:
If I try to add web.xml file, then it is started normally.

You are using the method setConfigLocation which, in this case, is wrong. You should use the register method instead.
private AnnotationConfigWebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(ge.dm.icmc.config.WebConfig.class);
return context;
}
However instead of implementing the WebApplicationInitializer I strongly suggest using one of the convenience classes of Spring for this. In your case the AbstractAnnotationConfigDispatcherServletInitializer would come in handy.
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
protected Class<?>[] getRootConfigClasses() { return null;}
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class};
}
protected String[] getServletMappings() {
return new String[] {"*.html"};
}
}

Related

How to test custom WebApplicationInitializer in Spring

I moved web.xml to Java annotation configuration
My custom code is
public class WebInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setDisplayName("app-name");
context.register(Config.class);
container.addListener(new RequestContextListener());
container.addListener(new ContextLoaderListener(context));
Dynamic dispatcher = container.addServlet("app-name", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/app-name-rest/*");
}
I tried the solution https://stackoverflow.com/a/25210356/6700081 but the line coverage is still 0%
I had the same problem and solved in this way:
public class WebInitializerTest {
#Mock
private MockServletContext mockServletContext;
#Mock
private ServletRegistration.Dynamic mockServletRegistration;
#BeforeEach
public void setUp() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testOnStartup() {
WebInitializer webInitializer = new WebInitializer();
when(mockServletContext.addServlet(ArgumentMatchers.eq("app-name"), any(Servlet.class))).thenReturn(mockServletRegistration);
webInitializer.onStartup(mockServletContext);
verify(mockServletContext, times(1)).addListener(any(RequestContextListener.class));
// other asserts..
}}
Note: I use Junit5 (#BeforeEach)

spring boot,Where's the Root WebApplicationContext and Servlet WebApplicationContext

I use spring-boot-starter-web 1.5.17.I can't find any auto configuration about build Root WebApplicationContext and Servlet WebApplicationContext.
When not use spring boot,we need do this
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{SecurityAdminConfig.class, DataSourceConfig.class, JavaConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{WebMvcConfig.class};
}
//controller、service
I know WebMvcAutoConfiguration do a lot of spring MVC configuration,but i can't find about auto build Root WebApplicationContext and Servlet WebApplicationContext.
public abstract class AbstractAnnotationConfigDispatcherServletInitializer
extends AbstractDispatcherServletInitializer {
#Override
protected WebApplicationContext createRootApplicationContext() {
Class<?>[] configClasses = getRootConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
AnnotationConfigWebApplicationContext rootAppContext = new AnnotationConfigWebApplicationContext();
rootAppContext.register(configClasses);
return rootAppContext;
}
else {
return null;
}
}
#Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext servletAppContext = new AnnotationConfigWebApplicationContext();
Class<?>[] configClasses = getServletConfigClasses();
if (!ObjectUtils.isEmpty(configClasses)) {
servletAppContext.register(configClasses);
}
return servletAppContext;
}
protected abstract Class<?>[] getRootConfigClasses();
protected abstract Class<?>[] getServletConfigClasses();
}
How can know this beans go Root WebApplicationContext or Servlet WebApplicationContext?
image here
There is, by default, a single application context in a Spring Boot web (or otherwise) application. It is created by SpringApplication when your application starts.
The right way to do it would be this:
public class App {
public static void main(String[] args) {
new SpringApplicationBuilder()
.parent(ParentConfig.class).web(WebApplicationType.NONE)
.child(WebConfig.class).web(WebApplicationType.SERVLET)
.sibling(RestConfig.class).web(WebApplicationType.SERVLET)
.run(args);
}
}
I have taken it from here:
However, it is still not clear why by default everything is in the same context..
Also, I am not sure if that's fine that other beans created by WebMvcAutoconfiguration will be shared across all child contexts.

Spring Boot + JSF static page configurations

am getting started with Spring Boot + JSF.
Spring documentation says:
Spring will automatically load and serve resources inside
/static (or /public or /resources or /META-INF/resources.
This is not working for me.
it is discouraged to use the "webapp" (src/main/webapp) folder.
But for my static content, it seem to be the only folder thats working with my JSF static page.
see Spring Boot static content.
I have tried these configuration:
#Configuration
public class JSFServletConfigs implements ServletContextInitializer// ,ServletContextAware
{
#Override // ServletContext initiallization parameters
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("facelets.DEVELOPMENT", "false");
servletContext.setInitParameter("javax.faces.PROJECT_STAGE", "Development");
servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX", ".xhtml");
servletContext.setInitParameter("javax.faces.PARTIAL_STATE_SAVING_METHOD", "true");
servletContext.setInitParameter("javax.faces.FACELETS_REFRESH_PERIOD", "-1");
}
#Bean // Registering the FacesServlet.
public ServletRegistrationBean servletRegistrationBean() {
FacesServlet servlet = new FacesServlet();
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(servlet) {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
FacesInitializer facesInitializer = new FacesInitializer();
Set<Class<?>> clazz = new HashSet<Class<?>>();
clazz.add(JSFServletConfigs.class);
facesInitializer.onStartup(clazz, servletContext);
}
};
servletRegistrationBean.addUrlMappings("*.xhtml", "*.jsf", "*.html");
return servletRegistrationBean;
}
#Bean
public InternalResourceViewResolver jsfViewResolving(){
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/<sub-folder of any LOCATION>/");
viewResolver.setSuffix(".xhtml");
return viewResolver;
}
}
Servlet pre-configs:
#Configuration
#EnableWebMvc
public class DefaultServletConfigs extends WebMvcConfigurerAdapter {
#Override // Enabling the default Servlet at path="/"
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
private final String[] LOCATIONS = {"<All my possible locations>"};
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if(!registry.hasMappingForPattern("/**")){
registry.addResourceHandler("/**").addResourceLocations(LOCATIONS);
}
if(!registry.hasMappingForPattern("webjars")){
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
}
My Question are:
What am I missing here?
How do I get the flexibility to place my resources in any of the other folders above
(i.e. "/static", "/public", "/resources", "/META-INF/resources").

How can I run jobs after spring beans is initialized?

I am working on Spring 4 mvc and hibernate
I want to run code on the server startup that will use the get data from the database then do some business logic
where can I put my code I tried to put the code
org.springframework.web.servlet.support.AbstractDispatcherServletInitializer.onStartup(ServletContext)
but I was not able to use #Autowired variables
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Autowired
TaskDAO task;
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { SpringRootConfig.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { SpringWebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
task.getAllTasks()
// TODO Auto-generated method stub
super.onStartup(servletContext);
}
}
You are not able to autowire variables because your class is not managed by spring. So annotate your class with #Component annotation.
Then you can define a method that will do your logic (for example onStartup method) and annotate it with the #PostConstruct annotation as explained in this answers.
How to call a method after bean initialization is complete?
It will execute the method after the beans initialization.
This could be your class:
#Component
public class WebInitializer{
#Autowire
TaskDAO task;
#PostConstruct
private void onStartup(){
task.getAllTasks();
// Do whatever you want
}
}

how to add filters to servlet when using #enablewebmvc annotation in spring 4?

Here is the current configuration
public class WebAppConfig implements WebApplicationInitializer {
private static final String CHARACTER_ENCODING_FILTER_ENCODING = "UTF-8";
private static final String CHARACTER_ENCODING_FILTER_NAME = "characterEncoding";
private static final String CHARACTER_ENCODING_FILTER_URL_PATTERN = "/*";
private static final String DISPATCHER_SERVLET_NAME = "dispatcher";
private static final String DISPATCHER_SERVLET_MAPPING = "/";
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(ExampleApplicationContext.class);
configureDispatcherServlet(servletContext, rootContext);
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
configureCharacterEncodingFilter(servletContext, dispatcherTypes);
servletContext.addListener(new ContextLoaderListener(rootContext));
}
private void configureDispatcherServlet(ServletContext servletContext, WebApplicationContext rootContext) {
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(
DISPATCHER_SERVLET_NAME,
new DispatcherServlet(rootContext)
);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping(DISPATCHER_SERVLET_MAPPING);
}
private void configureCharacterEncodingFilter(ServletContext servletContext, EnumSet<DispatcherType> dispatcherTypes) {
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding(CHARACTER_ENCODING_FILTER_ENCODING);
characterEncodingFilter.setForceEncoding(true);
FilterRegistration.Dynamic characterEncoding = servletContext.addFilter(CHARACTER_ENCODING_FILTER_NAME, characterEncodingFilter);
characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, CHARACTER_ENCODING_FILTER_URL_PATTERN);
}
}
Now I want to use #EnableWebMvc
#EnableWebMvc
#ComponentScan(basePackages = { "com.example.mvc.base.controller" })
public class WebAppConfig extends WebMvcConfigurerAdapter {
}
how would I add filters and Listeners to servletContext which I did using WebApplicationInitializer?
You still continue adding filters and listeners thorough your WebApplicationInitializer. This class methods starts up the web application with a Servlet registered with required contexts and beans.
In This class a DispatcherServlet is created containing programmatically configured AnnotationConfigWebApplicationContext.The dispatcher is also mapped to .html. 
WebAppConfig class enables WebMVC based on annotation and scans the base packages for the annotated resources. These are further registered by the web application context of the default servlet which was initialized by WebApplicationInitializer.

Resources