How to access spring.application.instance_id programmatically? - java

I have the following content in my "applicationname.yml" file of my Spring Boot/Cloud application. How can i get the value of spring.application.instance_id in my java code ? This "applicationname.yml" file is hosted in the 'Spring Cloud Config Server'.
eureka:
password: password
client:
registryFetchIntervalSeconds: 5
serviceUrl:
defaultZone: ${vcap.services.${PREFIX:}eureka.credentials.uri:http://user:password#localhost:8761}/eureka/
instance:
preferIpAddress: true
leaseRenewalIntervalInSeconds: 10
metadataMap:
instanceId: ${vcap.application.instance_id:${spring.application.name}:${spring.application.instance_id:${server.port}}}
I have a java class where i am trying to access this variable's value using the #Value annotation and it gives me an error. Here is what i have to get and print the value in the java class
#Value("${eureka.instance.instanceId}")
private String EinstanceId;
#Value("${spring.application.instance_id}")
private String SinstanceId;
Error Message:
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.String com.citigroup.ccp.psg.error.PSGErrorFilter.instanceId; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'eureka.instance.instanceId' in string value "${eureka.instance.instanceId}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 49 more
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'eureka.instance.instanceId' in string value "${eureka.instance.instanceId}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:175)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:801)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:955)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
... 51 more

You miss metadata block. Use:
#Value("${eureka.instance.metadataMap.instanceId}") String instanceId;
As far as I know there is no instance_id property in spring.application namespace.

Use the #Value annotation with Spring Expression Language
import org.springframework.beans.factory.annotation.Value;
//...
#Value("${spring.application.instance_id}")
private String instanceId;
//...

Related

Caused by: java.lang.IllegalArgumentException: class ConfigClientRetryBootstrapper is not assignable to interface BootstrapRegistryInitializer

I just upgraded spring boot version to : 2.7.0 & spring cloud to: 2021.0.3 and because it is a legacy system and got an error I added the dependency mentioned in :No spring.config.import property has been defined and got the following error
Caused by: java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.boot.BootstrapRegistryInitializer : org.springframework.cloud.config.client.ConfigClientRetryBootstrapper
at org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:449)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:431)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:424)
at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:266)
at org.springframework.boot.builder.SpringApplicationBuilder.createSpringApplication(SpringApplicationBuilder.java:129)
at org.springframework.boot.builder.SpringApplicationBuilder.<init>(SpringApplicationBuilder.java:102)
at org.springframework.boot.builder.SpringApplicationBuilder.<init>(SpringApplicationBuilder.java:98)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createSpringApplicationBuilder(SpringBootServletInitializer.java:166)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:130)
at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:97)
at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:174)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5221)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
... 44 more
Caused by: java.lang.IllegalArgumentException: class org.springframework.cloud.config.client.ConfigClientRetryBootstrapper is not assignable to interface org.springframework.boot.BootstrapRegistryInitializer
at org.springframework.util.Assert.assignableCheckFailed(Assert.java:720)
at org.springframework.util.Assert.isAssignable(Assert.java:651)
at org.springframework.util.Assert.isAssignable(Assert.java:682)
at org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:443)
... 56 more
Can someone help please ?
Thanks

Spring Boot only initializes one data source but not the other

