Can I use Spring Expression Language in an "alias" definition? - spring

I am trying to create an alias in a spring context config like this:
<alias name="#{ ... code to lookup from config file ...}" alias="BeanName"/>
but it doesn't seem to execute the EL in the "name" attribute. Is this not allowed?

It's not that it's not allowed, it's that there is no registered BeanExpressionResolver for aliases. You can use property placeholders ${}, but that's a whole different component that handles it.

Related

When using ConfigurationProperties with a camelCase prefix, how do I solve "Prefix must be in canonical form"?

I had a property configured in my yml as
foobar:
baz: 7
and a configuration class annotated with
#ConfigurationProperties(prefix = "foobar")
and everything was working fine.
The code in my organization is generally camelCase, so I renamed both the property and prefix to fooBar. IntelliJ is now highlighting the prefix = "foobar" line with the error, "Prefix must be in canonical form". What can I do, while keeping camelCasing in the yml config?
Spring Boot supports multiple formats of property names, but encourages you to access them in a canonical way.
Per Property Binding in Spring Boot 2.0:
It turns out the idea of relaxed property names is much easier to implement if you restrict it to one direction. You should always access properties in code using a canonical form, regardless of how they are represented in the underlying source.
The ConfigurationPropertyName class enforces these canonical naming rules, which basically boil down to “use lowercase kebab-case names”.
So, for example, you should refer to a property in code as person.first-name even if person.firstName or PERSON_FIRSTNAME is used in the underlying source.
You can keep your config yml in camel case:
fooBar:
baz: 7
but change the access in the configuration class annotation to use kebab-case:
#ConfigurationProperties(prefix = "foo-bar")

How does Spring Data JPA resolve property name containing single letter abbreviation for a word in query methods?

I've an entity with property name qYear. I tried creating a findByIdAndQYear method in repository but that did not work. I ran into IllegalArgumentException: Unable to locate Attribute with the the given name [QYear] on this ManagedType).
However findByIdAndqYear works. Any idea how single letter abbreviations like this are expanded please?
Spring Data (not just the JPA module) base this on the Java Bean Specification.
In order to avoid misinterpretation of the specification this is actually implemented using [java.beans.Introspector][1].
See also https://jira.spring.io/browse/DATACMNS-1589

JAX-WS and curly braces syntax

All over the Internet I find code examples of JAX-WS beans being defined in this fashion:
<jaxws:client name="{http://cxf.apache.org/}MyService" createdFromAPI="true">
What is the meaning of the curly braces here exactly?
You might need to specify individual examples of where you've seen it, but from what you've shared here, this seems to be erroneous use of that naming convention.
See, the schema for the Spring-CXF XML configuration document supports two types of "name" attributes:
name: use this to name just the bean within the spring context - treat it no differently as you would adding id to a spring bean. No need for a namespace or prefixing of any kind
serviceName: this name should come from the WSDL as part of the name attribute from the definitions root element. It's this one that uses the QName format - what you have here as {http://cxf.apache.org/}MyService which the CXF API will try to match with what's in the WSDL of the SOAP service you're consuming.
TL;DR: that naming convention with the URL prefix doesn't belong on the name attribute but on the serviceName attribute and its value ought to come from the WSDL file.

How to find out if a property is defined in placeholder in Spring?

Due to some backward compatible reasons, some old apps didn't define a new property in its app.properties, which is referred in a shared Spring context.xml thru placeholders. Is there a way in Spring to find out if a property is defined in the placeholder?
There are posts about setting null default values using Spring expression language. But, I don't see an answer on how to determine if a property is defined in the placeholder, or you'd get "Could not resolve placeholder ...".
I'm looking for something like
<constructor-arg value="#{someAPI('my.new.prop') ? ${my.new.prop} : #null}" />
Your input is highly appreciated!

How to disable interpolation of property values in property placeholders

I'm using Spring 3 and Spring's property-placeholders in my application context:
<context:property-placeholder location="my.properties"/>
my.properties contains:
key1=value1
key2=some JSP code ${some-model-attr}
The issue is, the values in my.properties are also evaluated against the placeholders, but in my case the values contain JSP EL, which causes "property not found" errors during Spring initialization:
java.lang.IllegalArgumentException: Could not resolve placeholder 'some-model-attr'
So far I have this workaround, but it's ugly:
key1=value1
key2=some JSP code #{'$'}{some-model-attr}
Hence my question:
Is it possible to tell Spring not to interpolate property placeholder values, or, in other words, not to evaluate placeholders recursively?
It looks like it isn't possible to tell Spring not to recursively evaluate placeholders.
The placeholders are evaluated by org.springframework.util.PropertyPlaceholderHelper which (in Spring 3) contains the following line:
// Recursive invocation, parsing placeholders contained in the placeholder key.
placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
So the recursive call is hard-coded into the evaluation.
However I think you could change the default prefix and suffix for placeholders so that you use a different syntax for Spring placeholders. <context:property-placeholder> is just a convenient way of constructing the org.springframework.beans.factory.config.PropertyPlaceholderConfigurer class, and that class has methods setPlaceholderPrefix() and setPlaceholderSuffix(). You could use those methods to change the syntax of the Spring placeholders to something like:
$[property]
instead of
${property}
Then I expect Spring won't parse your JSP properties any more because they're in a different syntax:
key2=some JSP code ${some-model-attr}
As a workaround you can use SpEL expression templating. For example:
key2=some JSP code $#{'{some-model-attr}'}
This works because Spring no longer sees the configured property placeholder prefix of ${. However, the SpEL expression evaluates to the String concatenation of:
'some JSP code $' + '{some-model-attr}'
which is the same as
some JSP code ${some-model-attr}

Resources