Android injecting class return null - java

I'm using JobQueue library and i can successful inject some class such as GithubService to that for example:
public interface GithubService {
#GET("repositories")
Call<List<GithubRepo>> getAllRepositories();
}
now i'm trying to inject other class as RxBus
public interface Bus {
void register(#NonNull Object observer);
<T> CustomSubscriber<T> obtainSubscriber(#NonNull Class<T> eventClass, #NonNull Consumer<T> receiver);
<T> void registerSubscriber(#NonNull Object observer, #NonNull CustomSubscriber<T> subscriber);
void unregister(#NonNull Object observer);
void post(#NonNull Object event);
}
into job file, but i get null
job class:
public class GetLatestRepositories extends Job implements JobManagerInjectable {
#Inject
transient GithubService githubService;
#Inject
transient Bus eventBus;
private Call<List<GithubRepo>> repositoryCall;
public GetLatestRepositories() {
super(new Params(JobPriority.MID).requireNetwork().persist());
eventBus.register(this); /* IS NULL*/
}
#Override
public void onAdded() {
}
...
#Override
public void inject(ApplicationComponent component) {
component.inject(this);
}
}
ApplicationComponent
#ActivitiesScope
#Component(dependencies = GithubApplicationComponent.class)
public interface ApplicationComponent {
void inject(ActivityRegister activityRegister);
void inject(ActivityStartUpApplication activityStartUpApplication);
void inject(GetLatestRepositories getLatestRepositories);
}
GithubApplicationComponent
#AlachiqApplicationScope
#Component(
modules = {
UserInformationModule.class,
NetworkServiceModule.class,
PicassoModule.class,
JobManagerModule.class,
RxModule.class,
ActivityModule.class
}
)
public interface GithubApplicationComponent {
Picasso getPicasso();
GithubService getGithubService();
JobManager getJobManager();
Bus getBus();
}
RxModule
#Module
public class RxModule {
#Provides
#AlachiqApplicationScope
public Bus getBus() {
return new RxBus();
}
}
RxBux files

In RxModule instead of:
return new RxBus();
Do:
return BusProvider.getInstance();

Related

EventListener for generic Events with Spring

I have two beans of the same class that I want to listen each for a bean-specific but generic event:
public class MyBeanClass <E> {
#EventListener
public void handleEvent(E event) { ... }
}
Config:
public class MyConfig {
#Bean
public MyBeanClass<AEvent> myBeanAClass() {
return new MyBeanClass<>();
}
#Bean
public MyBeanClass<BEvent> myBeanBClass() {
return new MyBeanClass<>();
}
}
So bean "myBeanAClass" shall listen for AEvent's and bean "myBeanBClass" shall listen for BEvent's.
Test:
#Test
public void testHandleAEvent() {
AEvent event = new AEvent();
publisher.publishEvent(event);
Mockito.verify(myBeanAClass, times(1)).handleEvent(Mockito.any()); // Fail
Mockito.verify(myBeanBClass, times(0)).handleEvent(Mockito.any());
}
Error:
org.mockito.exceptions.verification.TooManyActualInvocations:
mypackage.MyBeanClass#0 bean.handleEvent(
<any>
);
Wanted 1 time:
-> at mypackage.MyTest.testHandleAEvent(MyTest.java:45)
But was 5 times:
-> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
-> at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Because of Type Erasure the generic type E in handleEvent(E event) will be replaced with Object. After replacement class will look:
public class MyBeanClass {
#EventListener
public void handleEvent(Object event) { ... }
}
It means that such listener will accept any events from the application even generated by the spring framework internally. The method signature declares the event type it consumes. EventListener documentation
Solution 1. Create listener adapter foreach event
Adapters for base generic listener:
public class MyBeanClass <E> {
public void handleEvent(E event) {
event.toString();
}
}
public class MyBeanAClass {
private MyBeanClass<AEvent> myBeanClass;
public MyBeanAClass(MyBeanClass<AEvent> myBeanClass) {
this.myBeanClass = myBeanClass;
}
#EventListener
public void handleEvent(AEvent event) {
myBeanClass.handleEvent(event);
}
}
public class MyBeanBClass {
private MyBeanClass<BEvent> myBeanClass;
public MyBeanBClass(MyBeanClass<BEvent> myBeanClass) {
this.myBeanClass = myBeanClass;
}
#EventListener
public void handleEvent(BEvent event) {
myBeanClass.handleEvent(event);
}
}
Events:
public class AEvent extends ApplicationEvent {
private final String message;
public AEvent(Object source, String message) {
super(source);
this.message = message;
}
}
public class BEvent extends ApplicationEvent {
private final String message;
public BEvent(Object source, String message) {
super(source);
this.message = message;
}
}
Config:
public class MyConfig {
#Bean
public MyBeanAClass myBeanAClass() {
return new MyBeanAClass(new MyBeanClass<>());
}
#Bean
public MyBeanBClass myBeanBClass() {
return new MyBeanBClass(new MyBeanClass<>());
}
}
Test:
class ApplicationTests {
#MockBean
private MyBeanAClass myBeanAClass;
#MockBean
private MyBeanBClass myBeanBClass;
#Autowired
private ApplicationEventPublisher applicationEventPublisher;
#Test
public void testHandleAEvent() {
AEvent event = new AEvent(this, "Message");
applicationEventPublisher.publishEvent(event);
Mockito.verify(myBeanAClass, times(1)).handleEvent(Mockito.any());
Mockito.verify(myBeanBClass, times(0)).handleEvent(Mockito.any());
}
}
Solution 2. Generic Application Event
Create a generic event type. Implement org.springframework.core.ResolvableTypeProvider in generic event class, then listener will resolve it.
public class GenericSpringEvent<T> implements ResolvableTypeProvider {
private final T source;
public GenericSpringEvent(T source) {
this.source = source;
}
public T getSource() {
return source;
}
#Override
public ResolvableType getResolvableType() {
return ResolvableType.forClassWithGenerics(
getClass(),
ResolvableType.forInstance(this.source)
);
}
}
Implement generic listeners for each event
public class GenericSpringAEventListener {
#EventListener
public void handle(GenericSpringEvent<AEvent> event) {
event.toString();
}
}
public class GenericSpringBEventListener {
#EventListener
public void handle(GenericSpringEvent<BEvent> event) {
event.toString();
}
}
Config:
public class MyConfig {
#Bean
public GenericSpringAEventListener genericSpringAEventListener() {
return new GenericSpringAEventListener();
}
#Bean
public GenericSpringBEventListener genericSpringBEventListener() {
return new GenericSpringBEventListener();
}
}
Test:
class ApplicationTests {
#MockBean
private GenericSpringAEventListener aListener;
#MockBean
private GenericSpringBEventListener bListener;
#Autowired
private ApplicationEventPublisher applicationEventPublisher;
#Test
public void testHandleAEvent() {
AEvent event = new AEvent(this, "Message");
GenericSpringEvent<AEvent> genericEvent = new GenericSpringEvent<>(event);
applicationEventPublisher.publishEvent(genericEvent);
Mockito.verify(aListener, times(1)).handle(Mockito.any());
Mockito.verify(bListener, times(0)).handle(Mockito.any());
}
}

Get service that handle case from List

I have some handlers who implements interface. Each handler should serve some cases according to one or more types. I get the list of that handlers via autowired.
So when I want to use these handler in the iterate over them and check whether some of them handle the case, if so I run it on the case.
As describe here -
#Service
public class CarCreator implments ICreator{
#Override
public boolean shouldServe(IEntity entity){
entity.getType().equal(Type.Car);
}
#Override
public boolean crate(IEntity entity){ .. some code ...}
}
#Service
public class HouseCreator implments ICreator{
#Override
public boolean shouldServe(IEntity entity){
entity.getType().equal(Type.House);
}
#Override
public boolean crate(IEntity entity){ .. some code ...}
}
#Service
public class AnimalCreator implments ICreator{
#Override
public boolean shouldServe(IEntity entity){
entity.getType().equal(Type.Animal);
}
#Override
public boolean crate(IEntity entity){ .. some code ...}
}
interface ICreator{
boolean shouldServe(IEntity entity);
public boolean crate(IEntity entity);
}
public void EntitiesCreatorManger{
List<ICreator> creators;
#Autowired
public EntitiesCreatorManger(List<ICreator> creators){ this.creators = creators;}
public void createEntities(List<IEntity> entitites){
entities.stream.forEach(entity-> {
for(ICreator creator : creators){
if(creator.shouldServe(entity){
creator.create(entity);
break;
}
}
}
}
I want to do it with more elegant way and not for each list of interfaces in my system to use like this. Is there such way?
put all your ICreators in a lookup map:
Map<IEntity, ICreator> map = ...
ICreator creator = map.get(entity);
if(creator != null) {
...}
You seem to have an enumeration of types. Move the create logic onto the enum instances, and delegate to the create() call to the type.
public enum Type implements ICreator {
Car {
#Override
public void create(IEntity entity) {
// car creation
}
},
House {
#Override
public void create(IEntity entity) {
// house creation
}
},
Animal{
#Override
public void create(IEntity entity) {
// animal creation
}
};
}
public void EntitiesCreatorManager{
public void createEntities(List<IEntity> entities){
entities.forEach(entity -> entity.getType().create(entity));
}
}

Which one is preferred Registering Observer via Singleton or via RxJava?

I have a problem in which i am downloading some data in my background Service which is updating AppSingleton class which further notify the registered Observers in it.
Is Registering Observer via Singleton is preferred or that via RxJava.
AppSingleton looks like this:
public class AppGlobalData implements AppObservable {
private static final AppGlobalData ourInstance = new AppGlobalData();
private List<Customer> customerList;
private List<AppObserver> appObservers=new ArrayList<>();
public static synchronized AppGlobalData getInstance() {
return ourInstance;
}
private AppGlobalData() {
}
#Override
public void register(AppObserver obj) {
appObservers.add(obj);
}
#Override
public void unregister(AppObserver obj) {
appObservers.remove(obj);
}
#Override
public void notifyObservers() {
for (AppObserver observer : appObservers)
observer.update();
}
public List<Customer> getCustomerList() {
return customerList;
}
public void setCustomerList(List<Customer> customerList) {
this.customerList = customerList;
notifyObservers();
}
}

Dagger 2 not injecting in interface type

I an trying to inject a field in an interface type which is implemented by a class.
Here is what i have done so far.
These are view interface:
public interface PostView extends View, ListView<Post>, EmptyView<String> {
}
public interface View {
public void showProgressIndicator();
public void hideProgressIndicator();
public void onSuccess();
public void onFailure();
public void onFailure(String message);
}
public interface ListView<E> {
public void onListItems(List<E> items,
int pageNum,
int pageSize,
boolean next);
}
public interface EmptyView<E> {
public void onEmpty(E e);
public void onEmpty(String message);
}
Components:
#Singleton
#Component(modules = ApiModule.class)
public interface ApiComponent {
Api provideApi();
}
#UserScope
#Component(dependencies = ApiComponent.class, modules = PostModule.class)
public interface PostComponent {
PostPresenter providePostPresenter();
void inject(NetworkTest networkTest);
}
Modules:
#Module
public class ApiModule {
private static final Logger logger = Logger.getLogger(ApiModule.class.getSimpleName());
private final String baseUrl;
public ApiModule(String baseUrl) {
this.baseUrl = baseUrl;
}
#Provides
#Singleton
boolean provideIsLoggerEnabled() {
logger.info("proviedIsLoggerEnabled()");
return true;
}
#Provides
#Singleton
OkHttpClient provideOkHttpClient(boolean logEnabled) {
logger.info(" provideOkHttpClient(logEnabled)");
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
Interceptor requestInterceptor = new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
return chain.proceed(chain.request());
}
};
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.addInterceptor(requestInterceptor)
.addNetworkInterceptor(interceptor);
return builder.build();
}
#Provides
#Singleton
Api provideApi(OkHttpClient okHttpClient) {
logger.info("provideApi");
Retrofit retrofit = new Retrofit.Builder()
.client(okHttpClient)
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
return retrofit.create(Api.class);
}
}
#Module
public class PostModule {
private static final Logger logger = Logger.getLogger(PostModule.class.getSimpleName());
private final PostView postView;
public PostModule(PostView postView) {
this.postView = postView;
}
#Provides
#UserScope
PostService providePostService(Api api) {
logger.info("Provider post with api now");
return new PostService(api);
}
#Provides
#UserScope
PostPresenter providePostPresenter(PostService service) {
logger.info("Providing presenter with service now");
return new PostPresenter(postView, service);
}
}
Presenter:
public class PostPresenter extends AbstractPresenter {
private static final Logger logger = Logger.getLogger(PostPresenter.class.getSimpleName());
private PostView postView;
private PostService postService;
public PostPresenter(PostView postView, PostService postService) {
this.postView = postView;
this.postService = postService;
}
#Override
protected View getView() {
logger.info("Getting view");
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
public void getPosts() {
logger.info("Getting posts ");
Call<List<Post>> posts = this.postService.getPosts();
postView.showProgressIndicator();
posts.enqueue(new Callback<List<Post>>() {
#Override
public void onResponse(Call<List<Post>> call, Response<List<Post>> rspns) {
postView.onListItems(rspns.body(), 1, 25, true);
postView.hideProgressIndicator();
postView.onSuccess();
}
#Override
public void onFailure(Call<List<Post>> call, Throwable thrwbl) {
onApiCallError(thrwbl);
postView.hideProgressIndicator();
}
});
}
}
public abstract class AbstractPresenter {
private static final Logger logger = Logger.getLogger(AbstractPresenter.class.getSimpleName());
protected abstract View getView();
/*
* General indication whether api call stated or not.
*/
protected void onApiCallStart() {
logger.info("Api call started");
View v = getView();
if (v != null) {
v.showProgressIndicator();
}
}
protected void onApiCallEnd() {
logger.info("Api call finished");
View v = getView();
if (v != null) {
v.hideProgressIndicator();
}
}
/*
* General error handling
*/
protected void onApiCallError(Throwable e) {
logger.info("Api call terminated with error");
View v = getView();
if (v != null && e != null) {
v.onFailure(e.getMessage());
}
}
}
NetworkTest:
public class NetworkTest implements PostView {
private static final Logger logger = Logger.getLogger(NetworkTest.class.getSimpleName());
private PostComponent component;
#Inject
PostPresenter presenter;
public NetworkTest(ApiComponent apiComponent) {
component = DaggerPostComponent.builder()
.apiComponent(apiComponent)
.postModule(new PostModule(this))
.build();
}
public void init() {
component.inject(this);
}
void showPosts() {
if (presenter != null) {
logger.info("Hurray it worked");
presenter.getPosts();
} else {
logger.warning("Alas it failed");
}
}
#Override
public void showProgressIndicator() {
logger.info("Show progress indicator here");
}
#Override
public void hideProgressIndicator() {
logger.info("Hide progress indicator here");
}
#Override
public void onSuccess() {
logger.info("Api calls successfull");
System.exit(0);
}
#Override
public void onFailure() {
logger.warning("Api call failure");
System.exit(0);
}
#Override
public void onFailure(String message) {
logger.warning(message);
System.exit(0);
}
#Override
public void onListItems(List<Post> items, int pageNum, int pageSize, boolean next) {
logger.info("List received is: " + new Gson().toJson(items));
}
#Override
public void onEmpty(String e) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
public static void main(String[] args) {
ApiComponent apiComponent = DaggerApiComponent.builder()
.apiModule(new ApiModule("https://jsonplaceholder.typicode.com/"))
.build();
NetworkTest networkTest = new NetworkTest(apiComponent);
networkTest.init();
networkTest.showPosts();
}
}
My Problem is when i try to use
void inject(NetworkTest networkTest); //It works
void inject(PostView postView); //Doesn't work
I want that PostPresenter should get Injected in any class who is implementing PostView.
But when i do this #Inject field return null.
Does anyone have any clue about this.
NetworkTest has an #Inject field that Dagger can detect at compile time. PostView does not. Dagger 2 can perform injection on both NetworkTest and PostView, but because PostView has no #Inject-annotated methods, there's nothing for Dagger 2 to inject.
If you want to express that arbitrary implementors of PostView can be injected, you should add an #Inject-annotated initialize or injectPresenter method (et al); otherwise, just get/inject concrete types from Dagger so all of their dependencies can be injected at once.
As stated in the Dagger 2 user's guide (emphasis mine), "Dagger is a fully static, compile-time dependency injection framework for both Java and Android." Unlike with Guice or Spring, Dagger 2 performs no runtime reflection, so (for instance) a generated Component method inject(PostView) can only inject fields and methods defined on PostView or its supertypes, and not anything defined on a subtype.
In a general sense, I don't think it's reasonable for you to expect (or constrain) your PostView interface implementors to require the injection of a Presenter a certain way; if you want to make an explicit presenter-providing lifecycle method, you can do that on PostView without involving Dagger, and that way your classes can be more specific with their dependencies rather than mixing the necessary deps with the "unnecessary-but-included" deps you prescribe.

Generics specific interface definition in Java

Is it possible to define following in Java:
public interface IGenericRepo<T> {
void add();
void delete();
void attach();
}
public interface IGenericRepo<Book> {
default String bookSpecificMethod(){
return "smthn";
}
}
public class NHGenericRepo<T> implements IGenericRepo<T>{
/* implementation */
}
public class NHUnitOfWork implements UnitOfWork{
#Autowired
public void setBookRepo(NHGenericRepo<Book> bookRepo) {
this.bookRepo= bookRepo;
}
public NHGenericRepo<Book> getBookRepo() {
return bookRepo;
}
private NHGenericRepo<Book> bookRepo;
}
And to be able somewhere in code to have:
{
#Autowired
public void setNhuw(NHUnitOfWork nhuw) {
this.nhuw = nhuw;
}
private NHUnitOfWork nhuw;
/**/
{
String st = this.nhuw.getBookRepo().bookSpecificMethod();
}
}
In .net this is possible by using Extension Method with "this IGenericRepo<Book>" as a first method parameter.
The closest you can come is:
public interface IBookGenericRepo extends IGenericRepo<Book> {
void BookSpecificMethod();
}

Categories

Resources