spring boot can not get configuration from application.yml - spring

My spring boot application can not get configuration parameters from application.yml file. My main class as following:
#SpringBootApplication(scanBasePackages={"com.test"})
public class Main {
#Bean
public Validator validator(){
return new org.springframework.validation.beanvalidation.CustomValidatorBean();
}
public static void main(String[] args) throws IOException {
new SpringApplicationBuilder(Main.class)
.properties("application.yml")
.build()
.run(args);
}
}
My controller class as following:
#RestController
#RequestMapping("/test_traffic")
#Component
public class AnycastTrafficController {
#Autowired
TestService testService;
#GetMapping("/test")
public Object component() {
return testService.getTraffic();
}
}
My Service class as following:
#Service
public class TestService {
#Autowired
TestDao testDao;
public Object getTraffic() {
testDao.getTraff();
}
}
My Dao class as following:
#Component
public class TestDao {
#Autowired
MyDBConfig mydbConfig;
public DB getMyDBConfig () {
DB db = new DB(mydbConfig.id, mydbConfig.key);
return db;
}
}
My Config class as following:
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "mydb")
public class MyDBConfig {
public String id;
public String key;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
My application.yml (which located at /src/main/resources)as following:
server:
port: 8003
context-path: /
logging:
level:
ROOT: INFO
org.springframework: INFO
org.springframework.data: INFO
com.alibaba: INFO
file: log/
docserver:
accessKeyId: 1111
accessKeySecret: 2222
---
spring:
profiles: dev
application:
name: test-application
mydb:
id: 1111111
key: 2222222
But when I started the Main class and request the url, it threw exception as following:
the id should not be empty.
that mean my Configuration class didn't get the configure data from yml file, so where I did wrong please. p.s(but the server port 8003 could be found by application). Thanks!

Your application.yml contains an invalid property option.
Instead of
spring:
profiles: dev
you should use
spring:
profiles:
active: dev
After correcting this this, the configuration processor should work properly.

Related

What is idea of bindings in spring boot rabbitmq?

I need to bind several exchanges with several routing keys to one single queue and be able to send messages by exchange and routing key and receive it by listening to queue by queue-name.
my code:
#Configuration
#RequiredArgsConstructor
#EnableConfigurationProperties(ExchangeConfig.class)
public class RabbitConfig {
private final ExchangeConfig exchangeConfig;
#Bean
public List<Binding> bindings() {
List<Binding> bindings = new ArrayList<>();
exchangeConfig.getExchangesWithKeys()
.forEach(exchangeWithKeys -> exchangeWithKeys.getRoutingKeys()
.forEach(key -> {
Exchange exchange = ExchangeBuilder.directExchange(exchangeWithKeys.getExchange()).build();
Queue queue = QueueBuilder.durable(exchangeConfig.getLogsQueue()).build();
Binding binding = BindingBuilder.bind(queue).to(exchange)
.with(key).noargs();
bindings.add(binding);
}));
return bindings;
}
}
config:
spring:
rabbitmq:
host: localhost
port: 5672
rabbitmq:
exchanges-with-keys:
- exchange: exchange1
routing-keys: exchange1.live, exchange1.after
- exchange: exchange2
routing-keys: exchange2.live, exchange2.after
- exchange: exchange3
routing-keys: exchange3.live, exchange3.after
logs-queue: log-messages_q
props:
#Data
#Component
#ConfigurationProperties(prefix = "rabbitmq")
public class ExchangeConfig {
private String logsQueue;
private List<ExchangeWithKeys> exchangesWithKeys;
#Data
public static class ExchangeWithKeys {
private String exchange;
private List<String> routingKeys;
}
}
listener:
#Component
#Slf4j
#RequiredArgsConstructor
public class LogsListener {
private final LogMessageEventProcessor logMessageEventProcessor;
#RabbitListener(queues = "${rabbitmq.logs-queue}")
public void onLiveEvent(LogMessageEvent event) {
log.info("Received log event message [{}]", event.getBody());
logMessageEventProcessor.processLogMessageEvent(event);
}
}
test:
#SpringBootTest
#ContextConfiguration(initializers = LogsListenerTest.Initializer.class)
class LogsListenerTest {
#Autowired
private RabbitTemplate template;
#ClassRule
private static final RabbitMQContainer container = new RabbitMQContainer("rabbitmq:3.7.25-management-alpine")
.withExposedPorts(5672, 15672).withQueue("log-messages_q");
#BeforeAll
private static void startRabbit() {container.start();}
#AfterAll
private static void stopRabbit() {
container.stop();
}
#Test
public void test() {
template.convertAndSend("exchange1", "exchange1.live", new LogMessageEvent());
template.receiveAndConvert("log-messages_q");
}
public static class Initializer implements
ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(#NotNull ConfigurableApplicationContext configurableApplicationContext) {
val values = TestPropertyValues.of(
"spring.rabbitmq.host=" + container.getContainerIpAddress(),
"spring.rabbitmq.port=" + container.getMappedPort(5672)
);
values.applyTo(configurableApplicationContext);
}
}
}
Everything above does not working.
So where should i put these bindings to make it work? Thanks.
What version are you using? The use of List<Binding> has been replaced by Declarables.
See https://docs.spring.io/spring-amqp/docs/current/reference/html/#collection-declaration
The documentation is a bit out of date, the admin declareCollections property was removed in 2.2.

