Apache Camel fields injection - spring

Using Apache Camel PropertyPlaceHolder I want to inject a property value in a Java Class field using Simple Expression Language:
#Simple("${properties:prop1}")
private String prop1;
#Simple("${properties:prop2}")
private String prop2;
That works fine with method's parameters:
public void test(#Simple(value = "${properties:prop}") String prop) {
//....
}
But in java class fields I keep having null value, nothing is injected.
Any ideas please on how can I do that?
Thank you in advance.

Using
#Simple("${properties:prop2}")
private String prop2;
On fields is not supported in Camel.
There is a JIRA ticket to support this in the future: https://issues.apache.org/jira/browse/CAMEL-3215

Related

Camel REST DSL set Example Value for Swagger UI

Is it possible and if yes, how to set the Example Value for Swagger UI using Camel REST DSL in Java?
I'm running Swagger UI from org.webjars dependency in Spring Boot.
rest("/test").description("Some description").consumes("application/json").produces("application/json")
.post("/trigger").id("trigger")
.description("Another description")
.type(Map.class).param().name("body").type(body).description("More description"))
.required(true).example(readJson.getJson("json_example.txt")).endParam()
.route().bean(new Service(), "Trigger");
This readJson get JSON as String.
It looks like .example() is ignored and nothing appears in Swagger UI.
It always shows the "string" value inside Example Value like on the picture below.
As a solution, I've created Java POJO class with next code:
public class User{
public String user_id;
public String user_name;
}
Then I linked that class to the Camel REST DSL inside SpringBootRouter class:
...
rest("/test").description("Some description").consumes("application/json").produces("application/json")
.post("/trigger").id("trigger")
.description("Another description")
.type(User.class).param().name("body").type(body).description("More description"))
.required(true).endParam()
.route().bean(new Service(), "Trigger");
...
And this is the result:
If there is a better solution, please tell.
UPDATE:
To replace default value "string" for String or 0 for int or true for Boolean, I've used ApiModelProperty like this:
import io.swagger.annotations.ApiModelProperty;
public class User{
#ApiModelProperty(example = "1165")
public String user_id;
#ApiModelProperty(example = "Bob")
public String user_name;
}
And this is the final result:
In swagger v3 you use
#Model(description = "The user name", example = "Bob")
public String user_name;

Spring Autowire configuration in flink

