Can properties file be customised in spring boot? - spring-boot

I am new to spring boot. Spring boot has default properties file located in /src/main/resource folder with name application.properties. Now I want not to use the default property.
Suppose if I put two properties file:
1. demo1.properties
2. demo2.properties
How will be those two properties file referred in spring boot?
I am trying to use #PropertySource in main class but it is not working. Is there any other way?
This is my main class::
#SpringBootApplication
#ComponentScan("com.wiley.dnb.controller")
#PropertySource("classpath:log4j.properties")
#PropertySource("classpath:services.properties")
public class DNBMain {
public static void main(String[] args) {
// TODO Auto-generated method stub
SpringApplication.run(DNBMain.class, args);
}
}
Thanks in advance.

You need spring profiles!
Profiles help to have different application configuration for different environments.
At startup of your program, you choose which profile/configuration to use.
Here is a tutorial on this subject:http://www.springboottutorial.com/spring-boot-profiles

Add this dependency;
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
And add #PropertySource("classpath:application.properties") into your configuration Class.

You could annotate a configuration class with :
#PropertySource({"classpath:demo1.properties", "classpath:demo2.properties"})
to add properties in the Spring environment.
For example :
#SpringBootApplication
#PropertySource({"classpath:demo1.properties", "classpath:demo2.properties"})
public class MyApplication { ...}
Of course these properties file have to be located in the classpath at runtime.

Related

Using a RestTemplate in a non Web app in SpringBoot app

I have a Spring Boot app that is not a web app, that has this piece of code
ResponseEntity<GeolocationAddress> response = new RestTemplate().getForEntity(urlStringConnection,
GeolocationAddress.class);
But then I have this error:
The import org.springframework.web cannot be
resolved
so I added this dependency
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.0.2.RELEASE</version>
</dependency>
But then when I start the app I got this error:
Could not evaluate condition on org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration due to org/springframework/web/context/support/StandardServletEnvironment not found. Make sure your own configuration does not rely on that class. This can also happen if you are #ComponentScanning a springframework package (e.g. if you put a #ComponentScan in the default package by mistake)
I may be a little late, but I had similar issues. By default Spring Boot tries to deduce the type of the application context to use by examining the class path. If it finds either javax.servlet.Servlet or org.springframework.web.context.ConfigurableWebApplicationContext, it instantiates a WebApplicationContext.
To avoid the error you got, I had to do the following in the main method of the app:
#SpringBootApplication
public class App {
public static void main(String[] args) {
new SpringApplicationBuilder(App.class)
.contextClass(AnnotationConfigApplicationContext.class).run(args);
}
}
I also excluded any unwanted AutoConfigure classes in the application.properties :
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,org.springframework.boot.actuate.autoconfigure.TraceWebFilterAutoConfiguration,org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,org.springframework.boot.actuate.autoconfigure.EndpointWebMvcAutoConfiguration,org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,org.springframework.boot.actuate.autoconfigure.CrshAutoConfiguration

Spring Boot Override Properties Externally

I have a Spring Boot application that is getting deployed as a WAR to a Tomcat server. There is already a currently deployed Spring Boot application on Tomcat server that has an application.properties file on classpath that is overriding the one bundled in the WAR. I need to do the same thing for my application, but I can't use the name application.properties as it is already taken, and my application is trying to use the application.properties on the classpath from Tomcat, which is intended for the other Spring Boot application.
Is there a way I can tell Spring Boot to look for a properties file on the classpath called myapp.properties or something along those lines?
I tried doing the following, but it doesn't seem to work when being deployed as a WAR.
#SpringBootApplication
public class ParameterManagerApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(ParameterManagerApplication.class)
.properties("spring.config.name:parameter-portal")
.build()
.run(args);
}
}
By default, Spring Boot looks for the application.properties file in these locations.
/config subdir of the working directory
The working directory
config package in the classpath
classpath root
So, the following worked for us when we placed myserver.properties under any of these locations.
public static void main(String[] args){
System.setProperty("spring.config.name","myserver");
SpringApplication.run(Application.class,args);
}
Otherwise, You can try setting the spring.config.location as below.
new SpringApplicationBuilder(Application.class)
.properties("spring.config.name:application,myserver",
"spring.config.location:classpath:/external/myproperties/")
.build().run(args);
We can also optionally define a custom source where we’re storing these properties, else the default location (classpath:application.properties) is looked up. So we now add the above annotations to the existing properties class:
#Configuration
#PropertySource("classpath:configprops.properties")
#ConfigurationProperties(prefix = "dev")
public class ConfigProperties {
// previous code
}
Now any properties defined in the property file that has the prefix dev and the same name as one of the properties are automatically assigned to this object.
#Simple properties
dev.host=mailer#mail.com
dev.port=9000
Check this

