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