How to override GWT-supplied implementation of CanvasElement in PlayN HTMLGraphicsCanvas? - gwt

I'm looking to supply my own implementation of CanvasElement class. This class is instantiated in HTMLGraphicsCanvas class in the PlayN stack.
What is the ideal way of doing this? There are 2 ways that I've tried but failed:
A) Subclassing HTMLGraphics and HTMLPlatform? --this doesn't seem to be possible.
B) The GWT module mechanism seems to require that my custom implementation of a GWT-supplied class be of the same package. So take for example this XML snippet:
<replace-with class="com.google.gwt.dom.client.DOMImplOpera">
<when-type-is class="com.google.gwt.dom.client.DOMImpl"/>
<when-property-is name="user.agent" value="opera"/>
</replace-with>
If I do something like:
<replace-with class="com.domain.example.CustomCanvasElement">
<when-type-is class="com.google.gwt.dom.client.CanvasElement"/>
<when-property-is name="user.agent" value="opera"/>
</replace-with>
...it does not seem to work because the packages are different. At least that's what I think is happening.
Any other ideas? Much appreciated.

Ok so I can answer the B) part of my own question. Although I would really appreciate an answer to my overall question about how to supply my own implementation.
So my guess wasn't entirely correct. According to this section of Deferred Binding, basically you have to first create a superclass object that Browser-specific objects will subclass. So for instance:
GenericBrowserObject is the superclass and might have common implementations of certain methods between Browser-specific objects or might be your "catch-all" implementation for all other (non-specific) Browsers.
So for instance, let's say you only want to have specific implementations for IE and Gecko-based browsers.
GeckoBrowserObject extends GenericBrowserObject
IEBrowserObject extends GenericBrowserObject
Let's say that there is a common method called setStyle in GenericBrowserObject but they have differing implementations between GeckoBrowserObject and IEBrowserObject, then you would override setStyle in each of those classes and supply their own implementations.
The class that manipulates these objects needs to instantiate GenericBrowserObject superclass in this way:
GenericBrowserObject obj = GWT.create(GenericBrowserObject.class);
obj.setStyle("whatever");
Then in your module file (something.gwt.xml), you would have something like this:
<replace-with class="com.domain.blah.GenericBrowserObject">
<when-type-is class="com.domain.blah.GenericBrowserObject"/>
</replace-with>
<replace-with class="com.domain.blah.IEBrowserObject">
<when-type-is class="com.domain.blah.GenericBrowserObject"/>
<any>
<when-property-is name="user.agent" value="ie6"/>
<when-property-is name="user.agent" value="ie8"/>
</any>
</replace-with>
<replace-with class="com.domain.blah.GeckoBrowserObject">
<when-type-is class="com.domain.blah.GenericBrowserObject"/>
<any>
<when-property-is name="user.agent" value="gecko"/>
<when-property-is name="user.agent" value="gecko1_8"/>
</any>
</replace-with>
When GWT compiles this, it will generate the correct objects based on the user agent string via GWT.create.

Related

How to override the deferred binding configuration of a inherit gwt module

is it possible to override the deferred binding configuration of a inherit module?
Here is a example:
In the module, I want to use, a deferred binding is declared as follows moduleA.gwt.xml:
<replace-with class="A1Impl">
<when-type-is class="A"/>
</replace-with>
<replace-with class="A2Impl">
<when-type-is class="A"/>
<when-property-is name="p" value="1"/>
</replace-with>
The declaration says: Use A1Impl class as default and A2Impl class, if property p has the value 1.
Now, in my app I want to use that module and want P to be 1 (because this controls the above shown, but also a lot of other deferred binding configurations) mymodule.gwt.xml:
<inherits name='moduleA'/>
<set-property name="p" value="1" />
But additionally I want to override the deferred binding configuration of the inherit module to use my own implementation of A. I tried something like this in my module, but it didn't work:
<replace-with class="B1Impl">
<when-type-is class="A"/>
<when-property-is name="p" value="1"/>
</replace-with>
It should say something like this: Do not use A2Impl (declared in inherit module) if property p has the value 1 but use my own implementation B1Impl instead.
Is this possible?
Thanks in advance for any help.
In short, yes, you can redefine any rebind rules that have already been set. Simply inherit the module you are changing, then make your changes after that rebind rule.
<inherits name="package.to.ModuleA" />
<set-property name="p" value="1" />
With the code above, p is always 1, so setting specific rules about what p will be is a little bit silly. Unless p is ever able to be something other than 1, you really don't even need the when-property-is rule.
Your replace-with looks correct as long as it is listed after your inherits statements. For this reason, I always encourage developers to list all inherits rules first, and then go on to any replace-with and generate-with or set-property rules.
For more detail than that, you'll need to post something a little more concrete.

