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"/>
Related
I have project with Spring configuration in XML file. I added below aspect with pointcut.
<aop:aspectj-autoproxy/>
<aop:config proxy-target-class="true">
<aop:aspect id="customAuditAspect" ref="customAudit">
<aop:pointcut id="customAuditPointcut"
expression="#target(lombok.NoArgsConstructor)"/>
<aop:before pointcut-ref="customAuditPointcut" method="customAuditUpdate"/>
</aop:aspect>
</aop:config>
And this is a bean, which abovementioned pointcut refers to:
<bean id="customAudit" class="com.socha.modules.inspektr.aspect.AuditCustomUpdateAspect"/>
This is class:
#Slf4j
#NoArgsConstructor
public class AuditCustomUpdateAspect {
#Autowired
JdbcTemplate jdbcTemplate;*
public void customAuditUpdate() {
log.warn("here I am");
}
}
When i deploy Web app with this feature, it complains in following way:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'dataSourceAudit'
defined in ServletContext resource [/WEB-INF/spring-context/portlet-application-context.xml]:
Unsatisfied dependency expressed through constructor parameter 0:
Could not convert argument value of type [com.sun.proxy.$Proxy1719]
to required type [com.zaxxer.hikari.HikariConfig]:
Failed to convert value of type 'com.sun.proxy.$Proxy1719
implementing org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,org.springframework.cglib.proxy.Factory,com.zaxxer.hikari.HikariConfigMXBean,org.springframework.core.DecoratingProxy'
to required type 'com.zaxxer.hikari.HikariConfig';
nested exception is java.lang.IllegalStateException:
Cannot convert value of type 'com.sun.proxy.$Proxy1719
implementing org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised,org.springframework.cglib.proxy.Factory,com.zaxxer.hikari.HikariConfigMXBean,org.springframework.core.DecoratingProxy'
to required type 'com.zaxxer.hikari.HikariConfig':
no matching editors or conversion strategy found
Below I am attaching this bean with all its dependent beans:
<bean id="inspektrTransactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate"
p:transactionManager-ref="txManagerAudit" p:isolationLevelName="ISOLATION_READ_COMMITTED"
p:propagationBehaviorName="PROPAGATION_REQUIRED"/>
<bean id="auditHikariCPConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="poolName" value="auditHikariCP"/>
</bean>
<bean id="dataSourceAudit" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg ref="auditHikariCPConfig"/>
</bean>
I understand more or less how is AOP in Spring working. Class HikariDataSource of bean dataSourceAudit implements some interfaces and by default it applies JDK proxying. In above snippet I am trying to apply proxy-target-class=true, but it still fails. I see when I add this setting, that implemented interfaces changes a bit - org.springframework.cglib.proxy.Factory appears, but content of error is still the same. Maybe I am eventually failing to apply this setting on HikariDataSource bean and that's why it is not working?
Thank you in advance for any hints
This particular problem was solved by narrowing scope of the classes to be adviced , as R.G and Kriegaex suggested. Errors stopped occuring
Thank you
Problem:
I'm integrating with a library written by the other team. This library provides a set of classes that I'm using in my Spring-driven application. Every bean in my application is in singleton scope.
Also 99% of the classes from that library uses constructor injection.
I'm using XML and my configuration looks very similar to the following:
<bean id="lib.service1" class="lib.Service1"/>
<bean id="lib.service2" class="lib.Service2">
<constructor-arg ref="lib.service1"/>
</bean>
<bean id="lib.service3" class="lib.Service3">
<constructor-arg ref="lib.service1"/>
</bean>
<bean id="lib.service4" class="lib.Service3">
<constructor-arg ref="lib.service2"/>
<constructor-arg ref="lib.service3"/>
</bean>
<!-- other bean definitions -->
<bean id="lib.serviceN" class="lib.ServiceN">
<constructor-arg ref="lib.serviceX"/>
<constructor-arg ref="lib.serviceY"/>
<constructor-arg ref="lib.serviceZ"/>
<constructor-arg ref="lib.serviceK"/>
</bean>
<!-- other bean definitions -->
What I want:
I want to simplify my configuration to not to use bean IDs and ask spring to do constructor injection for me based on the type of arguments in the bean constructors. I can also ask library implementers to add #Inject annotation to the class constructors (the 99% of the classes have just one public constructor), but this is all that I can ask wrt refactoring of their library.
And eventually I want to have just following in my spring config (doesn't work, but illustrates the idea):
<bean class="lib.Service1"/>
<bean class="lib.Service2"/>
<bean class="lib.Service3"/>
<!-- ... -->
<bean class="lib.ServiceN"/>
Here I'm expecting Spring to figure out that I want to use constructor injection for all those beans and infer bean instances based on the constructor argument types.
Note that I cannot use component scan - they have one package (lib. in the example given above) and some classes in that package are useless for my application and too expensive to be needlessly created. Plus some classes that I'm not using are experimental and can be changed/renamed/removed without prior notice.
Add autowire="constructor", assuming these bean types only have one constructor and that the corresponding parameters match single beans.
<bean class="lib.Service1" autowire="constructor"/>
From the documentation
"constructor"
Analogous to "byType" for constructor arguments. If there
is not exactly one bean of the constructor argument type in the
bean factory, a fatal error is raised. Note that explicit
dependencies, i.e. "property" and "constructor-arg" elements, always
override autowiring. Note: This attribute will not be inherited by
child bean definitions. Hence, it needs to be specified per concrete
bean definition.
I have bean which has to be binded at run time.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="${requiredBean:mysql}"/>
</bean>
<bean id="mysql" class="xxx.xxx.xxxxxx">
</bean>
<bean id="mongo" class="xxx.xxx.xxxxxx">
</bean>
In the property file I added the property
requiredBean=mongo
But due to some reason the requiredBean from the properties file is not picked up by the spring (The properties file is configured correctly and all other properties are loading properly except for this one).
I just want to know if the syntax that I used for declaring the arg for constructor aa ref is right or is there any other way to declare it.
Pls help me to resolve this.
Let me know if the question is not clear.
if you are sure (as you already mentioned in the content of .properties) that you are mentioning the right property(no spelling error), then problem is something else, and not the property itself. Try removing the default value . It must throw exception like :::: java.lang.IllegalArgumentException: Could not resolve placeholder 'XYZ' in string value "${XYZ}". If it does not throw this exception, issue is not related to this bean at all.
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.
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!