Spring Boot #EnableEurekaClient conditionally - spring-boot

I'm using several profiles for my app, that I can select via the application.yml prop:
spring.profiles.active: dev #can be integration, uat, prod
My applications all start by:
#SpringBootApplication
#EnableEurekaClient
public class MyApp {
}
Now, I'd like to enable the eureka client only for selected profiles. I don't want, for example, to enable that in dev profile as in dev you don't mind about the service register right?
Is it possible? I tried to move eureka related properties in the single profile files but they are found anyway...

you can extract your config and only activate it on certain profiles
#Configuration
#Profile(value= {"uat","prod"})
#EnableEurekaClient
public class EurekaClientConfiguration {
//your configuration
}
on the other hand you could de-activate config for a certain profile by using a ! (=not) #Profile("!dev")

Related

Why spring client cannot obtain spring config server properties?

I've got a #SpringBootApplication, running with the production profile, and a spring config server,
{"name":"config-client","profiles":["production"],"label":null,"version":"97611975e6ddb87c7213e18ddbe203ab6ae5485d","state":null,"propertySources":[{"name":"http://git/scm/abm/abm-settings.git/application-production.yml","source":{"my.pretty.property.id":21}}]}
I cannot load property my.pretty.property.id from server (they are always null), I am using
#Getter
#Setter
#Component
#ConfigurationProperties(prefix = "my.pretty.property")
public class MyProperties {
private String id;
}
and my bootstrap.yml is
spring.cloud:
config:
uri: http://${SERVICE_HOST}/${PROJECT_KEY}-config-server
enabled: false
failFast: true
build.gradle contains this:
"org.springframework.cloud:spring-cloud-starter-consul-all",
"org.springframework.cloud:spring-cloud-consul-core",
"org.springframework.cloud:spring-cloud-starter-hystrix",
"org.springframework.cloud:spring-cloud-starter-hystrix-dashboard",
"org.springframework.cloud:spring-cloud-starter-zipkin",
"org.springframework.cloud:spring-cloud-config-client"
My client application is normally built and deployed, what am I missing?
From Spring Cloud Config:
The HTTP service has resources in the form:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
As you mentioned your application is running under production profile - hence Spring will try to find file: <cloud-config-server-url>/application-production.yml and load it, besides application.properties. But your properties are located in application-integration.yml and you don't use integration profile.
So the solution is to use an integration profile or to create an application-production.yml on your config. server.
The following config is right, but spring.cloud.config.enabled should be true, I didn't overrride it in my production environment

Unable to generate different spring-cloud-gateway routes based on active Spring profile

I'm trying to define different routes in Spring Cloud Gateway using Spring profiles. Everything I've read about how Spring manages profiles using yaml sems to indicate it should work, but for the life of me it just ... doesn't seem to. (My other Spring apps use properties, so I'm unused to the yaml config -- it's possible I'm missing something.)
Effectively what I'm trying to do is to have a "prod" profile which contains the URIs for my production servers, and a "dev" profile which contains the localhost equivalents.
I have two profiles, dev and prod. My application.yml file looks like this
spring:
profiles:
default: prod
management:
endpoint:
health:
enabled: true
endpoints:
web:
exposure:
include: hystrix.stream, gateway
---
spring
profiles: prod
cloud:
gateway:
routes:
- id: test_route
uri: http://foo.mycompany.com
predicates:
- Path=/status
- Method=GET
---
spring
profiles: dev
cloud:
gateway:
routes:
- id: test_route
uri: http://localhost:8080
predicates:
- Path=/status
- Method=GET
My understanding is as follows:
the spring.profiles.default property tells Spring that, if no profile is specified, to use the prod profile
Spring will treat the --- as a "file separator" and re-evaluate each set of properties and overwrite previous values if the spring.profiles parameter evaluates true
Given this understanding, I would expect Spring to parse the "default" properties first, learning that the default activated profile should be prod. Then it will parse the prod properties. Since "prod" is an active profile (the only active profile, being the default), it should parse and apply the prod routes. Then it would parse the dev routes, but recognize that dev is not an active profile, and not overwrite those values. This is my understanding from reading the documentation on how to change config based on the environment.
However, when I load this, and I hit the actuator endpoint -- /actuator/gateway/routes -- I get back [] where I would expect to see the prod routes. I do see in my logs that the prod profile is activated, but it seems like not having the properties in the "default" section at top causes them to not be applied when the parser reads them out of the profile section.
The other thing I tried was putting the "dev" properties as the defaults, and then attempting to use the "prod" profile properties to overwrite the URIs. A similar issue happened there -- I hit the actuator endpoint and got back routes, but they were just the dev ones from the default.
How can I leverage Spring profiles to configure different Spring Cloud Config routes in my application.yml ?
Versions:
spring-cloud-gateway 2.0.1.BUILD-SNAPSHOT (to get a workaround for this bug, probably not relevant)
spring-cloud-starter-gateway
spring-boot 2.0.3.RELEASE
spring-boot-starter-webflux
spring-boot-starter-actuator
(I can't use Spring Cloud Config for political reasons. My company's chief architect has a severe case of Not Invented Here Syndrome.)
You cannot use spring.profiles.default in the property file. It will be too late for setting such value.
So you can set it using program argument (or System property). E.g.
java -jar --spring.profiles.default=dev your-app.jar
Or you can do it in the code by hardcoding the default profile:
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(DemoApplication.class);
ConfigurableEnvironment environment = new StandardEnvironment();
environment.setDefaultProfiles("dev");
application.setEnvironment(environment);
application.run(args);
}
}
Some related information you can find here by reading all comments:
https://github.com/spring-projects/spring-boot/issues/1219

