Spring boot : Field names from properties file, and field values at runtime - java

I've a scenario to solve, where I need to maintain some key-value pairs in the code. The key names are to be read from properties file. Which I'm going to do like this in spring boot.
#Data
#ConfigurationProperties( prefix = "project.keysList" )
public class KeyNames {
private String key1Name;
private String key2Name;
...
}
I'll get the corresponding values during the run-time. How can I store the values elegantly ? These are the options I'm considering.
Define one more model object called KeyValues and store them.
Define a hashmap called KeyValues and store the keyNames and corresponding values.
Is there a better way other than these two, where I don't need to define a new object for storing the values, which I get during the run time.?
Appreciate any help in this..
Pls ask for clarifications in case my qn is not too clear.

Define your key and value in resources folder of application.properties file and define #Value annotation in the above your Configuration class of field name.
For example:
application.properties file
key1.name=valuename
key2.name=valuename
============================
#ConfigurationProperties( prefix = "project.keysList" )
public class KeyNames {
#Value("${key1.name}")
private String key1Name;
#Value("${key2.name}")
private String key2Name;
}

#Data
#ConfigurationProperties(prefix = "custom")
public class CustomProperties {
private Long id;
private String name;
private String phone;
}

Related

How to convert a Properties Object to Custom Object using Jackson?

In a Spring Boot application, Spring Boot is used to build a Properties object from a YAML file as follows:
YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();
yamlFactory.setResources(new DefaultResourceLoader().getResource("application.yml"));
Properties properties = yamlFactory.getObject();
The reason why Spring Boot's own parser is used is that it not only reads YAML-compliant settings, but also dot-notated properties like e.g:
artist.elvis.name: "Elvis"
artist.elvis.message: "Aloha from Hawaii"
Now that the Properties object is built, I want to map it into an object like the following for example:
#JsonIgnoreProperties(ignoreUnknown = true)
private record Artist(Elvis elvis) {
private record Elvis(String name, String message) { }
}
My question is:
How can this be done with Jackson? Or is there another/better solution for this?
Many thanks for any help
I saw functionality like that in Ratpack framework.
e.g.:
var propsFileUrl =
Thread.currentThread()
.getContextClassLoader()
.getResource("application.properties");
ApplicationProperties applicationProperties =
ConfigData.builder()
.props(propsFileUrl)
.build()
.get(ApplicationProperties.class);
under the hood it is indeed done by using jackson's object mapper, but the logic is not as trivial to post it here.
here's the library:
https://mvnrepository.com/artifact/io.ratpack/ratpack-core/2.0.0-rc-1
application.yml is the default yml file, so no custom configuration is required. Value annotation should be able to read the properties.
#Value("${artist.elvis.name}")
private String name;
Next part I am not sure about your requirements, but hope this is what you are looking for.
To bind to this object 'constructor' can be a good option.
Class for elvis
#Bean
public class Elvis {
private String name;
private String message;
public Elvis(#Value("${artist.elvis.name"}) final String name, #Value("${artist.elvis.message"}) final String message) {
this.name=name;
this.message=message
}
// getter setter for name and message
}
Now Autowire the created bean to Artist bean
#Bean("artists")
public class Artists {
#Autowired
private Elvis elvis
pubic Elvis getElvis() {
return elvis;
}
}

Spring boot elastic search repository

I have several indices where I save products:
product-example1
product-example2
product-example3
product-example4
product-example5
I have the a document in elastic search that has the same structure and it can used for different indices:
#Data
#org.springframework.data.elasticsearch.annotations.Document(indexName = "", type = "", createIndex = false)
public class ProductDocument {
#Id
private String id;
private String title;
private String seller;
private String releaseDate;
....
}
So basically I want to use same settings, same mappings same search service.
So I made indexName and type parametric in spring boot java, instead of creating 5 classes extending ProductDocument ?
#Autowired
private final ElasticsearchTemplate elasticsearchTemplate;
this.elasticsearchTemplate.createIndex("product-example1", loadFile("/files/settings.json"));
this.elasticsearchTemplate.putMapping("product-example1", "product-type1", loadFile("/files/mapping.json"));
this.elasticsearchTemplate.createIndex("product-example2", loadFile("/files/settings.json"));
this.elasticsearchTemplate.putMapping("product-example2", "product-type2", loadFile("/files/mapping.json"));
......
Now I want to create a ProductRepository but I don't have a class with defined index name. If I use generic class:
public interface DocumentRepository extends ElasticsearchRepository<ProductDocument, String> {
}
I get the error which is totally understable cause I created the index names in dynamic way:
lang.IllegalArgumentException: Unknown indexName. Make sure the indexName is defined. e.g #ProductDocument(indexName="foo")
So is it possible somehow to create repository for indexes that I created in dynamic way as described above, and pass the index name and type as parameter ?
Please help! I'm stuck.

