How to initialize context parameters in Spring Boot? - spring

I need to set a context param on startup.
#Bean
public ServletContextInitializer initializer() {
return new ServletContextInitializer() {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("joinfaces.primefaces.theme", "poseidon-blue");
}
};
}
However I get the following error
Initialization parameters cannot be set after the context has been initialized
How is this caused and how can I solve it?

Related

Problems using dbunit with Spring (without spring-test-dbunit)

I'm trying to use dbunit to test my DAOs. We use Spring in a version that is not compatible with spring-test-dbunit. I can't autowire my dao beans into my test class, because then I would have to use #RunWith(SpringJUnit4ClassRunner.class) which regards one parameterless constructor. My class looks like following:
public class DbUnitExample extends DBTestCase {
#Autowired
public MyDAO myDAO;
public DbUnitExample(String name) {
super(name);
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, "com.mysql.jdbc.Driver");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, "...");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, "...");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, "...");
}
#Override
protected IDataSet getDataSet() throws Exception {
return new FlatXmlDataSetBuilder().build(new FileInputStream("target/partial.xml"));
}
#Override
protected DatabaseOperation getSetUpOperation() throws Exception {
return DatabaseOperation.REFRESH;
}
#Override
protected DatabaseOperation getTearDownOperation() throws Exception {
return DatabaseOperation.NONE;
}
#Test
public void testSometing() throws Exception {
myDAO.deleteById(12662);
}
}
Of course I get an NPE because my dao bean can't be found. When I use #RunWith(SpringJUnit4ClassRunner.class) I need to provide one parameterless constructor and have to delete my "dbunit"-constructor. Is there a standard way or workaround to use dbunit with spring without the use of spring-test-dbunit
EDIT
My class now looks like following:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("/test-application.xml")
#DirtiesContext
#TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class })
public class DbUnitExample extends DBTestCase {
#Autowired
public MyDAO myDAO;
public DbUnitExample() {
super("target/partial.xml");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_DRIVER_CLASS, "com.mysql.jdbc.Driver");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_CONNECTION_URL, "...");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_USERNAME, "...");
System.setProperty(PropertiesBasedJdbcDatabaseTester.DBUNIT_PASSWORD, "...");
}
#Override
protected IDataSet getDataSet() throws Exception {
return new FlatXmlDataSetBuilder().build(new FileInputStream("target/partial.xml"));
}
#Override
protected DatabaseOperation getSetUpOperation() throws Exception {
return DatabaseOperation.REFRESH;
}
#Override
protected DatabaseOperation getTearDownOperation() throws Exception {
// return DatabaseOperation.NONE;
// return DatabaseOperation.REFRESH;
return DatabaseOperation.CLEAN_INSERT;
}
#Test
public void testSometing() throws Exception {
myDAO.deleteById(12662);
}
}
It compiles now, but has no dbunt-functionality, which means if I delete a row it doesn't get restored to it's previous state (inserted again).
Since you are using Spring, I suggest autowiring the dbUnit instances into the test. The dbUnit Test Cases page has "Configuration Example Using Spring" for the PrepAndExpectedTestCase, but just copy the code and change it to DBTestCase and adjust accordingly.

Spring Boot and Spring-starter-data-jpa : Lazy loading of datasource setup

I am working on an application with Spring-starter-data-jpa and multi datasources, that need to lazy initialize datasouce connection, but i dosen't manage to work with it.
For exemple if i put a wrong password on a datasource configuration, the application startup fails.
I try to put a #Lazy annotation on the Datasource #Configuration class but the application still crash on startup.
I try to implement a LazyConnectionDataSourceProxy instead the Datasource without success.
I can't imagine that it is not possible.
Is somewone have an idea to how lazy load datasources configuration on the first jpa repository call ?
I tryed to do this with a kind of adapter/singleton mix pattern like this :
#Component
public class TestErrorDatasource implements DataSource {
private DataSource datasource;
#Autowired Environment env;
#Override
public PrintWriter getLogWriter() throws SQLException {
return getDatasource().getLogWriter();
}
#Override
public int getLoginTimeout() throws SQLException {
return getDatasource().getLoginTimeout();
}
#Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return getDatasource().getParentLogger();
}
#Override
public void setLogWriter(PrintWriter arg0) throws SQLException {
getDatasource().setLogWriter(arg0);
}
#Override
public void setLoginTimeout(int arg0) throws SQLException {
getDatasource().setLoginTimeout(arg0);
}
#Override
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
return getDatasource().isWrapperFor(arg0);
}
#Override
public <T> T unwrap(Class<T> arg0) throws SQLException {
return getDatasource().unwrap(arg0);
}
#Override
public Connection getConnection() throws SQLException {
return getDatasource().getConnection();
}
#Override
public Connection getConnection(String arg0, String arg1) throws SQLException {
return getDatasource().getConnection(arg0, arg1);
}
private DataSource getDatasource() {
if(datasource == null) {
this.datasource = DataSourceBuilder
.create()
.driverClassName(env.getProperty("testError.datasource.driverClassName"))
.url(env.getProperty("testError.datasource.url"))
.username(env.getProperty("testError.datasource.username"))
.password(env.getProperty("testError.datasource.password"))
.build();
}
return datasource;
}
}
But it dosen't work.
I put a break point on the getConnection() methode and i raised tha it's called on startup by
org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl
class
Is there any configuration to avoid hibernate check the getConnection() methode on starup ?
Thanks in advance
A datasource is just an interface with a 'getConnection()' method on it.
So create your own implementation that delegates to a singleton that is created only when getConnection is first called.
In other words, whilst your implementation can be a Spring bean, its singleton dependency isn't, and isn't injected, but set the first time you access getConnection.

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

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

How can I get the bean definitions without actually creating the beans?

For static analysis of my Spring config, I need just the bean definitions - actually creating the beans would cause problems because some need a (properly initialized) database.
Is there a way to prevent the AnnotationConfigApplicationContext to create any beans? Instead, it should just load and analyze the config and stop.
you could implement the BeanDefinitionRegistryPostProcessor interface. in the postProcessBeanDefinitionRegistry method you have access to BeanDefinition's
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// ...
}
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registry.getBeanDefinition("myBean");
}
}

Resources