How to correctly using Spring profile on windows

I am trying to maintain different Spring profiles for development and production, for which I have created a folder(web skeleton) on my desktop with my Spring Boot project, application-dev.properties and application-prod.properties.
However, I am unable to import the profile into my project. The code that I use to import it to my project is as follows.
#Configuration
#Profile("dev")
#PropertySource("file:///${user.home}/web skeleton/application-dev.properties")
public class DevelopmentConfig {
#Bean
public EmailService emailService(){
return new MockEmailService();
}
Can someone tell me if this is the right way to use PropertySource in Spring.
You can optionally define a custom source where we’re storing these properties, else the default location (classpath:application.properties) is looked up. So we now add the above annotations to the existing properties class:
#Configuration
#PropertySource("classpath:configprops.properties")
#ConfigurationProperties(prefix = "dev")
public class ConfigProperties {
// previous code
}
Now any properties defined in the property file that has the prefix dev and the same name as one of the properties are automatically assigned to this object.
#Simple properties
dev.host=mailer#mail.com
dev.port=9000
Check this
I have done this kind of configuration too
Just add below code in your configuration class
#PropertySource("classpath:application-${spring.profiles.active}.properties")
And this propery in application.properties
spring.profiles.active=dev
you can change it to prod and cert as per you need.

Spring-boot not respecting liquibase properties

I'm in the process of setting up liquibase to manage my database in a new spring boot application. I need the liquibase dependency in my classpath to reset the database state after certain integration tests run. During my tests I do not want liquibase to be enabled via spring auto config during application context initialization. I've tried adding liquibase.enabled = false to the application.properties, however when I debug the LiquibaseAutoConfiguration class it appears that enabled is always set to true.
I'm not new to spring, but I am new to spring-boot's auto configuration. Has anyone had issues with spring boot not respecting properties in application.properties?
My setup is fairly minimal:
Relevant code snippets:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { SpringBootClass.class })
public class databaseTests{
#Before
public void setup() throws LiquibaseException, SQLException {
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(new JdbcConnection(dataSource.getConnection()));
Liquibase liquibase = new Liquibase("db/changelog/db.changelog-master.yaml", new FileSystemResourceAccessor("src/main/resources/"),database );
liquibase.dropAll();
liquibase.update("test");
}
..
}
#SpringBootApplication
#Import({ DataSourceConfig.class, HibernateConfig.class, OauthConfig.class })
#EnableConfigurationProperties
public class SpringBootClass {
..
}
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.6.RELEASE</version>
<!-- <liquibase.version>3.3.5</liquibase.version> -->
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<scope>test</scope>
</dependency>
If you want your tests to consume application.properties you need to run them as a Spring Boot application. Your use of #ContextConfiguration means that you're currently running them as a vanilla Spring Framework application. Replace the #ContextConfiguration annotation with #SpringApplicationConfiguration.
Should have RTFM...
from spring boot documentation
ConfigFileApplicationContextInitializer is an
ApplicationContextInitializer that can apply to your tests to load
Spring Boot application.properties files. You can use this when you
don’t need the full features provided by
#SpringApplicationConfiguration.
#ContextConfiguration(classes = Config.class,
initializers = ConfigFileApplicationContextInitializer.class)
Changing my config to use the initializer worked.

drools-6 (kie) auto scanning (from spring) of modules and sessions from kie workbench deployed artifacts

