I have a spring boot application, say A, which has a bean defined in xml:
<bean class="com.learning.MyBean" name="myBean">
<property name="maxAngle" value="360" ></property>
</bean>
Bean is:
public class MyBean {
#Value("${maxAngle}")
public void setMaxAngle(double maxAngle) {
....
}
}
When I run A independently, all is fine. But when I include it as dependency in another spring boot application, then I get error related to injection of maxAngle:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myBean': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'maxAngle' in value "${maxAngle}"
What can be the issue here?
#Value annotation is used to bind properties defined in application.properties or application.yaml.
Try adding maxAngle=360 to application.properties or application.yaml and remove it from bean XML defination
Related
I have a properties XML file as following :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="sample.findAll">
<![CDATA[
The SQL query goes here
]]>
</entry>
</properties>
And a config file as following :
#ImportResource("classpath:sql/find-all-sample-native-query.xml")
#Configuration
public class SampleFindAllConfig {
#Value("#{sample.findAll}")
private String findAllQuery;
#Bean
public String findAllSampleNativeQuery() {
return findAllQuery;
}
}
I'm injecting the Bean in the DAO class as following :
#Inject
private String findAllAnomalieNativeQuery;
But I get this error when I run my application :
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'sampleDAO': Unsatisfied dependency
expressed through field 'findAllSampleNativeQuery'; nested exception
is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'sampleFindAllConfig': Unsatisfied
dependency expressed through field 'findAllQuery'; nested exception is
org.springframework.beans.factory.BeanExpressionException: Expression
parsing failed; nested exception is
org.springframework.expression.spel.SpelEvaluationException: EL1008E:
Property or field 'sample' cannot be found on object of type
'org.springframework.beans.factory.config.BeanExpressionContext' -
maybe not public?
How can I solve this ?
There are two problems with the code.
Problem 1: Use #PropertySource to load with property values with #Value
#ImportResource imports beans definitions, usually in conjunction with XML Spring configuration.
To load property values for #Value from a configuration file, use #PropertySource.
Problem 2: Reference properties using the ${...} syntax
#{sample.findAll} is a SpEL expression. It asks Spring to evaluate sample.findAll, using sample as a bean. Since there is no bean of that name in the context, Spring rightly complains that there is no such bean.
To load the value of the property sample.findAll from a configuration source, use the syntax ${sample.findAll}.
The following code will work:
#Configuration
#PropertySource("classpath:sql/find-all-sample-native-query.xml")
public class SampleFindAllConfig {
#Value("${sample.findAll}")
private String findAllQuery;
#Bean
public String findAllSampleNativeQuery() {
return findAllQuery;
}
}
How can the Class in a jar file get scanned by the <context:component-scan base-package="" />. I am getting the below error for my autowired class.
SEVERE [localhost-startStop-1] org.apache.catalina.core.ApplicationContext.log StandardWrapper.Throwable
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: org.quartz.Scheduler com.path.controller.MyController.scheduler; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.quartz.Scheduler] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
code:
package com.path.controller;
import org.quartz.Scheduler;
#Controller
public class MyController{
#Autowired
Scheduler scheduler;
}
This scheduler is inside the jar file quartz-oracle-2.1.6.jar and is under WEB-INF\lib. This lib is outside the classes folder of the deployment package. In the applicationcontext.xml i have the below entry,
<context:component-scan base-package="com.path" />
When you export the jar file using the export utility in eclipse there is a option called Add directory entries. Check this option and export the jar file, this will solve the problem
I'm guessing you haven't defined your scheduler bean. You need to first define the bean in order to inject into your controller.
In your applicationcontext.xml first define a bean with type Scheduler.
You might need something like below. Be sure to check out the quartz documentation to check which scheduler you need and how to instantiate it.
<bean id="schedulerFactory"
class="org.quartz.StdSchedulerFactory" />
<bean id="scheduler" class="org.quartz.Scheduler" factory-bean="schedulerFactory" factory-method="getDefaultScheduler" />
As the exception complains "No qualifying bean of type [org.quartz.Scheduler]" , we will have to define the bean of type org.quartz.Scheduler, But that is not possible without any concrete implementation of the same, So , we will have to get a concrete implementation from the Factory class org.quartz.impl.StdSchedulerFactory and it's non static method getScheduler().
Hence, you will have to add following two lines in you context xml file and it will work , I have verified the same with the same version of spring which you are using :
<bean id="schedulerFactory" class="org.quartz.impl.StdSchedulerFactory" />
<bean id="scheduler" class="org.quartz.Scheduler" factory-bean="schedulerFactory" factory-method="getScheduler" />
A console output after printing the initialized bean gives this :
scheduler=org.quartz.impl.StdScheduler#536aaa8d
I have a large Spring Project, whose beans are mostly created via the #Component annotation on classes. I'm slowly tring to move the bean definition to the spring.xml config file.
I however, get a the following error whenever I try to autowire a bean created in the xml config file into a bean created via the #Component annotation.
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ComponentBean' defined in class path resource [spring.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'xmlBean' of bean class [myproject.XmlBean]: Bean property 'xmlBean' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
In my spring.xml:
<bean id="xmlBean" class="myproject.XmlBean" />
Trying to autowire beans into #Component beans as follows does not work:
#Component
class ComponentBean {
#Autowired
private XmlBean xmlBean;
// Bean setters and getters
}
Is there a way by which I could marsh up the two, as I slowly port my bean definitions to the spring.xml config file.
We have a sample app that showcases some things we are doing client side. It pulls in a few internal libraries to get everything functional. It dummies in some hard-coded data so it doesn't have to be concerned with any kind of persistence mechanism.
In some of these libraries that are pulled in, there are spring data jpa repositories. Something like this:
public interface MyLibraryEntityRepository extends JpaRepository<MyLibraryEntity, Long>
{
//...
}
When the server starts up, I get an error like this:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myLibraryEntityRepository': Cannot create inner bean '(inner bean)#788f64f1' of type [org.springframework.orm.jpa.SharedEntityManagerCreator] while setting bean property 'entityManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#788f64f1': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' is defined
It can't find the entityManager, but I don't want to have to use an entityManager. So, in an attempt to override the myLibraryEntityRepository bean, I added the following to my Java config:
#Bean
public MyLibraryEntityRepository getMyLibraryEntityRepository()
{
return myDummyImpl();
}
However, this results in the same error.
Is there any way I can override the bean definition for the spring data jpa repository so that I can use my own dummy implementation and not have to configure an entityManager in my app?
You can use #Bean(name="dummyBean") and the in the #Autowired use the annotation #Qualifier("dummyBean")
My XML configuration includes these bean definitions:
<bean id="abstractFormAction" class="staffing.server.action.form.AbstractFormAction" abstract="true" parent="baseAction">
<property name="volunteerSaver" ref="volunteerSaver"/>
<property name="emailSender" ref="emailSender"/>
<property name="closed" value="${form.closed}"/>
</bean>
<bean id="volunteerFormAction" class="staffing.server.action.form.VolunteerFormAction" parent="abstractFormAction">
<property name="captchaGenerator" ref="captcha"/>
</bean>
Indicating that VolunteerFormAction is a concrete implementation of AbstactFormAction, and will inherit the properties of AbstactFormAction.
In AbstractFormAction, I declare the properties like this:
#Autowired protected VolunteerSaver volunteerSaver;
#Autowired protected EmailSender emailSender;
#Autowired protected boolean closed;
I get the following exception when I try to deploy:
org.springframework.beans.factory.BeanCreationException: Error
creating bean with name 'volunteerFormAction': Injection of autowired
dependencies failed; nested exception is
org.springframework.beans.factory.BeanCreationException: Could not
autowire field: protected boolean
staffing.server.action.form.AbstractFormAction.closed; nested
exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
matching bean of type [boolean] found for dependency: expected at
least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
It seems to be complaining that it cannot find a bean of byte boolean. But why would it want a bean when have defined property 'closed' by value, not by reference?
You need to use #Value annotation for passing values using property place holders. #Autowire expects a bean of the specified type to be present in the applicationContext.
If you are autowiring the values why are you passing the values int he bean definition? I think what you need is
<bean id="abstractFormAction" class="staffing.server.action.form.AbstractFormAction" abstract="true" parent="baseAction"><bean>
<bean id="volunteerFormAction" class="staffing.server.action.form.VolunteerFormAction" parent="abstractFormAction">
<property name="captchaGenerator" ref="captcha"/>
</bean>
and
#Autowired protected VolunteerSaver volunteerSaver;
#Autowired protected EmailSender emailSender;
#Value("#{form.closed}") protected boolean closed;
If you can use component-scan you need not even specify create the beans
You can add <context:component-scan base-package="<your base package>"/> to your context.xml file and add the annotation #Controller to your controller file
You shouldn't annotate closed with #Autowired.
#Autowired instructs Spring to look up a bean of the type of the autowired field (boolean) in your context, that's why it's complaining about "No matching bean of type [boolean]"
If you inject the value from xml config, there is no need for any annotation on that field.
Based on the code you've shown, it's likely that you have a problem in the way you're loading your Spring contexts. My guess is that you're incorrectly component-scanning your controllers in both the root web application context and in the child context where the controllers are supposed to live. That means there are two instances of this class being created, and only one of them is being configured via the XML. Spring is attempting to autowire the other instance and failing with the given error. You'll find descriptions of the problem and solution in several other SO answers, like these:
Declaring Spring Bean in Parent Context vs Child Context
Spring XML file configuration hierarchy help/explanation
Spring-MVC: What are a "context" and "namespace"?
If you give more detail about your config files and context configuration, someone might be able to point out exactly where you're going wrong.