package com.mkyong.output;
IOutputGenerator.java
public interface IOutputGenerator
{
public void generateOutput();
}
package com.mkyong.output;
OutputHelper.java
#Component
public class OutputHelper {
#Autowired
IOutputGenerator outputGenerator;
public void generateOutput() {
outputGenerator.generateOutput();
}
/*//DI via setter method
public void setOutputGenerator(IOutputGenerator outputGenerator) {
this.outputGenerator = outputGenerator;
}*/
}
package com.mkyong.output.impl;
CsvOutputGenerator.java
#Component
public class CsvOutputGenerator implements IOutputGenerator {
public void generateOutput() {
System.out.println("This is Csv Output Generator");
}
}
SpringBeans.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="com.mkyong" />
</beans>
i am getting this exception Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'OutputHelper' is defined
even though i have marked OutputHelper as component.
I have changed
OutputHelper output = (OutputHelper) context.getBean("OutputHelper");
to
OutputHelper output = (OutputHelper) context.getBean("outputHelper");
and it worked.
Hi i think you haven't added following in your Spring XML configuration
xmlns:mvc="http://www.springframework.org/schema/mvc"
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
<mvc:annotation-driven/>
you need to see top exception and read the whole line.
i guess there have a exception is nested exception just like #Autowired xxxxxx,meas autowired fail.
i have notice this:
#Autowired
IOutputGenerator outputGenerator;
and
#Component
public class CsvOutputGenerator implements IOutputGenerator
so, in the default, class name is used to #Autowired,you can rewrite to
#Autowired
IOutputGenerator csvOutputGenerator;
notice:
"csvOutputGenerator" first letter is lowercase
the easier option would be to enable annotations in beans already registered in the application context, means that you can just use #Autowired instead of getting manually all beans with context.getBean()
just add this line to your SpringBeans.xml
<context:annotation-config>
if you really want to understand what you are doing reading this could help.
Related
I have tennisCoach object created by Spring framework:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml") ;
Coach theCoach = context.getBean("tennisCoach", Coach.class);
Can't understand why I need #Autowired annotation in TennisCoach constructor in code below. It works fine with and without #Autowired annotation.
#Component
public class TennisCoach implements Coach {
private FortuneService fortuneService;
#Autowired
public TennisCoach(FortuneService theFortuneService) {
fortuneService = theFortuneService;
}
#Override
public String getDailyWorkout() {
return "Practice your backhand volley";
}
#Override
public String getDailyFortune() {
return fortuneService.getFortune();
}
}
UPD
Content of applicationContext.xml :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.luv2code.springdemo"></context:component-scan>
</beans>
From #Autowired Javadoc:
If a class only declares a single constructor to begin with, it will always be used, even if not annotated.
Since Spring 4.3 you don’t need the #Autowired annotation as soon as you have the only constructor in your class.
Here #Autowired is used for constructor injection. TennisCoach has a dependency on FortuneService and it is injected through constructor. I'm not sure how you have configured beans in applicationContext.xml
I'm guessing something is wrong integrating my spring and camel contexts.
I'm unit testing a Camel Component, and I'm trying to inject a bean (MainframeEncoderProvider) generated by spring component-scan. I can see that the bean is being constructed (breakpointing an init block), and I can autowire it into ToFalinkProducerTest, but it's not getting into the camel Component. The component is instantiated via META-INF auto-discovery, if that's relevant (http://camel.apache.org/how-do-i-add-a-component.html)
Test class setup:
#RunWith(CamelSpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath*:spring-config/testContext.xml"})
public class ToFalinkProducerTest extends CamelTestSupport{
[some tests...]
#Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
public void configure() {
//#formatter:off
from("direct:start")
.to("tofalink:x?encoderName=test")
.to("mock:result");
//#formatter:on
}
};
}
testContext:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
">
<!-- lightweight testcontext -->
<context:annotation-config/>
<context:component-scan base-package="net.mo"/>
<camel:camelContext>
<camel:contextScan/>
</camel:camelContext>
</beans>
component:
/**
* Represents the component that manages {#link ToFalinkEndpoint}.
*/
public class ToFalinkComponent extends DefaultComponent {
#Autowired
private MainframeEncoderProvider provider;
protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception {
Endpoint endpoint = new ToFalinkEndpoint(uri, this);
setProperties(endpoint, parameters);
return endpoint;
}
protected MainframeEncoderProvider getProvider() {
return this.provider;
}
}
Managed to fix this, after a lot of faffing around. Replaced CamelTestSupport extension with CamelSpringTestSupport, and dropped #RunWith and #ContextConfiguration. Implemented createApplicationContext() with my xml spring context file, to retain the component scanning.
left the auto-discovery mechanic in place.
Now I just have to see whether it works at runtime :/
My application uses struts and spring frameworks. I have a class FormA which has an autowired property in it. When I try to instantiate it while writing unit tests I get a Null Pointer Exception. Here is my code.
My ClassA:
public class FormA{
private String propertyOne;
#Autowired
private ServiceClass service;
public FormA(){
}
}
My unit test method:
#Test
public void testFormA(){
FormA classObj = new FormA();
}
#Autowired only works when object life cycle is managed by Spring.
You'll need to run your tests with #RunWith(SpringJUnit4ClassRunner.class), and instead of instantiating FormA manually, inject it in the test class as well, using #Autowired.
When you create an object by new, autowire\inject don't work...
as workaround you can try this:
create your template bean of NotesPanel
<bean id="notesPanel" class="..." scope="prototype">
<!-- collaborators and configuration for this bean go here -->
</bean>
and create an istance in this way
applicationContext.getBean("notesPanel");
PROTOTYPE : This scopes a single bean definition to have any number of object instances.
anyway a unit test should be
Test class
#RunWith( SpringJUnit4ClassRunner.class )
#ContextConfiguration(locations = { "classpath:META-INF/your-spring-context.xml" })
public class UserServiceTest extends AbstractJUnit4SpringContextTests {
#Autowired
private UserService userService;
#Test
public void testName() throws Exception {
List<UserEntity> userEntities = userService.getAllUsers();
Assert.assertNotNull(userEntities);
}
}
your-spring-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="userService" class="java.package.UserServiceImpl"/>
</beans>
I have 2 classes in 2 different projects, and I have some difficulties to autowire a field.
In project pack, I have this Computation class :
package fr.aaa;
#Component
public class Computation {
#Autowired
#Qualifier("curveDAO")
CurveAccess curveDAO;
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:applicationContext.xml");
}
}
In project db, I have this CurveAccess interface :
package com.bbb
public interface CurveAccess {
// some methods
}
implemented by a CurveDAO class :
package com.bbb.impl
#Repository("curveDAO")
#Transactional("cvaTxManager")
public class CurveDAO implements CurveAccess {
// some methods
}
My applicationContext.xml file from pack project :
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
xmlns:security="http://www.springframework.org/schema/security" xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
<import resource="classpath:spring/persistence.xml"/>
<context:annotation-config />
<context:component-scan base-package="fr.aaa.*, com.bbb.*"/>
<util:properties id="jdbcProps" location="jdbc.properties" />
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:configuration.properties</value>
<value>classpath:jdbc.properties</value>
</list>
</property>
</bean>
When running, I have this exception :
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'Computation': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.bbb.CurveAccess fr.aaa.Computation.curveDAO; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.bbb.CurveAccess] 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), #org.springframework.beans.factory.annotation.Qualifier(value=curveDAO)}
How can I solve this problem ?
Actually, your code works perfectly fine:
#SpringBootApplication
public class So21481801Application implements CommandLineRunner {
public interface CurveAccess {
String hello();
}
#Repository("curveDAO")
public class CurveDAO implements CurveAccess {
#Override
public String hello() {
return "Hello";
}
}
#Repository("curveDAOWorld")
public class CurveDAOWorld implements CurveAccess {
#Override
public String hello() {
return "World";
}
}
#Autowired
#Qualifier("curveDAO")
CurveAccess curveDAO;
#Autowired
#Qualifier("curveDAOWorld")
CurveAccess curveDAOWorld;
#Override
public void run(String... args) {
System.out.println(curveDAO.hello());
System.out.println(curveDAOWorld.hello());
}
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(So21481801Application.class, args);
context.close();
}
}
Probably you have some problem on how you are using the component-scan configuration on XML and the Java annotations. Mix them is not a good idea.
You need a class that implements CurveAccess interface
#Component
public class CurveAccessImpl implements CurveAccess {
//methods
}
Also remove Qualifier from curveDao in Computation bean since there is no such bean with id curveDao.
#Autowired
CurveAccess curveDAO;
We have an application where we are trying to inject an empty java.util.HashSet into a member of type java.util.Set, in a class which itself is a #Component. Spring seems to inject a HashSet with one element of the containing type. Any idea why Spring doesn't just inject an empty set?
Set element class:
#Component
public class SetElement
{
private String value;
public String getValue()
{
return value;
}
}
Class that contains a Set as a member:
#Component
public class MyClassWithSet
{
#Autowired
private Set<SetElement> setOfElements;
protected void setStringSet(Set<SetElement> stringSet)
{
this.setOfElements = stringSet;
}
public Set<SetElement> getStringSet()
{
return Collections.unmodifiableSet(setOfElements);
}
}
Spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<bean id="setOfElements" class="java.util.HashSet" />
<context:component-scan base-package="com.vikdor.db " />
</beans>
Sample test case to confirm the behavior
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations =
{ "classpath:META-INF/spring.xml" })
public class SpringSetTest
{
#Autowired
private MyClassWithSet myClassWithSet;
#Test
public void test()
{
assertNotNull(myClassWithSet);
assertNotNull(myClassWithSet.getStringSet());
assertTrue(myClassWithSet.getStringSet().isEmpty());
}
}
If you use #Autowired on a typed collection instance, then all beans in the application context that satisfy the type are injected:
It is also possible to provide all beans of a particular type from the
ApplicationContext by adding the annotation to a field or method that
expects an array of that type [...] The same applies for typed
collections:
public class MovieRecommender {
private Set<MovieCatalog> movieCatalogs;
#Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-autowired-annotation
Thus, your single instance of SetElement is injected into the #Autowired Set<SetElement>. A possible solution would be to use a setter for the field. Alternatively, you could use the #Qualifier annotation or the #Resource annotation to refer to the bean by name.