Spring Boot Auto-Configuration of object type - spring-boot

I'm probably in a very wrong direction here but failing to see the obvious:
In a Camel component documentation for RabbitMQ (https://camel.apache.org/components/3.18.x/spring-rabbitmq-component.html)
, one can read that we can set auto-config property "camel.component.spring-rabbitmq.message-properties-converter" as "a org.apache.camel.component.springrabbit.MessagePropertiesConverter type".
What does this mean in practice ?
I have tried to set it as a class name (string) of a class that implements org.apache.camel.component.springrabbit.MessagePropertiesConverter : it didn't work (no error, warning or any other evidence the custom class was being used)
I have tried to set it as the name of a bean of a MessagePropertiesConverter it didn't work.
Exactly what should be in a ".properties|yaml" file that can be of "MessagePropertiesConverter type" ?

Related

Missing Converter when using Spring LdapTemplate with Grails Validateable annotation

I'm using the Spring LDAP (docs) library in a Grails application. I have a class annotated with the #Entry annotation, so it is mapped to an LDAP server. This all works quite beautifully.
However, when I add the Grails #Validateable annotation (to enable validating the LDAP class similarly to Grails domain classes) and attempt to retrieve data from LDAP (i.e. a findAll operation on the LdapUserRepo, or similar), I get the following exception:
Message: Missing converter from class java.lang.String to interface org.springframework.validation.Errors, this is needed for field errors on Entry class com.ldap.portal.LdapUser
Basically, it seems like the AST transformation performed by the #Validateable annotation is producing extra fields (namely the errors field) on the LdapUser object. It appears that Spring LDAP, in processing the #Entry logic, assumes a default mapping for the fields property (probably interpreting it as a string field on the LDAP object). When it gets nothing from the LDAP server, it attempts to set the field of type ValidationErrors to a value of type String -- an empty string.
I did some looking in github and found this code that seems relevant and may support my theory.
My question is: is this behavior expected for annotations, and how can one prevent fields added by one annotation from being inappropriately processed by another annotation?
At present the best workaround I've come up with for my specific issue is to add an errors field to my LdapUser object and mark it as transient (so that LDAP ignores it):
#Transient
ValidationErrors errors

Cannot convert value of type [org.springframework.core.env.StandardEnvironment] to required type

I try to upgrade spring from 3.0 to 3.2.8, but I receive the following error
Cannot convert value of type [org.springframework.core.env.StandardEnvironment] to required type [xxx] for property 'environment': no matching editors or conversion strategy found
I guess its some name conflict to an new class StandardEnvironment, but I don't find any place that defines the property 'environment'
Any help please?
It seems that I have a function called setEnvironment which is in conflict with some spring builtin function setEnvironment which is used to set StandardEnvironment when initialize spring framework, so I changed function name to something else, so it worked. really weird problem.
Here is your issue:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'backOfficeContext' defined in class path resource [se/softronic/appia/cache/DomainSpecificEhCacheBeanPostProcessorTest-context.xml]:
The class for bean 'backOfficeContext' contains property BackOfficeEnvironment environment
So, just change the environment property name to something another, or get rid of default-autowire="byName" and just rely on byType by default.

Custom annotation like #Value

I need to create a means to add a custom annotation like
#Value("${my.property}")
However, in my case I need to get the value from a database rather then a properties file.
Basically I would like to create a bean on container startup that reads in property name value pairs from a database and can then inject these into fields belonging to other beans.
Approach #1:
One way is to create an Aspect, with a point-cut expression that matches any method having this annotation.
Your aspect will then:
Read the property value in the annotation
Look up the required value an inject it into the class.
AOP Kickstart
Here's a guide to getting started with AOP in Spring
http://www.tutorialspoint.com/spring/aop_with_spring.htm
Joinpoint matching
Here's a reference that describes how to create a join-point that matches on annotations: http://eclipse.org/aspectj/doc/next/adk15notebook/annotations-pointcuts-and-advice.html
Approach #2:
Another way is to use a BeanFactoryPostProcessor - this is essentially how a PropertyPlaceholderConfigurer works.
It will look at your bean definitions, and fetch the underlying class.
It will then check for the annotation in the class, using reflection.
It will update the bean definition to include injecting the property as per the value in the annotation.
. . actually I think approach #2 sounds more like what you want - all of the processing happens on "start-up". . . (In actual fact your modifying the bean recipes even before startup). . whereas if you used AOP, you'd be intercepting method invocations, which might be too late for you?
Namespace Handler
If you wanted you could even create your own Spring namespace handler to turn on your post processor in a terse way. Eg:
<myApp:injectFromDb />
as an alternative to:
<bean class="MyDatabaseLookupProcessorImpl etc, etc. />
Update: Approach #3
As of Spring 3.1 there's also the PropertySourcesPlaceholderConfigurer, that will provide most of the plumbing for you, so you can achieve this with less code.
Alternatively you should be able to configure kind of properties repository bean and then use it in SpEL directly in #Value annotation.
Let's say you'd have bean called propertiesRepository in your context that implements following interface:
interface PropertiesRepository {
String getProperty(String propertyName);
}
then on bean where you want to inject values you can use following expression
#Value("#{propertiesRepository.getProperty('my.property')}")
String myProperty;
You can use #Value annotation by injecting database configuration in application environment itself.
I know this is an old question but I didn't find an exact solution. So documenting it here.
I have already answered the same on different forum.
Please refer to this answer for exact solution to your problem.

Spring #Value default property is not taken when runing JUnit tests

This is confusing. I have a property outerParameter, which is optionaly given among VM options when starting tomcat. I am using it by the following way in my logic:
#Value("${outerParameter:paused}")
private String featureStatus = "active";
public String getFeatureStatus() {
return featureStatus;
}
When starting tomcat without parameter - getFeatureStatus gives "paused", as expected. When starting with defined parameter - gives this parameter value, as expected.
The confusing part is that when I am runing JUnit tests for getFeatureStatus, it anyway gives me "active" and not the default "paused". The context for tests doesn't contain any <context:property-placeholder../> configuration.
I am trying to understand what I am missing, maybe somebody could give me a hand
I found this:
Spring #Value annotation not using defaults when property is not present
which could be the answer for my case too. It says "Perhaps initialization of property placeholder configurer fails due to missed properties file, so that placeholders are not resolved".
But if so, why it doesn't fail when starting tomcat without defined outerParameter?
Thanks
It means that the property is not loaded in the test case's classpath. Try loading the properties file in the context for test.

How to get property from context property placeholder tag inside custom java component

I have Mule Configuration that defines
<context:property-placeholder location="classpath:/mule-sw.properties"/>
And I also have a custom component class in Java which use #Lookup annotation on one of my field
#Lookup("file-path")
private String path;
Considering my "mule-sw.properties" is like this
file-path=C:/hello.txt
After I start up the Mule App, I always get Deploy Exception
org.mule.api.expression.RequiredValueException: "Required object not found in registry of Type "class java.lang.String" with name "file-path" on object "class component.CustomComponent"
I also tried to change the #Lookup("file-path") with #Lookup("${file-path}") with no success.
Anyone can give me a better solution ?
Any help is kindly appreciated.
Thanks
The #Lookup annotation is designed to retrieve objects from the registry , whereas what you are trying to do is to assign a value to an attribute of your custom component.
There are 2 way to do that:
1) Through property injection, i.e. you declare your component like the following:
<custom-component class="org.myCompany.CustomComponent">
<property name="file-path" value="${file-path}" />
</custom-component>
2) Through Spring EL support and the #Value annotation, i.e. you annotate your attribute in the following way
#Value("${file-path}")
private String path;
I'd recommend the first approach since it is easier to maintain from a flow perspective
#Value("#{'${file-path}'}")
private String path;
Give this a shot. I think you need to wrap it in an EL block #{} for it to be properly recognized.

Resources