i am trying to use the comination of flink and springboot and im having some problems.
Lets say i am having this flow.
Getting json string that have one field date that contains date string.
using map function and ObjectMapper to parse it into object of LocalDateTime
print
This is simple usecase that will describe my probem.
So, i have Word Class represnting Word that contains LocalDateTime field.
#Data
public class Word {
#JsonDeserialize(using = LocalDateTimeSerde.class)
LocalDateTime date;
}
The LocalDateTimeDeserlization is looking like that(I want to autowire the app configuration):
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
#JsonComponent
public class LocalDateTimeSerde extends JsonDeserializer<LocalDateTime> {
private final AppConf conf;
#Override
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(this.conf.getDateFormatter());
return LocalDateTime.parse(jsonParser.getText(), formatter);
}
}
AppConf.java represneting the configuration of the application is:
#Data
#Configuration
#ConfigurationProperties(value = "app")
public class AppConf {
private String dateFormatter;
}
DemoApplication.java:
final StreamExecutionEnvironment env = StreamExecutionEnvironment.createLocalEnvironment(1);
String example = "{\"date\":\"2019-01-29 00:00\"}";
var stream = env
.fromElements(example)
.map(x->new ObjectMapper().readValue(x,Word.class))
.returns(Word.class);
stream.print();
env.execute("Demo App");
The exception im getting is :
Caused by: java.lang.IllegalArgumentException: Class com.example.demo.LocalDateTimeSerde has no default (no arg) constructor
The main problem here is that the code of the deserialization is running on the TaskManager and over there springboot doesnt take a part, so it doesn`t inject AppConf into the class.
Adding #NoArgsConstructor will not solve the problem
I think i know why it is hapenning (because flink master serialize the classes to the workers and then springboot doesn`t "ScanComponents" and takes control.
Is there any solution for that? I really want to combine spring with flink also in the worker`s function.
Thanks.
In general, I personally don't think it's a good idea to mix those concepts. The easiest solution is to use AutoWired only on the job manager and use explicit dependency injection when you go into Flink-land.
For example, you could extract the date pattern in the DemoApplication and set it on the ObjectMapper. (Don't forget to initialize ObjectMapper only once in your real code!)
If you really want to use AutoWiring. I guess you need to manually trigger the autowiring on taskmanager. There is a related post specifically for ObjectMapper.

#Value In Spring MVC is not getting populated

I am trying to populate an attribute using the #Value annotation in Spring MVC, and it is not getting populated.
I am trying to access the attribute using Struts2 JSP property. my use case looks like that:
public class TransferCreditsAction extends StudentAwareAction {
protected Log logger = LogFactory.getLog(this.getClass());
#Value( "${transfer.credit.url}" )
private String transferCreditUrl;
public void setStates( List<TranslatedValue> states ) {
this.states = states;
}
#Value( "${transfer.credit.url}" )
public String getTransferCreditUrl() {
return transferCreditUrl;
}
}
My property file looks like:
transfer.credit.url
I am accessing this attribute using JSP which looks like:
<s:property value='transferCreditUrl'/>"
I know for a fact that my JSP can access this field, because I tested it when I have this field set for a default value.
However, this field is not getting populated from my property file. I am using Spring 4.1.6
Any help is really appreciated.
Spring can only inject values in its own managed spring beans. That means your TransferCreditsAction should be a spring bean.
There are various ways to declare your TransferCreditsAction class as a spring bean, already answered elsewhere.
You haven't added whats on top of TransferCreditsAction class.
Values will be injected in a Bean Env.
There are many ways of Doing it
Assuming my property file contains
username=Ashish
app.name=Hello
1.
#Service
#PropertySource(value = { "classpath:sample.properties" })
public class PaloAltoSbiClientImpl implements PaloAltoSbiClient {
public static String username;
#Value("${username}")
public void setUrl(String data) {
username = data;
}
...
2.
#Service
public class PaloAltoSbiClientImpl implements PaloAltoSbiClient {
#Value("${username}")
public static String username;
...
3.
#Component
public class TokenHelper {
#Value("${app.name}")
private String APP_NAME;
Just give the properties file reference on top of the class in which you are trying to get.
#PropertySource(value = { "classpath:sample.properties" })
This issue was happening because I was missing <context:annotation-config/> in my applicationContext. Once I added it, it start working with no issues.

Spring MVC mapping #RequestBody with variables containing a dot

I am doing a POST request to my Rest Contoller with the following object:
{
"relationship.name": "someting"
}
I'd like to map that to a POJO:
public class Request {
private String relationshipName;
// Getters, setter and contructor
}
How would I dot that?
Annotate your property with #JsonProperty
public class Request {
#JsonProperty("relationship.name")
private String relationshipName;
...
}
By default, the mapping will use the variable name as the key for the property. So without the annotation, it would expect relationshipName. #JsonProperty allows you to customize the key without changing the variable name.
Have u tried using #JsonProperty on relationshipName?
#JsonProperty(name), tells Jackson ObjectMapper to map the JSON property name to the annotated Java field's name.

How to bind a string array of properties in Spring?

I have the following in my application.properties file
some.server.url[0]=http://url
some.server.url[1]=http://otherUrl
How do I refer to the array of properties using the #Value anotation inside a #Bean method?
I am using Java 6 with Tomcat 7 and Spring boot 1.4
I was also having the same problem as you mentioned and it seems using index form on application.properties was not working for me either.
To solve the problem I did something like below
some.server.url = url1, url2
Then to get the those properties I simply use #Value
#Value("${some.server.url}")
private String[] urls ;
Spring automatically splits the String with comma and return you an Array. AFAIK this was introduced in Spring 4+
If you don't want comma (,) as seperator you have to use SpEL like below.
#Value("#{'${some.server.url}'.split(',')}")
private List<String> urls;
where split() accepts the seperator
You can use a collection.
#Value("${some.server.url}")
private List<String> urls;
You can also use a configuration class and inject the bean into your other class:
#Component
#ConfigurationProperties("some.server")
public class SomeConfiguration {
private List<String> url;
public List<String> getUrl() {
return url;
}
public void setUrl(List<String> url) {
this.url = url;
}
}
Follow these steps
1)
#Value("${some.server.url}")
private List urls;
2)
#ConfigurationProperties("some.server")
public class SomeConfiguration {
3)
You should have getter and setter for instance variable 'urls'

Resources