Spring EL template in a spring bean definition - spring

I have a bean that has a map injected. The entries in the map are of type myBean (see below) and are defined in my spring XML. It may be that not all properties of myBean are defined in the xml, so I thought I would provide defaults in the form of a template where the variable bit in the template is provided by another property that will be present (p1 below). I hope that makes sense.
I am sure there are other ways to achieve this; well, I know there are, but I am new to Spring and I came across Spring EL and it sounded like it was suited to this kind of thing, so I tried this:
<bean id="myDefaults" class="com.myco.MyDefaults">
<property name="prop1" value="abc#{this.p1}def"/>
</bean>
<bean id="myBean" class="com.myco.MyBean" abstract="true">
<property name="theDefaults" ref="myDefaults"/>
</bean>
In MyBean the value of p1 is 100, and I was hoping that the value of theDefaults would be abc100def, but instead I get an error:
Error creating bean with name 'myDefaults' defined in class path resource [myapp-spring.xml]:
Initialization of bean failed; nested exception is
org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is
org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'this' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext'
Thanks for any help
Paul

The variable is #this, not this but in any case, it's not needed in this context, it's implied.
Use value="abc#{p1}def"

Related

Spring bean creation

Is it possible to create to bean with same id with same class with different property in spring ? Like:
<bean id ="a" class= "com.tofek.A"
<property message = "khan"/>
</bean>
<bean id = "a" class = "com.tofek.A"
<property message="tofek"/>
</bean>
As per my understanding it will create, but while fetching the bean using getBean() method it will give exception like NoBeanDefinitionFoundException.
Please correct my understanding if I'm wrong?
Make sure your spring context is loaded sucessfully.
Answering your question. You can have two identical bean definitions in two different sprintContext configurations.
The bean from second context will override bean created by first one.
For example :
context1.xml
<bean id="bean1" class="org.springframework.beans.TestBean"/>
context2.xml
<bean id="bean1" class="org.springframework.beans.TestBean"/>
then, the bean from context2.xml will override bean created by contex1.xml.
It of course depends on order of creating spring contexts. The laters overrides the ones made before.
You can use getBean() to fetch bean by type or name. In this case, both bean have same id's and types, the spring wouldn't know which one you want to fetch.

How to assign java.util.logging.Level to a bean?

I created an application and want to config its logging.Level thorugh bean
<bean id="loggingLevel" class="java.util.logging.Level"> <constructor-arg> <value>INFO</value> </constructor-arg> </bean>
but it failed. Here is the error message:
Unsatisfied dependency expressed through constructor argument with index 1 of type [int]: Ambiguous constructor argument types - did you specify the correct bean references as constructor arguments?
So how to do it the right way?
Instances of java.util.logging.Level are not intended to be instantiated this way, they should be obtained from static fields. In Spring you may use <util:constant>:
<util:contstant id = "loggingLevel" static-field="java.util.logging.Level.INFO" />

Can I use a property placeholder with Spring EL?

