Inject properties name into class anotation - spring

Is it possible to inject property name into the procedureName?
im using spring boot.
Try to use the next the next construction:
procedureName = "${procedure}" but it doesnt work
Also to write the special PropertySourcesPlaceholderConfigurer i think it not a good idea .
#NamedStoredProcedureQueries({
#NamedStoredProcedureQuery(name = "test",
procedureName = "${procedure}",
parameters = {
})
})
public class R
try to get property from properties-test.yml

Spring properties used to inject values in bean properties like below,
public class ClassWithInjectedProperty {
#Value("${props.foo}")
private String foo;
}
you case is not valid for value injection.

Related

#ConstructorBinding data class Properties with numbers as names

i'm adding property validation to an existing big project. It has hundrets of webservices and there are some that have simple numbers as names.
Now im trying to write a data class using #Validated, #ConstructorBinding and #ConfigurationProperties.
So imagine a property
dummy.941=http:...
The name of the variable would need to be 941 now, as far as i can tell, but kotlin/java dont allow variable names starting with numbers.
#Validated
#ConstructorBinding
#ConfigurationProperties(value = "dummy", ignoreUnknownFields = false)
data class DummyProperties(
val abc: Abc = Abc(), ....
val 941: Ws941: Ws941()
)
Is there any workaround, some annotation, that says which property is meant? It is not possible to change the name of the property, since the same property database is in use different working systems and people told me thats off the table.
Thanks for any help!
EDIT:
I found a way, spring offers a #Name annotation (org.springframework.boot.context.properties.bind)
#Valid
#Name(value = "703")
val s703: S703 = S703(),
Works like a charm:)
Some time ago, I had a similar issue. You can solve it, at least for Java, by using a custom setter. I have no idea about Kotlin, but I assume it works in the same way for Spring Kotlin.
#ConfigurationProperties(value = "dummy", ignoreUnknownFields = false)
public class DummyProperties {
private Ws941 _941;
public void set941(Ws941 _941) {
this._941 = _941;
}
public Ws941 get941() {
return this._941;
}
}
Spring can map using the setter, so the variable can have a different name.

Evaluate property from properties file in Spring's #EventListener(condition = "...")

I would like to make the execution of an event handler dependent on whether or not a property is set to true in a properties file.
#EventListener(ContextRefreshedEvent.class, condition = "${service.enabled}")
public void onStartup() { }
However, this does not seem to work. I am getting the following error on startup:
org.springframework.expression.spel.SpelParseException: EL1043E:(pos 1): Unexpected token. Expected 'identifier' but was 'lcurly({)'
Is it possible to use a property from a properties file as a condition here?
The issue is condition argument is expecting a SPEL.
This works try it out.
In your bean where you have this #EventListener, add these lines
public boolean isServiceEnabled() {
return serviceEnabled;
}
#Value("${service.enabled}")
public boolean serviceEnabled;
change your declaration of evnt listener like this
#EventListener(classes = ContextRefreshedEvent.class, condition = "#yourbeanname.isServiceEnabled()")
public void onStartup() { }
change yourbeanname with the correct bean name .
I had the same annoying experience (with Spring Boot 2.4.2 on Java11).
In my case I had the boolean property in a #ConfigurationProperties class anyways in the same java file and still struggled a bit. First the #ConfigurationProperties need to be annotated as #Component to actually be a valid Bean and can be used in SpEL.
And I had to use the same long attributeName for the ConfigurationProperties in the Service itself and the EventListener Annotation for the Bean resolution to work fine. I needed some the ConfigurationProperties values also in another place of the Service, that's why they needed to be (Constructor) Autowired as well...
So this worked for me:
#ConfigurationProperties("my.custom.path")
#Component //Important to make this a proper Spring Bean
#Data //Lombok magic for getters/setters etc.
class MyCustomConfigurationProperties {
boolean refreshAfterStartup = true;
}
#Service
#RequiredArgsConstructor //Lombok for the constructor
#EnableConfigurationProperties(MyCustomConfigurationProperties.class)
#EnableScheduling
public class MyCustomService {
private final MyCustomConfigurationProperties myCustomConfigurationProperties;
#EventListener(value = ApplicationReadyEvent.class, condition = "#myCustomConfigurationProperties.refreshAfterStartup")
public void refresh() {
//the actual code I want to execute on startup conditionally
}
}

Spring Data - SpelEvaluationException - Property or field cannot be found on null