I have followed multiple articles on creating multiple data sources and tried the same in my code. But strangely spring boot in only initializing one data source and not the other. When I remove any one of them from the code, the other is created without any issues. Any idea.
Bean Configuration -
#Configuration
public class DBConfiguration {
#Bean("dataSource")
#ConfigurationProperties(prefix = "p.datasource")
public DataSource pDataSource() {
System.out.println("**************************> dataSource");
return DataSourceBuilder.create().build();
}
#Bean("storeFrontDataSource")
#ConfigurationProperties(prefix = "c.datasource")
public DataSource cDataSource() {
System.out.println("**************************> storeFrontDataSource");
return DataSourceBuilder.create().build();
}
}
YML File (removed some data for confidentiality) -
p:
datasource:
url: {some-url}
driver-class-name: com.ibm.db2.jcc.DB2Driver
username: abc
password: xyz
type: com.zaxxer.hikari.HikariDataSource
hikari:
schema:
connection-init-sql: select 1 from dual
minimum-idle: 25
maximum-pool-size: 100
idle-timeout: 10_000
max-lifetime: 20_000
connection-timeout: 1_000
validation-timeout: 500
c:
datasource:
url: {some-url}
driver-class-name: com.ibm.db2.jcc.DB2Driver
username: abc
password: xyz
type: com.zaxxer.hikari.HikariDataSource
hikari:
schema:
pool-name: uspo-cis-sf-pool
connection-init-sql: select 1 from dual
minimum-idle: 1
maximum-pool-size: 5
idle-timeout: 10_000
max-lifetime: 50_000
connection-timeout: 2_000
validation-timeout: 500
Error thrown -
Only the "datasource" bean is found and not the "storeFrontDataSource" bean. Even on the console only one of System.out.println() is called (i.e. for "datasource") while other is not printed. SpringBoot is not even initializing the other bean definition.
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.zaxxer.hikari.HikariDataSource' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Qualifier(value=storeFrontDataSource)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1790) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1346) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.3.jar:5.3.3]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-5.3.3.jar:5.3.3]
... 38 common frames omitted
Note - Even defining #Primary doesn't helps. Both System.out.println() should be printed to console regardless.
As per the advise #tgdavies, I found some of the classes from the dependent libraries were injecting 'HikariDataSource' instead of 'DataSource'. After fixing them the issue got resolved.
You need to create customer configuration class for create multiple datosource and you define primary datasource.
Check this example from baeldung

Upgrading from Springboot 2.1.4.RELEASE to 2.5.0 giving IllegalArgumentException on runtime

I upgraded springboot2.1.4.RELEASE to 2.5.0 ,In local, it is able to run fine and read from the application.properties file, but when I try to deploy in aws ECS it is giving the following error. Any pointers will help
Error:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'cloudPlatformSecuirtyResourceServerConfig': Unsatisfied dependency expressed through field 'uaaResourceInfo'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'UAAResourceInfoConfig': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'moa.aws.secrets.uaa.clientId' in value "${moa.aws.secrets.uaa.clientId}"
The application.yml
uaa:
accessTokenURI: ${uaa.accessTokenURI}
clientId: ${moa.aws.secrets.uaa.clientId}
clientSecret: ${moa.aws.secrets.uaa.clientSecret}
clientScope: oa.ups.reader,uaa.resource
The code which is calling the bean
#Configuration
#Profile({"security"})
public class UAAResourceInfoConfig {
#Value("${uaa.accessTokenURI}")
private String uaaAccessTokenURI;
#Value("${uaa.clientId}")
private String uaaClientId;
#Value("${uaa.clientSecret}")
private String uaaClientSecret;
#Value("${uaa.clientScope}")
private String uaaClientScope;
#Bean("UAAResourceInfo")
public UAAResourceInfo uaaResourceInfo() {
return new UAAResourceInfo(uaaAccessTokenURI, uaaClientId, uaaClientSecret, uaaClientScope);
}
}
The only difference between application.properties file and Secrets Manager of aws is , in the properties file the properties are stored individually like
moa.aws.secrets.uaa.clientId=xxx
moa.aws.secrets.uaa.clientSecret=xxxx
moa.aws.secrets.moa.db_url=xxxxx
moa.aws.secrets.moa.db_username=xxxx
moa.aws.secrets.moa.db_password=xxxx
But in Secrets Manager, they may be stored in a json format
moa.aws.secrets={"tenantId": "xxxxx","moa.db_url": "xxxx","moa.db_username": "xxx","moa.db_password": "YOUR_LOCAL_DB_PASS","uaa.clientId": "xxxxxx","uaa.clientSecret": "xxxxx","uaa.scope": "xxxx"}