Before upgrading to Spring 3 I had this in my applicationContext.xml file:
<bean class="com.northgateis.pole.ws.PolePayloadValidatingInterceptor">
<property name="validateRequest" value="${validateRequest}" />
<property name="validateResponse" value="${validateResponse}" />
</bean>
where ${validateRequest) and ${validateRequest) refer to properties that may or may not be defined in my properties file.
In Spring 2, if these proeprties were not present in the properties file the setters on the bean were not called and so the defaults hard-coded in PolePayloadValidatingInterceptor were used.
After upgrading to Spring 3, it seems the behaviour is different: If the properties are not present in the properties file I get the following exception:
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'annotationMapping' defined in class path resource [com/northgateis/pole/ws/applicationContext-ws.xml]: Could not resolve placeholder 'validateRequest'
at org.springframework.beans.factory.config.PropertyPlaceholderConfigurer.processProperties(PropertyPlaceholderConfigurer.java:272)
at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:75)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:640)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:615)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:405)
at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:272)
I tried dabbling with Spring EL but the following doesn't seem to work:
<bean class="com.northgateis.pole.ws.PolePayloadValidatingInterceptor">
<property name="validateRequest" value="${validateRequest?:true}" />
<property name="validateResponse" value="${validateResponse?:false}" />
</bean>
The value after the Elvis operator is always used, even when the properties are defined in the proeprties file. Interesting that the syntax is accepted.
Any suggestions?
It looks like Spring 3's handling of default values with the Elvis operator was rather broken. This has apparently been fixed (see SPR-7209) in the fresh-out-of-the-oven Spring 3.0.3, and the correct syntax should be the rather baroque:
#{${validateRequest}?:true}
There's no need for Spring EL for setting a default value for a missing property when resolving it with a placeholder configurer. Simply use ${validateRequest:true}. The "Elvis operator" is not concerned with resolving placeholders, it just relies on whatever input the placeholder configurer provides.
See SPR-4785.

Problems overriding a property to null in Spring bean declaration

Just wondering if there is a way in Spring to have a parent controller:
<bean id="parentController" class="org.springframework.web.portlet.mvc.SimpleFormController" abstract="true">
<property name="validator" ref="validatorImpl"/>
...
</bean>
, and a class extending it:
<bean id="child1Controller" class="com.portlet.controller.Child1Controller" parent="parentController">
<property name="validator"><null/></property>
...
</bean>
<bean id="child2Controller" class="com.portlet.controller.Child2Controller" parent="parentController">
...
</bean>
, in such a way that the child overrides a property to null.
I know if you don't declare the property in either the parent or the child, you get the wanted effect, but as in most of the places validator refers to validatorImpl, I thought as a inheritance principle, I would be able to override a property to null.
I keep getting:
15:29:50,141 ERROR [PortletHotDeployListener:534] org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'childController' defined in PortletContext resource [/WEB-INF/context/sugerencia-context.xml]: Initialization of bean failed; nested exception is java.lang.NullPointerException
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'childController' defined in PortletContext resource [/WEB-INF/context/sugerencia-context.xml]: Initialization of bean failed; nested exception is java.lang.NullPointerException
On the other hand,
<bean id="parentController" class="org.springframework.web.portlet.mvc.SimpleFormController" abstract="true">
...
</bean>
<bean id="child1Controller" class="com.portlet.controller.Child1Controller" parent="parentController">
...
</bean>
<bean id="child2Controller" class="com.portlet.controller.Child2Controller" parent="parentController">
<property name="validator" ref="validatorImpl"/>
...
</bean>
Thanks.
Explicitly setting a property to <null/> isn't the same as not setting it. The property's setter method may check that the value you're injecting is non-null, for example.
If you look at the source code for BaseCommandController (which is a superclass of your controller), you'll see that setValidator does no such checking. However, when the bean is initialized in initApplicationContext(), it iterates over the array of validators, assuming they're all non-null, and will throw a NPE if there's a null in that array, which if likely what's happening here.
Unfortunately, there is no way to "unset" a property that has been configured in a parent bean definition. You'll need to rearrange the definitions so that the parent doesn't set it.
I think the problem is in your parent you are either using the validator in either setter method or in afterPropertiesSet. That may be the reason for the NPE. Check it once, if you are not using the validator which in your case is null anywhere in the initialization phases in your parent class, it should work fine.

Spring bean with no id or name

