In application.properties, I specified
spring.profiles.active=dev
which should have picked application-dev.properties as the profile to activate.
However, when I Run As Java Application in Eclipse, I got the following message.
No active profile set, falling back to default profiles: default.
My best guess is this has something to do with Eclipse. Any comments?
Edit: I have tried Maven Update Project, followed by mvn clean install -U, also tried restarting Eclipse and cleaning the project. None of these worked...
I was getting the same Problem.
After adding the below dependency in the pom.xml file, the application starts running.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Each enterprise application has many environments, like: dev, stage, prod.
Every environment requires a setting that is specific to them. For example, the database settings for dev env are not the same for prod env.
To create multiple environments in spring we should create a properties file for each one.
NB: No matter what type of file you use .properties or .yml, it will work
The application.yml will remain as a master properties file, but if we override any key in the profile-specific file, the latter will gain precedence.
In the normal Spring way, you can use a spring.profiles.active property to specify which profiles are active. You can specify the property in any of the usual ways, for example you could include it in your application.yml:
You should specify the profiles to enable on the command line, if you you need to use multiple profiles make sure to separate them with a comma :
$ mvn spring-boot:run -Dspring-boot.run.profiles=dev
Related
I am now to Spring profile and I have a question, if I am doing a environment specific build using maven like mvn -Ptest then do I need to provide SPRING_PROFILES_ACTIVE parameter on execution.
If I understand Spring Profile correctly, giving SPRING_PROFILES_ACTIVE will direct my spring boot application to pick up the necessary application properties/#profile beans then why do I need to do mvn -Ptest.
One point I came accross is that mvn -Ptest allows us to package our properties file accordingly but in that case, isnt using Spring Profile a better solution.
It will be great if someone can point any scenario wherein we have to use mvn -Ptest even if we are using spring profile in Java application.
I think you are confusing maven profiles with spring profiles.
Maven profiles allow you to execute builds with different build configurations. It is only used during the maven build process.
Spring profiles can allow you to load different property files and is available at runtime to do whatever you want.
Now, you may have a maven profile that executes your spring application with a spring profile set but the difference is build vs execution time.
This has been driving me crazy - I have a Spring Boot app which uses Maven as its build tool. In the POM there are various profiles set up, which point to resources in a corresponding directory within the project, so that if you build, for example, with
mvn clean install -PBrandADev
you get Brand A's Dev profile, with the corresponding application.properties and other config files, and if you build it with
mvn clean install -PBrandBProd
you get Brand B's production profile. This is important to me because it controls which CMS I'm connecting to, and thus I'm able by building as Brand B Prod to run an instance of the Prod environment in debug & see what's going wrong when there's a bug, or otherwise to build the Dev profile for the development work I'm doing, to plug into the Dev CMS.
As it's a Spring Boot app, in the resources directory for each profile we have a banner.txt file that says "Brand A - Dev" or "Brand A - QA" or whatever the brand & CMS is for that profile.
Just lately though, I'm building for a particular profile, e.g. I want Brand B's Preview-Prod environment, and I see when it starts up for its integration tests "Brand B - Preview-Prod", which is as should be expected, but then when I start it up using the Application config item in the Run/Debug configurations widget at the top of the screen, it starts up saying "Brand A - Dev"
I've tried cleaning & reinstalling the app. I've tried re-importing the maven dependencies. I've tried invalidating the cache and restarting the IDE. I've tried deselecting all the profiles and reselecting the one I need. No joy. Except, just earlier today, it worked, and then I tried to swap back to the Dev environment & it got stuck on Prod. Does anyone know what I can do to force it to use the profile it's built with? Is this a bug in IntelliJ or what?
You can use the spring-boot maven plugin instead.
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
This allows you to use mvn spring-boot:run -PBrandADev and start the spring boot application with the correct maven profile.
A possible reason of such behaviour could be the Run Configuration used to start the application which builds it using default profile before starting the application. Verify Before Launch section of the configuration.
As a workaround, create a Run Configuration per profile you'd like to start, and specify -Dspring.profiles.active=<PROFILE-NAME> in the VM Options of the run configuration. Additionally, you could build the application using the same profile before starting it, adjust the Before Launch section accordingly.
I am new to maven and read bit about profiles at this and other resources
What i understood we use profile if we want to do override some default values or do some specific stuff.
In my legacy project i can see below profile where i just see overriding app.mode property. But i do not see using this property
further any where in build. I am sure what special being done here?
<profiles>
<profile>
<id>dev</id>
<properties>
<app.mode>dev</app.mode>
</properties>
</profile>
</profiles>
Maven profiles can be configured however you want them to be. Here are some use cases:
a) The project has several developers. For political and religious reasons, some of the developers are using Windows and some are using Linux. The team develops two profiles, one for Linux and one for Windows, setting project root paths, temporary folder paths, support program paths. These variables are injected into the dependency-calculation process, and subordinate processes that need this information. These profile settings are put into the settings.xml file for each programmer.
b) One of the developers is on loan to the project for a week. She doesn't want to reconfigure her computer for the project standard directory layout, etc., so she creates her own settings.xml that allows her to work in her own root directory.
c) The project uses a continuous integration server, such Hudson or Jenkins. The CI needs to have its own database for integration testing, so it would perhaps have modes like "devtest" and "prodtest" and "fulltest", depending on the requirements.
The profile would be activated if you pass -Pdev on the command line to Maven.
mvn -Pdev
See http://maven.apache.org/guides/introduction/introduction-to-profiles.html.
What this profile does is change the setting of the property app.mode from whatever it was before to dev. You will want to search your pom file (and the poms of any modules) for uses of $[app.mode} to see what's happening -- if anything.
Maven properties do not pass into Spring automatically, but it's not uncommon to find configuration in to re-export them as system properties to make them visible to Spring. This typically happens in the configuration for surefire and failsafe, but it's explicit, you'll still see ${app.mode} in a pom somewhere.
If the property being set there isn't used anywhere else in the build (did you check any sub-modules?) then the answer to your question is "In this case it does nothing."
However, in general, setting a property like that will make it available later in the build in case you needed it for something. If I had to guess, I'd say that this is the result of either an incomplete cleanup of code, or premature optimization.
I think your expectation is correct. Its used to pass on app.mode parameter to spring. See
How can I use maven profile Id value in spring bean files?
http://spring.io/blog/2011/02/11/spring-framework-3-1-m1-released/
In most Java projects (Maven, Spring) I work on, I have the following requirements:
The packaged jar needs to run in multiple environments e.g. dev, beta, prod
The jar must not be rebuilt for each environment
Each environment requires different configuration properties
In development, I need to be able to easily switch between different environments in order to ensure that each environment is configured correctly, before deployment
So far, I have accomplished this by putting all configuration properties into separate properties files, one per environment. I then have Spring load in these files from the classpath. Then I simply alter the classpath at runtime to load in the needed properties.
This approach has worked well when I was using Eclipse since it is easy to setup multiple run configurations and alter the classpath for each one. Once this is done, switching environments is a matter of choosing the relevant run configuration.
Unfortunately, this is much harder to accomplish in IntelliJ because runtime dependencies can only be added to a module's configuration (as documented in this answer). If I try to set the classpath in the run configuration itself then this overrides all of modules dependencies, preventing the application from running at all (as documented here). Therefore, to switch environment, I must re-edit the modules dependencies every time.
Is there an easier way of achieving this with IntelliJ?
If not, is that because my configuration requirements, or my solutions to them, are unusual? In which case, is there a better way?
Previous Approaches
I have already tried and rejected a number of approaches:
Maven Profiles - These require rebuilding my jar whenever I want to switch environment. Apart from being annoying and dangerous, this seems entirely inappropriate for runtime configuration (but ideal for buildtime configuration). This seems like a great way to risk getting a broken build into production as you aren't testing against the same jar that actually gets deployed. Yuck!
Spring Profiles - These look much more appropriate but appear to require all configuration to be deployed with the jar and distinguished by filename e.g. dev.properties, prod.properties. You can then select which one you want by passing a variable at runtime. This is much better but I don't want my prod.properties to find their way into version control, nor get deployed with the jar itself. Therefore, it still seems necessary to modify the classpath in order to include them which I can't easily do in IntelliJ
When I ran in similar problems, I started loading my properties with a helper class. The helper class will look for a System property that contains either the environment or the absolute/classpath-relative path to load the properties from.
That way, the code is always the same and I don't have to change the project's configuration. I just use different launch configs that set different properties.
The main drawback here of course that test / dev configs leak into prod. With Maven, the simple solution is to move those into a new module and set the scope for it to provided. That way, the module will be visible inside of Maven but it won't be included during WAR packaging, etc.
I do something similar to what #AaronDigulla does but I overlay the properties. That is I first load all the properties from property files in the classpath (using Spring). Then I search for specific variable name and value (in the following order):
in servlet init parameters
then in system properties
finally then environment variables
This variable name and value contains the path of property files that will override/overlay the properties loaded from the classpath. Also each property loaded will perform the same type of resolution (that is system properties, environment variables and servlet init parameters override the properties from the property file).
Now all developers are pushed to use the default configuration that is in the classpath (ie use the same username/password for their database). Those that have different settings can use the above 3 different ways to override.
You can use the same bootstrapping configuration code that I use which will load all property files in classpath*:META-INF/spring/*.properties first then it will load all property files with the file/classpath URL set in the property/environment/init parameter variable called MyConfigParameter (if set).
Then finally after the property files are loaded it will set the Spring profiles by pulling the property/environment/init parameter called MyConfig.profiles (comma separated).
So in production you might set the environment variable MyConfigParameter=file://etc/myapp/*.properties.
Then in one of those property files you might set MyConfig.profiles=production,postgres which will set the Spring profile production and postgres.
Your Maven profiles for releasing/building on your build machine can obviously adjust the MyConfigParameter in the environment using System Properties. However you will have to tell surefire unit testing specifically about this property (especially if forking):
<!-- Surefire setup -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.9</version>
<configuration>
<printSummary>false</printSummary>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<systemPropertyVariables>
<MyConfigParameter>${MyConfigParameter}</MyConfigParameter>
</systemPropertyVariables>
</configuration>
</plugin>
<!-- Profile to change MyConfigParameter -->
<profiles>
<profile>
<id>release</id>
<activation>
<property>
<name>env</name>
<value>release</value>
</property>
</activation>
<properties>
<MyConfigParameter>file://etc/MyApp/*.properties</MyConfigParameter>
</properties>
</profile>
</profiles>
My Maven project contains 3 different profiles, dev, stage, and prod, that contain different configuration settings. I would like to make it so that the install and deploy phases cannot be executed (or execute but do nothing) if the active profile is not prod, to keep dev and stage builds out of the repo. Is there a way to do this?
I'm guessing it involves adding the <plugin> to the dev and stage profiles and manually binding it to a "none" phase or something like that.
If that's what you really want to do, then just run the "package" phase on dev and staging, and in your maven settings file the provided user should not have write privileges to the repository.
What I would recommend doing, though, is to keep your configuration files outside of the build artifact, so that you only have one build that gets promoted between environments. As part of a script for deploying a build, you can automatically copy the correct settings, getting a similar effect.
Regardless of whether how you want to do this is the best idea, what you could do is use the Maven Enforcer Plugin to validate that the profile property is set to the value of your 'prod' profile. The plugin binds by default to the validate phase, so you would need to bind it to the package phase, or only the 'prod' profile will be usable.
The specific recipe I would use for this:
There's a built-in rule called requireProperty you can use to make assertions on properties and their values. You could set a property from your prod profile and then (outside any profile) configure the enforcer plugin to check to see that said property is set to the value you expect. This is hokie, however.
I strongly suggest that you externalize environment-specific configuration values into property placeholders and use profiles only to set those values rather than switching out environment-specific config files or affecting the contents of the artifact that you're generating.