Unable to fetch property value from the config server

I am learning Spring Boot v.2.3.9.RELEASE + Microservices project from here - https://www.youtube.com/watch?v=Z7A_M8HkJG0
In this example, I am unable to fetch the details from the properties file using spring-cloud-config.
spring-config-server
application.yml
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/techefx/environment-variable-repo.git
server:
port: ${port:8888}
ConfigServerApplication.java
#SpringBootApplication
#EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
property-access-service
PropertyAccessBean.java
#Component
#ConfigurationProperties(prefix = "property-file")
#Builder
#Data
#NoArgsConstructor
#AllArgsConstructor
public class PropertyAccessBean {
private String name;
private String description;
}
PropertyAccessValue.java
#Builder
#Data
#NoArgsConstructor
#AllArgsConstructor
public class PropertyAccessValue {
private String name;
private String description;
}
PropertyAccessServiceApplication.java
#SpringBootApplication
public class PropertyAccessServiceApplication {
public static void main(String[] args) {
SpringApplication.run(PropertyAccessServiceApplication.class, args);
}
}
put (default-label: main) in yml file:
spring:
application:
name: techefx-spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://github.com/techefx/environment-variable-repo.git
default-label: main
server:
port: ${port:8888}

Use configuration properties in apache camel route

Is it possible to use concated strings in a apache camel route? Property placeholders work fine but concatation doesn't work.
If tried something like this but the route doesn't pass the data.
dependencies
"org.springframework.boot:spring-boot-starter:2.1.3.RELEASE",
"org.apache.camel:camel-jackson:2.23.1",
"org.apache.camel:camel-paho:2.23.1",
application.properties
a.b.property1=test
a.b.property2=test
RouteConfig
#Configuration
#ConfigurationProperties(prefix = "a")
public class RouteConfig{
private B b;
public B getB() {
return b;
}
public static class B {
private String property1;
private String property2;
public String getProperty1() {
return property1;
}
public String getProperty2() {
return property2;
}
}
}
#Component
public class Route extends RouteBuilder {
#Autowired
RouteConfig routeConfig;
#Override
public void configure() throws Exception {
from("paho://" + routeConfig.getB().getProperty1()).to(direct:foo)
}
}
Apache camel should build the route with a string which is build with concatination.

springboot could not found feignclient

