I am using Spring Dynamic Modules for the first time. I have tried to expose a service (simple listofValuesDAO Bean) through a bundle and am trying to inject it in another bundle to use the bean.
Below is configuration tag in osgi-context.xml of Bundle1 through which service was exposed:
<osgi:service ref="listOfValuesDAO" auto-export="interfaces"/>
and I am trying to fetch it in Bundle2 through below tag in osgi-context.xml:
<osgi:reference id="listOfValuesDAO" interface="com.dao.IListOfValuesDAO" />
The issue is that when I try to inject it in my bean in Bundle2 using below configuration:
<bean id="exportServiceImpl" class="com.service.impl.ExportServiceImpl">
<property name="listOfValuesDAO" ref="listOfValuesDAO"/>
</bean>
System throws below exception:
Exception in thread "SpringOsgiExtenderThread-85"org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'exportServiceImpl' defined in URL [bundle://325.16:0/META-INF/spring/module-context.xml]:
Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'listOfValuesDAO' of bean class [com.service.impl.ExportServiceImpl]:
Bean property 'listOfValuesDAO' is not writable or has an invalid setter method. Did you mean 'listOfValuesDao'?
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1396)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1118)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
Below is property in my ExportServiceImpl Class:
public class ExportServiceImpl implements IExportService {
IListOfValuesDAO listOfValuesDao;
public void setListOfValuesDao(IListOfValuesDAO listOfValuesDao) {
this.listOfValuesDao = listOfValuesDao;
}
public IListOfValuesDAO getListOfValuesDao() {
return listOfValuesDao;
}
}
Could someone please help me in resolving this issue?
It seems to be a problem with case inconsistency: listOfValuesDao and listOfValuesDAO are different names.
You use the first version in the Service, and the second in the XML bean definition. Try:
<bean id="exportServiceImpl" class="com.service.impl.ExportServiceImpl">
<property name="listOfValuesDao" ref="listOfValuesDao"/>
</bean>
Related
In my applicationContext.xml I have 2 beans with same class and different id(test and test1). The application context gets loaded correctly, but when I add #RequestMapping to one method then the bean creation fails with the below error. This used to work with AnnotationMethodHandlerAdapter but its failing with RequestMappingHandlerMapping and RequestMappingHandlerAdapter.
Error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0': Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping found. Cannot map 'test1' bean method
public java.lang.String com.test.render()
to {[/render],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}: There is already 'test' bean method
Please suggest how to fix this.
Code:
applicationContext.xml
<bean id="test" class="com.abc.test" />
<bean id="test1" class="com.abc.test" />
Controller
#Controller
#RequestMapping( value ={"/test/", "/test1/"})
public class test {
#RequestMapping("render")
public String render ()
{
//some code here.
}
}
You can do it like this...
switch from singleton approach to prototype and inside the xml do
While programmatically define
class P1 {
#Autowire
NotSoSingleton prototypedBean;
}
class P2 {
#Autowire
NotSoSingleton prototypedBean;
}
class P3 {
#Autowire
NotSoSingleton prototypedBean;
}
Would this approach do?
I could find a work around with this. This solution if for the comments I posted on 21-May
I used order property to instantiate the custom defined RequestMappingHandlerMapping in the xml file and it worked!!
It took my custom defined RequestMappingHandlerMapping instead of the default one loaded by <annotation-driven>.
I'm using Google Gson(gson) library form reading/writing json files and spring mvc 3 in my web application side.
So In controller, I want to create a singleton instance of Gson with pretty printing. In java the code would be,
Gson gson = new GsonBuilder().setPrettyPrinting().create();
In Controller, I created an autowired entry as below,
#Autowired
private Gson gson;
and the xml bean configuration is as below,
<bean id="gsonBuilder" class="com.google.gson.GsonBuilder">
<property name="prettyPrinting" value="true"/>
</bean>
<bean id="gson" factory-bean="gsonBuilder" factory-method="create"/>
It throws the following exception in catalina logs,
Caused by: org.springframework.beans.NotWritablePropertyException: Invalid property 'prettyPrinting' of bean class [com.google.gson.GsonBuilder]: Bean property 'prettyPrinting' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:1024)
at org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:900)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:76)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:58)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1358)
I knew that the setter signature of setPrettyPrinting() is different than spring expects, that's why spring is throwing the exception.
public GsonBuilder setPrettyPrinting() {
prettyPrinting = true;
return this;
}
But I'm unable to find a way to wire the builder pattern beans. I'm pretty new to spring. Can any one let me know, whether it is possible to solve this problem in xml bean approach ?
Simply use a static factory method as described in the documentation and use Java code to create Java objects: it's sooo much easier and safe:
<bean id="gson"
class="com.foo.bar.MyGsonFactory"
factory-method="create"/>
and in MyGsonFactory:
public static Gson create() {
return new GsonBuilder().setPrettyPrinting().create();
}
The setPrettyPrinting method doesn't take a parameter, so it doesn't look like a java bean property setter. That's why your approach didn't work. You can use the factory method mentioned in the other answer or use a method invoking bean in the config file like so:
<bean id="myStarter" class="org.springframework.beans.factory.config.MethodInvokingBean">
<property name="targetObject" ref="gsonBuilder"/>
<property name="targetMethod" value="setPrettyPrinting"/>
</bean>
The factory approach seems more straightforward and idiomatic to me, but I include this approach for the sake of completeness.
There are interfaces Work and You. There are implementation types WorkImpl and YouImpl and YouImpl2.
I use constructor autowire to inject a You implementation instance in a WorkImpl instance.
Because there are multiple You implementations types, I thought Spring would throw an exception. But Spring instantiates an instance of one of the implementation types, in my case it was YouImpl. This is what I do not understand.
The configuration file is partly,
<bean
id="work"
class="my.test.own.spring_book.WorkImpl"
autowire="constructor"
>
<property name="age" value="52"/>
<property" name="name" value="Foo Bar"></property>
</bean>
<bean
id="you"
class="my.test.own.spring_book.YouImpl"
>
</bean>
<bean
id="you2"
class="my.test.own.spring_book.YouImpl2"
>
</bean>
WorkImpl has one constructor,
public WorkImpl(You you) {
this.you=you;
}
There are few types of autowiring using configuration approach:
byName
byType
constructor
autodetect:- Similar to byType, but type applies to constructor arguments.
Spring container looks at the constructor of the beans on which autowire attribute is set to byType in the XML configuration file. It then tries to match and wire a property if its type matches with exactly one of the beans name in configuration file.
<bean id="you" class="my.test.own.spring_book.YouImpl">
</bean>
<bean id="you2" class="my.test.own.spring_book.YouImpl2">
</bean>
It will match with you as name of parameter used in constructor is you
public WorkImpl(You you) {
this.you=you;
}
In order to avoid this you can use autowire-candidate="false" hence that bean will not take part in autowiring
<!-- This bean will not be injected-->
<bean id="you" class="my.test.own.spring_book.YouImpl" autowiring-candidate="false">
</bean>
<bean id="you2" class="my.test.own.spring_book.YouImpl2">
</bean>
Above is the answer of your question. But I will try to explain more so I can use this answer for future if I forget.
Now suppose you don't give id attribute to the bean or value of id attribute is different than the constructor parameter name.
<bean id="you1" class="my.test.own.spring_book.YouImpl" autowiring-candidate="false">
</bean>
<bean id="you2" class="my.test.own.spring_book.YouImpl2">
</bean>
Spring container searches any bean with type You, yes found two. Do next step
Spring container sees any bean with name(i.e id="you") you. No
It throws exception Unsatisfied dependency Injection
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'work' defined in class path resource [autowire-contructor.xml]: Unsatisfied dependency expressed through constructor argument with index 0 of type
[my.test.own.spring_book.You]: : No unique bean of type [my.test.own.spring_book.You] is defined: expected single matching bean but found 2: [you1, you2]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException
I have a bean I am trying to configure in Spring context using Constructor injection. When I pass subclass for one of the constructor arguments, the bean is instantiated by Spring container only if I do not specify the "type" attribute. Would anybody have any idea what's wrong? Below are more specifics.
class MyClass{
public MyClass(SomeAbstractBase absObject){
//do stuff
}
}
class ConcreteClass extends SomeAbstractBase{
//
}
Spring configs (First and second do not work but the third one using type attribute works)-
Config I-
<bean id="concreteclass"
class="ConcreteClass"/>
<bean id="myclass"
class="MyClass">
<constructor-arg type="ConcreteClass" ref="concreteclass"/>
</bean>
Config II-
<bean id="concreteclass"
class="ConcreteClass"/>
<bean id="myclass"
class="MyClass">
<constructor-arg type="SomeAbstractBase" ref="concreteclass"/>
</bean>
Config III-
<bean id="concreteclass"
class="ConcreteClass"/>
<bean id="myclass"
class="MyClass">
<constructor-arg ref="concreteclass"/>
</bean>
I get the following exception at initialization-
Exception in thread "main"
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'jedispool' defined in class path resource
[cache-spring-config.xml]: Could not resolve matching constructor
(hint: specify index/type/name arguments for simple parameters to
avoid type ambiguities)
Why would neither of the first or second config work?
Thank you
Type argument accept only the full qualified type (because if not spring cannot determine exactly the package and the type will not match your class):
So you need to use the canonical name of your class to be a type
ConcreteClass => com.your.app.ConcreteClass
A class is not just a name, is a package + name (too be short)
I believe the error you had appeared because you had static nested classes. Here's an SSCCE
package test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) throws Exception {
System.out.println(MyClass.class.getName());
System.out.println(ConcreteClass.class.getName());
System.out.println(SomeAbstractBase.class.getName());
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
}
static class MyClass {
public MyClass(SomeAbstractBase absObject) {
}
}
static class ConcreteClass extends SomeAbstractBase {
//
}
static abstract class SomeAbstractBase {
}
}
With spring.xml containing
<bean id="concreteclass" class="test.Test.ConcreteClass" />
<bean id="myclass" class="test.Test.MyClass">
<constructor-arg type="test.Test.SomeAbstractBase" ref="concreteclass" />
</bean>
The above fails with a UnsatisfiedDependencyException. In this specific example, the class attribute isn't used correctly. The fully qualified class name for ConcreteClass is test.Test$ConcreteClass, not test.Test.ConcreteClass as I've specified. The same applies to MyClass and SomeAbstractBase.
However, specifying test.Test.ConcreteClass in the class attribute for the concreteclass bean doesn't fail because at some point during processing of bean declarations, Spring tries to resolve the class String into a Class object using Class.forName(String). It will call ClassUtils.forName(String, ClassLoader) to do this. Initially it will fail because there is no such class test.Test.ConcreteClass. However, this is done in a try-catch which on ClassNotFoundException will transform the String class name from test.Test.ConcreteClass to test.Test$ConcreteClass and try again. It will work and correctly create a bean of type test.Test$ConcreteClass for your concreteclass bean.
When it tries to create your myclass bean, however, it does not apply such logic for resolving which constructor to use and therefore cannot understand that with the type attribute value of test.Test.SomeAbstractBase, you actually meant test.Test$SomeAbstractBase, so it fails saying the type is ambiguous.
Change your bean declarations to correct types
<bean id="concreteclass" class="test.Test$ConcreteClass" />
<bean id="myclass" class="test.Test$MyClass">
<constructor-arg type="test.Test$SomeAbstractBase" ref="concreteclass" />
</bean>
and it will work.
Take a look at kakawait's answer, you need to specify the fully qualified class name for the bean you are trying to instantiate.
I'm trying to inject a constructor that takes some arguments. After compiling Spring complains it couldn't find a default constructor (I haven't defined it) and throws BeanInstatiationException and NoSuchMethodException.
After defining a default constructor the exceptions don't appear anymore, however my object is never initialized with the argument constructor, only the default one is called. Does Spring really require a default constructor in this case? And if yes, how can I make it use the argument constructor instead of the default one?
This is how I wire everything:
public class Servlet {
#Autowired
private Module module;
(code that uses module...)
}
#Component
public class Module {
public Module(String arg) {}
...
}
Bean configuration:
<beans>
<bean id="module" class="com.client.Module">
<constructor-arg type="java.lang.String" index="0">
<value>Text</value>
</constructor-arg>
</bean>
...
</beans>
Stack trace:
WARNING: Could not get url for /javax/servlet/resources/j2ee_web_services_1_1.xsd
ERROR initWebApplicationContext, Context initialization failed
[tomcat:launch] org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'module' defined in URL [...]: Instantiation of bean failed;
nested exception is org.springframework.beans.BeanInstantiationException: Could not
instantiate bean class [com.client.Module]: No default constructor found; nested
exception is java.lang.NoSuchMethodException: com.client.Module.<init>()
Spring only "requires" a default constructor if you plan on instantiating it without any arguments.
for example, if your class is like this;
public class MyClass {
private String something;
public MyClass(String something) {
this.something = something;
}
public void setSomething(String something) {
this.something = something;
}
}
and you set it up in Spring like this;
<bean id="myClass" class="foo.bar.MyClass">
<property name="something" value="hello"/>
</bean>
you're going to get an error. the reason is that Spring instantiates your class new MyClass() then tries to set call setSomething(..).
so instead, the Spring xml should look like this;
<bean id="myClass" class="foo.bar.MyClass">
<constructor-arg value="hello"/>
</bean>
so have a look at your com.client.Module and see how its configured in your Spring xml
Most probably you are using component-scanning and since you define annotation #Component for class Module it tries to instantiate the bean. You do not need #Component annotation if You are using XML for bean definition.
Just faced the same problem, i guess till now you might have solved the problem.
Below is what you could have changed your bean configuration to,
<bean id="module" class="com.client.Module">
<constructor-arg value="Text"/>
</bean>