Can impl bean in spring have more public methods than Interface? - spring

if there is an interface in spring with 1 abstract public method and an implementation of this interface with 2 public methods (1 is overide and second public method is extra). If we autowire the interface we are not able to use the second public method in impl. Is this a correct behavior? In maven build it does say its using and autowiring IMPL bean but not able to find the second extra public method.

It's more of a Java question rather than a Spring one. There are a few things going on here:
Yes, an implementation can have more methods than the interface it's implementing.
Since you cannot initialize an interface, as in Spring case, it can only autowire an implementation of the interface to your bean.
Let's look at the following example:
You have an interface SomeInterface with methods methodA, and it's implementation SomeInterfaceImpl with methodA and methodB.
If you autowire a bean by its interface:
#Autowired private SomeInterface someInterface;
then you can only access methodA (without explicitly casting it to SomeInterfaceImpl, obviously), although what you have autowired is SomeInterfaceImpl and has methodB implemented.
If you autowire its impltementation:
#Autowired private SomeInterfaceImpl someInterface;
then you'll be able to access both methodA and methodB. HTH.

Related

Spring Boot - Override bean from controller

I have two controllers (ControllerA and ControllerB)
Both controllers call to a service (MyService).
MyService calls to an interface called MyRepository which has two implementations (FirstRepository and SecondRepository).
How is possible to use FirstRepository when the service (MyService) is called from ControllerA and use SecondRepository when the call comes from ControllerB?
This way I can reuse MyService and which repository is used comes from Spring Configuration.
I can see two possible solutions here.
1. In you MyService class autowire both implementations with #Qualifier annotation (you can also autowire List.
Then MyService method would have a parameter saying which MyRepository implementation should be called. I would not recommend this solution.
2. Define two implementations of MyService (FirstService, SecondService). Then FirstService would autowire FirstRepository and SecondService would autowire SecondRepository (use #Qualifier annotation again. Now you can easily inject FirstService to ControllerA and SecondService to ControllerB.
But first I would think about architecture. Maybe you don't need separate controllers?
Have you checked #Primary or #Resource or #Qualifier annotations? Based on your requirement you can choose out of them.
Something similar has been discussed here.
I ended up creating two controllers and defining two #Configuration classes, one for each #Controller.
And using the #Qualifier annotations defined two sets of beans, and then in each controller let Spring know which #Qualified bean I want injected.
#RestController
#RequestMapping("/v1/inapp/purchases")
class AController(
#Qualifier("appStore") private val redeemPurchaseService: RedeemPurchaseService
) : RedeemPurchaseApiDocumentation { // More code }
And the other controller
#RestController
#RequestMapping("/v1/inapp/purchases")
class GPlayRedeemPurchaseController(
#Qualifier("gplay") private val redeemPurchaseService: RedeemPurchaseService
) : RedeemPurchaseApiDocumentation { // More code }
And two #Configuration files, one per controller.

How do I autowire an instance of a java class?

I have a class that starts like this:
import javax.mail.Session;
//... more imports
#Component("eMailUtility")
public class MailUtility {
#Autowired
Session mailSession;
//...
}
My IDE tells me "Could not autowire. No beans of 'Session' type found."
This message doesn't surprise me, but I'm not sure how to fix it. Session is a final class with factory methods but no public constructors. I can easily instantiate a Session somewhere, but I don't know what I need to do to make it recognizable as a target of an autowired injection. All the examples I've found on the internet show how to autowire an instance of a class that I wrote, which doesn't help me here.
(A detailed explanation of exactly how autowire works, which doesn't gloss over anything, would be very helpful, but I can't seem to find one. If you know of a good link, that would be helpful.)
You'd have to create a method in a class that is annotated with #Configuration that returns a Session object and annotate that method with #Bean. In your case something like this:
#Bean
public Session session() {
return <instance>;
}
If it was one of your own classes you could also annotate it with #Component, or other annotations that are itself annotated with #Component. Spring would then find the class with this annotation and automatically create the bean for you.
For an explanation about #Autowired you can look at this answer: Understanding Spring #Autowired usage

Is it possible to retrieve a Spring bean with prototype scope without using ApplicationContextAware

Using Spring 3.1. If I want to retrieve a bean with prototype scope (i.e. I want a different instance of the class each time), is it possible to retrieve the bean without having to use an ApplicationContextaware class?
This is how I do it at present
#Component
#Qualifier("MyService")
public class MyServiceImpl implements MyService {
#Override
public void doSomething() {
Blah blah = (Blah)ApplicationContextProvider.getContext().getBean("blah");
blah.setThing("thing");
blah.doSomething();
}
}
#Component("blah")
#Scope("prototype")
public class Blah {
....
}
where ApplicationContextProvider implements ApplicationContextAware.
Is it possible to do this with annotations or simple Spring configuration without having to use an ApplicationContextAware class?
Spring has some fairly sophosticated methods for achieving what you're after...
See the spring documentation: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-factory-scopes-other-injection
Searching for spring proxy scope on google also threw up some results...
You don't really need a ApplicationContextAware. You just need a BeanFactory (ApplicationContextAware is just a convinient way to get it).
A bean with scope prototype just means that everytime ApplicationContext.getBean is called a new instance of the bean is created. If you try to inject a prototype bean in a singleton, your prototype bean will be injected once (and so is no more a prototype).
There is something called method injection that may help you if you really need it, but it is more complex than simply calling applicationContext.getBean().

how to implement Factory Pattern with Spring 3.0 Services

In my project I have an interface annotated with org.springframework.stereotype.Service tag.
I have two different implementation for this interface.
In my manage bean, I am injecting interface Service class and using its methods.
Now my requirement is, in run time I have to pick particular implementation (lets say based on login user group) so that respective logic can be invoked.
As per my understanding, we can achieve this using Factory pattern in java and achieve the same.
How can we implement this in SPRIng???
Besides suggested related topic above, there is a good thread on JavaRanch.
You can use
#Qualifier("myServiceImpl1") annotation together with #Autowired. In
that case this particular implementation of the interface will be
injected. You should also use the same name with your #Component,
#Service or #Repository annotations e.g.
#Service("myServiceImpl1")
public class MyServiceImpl1 implements MyService{}
public class Consumer{
#Autowired
#Qualifier("myServiceImpl1")
public MyService myServiceImpl1;
}
#Primary together with #Component, #Service or #Repository
annotations in your implementation class, in that case this
implementation will be injected by default.
If you mark a list of some interface type with #Autowired, all
available implementations of this interface will be injected.
#Autowired
public List<MyService> allAvailableImplementations;

Spring DI? Interface Type?

I understand the how, but can't seem formally shape the definitions.
As known DI can be done via constructor or setter or interface.
I am confused about the latest one -interface based DI, is it used in Spring?
UPDATE: I gave bad examle in here, which led to wrong understanding.
To fix it up:
Say we have setter and in setter we inject interface implemented by some class. Is that considered DI via setter or interface?
http://martinfowler.com/articles/injection.html#UsingAServiceLocator
this article divides DI on:
"There are three main styles of dependency injection. The names I'm using for them are Constructor Injection, Setter Injection, and Interface Injection. If you read about this stuff in the current discussions about Inversion of Control you'll hear these referred to as type 1 IoC (interface injection), type 2 IoC (setter injection) and type 3 IoC (constructor injection). I find numeric names rather hard to remember, which is why I've used the names I have here."
Else Service Locator pattern used for IoC, is it the one that actually makes possible #Autowired? - ie that not all classes explicitly need to be declared in xml for DI, as we can declare them as #Repository or #Controller or alike again if I recall correctly.
Thanks,
Autowiring an interface means wire a bean implementing that interface. This relies on an implementation actually existing in the bean factory.
#Autowired
UserService us; // wire a bean implementing UserService
--
#Service
public class UserServiceImpl implements UserService {
// the #Service annotation causes this implementation of UserService to
// be made available for wiring in the bean factory.
}
Worth noting is that if you wire by interface, Spring will expect there to exist one and exactly one bean in the bean factory implementing that interface. If more than one bean is found, an error will be thrown and you will have to specify which bean to wire (using the #Qualifier annotation).
EDIT:
When wiring, you can either wire a member variable or a setter method.
#Autowired
UserService us;
--
#Autowired
public void setUserService(UserService us) {
this.us = us;
}
These two produce the same result. The difference is that in the former, Spring will use reflection to set the variable us to a bean implementing UserService. In the latter, Spring will invoke the setUserService method, passing the same UserService imlementation.

Resources