Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: Autowire Interfaces

  1. #1
    Join Date
    Dec 2007
    Posts
    11

    Default Autowire Interfaces

    I have what seems like a simple problem, but I am unable to solve it in the manner I would like. I am moving away from by-name autowiring, towards the more explicit use of by-type with @Autowire (Spring 2.5.1). However, I have a problem when I have multiple beans of the same type. I understand how to use @Qualifier, but this doesn't work for me. Here is the problem:

    We have a pretty standard DAO layer. Each DAO object implements an interface, and we currently have implementations for JPA. We have one implementation (and interface) which implements the CRUD stuff, and all of the other DAOs inherit that implementation and interface. It just so happens that we occasionally want to inject the CRUD Dao. So, I tried this (we classpath scan for our daos):

    Code:
    @Resource
    @Qualifier("crudDao")
    public class JpaCrudDao implements CrudDao {
    }
    
    public class SomeOtherClass {
       public final CrudDao crudDao;
       public SomeOtherClass(@Qualifier CrudDao dao) {
          this.crudDao = crudDao;
       }
    }
    Of course, this doesn't work, because I 'qualified' the implementation class rather than the interface. I know that Guice has an @ImplementedBy annotation that you put on interfaces to mark a default implementation (and I think that is essentially what I want in this case). Is there any way to do this in Spring?

    My current workaround is to add a definition for JpaCrudDao in xml and mark 'primary=true'. This doesn't feel right for two reasons:
    1) it forces me to configure this bean in xml
    2) there is no explicit qualifier. It is a bit confusing to have:
    Code:
    public class SomeOtherClass {
       public final CrudDao crudDao;
       public SomeOtherClass(CrudDao dao) {
          this.crudDao = crudDao;
       }
    }
    because you know that every DAO in the system is a CrudDao. There has to be a better way!

    Suggestions would be greatly appreciated!

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,624

    Default

    The @Qualifier is to be used with a name not simply @Qualifier...

    Code:
    public SomeOtherClass(@Qualifier("crudDao") CrudDao dao) {
      this.crudDao = crudDao;
    }
    If you don't spring reverts to by-type and since you have multiple implementations that isn't going to work...
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    Dec 2007
    Posts
    11

    Default

    I am sorry. There was an error in my earlier post. What you said I should do, I did in fact do and it didn't work. I interpreted the failure as being because the name "crudDao" was attached to the implementation class, and not the interface (note that I annotated JpaCrudDao and gave it the "crudDao" name).

  4. #4
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,624

    Default

    If you are using those annotations @Qualifier and @Resource I suggest you switch to @Repository("crudDao") on your dao and the @Qualifier in your setmethod.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  5. #5
    Join Date
    Dec 2007
    Posts
    11

    Default

    Thanks for the reply. I had thought of doing this, but I was hoping to move away from setter injection towards constructor injection. Since I can't mark a constructor parameter with @Resource, I can't use it in this way. Perhaps that is my best bet, though.

  6. #6
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,624

    Default

    You are using the @Qualifier so why not use the @Autowired that is possible to use on a constructor.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  7. #7
    Join Date
    Dec 2007
    Posts
    11

    Default I figured out a solution, but I don't understand it...

    That is precisely what I am trying to do. The problem as far as I can tell is that the implementation class, JpaCrudDao, is getting the @Qualifier name attached to it, while I am injecting the Interface, CrudDao. In short:
    Code:
    @Repository
    @Qualifier("crudDao")
    public class JpaCrudDao implements CrudDao {
    }
    
    public class SomeClass {
      final CrudDao crudDao;
      @Autowired
      public SomeClass(@Qualifier("crudDao") CrudDao c) {
        this.crudDao = c;
      }
    }
    complains upon container startup because many classes implement CrudDao. On a whim, I tried this:

    Code:
    @Repository("crudDao")
    public class JpaCrudDao implements CrudDao {
    }
    
    public class SomeClass {
      final CrudDao crudDao;
      @Autowired
      public SomeClass(@Qualifier("crudDao") CrudDao c) {
        this.crudDao = c;
      }
    }
    This works fine. Note, the only difference is that I pulled the @Qualifier from the JpaCrudDao, and named it using the @Repository annotation. I thought that @Qualifier was supposed to be used for this in the context of @Autowire.

    Is this a bug?

  8. #8
    Join Date
    Jul 2005
    Location
    Geneva (Switzerland)
    Posts
    304

    Default

    No, this is the expected behaviour. @Resource (or the related @Repository, ...) are used to name a bean. @Qualifier is used to tell which bean you want to inject. Your final example looks just like it should look ...

  9. #9
    Join Date
    Dec 2007
    Posts
    11

    Default

    Great! Thanks for the response. The docs aren't very clear on this:

    3.12.6. Providing qualifier metadata with annotations

    The above section indicates the former, at least by my reading...

  10. #10
    Join Date
    Dec 2007
    Posts
    11

    Default

    Sorry. I was a bit unclear in the last post. My reading of the docs indicate that you should use @Qualifier in this case:

    http://static.springframework.org/sp...ing-qualifiers

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •