Use configuration properties in apache camel route - spring

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.

Related

Spring Boot #ConfigurationProperties

so I'm kinda new to Springboot and I'm trying to get the value from application.properties. I want to get multiple value from the application.properties and insert it into a list. At first, I tried to get the value from controller class and it works. Now I tried to get the value from a new class, but the value won't show up and it's showing an error because it says that it's null. Am i missing an annotation or did i do something wrong in the code? Below is my code.
application.properties:
example.name[0] = asdf
example.name[1] = qwer
List Value class:
#ConfigurationProperties(prefix = "example")
#Configuration
public class NameProperties {
private List<String> name;
public List<String> getName() {
return name;
}
public void setName(List<String> name) {
this.name = name;
}
}
What i tried in controller and worked:
#RestController
#CrossOrigin
#RequestMapping("/tes/**")
public class NameController {
#Autowired
NameProperties property = new NameProperties();
#GetMapping
public String tes() {
String name = property.getName().get(0);
System.out.println(name);
return name;
}
}
In the new class that doesn't work:
#Component
public class NameConfiguration {
#Autowired
NameProperties property = new NameProperties();
public void getName(int index) {
System.out.println(property.getName().get(0));
}
}
The code to test the new class in the controller:
#RestController
#CrossOrigin
#RequestMapping("/tes/**")
public class NameController {
NameConfiguration conf = new NameConfiguration();
#GetMapping
public String tes() {
conf.getName(0);
}
}
Is it because the value doesn't get injected when I call the class or what should I do? Appreciate any kind of help. Thanks!
Hello friend when you declare your class as a Spring Bean you shouldn't initialize the object yourself other the properties define in it will not be injected by Spring, so you should let spring help you with that, try these class below
NameProperties
#Component
#ConfigurationProperties(prefix = "example")
public class NameProperties {
private List<String> name;
public List<String> getName() {
return name;
}
public void setName(List<String> name) {
this.name = name;
}
}
NameConfiguration.java
#Component
public class NameConfiguration {
#Autowired
NameProperties property;
public void getName(int index) {
System.out.println(property.getName().get(0));
}
}

Getting null value from #configuration

