GWT Dynamic loading using GWT.create() with String literals instead of Class literals - gwt

GWT.create() is the reflection equivalent in GWT,
But it take only class literals, not fully qualified String for the Class name.
How do i dynamically create classes with Strings using GWT.create()?
Its not possible according to many GWT forum posts but how is it being done in frameworks like Rocket-GWT (http://code.google.com/p/rocket-gwt/wiki/Ioc) and Gwittir (http://code.google.com/p/gwittir/wiki/Introspection)

It is possible, albeit tricky. Here are the gory details:
If you only think as GWT as a straight Java to JS, it would not work. However, if you consider Generators - Special classes with your GWT compiler Compiles and Executes during compilation, it is possible. Thus, you can generate java source while even compiling.
I had this need today - Our system deals with Dynamic resources off a Service, ending into a String and a need for a class. Here is the solutuion I've came up with - btw, it works under hosted, IE and Firefox.
Create a GWT Module declaring:
A source path
A Generator (which should be kept OUTSIDE the package of the GWT Module source path)
An interface replacement (it will inject the Generated class instead of the interface)
Inside that package, create a Marker interface (i call that Constructable). The Generator will lookup for that Marker
Create a base abstract class to hold that factory. I do this in order to ease on the generated source code
Declare that module inheriting on your Application.gwt.xml
Some notes:
Key to understanding is around the concept of generators;
In order to ease, the Abstract base class came in handy.
Also, understand that there is name mandling into the generated .js source and even the generated Java source
Remember the Generator outputs java files
GWT.create needs some reference to the .class file. Your generator output might do that, as long as it is referenced somehow from your application (check Application.gwt.xml inherits your module, which also replaces an interface with the generator your Application.gwt.xml declares)
Wrap the GWT.create call inside a factory method/singleton, and also under GWT.isClient()
It is a very good idea to also wrap your code-class-loading-calls around a GWT.runAsync, as it might need to trigger a module load. This is VERY important.
I hope to post the source code soon. Cross your fingers. :)

Brian,
The problem is GWT.create doen't know how to pick up the right implementation for your abstract class
I had the similar problem with the new GWT MVP coding style
( see GWT MVP documentation )
When I called:
ClientFactory clientFactory = GWT.create(ClientFactory.class);
I was getting the same error:
Deferred binding result type 'com.test.mywebapp.client.ClientFactory' should not be abstract
All I had to do was to go add the following lines to my MyWebapp.gwt.xml file:
<!-- Use ClientFactoryImpl by default -->
<replace-with class="com.test.mywebapp.client.ClientFactoryImpl">
<when-type-is class="com.test.mywebapp.client.ClientFactory"/>
</replace-with>
Then it works like a charm

I ran into this today and figured out a solution. The questioner is essentially wanting to write a method such as:
public <T extends MyInterface> T create(Class<T> clz) {
return (T)GWT.create(clz);
}
Here MyInterface is simply a marker interface to define the range of classes I want to be able to dynamically generate. If you try to code the above, you will get an error. The trick is to define an "instantiator" such as:
public interface Instantiator {
public <T extends MyInterface> T create(Class<T> clz);
}
Now define a GWT deferred binding generator that returns an instance of the above. In the generator, query the TypeOracle to get all types of MyInterface and generate implementations for them just as you would for any other type:
e.g:
public class InstantiatorGenerator extends Generator {
public String generate(...) {
TypeOracle typeOracle = context.getTypeOracle();
JClassType myTYpe= typeOracle.findType(MyInterface.class.getName());
JClassType[] types = typeOracle.getTypes();
List<JClassType> myInterfaceTypes = Collections.createArrayList();
// Collect all my interface types.
for (JClassType type : types) {
if (type.isInterface() != null && type.isAssignableTo(myType)
&& type.equals(myType) == false) {
myInterfaceTypes.add(type);
}
for (JClassType nestedType : type.getNestedTypes()) {
if (nestedType.isInterface() != null && nestedType.isAssignableTo(myType)
&& nestedType.equals(myTYpe) == false) {
myInterfaceTypes.add(nestedType);
}
}
}
for (JClassType jClassType : myInterfaceTypes) {
MyInterfaceGenerator generator = new MyInterfaceGenerator();
generator.generate(logger, context, jClassType.getQualifiedSourceName());
}
}
// Other instantiator generation code for if () else if () .. constructs as
// explained below.
}
The MyIntefaceGenerator class is just like any other deferred binding generator. Except you call it directly within the above generator instead of via GWT.create. Once the generation of all known sub-types of MyInterface is done (when generating sub-types of MyInterface in the generator, make sure to make the classname have a unique pattern, such as MyInterface.class.getName() + "_MySpecialImpl"), simply create the Instantiator by again iterating through all known subtypes of MyInterface and creating a bunch of
if (clz.getName().equals(MySpecialDerivativeOfMyInterface)) { return (T) new MySpecialDerivativeOfMyInterface_MySpecialImpl();}
style of code. Lastly throw an exception so you can return a value in all cases.
Now where you'd call GWT.create(clz); instead do the following:
private static final Instantiator instantiator = GWT.create(Instantiator.class);
...
return instantiator.create(clz);
Also note that in your GWT module xml, you'll only define a generator for Instantiator, not for MyInterface generators:
<generate-with class="package.rebind.InstantiatorGenerator">
<when-type-assignable class="package.impl.Instantiator" />
</generate-with>
Bingo!

