Spring Boot Application not reading application.properties file when using Maven test - spring

UPDATE:
I realized a couple of things now. My application.properties file is being loaded properly because I verified via the /env path (thanks Dave) that my DB properties are being loaded. The problem appears to be that when I run it using the Spring Boot maven plug-in, it fails to initialize my dataSource.
mvn spring-boot:run
This then causes my application to blow-up with errors because other beans can't get initialized. The odd thing is it runs fine from Eclipse.
I have a class called DataService that extends JdbcTemplate. In my DataService constructor, I inject the DataSource.
#Component
public class DataService extends JdbcTemplate {
#Autowired
public DataService(DataSource dataSource){
super(dataSource);
}
...more custom methods
}
I use this DataService class in other beans to perform DB operations. My DataSource is defined in my application.properties file
spring.datasource.url: jdbc:h2:tcp://localhost/~/testdb2
spring.datasource.driverClassName: org.h2.Driver
This is my Application.java class
#Configuration
#ComponentScan
#EnableAutoConfiguration
#EnableWebMvcSecurity
#EnableAsync
#EnableScheduling
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I first realized this when I was attempting to run jUnit tests from Maven using
mavent test
I thought it just had to do with how it was executing the jUnit test cases however it is also occurring when I simply try to run the application using maven.
My JUnit4 test class is defined as follows:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes={Application.class})
#WebAppConfiguration
public class QuestionRepositoryIntegrationTests {
...methods
}
I used the example from the Spring Boot how-to docs (https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html)
When I run this JUnit class from Eclipse, it works just fine. When it executes from maven, it starts to act up as I described above.

Try to define the <resources> tag in the build section in your pom, setting path for resource directory where is application.properties:
<build>
<resources>
<resource>
<directory>resources</directory>
<targetPath>${project.build.outputDirectory}</targetPath>
<includes>
<include>application.properties</include>
</includes>
</resource>
</resources>
</build>

You can configure your main datasource as the following, I'm using mysql here. But you can use your own datasource. you can configure the following in your application.properties inside src/main/resources
spring.datasource.url = jdbc:mysql://localhost:3306/dsm
spring.datasource.username = root
spring.datasource.password = admin123
spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
To run test inside your application you can either use the same datasource or create application-test.properties inside src/test/resources and it's possible to configure test data source over there.

Just add the following statement;
#TestPropertySource("classpath:application.properties")
To your test class. I am assuming you have your application.properties file under src/test/resources
Here is my working example;
#RunWith(SpringJUnit4ClassRunner.class)
#TestPropertySource("classpath:application.properties")
public class TestTwitterFeedRoute extends CamelTestSupport {
//...
}

This works for me:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestApplication.class,
initializers = ConfigFileApplicationContextInitializer.class)
public class SomeTestClass {
...
}

Make sure your #ConfigurationProperties annotation is set to the same prefix as whatever you're using in your configuration file (application.config)

If you're using eclipse, its always a good idea to check the projects build resources. (Rclick project->properties->build path)
I was not getting my application.properties file picked up and turned out I simply missed adding it to build resources.

I'm trying to load all properties files form outside jar, below entry in pom works perfect, you can also exclude or include files depends upon requirements.
<build>
<resources>
<resource>
<directory>config</directory>
<includes>FILENAME</includes>
<excludes>FILENAME</excludes>
</resource>
</resources>
</build>

Related

Is it possible to load Spring-Boot properties from config folder within parent module of a Maven multi-module project?