I'm reviewing some Spring code, and I see a few bean defs that do not have an id or a name.
The person who did it is not around to ask.
The application is working fine.
I am not familiar what this necessarily means.
Anybody know if this means anything in particular?
Some beans are not required to be accessed by other beans in the context file or programmatically. So as mentioned by JacobM, they don't require an id or name as they're not referenced.
Such an example would be a PropertyPlaceholderConfigurer, which reads a property file, then allows for runtime property replacement in the context definition.
The example definition would be
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="myapp.properties" />
</bean>
The JavaDoc provides further documentation on this object, but further on in the file you can reference properties from your file by just using the standard template replace placeholder ${...}.
One possibility is that you can define a bean in place, and so you don't need an id since you don't need to refer to it from anywhere else. Say I have a Foo object that takes a Bar property:
<bean id="foo" class="Foo">
<property name="bar">
<bean class="Bar">
</property>
</bean>
The Bar bean doesn't need a name because it's only used to set that one property.
Check the possibility of auto-wiring. An other bean could reference the unnamed bean by having the autowire property set to byType.
This is just a guess. Without a concrete example, I can't say any more.
The id and name attributes are optional and are used to reference the bean definition from other definitions. Look at the official Spring documentation for more detail.
take a look at https://docs.spring.io/spring/docs/4.3.12.RELEASE/spring-framework-reference/htmlsingle/#beans-beanname it says,
You are not required to supply a name or id for a bean. If no name or id is supplied explicitly, the container generates a unique name for that bean. However, if you want to refer to that bean by name, through the use of the ref element or Service Locator style lookup, you must provide a name. Motivations for not supplying a name are related to using inner beans and autowiring collaborators.
Also, Beans such as BeanPostProcessor, BeanFactoryPostProcessor and PropertyPlaceholderConfigurer are automatically detected by application context and typically won't have name
If you consider any spring bean, Spring mandates it to have an identifier. In case, if you have not provided any identifier (via id or name attribute) to a bean in your configuration, you won't run into exceptions. Spring will manage such situation by assigning a default identifier. it has BeanNameGenerator to assign default name. <bean class="com.package.name.TestBean"> will be named as "com.package.name.TestBean" #Bean kind of beans will have its method name as bean name
thus, in your code, for some reason, you can skip naming few beans and the code still works if you are accessing those beans with their default name
credits : https://www.javacodegeeks.com/2013/02/spring-bean-names.html
Beans without id or name can still be referenced by the class name. Spring names those beans automatically using the class name and if there is more than one bean of the same class it appends a number to them.
Anonymous beans are usually defined inside a property tag, but if they're just there maybe there's autowiring configured in some other beans.
Anyway, I think adding a name or id to those beans won't break your application.
As a couple of people mentioned above, not all bean-grabbing is based on name/ID; some of it is based on type. For example, there is a method
BeanFactoryUtils.beansOfTypeIncludingAncestors(...)
that grabs all the beans of some given type. This is used for example by the Spring Web MVC DispatcherServlet (among many other places) to discover beans by type, such as HandlerMappings, HandlerAdapters, HandlerExceptionResolvers and so forth. Contrast this with cases where the bean must have a specific well-known name/ID to be found, such as the LocaleResolver (ID must be "localeResolver" or it won't be found) and ThemeResolver (ID must be "themeResolver" or it won't be found).
Beans defined without name and ID can be accessed with a generated ID (full package name and class name), for example:
bean defined as
<bean class="pl.finsys.initOrder.TestBeanImpl">
can be accessed by
TestBean bean = (TestBean) ctx.getBean("pl.finsys.initOrder.TestBeanImpl");
//Bean Cfg File without Bean id
<bean class="com.ds.DemoBean">
<property name="msg" value="Hello"/>
</bean>
//We can Access
Object obj=factory.getBean("com.ds.DemoBe
its not a mandatory to provide java Bean Id..If we are not providing Bean Id,our Container Provides the Default Been Id.Default Bean Id look like as
"(Package Name).(Bean Class Name)#N"where N=0,1,2,......etc.
It seems there is a subtle difference between unnamed and named bean behaviour. If you have an XML config file imported twice, each named bean will be created only once, but an unnamed bean will be created as many times as its definition is included. When trying to autowire such a bean by type, it leads to errors like this:
No qualifying bean of type [your.class.Name] is defined: expected single matching bean but found 4

Resources