What exactly is the question - i am guessing you wish to pass parameters in addition to the class literal to a generator.
As you probably already know the class literal passed to GWT.create() is mostly a selector so that GWT can pick and execute a generator which in the end spits out a class. The easist way to pass a parameter to the generator is to use annotations in an interface and pass the interface.class to GWT.create(). Note of course the interface/class must extend the class literal passed into GWT.create().
class Selector{
}
#Annotation("string parameter...")
class WithParameter extends Selector{}
Selector instance = GWT.create( WithParameter.class )

Everything is possible..although may be difficult or even useless. As Jan has mentioned you should use a generator to do that. Basically you can create your interface the generator code which takes that interface and compile at creation time and gives you back the instance. An example could be:
//A marker interface
public interface Instantiable {
}
//What you will put in GWT.create
public interface ReflectionService {
public Instantiable newInstance(String className);
}
//gwt.xml, basically when GWT.create finds reflectionservice, use reflection generator
<generate-with class="...ReflectionGenerator" >
<when-type-assignable class="...ReflectionService" />
</generate-with>
//In not a client package
public class ReflectionGenerator extends Generator{
...
}
//A class you may instantiate
public class foo implements Instantiable{
}
//And in this way
ReflectionService service = GWT.create(ReflectionService.class);
service.newInstance("foo");
All you need to know is how to do the generator. I may tell you that at the end what you do in the generator is to create Java code in this fashion:
if ("clase1".equals(className)) return new clase1();
else if ("clase2".equals(className)) return new clase2();
...
At the final I thought, common I can do that by hand in a kind of InstanceFactory...
Best Regards

I was able to do what I think you're trying to do which is load a class and bind it to an event dynamically; I used a Generator to dynamically link the class to the event. I don't recommend it but here's an example if it helps:
http://francisshanahan.com/index.php/2010/a-simple-gwt-generator-example/

Not having looked through the code of rocket/gwittir (which you ought to do if you want to find out how they did it, it is opensource after all), i can only guess that they employ deferred binding in such a way that during compile time, they work out all calls to reflection, and statically generate all the code required to implement those call. So during run-time, you cant do different ones.

What you're trying to do is not possible in GWT.
While GWT does a good job of emulating Java at compile time the runtime is of course completely different. Most reflection is unsupported and it is not possible to generate or dynamically load classes at runtime.
I had a brief look into code for Gwittir and I think they are doing their "reflection stuff" at compile time. Here: http://code.google.com/p/gwittir/source/browse/trunk/gwittir-core/src/main/java/com/totsp/gwittir/rebind/beans/IntrospectorGenerator.java

You might be able to avoid the whole issue by doing it on the server side. Say with a service
witch takes String and returns some sort of a serializable super type.
On the server side you can do
return (MySerializableType)Class.forName("className").newInstance();
Depending on your circumstances it might not be a big performance bottleneck.

Related

Add new Constructor to an existing Java Class via AspectJ

Trying to clean up some nasty code, for which we dont have the source code. Imagine something like this:
public class Driver{
private String paramA;
private String paramB;
new Driver(HugeAndOverbloatedObject object)
{
paramA = object.getSubObject4711().getParamX();
paramB = object.getSubObject4712().getParamY();
}
}
This third library has this all over the place: tight coupling via constructors, eventhough the classes are hardly related. The rude combination of private members and forced constructor inheritance make the extension of the code virtually impossible without creating "sloppy" constructor parameter objects.
So I am trying to manipulate the classes via AspectJ and compile time weaving, so I can slim down on the constructors, to something like this:
Driver driver = new Driver("paramA", "paramB");
I think this should be possible, and I have made some progress. If I have something like this:
public aspect NewConstructor {
Driver.new(String parameterA, String parameterB){
//New Constructor Code
}
}
and run this through the weaver I actually find a new constructor in the driver, but not quite as I expected.
Issue: Unexpected third Parameter in the woven class
I was hoping I can invoke it with two parameters:
new Driver("paramA", "paramB")
Instead I need to invoke it with three parameters:
new Driver("paramA", "paramB", new NewConstructor())
Why do I need to instantiate a new instance of the aspect and pass it as an argument? Can this be prevented?
Something odd is going on here. You should not need to add the aspect as a third argument to the constructor. In fact, when I try this myself using the following class and aspect, I do not get any compile errors:
Java class:
package pack;
public class Driver {
public static void main(String[] args) {
new Driver("paramA", "paramB");
}
}
Aspect:
package pack;
public aspect NewConstructor {
public pack.Driver.new(String parameterA, String parameterB){
}
}
Are your Java class and aspect in different projects? Are you using an aspect path and/or in path? Are you using load time weaving?
If after doing a full build of your project you still see the probem, it's worth raising a bug for AspectJ.