Is it possible to load multiple Spring-Boot .yml config files from a config folder within parent module of a multi-module project?
So, structure looks like this:
parent-module/
pom.xml
config/
application-prd.yml
application-dev.yml
module1
pom.xml
src/main/resources/
logback-spring.xml
bootstrap.yml
Is this possible? How can it be done?
So, if I execute from root folder of multi-module project, I would use this command:
mvn -pl module1 spring-boot:run
OR
mvn spring-boot:run
And I would hope that the config folder would be included in the classpath? I am trying to do this but not getting it to work. Am I missing something?
We know this to be true: Child POMs inherit properties, dependencies, and plugin configurations from the parent. But shouldn't that mean that {parent}/config/application.yml is in the classpath already?
Example project to use for proving: https://github.com/djangofan/spring-boot-maven-multi-module-example . Clone it and modify if you think you can solve it.
No need to write code. You can use Exec Maven Plugin for this. Add the plugin to the parent module:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<configuration>
<mainClass>PACKAGE.MODULE_MAIN_CLASS</mainClass>
<arguments>
<argument>--spring.profiles.active=dev</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
then run mvn install once and then mvn exec whenever you want to start the application.
mvn exec:java -pl module1
For more on Maven goals in a multi-module project, check this answer https://stackoverflow.com/a/11091569/512667 .
Another way to configure this is like so, which requires the workingDirectory arg:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.example.Application</mainClass>
<workingDirectory>${maven.multiModuleProjectDirectory}</workingDirectory>
<arguments>
<argument>--spring.profiles.active=dev</argument>
</arguments>
</configuration>
</plugin>
In this case, execute:
mvn spring-boot:run -pl module1
Yes, it is possible.
Maven changes the working directory to the module's directory when you use the -pl. So it is no longer the root which has the config/ dir.
Either you can refactor your maven multi-module setup to a way that you can package the common application.yml files and than use them. I wouldn't recommend that as it has many pitfalls.
Probably easier to use the --spring.config-location
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
I can not test it at the moment but if it doesn't work you can always try the -Dspring.config.location or the SPRING_CONFIG_LOCATION environment variable.
I found a customized way of doing it, which I still consider to be a hack, as you can see below, but I am still looking for an actual answer to my question, if it exists.
#Slf4j
#SpringBootApplication
public class Application {
private static String DEV_PROPS = "application-dev.properties";
private static String PRD_PROPS = "application-prd.properties";
private static String DEFAULT_PROPS = "application.properties";
private static Path CONFIG = Paths.get(System.getProperty("user.dir"))
.resolve(Paths.get(".."))
.resolve("config");
private static final String EXT_CONFIG_DIR = CONFIG.toString() + File.separator;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer properties = new PropertySourcesPlaceholderConfigurer();
Resource[] resources = new Resource[] {
new FileSystemResource(EXT_CONFIG_DIR + PRD_PROPS),
new FileSystemResource(EXT_CONFIG_DIR + DEV_PROPS),
new ClassPathResource(DEFAULT_PROPS)
};
log.info("Properties: " + Arrays.deepToString(resources));
properties.setIgnoreResourceNotFound(true);
properties.setLocations(resources);
return properties;
}
}
The problem with this method, is that configuration has to be changed to support additional environment profile names.

I have 2 CommandLineRunner in same Spring boot

I have 2 classes in spring boot that implement command line runner. They basically look like this:
#SpringBootApplication
#ComponentScan("com.xxxx")
public class Application implements CommandLineRunner {
and the second looks like:
#SpringBootApplication
#ComponentScan("com.xxxx")
public class ApplicationWorklfow implements CommandLineRunner {
They compile fine. But when I try and run it with java -jar, I get an error presumably as spring does not know which one to run.
is there a command that I can use that will tell the jar which application I am trying to run?
You can have any number of CommandLineRunner beans but there should be only one entry point class that can have #SpringBootApplication annotation. Try by removing #SpringBootApplication annotation on ApplicationWorklfow.
PS:
It seems your main requirement is to conditionally enable one of 2 CommandLineRunner beans. You can have only one Application class and enable CLR beans conditionally either using #Profile or #ConditionalOnProperty etc.
Having multiple entry point classes with #SpringBootApplication annotation is not a good idea.
#SpringBootApplication
public class Application {
}
#Component
#Profile("profile1")
public class AppInitializer1 implements CommandLineRunner {
}
#Component
#Profile("profile2")
public class AppInitializer2 implements CommandLineRunner {
}
Now you can activate your desired profile as follows:
java -jar -Dspring.profiles.active=profile1 app.jar
With profile1 activated, only AppInitializer1 will run.
PS: PS:
If for some reason you still want to configure mainClass you can do as follows:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>${start-class}</mainClass>
</configuration>
</plugin>
You might leverage Maven profiles to provide different classes for different profiles. See https://docs.spring.io/spring-boot/docs/2.0.1.RELEASE/maven-plugin/usage.html for more info.

Spring - Combing Java Config and Xml to reference a bean defined in legacy XML

Is it possible to configure a classpath resource for a Java bean in any other location in the classpath than src/main/resources? I have an application which picks up its configuration files from src/main/app/conf/beans.xml. I want to use the bean defined in the xml configuration in my JavaConfig configuration, how can I specify the location in a JavaConfig file, for example something like below?
#Configuration
#ImportResource("classpath:..beans.xml)
public class AppConfig{
// Reference Bean
#Autowired
private MessageLoader loader;
}
That is certainly possible. If your resources are not present in src/main/resources then, you can specify that directory in your POM.
<resource>
<directory>[your folder here]</directory>
</resource>
Reference here

how load external configuration class in spring boot

I have a spring boot application
The structure of my application is:
src
main
java
org
Application.java
service
--another classes are here
Application.java
package org.baharan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) throws Throwable {
SpringApplication.run(Application.class, args);
}
}
Another confirguration class files sush as oracle config and security config are in another application(is named core) is added in my pom.xml
<dependency>
<groupId>org.baharan.amad</groupId>
<artifactId>core</artifactId>
<version>1.0-releases</version>
<type>war</type>
</dependency>
When i build my application, all of classes and properties files of core application are added in my target by overlay maven
When i excute Application.java,spring boot couldn't find any config class isn't in my application but they are in core(after build all of them is added in my target)
In other word how spring boot load configuration classes which dont exist in current application.
please help me.
If they're spring configs you can still use #ComponentScan to load in other bean configs e.g.
#ComponentScan("classpath*:com.myorg.conf")
and
#ComponentScan("classpath*:conf/appCtx.xml")