Autowiring RestTemplate causes "argument type mismatch" when including Eureka

After adding
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
to my dependencies I get the following exception
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [example.nagios.notificationmanager.core.nagiosapi.NagiosAPIService]: Illegal arguments for constructor; nested exception is java.lang.IllegalArgumentException: argument type mismatch
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:158)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:122)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:267)
... 24 more
Caused by: java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
... 26 more
So it fails to create the service with the following constructor
#Autowired
public NagiosAPIService(#Value("${nagios.state.uri}") String nagiosStateUri,
#Qualifier("systemAuthorized") RestTemplate restTemplate, NagiosCheckService nagiosCheckService) {
this.nagiosStateUri = nagiosStateUri;
this.restTemplate = restTemplate;
this.nagiosCheckService = nagiosCheckService;
}
I removed one parameter after the other, and it's the RestTemplate which causes the error.
Without spring-cloud-starter-eureka in my dependencies everything works fine.
Could anybody tell me why eureka causes this error?
I think it's just that there is some (optional, but active by default if you use that starter) autoconfiguration to monitor rest template usage for metrics. You can probably still autowire a RestOperations, or set spring.aop.proxy-target-class=true to get it to work as is.

#Value -> Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'

Good day, I'm working on a web application using Spring 4.1.1.RELEASE. All Spring configuration is done with annotations and it works fine except one thing:
I have a config.properties file in the project with these lines
cases.caseList.filter=test
cases.caseList.numberOfCasesPerPage=50
I have a config class
#Configuration
#ComponentScan(basePackageClasses={CaseConfig.class})
#PropertySource(value = "classpath:config.properties")
public class CasesModuleTestContextConfig { ... }
And another class
#Component
public class HttpRequestParamsToPaginationParams extends AbstractConverter<Map<String, String>, PaginationParams> {
#Value("${cases.caseList.filter}")
private String filter;
#Value("${cases.caseList.numberOfCasesPerPage}")
private Integer count;
...
}
Value of property 'filter' is successfuly injected from the property resource. But I'm getting an exception on property 'count':
13:58:45.274 [main] WARN o.s.c.s.GenericApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cz.pokus.core.test.config.ConversionServiceTestConfig': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.List cz.pokus.core.test.config.ConversionServiceTestConfig.converterList; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'httpRequestParamsToPaginationParams': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.lang.Integer cz.pokus.core.cases.converter.HttpRequestParamsToPaginationParams.count; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For input string: "${cases.caseList.numberOfCasesPerPage}"
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.1.1.RELEASE.jar:4.1.1.RELEASE]
...
Caused by: org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.lang.Integer'; nested exception is java.lang.NumberFormatException: For input string: "${cases.caseList.numberOfCasesPerPage}"
...
Caused by: java.lang.NumberFormatException: For input string: "${cases.caseList.numberOfCasesPerPage}"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) ~[na:1.8.0_20]
at java.lang.Integer.parseInt(Integer.java:569) ~[na:1.8.0_20]
at java.lang.Integer.valueOf(Integer.java:766) ~[na:1.8.0_20]
...
When I change type of property 'count' to String it start working:
#Value("${cases.caseList.numberOfCasesPerPage}")
private String count;
I believe Spring is able to convert String to Integer when injecting value from property resource into a Integer property using #Value. I'v found examples where people use without complaining. Do you please have any ideas why it doesn't work for me?
Thanks a lot in advance.
If you are trying to access the property values using #Value("") annotation, you should declare PropertySourcesPlaceholderConfigurerBean.
Try to add below snippet of code in your configuration class.
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
If you don't want to declare it, Try with org.springframework.core.env.Environment class by autowiring it in your class, to get the property values.
#Autowired
private Environment environment;
public void readValues() {
System.out.println("Some Message:"
+ environment.getProperty("<Property Name>"));
}
In my case I foregot the $ sign into the annotation
#Value("{cases.caseList.filter}")
instead of
#Value("${cases.caseList.filter}")

Categories