custom code generation in xtext

I am using Xtext do define a new language. I wish to generate code from this language, however I do not want to use the automatically suggested doGenerate function. Instead, I need to use a java code (not Xtend), that I can call from the build process.
Of course in that java code I want to be able to use the 'resource' that is passed to the original suggested function, so I can access all the information from the DSL's code.
I Believe by default the generator is implementation is an xtend file but there is nothing stopping you from changing this to a java file, you just need to override the binding in your [LanguageName]RuntimeModule class as follows:-
public class ExampleRuntimeModule extends com.example.AbstractExampleRuntimeModule {
#Override
public Class<? extends IGenerator> bindIGenerator() {
return YourOwnGenerator.class;
}
}
Where YourOwnGenerator should implement IGenerator.

EXT GWT BaseModel needs to have DTO reference?

I am very new to GWT.
I am using ext-gwt widgets.
I found many places in my office code containing like,
class A extends BaseModel{
private UserAccountDetailsDto userAccountDetailsDto = null;
//SETTER & GETTER IN BASEMODEL WAY
}
Also, the DTO reference is unused.
public class UserAccountDetailsDto implements Serializable{
private Long userId=null;
private String userName=null;
private String userAccount=null;
private String userPermissions=null;
//NORMAL SETTER & GETTER
}
Now, I am able to get the result from GWT Server side Code and things Work fine, but when I comment the DTO reference inside the class A, I am not getting any Result.
Please explain me the need of that.
Thanks
Well the problem is in implementation of GXT BaseModel and GWT-RPC serialization.
BaseModel is based around special GXT map, RpcMap. This map has defined special serialization rules, which let's avoid RPC type explosion, but as side effect, only some simple types stored in map will be serialized. E.g. you can put any type inside the map, but if you serialize/deserialize it, only values of type Integer, String ,Double,Byte, Float and Short (and arrays of this types) will be present. So the meaning behind putting reference to the DTO inside BaseModel, is to tell GWT-RPC that this type is also have to be serialized.
Detailed explanation
Basically GWT-RPC works like this:
When you define an interface for service, GWT-RPC analyzes all the classes used in parameters/ return type, to create serializers/deserializers. If you return something like Map<Object,Object> from your service, GWT-RPC will have to create a serializer for each class which implements Map and Serializable interfaces, but also it will generate serializers for each class which implements Serializable. In the end it is quite a bad situation, because the size of your compiled js file will be much biggger. This situation is called GWT-RPC type explosion.
So, in the BaseModel, all values are stored in RpcMap. And RpcMap has custom written serializer (RpcMap_CustomFieldSerializer you can see it's code if you interested how to create such things), so it doesn't cause the problem described above. But since it has custom serializer GWT dosn't know which custom class have been put inside RpcMap, and it doesn't generate serializers for them. So when you put some field into your BaseModel class, gwt knows that it might need to be able to serialize this class, so it will generate all the required stuff for this class.
Porting GXT2 Application code using BaseModel to GXT3 Model is uphill task. It would be more or less completely rewrite on model side with ModelProviders from GXT3 providing some flexibility. Any code that relies on Model's events, store, record etc are in for a rewrite.

How to use GWT SerializationStreamFactory

I am trying to serialize a object in GWT using SerializationFactory, but I am not able to get it working. Here is the sample code of my POC:
import com.google.gwt.user.client.rpc.SerializationException;
import com.google.gwt.user.client.rpc.SerializationStreamFactory;
import com.google.gwt.user.client.rpc.SerializationStreamReader;
import com.google.gwt.user.client.rpc.SerializationStreamWriter;
...........
Some code here....
.........
......
SerializationStreamFactory factory = (SerializationStreamFactory) GWT.create(MyClass.class);
SerializationStreamWriter writer = factory.createStreamWriter();
try {
writer.writeObject(new MyClass("anirudh"));
String value = writer.toString();
SerializationStreamReader reader = factory.createStreamReader(value);
MyClass myObj = (MyClass) reader.readObject();
System.out.println(myObj.getName());
} catch (SerializationException e) {
e.printStackTrace();
}
It gave me the following exception
Caused by: java.lang.RuntimeException: Deferred binding failed for 'com.anirudh..client.MyClass' (did you forget to inherit a required module?)
also in my code the class whose object I am trying to serialize implements IsSerializable
MyClass implements IsSerializable
I don't want to use GWT Auto-Bean framework because it does not fit my use case. Also I am not using GWT-RPC framework and right now I am quite adamant about using SerializationStreamFactory :D because I seriously want to know how this thing works.
Can anyone share a working example of SerializationStreamFactory or help me out pointing any mistake(s) I did.
Thanks in advance
SerializationStreamFactory factory = (SerializationStreamFactory) GWT.create(MyClass.class);
What are you expecting this line to do? GWT will attempt to find a replace-with or generate-with rule that matches this class (either when-type-assignable or when-type-is), or failing that will attempt to invoke a zero-arg constructor on MyClass, effectively new MyClass(). Is this what you are expecting?
The selected exception you've pasted suggests that MyClass may not be on the source path that GWT has been given to compile from, but the full error log will provide more information.
It looks as though you are trying to mimic the generated RPC code, where a *Async rpc interface would be implemented by code that extends from com.google.gwt.user.client.rpc.impl.RemoteServiceProxy (which implements SerializationStreamFactory). That base implementation is extended further to initialize several fields such as the com.google.gwt.user.client.rpc.impl.Serializer instance, actually responsible for serializing and deserializing object streams.
Serializers are created (by default) from the base class of com.google.gwt.user.client.rpc.impl.SerializerBase, through the rebind class com.google.gwt.user.rebind.rpc.TypeSerializerCreator. If you've build your own generator for MyClass, you should be kicking this off to get the work done as ProxyCreator already should be doing.
Remember when building your own serialization/deserialization mechanism that you need to decide which types can be marshalled within this system - if you open it to all types, then you will need to generate FieldSerializer types for all possible objects on the source path. This will greatly expand the size of your compiled code.
If your main goal is learning how this 'magic' works, dig into the generators and associated code that live in the com.google.gwt.user.rebind.rpc package. There are other libraries that leverage these ideas such as the gwt-atmosphere project (see https://github.com/Atmosphere/atmosphere to get started). Also review the generated code that GWT creates when it builds a 'tradition' RPC interface.

Dependency injection not working in gwt 2.1

I have a new project where I am using GWT-Views like Composite, etc.
I have injected the items in the main menu (like ProductList below) using GinInjector. This works fine!
Somewhere I want to have a reference from a small component to an item from my main menu in order to update it. I try to inject it this way:
public class ProductForm extends Composite {
...
#Inject
ProductList list;
....
}
But when I use the list I always get null. Whereby, ProductList is defined this way:
public class MyModule extends AbstractGinModule {
...
#Override
protected void configure() {
bind(ProductList.class).asEagerSingleton();
bind(ProductForm.class).asEagerSingleton();
}
...
}
Any idea what I am doing wrong?!
Solution:
I failed to mention that ProductForm is an element of the ProductList using the UIBinder's #UIField tag, So That injecting it will create a new object rather than the one created using UIBinder.
I had to restructure my code to include presenters and an event bus so that no direct references between views are needed (other than the #UIField attributes).
I was working through Gin documentation : I'll quote it here :
Gin "Magic"
Gin tries to make injection painless and remove as much boilerplate from your code as possible. To do that the generated code includes some magic behind the scenes which is explained here.
Deferred Binding
One way Gin optimizes code is by automating GWT deferred binding. So if you inject an interface or class1 bound through deferred binding (but not through a Guice/Gin binding), Gin will internally call GWT.create on it and inject the result. One example are GWT messages and constants (used for i18n purposes):
public interface MyConstants extends Constants {
String myWords();
}
public class MyWidget {
#Inject
public MyWidget(MyConstants myconstants) {
// The injected constants object will be fully initialized -
// GWT.create has been called on it and no further work is necessary.
}
}
Note: Gin will not bind the instances created through GWT.create in singleton scope. That should not cause unnecessary overhead though, since deferred binding generators usually implement singleton patterns in their generated code.
You can see for yourself in this URL : http://code.google.com/p/google-gin/wiki/GinTutorial
It fails to mention why a singleton cannot be autogenerated by deferred binding and injected.
You can fix this by handcreating, using GWT.create(YourFactoryInterface.class).getProductList() in the constructor.
This means for testing puposes, you will need to pull the GWT.create into a seperate method and override it in a subclass and use that for testing like :
YourFactoryInterface getFactory() {
return GWT.create(YourFactoryInterface.class)
}
and
getFactory().getProductList()
Gin's asEagerSingleton() binding was broken for quite a while, and was injecting null. Not sure when the fix went in, but I had problems with eager singletons on v1.0. See the issue or the explanation, if you're interested. I'd either switch to regular .in(Singleton.class) bindings, or make sure you're using Gin 1.5.
Is the Ginjector creating the ProductForm? I think maybe that is needed to make it populate the injected variable.