How can I make WebApplicationContext access beans in ApplicationContext? - spring

This is how I try to bootstrap Spring in my Java Web Application:
public class SpringBootstrap implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
final AnnotationConfigApplicationContext rootContext = new AnnotationConfigApplicationContext();
rootContext.register(RootContextConfiguration.class);
final AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
webContext.register(WebContextConfiguration.class);
webContext.setParent(rootContext);
final DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext);
final ServletRegistration.Dynamic dispatcher = servletContext.addServlet("springDispatcher", dispatcherServlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
final ContextLoaderListener contextLoadListener = new ContextLoaderListener(webContext);
servletContext.addListener(contextLoadListener);
}
}
And RootContextConfiguration and WebContextConfiguration classes are as follows:
#Configuration
#ComponentScan(basePackages = "biz.tugay.janeleven.root")
public class RootContextConfiguration {
}
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "biz.tugay.janeleven.web")
public class WebContextConfiguration {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
return resolver;
}
}
When I try deploying the application to Tomcat and start I will get:
Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type
[biz.tugay.janeleven.root.service.AppUserService] found for
dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
I am also including the HelloServlet and AppUserService classes here, with their package information:
package biz.tugay.janeleven.root.service;
#Service
public class AppUserService {
public AppUser addAppUser(String name) {
final AppUser appUser = new AppUser(name);
AppUserDB.addUser(appUser);
return appUser;
}
public Collection<AppUser> getAllAppUsers() {
return AppUserDB.getAll();
}
}
package biz.tugay.janeleven.web;
#Controller
#RequestMapping(value = "/")
public class HelloWorldServlet {
#Autowired
private AppUserService appUserService;
#RequestMapping(value = "", method = RequestMethod.GET)
public String helloWorld(Model model) {
final Collection<AppUser> appUserList = appUserService.getAllAppUsers();
model.addAttribute("appUserList", appUserList);
return "hello.jsp";
}
#RequestMapping(value = "", method = RequestMethod.POST)
public String addApplicationUser(#RequestParam("username") String username) {
appUserService.addAppUser(username);
return "redirect:/";
}
}
My expectation is that, WebContextConfiguration should be able to find beans that are managed by RootContextConfiguration since I am calling:
webContext.setParent(rootContext);
during the bootstrap process. But obviously I am missing something.

You are correct that the web context will inherit from the root context, however
you did not include the rootContext when you initialized servletContext.addListener(); see similar code below which will help you fix your issue.
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(AppConfig.class);
servletContext.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
dispatcherContext.register(WebConfig.class);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher",
new DispatcherServlet(dispatcherContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}

Related

How to config MessageDispatcherServlet and ServletRegistration both by using spring annotaion