Netbeans 8 won't reload static Thymeleaf files

I am using Spring Boot and Thymeleaf via Maven. I can't seem to get Netbeans to automatically re-deploy any of my Thymeleaf template files when I make changes. In order to see the changes I need to do a full clean/build/run. This takes way too long.
The templates are in src/main/resources/templates. I have an application.properties file in src/main/resources/ with spring.thymeleaf.cache=false and spring.template.cache=false.
I have "Compile on save", "Copy resources on save" and "Deploy on save" turned on in the project settings.
My maven build produces a war file that Netbeans deploys to Tomcat and I am using the annotation #EnableAutoConfiguration.
Netbeans does hot deploy changes to the Java classes but not for any of the static files in src/main/resources/.
Software in use:
Mac OS X 10.9.4
Java 1.8
Netbeans 8.0.1
Tomcat 8.0.12
Spring Boot 1.1.7
Thymeleaf 2.1.3 (via Spring Boot)
Any guidance is much appreciated.
An option would be to look into configuring Thymeleaf's FileTemplateResolver
To do that with Spring Boot, define a bean implementing the ITemplateResolver interface with the name defaultTemplateResolver, when present, Spring Boot would take it instead of its default, here is how that would be done, and assuming you have component scanning active so this configuration class will be picked up automatically:
#Configuration
public class ThymeleafConfiguration {
#Bean
public ITemplateResolver defaultTemplateResolver() {
TemplateResolver resolver = new FileTemplateResolver();
resolver.setSuffix(".html");
resolver.setPrefix("path/to/your/templates");
resolver.setTemplateMode("HTML5");
resolver.setCharacterEncoding("UTF-8");
resolver.setCacheable(false);
return resolver;
}
}
The prefix should be a relative path that when added to your runtime working directory (cwd), would resolve to the templates directory. If you are unsure, set that to the full absolute path, but then there would be no point of the above bean. Since setting the spring.thymeleaf.prefix property to an absolute path would probably have the same effect.
Have been looking for a solution to my eclipse+thymeleaf+sprint boot reloading templates dynamically for a log while....
Finally I found this question here and spring.thymeleaf.cache=false and spring.template.cache=false fixed my issue.
Besides setting the Thymeleaf views as non-cacheable by ie. spring.thymeleaf.cache=false in your application.properties,
try explicitly defining the resource directory in your pom.xml:
<build>
...
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
...
</build>
To deal with that, the spring-boot-maven-plugin in the pom.xml should seems like this:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>
</dependencies>
</plugin>
And add this to your application properties:
spring.thymeleaf.cache=false
It usually works to Spring beans too.
Just to say this works nicely for me using an external instance of Tomcat:
Run Tomcat with JRebel or Spring Loaded javaagent as a VM option
Turn off "Compile on save", "Copy resources on save" and "Deploy on save"
Add a custom action in Netbeans that executes the compile goal
Run that when you want to see an update
http://wiki.netbeans.org/MavenBestPractices#Binding_Maven_goals_to_IDE_actions
https://github.com/spring-projects/spring-loaded
https://zeroturnaround.com/software/jrebel/quickstart/standalone/
Or you can you use the embedded tomcat with spring-boot-maven-plugin and Spring Loaded instead, then you won't need the compile action:
https://docs.spring.io/spring-boot/docs/current/reference/html/howto-hotswapping.html
I had this problem too. I notice Netbeans reload automaticaly webpages that are in
/src/main/webapp/
You have to move all your templates from /src/main/resources/templates to this directory.
Also you have to change the spring boot property on application.properties file:
spring.thymeleaf.prefix=templates/
That works for me
I had this same issue on Netbeans 8.0.2 and Windows. I was building a WAR to be deployed to Tomcat, but I wanted to try out Spring Boot. It looks like newer versions of Netbeans might resolve this with the Spring Boot plugin or using Eclipse. It seemed nutty to swap IDEs over something tiny like this. I tried all of the suggestions I could find; spring loaded, caching properties, extending the TemplateResolver...I couldn't get any of them to work. I finally stumbled on this blog and following these instructions solved my issue.

Resources