I am having a problem with autowiring. Here is my project's situation:
I have a jar (let's call it module.jar). This jar contains an Interface (IService):
package com.module.service;
public interface IService {
String create(Object data) throws Exception;
String update(Object data);
}
an abstract class which implements the interface (ServiceImpl):
package com.module.service
public abstract class ServiceImpl implements IService {
#Override
public final String create(Object data) throws Exception {
return update(data);
}
public abstract String update(Object data);
}
and a separate class which has an autowired IService field:
package com.module.service;
public class DoSomething {
#Autowired
IService service;
public String doCreate(Object data) {
return service.create(data);
}
}
I have a project (let's call it project). This project contains module.jar, and a class which extends the abstract ServiceImpl (we'll call it ServiceImplExt). ServiceImplExt is declared like so:
package com.project.service;
import com.module.service.ServiceImpl;
#Service
public class ServiceImplExt extends ServiceImpl {
#Override
public String update(Object data) {
data.setFname("John");
data.setLname("Doe");
return data;
}
}
I have added the ServiceImplExt's package to the component-scan of my 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-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:component-scan base-package="com.project.service" />
</beans>
After all of this, still when I start the server I get the following exception:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.demo.service.IService] 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)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1100)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:960)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:855)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:480)
... 42 more
I cannot figure out what it is that I can be doing wrong. Any ideas?
Added the code, added xml to aide potential helpers
Related
I have a query. About "Spring autowire byType vs constructor ( xml configuration)".
Read at multiple places that constructor autowire injection is similar to byType. But while I am testing, In case of ambiguity, constructor autowire behaves like byName (even not exactly), need your input if I am missing any important point.
I have below configuration:
<bean name="customerRepository" class="repository.HibernameCustomerRepositoryImpl"/>
<bean name="customerRepository1" class="repository.EclipselinkCustomerRepositoryImpl"/>
<bean name="customerService" class="service.CustomerServiceImpl" autowire="..."/>
byType output : org.springframework.beans.factory.NoUniqueBeanDefinitionException [Good Expected output]
constuctor output: pankaj [Notice I am not getting NoUniqueBeanDefinitionException and it gives me output for customerRepository why? below is sample code]
[Seems In case of ambiguity it does check for property name and choose bean whose name matching with property name]
Sample code:
public class CustomerServiceImpl implements CustomerService {
private CustomerRepository customerRepository;
public CustomerServiceImpl() {
}
public CustomerServiceImpl(CustomerRepository customerRepository) {
this.customerRepository = customerRepository;
}
// public void setCustomerRepository(CustomerRepository customerRepository) {
// this.customerRepository = customerRepository;
// }
#Override
public List<customer> findAll() {
return customerRepository.findAll();
}
}
Yes, Spring does autowire by name, but not exactly like it does with the "byName" autowire mode.
The Spring Documentation states :
Autowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired. For example, if a bean definition is set to autowire by name and it contains a master property (that is, it has a setMaster(..) method), Spring looks for a bean definition named master and uses it to set the property.
So, in order to autowire by name the setter method should be present. However, in this case the container matches the bean definition name with the name of the constructor argument to autowire in case of ambiguity.
Example:
Motor.java
package com.chiranth;
public interface Motor
{
public void start();
}
ElectricMotor1.java
package com.chiranth;
public class ElectricMotor1 implements Motor
{
public void start()
{
System.out.println("Motor 1 Started.");
}
}
ElectricMotor2.java
package com.chiranth;
public class ElectricMotor2 implements Motor
{
public void start()
{
System.out.println("Motor 2 Started.");
}
}
TeslaModelX.java
package com.chiranth;
public class TeslaModelX
{
private Motor motor;
public TeslaModelX(Motor electricMotor1)
{
motor=electricMotor1;
}
public void goForward()
{
motor.start();
System.out.println("Going Forward.");
}
}
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"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="electricMotor1" class="com.chiranth.ElectricMotor1"/>
<bean id="electricMotor2" class="com.chiranth.ElectricMotor2"/>
<bean id="modelX" class="com.chiranth.TeslaModelX" autowire="constructor"/>
</beans>
Test.java
package com.chiranth;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test
{
public static void main(String[] args)
{
ApplicationContext context= new ClassPathXmlApplicationContext("Spring.xml");
TeslaModelX modelX=(TeslaModelX)context.getBean("modelX");
modelX.goForward();
}
}
OUTPUT:
Motor 1 Started.
Going Forward.
Even though the property name doesn't match the bean name in the above example, autowiring is achieved.
Yes, you are right, when there is a ambiguos situation, Spring does Autowiring by Name. You can use #Qualifier to help Spring chose the right implementation based on name.
Check the docs
In a Spring 3.1.3.RELEASE project I want to create and autowire a list that contains some enum to some service.
Unfortunately the autowiring fails (NoSuchBeanDefinitionException), while I can retrieve the bean in the context and manually wire the dependency.
Here is a small testcase showcasing the issue (using Spring 3.1.3 and JUnit):
The XML context (int package /junk):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
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/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="junk"/>
<util:list id="myList" value-type="junk.GreatThings">
<value>SUPER</value>
<value>COOL</value>
</util:list>
</beans>
The enum:
package junk;
public enum GreatThings {AMAZING, GREAT, SUPER, COOL}
The test class (in package junk - I've removed the import for clarity):
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath*:junkcontext.xml"})
public class TestAutowiringSupport {
#Autowired #Qualifier("myList") List<GreatThings> greatThings;
#Test public void testSuperCool() {
Assert.assertThat(greatThings, hasItem(SUPER));
Assert.assertThat(greatThings, hasItem(COOL));
}
}
This result in a NoSuchBeanDefinitionException.
I have try to put a #Qualifier with my bean id to help Spring to perform the wiring without any success.
My IDE is however able to detect the wiring by itself:
And if I use the Spring lifecycle callbacks to get back the bean and wire it manually then, it is fine.
Version that compiles and runs fine:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = {"classpath*:junkcontext.xml"})
public class TestAutowiringSupport implements ApplicationContextAware
{
ApplicationContext ctx;
List<GreatThings> greatThings;
#Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {this.ctx = ctx;}
#PostConstruct
public void manualWiring() {greatThings = (List<GreatThings>) ctx.getBean("myList");}
#Test public void testSuperCool() {
Assert.assertThat(greatThings, hasItem(SUPER));
Assert.assertThat(greatThings, hasItem(COOL));
}
}
What's wrong with the autowiring in this case ?
Looks like some problem with generics.
With Spring 4.1 I am able to execute this code: where greatThings is of type List<Object>
#Qualifier("myList")
#Autowired List<Object> greatThings;
#Test
public void testSuperCool() {
Assert.assertThat(greatThings, Matchers.hasSize(2));
Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.SUPER));
Assert.assertThat(greatThings, Matchers.hasItem(GreatThings.COOL));
}
As stated in the reference documentation, placing the #Autowired annotation over a typed collection means "find all beans of the given type (GreatThings in your case), put them in a collection and inject that collection". You are getting the exception because there are no beans of type GreatThings declared.
The problem is that there is no easy way to declare enum values as beans. Then again I don't see the use case to be honest.
I'm creating a Jersey JAX-RS web service with the following:
package com.mycompany.rest.config;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
return getRestResourceClasses();
}
private Set<Class<?>> getRestResourceClasses() {
Set<Class<?>> resources = new java.util.HashSet<Class<?>>();
resources.add(com.mycompany.rest.controllers.UserController.class);
return resources;
}
}
However, when I try and integrate a spring applicationContext such as the following :
<?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.mycompany.rest.user"/>
<bean id="userService" class="com.mycompany.rest.user.UserServiceImpl" />
</beans>
I get null pointers from my controller class for the userService being loaded by the bean pasted above. I'm assuming this is because the application context is not being loaded into the Jersey application.
Is there a way of doing this?
If you want to inject Spring beans into your Jersey resource classes, you need to add jersey-spring3 dependency to your class path. see https://jersey.java.net/documentation/latest/spring.html
An hello-world example can be found at https://github.com/jersey/jersey/tree/2.19/examples/helloworld-spring-webapp
I had the same problem, and i fixed it by adding #autowired to my service, and extending SpringBeanAutowiringSupport like the following :
#Path("/mails")
public class MailController extends SpringBeanAutowiringSupport{
#Autowired
private MailService mailService;
#GET
#Path("/{code}")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public String getMails(#PathParam("code") String code) throws Exception {
//function logic
}
Note that this is working without integrating jersey-springx.jar
And I'm using Spring 3 along with jersey-bundle-1.19.1.jar
I have two classes: vehicle.Tire and vehicle.Car.
package vehicle;
#Named
public class Tire {
private String age;
}
package vehicle;
#Named
public class Car {
private Tire tire;
// Spring calls this setter because default-autowire="byName" of xml configuration
public void setTire(Tire newTire) {
this.tire = newTire;
}
public Tire getTire() {
return this.tire;
}
}
The following spring xml works fine.
<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-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
default-autowire="byName">
<context:component-scan base-package="vehicle" />
</beans>
I tried to create a java configuration above:
#Configuration
#ComponentScan(basePackages={"vehicle"})
public VehicleConfig {
}
I'm not using #Inject nor #Autowired annotations in the classes, but spring autowires and it works with xml.
Using java configuration, the method setTire of Car is not called :(
What is missing? How can I change java configuration using component scan without modifying Car and Tire classes? Is there default-autowire="byName" xml tag attribute equivalent in java?
I used the class above to test java configuration
#Test
public class VehicleConfigTest {
public void testTire() {
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext();
applicationContext.register(VehicleConfig.class);
applicationContext.refresh();
Car car = applicationContext.getBean(Car.class);
Assert.assertNotNull(car.getTire());
}
}
Thanks in advance.
There is no equivalent in sprig java configuration to default-autowire="byName" global xml tag attribute.
More, the right way to have injection is using #Inject annotation by cdi or #Autowired annotation by spring. So, the class Car should be modified:
package vehicle;
#Named
public class Car {
#Inject
private Tire tire;
public Tire getTire() {
return this.tire;
}
}
Now, both xml or java configuration works.
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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.pomkine.pottyauth.domain.User"/>
<bean id="userdao" class="com.pomkine.pottyauth.persistance.GaeUserDao"/>
<bean id="userservice" class="com.pomkine.pottyauth.service.UserServiceImpl">
<constructor-arg ref="userdao"/>
</bean>
</beans>
Controller:
#Controller
public class RosterController {
private UserService userService;
#Inject
public RosterController(UserService userService){
this.userService=userService;
}
#RequestMapping(value = {"/userRoster"}, method = RequestMethod.GET)
public String showRosterPage(Map<String,Object> model){
model.put("users",userService.getAllUsers());
return "userRoster";
}
}
So I want UserService to be injected into my controller. But I'm getting the following exception:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'rosterController' defined in file [S:\Coding\Idea_workspace\pottyAuth\target\pottyAuth-1.0\WEB-INF\classes\com\pomkine\pottyauth\mvc\RosterController.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.pomkine.pottyauth.service.UserService]: : No matching bean of type [com.pomkine.pottyauth.service.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
Here is my UserServiceImpl class:
public class UserServiceImpl implements UserService {
private UserDao dao;
public UserServiceImpl(UserDao dao){
this.dao=dao;
}
#Override
public User getUser(User user) {
return dao.getUser(user);
}
#Override
public void addUser(User user) {
dao.addUser(user);
}
#Override
public List getAllUsers() {
return dao.getAllUsers();
}
}
So I'm expecting Spring container to create UserServiceImlp bean and inject it into RosterController. But it seems that it cannot find UserServiceImpl bean.
What could be wrong?
UserServiceImpl is not implementing UserService
edit:
also I can't see
<context:component-scan base-package="">
Is this whole Spring configuration?
It means Spring couldnt find any bean of type UserService. Check your UserServiceImpl class.
Wondering why you are using both XML and annotation based approach to define beans? It will good if you stick to either of them.
EDIT:
Add #Component annotation to UserServiceImpl. So that Spring will come to know that it should create a object of UserServiceImpl
#Component
public class UserServiceImpl implements UserService
{
.....
}
and as #pawelccb have mentioned use
<context:component-scan base-package="your.base.package">
in Spring config file.
Check this link for details.