1

We are using Spring MCV and i am trying to use spring auto wiring to decouple my code. however, autowiring is not happening at all. Can you please suggest any issue in following code/ dispatcher

dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
               http://www.springframework.org/schema/mvc
               http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-4.1.xsd"
           xmlns:context="http://www.springframework.org/schema/context">
        <context:component-scan base-package="com.eos.accounts" />
    </beans>

User.java

package com.eos.accounts.data;
@Service
public class User {
.......
    @Autowired
    public UserMilesHelper  userMilesHelper             ;
.....
public static setUserPoints(User user){
 user.setPoints(user.userMilesHelper.getUserPoints(user.getUserId()));
}

IUserMilesHelper.java

package com.eos.accounts.data;

public interface IUserMilesHelper {

    public int getUserPoints(int userId);

}

UserMilesHelper.java

    package com.eos.accounts.data;

    import org.springframework.stereotype.Component;
   //I have used @Repository or Qualifier etc, no avail 
    @Component
    public class UserMilesHelper implements IUserMilesHelper {

        @Override
        public int getUserPoints(int userId) {
            return 10;
        }

    }

Web.xml

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>throwExceptionIfNoHandlerFound</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>50</load-on-startup>
</servlet>
Mukesh Kumar
  • 333
  • 1
  • 5
  • 20

4 Answers4

0

your User.java class have to be annotated with @Component too or any of its children for ex.

@Controller @Service @RestController

Bassem Reda Zohdy
  • 12,662
  • 3
  • 33
  • 39
0

Spring initiliaze component in his context by scanning packages and looking for class annoted with stereotypes (@Controller, @Service, @Repository....) or by explicit instantiation with manually adding a bean. If you use a the new it won't call Spring initilization mecanism and won't inject the dependancy.

I suppose your User class is not a singleton class so you should add @Scope("prototype") and use applicationContext.getBean(User.class) to instantiate with dependancy.

But to be honest i would instead refactor the code to avoid public members and static method to set variable and have class like that:

@Service
public class UserService{

   private IUserMilesHelper userHelper;

   @Autowired
   public UserService(IUserMilesHelper userHelper){
       this.userHelper = userHelper:
   }

   public setUserPoints(User user){
      user.setPoints(userHelper.getUserPoints(user.getUserId()));
   }
}
Baptiste Beauvais
  • 1,886
  • 1
  • 12
  • 19
  • I completely agree with you however, this static function is part of a legacy code and initializes at the time of server startup. addtionally, we are not using applicationContext.getBean(User.class) explicitly anywhere in our code – Mukesh Kumar Sep 18 '17 at 07:53
  • Well if you want to inject dependancy the targeted object must pass through Spring's applicationContext somehow. getBean witth a prototype scope is a workaround to make Spring instantiate your User. However if Spring doesn't suit your needs for that scenario it's better to find a simple solution without than one turning everything upside down to make it works. – Baptiste Beauvais Sep 18 '17 at 08:31
  • As per my research, I don't have to mention '@Service' on 'User.java' because Spring will take care of this automatically if i mention ' – Mukesh Kumar Sep 19 '17 at 06:37
0

By default, the name of the dispatcher servlet is xxx-servlet.xml where xxx is the servlet name. Which means that the spring is looking for dispatcher-servlet.xml, which is not the name of your XML config.

Thus the context itself is not loaded for you. Change it and test.

Apart from that, make sure that you follow best practises. Autowire on interfaces rather than on concrete class. Quick link for you - Spring: Why do we autowire the interface and not the implemented class?

Karthik R
  • 5,523
  • 2
  • 18
  • 30
  • Servlet-Dispatcher.xml is already there. I have mentioned in question too(first block). Pls check. and also please explain which part you want to change. – Mukesh Kumar Sep 18 '17 at 09:10
  • Did you read the answer carefully? The name of the xml should be dispatcher-servlet.xml not servlet-dispatcher.xml? – Karthik R Sep 18 '17 at 09:13
  • Sorry. there was typo mistake. It's dispatcher-servlet.xml only. updated the question. – Mukesh Kumar Sep 18 '17 at 09:19
  • If that's how your code is, no other clue. `@Autowired private IUserMilesHelper userHelper;` instead of Concrete class. That's the max I got here as of now. – Karthik R Sep 18 '17 at 09:22
0

pleae change <context:component-scan base-package="com.eos.accounts" /> to <context:component-scan base-package="com.eos.accounts.*" />

give it a try and let me know the result. hope it helps.

ali4j
  • 522
  • 3
  • 15