I'm creating pojo class and store the application.properties variable but I'm getting null values
NOTE: need to access env from my Abstract class
POJO class
package mynt.xyz.c4.pushnotif.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
#Configuration("notificationEnvironment")
#ConfigurationProperties(prefix = "app.notif")
public class NotificationEnvironment {
private String key;
private String url;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
Initializing class with #autowired
public abstract class NotificationBase {
#Autowired
NotificationEnvironment notificationEnvironment;
public void getEnv(){
system.out.println(notificationEnvironment.getKey()); // null value
}
}
concrete class that extend to my NotificationBaseClass
#Component
#Qualifier("androidNotification")
public class AndroidNotification extends NotificationBase implements Notification {
public AndroidNotification(String message, String title, String datalink, List<String> instanceIds) {
super(message, title, datalink, instanceIds);
}
AndroidNotification(){
super();
}
#Override
public void send() {
this.getEnv();
}
}
application.properties
app.notif.key=jkashdkjashd
app.notif.url=https/some.url
You can auto wire #Configuration class from #Configuration class
#Configuration class may reference the instance of any other #Configuration class using #Autowired. This works because the #Configuration classes themselves are instantiated and managed as individual Spring beans.
Make your class #Component and add prefix value in #ConfigurationProperties, like this. This works for me, hope this works for you as well.
#Component
#ConfigurationProperties(prefix = "app.notif")
public class NotificationEnvironment {
private String key;
private String url;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
}
You can use this properties like this:
#Component
public class NotificationBase {
private static NotificationEnvironment notificationEnvironment;
#Autowired
public NotificationBase(NotificationEnvironment notificationEnvironment){
this.notificationEnvironment = notificationEnvironment;
}
public static void getEnv(){
System.out.println(notificationEnvironment.getKey()); // null value
}
}
Here is the one of the concrete class definition as OP author mentioned.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class ConcreteNotification extends NotificationBase {
#Autowired
public ConcreteNotification(NotificationEnvironment notificationEnvironment) {
super(notificationEnvironment);
}
}
updated NotificationBase as below
public abstract class NotificationBase {
NotificationEnvironment notificationEnvironment;
public NotificationBase(NotificationEnvironment notificationEnvironment) {
this.notificationEnvironment = notificationEnvironment;
}
public void getEnv(){
System.out.println(notificationEnvironment.getKey());
}
}
The controller class I am using to get configuration values
#RestController
public class ArticleCommentController {
#Autowired
ConcreteNotification concreteNotification;
#RequestMapping(value = "/health_check", method = RequestMethod.GET)
public void getDemo() {
concreteNotification.getEnv();
}
}
output:
jkashdkjashd

Retrieving the value of a property pom.xml

I would like to retrieve the value of a property in file application.properties in my service layer of my application, the value of setVersion is null
version=5.4.3
and the function for recovery the version
#Override
public ProductDto getVersionApp() {
ProductDto dto = new ProductDto();
Properties prop = new Properties();
try {
prop.load(new FileInputStream("/concerto-rest-api/src/main/resources/application.properties"));
dto.setVersion(prop.getProperty("version"));
LOG.info("version ",prop.getProperty("version"));
} catch (IOException ex) {}
return dto;
}
You can use #Value("${version}") in you service, provided you service is a spring bean.
If you are using the spring-boot framework, there are several ways you can get that property.
First:
#SpringBootApplication
public class SpringBoot01Application {
public static void main(String[] args) {
ConfigurableApplicationContext context=SpringApplication.run(SpringBoot01Application.class, args);
String str1=context.getEnvironment().getProperty("version");
System.out.println(str1);
}
}
Second:
#Component
public class Student {
#Autowired
private Environment env;
public void speak() {
System.out.println("=========>" + env.getProperty("version"));
}
}
Third:
#Component
#PropertySource("classpath:jdbc.properties")//if is application.properties,then you don't need to write #PropertyScource("application.properties")
public class Jdbc {
#Value("${jdbc.user}")
private String user;
#Value("${jdbc.password}")
private String password;
public void speack(){
System.out.println("username:"+user+"------"+"password:"+password);
}
}

factory pattern using spring

How can I choose a service implementation depending on a request parameter on SpringBoot? I can do this by manually instantiating the service, but that's not making use of the Spring Injection feature.
I can also Autowire the two services separately but I'm thinking that if I have more implementations that would pollute the class.
Here's a crude example:
#RestController
class RestControllerTest {
#Autowired
PizzaService pizzaService;
public void bakePizza(#RequestParam("type") String type,#RequestParam("extra") String extra) {
if (type.equals("cheese")) {
//set pizzaService Cheese Implementation
pizzaService = new CheezePizza();
} else {
//set PizzaService vegetable Impleentation;
pizzaService = new VegetablePizza();
}
pizzaService.prepareIngredients(extra);
pizzaService.bakePizza();
}
}
public abstract class PizzaService {
String ingredients;
public abstract void prepareIngredients(String exraIngredient);
public void bakePizza() {
System.out.println("baking pizza with " + ingredients);
}
}
class CheezePizza extends PizzaService {
#Override
public void prepareIngredients(String exraIngredient) {
ingredients = "Cheese " + exraIngredient;
}
}
class VegetablePizza extends PizzaService {
#Override
public void prepareIngredients(String exraIngredient) {
ingredients = "Vegetable " + exraIngredient;
}
}
You could autowire list of beans of same type. So let's say you add getType() to your PizzaService and register every type as spring bean.
public abstract class PizzaService {
abstract String getType();
}
#Component
class CheezePizza extends PizzaService {
#Override
public String getType() {
return "cheese";
}
}
#Component
class VegetablePizza extends PizzaService {
#Override
public String getType() {
return "vegetable";
}
}
#RestController
class RestControllerTest {
private final Map<String, PizzaService> pizzaServices;
public RestControllerTest(List<PizzaService> services) {
pizzaServices = services.stream().collect(Collectors.toMap(PizzaService::getType, Function.identity()));
}
public void bakePizza(#RequestParam("type") String type, #RequestParam("extra") String extra) {
PizzaService pizzaService = pizzaServices.get(type); // remember of handling missing type
pizzaService.prepareIngredients(extra);
pizzaService.bakePizza();
}
}
Another way is to use name your beans by convention i.e. cheesePizza, vegetablePizza and then use ApplicationContext#getBean(type + "Pizza") but I like first approach better, because it's less magical.

Why are spring beans validated even if the condition says it should not be loaded into the context?

Given the example below, I would expect MyConfig.getSrvConfig() would not be called and therefore no validation would be executed on the returned object neither.
But for some reason the validation is executed and the test case fails. Is there anything wrong in this setup?
I know the test would pass if I have private MySrvConfigBean srvConfig not initialized at declaration - but I really don't want MySrvConfigBean to be a standalone class with a #ConfigurationProperties(prefix = "cfg.srvConfig") annotation.
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = { TestCaseConfiguration.class })
public class ConditionalConfigValidationTest {
#Autowired
private ApplicationContext applicationContext;
#Test
public void test() {
assertNotNull(applicationContext);
assertFalse("srvConfig must NOT be in context", applicationContext.containsBean("srvConfig"));
}
#Configuration
#EnableConfigurationProperties(value = { MyConfig.class })
public static class TestCaseConfiguration {
}
#Component
#Validated
#ConfigurationProperties(prefix = "cfg")
public static class MyConfig {
private MySrvConfigBean srvConfig = new MySrvConfigBean();
#Bean
#Valid
#Conditional(MyCondition.class)
public MySrvConfigBean getSrvConfig() {
return srvConfig;
}
public static class MySrvConfigBean {
#NotNull
private String name;
public String getName() {
return name;
}
}
}
public static class MyCondition implements Condition {
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return false;
}
}
}
The reason we would like to have it this way is, because we then are able to structure configuration in code the same way as we have it in the YAML file, e.g.: (cfg and cfgA are the "root" objects for two different configuration hierarchies).
cfg:
srvConfig:
name: Dude
clientConfig:
xxx: true
yyy: Muster
cfgA:
aaaConfig:
bbb: false
ccc: Dundy
dddConfig:
fff: 3
It feels like the execution of the validation (triggered by #Valid on getSrvConfig()) is a bug in this case.
Apparently this is not supported and should be solved in a different way:
#Configuration
#Conditional(MyCondition.class)
#EnableConfigurationProperties(value = { MyConfig.class })
public static class TestCaseConfiguration {
}

Resources