Spring Framework: Is there a list of "reserved words" or "Predefined Variables" about SpEL? - spring

For Spring Framework where is the complete list of reserved words or Predefined Variables about SpEL with their respective explanation? It such as for:
environment
systemProperties
systemEnvironment
For example in this valuable tutorial is just shown the 2 latest of the list shown above
Spring Expression Language (SpEL) Predefined Variables
Consider if Spring 6 added more of them, it as an improvement, therefore could be more.
Yes, I did do a research - currently for version 6 - at the official documentation at:
Spring Expression Language (SpEL)
But does not contain the reserved words.

There isn't really a list of reserved words for SpEL like what you are looking for, at least not in generic SpEL parsing and evaluation.
There is default SpEL support in the application context and notably in #Value annotations, as documented in the reference guide: Expressions in Bean Definitions.
Thi is provided via a SpEL StandardEvaluationContext which uses the beanFactory as the root object. Or rather, it uses a BeanExpressionContext view of the bean factory plus a dedicated PropertyAccessor is added to this evaluation context so that every beanName in the bean factory is considered a property of that root object during evaluation.
As a result, if a bean named foo is registered in the factory, #Value("#{ foo }") will be interpreted as "the property foo of the root object", which resolves to the aforementioned bean.
So systemProperties/systemEnvironment and environment are not really predefined SpEL variables, but rather standard beans in an AbstractApplicationContext.

Related

How to load a bean only if the property value is other than a fixed value

I am facing a situation in which a bean should be created by the application context only if the property contains any other value than a specific value.
i.e... one property file.path= /specific/path, If the value is other than this then bean should be loaded.
I can see that there is #ConditionalOnProperty (name="file.path", havingValue="....") out of the box but in my case, I am looking a property like havingValueOtherThan="..." or similar kind of property or annotation if it is there out of the box in the spring.
There are many possible options, besides profiles that were stated in comments, here are 2 options:
Option 1
Use #ConditionalOnExpression with any SPeL expression you wish
Option 2
You can always create your own conditional annotation with any logic:
Create an annotation that will depict your own business case with a #Conditional on it.
Then Implement the conditional logic of your choice. Here is an example of achieving this.
BTW, the profiles that mentioned in comments are using Conditionals engine under the hood (The #Profile annotation has a #Conditional({ProfileCondition.class}) in its definition since Spring 4.x)

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.

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.

Calling static methods from Spring Security Expressions?

I'm looking for a way to extend Spring Security Expressions to support an existing security infrastructure. I'm aware you can extend the MethodSecurityExpressionRoot as described here, but I also found reference to directly calling static methods through Spring Expression Language (Spring EL or SpEL). Unfortunately the official page on Spring Expression methods doesn't directly describe how to do this.
How can I invoke a static method through Spring Expression methods?
By using the T(fully.qualified.name).methodName() syntax:
You can use the special T operator to specify an instance of java.lang.Class (the type). Static methods are invoked by using this operator as well. The StandardEvaluationContext uses a TypeLocator to find types, and the StandardTypeLocator (which can be replaced) is built with an understanding of the java.lang package. This means that T() references to types within java.lang do not need to be fully qualified, but all other type references must be.
The T element returns a reference to the type instead of an instance. For example, the equivalent of Collections.singleton("Hello") is
T(java.util.Collections).singleton('Hello')

Injecting Spring Spel Expressions into bean properties

How can I inject a String meant to be a spel expression into an app context bean property without having the context interpret the string property as a spel resolvable value.
<bean id="x" p:spelExpression="${#code}/${#value}"/>
I want the the class's setter property to take a string argument and creates a reusable SpelExpression as a private property of the bean, however, the spring application context appears to be recognizing the #variableName as spel expressions and attempting to interpret the expression at initialization time.
I find Spel interpretation to be very useful, but would like to to use spel internally as well, with expression injection into my own beans.
Is it possible to disable the Spel Interpretation of for a bean, or even for a whole context file (maybe with some namespace shenanigans) without having to disable or modify spel expression resolution for the whole application context.
The #{...} are markers for spel interpreter in xml context.
I don't undestand : ${#code}/${#value}. Good is #{code/value}, as I understand things, if code and value are id.
So, if you want a spel expression without interpret it, put string code/value in xml.

Resources