Change a binding to a proxy - java

I create a proxy class using a APT(Annotation Processor) to do some instrumentation in the original class.
I want to change a binding in Dagger 2 with this proxy instead of the default implementation when the implementation class is annotated with #MyCustomAnnotation.
Implementation(By user):
#MyCustomAnnotation
public class MyServiceImpl implements MyService {
// Implementation
}
Original Module:
#Module
public class AppModule {
#Provides
#Singleton
MyService providesService() {
return new MyServiceImpl();
}
}
Final module replacing the implementation:
#Module
public class AppModule {
#Provides
#Singleton
MyService providesService() {
return new MyServiceImplProxy();
}
}
I need something transparent from a user perspective.
What do you guys suggest?

Well, I ended up using #Binds and doing a double bind.
Changed the user module to a simple #Binds:
#Module(includes = { OverrideModule.class })
public abstract class AppModule {
#Binds
#Singleton
abstract MyService providesMyService(MyServiceImpl impl);
}
And created a override module:
#Module
public abstract class OverrideModule {
#Binds
abstract MyServiceImpl providesMyServiceImpl(MyServiceImplProxy impl);
}

Related

How to inject this or that implementation depending on configuration a parameter with Spring

I am using the Spring/Springboot framework and would like to know if there is a possibility to "choose" or "select" the implementation class to instanciate depending on a configuration parameter
Let's say I have an interface IMyInterface and two possible implementations IImplentation1 and IImplementation2
I also have a class FooBar whose constructor receives a configuration class MyConf and an instance of IMyInterface
#Component
interface IMyInterface {
}
class IImplentation1 implements IMyInterface {
}
#Component
class IImplentation2 implements IMyInterface {
}
#Component
#ConfigurationProperties("my.application")
#Validated
class MyConf {
String kind; /// could be an enum
}
class IImplentation2 implements IMyInterface {
}
#Component
class FooBar {
#Autowired
public FooBar(MyConf myConf,
IMyInterface myInterface) { /// IImplentation1 or IImplentation2
... /// depending on MyConf.kind
}
}
Thanks for help
Regards
Philippe

More than one ejb found with interface of type for binding

I have an interface like this:
#Local
public interface MyInterface {
}
And two classes that implements this interface:
#Singleton
public class FirstBean implements MyInterface {
}
#Singleton
public class SecondBean implements MyInterface {
}
And another class like below:
#Singleton
public class ThirdBean {
#EJB
private MyInterface xpto;
}
And i am receiving the following error on deploy:
More than one ejb found with interface of type for binding
How to solve it?
Try to use qalifier
#java.lang.annotation.Documented
#java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE,ElementType.FIELD})
#javax.inject.Qualifier
public #interface First {
}
Mark bean using this qualifier
#Singleton
#First
public class FirstBean implements MyInterface {
}
Then inject it
#Singleton
public class ThirdBean {
#Inject
#First
private MyInterface xpto;
}

Spring #Autowire another implementation of the current service

I need to have an interface and then two implementations in different maven modules. Both impl services see api modul with interface but they don't see each other.
There is a default implementation and then transactional implementation. I want transactional impl service just load and call default impl service. Like this:
package my.app.core.api;
public interface MyService {
boolean process();
}
package my.app.core.impl
#Service
public class MyServiceImpl implements MyService {
#Override
public boolean process() {
// do something cool...
}
}
package my.app.somewhere.else.impl
#Service
#Transactional
public class TransactionalMyServiceImpl implements MyService {
#Autowire
private MyService myService;
#Override
public boolean process() {
myService.process();
}
}
Is it possible or do I need to #Autowire explicitly MyServiceImpl instead of interface? Which means to add maven dependancy to my.app.somewhere.else.impl.pom.
You can give different names to your services like so:
#Service
#Qualifier("transactionalMyService")
And then when you autowire you can use the name:
#Autowired
#Qualifier("transactionalMyService")
private MyService myService;

How to autowire Spring services that inherit?

I have 2 services, EFT and Cheque that are substantially similar.
Runs fine if I mark the implementation as #service.
Otherwise I get a no such bean definition exception. No qualifying bean of type 'EftPaymentService'.
Top level interface.
public interface PaymentService {
public void paymentsResponse();
}
Eft service interface.
#Service
public interface EftPaymentService extends
PaymentService {
public void processEft(String code) throws PaymentsException;
}
Cheque service interface
#Service
public interface ChequePaymentService extends
PaymentService {
public void processCheque(String code) throws PaymentsException;
}
Top level implementation
public abstract class PaymentServiceImpl implements PaymentService {
#Autowired
protected SessionFactory sftpSessionFactory;
#Autowired
protected SftpConfig.UploadGateway gateway;
public void paymentsResponse(){
}
}
Eft implementation
public class EftServiceImpl extends PaymentsServiceImpl implements EftPaymentService {
}
Cheque implementation
public class ChequeServiceImpl extends PaymentsServiceImpl implements ChequePaymentService {
}
What is going on here?
Refactor using composition?
Annotate implementations with #Service & use constructor-based injection.

Dagger 2 - Provides methods to have dependencies of their own

I'm trying to understand and implement Dagger 2. I've already read a lot of different tutorials and official documentation. I think I understand it in general but I still can not understand some simple points (while I wrote it I've found solution for some but..):
It's possible for #Provides methods to have dependencies of their own.
When it's possible?
What I see it's possible to get "component contains a dependency cycle".
Can someone help me to understand cases when it possible and when it not possible.
Thanks.
Actually, you can use qualifiers (#Named("something") annotation) to get multiple different type of implementation for a given dependency.
#Singleton
#Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(BaseActivity baseActivity);
#Named("first")
BaseNavigator firstNavigator();
#Named("second")
BaseNavigator secondNavigator();
Context context();
//...
}
#Module
public class ApplicationModule {
private final AndroidApplication application;
public ApplicationModule(AndroidApplication application) {
this.application = application;
}
#Provides
#Singleton
#Named("first")
BaseNavigator provideFirstNavigator() {
return new SomeNavigator();
}
#Provides
#Singleton
#Named("second")
BaseNavigator provideSecondNavigator() {
return new OtherNavigator();
}
#Provides
Context provideApplicationContext() {
return this.application;
}
}
public abstract class BaseActivity extends Activity {
#Inject
#Named("second")
BaseNavigator navigator;
After very long way of many experiments I've found the answer.
I'm making this answer as cue card for myself and hope it can help other daggers jedis.
So we have dagger structure
AndroidApplication
BaseActivity
Navigator
ApplicationComponent
ApplicationModule
...
ApplicationComponent.class
#Singleton
#Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(BaseActivity baseActivity);
Navigator navigator();
Context context();
//...
}
ApplicationModule.class
#Module
public class ApplicationModule {
private final AndroidApplication application;
public ApplicationModule(AndroidApplication application) {
this.application = application;
}
#Provides
#Singleton
Navigator provideNavigator() {
return new Navigator();
}
#Provides
#Singleton
Context provideApplicationContext() {
return this.application;
}
}
Navigator.class
#Singleton
public class Navigator implements BaseNavigator {
public Navigator() {}
}
BaseActivity.class
public abstract class BaseActivity extends Activity {
#Inject
Navigator navigator;
//code here
}
This code will work and BaseActivity will get navigator as new Navigator() provided by ApplicationModule.
But if you have several implementation of BaseNavigator class you can get some certain implementation for example Navigator class without creating new instance manually.
*This construction will give you "component contains a dependency cycle"
#Provides
#Singleton
Navigator provideNavigator(Navigator navigator) {
return navigator;
}
You can do this:
ApplicationComponent.class
#Singleton
#Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(BaseActivity baseActivity);
BaseNavigator navigator(); // changed to interface type
Context context();
//...
}
ApplicationModule.class
#Module
public class ApplicationModule {
private final AndroidApplication application;
public ApplicationModule(AndroidApplication application) {
this.application = application;
}
#Provides
#Singleton
BaseNavigator provideNavigator(Navigator navigator) {
return navigator;
} // this will return interface type but with implementation you needed
#Provides
#Singleton
Context provideApplicationContext() {
return this.application;
}
}
Navigator.class
#Singleton
public class Navigator implements BaseNavigator {
#Inject // don't forget to add this annotation to the constructor
public Navigator() {}
}
BaseActivity.class
public abstract class BaseActivity extends Activity {
#Inject
BaseNavigator navigator;// changed to interface type
//code here
}
Now you did not create new instance for Navigator, Dagger did it instead of you in its generated factory.

Categories

Resources