After the registration at the Spring Boot Admin (SBA) Server, some actuators of the clients get adressed with http://springapplication.com/actuator instead of https://springapplication.com/actuator.
Why does it change the endpoints to HTTP and doesn´t stay at HTTPS? Is it customizable?
Here are some Logs and the Java/YML-Files.
Logs:
2018-07-02 06:13:27.683 INFO 3194 --- [-client-epoll-7] d.c.b.a.server.services.StatusUpdater : Couldn't retrieve status for Instance(id=0d47f12b0a94, version=57, registration=Registration(name=springbootapplication-Name, managementUrl=https://springbootapplication.com/actuator, healthUrl=https://springbootapplication.com/actuator/health, serviceUrl=https://springbootapplication.com, source=http-api), registered=true, statusInfo=StatusInfo(status=UP, details={}), statusTimestamp=2018-07-02T05:06:08.423Z, info=Info(values={}), endpoints=Endpoints(endpoints={httptrace=Endpoint(id=httptrace, url=http://springbootapplication.com/actuator/httptrace), flyway=Endpoint(id=flyway, url=http://springbootapplication.com/actuator/flyway), loggers=Endpoint(id=loggers, url=http://springbootapplication.com/actuator/loggers), health=Endpoint(id=health, url=https://springbootapplication.com/actuator/health), env=Endpoint(id=env, url=http://springbootapplication.com/actuator/env), heapdump=Endpoint(id=heapdump, url=http://springbootapplication.com/actuator/heapdump), scheduledtasks=Endpoint(id=scheduledtasks, url=http://springbootapplication.com/actuator/scheduledtasks), mappings=Endpoint(id=mappings, url=http://springbootapplication.com/actuator/mappings), beans=Endpoint(id=beans, url=http://springbootapplication.com/actuator/beans), configprops=Endpoint(id=configprops, url=http://springbootapplication.com/actuator/configprops), threaddump=Endpoint(id=threaddump, url=http://springbootapplication.com/actuator/threaddump), metrics=Endpoint(id=metrics, url=http://springbootapplication.com/actuator/metrics), conditions=Endpoint(id=conditions, url=http://springbootapplication.com/actuator/conditions), auditevents=Endpoint(id=auditevents, url=http://springbootapplication.com/actuator/auditevents), info=Endpoint(id=info, url=http://springbootapplication.com/actuator/info), jolokia=Endpoint(id=jolokia, url=http://springbootapplication.com/actuator/jolokia)}), buildVersion=null)
Application.yml (Server):
server:
port: 5100
spring:
security:
user:
name: admin
password: password
SecuritySecureConfig.java (Server):
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
#Configuration
public class SecuritySecureConfig extends WebSecurityConfigurerAdapter {
private final String adminContextPath;
public SecuritySecureConfig(AdminServerProperties adminServerProperties) {
this.adminContextPath = adminServerProperties.getContextPath();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
http.authorizeRequests().antMatchers(adminContextPath + "/assets/**").permitAll()
.antMatchers(adminContextPath + "/login").permitAll().anyRequest().authenticated().and().formLogin()
.loginPage(adminContextPath + "/login").successHandler(successHandler).and().logout()
.logoutUrl(adminContextPath + "/logout").and().httpBasic().and().csrf().disable();
}
}
SpringBootAdminApplication.java (Server):
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.PropertySource;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
#EnableAutoConfiguration
#EnableWebSecurity
#EnableAdminServer
#SpringBootApplication(scanBasePackages = "administration")
#PropertySource(value = "META-INF/build-info.properties", ignoreResourceNotFound = true)
public class SpringBootAdminApplication {
private static final Logger log = LoggerFactory.getLogger(SpringBootAdminApplication.class);
public static void main(final String[] args) {
SpringApplication.run(SpringBootAdminApplication.class, args);
}
}
Application.yml (Client):
spring:
application:
name: springapplication
boot:
admin:
client:
username: ${application.security.usernameAdmin}
password: ${application.security.passwordAdmin}
url: "https://springBootAdminServerURL.com"
instance:
service-base-url: https://http://springapplication.com/
metadata:
user.name: ${application.security.usernameAdmin}
user.password: ${application.security.passwordAdmin}
management:
endpoints:
web:
exposure:
include: "*"
application:
security:
usernameAdmin: admin
passwordAdmin: password
I had the same problem. Look at your applications /actuator endpoint. Is it reporting urls as http? It did for me, even if health used https. What solved it for me was adding server.use-forward-headers=true which adds all X-Forwarded-*, including the X-Forwared-Proto that identifies scheme (http/https).
Remember if your app is behind a reverse proxy like NGINX, you'd also need to configure this. Example for NGINX
location / {
proxy_set_header X-Forwarded-Proto $scheme;
...
}
Need correction in the config file for below property which signifies as
Base url for computing the service-url to register with. The path is
inferred at runtime, and appended to the base url.
spring.boot.admin.client.instance.service-base-url
instance:
service-base-url: https://springapplication.com/
In my experience this is usually due to two issues.
Incorrect port configs
Untrusted SSL certs
To fix the first issue, you need to make sure your client application correctly informs Eureka to use the secure port:
eureka:
instance:
nonSecurePortEnable: false
securePortEnabled: true
To fix the second, you need to ensure the SSL cert is trusted by the JVM that is running Spring Boot Admin. Just install your cert into the JRE's cacert file using keytool. I would recommend enabling SSL debug logging while trying to get this to work.
-Djavax.net.debug=SSL
These two steps solved this issue for me.
Related
I'm trying to use Spring cloud bus with Kafka in my microservices application, and indeed I could use it, but only data which is controlled by Spring cloud config server got refreshed!
I'm using jdbc back-end with my config server, and in order to simulate my need, I'm changing some value in properties file in one of my services, beside the properties table, and call the /monintor end point again (mentioned here section 4.3 https://www.baeldung.com/spring-cloud-bus); as a result, only data coming from properties table is changed.
This is the yml file for my Config server
spring:
cloud:
config:
server:
jdbc:
sql: SELECT KEY,VALUE from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=?
order: 1
stream:
kafka:
binder:
brokers: localhost:9092
datasource:
url: jdbc:mysql://localhost:3306/sweprofile?zeroDateTimeBehavior=convertToNull
username: 123
password: 123ertbnm
hikari:
maximum-pool-size: 10
connection-timeout: 5000
profiles:
active:
- jdbc
application:
name: configServer
These are yml files for One of my Miscroservices and its propeties file respectively
spring:
datasource:
username: 123
password: 123ertbnm
url: jdbc:mysql://localhost:3306/sweprofile?zeroDateTimeBehavior=convertToNull
jpa:
properties:
hibernate:
format_sql: true
ddl-auto: none
application:
name: auth-service
cloud:
config:
discovery:
enabled: true
service-id: configServer
bus:
refresh:
enabled: true
profiles:
active: jdbc
management:
endpoints:
web:
exposure:
include: ["health","info","refresh", "bus-refresh"]
# This line is dummy data for testing purpose
ali.man = " Ola 12333"
This is snapshot from rest controller
#RestController
#RequestMapping("/user")
#RefreshScope
public class AuthController {
private UserAuthService userAuthService;
#Value("${name}")
private String name; // changed normally
// Calling the key value mentioned in properties file after changing
#Value("${ali.man}")
private String k; // -> not changed
public AuthController(UserAuthService userAuthService) {
this.userAuthService = userAuthService;
}
#GetMapping("authTest")
public String getAuth() {
return name + k;
}
}
What did I miss? Why value from Properties file is not changed? hopefully I can use Spring cloud bus with Kafka to refresh these external data.
After some hours of investigation, I found that there is some recommended way. Cloud bus can send Refresh Event and Spring boot has RefreshEvent Listener to that event; this what I build my solution on.
So when event is sent by the bus; all instances will do the same logic ( Refreshing data ) on the loaded in memory configurations.
I used this snippet to apply this
#Configuration
public class ReloadLookupEvent implements ApplicationListener<RefreshScopeRefreshedEvent> {
#Autowired
private CacheService cacheService;
#Override
public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
cacheService.refreshLookUp();
}
}
I could refresh all other configurations on demand, maybe it is a workaround, but acceptable.
I need to import Spring properties (in Spring Boot) as spring.datasource, server.port... from a file that is located in the file system (out of the java application).
This is for a Spring Boot application that needs to connect to a database.
spring:
datasource:
url: jdbc:oracle:thin:#X.X.X.X:XXXX:XXXX
username: XX
password: XX
driver-class-name: oracle.jdbc.driver.OracleDriver
hikari:
connection-timeout: 60000
maximum-pool-size: 5
application:
name: XX
server:
port: 9000
contextPath: /
servlet:
session:
cookie:
http-only: true
secure: true
By the moment I am not able to import properties from file using #PropertySource(value = "C:/test.properties") in class.
There are multiple ways to achieve this. My preferred one is to annotate your applications main class with #PropertySource and configure it to read your property file.
Example:
#SpringBootApplication
#PropertySource({
"file:C:\test.properties"
})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I have springBatch App where I was using multiple datasources which I configured as below which is pretty much straight forward. It was working fine.
How to use 2 or more databases with spring?
Now I had to integrate it to Jhipster project. I did similar kind of configuration in application.yml. I removed auto generated Datasource from application.yml and added configurations similar to above post and injected the primary Datasource in DataBaseConfiguration.java which is Jhipster generated class. With this configuration I am unable to do CRUD operation on Database entities form JHipster UI. I am not seeing any errors in logs.
I am not sure what's the right/simple way of configuring multiple datasources in Jhipster project. A sample example utilizing multiple databases would give a good start for me. I didn't find much resources on this.
Below are code sample's for changes I performed to have multiple datasources in JHipster
# ===================================================================
# Spring Boot configuration for the "dev" profile.
#
# This configuration overrides the application.yml file.
#
# More information on profiles: http://www.jhipster.tech/profiles/
# More information on configuration properties: http://www.jhipster.tech/common-application-properties/
# ===================================================================
# ===================================================================
# Standard Spring Boot properties.
# Full reference is available at:
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
# ===================================================================
spring:
profiles:
active: dev
include: swagger
devtools:
restart:
enabled: true
livereload:
enabled: false # we use gulp + BrowserSync for livereload
jackson:
serialization.indent_output: true
jpa:
database-platform: org.hibernate.dialect.Oracle12cDialect
database: ORACLE
show-sql: true
properties:
hibernate.id.new_generator_mappings: true
hibernate.cache.use_second_level_cache: false
hibernate.cache.use_query_cache: false
hibernate.generate_statistics: true
hibernate.default_schema: ********x
mail:
host: localhost
port: 25
username:
password:
messages:
cache-seconds: 1
thymeleaf:
cache: false
batch:
job:
enabled: false
liquibase:
contexts: dev
# ===================================================================
# To enable SSL, generate a certificate using:
# keytool -genkey -alias ********x-storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
#
# You can also use Let's Encrypt:
# https://maximilian-boehm.com/hp2121/Create-a-Java-Keystore-JKS-from-Let-s-Encrypt-Certificates.htm
#
# Then, modify the server.ssl properties so your "server" configuration looks like:
#
# server:
# port: 8443
# ssl:
# key-store: keystore.p12
# key-store-password: <your-password>
# keyStoreType: PKCS12
# keyAlias: ********x
# ===================================================================
server:
port: 8080
# ===================================================================
# JHipster specific properties
#
# Full reference is available at: http://www.jhipster.tech/common-application-properties/
# ===================================================================
jhipster:
http:
version: V_1_1 # To use HTTP/2 you will need SSL support (see above the "server.ssl" configuration)
# CORS is only enabled by default with the "dev" profile, so BrowserSync can access the API
cors:
allowed-origins: "*"
allowed-methods: "*"
allowed-headers: "*"
exposed-headers: "Authorization"
allow-credentials: true
max-age: 1800
security:
authentication:
jwt:
secret: my-secret-token-to-change-in-production
# Token is valid 24 hours
token-validity-in-seconds: 86400
token-validity-in-seconds-for-remember-me: 2592000
mail: # specific JHipster mail property, for standard properties see MailProperties
from: ********x#localhost
base-url: http://127.0.0.1:8080
metrics: # DropWizard Metrics configuration, used by MetricsConfiguration
jmx.enabled: true
graphite: # Use the "graphite" Maven profile to have the Graphite dependencies
enabled: false
host: localhost
port: 2003
prefix: ********x
prometheus: # Use the "prometheus" Maven profile to have the Prometheus dependencies
enabled: false
endpoint: /prometheusMetrics
logs: # Reports Dropwizard metrics in the logs
enabled: false
report-frequency: 60 # in seconds
logging:
logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration
enabled: false
host: localhost
port: 5000
queue-size: 512
# ===================================================================
# Application specific properties
# Add your own application properties here, see the ApplicationProperties class
# to have type-safe configuration, like in the JHipsterProperties above
#
# More documentation is available at:
# http://www.jhipster.tech/common-application-properties/
# ===================================================================
datasource.********x.type: com.zaxxer.hikari.HikariDataSource
datasource.********x.url: "jdbc:oracle:thin:#********x"
datasource.********x.username: ********x
datasource.********x.password: ********x
datasource.********xy.type: com.zaxxer.hikari.HikariDataSource
datasource.********xy.url: "jdbc:oracle:thin:#yyyyyy"
datasource.********xy.username:********x
datasource.********xy.password: "********x"
package com.********x
import io.github.jhipster.config.JHipsterConstants;
import io.github.jhipster.config.liquibase.AsyncSpringLiquibase;
import liquibase.integration.spring.SpringLiquibase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
#Configuration
#EnableJpaRepositories("com.********x")
#EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
#EnableTransactionManagement
public class DatabaseConfiguration {
private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);
private final Environment env;
public DatabaseConfiguration(Environment env) {
this.env = env;
}
#Autowired
#Qualifier("********x")
private DataSource dataSource;
#Bean
public SpringLiquibase liquibase(#Qualifier("taskExecutor") TaskExecutor taskExecutor
, LiquibaseProperties liquibaseProperties) {
// Use liquibase.integration.spring.SpringLiquibase if you don't want Liquibase to start asynchronously
SpringLiquibase liquibase = new AsyncSpringLiquibase(taskExecutor, env);
liquibase.setDataSource(dataSource);
liquibase.setChangeLog("classpath:config/liquibase/master.xml");
liquibase.setContexts(liquibaseProperties.getContexts());
liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
liquibase.setDropFirst(liquibaseProperties.isDropFirst());
if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_NO_LIQUIBASE)) {
liquibase.setShouldRun(false);
} else {
liquibase.setShouldRun(liquibaseProperties.isEnabled());
log.debug("Configuring Liquibase");
}
return liquibase;
}
}
So I injected primary Datasource in DatabaseConfiguration.java and using other datasource where required. Both these datasources are created similar to the above post like how spring suggests.
Here is how I make two datasource work in JHipster project :
The default datasource properties generate by JHipster:
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:h2:file:./target/h2db/db/mockpartenaire;DB_CLOSE_DELAY=-1
username: mockpartenaire
password:
Configs for the JHispter default datasource :
#Configuration
#EnableTransactionManagement
public class PrimaryDbConfig {
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSourceProperties defaultDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#Primary
#ConfigurationProperties("spring.datasource")
public DataSource defaultDataSource() {
return defaultDataSourceProperties().initializeDataSourceBuilder().build();
}
#Bean(name = "entityManagerFactory")
#Primary
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(defaultDataSource())
.packages(Input.class)
.persistenceUnit("default")
.build();
}
#Bean(name = "transactionManager")
#Primary
public JpaTransactionManager db2TransactionManager(#Qualifier("entityManagerFactory") final EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
The second datasource properties:
partner:
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:postgresql://localhost:5432/partner
username: partner
password: partner
driver-class-name: org.postgresql.Driver
The second datasource configs :
#Configuration
#EnableTransactionManagement
#EntityScan(basePackages = "com.my.test.custom.domain")
#EnableJpaRepositories(transactionManagerRef = "partnerTransactionManager", entityManagerFactoryRef = "partnerEntityManagerFactory", basePackages = "com.my.test.custom.repository")
public class PartnerDbConfig {
#Bean
#ConfigurationProperties("partner.datasource")
public DataSourceProperties partnerDataSourceProperties() {
return new DataSourceProperties();
}
#Bean
#ConfigurationProperties("partner.datasource")
public DataSource partnerDataSource() {
return partnerDataSourceProperties().initializeDataSourceBuilder().build();
}
#Bean(name = "partnerEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean customerEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
Properties properties = new Properties();
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect");
LocalContainerEntityManagerFactoryBean emf = builder
.dataSource(partnerDataSource())
.packages(TestPost.class)
.persistenceUnit("partner")
.build();
emf.setJpaProperties(properties);
return emf;
}
#Bean(name = "partnerTransactionManager")
public JpaTransactionManager db2TransactionManager(#Qualifier("partnerEntityManagerFactory") final EntityManagerFactory emf) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf);
return transactionManager;
}
}
The default datasource configured by JHipster will continue to work it's entities. For your custom entities using the second datasource, here is the repository configuration :
#SuppressWarnings("unused")
#Repository
#Transactional("partnerTransactionManager")
#PersistenceContext(name = "partnerEntityManagerFactory")
public interface TestPostRepository extends JpaRepository<TestPost,Long>{
}
I found #freemanpolys answer great but it needs an extra property if you want it to work with postGres.
Add the following property to both the default and secondary datasource:
autocommit: false
I am running Spring Boot v1.5.2.RELEASE.
How to have /health show below without disabling security for entire Spring Boot project?
{
"status": "UP",
"testing": {
"status": "UNKNOWN",
"foo": "bar"
}
}
Here is my code below for TestingHealthIndicator.java:
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
import org.springframework.boot.actuate.health.Health.Builder;
import org.springframework.stereotype.Component;
#Component
public class TestingHealthIndicator extends AbstractHealthIndicator {
#Override
protected void doHealthCheck(Builder builder) throws Exception {
builder.withDetail("foo", "bar");
}
}
"testing" shows in /health only if i set the following in application.properties
management.security.enabled=false
management.health.defaults.enabled=false
But I do NOT want to disable security for entire project.
I did see some helpful info here: https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html, but did not see a specific way set custom AbstractHealthIndicator as non-sensitive.
Assuming that you would like to disable Security for healthcheck only. For the rest of the apis, you would like to do the authentication as normal. So, the health needs to show all the information. I used to have the same project in Springboot 4.4. This is what I configured in my application.yml
endpoints:
health:
sensitive: false
management:
security:
enabled: false
health:
defaults:
enabled: true
In the security, put the other apis do the fullyAuthentication.
<intercept-url pattern="/health access="permitAll" />
<intercept-url pattern="/api/**" access="isFullyAuthenticated()" />
Hope this help.
I'm trying to write a simple Spring Boot application that can (1) register with a Netflix Eureka server, and (2) query the Eureka server to retrieve details of other registered services.
My client class has an #Autowired field of type com.netflix.discovery.DiscoveryClient that is used to talk to Eureka and query it to learn about other services. On my main class I have the annotation #EnableDiscoveryClient:
#SpringBootApplication
#EnableDiscoveryClient
public class AppBootstrap {
public static void main(String[] args) {
SpringApplication.run(AppBootstrap.class, args);
}
}
In my application.yml file under src/main/resources I have:
eureka:
instance:
lease-renewal-interval-in-seconds: 10
lease-expiration-duration-in-seconds: 20
prefer-ip-address: true
secure-port: 443
non-secure-port: 80
metadata-map:
instanceId: my-test-instance
client:
service-url:
defaultZone: http://localhost:9080/eureka/
registry-fetch-interval-seconds: 6
instance-info-replication-interval-seconds: 6
register-with-eureka: true
fetch-registry: true
heartbeat-executor-thread-pool-size: 5
eureka-service-url-poll-interval-seconds: 10
When I start my app the service fails to boot, throwing an exception that is rooted at:
Caused by: java.lang.AbstractMethodError: org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean.getInstanceI
d()Ljava/lang/String;
at com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider.get(EurekaConfigBasedInstanceInfoProvider
.java:53)
at com.netflix.appinfo.ApplicationInfoManager.initComponent(ApplicationInfoManager.java:90)
... 25 more
I've no idea what's going on here. Any ideas? I believe the app should still start even if my Eureka config is incorrect, but it falls over at start time.
Secondly, am I using the correct DiscoveryClient? Ideally I'd like to make it general such that I could use it with Eureka, Consul or ZooKeeper as examples. I find the documentation isn't great at illucidating exactly what's required when using these Spring Cloud / Netflix discovery components.
You can use
org.springframework.cloud.client.discovery.DiscoveryClient
then you can get the list of instances with discoveryClient.getInstances
ServiceInstance instance = discoveryClient.getInstances(service).get(0);
instance.getUri().toString();
If you use another components like RestTemplate, Ribbon, etc you only need to use the name of the service (name registered in eureka) in the URL
restTemplate.getForObject("http://PRODUCTSMICROSERVICE/products/{id}", Product.class, id)
You can see more here
https://spring.io/blog/2015/01/20/microservice-registration-and-discovery-with-spring-cloud-and-netflix-s-eureka
I received the autowiring error in my experience when i was using discoveryclient to get the information in the class outside any function. So I was using eureka to find out the port for my service as the port was described as 0 hence service was picking up port dynamically while starting as spring boot application. I needed to know the port programmatically . In the controller i used the code like below in wrong way
public class HelloController {
private static final Logger LOG = LoggerFactory.getLogger(HelloController.class);
#Autowired
private DiscoveryClient discoveryClient;
int port = discoveryClient.getLocalServiceInstance().getPort();
#RequestMapping("/hello/{id}")
public String sayhello(#PathVariable String id)
{
String s ="A very nice and warm welcome to the world "+id;
LOG.info(String.format("calling helloservice for %s",id));
LOG.info(String.format("calling helloservice for port %d",port));
return s;
}
Once i put the port code inside the sayhello method the error went away. So the correct way of retreiving the port is as below
public class HelloController {
private static final Logger LOG = LoggerFactory.getLogger(HelloController.class);
#Autowired
private DiscoveryClient discoveryClient;
#RequestMapping("/hello/{id}")
public String sayhello(#PathVariable String id)
{
String s ="A very nice and warm welcome to the world "+id;
int port = discoveryClient.getLocalServiceInstance().getPort();
LOG.info(String.format("calling helloservice for %s",id));
LOG.info(String.format("calling helloservice for port %d",port));
return s;
}
If we are using the latest versions of Spring Boot then we wouldn't require the #EnableDiscoveryClient or #EnableEurekaClient to be defined in the main class. This happens in the background by Spring when we add the dependencies in pom.xml
Please make sure your files have the below basic informations.
pom.xml
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.0-SNAPSHOT</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
application.properties or YAML file as per choice
spring.application.name=eureka-client
eureka.client.service-url.defaultZone: ${EUREKA_URI:http://localhost:8761/eureka}
eureka.instance.prefer-ip-address= true
server.port= 8082
No changes or # Annotations required in the main class in Application.java
Please checkout my GIT Repository here for the working code.
add application.yml file these settings;
Our product application run at this port
server :
port : 8482
Our service will be register by own service name
spring :
application :
name : product-service
# To be register we assign eureka service url
eureka:
client:
service-url :
defaultZone:
${EUREKA_URI:http://localhost:8481/eureka} # add your port where your eureka server running
instance :
prefer-ip-address : true
# Logging file path
logging :
file :
path : target/${spring.application.name}.log