Resty-GWT dynamic code generation

I am using the resty-gwt library and wondering if it would be possible to use the JsonEncoderDecoder interface dynamically?
eg. I have a pojo as follows:
#JsonTypeInfo(use=Id.CLASS, include=As.PROPERTY, property="class")
public class MyObject {....}
With the class name returned in the response: is it possible using generators to generate the interface
public interface MyObjectCodec extends JsonEncoderDecoder<MyObject > {}
and somehow make a call to GWT.create(MyObjectCodec.class)
so that I can decode the object?
I believe you can even if I have never tried.
Extract from restyGWT.gwt.xml
<generate-with class="org.fusesource.restygwt.rebind.RestServiceGenerator">
<when-type-assignable class="org.fusesource.restygwt.client.RestService" />
</generate-with>
<generate-with class="org.fusesource.restygwt.rebind.JsonEncoderDecoderGenerator">
<when-type-assignable class="org.fusesource.restygwt.client.JsonEncoderDecoder" />
</generate-with>
<generate-with class="org.fusesource.restygwt.rebind.DirectRestServiceGenerator">
<when-type-assignable class="org.fusesource.restygwt.client.DirectRestService" />
</generate-with>
So if you are writing a JsonEncoderDecoder the generator should generate the code for you.
You should be able to use the method JSONValue encode(T value) to encode your object in JSONValue
I do not know what you mean by dynamic but IMO it is all "static" meaning it does not really depends on runtime variables or anything.

Does Autofac allow specifying what dependency type should be injected into constructor

Lets say I have EmailService which implments IEmailService. And EmailService has constructor dependency on ILoggingService. Now given that I have several implementations of ILoggingService, can achieve something like this:
<component service="IEmailService, MyInterfaces" type="EmailService, MyLib">
<parameters>
<parameter name="loggingService" value="LoggingService, MyLib" />
</parameters>
</component>
I have looked at giving names to registered types but so far couldn't find an example of how to use them from XML configuration.
In short I want to use XML configuration to specify which concrete logger implementation gets injection.
XML configuration in Autofac is targeted more toward the 80% use case rather than being a full implementation of Autofac's flexibility in XML form. Autofac instead recommends using its module mechanism for configuration. Modules, coupled with the XML configuration, can be a very powerful way to achieve what you're looking to accomplish and still have that flexibility to switch between dependencies as needed.
First, create an Autofac module that does the registration you want:
public class EmailModule
{
protected override void Load(ContainerBuilder builder)
{
// Register a named logging service so we can locate
// this specific one later.
builder.RegisterType<LoggingService>()
.Named<ILoggingService>("emailLogger");
// Create a ResolvedParameter we can use to force resolution
// of the constructor parameter to the named logger type.
var loggingServiceParameter = new ResolvedParameter(
(pi, ctx) => pi.Name == "loggingService",
(pi, ctx) => ctx.ResolveNamed<ILoggingService>("emailLogger"));
// Add the ResolvedParameter to the type registration so it
// knows to use it when resolving.
builder.RegisterType<EmailService>()
.As<IEmailService>()
.WithParameter(loggingServiceParameter);
}
}
Notice it's a little more complex of a registration because you're requiring a very specific resolution.
Now in XML configuration, register that module:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="autofac"
type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
</configSections>
<autofac>
<modules>
<module type="EmailModule, MyAssembly" />
</modules>
</autofac>
</configuration>
When you want to switch configurations, register a different module rather than fiddling with specific component registries.
Code disclaimer: I'm writing the syntax from memory and I'm not a compiler, so you may have to do a little tweaking... but the premise holds. Isolate the complexity in a module, then register your module.