How to register spring boot microservices on spring cloud Netflix eureka?

We were planning to use spring cloud Netflix oss components. So I was doing a small sample project.
I developed 2 spring microservices and those services runs well on
http://localhost:9000/microsvc-one http://localhost:9001/microsvc-two
And also wrote a sample spring cloud etflix eureka maven project which runs well on
http://localhost:8761
I used annotations #EurekaDiscoveryClient and #SpringBootApplication on both the spring boot microservices main class
I used annotation #EnableEurekaServer and #SpringBootApplication
Now I am facing a problem in registering those services in eureka server. I referred some samples. I am not understanding those.
I did some changes in application.yml files of microsvc-one and microsvc-two and also application.yml file of eureka server.
But still it shows empty.
What all changes are required or missing or correct configuration to be done so that my services are being registered on eureka.
I also have other question like do i need to create a separate project which has #EnableConfigServer and #SpringBootApplication Annotations other than the above 2 microservices and eureka server project module to register the services on eureka.
I see those in most of the examples.
If yes..how do we link between all these?
If you are using springBoot application you will need the annotaion #SpringBootApplication thats why that annotation is there on the project you are seeing. #EnableConfigServer is when you are using the spring-cloud config server it is used to externalize the configuration properties but since you have the application.yml inside the project so you donot need that either.
I am thinking you have a spring boot application for both Microservices and the Eureka server. You need to annotate the eureka main class with
#SpringBootApplication
#EnableEurekaServer
#EnableDiscoveryClient
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
Additionally you need annotate you microservice's main class with..
#SpringBootApplication
#EnableDiscoveryClient
public class MicroApplication {
public static void main(String[] args) {
SpringApplication.run(MicroApplication.class, args);
}
}
Since you donot have you application.yml file in the question here is what you need.
You need the below configuration in application.yml of the microservices.
eureka:
client:
serviceUrl:
defaultZone: ${eurekaurl:http://localhost:8761/eureka/}
In the Eureka Server application.yml file I have this in mine. you might need to tweak it based on what you want.
info:
component: Registry Server
server:
port: ${port:8761}
eureka:
client:
registerWithEureka: false
fetchRegistry: false
server:
enable-self-preservation: false
waitTimeInMsWhenSyncEmpty: 0
instance:
hostname: localhost
lease-expiration-duration-in-seconds: 15
lease-renewal-interval-in-seconds: 5
Suppose you have a microservice named "LoginServer" now, let's see how to register this service with discovery server (Eureka Server) at startup.
Here Spring Boot startup class of LoginServer.java:
#EnableAutoConfiguration
#EnableDiscoveryClient
public class LoginServer {
public static void main(String[] args) {
// Will configure using login-server.yml
System.setProperty("spring.config.name", "login-server");
SpringApplication.run(LoginServer.class, args);
}
}
The #EnableDiscoveryClient - enables service registration and discovery. In this case, this process registers itself with the discovery-server service using its application name, that is configured in YML configuration file.
let's see the complete setup:
First create a login-server.yml (any name but extension should be .yml) file into src/main/resources package folder. And write those configurations and save.
# Spring properties
spring:
application:
name: login-server # This name used as ID so ("spring.config.name",
#"login-server"); must be same.
# Discovery Server Access
eureka:
client:
serviceUrl:
defaultZone: http://localhost:1111/eureka/
# HTTP Server
server:
port: 2222 # HTTP (Tomcat) port
Run the LoginServer and let it finish initializing. Open the dashboard by putting this URL http://localhost:1111 in your favorite browser and refresh. After few seconds later you should see the LOGIN-SERVER. Generally registration takes up to 30 seconds (by default) so wait or restart.
And this is the microservice complete registration process.

Configure Spring Boot application to use MongoDB connection uri provided in environment variable

I would like to configure the connection-uri to my MongoDB through an environment variable. This way, I can set different values on localhost or if the Spring Boot application is running in a cloud.
I have included mongodb in my build.gradle file:
dependencies {
compile 'org.springframework.cloud:spring-cloud-spring-service-connector:1.2.2.RELEASE'
compile("org.springframework.boot:spring-boot-starter-data-mongodb")
...
}
To work locally, I have currently set the spring.data.mongodb.uri=mongodb://... in applications.properties but I would rather like to have that value read from an environment variable. How can I achieve this?
I have read articles about Spring Boot and Cloud suggesting extending the AbstractCloudConfig somehow like this:
public class CloudConfig extends AbstractCloudConfig {
#Bean
public MongoDbFactory documentMongoDbFactory() {
return connectionFactory().mongoDbFactory();
}
}
But I assume this wouldn't work with environment variables and working locally.
You should use profiles to do that.
Read about profiles
Read how to use Profiles
How to Set Profiles

Spring Boot: Change Port for Web Application

I am currently trying to create a web application with Spring Boot. I need to host my application to localhost:8081. How do I change the port?
Actually you want to change server.port and you can change it in many different ways as described http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config
Examples:
in your application.properties (in or outside the jar)
command line
java -Dserver.port=$PORT -jar target/demo-0.0.1-SNAPSHOT.jar
and much more
By default spring boot uses port 8080, BUT you can change the port just by adding the following code line in your main() like this:
System.getProperties().put( "server.port", *YOUR_PORT_NUMBER_GOES_HERE* );
e.g
#SpringBootApplication
public class MyClass {
public static void main(String[] args) {
System.getProperties().put( "server.port", 8181 ); //8181 port is set here
SpringApplication.run(MyClass.class, args);
}
OR
You can configure it in your application.properties file like so:
server.port=8181
If you DON'T have an application.properties file in your spring-boot application, you can go ahead and create one. Right-click on the src/java/resources folder and go to New-> Other-> General and choose 'File' then name as: application.properties
Any other configurations you might need are listed here https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html. These properties are also configured in the application.properties file.
Actually you want to change server.port and you can change it in many different ways as described
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-external-config
Put server.port=9000 in your application.properties
In your application.properties file, just add one line
server.port = 8080
And for more configurations you can refer Spring Boot documentation on port
If you are using the embedded tomcat server, you can configure the EmbeddedServletContainerFactory bean yourself in your Application class annotated with #SpringBootApplication.
This will give you options to customize your tomcat server, example configuration
#Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.setPort(9000);
factory.setSessionTimeout(10, TimeUnit.MINUTES);
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
return factory;
}
You could also do the same for Jetty, using the JettyEmbeddedServletContainerFactory bean, or for Undertow using the UndertowEmbeddedServletContainerFactory .
Official documentation found here : http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/
If you're using STS, you can do it following below steps:
Go to Boot Dashboard view, you'll see your Boot app, say myApp1
Right click and click on Open Config. This should open Run Time
Configuration section.
Go to Argument tab and add parameter server.port=, like in the example below, a custom port 9091 is added.
Start the app and if everything is good, you'll see the desired port
on Boot dashboard.
go to your application.properties file and type server.port=8081
see this image

Resources