Spring Boot - Autowiring a DataSource Bean - spring

I have a basic Spring Boot application annotated like this:
#SpringBootApplication
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
I have the following entries in my application.properties file:
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/db
spring.datasource.username=dbuser
spring.datasource.password=dbpassword
From my understanding Spring Boot should be able to automatically autowire a DataSource Bean from these properties.
However if I try:
#Autowired
DataSource dataSource;
anywhere in my application (f.i. in #Configuration files), I get the following error in IntelliJ:
"Could not autowire. No beans of 'DataSource' type found."
Is there something obvious that I'm missing for this to work?
I have a single DataSource.

The bean actually does get initialized correctly. This is possibly just an IntelliJ tooltip bug.
Adding #SuppressWarnings to hide the message will work without further issues.

Intelij apparently even in the 2016.2 still does not support the #SpringBootApplication annotation. You either have to remove the #SpringBootApplication annotation and replace it with the #Configuration, #EnableAutoConfiguration and #ComponentScan annotations or just ignore the errors.

Related

Is ApplicationContext automatically instantiated in Spring?

Is ApplicationContext automatically instantiated in Spring?
If I have my bean defined like this
#Component
public class Car{
...
}
and then I have my config class which tells Spring container where to look for beans through the annotation #ComponentScan
#Configuration
#ComponentScan
public class AppConfig {
...
}
Is Spring automatically creating a context loading all my beans? Or do I have to create it programmatically? If so how do I do it, with something like this?
#Configuration
#ComponentScan
public class AppConfig {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
context.getBean(Car.class);
...
}
Even doing this, there may be a problem, because every time I need the context I have to call new AnnotationConfigApplicationContext...
what is the recommended way to instantiate the context and making him available inside the whole project, maybe as a bean like inside Spring boot app where i can just autowire it.
How Spring Boot can initialize it, load all the beans and let the context available as a bean, ready to be autowired?
No, Application Context isn't automatically instantiated, if you're having a simple and basic Spring Core application. Moreover, your #Configuration class won't scan anything and won't create any beans, if you don't create your Spring Container/Context explicitly with that #Configuration class.
There are several ways of creating Application Context, but the most popular and traditional ones are:
ApplicationContext context = new ClassPathXmlApplicationContext(applicationContext.xml) - implying, that you have your container configuration in the applicationContext.xml file;
ApplicationContext context = new AnnotationConfigApplicationContext(ConfigClass.class); - implying, that your ConfigClass is the #Configuration class.
However, if you have the Spring Boot application annotated with #SpringBootApplication, then the Application Context will be automatically instantiated for you, because:
#SpringBootApplication annotation consists of:
#EnableAutoConfiguration - which enables Spring Boot’s auto-configuration mechanism;
#ComponentScan - which enable #Component scan on the package where the application is located;
#Configuration - allows to register extra beans in the context or import additional configuration classes.
and this will spin up the context for you.
You can obtain the reference to the Spring Context created by Spring Boot, by the factory method you have in your main method: SpringApplication.run(MainClass.class, args);
This returns the reference to the Application Context and you can assign it to variable like this:
ApplicationContext context = SpringApplication.run(MainClass.class, args)

Split jackson configuration into separate properties

I'm using Spring Boot 2.2.5.RELEASE and would like to split my application.properties into separate files. There are already similar questions on StackOverflow but none of them seem to work for configuring Jackson.
My current non working solution is the following:
root/
- application.properties (without Jackson configuration)
- jackson-configuration.properties (includes Jackson configuration)
Jackson configuration class:
#Configuration
#PropertySource("/jackson-configuration.properties")
public class JacksonConfiguration {
}
Please note, I've tried different ways to specify the path including:
"/jackson-configuration.properties"
"jackson-configuration.properties"
"classpath:/jackson-configuration.properties"
"classpath:jackson-configuration.properties"
Spring Boot does not seem to use the configuration. If I copy it over into the application.properties - it works.
Content of jackson-configuration.properties:
spring.jackson.property-naming-strategy=SNAKE_CASE
spring.jackson.mapper.sort-properties-alphabetically=true
spring.jackson.deserialization.fail-on-unknown-properties=true
spring.jackson.parser.strict-duplicate-detection=true
spring.jackson.time-zone=Europe/Zurich
My application is annotated with #SpringBootApplication , so it should scan for additional properties.
/edit
I just realized the problem is the testing, not the productive code itself. If I start the application it works. What doess not work is testing with #JsonTest. I can fix this problem by adding the following line to my tests #ContextConfiguration(classes = {JacksonConfiguration.class}). But in turn, this causes the annotation #JsonComponent to stop working but only for the #JsonTest annotated classes.
See the documentation here. Here is an excerpt from the documentation
In order to resolve ${...} placeholders in definitions or
#Value annotations using properties from a PropertySource, you must
ensure that an appropriate embedded value resolver is registered in
the BeanFactory used by the ApplicationContext. This happens
automatically when using in XML. When
using #Configuration classes this can be achieved by explicitly
registering a PropertySourcesPlaceholderConfigurer via a static #Bean
method.
You need to create a bean like this
#Bean
public static PropertySourcesPlaceholderConfigurer devPropertyPlaceholderConfigurer() throws IOException {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer.setLocations(new PathMatchingResourcePatternResolver().getResources("file:pathtToFile"));
configurer.setIgnoreUnresolvablePlaceholders(true);
return configurer;
}

Spring #configure annotation usage without bean definitions

I have some experience with spring dependency injection and transaction management but I am new to spring security. When i was reading an article related to spring security, I found that #Configuration annotation is used in an example but there were no bean definitions to be found.
According to my understanding, #Configuration annotation is used in classes which contain bean definitions. I need to know that what does the #Configuration annotation do in this example.
#Configuration
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {
#Autowired
DataSource dataSource;
... // web stuff here
#Override
public configure(AuthenticationManagerBuilder builder) {
builder.jdbcAuthentication().dataSource(dataSource).withUser("dave")
.password("secret").roles("USER");
}
}
Thank you
It's not mandatory to have Bean definitions in Spring managed classes.
In this case #Configuration (which wraps #Component) is used to indicate to Spring that this class should be instantiated and all it's dependencies should be injected - in this case that's DataSource and AuthenticationManagerBuilder. This is an example of Inversion of Control principle.
Spring also provides these ConfigurerAdapter hook points, where you can tweak the default configuration of an already instantiated component.
This is exactly what is happening in your Configuration class.

Disabling Transaction Management in Spring JMS listener

I have a spring boot application as a Spring JMS listener. i have configured multiple datasource manager one for Oracle and another one for DB2 .
whenever i am starting app ,jms listener container is looking for a transaction manager bean and giving below error as it find two bean.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.autoconfigure.jms.JmsAnnotationDrivenConfiguration': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.transaction.PlatformTransactionManager org.springframework.boot.autoconfigure.jms.JmsAnnotationDrivenConfiguration.transactionManager; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2: db2TransactionManager,oracleTransactionManager
i dont want to maintain JMS transaction. how could i achieve it or how can we disable jms transaction feature?
below are the annotation i have added on my main spring boot class. also i am using Spring Data repository
#SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
#ComponentScan(basePackages = "com.deere.oracledataupdate.*")
//#EnableJpaRepositories(basePackages ="com.deere.oracledataupdate.dao.springdata")
#EntityScan(basePackages = "com.deere.oracledataupdate.*")
#PropertySource({ "classpath:application-${IafConfigSuffix}.properties" })
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Looking to the current Spring Boot code we have (JmsAnnotationDrivenConfiguration):
#Autowired(required = false)
private JtaTransactionManager transactionManager;
So, right now it requires only the bean which is exactly JtaTransactionManager by type. I guess both yours are DataSourceTransactionManager.
I'm sure that was correct fix to worry only about the XA tx-manager for auto-config.
Seems for me you can fix your issue with something like #Primary on one of your tx-manager beans.
But... Do you need a JMS Annotation support in your application at all?
Maybe it would be just enough to exclude JmsAnnotationDrivenConfiguration as well?
If need it anyway, I see only one way to fix it: disable JmsAnnotationDrivenConfiguration and configure #EnableJms manually, bypassing the tx-manager issue and just don't configure it for the DefaultJmsListenerContainerFactory as you request.
See JmsAnnotationDrivenConfiguration source code for more information.

#Profile cause Unable to start EmbeddedWebApplicationContext

im trying to use #Profile functionality to separate production/dev environment configuration and 'tests' config. But when I add #Profile to my configuration class I get:
Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:124)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:476)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
at mypackage.configuration.PhoenixConfiguration.main(PhoenixConfiguration.java:26)
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:174)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:147)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:121)
... 7 more
Configuration class looks like this:
#Configuration
#EnableAutoConfiguration
#ComponentScan("mypackage")
#EnableJpaRepositories(basePackages = "mypackage.repository")
#EntityScan(basePackages = "mypackage.phoenix.domain")
#PropertySource("classpath:properties/application-production.properties")
#EnableWebMvc
#Profile("production")
public class PhoenixConfiguration extends WebMvcConfigurerAdapter{
public static void main(String[] args) throws Exception {
SpringApplication.run(PhoenixConfiguration.class, args);
}
}
ive tried to set active profile to production in application-production.properties
spring.profiles.active=production (with and without " )
or cmd command: mvn spring-boot:run -Dspring.profiles.active=production
nothing helps. Ofcourse everything works when I remove #Profile, but then I my tests are using production database ; )
If you add the profile your whole application basically stops working because your main entry point is annotated with #Profile.
I suggest you let Spring Boot do its work at the moment it appears as if you are trying to work very hard around Spring Boot and you are making things, imho, too complex.
Spring Boot will autodetect Spring Data JPA and the fact that you have Spring Web on your classpath. So remove #EnableJpaRepositories and #EnableWebMvc and don't let your class extends WebMvcConfigurerAdapter.
Spring boot by default will load the application.properties for you instead of putting in in properties either place it in the root of your classpath or config. At least remove the #PropertySource as Spring Boot will just load it. If you want to keep the properties path add the spring.config.location property which then points to your properties directory.
Finally I would probably also rename the file to PhoenixApplication but that is just me. That should leave you with something like
#Configuration
#EnableAutoConfiguration
#ComponentScan("mypackage")
#EntityScan(basePackages = "mypackage.phoenix.domain")
public class PhoenixApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(PhoenixApplication.class, args);
}
}
Now simply put your production configuration in the application.properties and put another one in src/test/resources to contain your test configuration. At runtime only the first will be available when testing the latter will override properties from the first.
If you really want to use profiles I would suggest doing it the other way around, configure for production and override for test. Then simply add #ActiveProfiles to your test case.
#ActiveProfiles("test")
#SpringApplicationConfiguration(classes=PhoenixApplication.class)
public class YourTest {}
This will start a test which will load the default application.properties and a application-test.properties which you can simply place in src/test/resources.

Resources