I'm new to Dagger 2, trying to port a (quite) complex application to it.
We have several dependencies on 'common' libraries (shared with other projects). Those 'common' libraries sometimes depend on other 'common' libraries. Each library exposes a module.
An example:
#Module
public class JsonModule {
#Provides
public Mapper provideMapper(ObjectMapper objectMapper) {
return new DefaultMapper(objectMapper);
}
#Provides
public ObjectMapper provideObjectMapper() {
return ObjectMapperFactory.build();
}
}
Our HttpModule depends on the JsonModule:
#Module(includes = {JsonModule.class})
public class HttpModule {
public HttpHelper provideHttpHelper(ObjectMapper objectMapper) {
return new DefaultHttpHelper(objectMapper);
}
}
Finally in my application, I depend on both these modules:
#Module(includes = {JsonModule.class, HttpModule.class})
public class MyAppModule {
public Service1 provideService1(ObjectMapper objectMapper) {
return new DefaultService1(objectMapper);
}
public Service2 provideService2(Mapper mappper) {
return new DefaultService2(mappper);
}
}
I then have 1 component that depends on my MyAppModule:
#Component(modules = MyAppModule.class)
#Singleton
public interface MyAppComponent {
public Service2 service2();
}
Unfortunately, when I compile the project, I get a Dagger compiler error:
[ERROR] com.company.json.Mapper is bound multiple times:
[ERROR] #Provides com.company.json.Mapper com.company.json.JsonModule.provideMapper(com.company.json.ObjectMapper)
[ERROR] #Provides com.company.json.Mapper com.company.json.JsonModule.provideMapper(com.company.json.ObjectMapper)
What am I doing wrong? Is it wrong to depend on a module twice in the same dependency graph?
In your MyAppModule you shouldn't include JsonModule, it is included by dagger implicitly. When including HttpModule dagger will automatically include all modules which HttpModule includes (in your case that is JsonModule).
It seems like the problem is related to our project's situation:
the common projects combine Groovy and Java
the common projects are built using Gradle
the application project combines Groovy and Java
the application project was built using Maven and the groovy-eclipse-compiler
Basicly: I blame the groovy-eclipse-compiler for now. I converted the project to Gradle, and everything works now.
Related
I'm creating an aspect to wrap my services but I'm also defining some services under the package
com.foo.arch
My application classes will be instead under
com.foo
Please notice that arch is a subpackage of com.foo but I can't put the "arch" keyword before.Isn't there a pointcut expression to say:
All classess under com.foo not having "arch" as third package?
Consider an interface SampleService
public interface SampleService {
void test();
}
and has 3 implementations in these three package
com
com.foo
com.foo.arch
an aspect to exclude arch package and only advice classes under com and com.foo would be as follows
#Component
#Aspect
public class ExcludeAspect {
#Around("execution(* test()) && !within(com.foo.arch.*)")
public void adviceTestMethod(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("Adviced");
pjp.proceed();
}
}
Reference :
within
Combining Pointcut Expressions
Hope this helps
How about adding this to your pointcut?
within(com.foo..*) && !within(com.foo.arch..*)
This will capture all sub-packages of com.foo except for com.foo.arch and its respective sub-packages.
If you only want com.foo and no sub-packages at all, it would simply be:
within(com.foo.*)
My app has hierarchy level class objects as follows.
Package com.sample.folder1;
Public class ParentClass{ }
Package com.sample.folder2;
Public class Childclass1 extends ParentClass{ }
Unit piece under test package:
#Test
Public void testMocking{
Childclass1 obj = Powermockito.mock(Chilclass1.class);
}
When I execute above junit in eclipse it throws
"VerifyError: Inconsistent stackmap frames....."
Please suggest mocking on hierarchy classes on same and different packages.
Try to add -noverify (Java 8) or -XX:-UseSplitVerifier (Java 7) as vm parameter.
Dagger 1's plus() method is something I used quite often in previous applications, so I understand situations where you might want to have a subcomponent with full access to the parent graphs bindings.
In what situation would it be beneficial to use a component dependency instead of a subcomponent dependency and why?
Component dependencies - Use this when you want to keep two components independent.
Subcomponents - Use this when you want to keep two components coupled.
I will use the below example to explain Component dependencies and Subcomponents. Some points worth noticing about the example are:
SomeClassA1 can be created without any dependency. ModuleA provides and instance of SomeClassA1 via the provideSomeClassA1() method.
SomeClassB1 cannot be created without SomeClassA1. ModuleB can provide an instance of SomeClassB1 only if an instance of SomeClassA1 is passed as an argument to provideSomeClassB1() method.
#Module
public class ModuleA {
#Provides
public SomeClassA1 provideSomeClassA1() {
return new SomeClassA1();
}
}
#Module
public class ModuleB {
#Provides
public SomeClassB1 provideSomeClassB1(SomeClassA1 someClassA1) {
return new SomeClassB1(someClassA1);
}
}
public class SomeClassA1 {
public SomeClassA1() {}
}
public class SomeClassB1 {
private SomeClassA1 someClassA1;
public SomeClassB1(SomeClassA1 someClassA1) {
this.someClassA1 = someClassA1;
}
}
Dagger will take care of passing the instance of SomeClassA1 as an argument to provideSomeClassB1() method on ModuleB whenever the Component/Subcomponent declaring ModuleB is initialized. We need to instruct Dagger how to fulfill the dependency. This can be done either by using Component dependency or Subcomponent.
Component dependency
Note the following points in the Component dependency example below:
ComponentB has to define the dependency via the dependencies method on #Component annotation.
ComponentA doesn't need to declare ModuleB. This keeps the two components independent.
public class ComponentDependency {
#Component(modules = ModuleA.class)
public interface ComponentA {
SomeClassA1 someClassA1();
}
#Component(modules = ModuleB.class, dependencies = ComponentA.class)
public interface ComponentB {
SomeClassB1 someClassB1();
}
public static void main(String[] args) {
ModuleA moduleA = new ModuleA();
ComponentA componentA = DaggerComponentDependency_ComponentA.builder()
.moduleA(moduleA)
.build();
ModuleB moduleB = new ModuleB();
ComponentB componentB = DaggerComponentDependency_ComponentB.builder()
.moduleB(moduleB)
.componentA(componentA)
.build();
}
}
SubComponent
Note the following points in the SubComponent example:
As ComponentB has not defined the dependency on ModuleA, it cannot live independently. It becomes dependent on the component that will provide the ModuleA. Hence it has a #Subcomponent annotation.
ComponentA has declared ModuleB via the interface method componentB(). This makes the two components coupled. In fact, ComponentB can only be initialized via ComponentA.
public class SubComponent {
#Component(modules = ModuleA.class)
public interface ComponentA {
ComponentB componentB(ModuleB moduleB);
}
#Subcomponent(modules = ModuleB.class)
public interface ComponentB {
SomeClassB1 someClassB1();
}
public static void main(String[] args) {
ModuleA moduleA = new ModuleA();
ComponentA componentA = DaggerSubComponent_ComponentA.builder()
.moduleA(moduleA)
.build();
ModuleB moduleB = new ModuleB();
ComponentB componentB = componentA.componentB(moduleB);
}
}
According to the documentation:
Component Dependency gives you access to only the bindings exposed as provision methods through component dependencies, i.e. you have access to only types which are declared in parent Component.
SubComponent gives you an access to the entire binding graph from its parent when it is declared, i.e. you have an access to all objects declared in its Modules.
Let's say, you have an ApplicationComponent containing all Android related stuff (LocationService, Resources, SharedPreference, etc). You also want to have your DataComponent where you manage things for persistence along with WebService to deal with APIs. The only thing you lack in DataComponent is Application Context which resides in ApplicationComponent. The simplest way to get a Context from DataComponent would be a dependency on ApplicationComponent. You need to be sure you have a Context explicitly declared in ApplicationComponent because you only have access to declared stuff. In this case, there is no manual work, meaning you don't need to specify Submodules in parent Component and explicitly add your submodule to a parent module like:
MySubcomponent mySubcomponent = myComponent.plus(new ChildGraphModule("child!")); // No need!
Now consider that case where you want to inject WebService from DataComponent and LocationService from ApplicationComponent into your Fragment which binds using the #Submodule plus feature above. The cool thing here is that the component you're binding to (ApplicationComponent) does not need to expose WebService nor LocationService because you have access to the entire graph right away.
Here is the code example with screenshot for more understanding of Component and SubComponent:
Component:
AppComponent contains two declarations.
AppComponent initializes into App class.
HomeActivityComponent is dependent upon AppComponent.
In HomeActivity on initialization of DaggerHomeActivityComponent, I am giving AppComponent object as a composition.
SubComponent:
AppComponent contains SubComponent or SubComponents.
AppComponent initializes into App class.
SubComponent doesn’t know about his ParentComponent. That only providing its own dependencies by including Module.
In HomeActivity I am injecting SubComponent by using its Parent Component.
And the Pictorial Diagram:
Source: link
One other thing that I didn't quite realize until now is that:
A #Subcomponent instance has exactly one parent component (although different components can instantiate that same #Subcomponent and be that instance's parent)
A #Component may have zero, one, or many "parent" components declared through component dependencies
every one!
I'm having a compilation problem in my GWT app which is divided in 3 modules:
App-core: containing the main classes without an entry point,
App-A and App-B: inherit from App-core, and containing there specific classes with an entry point in each submodule.
I'm using GIN to inject classes instances in every module:
in App-core:
public interface App-coreGinjector extends Ginjector {
EventBus getEventBus();
Provider<LoginPagePresenter> getLoginPagePresenter();
...
}
App-coreModule extends AbstractPresenterModule {
protected void configureCore() {
install(new DefaultModule(App-corePlaceManager.class));
bindConstant().annotatedWith(DefaultPlace.class).to(LoginPagePresenter.NAME_TOKEN);
...
bind(AuthenticationManager.class).to(AuthenticationManagerImpl.class);
bindPresenter(LoginPagePresenter.class, LoginPagePresenter.MyView.class,
LoginPageView.class, LoginPagePresenter.MyProxy.class);
}
in App-A:
#GinModules({ App-AModule.class })
public interface App-AGinjector extends App-coreGinjector {
MyApp-AScreen getMyApp-AScreen();
...
}
public class App-AModule extends App-coreModule {
#Override
protected void configure() {
configureCore();
...
//Here we bind the App-A classes inheriting from App-core classes
bind(App-coreScreenManager.class).to(App-AcreenManager.class).in(Singleton.class);
...
//Here we bind the specific App=A classes
}
And we do the same thing in App-B
The maven compilation is successful for the App-A, but it fail for the App-B, with this message:
[ERROR] Errors in 'C:\workspace\App-core\client\gin\App-coreGinjectorImpl.java'
[ERROR] Line 790: Rebind result 'com.gwtplatform.mvp.client.proxy.PlaceManager' must be a class
[ERROR] Line 818: Rebind result 'lu.sfeir.grh.client.authentication.AuthenticationManager' must be a class
[ERROR] Line 1047: Rebind result 'lu.sfeir.grh.client.login.LoginPagePresenter.MyView' must be a class
[ERROR] Line 2359: Rebind result 'com.google.gwt.event.shared.EventBus' cannot be abstract
[ERROR] Cannot proceed due to previous errors
So the weird part int all this is that this error come from the shared module between these two submodules, witch is the binding of the LoginPagePresenter and the AuthentificationManager, but we have this compilation error just in one sub module.
So if someone had this king of problems I'm waiting for his precious help ^^
Ah! if you want some precisions , don't be shy!!
In GWTP 0.7 and all EventBus instances are changed from
com.google.gwt.event.shared.EventBus;
to
com.google.web.bindery.event.shared.EventBus
If you are using GWTP 0.6 you have to change them back...
Is there a way to call a method in a Grails service, from a Scala class that is running on the same JVM?
I have seen something similar done from Groovy/Griffon but cannot figure out how to accomplish that in Grails. (http://www.jroller.com/aalmiray/entry/griffon_groovy_scala_working_together)
Basically, one of my Grails controllers calls some Scala code, which should return some values asynchronously. So, I guess, the only way to return those values is by calling back a method in a Grails service.
I found a way of doing it, inspired by the link in the question above, and one of the FAQs in the Grails website.
On the Scala side:
Declare an object similar to the following:
package scalaCallback
object ScalaCallback{
var cback: {def callback(example: String)} = null
def setCallback(cb: {def callback(example: String)}){
cback = cb
}
def invokeCallback(example: String){
if(callback != null) cback.callback(example)
}
}
On the Grails side:
Create a class in src/groovy similar to the following:
package groovyCallback
import org.codehaus.groovy.grails.commons.ApplicationHolder
class GroovyCallback{
private GroovyCallback() {}
private static final INSTANCE = new GroovyCallback()
static getInstance(){ return INSTANCE }
void callback(String example){
ApplicationHolder.application.mainContext.yourService.yourMethod(example)
}
}
In your BootStrap.groovy init add the following:
scalaCallback.cback = groovyCallback.GroovyCallback.getInstance()
When you call invokeCallback("example") in Scala, it will call yourService.yourMethod("example")
Note: the jar file with your Scala class should be in the lib folder of you Grails application
Your Grails service is a Spring bean. #Autowire the service into your Scala class (it will need to be a bean/#Component) and call the method.
EDIT - added example:
For example (using Java, not Scala but the approach is exactly the same):
Java code calling service:
package grailstest;
#Component
public class ServiceInjectionTester {
#Autowired TestService testService;
public String testTheService() {
return testService.serviceMethod();
}
}
Service:
class TestService {
String serviceMethod() {
return "success"
}
}
In Config.groovy:
grails.spring.bean.packages = [ "grailstest" ]
You can also wire your Java/Scala bean into your Grails classes:
class TestController {
#Autowired
ServiceInjectionTester serviceInjectionTester
def index = {
render(text: serviceInjectionTester.testTheService())
}
}
References:
Grails Reference 8.4 - Using Services from Java
Spring: The Foundation for Grails