Spring Beans - how to wire null as a constructor arg? - java

I have the following bean defined:
<bean id="myBean" class="com.me.myapp.Widget">
<constructor-arg name="fizz" value="null"/>
<constructor-arg name="buzz" ref="someOtherBean" />
</bean>
When I run my app, Spring throws a bean config exception:
[java] Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'myBean' defined in class path resource [spring-config.xml]:
Unsatisfied dependency expressed through constructor argument with index 0
of type [com.me.myapp.Widget]: Could not convert constructor argument value of
type [java.lang.String] to required type [com.me.myapp.Widget]: Failed to
convert value of type 'java.lang.String' to required type
'com.me.myapp.Widget'; nested exception is java.lang.IllegalStateException:
Cannot convert value of type [java.lang.String] to required
type [com.me.myapp.Widget]: no matching editors or conversion strategy found
I just want to create a Widget like I would if I wrote the following Java:
Widget w = new Widget(null, someOtherBean);
How can I do this? Thanks in advance!

You can use Spring's <null> tag:
<bean id="myBean" class="com.me.myapp.Widget">
<constructor-arg name="fizz">
<null />
</constructor-arg>
<constructor-arg name="buzz" ref="someOtherBean" />
</bean>

At times spring fails to inject the values in the ordered you have mentioned into a constructor. It's better if you try with explicit ordering, i.e.
<constructor-arg index="0" name="fizz"><null/></constructor-arg>
<constructor-arg index="1" name="buzz"><ref bean="someOtherBean"/></constructor-arg>

this was, actually, not working for me,
so what I've done is, not passing the object through spring,
but asking "if the object is null", and create New object and assign it to it,
it is also done once (similar to spring),
the difference is that, it is not the best practice, and the creation point of the object is in the flow of the class, and not in early stage.

Related

Error when constructing a spring bean of an object with one Enum, and then a vararg of enums

I have the following object and constructor:
public class Options {
public Options(Enum option, Enum... moreOptions) {
// My code...
}
public Enum build(String nameOfEnum) {
// Creates enum....
}
}
I'm trying to create a spring bean for it using the following xml, based off an answer to another stackoverflow question:
<bean id="myBean" class="com.mypackage.Options">
<constructor-arg value="#{Options.build('firstEnum')}" />
<constructor-arg>
<list>
<value>#{Options.build('secondEnum')}"</value>
<value>#{Options.build('thirdEnum')}"</value>
</list>
</constructor-arg>
<bean>
I just run into the following error, however:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name myBean defined in ServletContext resource [applicationContext.xml]: Unsatisfied dependency expressed through constructor argument with index 1 of type [java.lang.Enum[]]: Could not convert constructor argument value of type [java.util.ArrayList] to required type [[Ljava.lang.Enum;]: Failed to convert value of type 'java.util.ArrayList' to required type 'java.lang.Enum[]'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [java.lang.Enum]: no matching editors or conversion strategy found
I've tried some variations on my current spring config, like having all values in the list, or just creating each value on its own. None seem to work.
How do I correctly create my spring bean?

Spring get FactoryBean property

In Spring, you can get a reference to a FactoryBean using the following syntax:
<constructor-arg ref="&factoryBean" />
This is necessary because if you reference the FactoryBean without the & you will simply get an instance of a bean that the factory produces.
In Spring, you can get a reference to a Bean Property using the following syntax:
<constructor-arg ref="bean.propertyName" />
Now what I need to do is to combine these tactics to get a bean property from a FactoryBean.
I have tried the following syntax with no success:
<constructor-arg ref="&factoryBean.propertyName" />
The above syntax does not work because Spring attempts to reference a bean with the name factoryBean.propertyName

How to create bean of Java class ScheduledThreadPoolExecutor

I'm trying to create the following bean bean
<bean id="couchBaseExecutor" class="java.util.concurrent.ScheduledThreadPoolExecutor">
<constructor-arg name="corePoolSize" value="10"></constructor-arg>
</bean>
but it fails with the exception
13:48:24.206 [main] DEBUG o.s.c.LocalVariableTableParameterNameDiscoverer - ASM ClassReader failed to parse class file [class java.util.concurrent.ScheduledThreadPoolExecutor], probably due to a new Java class file version that isn't supported yet - unable to determine constructors/methods parameter names
java.lang.IllegalArgumentException: null
Does anyone have any idea why?
The core Java classes don't have debug symbols/parameter metadata, so Spring can't determine the name of the constructor arguments. In that case, you have to use the index attribute with value 0 for the first constructor-arg, like this:
<constructor-arg index="0" value="10"/>

Error when creating bean with type java.io.File [Ambiguous constructor argument types]

I have the following spring bean configuration
<bean id="fileBean" class="java.io.File">
<constructor-arg type="java.lang.String"
value="$prop{file.path.property}" />
</bean>
I'm getting the following error
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'fileBean' defined in class path resource [context.xml]:
Unsatisfied dependency expressed through constructor argument with index 0 of type
[java.net.URI]: Ambiguous constructor argument types - did you specify the correct
bean references as constructor arguments?
There is only one constructor for java.io.File with a single String parameter so I'm not sure why this is ambiguous. Any help appreciated.
Found this link that explains what is happening. It turns out that spring will match arguments by type if there is no argument index specified. In this case spring takes my single String argument and passes it to java.io.File constructor that takes TWO strings. This can be fixed by specifying the constructor-arg index.
<bean id="fileBean" class="java.io.File">
<constructor-arg index="0"
type="java.lang.String"
value="$prop{file.path.property}" />
</bean>
Just my two cents here: I had the exact same problem today. I have a unit test to check if Spring can read my XML config and generate all necessary beans. It was failing because I was editing the wrong XML file. I was editing a "dist" version from an Ant build, instead of the correct version from source control.
Lesson learned: Read those Spring exception messages (with XML file paths) very closely!

error passing a value in a bean

I'm getting an error when passing an integer through spring.
<bean id="propConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/application.properties"/>
</bean>
<bean id="portListenerService" class="com.service.portListenerService" scope="prototype" lazy-init="true" parent="abstractService">
<property name="devicePort" value="${devicePort}"/>
</bean>
portListenerService.java:
#Required
public final void setDevicePort(Integer devicePort) {
this.devicePort= devicePort;
}
Is this the correct way to do this? Because I am getting an error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'portListenerService' defined in ServletContext resource [/WEB-INF/service-config.xml]: Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type [java.lang.String] to required type [int] for property 'devicePort'; nested exception is java.lang.IllegalArgumentException: Original must not be null
Even when I hardcode the port instead of pulling it from application.properties, I get the same error. Is some other problem amiss?
Could the devicePort related code be violating javabean spec - like in this discussion?
It may not have anything to do with type of field. Usually this happens when there is a problem with setters, make sure the setter exists with return type void and your fields must start with lower case letter and setter would obviously have camel case for property with 'set' as prefix.
for example; I had the same issue recently and find out that the one of the letter within the property had different case in setter.
<bean name="gateway" class="com.xxxx.yyyy.zzz.MyClass" init-method="init">
...
<property name="stateLogIntervalms" value="${mux.state.log.interval.ms}" />
...
</bean>
definition of property in my class for correct like following;
protected Long stateLogIntervalms;
However definition of setter for incorrect like this;
public void setStateLogIntervalMs(Long stateLogIntervalms) {
this.stateLogIntervalms = stateLogIntervalms;
}
you can notice that the second last letter 'M' is in different case than what I had in xml property and java class.
Happy Coding:)

Categories