I write a spring boot application (which is configured throw a Spring Cloud Config Server).
This application has a small UI for information only. However, it should be possible to start this application multiple times so you can not set a fix port for this application (in the Config Server).
For this it is possible to set a random port (server.port=0) and you can start as many instances of this application as you want. A little issue is that if the user wants to access the UI he has to find out a “random port”.
So my question is: Is it somehow possible to define a preferred Port (using Config Server) and only if this port is not available take a random port?
You can just configure it via command line system property java -Dserver.port=$PORT -jar app.jar. Example is in this section of Spring Boot docs.
I bet also setting up environment variable SERVER_PORT may work.
I think also Spring Boot parameter should work: java -jar app.jar --server.port=$PORT
Related
My project has a bootstrap.yaml and a config server that deliver its appropriate profile. Everything is working great but I have to accomplish some others task like CI and CD.
My problem comes because the Jenkins machine is not allowed to resolved external domains and try to compile and run the Spring boot app without an a profile.
So my question is:
Is there a way to load application.properties when the config server
is not resolved?
Yes, there is a natural way based on the order in which Spring Boot loads PropertySources.
You can include properties you want to be applied in application.properties.
In case config server is not available - properties from application.properties will be used. If config server is available - you'll receive properties from there.
You might also want to disable config server connectivity for your CI using environment variable SPRING_CLOUD_CONFIG_ENABLED=false.
I am working on Java Springboot with MongoDB using Kubernetes. Currently I just hard coded the URI in application properties and I would like to know
how can I access to the MongoDB credentials on Kubernetes with Java?
The recommended way of passing credentials to Kubernetes pods is to use secrets and to expose them to the application either as environment variables, or as a volume. The link above describes in detail how each approach works.
If I properly understood the question, it is specifically about Java Spring Boot applications running on Kubernetes.
Few options come to my mind...some not that secure or exclusive to running on Kubernetes but still mentioned here:
Environment variables with values in the deployment/pod configuration. Everyone with access to the configuration will be able to see them.
Use ${<env-var>} / ${<end-var>:<default-value>} to access the environment variables in Spring Boot's application.properties/.yaml file. For example, if DB_USERNAME and DB_PASSWORD are two such environment variables:
spring.data.mongodb.username = ${DB_USERNAME}
spring.data.mongodb.password = ${DB_PASSWORD}
...or
spring.data.mongodb.uri = mongodb://${DB_USERNAME}:${DB_PASSWORD}#<host>:<port>/<dbname>
This will work regardless whether the application uses spring.data.mongodb.* properties or properties with custom names injected in a #Configuration class with #Value.
Based on how the Java application is started in the container, startup arguments can be defined in the deployment/pod configuration, similarly to the bullet point above.
Environment variables with values populated from secret(s). Access the environment variables from SpringBoot as above.
Secrets as files - the secrets will "appear" in a file dynamically added to the container at some location/directory; it would require you to define your own #Configuration class that loads the user name and password from the file using #PropertySource.
The whole application.properties could be put in a ConfigMap. Notice that the properties will be in clear text. Then populate a Volume with the ConfigMap so that application.properties will be added to the container at some location/directory. Point Spring Boot to that location using spring.config.location as env. var, system property, or program argument.
Spring Cloud Vault
Some other external vault-type of secure storage - an init container can fetch the db credentials and make them available to the Java application in a file on a shared volume in the same pod.
Spring Cloud Config...even though it is unlikely you'd want to put db credentials in its default implementation of the server storage backend - git.
Generally, we downloaded the TOMCAT to the computer and configure the context where it stores the project path then run the TOMCAT. So we can access our web project.
Is there a possibility that we can start the TOMCAT by just using java code.
like
Tomcat tomcat = new Tomcat(configuration);
tomcat.run();
Can not understand what are you trying to achieve? But, Spring Boot comes with embedded tomcat and your application is deployed automatically on tomcat (with default configurations). If you want to change configurations for the tomcat you can specify those configurations in application.properties.
Like, e-g if you want to change port of your server you can specify following property in application.properties.
server.port = 8085
There are other server related properties for which you can refer to https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html.
You can also implement WebServerFactoryCustomizer
in order to configure tomcat with java. For this purpose you can refer to https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-web-servers.html
I have simple Spring boot application which I need to deploy on development and prod different namespaces on a Kubernetes cluster using Helm.
I was thinking about keeping multiple application.properties (application-dev.properties, application-prod.properties) files for each environment and then create configmaps from them through values.yaml files which also will be different for each environment and specified when I execute Helm upgrade.
Now the question is how do I consume values from config.maps as I understand I can either mount the properties file inside container for example /deployment/application.properties
Or expose each property as an environment variable inside container.
But how do I consume them from Java application?
Also at the moment when I create container image it has current application .properties inside /resources/ files embedded and this is what application is using from default so I need to overwrite this behaviour when application is running inside container as opposite to then when its just build and run manually on developer desktop.
Springboot can automatically infer variables from environment variables. In your application.properties or application.yaml, just use ${MY_ENVIRONMENT_VARIABLE:my-defaultvalue}.
Use helm to populate your configmap.
Use configmap as environment variables into your deployment manifest.
This way you do not need to have multiple application.properties for dev, int ,prod inside your image. Keeping it intact across deployment.
And then in your helm chart, you can have multiple values.yaml example values-dev.yaml or values-int.yaml. you can also dynamically set helm values from command line, overriding the yaml file.
I have a demo app in github https://github.com/balchua/demo, which uses this pattern.
You could certainly use environment variables as Bal Chua suggests. If you do that you can override particular values at install time using --set or if you've a lot of config you can use the '-- values' flag and pass in a custom values.yaml file.
Another approach is to load a whole file using .Files.Glob (example in github) and load the file as part of the chart. You can then mount the file to /config to consume it in your spring boot application. Then your config file would be in the same form as a Spring boot config file, rather than a helm values.yaml. Though in many cases there needn't be much difference.
There's a discussion of how you could do similar for secrets (presumably you'll want to put your passwords in secrets) and use it for CI/CD in https://dzone.com/articles/hunting-treasure-with-kubernetes-configmaps-and-se (which is the article accompanying the github example). Basically you would use .Files.Glob with .AsSecrets instead of .AsConfig so as to encode the content. Many helm charts have the option to generate a random password if not specified but I'd guess you probably don't need that.
I'd recommend mounting the files (application.properties or application.yml) inside the ConfigMap onto somewhere on the file system that Spring Boot can automatically detect - then your app stays nice and simple
I am planning to use JGroups in a web application.
JGroups by default uses IPv6 for multicasting of messages. JGroups can only be configured to use IPv4 by setting a property like the following (see docs)
-Djava.net.preferIPv4Stack=true
This does not work if set in code. What are my options when running a war file in an application server for setting this property, specifically tomcat and glassfish?
It seems to me the following route might work. First, add a ServletContextListener to your web app and register it in web.xml before JGroups is loaded.
Now, inside the contextInitialized method, use System.setProperty("java.net.preferIPv4Stack", "true").
Disclaimer: not tested.
Unless you have a specific reason to put this in code, it can easily be configured for Tomcat by setting the environment variable CATALINA_OPTS (to -Djava.net.preferIPv4Stack=true). I think the proper place to do this is to create ${CATALINA_HOME}/bin/setenv.sh and place the setting in there.