Revision control , Build and deploy. production code vs test code - spring

Our project is comprised of a single war file (web application)
We have a master branch in our git repository that contains all the source files for it.
We are use a staging (test) environment and a production env.
both should be configured differently.
So our problem is:
When we push new features to the git repository, and building the war file. it consists data that is staging-specific. so we actually cant deploy this war in production.
Any idea on how to solve this issue? (the files that change from prod to test are for example:
spring config files, other config files, some xmls, etc)
one naive solution is to have 2 branches (one for production the other for testing) but that sounds really cumbersome.

For the long run:
Try to extract the specific settings from the spring context files, and make them parameter of your application that are configured in the application server.
For example the database connection settings: Configure a Database Connection in the application server and make them aviable via JNDI. Then your application can obtain the Database Connection from JNDI. So your application is independed of your concrete database connection settings.
You can use the same technique for other configuration. And of course you can use it to enable/disabe Spring Profiles.

Related

Clone only specific path - Spring Cloud Config Server

Is there any way by chance to make spring config server to clone only specific path instead of whole git repo? When I'm running it on production I may not want my entire code base repository to be cloned to some location as it is always a risk. I've done my research and couldn't figure out ways to clone only specific paths of git repo.
One solution is to host the configurations in a seperate repo. But that would defeat the purpose of one code many deploys suggestion of 12factor.net.
Another possibility is to copy the properties into config server's classpath and then to use native profile to load them. But this would defeat the purpose of Spring ConfigServer.
Also kindly do clarify What would be the best way to run spring config server on a production?
You should be separating your code base from your configuration settings.
Repo 1: Your App Code
Repo 2: Your Spring Cloud Config Server Code
Repo 3: Your configuration settings
When you're deploying, you're deploying the code. Not the configuration. A configuration change should not require a new deployment. A new deployment might require an updated configuration change, but the two are generally decoupled.
Configuration can be dynamically updated while code is running. This is completely separate from updating code and deploying the app. That's the whole point of externalized configuration.
TL;DR: You're looking at "one code many deploys" wrong. Configuration is externalized.
I took this straight from 12factor.net
Apps sometimes store config as constants in the code. This is a violation of twelve-factor, which requires strict separation of config from code. Config varies substantially across deploys, code does not.
Even though you are no longer storing them as constants but still in the same repository is not enough separation from the code. Use a separate repository for configurations.

UI base config for spring boot

