how to populate the environment before component scanning takes place - java

I am desperately attempting to populate the Environment with properties necessary to resolve bean properties in one of the scanned in components. What follows is a simple demonstration of two failed attempts to populate the environment.
This is the class whose bean property fails to get resolved during construction of the application context.
package com.enterprise.samples.email;
import ...
#Component
public class EmailBean {
#Value("mail.retry.count")
private int retryCount;
public int getRetryCount() {
return retryCount;
}
}
This is the java configuration class.
package com.enterprise.samples.configuration;
import ...
#Configuration
#PropertySource(value="classpath:aux.properties")
#ComponentScan(basePackages={ "com.enterprise.samples.email" })
public class Conf {
#Autowired
private ConfigurableEnvironment env;
// failed attempt #1
#PostConstruct
public void after() {
final MutablePropertySources mutablePropertySources = env.getPropertySources();
final HashMap<String, Object> emailProperties = new HashMap<>();
emailProperties.put("mail.retry.count", 3);
final MapPropertySource emailPropertiesSource =
new MapPropertySource("emailProperties", emailProperties);
mutablePropertySources.addFirst(emailPropertiesSource);
}
// failed attempt #2
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
final HashMap<String, Object> emailProperties = new HashMap<>();
emailProperties.put("mail.retry.count", 3);
final MapPropertySource emailPropertiesSource =
new MapPropertySource("emailProperties", emailProperties);
final MutablePropertySources mutablePropertySources = new MutablePropertySources();
mutablePropertySources.addFirst(emailPropertiesSource);
final PropertySourcesPlaceholderConfigurer result = new PropertySourcesPlaceholderConfigurer();
result.setPropertySources(mutablePropertySources);
return result;
}
}
Finally, this is the test class.
package com.enterprise.samples.tests;
import ...
public class BeanPropertyResolutionTest {
#Test
public void test() {
final AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Conf.class);
try {
final EmailBean emailBean = applicationContext.getBean(EmailBean.class, "emailBean");
Assert.assertEquals(3, emailBean.getRetryCount());
} finally {
applicationContext.close();
}
}
}
The following exception results:
WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'emailBean': Unsatisfied dependency expressed through field 'retryCount'; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: "mail.retry.count"
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'emailBean': Unsatisfied dependency expressed through field 'retryCount'; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: "mail.retry.count"
Can anyone tell me what I am doing incorrectly?

I assume your problem is here: #Value("mail.retry.count"). You almost got it right. You should've written this #Value("${mail.retry.count}"). And you don't need those attempt#1 and attempt#2.

Related

Autowire class with arguments in constructor fails

