In my web application I am creating a CustomWebApplicationInitializer which is extending from AbstractAnnotationConfigDispatcherServletInitializer.
I need to add another property source for the application. I am doing so in the onStartup method as below by setting the InitParameter in servletContext.
public class MvcWebApplicationInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
private static final String[] SERVLET_MAPPINGS = new String[] {"/"};
private static final String SESSION_COOKIE_PATH = "/";
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] {AppConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {WebConfig.class};
}
#Override
protected String[] getServletMappings() {
return SERVLET_MAPPINGS;
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.setInitParameter("contextInitializerClasses", "com.test.myproject.MyTestPropertySourceInitializer");
}
}
MyTestPropertySourceInitializer implements ApplicationContextInitializer and checks if the value of a certain property is set to true.
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment env = applicationContext.getEnvironment();
Boolean testPropEnabled = (Boolean) env.getProperty("testProperty.enabled", Boolean.class);
I have set that property value to true. But in the logs value is false and it does not process as expected. So I think that by the time the initialize method is called, the property file is not loaded in applicationContext.
Please advise how I can get this working. Thanks in advance.
try, by force load the properties file
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment env = applicationContext.getEnvironment();
env.getPropertySources().addFirst(new ResourcePropertySource("classpath:application.properties"))
Boolean testPropEnabled = (Boolean) env.getProperty("testProperty.enabled", Boolean.class);
}
Related
Hi I am new to spring boot currently I am trying to migrate my maven based web application to spring boot.
I was able to migrate all other configuration file except the below mentioned class:- ApplicationInitializer
public class ApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { Application.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Filter[] getServletFilters() {
Filter [] singleton = { new CORSFilter()};
return singleton;
}
}
I found one reference link similar to this Reference link which does the same work but I am not sure how to do this for my case.
Can anyone help me to figure it out that how to register my filter with dispatcher servlet.
Thanks in advance.
To register your filter with a dispatcher using SpringBootServletInitializer (that's what you refered to) you need to add FilterRegistrationBean. It may look like that:
public class Application extends SpringBootServletInitializer
{
#Override
protected SpringApplicationBuilder configure( SpringApplicationBuilder application )
{
return application.sources( Application.class );
}
#Bean
public FilterRegistrationBean filterRegistrationBean( ServletRegistrationBean servletRegistrationBean )
{
return new FilterRegistrationBean( new CORSFilter(), servletRegistrationBean );
}
public static void main( String[] args )
{
SpringApplication.run( Application.class, args );
}
}
Be aware that above code replaces your ApplicationInitializer.
I have a request dumper filter that I want to activate/deactivate at runtime (using a custom actuator endpoint). However I cannot find a way to do so without restarting the app. My current solution does just that:
#Configuration
public class AppConfigs {
#Value("${request.dumper.active:false}")
private Boolean dumpActive;
#Bean
public FilterRegistrationBean requestDumperFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
Filter requestDumperFilter = new RequestDumperFilter();
registration.setFilter(requestDumperFilter);
registration.addUrlPatterns("/*");
registration.setEnabled(dumpActive);
return registration;
}
Now I want to use something like that:
#Component
public class RequestdumperEndpoint implements Endpoint<Boolean > {
#Autowired
private RequestDumperFilter requestDumperFilter;
public String getId() {
return "requestdumper";
}
public Boolean invoke() {
return requestDumperFilter.isEnabled();
}
public Boolean setEnabled(Boolean enabled) {
return requestDumperFilter.setEnabled(enabled);
}
But obviously there are not isEnabled and setEnabled methods on a Filter.
Any ideas how I might be able to get what I need?
First add your filter using as a bean so you can hook into it:
public class MyWebInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
#Value("${request.dumper.active:false}")
private Boolean dumpActive;
#Bean
private MyRequestDumperFilter myRequestDumperFilter() {
MyRequestDumperFilter filter = new MyRequestDumperFilter();
filter.setEnabled(dumpActive);
return filter;
}
#Override
protected String[] getServletMappings() {
//..
return new String[0];
}
#Override
protected Filter[] getServletFilters() {
return new Filter[]{myRequestDumperFilter()};
}
#Override
protected Class<?>[] getRootConfigClasses() {
//..
return new Class<?>[0];
}
#Override
protected Class<?>[] getServletConfigClasses() {
//..
return new Class<?>[0];
}
}
You filter will then look something like :
public class MyRequestDumperFilter extends RequestDumperFilter{
private Boolean enabled;
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public Boolean getEnabled() {
return enabled;
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (enabled) {
super.doFilter(request, response, chain);
}
else {
chain.doFilter(request,response);
}
}
}
set active profile like context.getEnvironment().setActiveProfiles( "DEV" );
which can be achieved by using
public class SpringWebInitializer implements WebApplicationInitializer
{
public void onStartup( final ServletContext servletContext ) throws ServletException
{
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.getEnvironment().setActiveProfiles("DEV" )
}
}
But when extending AbstractAnnotationConfigDispatcherServletInitializer .
how can we achieve setting active profile ?
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
}
Activate your profile by using spring.profiles.active property.
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { WebConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
servletContext.setInitParameter("spring.profiles.active", "DEV");
}
}
You have a few options..
You can try having a context initializer to load the spring profile from a properties file on the classpath, like the following:
public class ContextProfileInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
private static final Logger LOGGER = LoggerFactory.getLogger(ContextProfileInitializer.class);
private static final String DEFAULT_SPRING_PROFILE = "local";
#Override
public void initialize(final ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
try {
environment.getPropertySources().addFirst(new ResourcePropertySource("classpath:conf/application.properties"));
if (environment.getProperty("spring.profiles.active") == null) {
environment.setActiveProfiles(DEFAULT_SPRING_PROFILE);
}
LOGGER.info("Activated Spring Profile: " + environment.getProperty("spring.profiles.active"));
} catch (IOException e) {
LOGGER.error("Could not find properties file in classpath.");
}
}
}
Here are some guides with more info:
https://gist.github.com/rponte/3989915
http://www.java-allandsundry.com/2014/09/spring-webapplicationinitializer-and.html
Alternatively (and a much easier way!) Use Spring Boot.
You can simply define spring.profiles.active in an application.properties file in the classpath. This will automatically be picked up and loaded into your environment.
More info here:
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-properties-and-configuration.html
You can use #ActiveProfiles("DEV") on some of your #Configuration classes, but probably more useful would be passing profile from outside - just run your .jar with additional parameter like -Dspring.active.profiles=DEV
I think it should be rather: -Dspring.profiles.active=... (Spring 4.1.5)
After I update my web application from Spring 4.1.0 to 4.1.2, the resource mapping stop working.
Without any change, each request to any resource is returning "HTTP 404 - NOT FOUND"(.js, .png, etc...).
Then I switch back to Spring 4.1.0, and everything becomes to work again.
This is my application configuration class:
public class MvcConfiguration extends WebMvcConfigurationSupport {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/**");
}
}
This question is similar to this: Resource Not Found after Spring 4.1.2 Update when deploy with JRebel 6.0.0
My resources are at:
[project]\WebContent\resources
And this is my servlet initializer:
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer implements HttpSessionListener {
private static final int MAX_UPLOAD_SIZE = 1 * 1024 * 1024; // 1mb;
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { MvcConfiguration.class };
}
#Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
#Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
#Override
protected Filter[] getServletFilters() {
CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter();
encodingFilter.setEncoding("UTF-8");
encodingFilter.setForceEncoding(true);
return new Filter[] { encodingFilter, new MultipartFilter() };
}
#Override
protected void customizeRegistration(Dynamic registration) {
File uploadDirectory = new File(System.getProperty("java.io.tmpdir"));
MultipartConfigElement multipartConfigElement = new MultipartConfigElement(uploadDirectory.getAbsolutePath(), MAX_UPLOAD_SIZE, MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2);
registration.setMultipartConfig(multipartConfigElement);
}
Just change your resource handler to the following:
public class MvcConfiguration extends WebMvcConfigurationSupport {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
This broke the code for me too when upgrading from Spring 4.1.1, but removing the trailing /** in Spring 4.1.6 fixed this.
I cannot seem to get simple Spring application to work with JavaConfig.
public class WebApp extends AbstractAnnotationConfigDispatcherServletInitializer {
private static final Logger logger = Logger.getLogger(WebApp.class);
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[0];
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{ WebAppConfig.class };
}
#Override
protected String[] getServletMappings() {
return new String[]{ "/" };
}
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
logger.debug("onStartup");
super.onStartup(servletContext);//MUST HAVE
servletContext.setInitParameter("defaultHtmlEscape", "true");
}
#Configuration
#EnableWebMvc
#ComponentScan("com.doge.controller")
public static class WebAppConfig extends WebMvcConfigurerAdapter {
}
}
And controller:
package com.doge.controller;
#RestController
public class HelloController {
#RequestMapping("/")
public String sayHello() {
System.out.println("something");
return "index";
}
}
I always get 404 on "localhost:8080/Build" nor "localhost:8080".
Nothing is ever logged nor printed, just "INFO: Server startup in 538 ms".
There are few options of initialize Spring web application. The easiest is like below:
public class SpringAnnotationWebInitializer extends AbstractContextLoaderInitializer {
#Override
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext applicationContext =
new AnnotationConfigWebApplicationContext();
applicationContext.register(WebAppConfig.class);
return applicationContext;
}
}
Other options can be found here: http://www.kubrynski.com/2014/01/understanding-spring-web-initialization.html