0

Following scenario

public interface MyInterface{
    
    void doSomething();
}

@ApplicationScoped
public static class MyInterfaceImpl implements MyInterface{

    @Override
    public void doSomething() {
        
    }
}


@ApplicationScoped
public static class MyInterfaceImplProxy implements MyInterface{

    @Inject
    MyInterface myInterface;
    
    @Override
    public void doSomething() {
        myInterface.doSomething();
    }
}

Of course, we now have a problem, as there are two beans available for one interface.

enter image description here

Is there a way to annotate the Proxy bean as such, so it won't be considered as an actual bean of type MyInterface or is the only way to use @Named beans here?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Marian Klühspies
  • 15,824
  • 16
  • 93
  • 136
  • 1
    It's been a while since I've done Spring, but doesn't it have something like `@Primary` for this purpose? – Jorn Aug 01 '23 at 07:09
  • 1
    @Jorn you might be right. In Jakarta it should be possible to handle it with `@Priority(0)` instead, as there is no `@Primary` annotation. Wasn't thinking about it that way. Thanks – Marian Klühspies Aug 01 '23 at 07:12
  • @Jorn This isn't Spring, but CDI. – Mark Rotteveel Aug 01 '23 at 09:56
  • 1
    @MarkRotteveel I noticed that later too, but my comment did apparently help OP so that's nice. – Jorn Aug 01 '23 at 11:08
  • 2
    One small note here, please do *not* use `@Named` as a standard CDI qualifier. Create your own custom one. The reason being that CDI actually employs special treatment WRT `@Named` when it comes to default qualifier. See https://jakarta.ee/specifications/cdi/4.0/jakarta-cdi-spec-4.0.html#builtin_qualifiers – Siliarus Aug 01 '23 at 11:59
  • The answer from Siliarus has all the helpful information to answer the question as it is (+1). However, can you take a step back and explain why do you want the `MyInterfaceImplProxy` from the perspective of design? Because it smells a lot like a use case for CDI decorators! – Nikos Paraskevopoulos Aug 01 '23 at 12:21
  • @NikosParaskevopoulos In my real-world application, the interface is a FileProvider that is responsible for file system operations (and has local and cloud implementations), and the proxy stores the file information in the database and fires events. Not sure if I'd even call it a proxy or just a service, I wanted to share the API between both, as there is no difference between them from the caller perspective. I've looked into CDI decorators, but I can't see what gains I'd get out of it from looking at the official docs right now. – Marian Klühspies Aug 01 '23 at 13:05
  • So there are 2 implementations of the `FileProvider` and you need some functionality that is common for both but independent of the specifics of each? Then an interceptor maybe? – Nikos Paraskevopoulos Aug 01 '23 at 20:41
  • 1
    @NikosParaskevopoulos maybe you are right, and maybe I should rethink the overall design as this was just prototyped. Thank you anyway for your help :) – Marian Klühspies Aug 02 '23 at 19:49

1 Answers1

3

You have two ways to go about this.

(1) You can start using CDI qualifiers to tell those beans apart - each bean has a set of type and set of qualifiers based on which it gets injected. In your example, default qualifiers are used, hence the ambiguous resolution.

(2) You can restrict bean types of a bean. This is done by placing @Typed() annotation on the bean class and explicitly listing the types you want that bean to have. Here is a link to the Jakarta doc describing it in more depth.

Last but not least, if you just meant to replace one impl with another one (or, in other words, provide an impl that should be prioritized), then you might want to look into CDI alternatives - which boils down to annotating the desired bean class with @Alternative @Priority(x). I am not sure this is what you are looking for, just putting it here so that you are aware of the option.

Siliarus
  • 6,393
  • 1
  • 14
  • 30