Where in the Spring documentation is referencing beans from SpEL expressions explained? - spring

I've looked up the documentation on SpEL, but I couldn't find an explanation for the following SpEL expression:
#{#someBean}
Or
#{#someBean.property}
I've seen it used in a few examples and in some SO answers, but I can't find where this behavior is documented. Or I overlooked it (multiple times).
Please point me in the right direction.

It depends of the context. If you are going to use bean reference during the configuration phase and use those #{} templates, then you don't need a bean reference operator: the BeanExpressionContext does direct BeanFactory access via its:
#Nullable
public Object getObject(String key) {
if (this.beanFactory.containsBean(key)) {
return this.beanFactory.getBean(key);
}
else if (this.scope != null) {
return this.scope.resolveContextualObject(key);
}
else {
return null;
}
}
This is what Spring Framework prepares for us in its EmbeddedValueResolver.
If you parse expressions yourself at runtime and use something like StandardEvaluationContext, then you indeed need a bean reference operator (#) to reach your bean via BeanFactoryAccessor.

Related

#Bean method requires to return null conditionally

I have basic authentication enabled in my system and now I am trying to integrate the SAML auth using Spring-security-SAML. I have created a method that returns the RelyingPartRegistrationRepository bean. In a condition While the user-configured values are not sufficient to Create the RelyingPartRegistration, I would have to either create a RelyingPartRegistrationRepository with Empty array which is not possible because there are checks to be not empty. another option is to return null from the Bean method. which is also a failure case because context initialization will fail in that case. All I want is to either not initialize this bean or at least not prevent context initialization. So that I can at least switch back to Basic Authentication.
You can use #ConditionalOn... to selectively enable/disable particular beans, based on things like properties
class MyConfiguration {
#Bean
#ConditionalOnProperty(name = "saml-enabled", havingValue = "true")
public RelyingPartRegistrationRepository() { ... }
}
See this article on Baeldung, and another article which covers a few other conditionals which may be useful, and of course the official documentation.

Spring prototype following prototype design pattern

Spring provides bean scope as "Prototype". Means whenever bean is required in application, Spring container will create a fresh/new instance of bean.
Does is follow prototype design pattern also?
Does it create object only once and in subsequent request calls clone() method on created object to create new object?
Also if someone can provide example of prototype in JDK, Spring, Hibernate or any J2EE framework.
No spring does not use cloning to create prototype scoped instances.
Below is the code snippet taken from AbstractBeanFactory.doGetBean() function:
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
#Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
The createBean method call boils down to below code:
BeanUtils.instantiateClass(constructorToUse);
Spring does not use the Prototype Pattern, it uses reflection.
Plus, in order to use clone() it would have to subclass somehow a bean, because clone() is protected, so it does not use clone() either.
Here is a code fragment from
org.springframework.beans.factory.support.SimpleInstantiationStrategy
where you can see the use of java.lang.reflect.Constructor and java.lang.Class reflection method:
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
if (beanDefinition.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (beanDefinition.constructorArgumentLock) {
constructorToUse = (Constructor<?>) beanDefinition.resolvedConstructorOrFactoryMethod;
...
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
...
}
...
}
...
}
So the term prototype is used to suggest that at every call to getBean, you'll get a new instance with the same properties. This is more than a simple call to a constructor however, because you'll get a bean with all dependencies wired and other properties set, so in a sense it is a prototype. Or at least it fits the concept very well.
I have not dug into Spring source code, but I think Beans with prototype scope in Spring are not created using clone() method because it is not mandatory to implement the Cloneable interface for those beans.
Moreover, suppose it is creating them using clone(). It would then be dangerous if someone is expecting deep copy instead of shallow copy.
You can always test it and find the answer.
No. Spring scopes such as prototype or singletone do not follow strictly design patterns. The naming of scopes was used to intuitively suggest behavior container provides.
This way you can have a "singleton" pattern within the container and create another object outside of the container. Similarly "prototype" pattern does not have to implement "clone" functionality.
You may want to look into this link as well: Singleton design pattern vs Singleton beans in Spring container
More elaborate explanations here:
https://springframework.guru/gang-of-four-design-patterns/prototype-pattern/

Using #Profile annotation with property place holder value

When we define profile for any component in spring, we declare it as
#Profile(value="Prod"). But i want to give that value from properties file.
Is it possible? If yes, how?
Going through the source code of Spring, I have arrived to the conclusion that what you are asking is not possible. To make this clear, it is not possible to have Spring evaluate ${property} inside #Profile.
Specifically take a look at ProfileCondition which checks whether or not the profile is active.
class ProfileCondition implements Condition {
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
if (context.getEnvironment() != null) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
return true;
}
}
return false;
}
}
return true;
}
}
The meat is context.getEnvironment().acceptsProfiles(((String[]) value)).
Now if you check the source of AbstractEnvironment where acceptsProfiles resides, you will find that the control reaches
protected boolean isProfileActive(String profile) {
validateProfile(profile);
return doGetActiveProfiles().contains(profile) ||
(doGetActiveProfiles().isEmpty() && doGetDefaultProfiles().contains(profile));
}
which does not attempt to evaluate the expression, but takes the String verbatim (also note that nowhere before isProfileActive is the String expression being evaluated either)
You can find the code I have mentioned above here and here.
One another note, I am not sure why you would need to have a dynamic profile name.
You seem to be trying to abuse the #Profile annotation. Use profiles for enabling functionality. Not for saying that a Bean is active in a specific environment.
A way to achieve something closer to what I think you are looking for, would be to have properties files specific to your environment, which define the profiles which should be active in them. This way, you can start your app with an arg such as:
--spring.profiles.active=prd
Spring Boot will then attempt to load application-prd.properties, where you could activate environment-specific profiles:
spring.profiles.active=sqlserver,activedirectory,exchangeemail
That way your beans will only be activated when the functionality they provide is required.
An alternative would be when creating the ApplicationContext:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigClass.class);
String profile = aplicationContext.getEnvironemnt().getRequiredProperty("profile");
applicationContext.getEnvironment().setActiveProfiles(profile);

spring security : Why can't we access Hibernate entitiy parameters in #PreAuthorize?

I have the following interface method on which I am applying #PreAuthorize :
#PreAuthorize("doSomething(#user.id)")
void something(User user, List<User> accessList);
where User is a Hibernate entity object. It gives me an error :
org.springframework.expression.spel.SpelEvaluationException:
EL1007E:(pos 13): Field or property 'id' cannot be found on null at
org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:204)
There is no way that the user parameter is null, as if I remove the annotation, and inspect the value of user in the method that implements this interface method, there is a valid User object present there. Additionally, just before calling this method, I have made sure that the user object is correctly constructed.
I really can't figure out why would the user field be considered null by the SPEL parser
You can check with the debugger what's going on in MethodSecurityEvaluationContext, inside Object lookupVariable(String name) method:
#Override
public Object lookupVariable(String name) {
Object variable = super.lookupVariable(name);
if (variable != null) {
return variable;
}
if (!argumentsAdded) {
addArgumentsAsVariables();
argumentsAdded = true;
}
and so you can see what's really going on in the addArgumentsAsVariables() method as the convertion of method arguments to SPEL variables is implemented very clearly in Spring.
Spring Security has a better answer for this problem now:
http://docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/reference/htmlsingle/#access-control-using-preauthorize-and-postauthorize
Basically, you can use the #P annotation or #Param annotation if you are using < JDK 8.
You can check LazyParamAwareEvaluationContext,inside loadArgsAsVariables() method, version 3.1.0.
The same key for different Entity, because of implementing interface.
I need to add something to this as the title indicates that we cannot access hibernate properties.
There are two editions of hasPermission, the loaded object and the serialized object. Here is some code from a test case:
#PreAuthorize("isAuthenticated() and hasPermission(#organization, 'edit')")
public long protectedMethod(Organization organization)
{
return organization.getId();
}
And for the latter here we see that we can infact access the id proprty of the organization (which is a hibernate entity):
#PreAuthorize("isAuthenticated() and hasPermission(#organization.getId(), 'organization', 'edit')")
public long protectedMethodSerializableEdtion(Organization organization)
{
return organization.getId();
}

Need help creating a specific pointcut inside of a method

I started with an original question on
Need help creating a specific pointcut that utilizes a value from a method annotation
I decided I wanted to ask another question to change the approach I was taking.
I have a method (navigation), that has a call inside of that method to another method which I would like to have #Around advice.
#RequestMapping(method = RequestMethod.GET)
public String navigation(ModelMap model) {
...
// Call Auto Handling
logger.info("Call AutoHandling");
this.processAutoHandling(callSession, FunctionalArea.PRE_MAIN_MENU);
}
...
return forward(returnView);
}
Is this possible as I cannot seem to get this to work if the method is inside of the same class.
This work if it was not on the object itself:
#Around("execution(* *.processAutoHandling(..)) &&" +
"args(callSession, functionalArea) && " +
"args(functionalArea) && " +
"target(bean)"
)
public Object processAutoHandlingCall2(ProceedingJoinPoint jp,
CallSession callSession,
FunctionalArea functionalArea,
Object bean)
throws Throwable {
logger.debug("processAutoHandleCall");
return jp.proceed();
}
With this call in my controller:
autoHandlingComponent.processAutoHandling(callSession, FunctionalArea.PRE_MAIN_MENU);
instead of
this.processAutoHandling(callSession, FunctionalArea.PRE_MAIN_MENU);
It seems that you are using Spring's proxy-based AOP. If so, this is a known limitation. See Understanding AOP Proxies from Spring documentation for more details. You have two ways to solve this issue:
Use the AopContext.currentProxy() approach outlined in the documentation. I will discourage this approach, since your code will now be tied to Spring AOP quite explicitly.
Use AspectJ's byte-code weaving. Since there is no proxy involved with it, you won't have the issue with 'this' pointing to original object and proxy is transparently available only to external objects.

Resources