I am trying to build a web (spring-mvc) application with kie (drools 6) integrated via injection. I have used kie workbench to create a workflow, complied and deployed. I have added reference of this artifact in my project's pom.xml and added the local kie-workbench repository as per this blog post and it's working fine (pulling in the artifact as dependency in my maven/spring project). What I am trying to do is inject the kiesession in one of my service as dependency with following snippet -
#Service
public class TniServiceImpl implements TniService {
#Inject
#KSession("tniSession")
private KieSession tniSession;
...
}
In my root-context.xml, I have added the kie namespace as well along with reference to xsd. I have added org.kie.spring.KModuleBeanFactoryPostProcessor as well as per drools documentation. I am trying to make CDI injection work for KSession scanning and injection (it's already working for my other components in same project, using #Inject). So far I am always getting "No qualifying bean of type [org.kie.api.runtime.KieSession] found for dependency" error. Looks like spring is not able to scan the available kie modules and sessions therein. Need help on following -
Is CDI inject really supported with spring? Do I have to configure kmodules and kession explicitly as mentioned here?
Am I missing something here which should make this scanning and injection work?
My environment is following -
spring 3.2.6-RELEASE (including webmvc and other components)
kie-api-6.0.1.FINAL
kie-spring-6.0.1.FINAL
kie-internal-6.0.1.FINAL
I have already gone through following links but no luck (mostly they are not trying to do what I am) -
Loading Drools/KIE Workbench artifacts directly from the repository
why does loading Drools 6 KIE JAR into code fail?
I'll appreciate if anybody can guide me on what could be the missing piece here or if there's no option but to explicitly define all kmodules/ksessions in spring config file.
I had the same problem and found a solution here: http://drools.46999.n3.nabble.com/Spring-4-0-amp-Drools-6-0-1-Integration-issue-td4028052.html
Basically you will need to inject ApplicationContext instead of kieSession and get xml bean manually.
TniServiceImpl.java
#Service
public class TniServiceImpl implements TniService {
#Inject
ApplicationContext context;
KieSession kieSession;
#PostConstruct
public void postConstruct(){
kieSession = (KieSession) context.getBean("ksession1");
}
...
}
root-context.xml
<kie:kmodule id="kmodule1">
<kie:kbase name="kbase1">
<kie:ksession name="ksession1" />
</kie:kbase>
</kie:kmodule>
<bean id="kiePostProcessor" class="org.kie.spring.KModuleBeanFactoryPostProcessor" />
Hope this helps.
UPDATE:
Another way to achieve this is to keep xml identical and instead of trying to inject KieSession, inject KieBase. Then, with the instance of KieBase, create new KieSessions.
#Service
public class TniServiceImpl implements TniService {
#Autowired
private KieBase kbase;
/* inside some method */
#RequestMapping(method=RequestMethod.GET)
public #ResponseBody Data getData() {
KieSession ksession = kbase.newKieSession();
...
}
}
The above answer doesn't work with spring mvc. I found that this is a bug in the existing drools and they are fixing it in the next version. I am stuck at this point since I am using DROOLS in batch mode but I want it to be used in a REST Service hosted on websphere.
The above solution works perfectly within a batch program.
This is what I have working with the latest Spring MVC (Spring Boot)
#SpringBootApplication
public class DroolDemoApplication {
public static void main(String[] args) {
SpringApplication.run(DroolDemoApplication.class, args);
}
#Bean
public KieContainer kieContainer() {
return KieServices.Factory.get().getKieClasspathContainer();
}
#Bean
public KieSession kieSession() throws IOException {
return kieContainer().newKieSession("DroolDemoSession");
}
}
and below is the kmodule.xml
<kbase name="DroolDemoKbase" packages="rules">
<ksession name="DroolDemoSession" />
</kbase>
finally all you do in your controller is
#Autowired
private KieSession kieSession;
kieSession.fireAllRules();
hope this helps those folks still having issues
I had similar issues with the rules not being triggered, and I solved it by using the 6.2.0.Final version of the kie-ci and kie-spring. I tried versions: 7.7.0, 7.2.0, 6.5.0 and 6.4.0, but none of them worked.
...
<properties>
<kie.version>6.2.0.Final</kie.version>
</properties>
...
<dependencies>
...
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-ci</artifactId>
<version>${kie.version}</version>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>kie-spring</artifactId>
<version>${kie.version}</version>
</dependency>
...
</dependencies>
What also helped was running mvn dependency:tree and seeing which versions of which artefacts/projects are being used.

Resources