I am trying to understand GWT generators but facing few issues. I am trying to display the compile time in an app using generators and running into this error -
Rebind result 'com.example.client.Function' must be a class
Here is what i have -
This is how i am calling my generated method -
Function b = GWT.create(Function.class);
label.setText(b.getBuildTime());
gwt.xml-
<generate-with class="example.frontend.client.gin.FunctionGenerator">
<when-type-assignable class="com.example.frontend.client.gin.Function" />
</generate-with>
Function.java
package com.example.frontend.client.gin;
public interface Function{
public String getBuildTime();
}
Generator class -
package com.example.frontend.egenerator;
import java.io.PrintWriter;
import java.util.Date;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import com.example.frontend.client.gin.Function;
public class FunctionGenerator extends Generator {
private static final String IMPL_TYPE_NAME = Function.class.getSimpleName() + "Impl";
private static final String IMPL_PACKAGE_NAME = Function.class.getPackage().getName();
@Override
public String generate(final TreeLogger logger, final GeneratorContext context, final String requestedClass) throws UnableToCompleteException {
TypeOracle typeOracle = context.getTypeOracle();
JClassType functionType = typeOracle.findType(requestedClass);
assert Function.class.equals(functionType.getClass());
ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(IMPL_PACKAGE_NAME, IMPL_TYPE_NAME);
composerFactory.addImport(Function.class.getCanonicalName());
composerFactory.addImplementedInterface(Function.class.getName());
PrintWriter printWriter = context.tryCreate(logger, IMPL_PACKAGE_NAME, IMPL_TYPE_NAME);
SourceWriter sourceWriter = composerFactory.createSourceWriter(context, printWriter);
if(sourceWriter != null) {
sourceWriter.print("public String getBuildTime() {");
sourceWriter.print(" return \"" + new Date() + "\" ;");
sourceWriter.print("}");
sourceWriter.commit(logger);
}
return IMPL_PACKAGE_NAME + "." + IMPL_TYPE_NAME;
}
}
Any ideas, what I am missing?
I believe you also need to null check the
PrintWritercreated bytryCreate, as it may return null. On the other hand,createSourceWriterwill not return null, so no need to null check that.Your generate-with is also incorrect, at least for the sample that you have here. It should have a different package (according to your
FunctionGeneratorsource at least),com.example.frontend.egenerator, notcom.example.frontend.client.gin:In general, your generators should not be in the
clientpackage, if for no other reason than preventing spurious errors which slow down the compiler (and really slow down super dev mode).Beyond that, the full log could help a lot to track down the issue, though without mapping the generator correctly there wouldn't be much of an error. Also be sure to compile with
strictturned on when working on generators to ensure that the compiler fails as soon as possible and you can stop at the very first error.With all of that said, tend to avoid new Generators at this point - they will slow down Super Dev Mode slightly (since they must be re-run every time you refresh), and they will not be supported in future versions of GWT. Annotation Processors (aka APT) are the preferred way to do this, but in your case you might also just be able to generate the class in ant or maven with a plugin.