Dagger 1 to 2 migration - Members injection methods may only return the injected type or void - dagger-2

Im trying to migrate our current system from dagger 1 to 2 and I been stuck for half a day on this. I don't think I'm understanding this well.
Here is my module:
public class BaseModule {
private final Context context;
private final SharedPreferences rawSharedPreferences;
public BaseModule(
Context context,
#Named("RawPreferences") SharedPreferences rawSharedPreferences
) {
this.context = context;
this.rawSharedPreferences = rawSharedPreferences;
}
#Provides
#Singleton
public Context provideContext() {
return context;
}
#Provides
#Singleton
public DevicePlatform provideDevicePlatform(AndroidDevicePlatform devicePlatform) {
return devicePlatform;
}
#Provides
#Named("RawPreferences")
#Singleton
public SharedPreferences provideRawSharedPreferences() {
return rawSharedPreferences;
}
#Provides
#Named("RawPreferencesStore")
#Singleton
public SharedPreferencesStore provideRawSharedPreferencesStore(
#Named("RawPreferences") SharedPreferences sharedPreferences) {
return new AndroidSharedPreferencesStore(sharedPreferences);
}
And my component:
#Singleton
#Component(
modules = {BaseModule.class}
)
public interface BaseComponent {
void inject (DefaultClientController defaultClientController);
void inject (StatisticsProvider statisticsProvider);
Context provideContext();
AndroidDevicePlatform provideDevicePlatform(AndroidDevicePlatform devicePlatform);
SharedPreferences provideRawSharedPreferences();
SharedPreferencesStore provideRawSharedPreferencesStore(
#Named("RawPreferences") SharedPreferences sharedPreferences);
}
I keep getting this error in provideRawSharedPreferencesStore when I run it:
Error:(168, 28) error: Members injection methods may only return the injected type or void.
I dont understand why. Can someone please help me out. Thanks!

A component can contain 3 types of methods:
inject something into some object, which is the error you see. Those methods usually return void, but you can just return the same object, if you try to have something like a builder.
MyInjectedObject inject(MyInjectedObject object); // or
void inject(MyInjectedObject object);
Subcomponents, for which you would include the needed modules as parameters (if they require initialization)
MySubcomponent plus(MyModuleA module);
and basically just "getters" or correctly called provision methods to expose objects, to manually get them from the component, and to your subcomponents
MyExposedThing getMything();
Which one of those is this?
// the line you get your error:
SharedPreferencesStore provideRawSharedPreferencesStore(
#Named("RawPreferences") SharedPreferences sharedPreferences);
You are already providing the SharedPreferencesStore from your module. There you also declare its dependency on RawPreferences: SharedPreferences. You do not have to do this again in your component.
It seems you just try to make the SharedPreferencesStore accessible, as described in 3.. If you just depend on it within the same scope / component, you could just remove the whole component. If you need the getter, you should just remove the parameter. Your Module knows how to create it.
SharedPreferencesStore provideRawSharedPreferencesStore(); // should work.

Related

Flutter, when to use Factory fromJson and constructor fromJson

I've been struggling with this for a long time.
For sure, what I currently know is that you should use a factory or static fromJson when you need only one object and a Constructor named .fromJson when you need to create multiple instances.
So.. when?? when we need a one instance and when we need multiple instances??
I'm creating a model class for API response right now, and I'm deeply troubled about whether to use the factory or not.
Factory constructor allows returning already created instances. It allows us easily make singletons and multitones. From the call side, it looks like the usual constructor, but from inside implementation, it varies. Also, the factory constructor doesn't force you to return only one instance (object) as you stated. You can create as many as you need. It allows returning already created instances. That's the difference with an ordinary constructor that always returns a new instance. So this feature gives us some flexibility and in some cases performance improvements.
An example:
class Logger {
static Logger _instance;
Logger._() {
print('Logger created');
}
factory Logger() {
return _instance ??= Logger._();
}
void log(String msg) => print('${DateTime.now()}: $msg');
}
void main() {
A().initialize();
B().initialize();
}
class A {
Logger _logger;
void initialize() {
_logger = Logger();
_logger.log('A initialized');
}
}
class B {
Logger _logger;
void initialize() {
_logger = Logger();
_logger.log('B initialized');
}
}
If we run this code it will produce output like that:
Logger created
2021-09-27 21:59:23.887: A initialized
2021-09-27 21:59:23.887: B initialized
Where you can see that only one instance of Logger class has been created. Despite from calling side we've requested to create two instances.
In most cases, if your task it to create a modal class for API response an ordinary constructor with a static fromJson method is enough.

Can't inject EPartService

In my bundle activator I try to inject fields 'IEventBroker' and 'EPartService'. But injected only first. Code follows:
#Inject
IEventBroker m_broker;
#Inject
EPartService m_part_service;
public void start(BundleContext context) throws Exception {
IEclipseContext service_context = EclipseContextFactory.getServiceContext(context);
ContextInjectionFactory.inject(this, service_context);
boolean contains = service_context.containsKey(EPartService.class);
// contains is always "true", but m_part_service is always "null"
// all follows invocations returns "null" too
//
// service_context.get(EPartService.class);
// service_context.getActiveLeaf().getActive(EPartService.class);
// service_context.getActiveLeaf().getLocal(EPartService.class);
// context.getServiceReference(EPartService.class);
// m_broker always non-null
m_broker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE, new EventHandler()
{
#Override
public void handleEvent(Event event)
{
// ... bla bla bla
}
});
}
In internal lists of IEclipseContext I found EPartService.
Can you help me? What I did wrong?
Bundle activators are not injected so you can't use #Inject.
The context returned by EclipseContextFactory.getServiceContext has very limited contents and can't be used to access things like EPartService.
In any case the bundle activator generally isn't even run until something else in your plugin is used, so it would be too late the see the startup complete message anyway.
So all this means you can't do what you want in the bundle activator start method.
To get notified about the app startup complete event you can use the application LifeCycle class or define an AddOn - both these classes are injected.
In those classes use a method like:
#Optional
#Inject
public void appStartupComplete(#UIEventTopic(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE)
org.osgi.service.event.Event event)

Why static map does not retain the value in future methods?

I have declared a map as a instance variable like this:
public class JSONParser_GET {
public static Map<String, String> mapOfValues= new Map<String,String>();
...
Now, I have a future method where I am adding the values to this map:
#future(callout=true)
public static void getRequest(String type,String e,String authHeader){
mapOfValues.put(type,lookupname);
...
But the values are not available when I try to access it in different method. Isn't that is what static is supposed to do?
As I am declaring it as static instance variable it should be globally available. I tried to use global keyword as well. But that also doesn't seems to work.
Any help is appreciated
I think, it's related to the Future annotation. That means, the method getRequest() will be executed asynchronously, not with all usual methods.
So, here is what I did..
It seems future methods may execute in parallel due to which it is not possible to get the values from the response in one Map itself.
So I wrote a method before the getRequest and made it as future so that I can make only one instance of future handler.
#future(callout==true)
public class JSONParser_GET {
public static Map<String, String> mapOfValues= new Map<String,String>();
getRequest()
getRequest()
getRequest()
}
public void getRequest{...}

Print data received by REST call when using #Resource in Grails

Following along with groovies docs on REST, i've setup a model like so:
import grails.rest.*
#Resource(uri='/books')
class Book {
String title
static constraints = {
title blank:false
}
}
I'd print out the parameters I receive when creating and saving. Is there away to override these methods created by the #Resource(uri='/books') annotation? Or handle the annotation a closure or something to do this?
I think you may have 2 choices if you wish to have a default RESTful interface and modify it somewhat for your needs.
Use the $ grails generate-controller [Domain Class Name] command that will generate the appropriate controller and change the generated file as needed.
Create a Book controller and extend the RestfulController; then override the default methods with the #Override annotation, print/log the params, and then call the matching super method.
import grails.rest.RestfulController
class BookController extends RestfulController {
static responseFormats = ['json', 'xml']
BookController() {
super(Book)
}
#Override
def save() {
println params
super.save params
}
#Override
def update() {
println params
super.update params
}
}

How do I mock Class<? extends List> myVar in Mockito?

I want to mock a Class in Mockito. It will then have a .newInstance() call issued which will be expected to return an actual class instance (and will return a mock in my case).
If it was setup correctly then I could do:
ArrayList myListMock = mock(ArrayList.class);
when(myVar.newInstance()).thenReturn(myListMock);
I know I can set it up so that a new instance of class ArrayList will be a mock (using PowerMockito whenNew), just wondering if there was a way to mock this kind of a class object so I don't have to override instance creation...
Below is the real class I'm trying to mock, I can't change the structure it is defined by the interface. What I'm looking for is a way to provide cvs when initialize is called.
public class InputConstraintValidator
implements ConstraintValidator<InputValidation, StringWrapper> {
Class<? extends SafeString> cvs;
public void initialize(InputValidation constraintAnnotation) {
cvs = constraintAnnotation.inputValidator();
}
public boolean isValid(StringWrapper value,
ConstraintValidatorContext context) {
SafeString instance;
try {
instance = cvs.newInstance();
} catch (InstantiationException e) {
return false;
} catch (IllegalAccessException e) {
return false;
}
}
Mockito is designed exclusively for mocking instances of objects. Under the hood, the mock method actually creates a proxy that receives calls to all non-final methods, and logs and stubs those calls as needed. There's no good way to use Mockito to replace a function on the Class object itself. This leaves you with a few options:
I don't have experience with PowerMock but it seems it's designed for mocking static methods.
In dependency-injection style, make your static factory method into a factory instance. Since it looks like you're not actually working with ArrayList, let's say your class is FooBar instead:
class FooBar {
static class Factory {
static FooBar instance;
FooBar getInstance() {
if (instance == null) {
instance = new FooBar();
}
return instance;
}
}
// ...
}
Now your class user can receive a new FooBar.Factory() parameter, which creates your real FooBar in singleton style (hopefully better and more threadsafe than my simple implementation), and you can use pure Mockito to mock the Factory. If this looks like it's a lot of boilerplate, it's because it is, but if you are thinking of switching to a DI solution like Guice you can cut down a lot of it.
Consider making a field or method package-private or protected and documenting that it's visible for testing purposes. Then you can insert a mocked instance in test code only.
public class InputConstraintValidator implements
ConstraintValidator<InputValidation, StringWrapper> {
Class<? extends SafeString> cvs;
public void initialize(InputValidation constraintAnnotation) {
cvs = constraintAnnotation.inputValidator();
}
public boolean isValid(StringWrapper value,
ConstraintValidatorContext context) {
SafeString instance;
try {
instance = getCvsInstance();
} catch (InstantiationException e) {
return false;
} catch (IllegalAccessException e) {
return false;
}
}
#VisibleForTesting protected getCvsInstance()
throws InstantiationException, IllegalAccessException {
return cvs.newInstance();
}
}
public class InputConstaintValidatorTest {
#Test public void testWithMockCvs() {
final SafeString cvs = mock(SafeString.class);
InputConstraintValidator validator = new InputConstraintValidator() {
#Override protected getCvsInstance() {
return cvs;
}
}
// test
}
}
I think you just need to introduce an additional mock for Class:
ArrayList<?> myListMock = mock(ArrayList.class);
Class<ArrayList> clazz = mock(Class.class);
when(clazz.newInstance()).thenReturn(myListMock);
Of course the trick is making sure your mocked clazz.newInstance() doesn't end up getting called all over the place because due to type-erasure you can't specify that it's actually a Class<ArrayList>.
Also, be careful defining your own mock for something as fundamental as ArrayList - generally I'd use a "real one" and populate it with mocks.