I have configure MessageDispatcherServlet for soap services and ServletRegistration for web services but controller not call in case of web services.
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
// use MessageDispatcherServlet instead of standard DispatcherServlet for SOAP messages
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setContextClass(WebServiceWsConfig.class);
servlet.setApplicationContext(context);
servlet.setTransformWsdlLocations(true);
// register MessageDispatcherServlet as Web Service entry point
final ServletRegistration.Dynamic dispatcher = servletContext.addServlet("MessageDispatcherServlet",servlet);
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/soapws/*");
dispatcher.addMapping("/");
}
}
My WebServicesConfig class is
#Configuration
#EnableWs
#EnableWebMvc
#ComponentScan(basePackages = "")
#PropertySource(value = {"classpath:config_local.properties"})
public class WebServiceConfig extends WebMvcConfigurerAdapter {
#Autowired
private Environment env;
#Bean(name = "pos")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema posSchema) {
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("posPort");
wsdl11Definition.setLocationUri("/soapws");
wsdl11Definition.setTargetNamespace("http://---.---.in/soap");
wsdl11Definition.setSchema(posSchema);
return wsdl11Definition;
}
#Bean
public XsdSchema studentsSchema() {
return new SimpleXsdSchema(new ClassPathResource("pos.xsd"));
}
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
I solve my problem using Spring Boot configuration, This help me calling Soap services as well as Web services.
#EnableWs
#Configuration
public class WebServiceConfig extends WsConfigurerAdapter{
#Bean
public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
MessageDispatcherServlet servlet = new MessageDispatcherServlet();
servlet.setApplicationContext(applicationContext);
servlet.setTransformWsdlLocations(true);
return new ServletRegistrationBean(servlet, "/ws/*");
}
#Bean(name = "pos")
public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema posSchema)
{
DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
wsdl11Definition.setPortTypeName("posPort");
wsdl11Definition.setLocationUri("/soapws");
wsdl11Definition.setTargetNamespace("http://---.---.in/soap");
wsdl11Definition.setSchema(posSchema);
return wsdl11Definition;
}
#Bean
public XsdSchema studentsSchema() {
return new SimpleXsdSchema(new ClassPathResource("pos.xsd"));
}

Spring beans are null, #Autowire injections do not work, what went wrong?

I have searched a lot to start with and did not find a solution. This question will be rather long with loads of code, the problem is that at run time DataSource object is null. These are the two ways i am trying to add dataSource beans to the spring container. I guess there is nothing wrong here. And beans are actually created.
package com.stubtech.eztaxi.eztaxiapp.config;
**imports
#Configuration
public class DBConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(DBConfig.class);
#Autowired
private Environment environment;
#Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(environment.getProperty("jdbc.driverClass"));
dataSource.setUrl(environment.getProperty("jdbc.url"));
dataSource.setUsername(environment.getProperty("jdbc.username"));
dataSource.setPassword(environment.getProperty("jdbc.password"));
return dataSource;
}
#Bean(name = "jndiDataSource")
public DataSource dataSourceJndi() {
DataSource dataSource = null;
try {
JndiDataSourceLookup jndiDataSourceLookup = new JndiDataSourceLookup();
jndiDataSourceLookup.setResourceRef(true);
dataSource = jndiDataSourceLookup.getDataSource("jdbc/EZTaxiDB");
LOGGER.debug("Created DS");
} catch (Exception e) {
LOGGER.error("No DS: " + e.getMessage());
}
return dataSource;
}
}
I have went around using .xml configuration files and used following class for web initialization:
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(WebConfig.class);
// Manage lifecycle of the rootContext
container.addListener(new ContextLoaderListener(rootContext));
DispatcherServlet dispatcherServlet = new DispatcherServlet(rootContext);
ServletRegistration.Dynamic registration = container.addServlet("dispatcherServlet", dispatcherServlet);
registration.setLoadOnStartup(1);
registration.addMapping("/");
DelegatingFilterProxy delegatingFilterProxy = new DelegatingFilterProxy("springSecurityFilterChain");
container.addFilter("springSecurityFilterChain", delegatingFilterProxy).addMappingForUrlPatterns(null, false, "/*");
}
}
At the same time I am trying to use jjwt tokens for autorisation, here is SecurityConfig:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final ITokenAuthService tokenAuthService;
private final UserDetailsService userDetailsService;
private final ISecretReader secretReader;
public SecurityConfig() {
super(true);
this.secretReader = new SecretReaderImpl();
this.userDetailsService = new UserDetailsServiceImpl();
this.tokenAuthService = new TokenAuthServiceImpl();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling().and()
.anonymous().and()
.servletApi().and()
.authorizeRequests()
// Allow anonymous resource requests
.antMatchers("/").permitAll()
.antMatchers("/favicon.ico").permitAll()
.antMatchers("**/*.html").permitAll()
.antMatchers("**/*.css").permitAll()
.antMatchers("**/*.js").permitAll()
// Allow anonymous logins
.antMatchers("/auth/**").permitAll()
// All other request need to be authenticated
.anyRequest().authenticated().and()
// Custom Token based authentication based on the header previously given to the client
.addFilterBefore(new StatelessAuthenticationFilter(tokenAuthService()),
UsernamePasswordAuthenticationFilter.class)
.headers().cacheControl();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean
public UserDetailsService userDetailsService() {
return userDetailsService;
}
#Bean
public ITokenAuthService tokenAuthService() {
return tokenAuthService;
}
#Bean
public ISecretReader secretReader() {
return secretReader;
}
}
I am trying to authorize using a servlet:
#Component
#WebServlet("/auth/login")
public class AuthenticationServlet extends HttpServlet { // implements ServletResponse {
private static final Logger LOGGER = LoggerFactory.getLogger(AuthenticationServlet.class);
private WebApplicationContext springContext;
#Autowired
private UserInfoDAOImpl userInfoDAO;
#Autowired
private AuthenticationManager authenticationManager;
public void init(final ServletConfig config) throws ServletException {
//this.authenticationManager = authenticationManager;
// ApplicationContext context =
// WebApplicationContextUtils.getRequiredWebApplicationContext(
// this.getServletContext());
// authenticationManager = (AuthenticationManager) context.getBean("authenticationManagerBean");
super.init(config);
springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext());
final AutowireCapableBeanFactory beanFactory = springContext.getAutowireCapableBeanFactory();
beanFactory.autowireBean(this);
LOGGER.debug("Initialised login servlet");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
UserInfo user = userInfoDAO.getUserInfoById("testuser");
String un = request.getParameter("un");
String pw = request.getParameter("pw");
Authentication authrequest = new UsernamePasswordAuthenticationToken(un, pw);
Authentication result = authenticationManager.authenticate(authrequest);
SecurityContextHolder.getContext().setAuthentication(result);
LOGGER.info("Successfully authenticated. Security context contains: " +
SecurityContextHolder.getContext().getAuthentication());
} catch (AuthenticationException e) {
LOGGER.error("Authentication failed: " + e.getMessage());
}
}
}
And finally this is where there is a NullPointer - dataSource is null:
#Component
public class UserInfoDAOImpl implements IUserInfoDAO {
private final static Logger LOGGER = LoggerFactory.getLogger(UserInfoDAOImpl.class);
#Autowired
private DataSource dataSource;
public UserInfo getUserInfoById(String username) {
LOGGER.debug("Get user is called");
String sql = "SELECT u.username name, u.password pass, ur.rolename role FROM " +
"users u INNER JOIN user_role ur on u.id=ur.userid WHERE " +
"u.enabled = 1 and u.username = ?";
UserInfo userInfo = null;
try {
userInfo = new JdbcTemplate(this.dataSource).queryForObject(sql, new Object[]{username},
(rs, rowNum) -> {
UserInfo user = new UserInfo();
user.setUsername(rs.getString("name"));
user.setPassword(rs.getString("pass"));
user.setRole(rs.getString("role"));
return user;
});
} catch (Exception e) {
LOGGER.error("Failed to fetch user: " + e.getMessage());
}
return userInfo;
}
}
And this is WebConfig:
#EnableWebMvc
#Configuration
#ComponentScan(basePackages = ("com.stubtech.eztaxi.eztaxiapp"))
#PropertySource("classpath:application.properties")
public class WebConfig extends WebMvcConfigurerAdapter {
private static final Logger LOGGER = LoggerFactory.getLogger(WebConfig.class);
#Autowired
private ApplicationContext appContext;
public WebConfig(){
LOGGER.debug("_____APP_STARTED_____");
LOGGER.debug("...");
}
}
Log from app initialization:
org.springframework.jdbc.datasource.DataSourceUtils]]
Fetching JDBC Connection from DataSource]]
org.springframework.jdbc.datasource.DriverManagerDataSource]]
org.springframework.jdbc.datasource.DataSourceUtils]]
Returning JDBC Connection to DataSource]]
Failed to fetch user: Property 'dataSource' is required]]
Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#596ded4b: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,webConfig,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor,DBConfig,securityConfig,userDetailsServiceImpl,userInfoDAOImpl,authenticationServlet,dataSource,jndiDataSource,org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration,authenticationManagerBuilder,enableGlobalAuthenticationAutowiredConfigurer,org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration,delegatingApplicationListener,webSecurityExpressionHandler,springSecurityFilterChain,privilegeEvaluator,autowiredWebSecurityConfigurersIgnoreParents,org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration,objectPostProcessor,org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration,requestDataValueProcessor,authenticationManagerBean,userDetailsService,tokenAuthService,secretReader,org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration,mvcValidator,mvcUrlPathHelper,mvcViewResolver,mvcPathMatcher,httpRequestHandlerAdapter,requestMappingHandlerMapping,mvcContentNegotiationManager,viewControllerHandlerMapping,resourceHandlerMapping,defaultServletHandlerMapping,mvcConversionService,beanNameHandlerMapping,mvcResourceUrlProvider,mvcUriComponentsContributor,simpleControllerHandlerAdapter,requestMappingHandlerAdapter,handlerExceptionResolver]; root of factory hierarchy]]
Registering bean definition for #Bean method com.stubtech.eztaxi.eztaxiapp.config.DBConfig.dataSource()]]
Registering bean definition for #Bean method com.stubtech.eztaxi.eztaxiapp.config.DBConfig.jndiDataSource()]]
Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#665a082b: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,webConfig,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor,DBConfig,securityConfig,userDetailsServiceImpl,userInfoDAOImpl,authenticationServlet,dataSource,jndiDataSource,org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration,authenticationManagerBuilder,enableGlobalAuthenticationAutowiredConfigurer,org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration,delegatingApplicationListener,webSecurityExpressionHandler,springSecurityFilterChain,privilegeEvaluator,autowiredWebSecurityConfigurersIgnoreParents,org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration,objectPostProcessor,org.springframework.security.config.annotation.web.configuration.WebMvcSecurityConfiguration,requestDataValueProcessor,authenticationManagerBean,userDetailsService,tokenAuthService,secretReader,org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration,mvcValidator,mvcUrlPathHelper,mvcViewResolver,mvcPathMatcher,httpRequestHandlerAdapter,requestMappingHandlerMapping,mvcContentNegotiationManager,viewControllerHandlerMapping,resourceHandlerMapping,defaultServletHandlerMapping,mvcConversionService,beanNameHandlerMapping,mvcResourceUrlProvider,mvcUriComponentsContributor,simpleControllerHandlerAdapter,requestMappingHandlerAdapter,handlerExceptionResolver]; root of factory hierarchy]]
Registered injected element on class [com.stubtech.eztaxi.eztaxiapp.service.impl.UserInfoDAOImpl]: AutowiredFieldElement for private javax.sql.DataSource com.stubtech.eztaxi.eztaxiapp.service.impl.UserInfoDAOImpl.dataSource]]
Processing injected element of bean 'userInfoDAOImpl': AutowiredFieldElement for private javax.sql.DataSource com.stubtech.eztaxi.eztaxiapp.service.impl.UserInfoDAOImpl.dataSource]]
Creating shared instance of singleton bean 'dataSource']]
Creating instance of bean 'dataSource']]
org.springframework.jdbc.datasource.DriverManagerDataSource]]
Eagerly caching bean 'dataSource' to allow for resolving potential circular references]]
Finished creating instance of bean 'dataSource']]
Creating shared instance of singleton bean 'jndiDataSource']]
Creating instance of bean 'jndiDataSource']]
org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup]]
org.springframework.jdbc.datasource.lookup.JndiDataSourceLookup]]
Eagerly caching bean 'jndiDataSource' to allow for resolving potential circular references]]
Not strongly caching class [com.sun.gjc.spi.jdbc40.DataSource40] because it is not cache-safe]]
Finished creating instance of bean 'jndiDataSource']]
Autowiring by type from bean name 'userInfoDAOImpl' to bean named 'dataSource']]
Returning cached instance of singleton bean 'dataSource']]
Returning cached instance of singleton bean 'jndiDataSource']]
org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource]]
org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource]]
org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource]]
org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource]]
org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource]]
org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource]]
org.springframework.security.web.access.expression.ExpressionBasedFilterInvocationSecurityMetadataSource]]
Rejected bean name 'dataSource': no URL paths identified]]
Rejected bean name 'jndiDataSource': no URL paths identified]]
org.springframework.jdbc.datasource.DataSourceUtils]]
Fetching JDBC Connection from DataSource]]
org.springframework.jdbc.datasource.DriverManagerDataSource]]
org.springframework.jdbc.datasource.DataSourceUtils]]
Returning JDBC Connection to DataSource]]
Failed to fetch user: Property 'dataSource' is required]]
Clearly you are creating the two different beans of DataSource in your Configuration Class. But at the time of injection you are just doing the following:
#Autowired
private DataSource dataSource;
The problem is that Spring does not know which of the two DataSource Bean is to be injected in here. You have to use #Qualifier to let Spring know which Bean is to be Injected.
Change it to following:
#Autowired
#Qualifier("dataSource")
private DataSource dataSource;
Alternatively, you can replace the two annotations with a single #Resource as follows:
#Resource(name = "dataSource")
private DataSource dataSource;