Replacing static String in #Table annotation with external config YAML file

I need to use two different schemas in one java app. For now I'm setting the value with static text:
#Table(name = "jhi_user", catalog = "some_catalog")
#Table(name = "jhi_persistent_audit_event", catalog = "some_other_catalog")
I want to read those values from class marked with #ConfigurationProperties annotation but I don't have any ideas how to do it correctly.
I've tried to create enum with static subclass, but it only works with constant values.
public enum MyData {
DB1(Constants.DB1),
DB2(Constants.DB2);
public static class Constants {
public static final String DB1 = ApplicationProperties.getDb1(); //<--- : attribute value must be constant
public static final String DB2 = "db2"; //<----- works
}
}
Is it any way to change database catalog for different classes without compiling the code? I suppose, I can set it to blank and then change them with reflection, is there a better way?

Spring - Set property value using annotations without using properties file

I have a bean class like, for example
class Sample {
private String message;
public void setMessage(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
}
and I want to set this property's value.
In Xml Configuration, I could do
<bean id = "sample" class = "Sample"
<property name = "message" value = "Hello there!"/>
</bean>
How do I achieve the same thing i.e. set property's value using Java Annotation? Now I have read that we can use #Value annotation using some properties file but cannot it be done without using properties file, doing the way I did it through xml file? Or using properties file is necessary?
I was able to do it by including #Value("Hello there!") above the setter method. But I could feel that is not a good idea. How to set the property values for different instances using Java Annotations?
Thanks.
The value inserted into the #Value can come from places other than a properties file, for example it can also use system properties.
Using the guide here as a starting point should help you understand a little better.
As a basic and mostly useless usage example we can only inject “string
value” from the annotation to the field:
#Value("string value")
private String stringValue;
Using the #PropertySource annotation allows us to work with values
from properties files with the #Value annotation. In the following
example we get “Value got from the file” assigned to the field:
#Value("${value.from.file}")
private String valueFromFile;
We can also set the value from system properties with the same syntax.
Let’s assume that we have defined a system property named systemValue
and look at the following sample:
#Value("${systemValue}")
private String systemValue;
Default values can be provided for properties that might not be
defined. In this example the value “some default” will be injected:
#Value("${unknown.param:some default}")
private String someDefault;
You have a few options, depending on your requirements. In both of these examples you can set the annotation on a setter instead of the field.
Custom PropertySource
This lets you continue using #Value with greater control for how the properties are supplied. There are a large number of PropertySource implementations, but you can always create your own.
References:
How to add custom property source to Spring's Environment
PropertySource JavaDoc
Example:
#Configuration
class MyConfiguration {
#Bean
PropertySource myPropertySource(ConfigurableEnvironment env) {
MapPropertySource source = new MapPropertySource("myPropertySource", singletonMap("myPropertyValue", "example"));
env.getPropertySources().addFirst(source);
return source;
}
}
class Sample {
#Value("${myPropertyValue}")
private String message;
public String getMessage() {
return message;
}
}
String Bean
Define a bean as a String and auto-wire it using its qualifier.
Example:
#Configuration
class MyConfiguration {
#Bean
String myPropertyValue() {
String value;
// do something to get the value
return value;
}
}
class Sample {
#Autowired
#Qualifier("myPropertyValue")
private String message;
public String getMessage() {
return message;
}
}

Setting list from drools decision table

I am using drools for implementing certain condtion.I don't know how to set the
arraylist of the bean in action from drools decision table.For example following is my class.
public class Dog implements Serializable{
private String id;
private List<String> names;
}
My decision table should set the list of names based on the id paseed.How to implement this?
Conditon Action
d:Dog
id ???(what needs to be done here)
1 "tom","jack","pearl"
This can be done in the usual way.
Condition Action
d:Dog d.getNames()
id addAll(Arrays.asList($param))
Match id! Add some names!
1 "tom","jack","pearl"
You'll have to import Arrays or use the full class name.
If you used Spreadsheet File (.xlsx or .xls) then you can try this:
pojo calss:
public class CategoryEntity {
private String type;
private String allAction;
private List<String> actionList; // list
// Getters and Setters
}
And Spreadsheet File like this:

Categories

Resources