I have the following class :
public class ProducerWrapper<K, V> {
Producer<K, V> producer;
ThreadPoolExecutor threadPoolExecutor;
#Autowired
public ProducerWrapper(Properties p, int poolsize) {
......
log.info("Created kafka producer");
}
....
I try to inject it in a different service :
#Service
public class mainService{
#Qualifier("ProducerX")
#Autowired
private ProducerWrapper<Long,CustomObject1> p1;
#Autowired
#Qualifier("ProducerY")
private ProducerWrapper<Long,CustomObject2> p2;
And I created the following configuration :
#Configuration
#ComponentScan("main_package..")
public class MyConf {
#Bean(name = "ProducerX")
public ProducerWrapper<Long, CustomObject1> createProducerWrapper() throws IOException {
FileInputStream propertiesFile = new FileInputStream("producerx.properties");
properties = new Properties();
properties.load(propertiesFile);
return new ProducerWrapper<>(properties,5);
}
#Bean(name = "ProducerY")
public ProducerWrapper<Long, CustomObject2> createProducerWrapper() throws IOException {
FileInputStream propertiesFile = new FileInputStream("producery.properties");
properties = new Properties();
properties.load(propertiesFile);
return new ProducerWrapper<>(properties,5);
}
}
As you can see I have a different properties file for each producer. The error I'm getting is the following :
Error creating bean with name 'ProducerWrapper' defined in file [..../ProducerWrapper.class]: Unsatisfied dependency expressed through constructor parameter 1;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'int' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Parameter 1 of constructor in com.xx.xx.ProducerWrapper required a bean of type 'int' that could not be found.
If I remove the autowired annotation on top of the constructor, I'm getting a different error that the default constructor can't be found by Spring.
In addition, in the logs I see the following message that indicates that everything in the constructor was run :
2020-06-24 12:14:49.331 INFO 30912 --- [ main] c.a.a.ProducerWrapper : Created kafka producer
What am I doing wrong ?
You have this signature:
#Autowired
public ProducerWrapper(Properties p, int poolsize) {
...
You have not provided the "poolsize" parameter to be autowired. i.e. there's no integer that exists in your config that can be autowired into this variable.
To resolve this: Create a PoolSize class that wraps an int value. Then create a PoolSize object in your config to be autowired.
It says in the error output:
...No qualifying bean of type 'int' available: expected at least 1 bean which qualifies as autowire candidate.
I found the solution in the following stackoverflow post
Bottom line :
The constructor in the ProducerWrapper class shouldn't have any annotation :
//None annotation above constructor
public ProducerWrapper(Properties p, int poolsize) {
......
log.info("Created kafka producer");
}
Create a configuration class for the beans just like I pasted in my main comment.
3.Remove the Service annoatipn from the ProducerWrapper

How to inject a Map in Spring #Value field?

How can I inject the following application.properties into a Map field?
my.server.url=localhost
my.server.port=8080
my.server.timeout=10000
What is wrong with the following class?
#Service
#ConfigurationProperties("my")
public class MyService {
private Map<String, String> server;
public void setServer(Map<String, String> server) { this.server = server; }
public MyService(WebClient.Builder builder) {
this.builder = builder.uri(server.get("url")).build();
}
}
Result:
Bean instantiation via constructor failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [MyService]: Constructor threw exception; nested exception
is java.lang.NullPointerException
create a bean as following in the configuration class :
#Bean(name = "appProperties")
public static PropertiesFactoryBean mapper() {
PropertiesFactoryBean bean = new PropertiesFactoryBean();
bean.setLocation(new ClassPathResource("application.properties"));
return bean;
}
And then inject the values in it as map as follows in to the desired class :
#Resource(name = "appProperties")
private Map<String, String> properties;

Spring batch jobParameters not working in java config

I am trying to run a batch job, where I want to make my SQL query dynamic. But I'm getting an exception while building code as "Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?". Below are the code snippets and exception trace for the same.
BatchConfig
#Configuration
#EnableBatchProcessing
public class StoreSalesBatchConfiguration {
#Autowired
#Qualifier("jobBuilderFactory")
private JobBuilderFactory jobBuilderFactory;
#Autowired
#Qualifier("stepBuilderFactory")
private StepBuilderFactory stepBuilderFactory;
#Autowired
#Qualifier("jobCompletionNotificationListener")
private JobCompletionNotificationListener jobCompletionNotificationListener;
#Autowired
#Qualifier("jobLauncher")
private JobLauncher jobLauncher;
#Autowired
#Qualifier("storeSalesJob")
private Job storeSalesJob;
#Autowired
private GameStoreSalesRepository storeSalesRepository;
#Bean
#StepScope
ItemReader<GameStoreSales> gameStoreSalesReader(#Qualifier("gdwMpsBatch") final DataSource dataSource,
#Value("#{jobParameters[maxDate]}") String maxDate) {
JdbcCursorItemReader<GameStoreSales> databaseReader = new JdbcCursorItemReader<>();
databaseReader.setDataSource(dataSource);
databaseReader.setSql(CommonConstants.STORE_SALES_QUERY);
databaseReader.setPreparedStatementSetter(new PreparedStatementSetter() {
#Override
public void setValues(PreparedStatement ps) throws SQLException {
ps.setString(1, maxDate);
}
});
databaseReader.setRowMapper(new BeanPropertyRowMapper<>(GameStoreSales.class));
return databaseReader;
}
#Bean
public GameStoreSalesProcessor gameStoreSalesProcessor() {
return new GameStoreSalesProcessor();
}
#Bean
public ItemWriter<GameStoreSales> gameStoreSalesWriter() throws Exception {
return new GameStoreSalesWriter();
}
#Bean
public Step gameStoreSalesStep(#Qualifier("gdwMpsBatch") final DataSource dataSource,
#Value("#{jobParameters[maxDate]}") String maxDate) throws Exception {
return stepBuilderFactory.get("gameStoreSalesStep").<GameStoreSales, GameStoreSales>chunk(1000)
.reader(gameStoreSalesReader(dataSource,maxDate)).processor(gameStoreSalesProcessor()).writer(gameStoreSalesWriter()).build();
}
#Bean(name = "storeSalesJob")
public Job storeSalesJob(Step gameStoreSalesStep) {
return jobBuilderFactory.get("storeSalesJob").incrementer(new RunIdIncrementer())
.listener(jobCompletionNotificationListener).flow(gameStoreSalesStep).end().build();
}
#Scheduled(cron = "*/30 * * * * *")
public void runStoreSalesJob() throws JobExecutionAlreadyRunningException, JobRestartException,
JobInstanceAlreadyCompleteException, JobParametersInvalidException {
String dateParam = new Date().toString();
String maxDate = storeSalesRepository.getMaxCalDate();
JobParameters param = new JobParametersBuilder().addString("date", dateParam)
.addString("maxDate", weekEnd)
.toJobParameters();
try{
jobLauncher.run(storeSalesJob, param);
} catch(Exception e){
e.printStackTrace();
}
}
}
Exception Trace:
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'storeSalesBatchConfiguration': Unsatisfied dependency expressed through field 'storeSalesJob'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'storeSalesJob' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'storeSalesJob' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gameStoreSalesStep' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'gameStoreSalesStep' parameter 1; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'storeSalesJob' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'storeSalesJob' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'gameStoreSalesStep' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'gameStoreSalesStep' parameter 1; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'gameStoreSalesStep' defined in class path resource [com/staples/mpsbatch/config/StoreSalesBatchConfiguration.class]: Unsatisfied dependency expressed through method 'gameStoreSalesStep' parameter 1; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
Caused by: org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'jobParameters' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' - maybe not public or not valid?
Please suggest why jobParameters are not being recognised and where the configuration is going wrong.
A spring batch StepScope object is one which is unique to a specific step and not a singleton. As you probably know, the default bean scope in Spring is a singleton. But by specifying a spring batch component being StepScope means that Spring Batch will use the spring container to instantiate a new instance of that component for each step execution.
This is often useful for doing parameter late binding where a parameter may be specified either at the StepContext or the JobExecutionContext level and needs to be substituted for a placeholder, much like your example with the filename requirement.
Another useful reason to use StepScope is when you decide to reuse the same component in parallel steps. If the component manages any internal state, its important that it be StepScope based so that one thread does not impair the state managed by another thread (e.g, each thread of a given step has its own instance of the StepScope component).
Try annotating with StepScope:
#Bean
#StepScope
public Step gameStoreSalesStep(#Qualifier("gdwMpsBatch") final DataSource dataSource,
#Value("#{jobParameters[maxDate]}") String maxDate) throws Exception {
return stepBuilderFactory.get("gameStoreSalesStep").<GameStoreSales, GameStoreSales>chunk(1000)
.reader(gameStoreSalesReader(dataSource,maxDate)).processor(gameStoreSalesProcessor()).writer(gameStoreSalesWriter()).build();
}

Spring Bean is not autowired

I have a problem with Spring bean DefaultConfigurationService initialization that is extended from abstract class. I am totally stuck.
Class hiearchy is as follows:
public interface ConfigurationService {
TaxPayer getTaxPayer();
}
This class is mentioned to be useful for services that need to be initialized:
public abstract class BaseInitializationAwareService {
private boolean initialized = false;
public abstract void initialize();
protected void checkInitialization() {
if (!initialized) {
initialize();
}
}
protected void setInitialized() {
this.initialized = true;
}
}
This class acts as base class for Configuration service.
public abstract class BaseConfigurationService extends BaseInitializationAwareService implements ConfigurationService {
}
And with this bean, that acts as a configuration service, is a problem:
public class DefaultConfigurationService extends BaseConfigurationService {
private TaxPayerService taxPayerService;
#Autowired
public void setTaxPayerService(TaxPayerService taxPayerService) {
Assert.notNull(taxPayerService);
this.taxPayerService = taxPayerService;
}
public void initialize() {
Optional<TaxPayer> dbtaxPayer = taxPayerService.getActiveTaxPayer();
if (!dbtaxPayer.isPresent()) {
throw new IllegalStateException("Tax payer setting not found!");
}
this.taxPayer = dbtaxPayer.get();
setInitialized();
}
// the rest omitted...
}
when I'm creating DefaultConfigurationService bean:
#Bean
public BaseConfigurationService configurationService() {
DefaultConfigurationService configurationService = new DefaultConfigurationService();
configurationService.initialize();
return configurationService;
}
then taxPayerService in DefaultConfigurationService is null - it seems that is not autowired.
Can it be connected to the fact that DefaultConfigurationService is extended from abstract class?
TaxPayer service bean:
#Bean
public TaxPayerService taxPayerService() {
DatabaseTaxPayerService taxPayer = new DatabaseTaxPayerService();
return taxPayer;
}
This bean is probably never initialized...
Thats is a exception:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'webSecurityConfig.ApiSecurity':
Unsatisfied dependency expressed through method
'setContentNegotationStrategy' parameter 0; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name
'org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration':
Unsatisfied dependency expressed through method 'setConfigurers'
parameter 0; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'passwordRecoverController': Unsatisfied
dependency expressed through method 'setUserService' parameter 0;
nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'defaultUserService': Unsatisfied
dependency expressed through method 'setNotificationService' parameter
0; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'notificationService': Unsatisfied
dependency expressed through method 'setConfigurationService'
parameter 0; nested exception is
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'configurationService' defined in class path
resource [com.example.config/AppConfig.class]: Bean instantiation via
factory method failed; nested exception is
org.springframework.beans.BeanInstantiationException: Failed to
instantiate [com.example.services.BaseConfigurationService]: Factory
method 'configurationService' threw exception; nested exception is
java.lang.NullPointerException
For example, bean that needs BaseConfigurationService:
public class EmailNotificationService extends BaseService implements NotificationService {
private BaseConfigurationService configurationService;
#Autowired
public void setConfigurationService(BaseConfigurationService configurationService) {
Assert.notNull(configurationService);
this.configurationService = configurationService;
}
// the rest omitted...
}
#update 1
Bean initialization example with internal dependencies to another beans:
#Bean
public TransactionDataService transactionDataService() {
return new DefaultTransactionDataService();
}
and DefaultTransactionDataService:
public class DefaultTransactionDataService implements TransactionDataService {
private PrivateKeyService privateKeyService;
#Autowired
public void setPrivateKeyService(PrivateKeyService privateKeyService) {
Assert.notNull(privateKeyService);
this.privateKeyService = privateKeyService;
}
}
and bean dependency
#Bean
public PrivateKeyService privateKeyService() {
return new DefaultPrivateKeyAwareService();
}
and it works.
It is related to your instruction to Spring how to initialize your bean:
#Bean is used to explicitly declare a single bean, rather than letting Spring do it automatically as above. It decouples the declaration of the bean from the class definition, and lets you create and configure beans exactly how you choose.
So when you create instance of your class manually your have to set all class field manually as well.
It can be done like this:
#Bean
public BaseConfigurationService configurationService() {
DefaultConfigurationService configurationService = new DefaultConfigurationService();
configurationService.setTaxPayerService(taxPayerService());
configurationService.initialize();
return configurationService;
}
Or move dependency directly to constructor, so dependency of your DefaultConfigurationService will be more obvious:
#Bean
public BaseConfigurationService configurationService() {
DefaultConfigurationService configurationService = new DefaultConfigurationService(taxPayerService());
configurationService.initialize();
return configurationService;
}
Good description

Jetty + SpringMVC: Error when set configureDefaultServletHandling because cannot find the default servlet name

I created an simple application without web.xml and spring-servlet.xml config file. I just config in Java code.
This is the project structure:
Project structure
This is my main class:
public class TripMapServer {
private static final int DEFAULT_PORT = 8080;
private static final String CONTEXT_PATH = "/";
private static final String MAPPING_URL = "/";
private static final String CONFIG_LOCATION = "com.biendltb.config";
private static final String DEFAULT_PROFILE = "dev";
public static void main(String[] args) throws Exception {
new TripMapServer().startJetty(getPortFromArgs(args));
}
private static int getPortFromArgs(String[] args) {
if (args.length > 0) {
try {
return Integer.valueOf(args[0]);
} catch (NumberFormatException ignore) {
}
}
return DEFAULT_PORT;
}
private void startJetty(int port) throws Exception {
Server server = new Server(port);
server.setHandler(getServletContextHandler(getContext()));
server.start();
server.join();
}
private static ServletContextHandler getServletContextHandler(WebApplicationContext context) throws IOException {
ServletContextHandler contextHandler = new ServletContextHandler();
contextHandler.setErrorHandler(null);
contextHandler.setContextPath(CONTEXT_PATH);
contextHandler.addServlet(new ServletHolder(new DispatcherServlet(context)), MAPPING_URL);
contextHandler.addEventListener(new ContextLoaderListener(context));
contextHandler.setResourceBase(new ClassPathResource("webapp").getURI().toString());
return contextHandler;
}
private static WebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.setConfigLocation(CONFIG_LOCATION);
context.getEnvironment().setDefaultProfiles(DEFAULT_PROFILE);
return context;
}
}
I created another class named WebConfig.java to set the config for spring-servlet:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"com.biendltb.controller"})
public class WebConfig extends WebMvcConfigurerAdapter{
private static final Charset UTF8 = Charset.forName("UTF-8");
#Autowired
public Environment env;
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(stringConverter());
}
private StringHttpMessageConverter stringConverter() {
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
stringConverter.setSupportedMediaTypes(Arrays.asList(new MediaType("text", "plain", UTF8)));
return stringConverter;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/src/main/resources/").setCachePeriod(Integer.MAX_VALUE);
registry.addResourceHandler("/js/**").addResourceLocations("/js/").setCachePeriod(Integer.MAX_VALUE);
registry.addResourceHandler("/css/**").addResourceLocations("/css/").setCachePeriod(Integer.MAX_VALUE);
registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(Integer.MAX_VALUE);
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/src/main/resources/pages/");
resolver.setSuffix(".jsp");
return resolver;
}
}
Error happened when I add the configureDefaultServletHandling function.
[org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'defaultServletHandlerMapping' threw exception; nested exception is java.lang.IllegalStateException: Unable to locate the default servlet for serving static content. Please set the 'defaultServletName' property explicitly.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'defaultServletHandlerMapping' defined in class path resource [org/springframework/web/servlet/config/annotation/DelegatingWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerMapping]: Factory method 'defaultServletHandlerMapping' threw exception; nested exception is java.lang.IllegalStateException: Unable to locate the default servlet for serving static content. Please set the 'defaultServletName' property explicitly.
It cannot find the default name of servlet. Normally, the default name of servlet will be "default".
I think maybe I should set the servlet name to solve this problem.
Do you have any idea to solve this problem?
Sorry about the code format not display correctly. Appreciated you support. Thank you very much.
I already found how to set the name for Spring servlet by java code:
contextHandler.addServlet(new ServletHolder("default", new DispatcherServlet(context)), MAPPING_URL);
But I met another issue, that is:
java.lang.NoClassDefFoundError: Could not initialize class org.springframework.web.util.NestedServletException
I try to google, many people faced with NoClassDefFoundError but no one met the issue org.springframework.web.util.NestedServletException.
I checked again to make sure all dependency were added.
Maybe I should post another question for that issue :(

Categories