How to load ApplicationContext java-config in Junit

I am trying to move spring xml config to java config. Right now, I am able to make everything work, except one thing, that is to run junit on my services. The problem is that my junit test couldn't detect application context. Hence, how I can load application context java-based config in Junit? Since I can run my service on a browser, I assume that my integration is correct, meaning that my test configuration is not right, but I can't find where is my be wrong.
This is my junit config:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(
classes={Bootstrap.class, RootContextConfig.class
, WebServletContextConfig.class, PersistenceConfig.class })
#WebAppConfiguration
//#TransactionConfiguration(transactionManager="transactionManager",defaultRollback=true)
public class BaseTest { ... }
Just in case, I include my application context configuration here also.
This is my bootstrap
public class Bootstrap implements WebApplicationInitializer
{
#Override
public void onStartup(ServletContext container)
throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(RootContextConfig.class);
container.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext servletContext = new AnnotationConfigWebApplicationContext();
servletContext.register(WebServletContextConfig.class);
ServletRegistration.Dynamic dispatcher = container.addServlet(
"SpringDispatcher", new DispatcherServlet(servletContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
My RootContext
#Configuration
#EnableScheduling
#EnableAsync(
mode=AdviceMode.PROXY, proxyTargetClass=false,
order=Ordered.HIGHEST_PRECEDENCE
)
#ComponentScan(
basePackages={"com.core", "com.common"},
excludeFilters=#ComponentScan.Filter(Controller.class)
)
#Import({PersistenceConfig.class})
public class RootContextConfig {...}
My WebServletContext
#Configuration
#EnableWebMvc
#ComponentScan(
basePackages = { "com.web" },
useDefaultFilters = false,
includeFilters = #ComponentScan.Filter({Controller.class, ControllerAdvice.class})
)
public class WebServletContextConfig extends WebMvcConfigurerAdapter {..}
My PersistentContext
#Configuration
#EnableTransactionManagement(
mode=AdviceMode.PROXY, proxyTargetClass=false
, order=Ordered.LOWEST_PRECEDENCE)
public class PersistenceConfig {
#Bean
public DataSource customerSupportDataSource() {
//JndiDataSourceLookup lookup = new JndiDataSourceLookup();\
BasicDataSource basic = new BasicDataSource();
basic.setDriverClassName(KEY_DRIVER_CLASS);
basic.setUrl(KEY_DB_URL);
basic.setUsername(KEY_DB_USERNAME);
basic.setPassword(KEY_DB_PASSWORD);
return basic;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean()
{
Map<String, Object> properties = new Hashtable<>();
properties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
adapter.setDatabasePlatform("org.hibernate.dialect.PostgreSQLDialect");
adapter.setGenerateDdl(true);
adapter.setShowSql(true);
LocalContainerEntityManagerFactoryBean factory =
new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(adapter);
factory.setDataSource(this.customerSupportDataSource());
factory.setPackagesToScan("com.common.model");
factory.setSharedCacheMode(SharedCacheMode.ENABLE_SELECTIVE);
factory.setValidationMode(ValidationMode.NONE);
factory.setJpaPropertyMap(properties);
return factory;
}
#Bean
public PlatformTransactionManager jpaTransactionManager()
{
return new JpaTransactionManager(
this.entityManagerFactoryBean().getObject()
);
}
}

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.

can not start spring mvc 4 application without web.xml

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"};
}
}

Resources