ERROR INFO LIKE BELOW:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field helloAgent in com.example.client.controller.Hello required a bean of
type 'com.example.common.agent.HelloAgent' that could not be found.
Action:
Consider defining a bean of type 'com.example.common.agent.HelloAgent' in
your configuration.
project structure:
module: test-client as feignclient caller.
module: test-server as feignclient interface implementation.
module: test-common put all feignclient together.
test-common:
package com.example.common.agent;
#FeignClient("hello")
public interface HelloAgent {
#GetMapping("/hello")
String hello(#RequestParam String msg);
}
test-server:(works fine)
package com.example.server.controller;
#RestController
public class Hello implements HelloAgent {
#Override
public String hello(#RequestParam String msg) {
System.out.println("get " + msg);
return "Hi " + msg;
}
}
test-client:
package com.example.client.controller;
#RestController
public class Hello {
#Autowired
private HelloAgent helloAgent;
#GetMapping("/test")
public String test() {
System.out.println("go");
String ret = helloAgent.hello("client");
System.out.println("back " + ret);
return ret;
}
}
----------------------------
#EnableEurekaClient
#EnableFeignClients
#SpringBootApplication
#ComponentScan(basePackages = {"com.example.common.agent","com.example.client.controller"})
public class TestClientApplication {
public static void main(String[] args) {
SpringApplication.run(TestClientApplication.class, args);
}
}
Is there anyway to put all feignclient together so that we can manage them gracefully?
Or there is only way to use them redundancy?
THANKS!
Feign doesn't know about #ComponentScan.
Use #EnableFeignClients(basePackages = {"com.example.common.agent","com.example.client.controller"})
Solution using Configuration
In case you use Swagger Codegen, you can use a configuration to bootstrap the apis:
#Configuration
public class ParkingPlusFeignClientConfiguration {
#Autowired
private ParkingPlusProperties properties;
#Bean
public ServicoPagamentoTicket2Api ticketApi() {
ApiClient client = new ApiClient();
// https://stackoverflow.com/questions/42751269/feign-logging-not-working/59651045#59651045
client.getFeignBuilder().logLevel(properties.getClientLogLevel());
client.setBasePath(properties.getHost());
// Generated from swagger: https://demonstracao.parkingplus.com.br/servicos
return client.buildClient(ServicoPagamentoTicket2Api.class);
}
}

Spring Boot Configuration Not Working

I'm using Spring boot.
I have an application.yml in src/main/resources. I then have a Configuration class that I am trying to get to load the application.yml. However, when I try to use the configuration class in another bean, the values are null. See the ApiHelper.java as to where the values are null.
I'm attempting to run the jar as so:
java -jar build/libs/app.jar
Am I doing something wrong? I've also tried using a properties file instead. When I unzip the jar file the configuration files are in the root.
src/main/resources/application.yml
spring:
profiles.active: default
---
spring:
profiles: default
api:
path: http://some-path
---
spring:
profiles: qa
api:
path: http://some-path2
src/main/java/AppConfig.java
#Configuration
#EnableConfigurationProperties(ApiConfig.class)
public class AppConfig {
#Autowired
private ApiConfig apiConfig;
#ConfigurationProperties(value = "api", exceptionIfInvalid=true)
public static class ApiConfig {
private String path;
public ApiConfig() {
System.out.println("Am I getting called?"); // yes it is
}
public String getPath() {
return path;
}
}
#Bean
public ApiHelper getApiHelper() {
return new ApiHelper();
}
}
src/main/java/ApiHelper.java
public class ApiHelper {
#Autowired
private ApiConfig apiConfig;
#PostConstruct
private void init() {
System.out.println(apiConfig); // prints ApiConfig#168498d6
System.out.println(apiConfig.getPath()); // prints null
}
}
It turns out that you need a setter to make it work:
#ConfigurationProperties(value = "api", exceptionIfInvalid=true)
public static class ApiConfig {
...
public void setPath(String path) {
this.path = path;
}
}

Resources