I have a centralized configuration for spring boot service. I followed this link to make it.
I have configServer and configs two separate project. Configs have several properties files. And configServer reading it and rendering to other services.
Now I want to make configs UI based.
e.g.
application.properties of configs which is hosted at git.
logging.path=logs
logging.level.root=INFO
logging.level.org.springframework.boot.autoconfigure.security=INFO
It`s UI should be
logging.path as key text box for value( logs ).
Is there any example for it. Any help will be appreciated.
Thanks.
Since you mention using text box in your post, I'm assuming that by UI you mean GUI.
While I'm not aware of any examples (and you do not specify whether you want to have a destktop or web application) if you're using git to store configuration, your app needs to:
Checkout the git repo with configuration (using JGit for example)
Load properties files generate edit window for each file (something
similar to what IntelliJ does for environment variables in run
configurations perhaps)
Save edits to files
Commit and push changes (again using JGit or a similar library)

How to configure different data sources for local testing and deployment in Spring Boot Application

I am trying to find the best way to configure my Spring Boot Web application to easily switching between the following data sources for both local testing and deployment.
H2 in memory db. Local testing only.
Dev oracle. Local testing and deployment.
Prod oracle. Deployment only.
By local testing, I mean to test in IDE environment (Eclipse). Dev and prod oracle databases are set up on two remote servers.
After some research, there are different ways to switch from one data source to another.
Use Spring profile. Using H2 and Oracle with Spring Boot. Set up the following files in classpath, application.properties, application-h2. properties and application-dev.properties. While connections for h2 and dev are defined in corresponding properties files, spring.profiles.active is set in application.properties. My understanding is this property can be overridden during build process by specifying spring.profiles.active. However, it seems to be a JVM variable, how do I set it running maven?
Maven profile. Create multiple profiles in pom and a filter pointing to application properties files. The profile specified by -P option during maven build will determine which application properties file to look. However, according to maven application with multi environment configuration can't deploy on tomcat, this will generate multiple wars for different deployment. So method 1 is preferred. Plus, it does not apply to switching datasources while testing locally.
Persistence units. Define different persistence units for different data sources in persistence.xml. Use EntityManager by choosing a specific unit. Variation of this method include having a variable in unit names which is determined in application.properties.
JNDI lookup. Set up a jndi name in application.properties with spring.datasource.jndi-name. The actual database information including url and credentials will be specified in context.xml in the tomcat folder where the war will be deployed.
My mind is set on local testing environment. Gonna go with method 1. Switching between H2 in memory and oracle is so easy just by changing the property in application.properties. Since the testing is usually done in IDE, war does not need to be generated, although answers are welcome for run maven install with spring.profiles.active.
As far as deployment, JNDI is definitely the way to go. However, I am concerned that the two properties in application.properties: spring.profiles.active and spring.datasource.jndi-name may be conflicting with each other. If I have spring.profiles.active=h2 and then tried to deploy the war to prod server, does it try to connect to h2 based on the spring profile or to prod db based on jdni-name? What is the best practice to accommodate all scenarios with enough flexibility?
Also is a explicit configuration class for DataSource required such as Configure Mutiple DataSource in Spring Boot with JNDI? My understanding is application.properties and spring profile should be enough to handle it, right?
Definitely use Spring profiles.
You don't want to use Maven profiles as it creates different artifacts. Ask your QA/Release engineers how they feel about having different artifacts for different environments :). They wouldn't be happy.
H2 is what you want to use in CI server integration testing as well. Such integration testing is fast and easy.
Instead of changing profile in application.properties, consider defining profile via command line parameter. So that configuration file changes are not required to run your application in different profiles.

spring boot cloud config

I want to use spring cloud config to externalise application properties. I have configured config-server and client, but i don't want to use git(enterprise) as source, this is due to the fact that git may be down for the maintenance. Therefore, i thought about releasing application properties to nexus as application.properties.tar.gz and do the following:
1.) When config-server starts, download the release version from nexus and then unpack the tar.gz to a file system on the server where config-server is running.
2.) The config server which will pick the unpacked properties files.
Please note that the nexus url, application.properties.tar.gz version and location are all passed as VM options to config server.
Is this a sensible option? if this not best option, please could you suggest any other options?
Thanks
kankalam
Unless the Git server is down for maintenance so frequently, I wouldn't go with that option, it seems to be an overkill. Also the Nexus server might go down, so there's no advantage on doing that.
The config server does not read the configuration from the repo once and again, the repository is cloned when configuration is requested. From the docs:
The default strategy for locating property sources is to clone a git
repository (at spring.cloud.config.server.git.uri) and use it to
initialize a mini SpringApplication. The mini-application’s
Environment is used to enumerate property sources and publish them via
a JSON endpoint.
With that in mind, you need to check that the git server you use is available before you start the application or before you refresh its context. If you think it might be a problem, you still have two options:
Set up a dedicated Git server for your application (Check out Gogs as a lightweight option).
Go the "native" way and load the files from the file system. This way you don't have a version control of the configuration files, but you could do it separately into your project.

Spring Cloud Config Server Shared Properties Across Applications

I currently have a number of deployable applications that work in a distributed fashion to solve a business problem. We are currently using a number of property configuration files to provide changing configuration per environment based off a system environment variable. All these deployable application share common configuration for database and messaging. This is currently achieved by picking up property files from the class path and having both deployed apps share a common jar for each connection (db, jms) containing property files.
I am looking to start using Spring Config Server to externalize this configuration if possible. I have a question about how to share this common config.
Currently it looks something like this:-
Web1
- database
- jms
Messaging1
- database
- jms
In this situation both deployed apps share the same connections and these connections change per environment (lab, prf, prd, etc). How can I achieve the same with the Spring Configuration Server where I have app config for each deployable app?
Application.yml
Web1.yml
Web1-dev.yml
Messaging1.yml
Messaging1-dev.yml
If a connection property changed for an environment I would need to make the change to each deployable app configuration rather than making it just once.
Is there currently anyway to achieve this? Am I just missing a simple point?
I found working solution here https://cloud.spring.io/spring-cloud-config/single/spring-cloud-config.html, paragraph "2.1.5 Sharing Configuration With All Applications". It says:
With file-based (i.e. git, svn and native) repositories, resources
with file names in application* are shared between all client
applications (so application.properties, application.yml,
application-*.properties etc.). You can use resources with these file
names to configure global defaults and have them overridden by
application-specific files as necessary.
You should create application.properties or application.yml at the top level of configuration repository (if it is git or svn based). Don't forget to commit the changes.
This is how I have configured for my setup.
1 All Common properties across all services and environments will be in root->application.properties files
2 All Common properties across all environments specific to service will be root->service-X.properties files
3: Similarly, to have common properties across specific environment use env->application.properties file
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri:[git repo]
search-paths: /,/{profile}/
Finally found a solution. It's buried in the issues at github ...
https://github.com/spring-cloud/spring-cloud-config/issues/32
It worked liked described. I only noticed, that you need to put the files in a /config folder to make it work. If you put it in the root the file ist used by the configserver itself and is not included in the config requests.
application.properties/application.yml will be shared across all applications.
application-DEV.properties/application-DEV.yml will be shared across all DEV environment applications. You can replace DEV with any spring profile.
{applicationName}.properties/{applicationName}.yml will be shared across the give application.

Resources