GWT GIN - trivial use-case fails (EventBus) - java

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

Related

How to #Inject into main class - Java - Play Framework

I'm creating a main class in Play framework. Then I tried to #Inject another DAO object, as below:
public class HistoricalTask {
#Inject
protected static DataDao dataDao =
Play.current().injector().instanceOf(DataDao.class);
public static void main(String[] args) {
List<DataObject> rs = dataDao.getData();
}
}
But, it doesn't work. And I got an error:
Caused by: java.lang.RuntimeException: There is no started application
So, Is there any solution to create another main class, using #Inject feature and separate with Play web server?
Thank you, guys!
It is not possible to do that since your application is still in initialisation process.
If you want to initialise something at the time of application startup consider creating a module and add it to your application.conf file. Here you can register all the beans you want and any specific initialisation that you want to do by binding an eager singleton.
For example:
public class DaoHelperModule extends AbstractModule {
#Override
protected void configure() {
bind(DaoService.class).asEagerSingleton();
}
}
Then in application.conf file:
play.modules.enabled += "services.producer.DaoHelperModule"
You can inject dependencies in the module as well.

Injecting Map of customized objects in Guice

I am new to Guice. I have written following module:
public class TransactionConfigModule extends AbstractModule {
#Override
protected void configure() {
MapBinder<String, ITransactionManager> transactionModeMap = MapBinder
.newMapBinder(binder(), String.class, ITransactionManager.class
, Names.named("TransactionManagerMap"));
transactionModeMap.addBinding(TransactionMode.CREDIT.platformName())
.to(CreditCardManager.class)
.asEagerSingleton();
transactionModeMap.addBinding(TransactionMode.DEBIT.platformName())
.to(DebitCardManager.class)
.asEagerSingleton();
}
}
And then I have created the injector (which has been there already) as follows:
Injector injector = createInjector(
new PaymentModule()
);
PaymentModule (which has been already there) is like following:
public class RBSAVSTechServiceModule extends AbstractModule {
...
protected void configure(){
install(new TransactionConfigModule()); <--- I just added this line in the existing code
}
}
Here I am getting following exception:
No implementation for java.util.Map<java.lang.String, ITransactionManager> was bound.
I am not getting any idea regarding how to fix this.
From the example above it is not clear where you are installing RBSAVSTechServiceModule. I assume it is done inside PaymentModule.
I also note that you created the map binder using a binding annotation. Are you sure that your injection point is using the corresponding #Named("TransactionManagerMap")? The error message seems to indicate it is not.

Guice method injection error : "Unable to create binding for <class>. It was already configured on one or more child injectors or private modules"

I have the following class wherein I need method injection using Guice.
#Singleton
public class A {
private final Injector injector;
#Inject
public A(Injector injector) {
this.injector = injector;
}
public void method1() {
...
final XInterface x = this.injector.getInstance(Key.get(XInterface.class, Names.named("provideX")));
...
}
}
And the module contains the following provides method:
public class MyModule extends AbstractModule {
#Override void configure() {
// no binding and scope for class A
}
#Provides
#Named("provideX")
public XInterface provide(#Named("isTest") boolean isTest, X x, XMock xMock) {
return isTest ? xMock : x;
}
}
Where isTest has a provider in the same module and can be ignored for this discussion.
Now, this injection in class A gives me the following error:
Unable to create binding for `A`. It was already configured on one or more child injectors or private modules. If it was in a PrivateModule, did you forget to expose the binding?
and the rest of the stacktrace isn't very helpful.
After digging around for a while and trying out a few things, I found that just defining a Singleton scope for class A in the MyModule.configure() like so : bind(A.class).in(Singleton.class); and removing the existing #Singleton annotation on the class A solved the error. Now my question is two fold:
What caused the error in my first implementation?
What is the difference between defining a singleton scope in the module and annotating a class with singleton scope and why did that solve the problem?
Thanks in advance!

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

How do I use GWTP with ginjector extensions?

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.

Categories

Resources