How do I use GWTP with ginjector extensions? - java

I have a mobule file with:
<extend-configuration-property name="gin.ginjector.extensions" value="test.client.gin.ClientInjectorAdditional"/>
My ClientInjectorAdditional is:
public interface ClientInjectorAdditional extends Ginjector {
NotificationFetcher getNotificationFetcher();
}
Now I want to inject NotificationFetcher in my entry point class. I tried
public class Test implements EntryPoint {
private static final ApplicationController controller = GWT.create(ApplicationController.class);
#Inject
private NotificationFetcher notificationFetcher;
#Override
public void onModuleLoad() {
controller.init(;
...
}
}
The problem is that notificationFetcher is not injected.
How do I use GWTP with ginjector extensions?
Edit:
When I use
private final ClientInjectorAdditional injector = GWT.create(ClientInjectorAdditional.class);
I get the following warning:
No gin modules are annotated on Ginjector interface test.client.gin.ClientInjectorAdditional, did you forget the #GinModules annotation?
Edit:
I tried:
#GinModules({ ClientModule.class })
public interface ClientInjectorAdditional extends Ginjector { ... }
But this gives the following error:
[DEBUG] [test] - Rebinding test.client.gin.ClientInjectorAdditional
[DEBUG] [test] - Invoking generator com.google.gwt.inject.rebind.GinjectorGenerator
[ERROR] [test] - Error injecting com.gwtplatform.dispatch.rest.client.ActionMetadataProvider: Unable to create or inherit binding: No #Inject or default constructor found for com.gwtplatform.dispatch.rest.client.ActionMetadataProvider
Path to required node:
com.gwtplatform.dispatch.rest.client.RestRequestBuilderFactory [com.gwtplatform.dispatch.rest.client.gin.RestDispatchAsyncModule.configureDispatch(RestDispatchAsyncModule.java:99)]
-> com.gwtplatform.dispatch.rest.client.DefaultRestRequestBuilderFactory [com.gwtplatform.dispatch.rest.client.gin.RestDispatchAsyncModule.configureDispatch(RestDispatchAsyncModule.java:99)]
-> com.gwtplatform.dispatch.rest.client.ActionMetadataProvider [#Inject constructor of com.gwtplatform.dispatch.rest.client.DefaultRestRequestBuilderFactory]
[ERROR] [test] - Error injecting com.gwtplatform.dispatch.rest.client.serialization.JacksonMapperProvider: Unable to create or inherit binding: No #Inject or default constructor found for com.gwtplatform.dispatch.rest.client.serialization.JacksonMapperProvider
Path to required node:
com.gwtplatform.dispatch.rest.client.serialization.Serialization [com.gwtplatform.dispatch.rest.client.gin.RestDispatchAsyncModule.configureDispatch(RestDispatchAsyncModule.java:103)]
-> com.gwtplatform.dispatch.rest.client.serialization.JsonSerialization [com.gwtplatform.dispatch.rest.client.gin.RestDispatchAsyncModule.configureDispatch(RestDispatchAsyncModule.java:103)]
-> com.gwtplatform.dispatch.rest.client.serialization.JacksonMapperProvider [#Inject constructor of com.gwtplatform.dispatch.rest.client.serialization.JsonSerialization]
[ERROR] [test] - Deferred binding failed for 'test.client.gin.ClientInjectorAdditional'; expect subsequent failures
[ERROR] [test] - Failed to create an instance of 'test.client.test' via deferred binding
[ERROR] [test] - Unable to load module entry point class test.client.test (see associated exception for details)
[ERROR] [test] - Failed to load module 'test' from user agent 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.152 Safari/537.36' at http-server.fritz.box:61196

GWTP creates the ginjector automagically with all its presenters and views getters.
it also supports extending this ginjector for non GWTP objects.
here's how you do it:
a. define an interface, lets name it GinjectorExtensions in package some.package.client
package some.package.client;
public interface GinjectorExtensions {
//your objects here
MyConstants getMyConstants();
MyMessages MyMessages();
MyRequestFactory getRequestFactory();
}
b. Edit your GWT module xml file to include the following line (which tells GWTP to add your lines of code to it's autogen Ginjector):
<set-configuration-property name="gin.ginjector.extensions"
value="some.package.client.GinjectorExtensions"/>
Then you just #Inject your objects anywhere and everything should work as expected.
EDIT: after reviewing your code, just remove the "extends Ginjector" from ClientInjectorAdditional and everything should work.

Here is the sample code directly from Gin Tutorial:
Please find out the discrepancies:
gwt.xml
<inherits name="com.google.gwt.inject.Inject"/>
MyWidgetClientModule.java
import com.google.gwt.inject.client.AbstractGinModule;
import com.google.inject.Singleton;
public class MyWidgetClientModule extends AbstractGinModule {
protected void configure() {
bind(MyWidgetMainPanel.class).in(Singleton.class);
}
}
MyWidgetGinjector.java
import com.google.gwt.inject.client.GinModules;
import com.google.gwt.inject.client.Ginjector;
#GinModules(MyWidgetClientModule.class)
public interface MyWidgetGinjector extends Ginjector {
MyWidgetMainPanel getMainPanel();
}
MyWidgetMainPanel.java
import com.google.gwt.user.client.ui.Button;
public class MyWidgetMainPanel extends Button {
}
EntryPoint.java
private final MyWidgetGinjector injector = GWT.create(MyWidgetGinjector.class);
public void onModuleLoad() {
MyWidgetMainPanel mainPanel = injector.getMainPanel();
mainPanel.setText("Hi");
RootPanel.get().add(mainPanel);
}

Easier solution is to inject Provider<NotificationFetcher> in constructor and then call provider.get() every time you want to instantiate NotificationFetcher. No additional dependency (like Ginjector, etc.) needs to be defined.

Related

Play 2.5.12 Java - Missing HttpContext when replacing deprecated GlobalSettings.OnStart

I'm trying to migrate from Play 2.3 to 2.5 but I have an issue on replacing the GlobalSettings.OnStart method.
In my old Global class that was extending GlobalSettings, in the onStartMethod I was initialising the Global Config and reading basic things from the DB.
I have created a new class and I m moving the code from the onStart method to the constructor of this one as mentioned in the doc.
https://www.playframework.com/documentation/2.5.x/GlobalSettings
https://www.playframework.com/documentation/2.4.x/PluginsToModules
I'm doing the binding as eagerSingleton from an AbstractModule. The class is correctly started but I keep getting the error:
GlobalBootstrapModule.configure:20 - Binding
OnStartConfig.:35 - Global...on start
Caused by: java.lang.RuntimeException: No EntityManager bound to this thread. Try wrapping this call in JPAApi.withTransaction, or ensure that the HTTP context is setup on this thread.
This is my code:
New class to replace onStart
public class OnStartConfig implements StartConfigInterface{
private final JPAApi jpaApi;
#Inject
public OnStartConfig(Application application, JPAApi jpa){
this.jpaApi = jpa;
Logger.debug("Global...on start");
jpaApi.withTransaction( ()-> {
GlobalConfiguration.aggregationCriteria = AggregationCriterion.getAll();
});
}
The interface I'm extending is just an empty placeholder.
AbstractModule used for the binding:
public class GlobalBootstrapModule extends AbstractModule {
#Override
protected void configure() {
Logger.debug("Binding");
bind(StartConfigInterface.class).to(OnStartConfig.class).asEagerSingleton();
}
}
And I have enabled the module in the application.conf file:
play {
modules {
enabled += modules.GlobalBootstrapModule
}
}
I suppose the problem is due to the lack of HttpContext. Where can I grab it from during the initialisation?
Any help would be hugely appreciated

Dagger 2, How to add interface in dependency

I just started working with dagger 2. I have created dependency graph for application level dependency. Now that i wanted to create dependency that are required for a specific activity So i created another Component for activity then i created the Module and scope for that component. Now that when i am done writing all the code i build the project but i get compiler error which i am unable to solve.
Here is what i am doing.
#FeedsCatalogActivityScope
#Component(modules = FeedsCatalogActivityModule.class, dependencies = FeederApplicationComponent.class)
//My activity requires Catalog adapter so i am creating dependency for that
public interface FeedsCatalogActivityComponent {
CatalogAdapter getCatalogAdapter();
}
Here is the Module
#Module
public class FeedsCatalogActivityModule {
private final SelectedInterfaceListener selectedInterfaceListener;
public FeedsCatalogActivityModule(SelectedInterfaceListener selectedInterfaceListener) {
this.selectedInterfaceListener = selectedInterfaceListener;
}
#Provides
#FeedsCatalogActivityScope
public CatalogAdapter catalogAdapter(Picasso picasso, SelectedInterfaceListener mSelectesInterfaceListener) {
return new CatalogAdapter(picasso, mSelectesInterfaceListener);
}
}
Here is the scope
#Scope
public #interface FeedsCatalogActivityScope {
}
So now when i build i get this error
/Users/Zeeshan/Desktop/personal/Feeder/app/src/main/java/io/droidninja/feeder/FeederApplication.java
Error:(10, 31) error: cannot find symbol class DaggerFeederApplicationComponent
/Users/Zeeshan/Desktop/personal/Feeder/app/src/main/java/io/droidninja/feeder/ui/activities/FeedsCatalogActivityComponent.java
Error:(13, 20) error: io.droidninja.feeder.ui.adapters.SelectedInterfaceListener cannot be provided without an #Provides-annotated method.
io.droidninja.feeder.ui.adapters.SelectedInterfaceListener is injected at
io.droidninja.feeder.ui.activities.FeedsCatalogActivityModule.catalogAdapter(…, mSelectesInterfaceListener)
io.droidninja.feeder.ui.adapters.CatalogAdapter is provided at
io.droidninja.feeder.ui.activities.FeedsCatalogActivityComponent.getCatalogAdapter()
Error:Execution failed for task ':app:compileDebugJavaWithJavac'.
Compilation failed; see the compiler error output for details.
What i am understanding is that i have problem in FeedsCatalogActivityModule. How should i provide SelectedInterfaceListener? It is a interface.
P.S i am new to dagger2 i just get started with it.
According to your code, you are suppose to pass an instance of SelectedInterfaceListener to FeedsCatalogActivityModule when your are building FeedsCatalogActivityComponent inside the activity that uses it.
in your activity create a method that setup the component like this
private void initializeInjector() {
FeedsCatalogActivityComponent feedsCatalogActivityComponent = DaggerFeedsCatalogActivityComponent.builder()
.feederApplicationComponent(feederApplicationComponent()/* create this method and it should return a correctly built FeederApplicationComponent */ )
.feedsCatalogActivityModule(
new FeedsCatalogActivityModule(
new SelectedInterfaceListener()
/* pass in the instance of SelectedInterfaceListener here */ )
).build();
}
And then remember to change the Module provides method to
#Provides
#FeedsCatalogActivityScope
public CatalogAdapter catalogAdapter(Picasso picassor) {
return new CatalogAdapter(picasso, this.selectedInterfaceListener);
}
Well, you must somehow provide an implementation for that interface. Take a look at:
#Binds
#Provides
Binds vs. Provides
Example
#Binds
abstract SelectedInterfaceListener provideDsListPresenter(SelectedInterfaceListenerImpl impl);

No implementation for akka.actor.ActorRef was bound

I'm trying to create an actor in Java Play Framework (2.5.10) for running periodic tasks. When my application runs, however, I get the error No implementation for akka.actor.ActorRef was bound (detailed error messages provided later in this post). I'm sure the mistake is pretty basic, but I'm new to the whole actors thing and am having trouble figuring it out.
Here's the class (root-level Module.java) that binds the scheduler class and the actor:
public class Module extends AbstractModule implements AkkaGuiceSupport {
#Override
public void configure() {
// Use the system clock as the default implementation of Clock
bind(Clock.class).toInstance(Clock.systemDefaultZone());
// Ask Guice to create an instance of ApplicationTimer when the
// application starts.
bind(ApplicationTimer.class).asEagerSingleton();
// Set AtomicCounter as the implementation for Counter.
bind(Counter.class).to(AtomicCounter.class);
// bind the ECWID data importer
bind(ImportScheduler.class).asEagerSingleton();
bindActor(UserImportActor.class, UserImportActor.ACTOR_NAME);
}
}
The scheduler class:
#Singleton
public class ImportScheduler {
#Inject
public ImportScheduler(final ActorSystem actorSystem, final ActorRef UserImportActor) {
actorSystem.scheduler().schedule(
Duration.create(1, TimeUnit.SECONDS),
Duration.create(1, TimeUnit.SECONDS),
UserImportActor,
0,
actorSystem.dispatcher(),
UserImportActor
);
}
}
And finally, the actor class:
public class UserImportActor extends UntypedActor {
public static final String ACTOR_NAME = "user_import_actor";
#Override
public void onReceive(Object message){
Logger.info("The user import actor was called!");
}
}
When the application runs, here's the error that I see (the full error is too long - I think the first few lines will suffice):
! #72bagdfd4 - Internal server error, for (GET) [/] ->
play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:
1) No implementation for akka.actor.ActorRef was bound.
while locating akka.actor.ActorRef
for parameter 1 at services.ecwid.db.ImportScheduler.<init>(ImportScheduler.java:12)
at Module.configure(Module.java:34) (via modules: com.google.inject.util.Modules$OverrideModule -> Module)
Any idea what I'm missing?
The bindActor method annotates your ActorRef with a name - the name of the actorRef itself.
Could you try using the #Named annotation?
#Inject
public ImportScheduler(final ActorSystem actorSystem, #Named("user_import_actor") ActorRef UserImportActor) {
...
}

No implementation was bound - Java Guice

Novice here trying to use a dummy Java Facebook app that uses Guice to inject a database dependency into the Facebook factory but continue to have Guice error out telling me:
### No implementation for com.example.storage.Db annotated with #com.example.storage.annotations.SystemDb() was bound while locating com.example.storage.Db annotated with #com.example.storage.annotations.SystemDb() for parameter 0 at com.example.facebook.client.exceptions.FacebookExceptionHandlerDb at com.example.facebook.client.guice.FacebookClientModule.configure
### Could not find a suitable constructor in com.example.facebook.statsd.StatsdClient. Classes must have either one (and only one) constructor annotated with #Inject or a zero-argument constructor that is not private. at com.example.facebook.statsd.StatsdClient.class while locating com.example.facebook.statsd.StatsdClient for parameter 1 at com.example.facebook.client.exceptions.FacebookExceptionHandlerDb. com.example.facebook.client.guice.FacebookClientModule.configure
Code for app:
app.java
package com.example.facebook;
import com.google.inject.Guice;
import com.restfb.Connection;
import com.restfb.types.Post;
import com.example.facebook.client.FacebookClientFactory;
import com.example.facebook.client.RobustFacebookClient;
import com.example.facebook.client.guice.FacebookClientModule;
import com.example.facebook.statsd.StatsdClient;
public class App {
public static void main ( String[] args ) {
final FacebookClientFactory facebookClientFactory =
Guice.createInjector(new FacebookClientModule()).getInstance(FacebookClientFactory.class);
//error from line above
final RobustFacebookClient robustFacebookClient =
facebookClientFactory.create("accessToken");
//more ...
}
The resulting error points me to the FacebookClientModule binding:
FacebookClientModule.java
public class FacebookClientModule extends AbstractModule {
bind(FacebookExceptionHandler.class).to(FacebookExceptionHandlerDb.class);
//error resulting from the failed binding on the FacebookExceptionHandlerDB class
install(new FactoryModuleBuilder()
.implement(FacebookClient.class, RobustFacebookClient.class)
.build(FacebookClientFactory.class));
}
}
Where inside the FacebookExceptionHandleDB class the constructor has the injection:
FacebookExceptionHandlerDB.java
public class FacebookExceptionHandlerDb implements FacebookExceptionHandler {
// list of class String variables ...
private final FacebookErrorParser parser;
private final Db db;
private StatsdClient statsd;
#Inject
public FacebookExceptionHandlerDb(#SystemDb Db db, StatsdClient statsd, FacebookErrorParser parser) {
this.db = db;
this.statsd = statsd;
this.parser = parser;
}
}
From what I can gleam, the dependency injection for parameters zero and one, db and statsD respectively, is failing. Could someone point out where or what in the app code is missing?
At first glance it seems like your missing the bindings for the Db annotated dependency and the StatsdClient.
You'll need to provide the missing bindings to your module like so
bind(Db.class).annotatedWith(SystemDb.class).to(DbImplOfSomeSort.class);
bind(StatsdClient.class).to(StatsdClientImplOfSomeSort.class);
Guice is able to automatically inject Concrete Class with either a public no argument constructor or a constructor with #Inject without any specific defined binding in your module but when it comes to Interfaces you have to define the necessary bindings.
Here Db.class and StatsdClient.class are interfaces which you need to bind to specific implementation.
Not the source of the issue in this particular case, but I ran across this issue when I had my implementation and interface classes backwards:
public class MyModule extends AbstractModule {
#Override
public void configure() {
bind(MyClassImpl.class).to(MyInterface.class);
}
}
Should have been:
bind(MyInterface.class).to(MyClassImpl.class);

GWT GIN - trivial use-case fails (EventBus)

GIN Module:
public class InjectorModule extends AbstractGinModule {
#Override
protected void configure() {
bind(EventBus.class).to(SimpleEventBus.class).in(Singleton.class);
}
}
Injector:
#GinModules(InjectorModule.class)
public interface Injector extends Ginjector {
EventBus getEventBus();
}
GWT Module entry point:
public class Module1 implements EntryPoint {
private final Injector injector = GWT.create(Injector.class);
public void onModuleLoad() {
injector.getEventBus();
}
}
Removing call to injector.getEventBus() make everything work fine. Call to injector.getEventBus() causes:
Caused by: java.lang.RuntimeException: Deferred binding failed for 'com.google.web.bindery.event.shared.EventBus' (did you forget to inherit a required module?)
at com.google.gwt.dev.shell.GWTBridgeImpl.create(GWTBridgeImpl.java:53)
at com.google.gwt.core.client.GWT.create(GWT.java:97)
at com.XXX.app.client.InjectorImpl.create_Key$type$com$google$web$bindery$event$shared$EventBus$_annotation$$none$$(InjectorImpl.java:72)
at com.XXX.app.client.InjectorImpl.get_Key$type$com$google$web$bindery$event$shared$EventBus$_annotation$$none$$(InjectorImpl.java:86)
at com.XXX.app.client.InjectorImpl.getEventBus(InjectorImpl.java:7)
at com.XXX.app.client.Module1.onModuleLoad(Module1.java:24)
GWT Development Mode says:
23:58:50.287 [ERROR] Deferred binding result type 'com.google.web.bindery.event.shared.EventBus' should not be abstract
if you are using gwt 2.4:
There are now two EventBus (one is deprecated) make sure you are using the same type in the injetor and in your entrypoint.
Note: if you are using GWT Activity and encounter this issue, please star this ticket with the workaround.
https://code.google.com/p/google-web-toolkit/issues/detail?id=6653

Categories

Resources