Can't marry GIN and custom bean validator in GWT application (compiler error)

Could you guys help me marry GIN and custom bean validator in GWT application (GWT 2.4) ?
GWT compiler gives me following errors:
Rebind result 'javax.validation.ValidatorFactory' must be a class
Rebind result 'com.google.gwt.validation.client.ProviderValidationMessageResolver' must be a class
My GIN module looks like this
#GinModules(ClientGinModule.class)
public interface ClientGinjector extends Ginjector
{
NewOrderView getOrderView();
}
Where NewOrderView just extends Composite.
In my .gwt.xml of my module I have following instructions
<replace-with class="com.mine.courierApp.client.validation.ClientValidatorFactory">
<when-type-is class="javax.validation.ValidatorFactory"/>
</replace-with>
<replace-with class="com.mine.courierApp.client.validation.ClientValidationMessagesResolver">
<when-type-is class="com.google.gwt.validation.client.UserValidationMessagesResolver"/>
</replace-with>
So I thought maybe GIN wants to know this in Java code so I modified my GIN module which became
public class ClientGinModule extends AbstractGinModule
{
protected void configure()
{
bind(javax.validation.ValidatorFactory.class).to(ClientValidatorFactory.class);
bind(com.google.gwt.validation.client.UserValidationMessagesResolver.class).to(ClientValidationMessagesResolver.class);
}
}
But it didn't help although error message became bigger:
Rebind result 'javax.validation.ValidatorFactory' must be a class
Rebind result 'javax.validation.ValidatorFactory' must be a class
Cannot proceed due to previous errors
Rebind result 'com.google.gwt.validation.client.ProviderValidationMessageResolver' must be a class
Update: Detailed GWT compiler output:
[ERROR] Errors in 'jar:file:/C:/work/externals/gwt/gwt-user.jar!/com/google/gwt/validation/client/BaseMessageInterpolator.java'
[ERROR] Line 96: Rebind result 'com.google.gwt.validation.client.ProviderValidationMessageResolver' must be a class
[ERROR] Errors in 'jar:file:/C:/work/externals/gwt/gwt-user.jar!/com/google/gwt/validation/client/GwtValidatorContext.java'
[ERROR] Line 36: Rebind result 'javax.validation.ValidatorFactory' must be a class
[ERROR] Errors in 'jar:file:/C:/work/externals/gwt/gwt-user.jar!/com/google/gwt/validation/client/spi/GwtValidationProvider.java'
[ERROR] Line 39: Rebind result 'javax.validation.ValidatorFactory' must be a class
[ERROR] Cannot proceed due to previous errors
What shall I do ?
It turned out I have to define
<replace-with class="com.mine.courierApp.client.validation.ClientValidatorFactory">
<when-type-is class="javax.validation.ValidatorFactory"/>
</replace-with>
<replace-with class="com.mine.courierApp.client.validation.ClientValidationMessagesResolver">
<when-type-is class="com.google.gwt.validation.client.UserValidationMessagesResolver"/>
</replace-with>
in all gwt modules, even in those that don't use validation at all.

GWT: is properties global for whole application?

I've got the following config <when-property-is name="isExecute" value="true" />.
Am I able to set property isExecute for module A true and for module B false?
Am I able to change property value by Java?
Does GWT.create read property condition each call or only once (cache)?
What are you trying to achieve? Replacing implementations during runtime? You can use Generator to do this.