I'm trying to use Spring Expression Language to configure an annotation from Spring Data ElasticSearch dynamically. The solutions I tried (this and this) produce the following error in my case:
Caused by: SpelEvaluationException: EL1007E: Property or field
'DbCreatorIndexNameConfig' cannot be found on null
The annotation in question is:
#ComponentScan(basePackageClasses = DbCreatorIndexNameConfig.class)
#Document(indexName = "#{DbCreatorIndexNameConfig.indexName()}", type = "video",
shards = 1, replicas = 0)
public class Video implements EsModel {
//...
The bean in question:
#Configuration("DbCreatorIndexNameConfig")
#ComponentScan(basePackageClasses = Video.class)
public class DbCreatorIndexNameConfig {
#Value("video_default")
public String indexName;
#Bean
public String indexName() {
return indexName;
}
public void setIndexName(String indexName) {
this.indexName = indexName;
}
}
Notes:
I have made sure, that the bean is wired into the application context via new AnnotationConfigApplicationContext(EsSpringTemplate.class, DbCreatorIndexNameConfig.class);
I have made sure that Spring knows the needed beans. They appear in
annotationConfigApplicationContext.getBeanDefinitionNames().
indexName must be a constant. Therefor it seems only possible to use SpEL
Any idea is highly appreciated! Thanks!
Modify it as follows:- You have to use '#' to access a bean in spel
#Document(indexName = "#{#DbCreatorIndexNameConfig.indexName()}", type = "video",
shards = 1, replicas = 0)

how to load property file in to spring boot project with annotations?

I have written queries in property file. I want to read the property file in to one class with annotations in spring boot. How can i read it? And is there any better approach for writing queries in spring boot project?
If you add your properties in application.properties file, you can read them inside the spring boot classes like:
#Service
public class TwitterService {
private final String consumerKey;
private final String consumerKeySecret;
#Autowired
public TwitterService(#Value("${spring.social.twitter.appId}") String consumerKey, #Value("${spring.social.twitter.appSecret}") String consumerKeySecret) {
this.consumerKey = consumerKey;
this.consumerKeySecret = consumerKeySecret;
} ...
You can annotate fields in your components by #Value("${property.name}")
Else, you can use Properties Object in java.util package.
For example, i have a mode property, which values are dev or prod, i can use it in my beans as follow :
#Value("${mode:dev}")
private String mode;
The other approach is by using :
Properties pro = new Properties();
pro.load(this.getClass().getClassLoader().getResourceAsStream());
You can use #PropertySource to read the properties from a file and then pass them to a bean. If you have a file called "queries.properties" that has a property like:
query1: select 1 from foo
Then your config might look like:
#PropertySource("classpath:queries.properties")
#Configuration
public class MyConfig {
#Bean
public DbBean dbBean(#Value("${queries.query1}") String query) {
return new DbBean(query);
}
}

Using Scala classes as DTOs in Spring MVC

In my project I'm using Spring + Scala.
Some of my Spring MVC controllers uses Spring feature for binding incoming HTTP parameters to DTO object. Like this:
#RequestMapping(value = Array("/", ""), method = Array(RequestMethod.POST))
def saveProduct(dto: MyDto): Iterable[MyDto] = {...}
And MyDto is simple scala class:
class MyDto extends Serializable {
#BeanProperty var id : Long = _
#BeanProperty var name: String = _
}
My problem is that I'm getting exceptions when trying to use Scala Option class for fields in MyDto:
class MyDto extends Serializable {
#BeanProperty var id : Option[Long] = None
#BeanProperty var name: Option[String] = None
}
Exception message is:
Failed to convert property value of type 'java.lang.String' to required type 'scala.Option' for property 'name';
What I can do to use Scala Options as type if fields in MyDto?
I am not a Scala expert, but here is one way:
Create a converter, along these lines:
import org.springframework.core.convert.converter.Converter
class TypeToOptionOfTypeConverter[T] extends Converter[T, Option[T]] {
override def convert(source: T): Option[T] = {
Some(source)
}
}
Register this converter with Spring MVC:
class WebConfig extends WebMvcConfigurerAdapter {
override def addFormatters(registry: FormatterRegistry): Unit = {
registry.addConverter(classOf[String], classOf[Option[String]], new TypeToOptionOfTypeConverter[String])
registry.addConverter(classOf[Long], classOf[Option[Long]], new TypeToOptionOfTypeConverter[Long])
}
}
That should be it, now your DTO should get cleanly mapped.
Spring has support for converting types using converters with its data binding. You will need to implement the converter so that Spring knows how to convert, for example, String to Option[String].
See:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html#core-convert

Resources