Are there any way not to define all Places in the PlaceHistoryMapper?
At this moment I am using Generator in order to generate list of all places automatically, but I am not sure that this is a correct way.
public class AppPlaceHistoryMapper extends AbstractPlaceHistoryMapper<Object> {
#Override
protected PrefixAndToken getPrefixAndToken(Place place) {
if (place instanceof AbstractPlace) {
return new PrefixAndToken(((AbstractPlace) place).getName(), ((AbstractPlace) place).getTokenizer()
.getToken((AbstractPlace) place));
}
throw new RuntimeException("Invalid place: " + place);
}
/**
* This method will be overrided by the gwt-generated class, so any changes made in it will not be executed
*
* #see PlaceMapperGenerator
*/
#Override
protected PlaceTokenizer<?> getTokenizer(String prefix) {
AbstractPlace[] places = {/* List of places generated by PlaceMapperGenerator */};
for (AbstractPlace p : places) {
if (p.getName().equals(prefix)) {
return p.getTokenizer();
}
}
throw new RuntimeException("Unable to find place for provided prefix: " + prefix);
}
}
Generator:
public class PlaceMapperGenerator extends Generator {
// #formatter:off
private static final String GENERATED_METHOD_TEMPLATE =
"protected com.google.gwt.place.shared.PlaceTokenizer<?> getTokenizer(String prefix) {" +
"AbstractPlace[] places = { %s };" +
"for (AbstractPlace p : places) {" +
"if (p.getName().equals(prefix)) {" +
"return p.getTokenizer();" +
"}" +
"}" +
"throw new RuntimeException(\"Unable to find place for provided prefix: \" + prefix);" +
"}"
; // #formatter:on
#Override
public String generate(TreeLogger logger, GeneratorContext context, String typeName) {
JClassType type;
try {
type = context.getTypeOracle().getType(typeName);
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
String implTypeName = type.getSimpleSourceName() + "Impl";
String implPackageName = type.getPackage().getName();
ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(implPackageName,
implTypeName);
composerFactory.setSuperclass(AppPlaceHistoryMapper.class.getName());
#SuppressWarnings("resource")
PrintWriter printWriter = context.tryCreate(logger, implPackageName, implTypeName);
if (printWriter != null) {
SourceWriter sourceWriter = composerFactory.createSourceWriter(context, printWriter);
sourceWriter.print(GENERATED_METHOD_TEMPLATE, getPlaces(context));
sourceWriter.commit(logger);
printWriter.close();
}
return composerFactory.getCreatedClassName();
}
private static String getPlaces(GeneratorContext context) {
JPackage[] packages = context.getTypeOracle().getPackages();
List<String> places = new ArrayList<String>();
for (JPackage p : packages) {
if (p.getName().startsWith(AbstractPlace.class.getPackage().getName())) {
JClassType[] types = p.getTypes();
for (JClassType type : types) {
if (type.getSuperclass() != null
&& type.getSuperclass().getQualifiedSourceName().equals(AbstractPlace.class.getName())) {
places.add("new " + type.getQualifiedSourceName() + "()");
}
}
}
}
return places.toString().replaceAll("^\\[|\\]$", "");
}
}
I'm afraid that the only way to figure out what Places and Tokenizers are in your application, without maintaining a list with them, is with a generator like you are doing.
Anyway instead of maintaining a generator I would use the #WithTokenizers annotation and let GWT generate your PlaceHistoryMapper take a look to the GWT MVP dev-guide
#WithTokenizers({HelloPlace.Tokenizer.class, GoodbyePlace.Tokenizer.class})
public interface AppPlaceHistoryMapper extends PlaceHistoryMapper {}
What I do in my applications is to use a script to generate activities, views, places and update gin modules and mappers based on a template.
Related
I passing a JSON string (inputJson) to my java code (PPProgramAddView) on the server side.
PPProgramAddView:
inputJson: [{"ppl_row":0,"ppl_time":"07:00","ppat_id":"Mw==","ppa_id":"MTI=","ppl_LeadAssist":"Lead"},{"ppl_row":1,"ppl_time":"07:10","ppat_id":"Mg==","ppa_id":"NA==","ppl_LeadAssist":"Assist"}]
When I try to process it I get the following error:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "ppl_row" (class client.Profile14), not marked as ignorable (5 known properties: "plTime", "plActivity", "plActivityType", "plRow", "plLeadAssist"])
at [Source: (String)"[{"ppl_row":0,"ppl_time":"07:00","ppat_id":"Mw==","ppa_id":"MTI=","ppl_LeadAssist":"Lead"},{"ppl_row":1,"ppl_time":"07:10","ppat_id":"Mg==","ppa_id":"NA==","ppl_LeadAssist":"Assist"}]"; line: 1, column: 14] (through reference chain: java.lang.Object[][0]->client.Profile14["ppl_row"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
I have done a search and I can not find '"plTime", "plActivity", "plActivityType", "plRow", "plLeadAssist"' anywhere.
My code is:
//Look through the new program lines and add them.
try {
ObjectMapper mapper = new ObjectMapper();
Profile14[] profiles14 = mapper.readValue(inputJson, Profile14[].class);
for (final Profile14 programLine : profiles14) {
String ppl_row = programLine.getplRow();
String ppl_time = null;
if (programLine.getplTime().length() < 1){
ppl_time = "00:01";
}else{
ppl_time = programLine.getplTime();
}
String ppat_id_encoded = programLine.getplActivityType();
String ppa_id_encoded = programLine.getplActivity();
String ppl_LeadAssist = programLine.getplLeadAssist().substring(0, Math.min(programLine.getplLeadAssist().length(), 45));
byte[] valueDecoded3 = Base64.decodeBase64(ppat_id_encoded);//decoding part
String ppat_id = new String(valueDecoded3);
byte[] valueDecoded4 = Base64.decodeBase64(ppa_id_encoded);//decoding part
String ppa_id = new String(valueDecoded4);
System.out.println("ppID: " + ppID + " ppat_id: " + ppat_id + " ppa_id: " + ppa_id +
" ppl_row : " + ppl_row + " ppl_time: " + ppl_time + " ppl_LeadAssist: " + ppl_LeadAssist);
MySQLConnection.addPPProgramLine(ppID, ppat_id, ppa_id, ppl_row, ppl_time, ppl_LeadAssist);
}
} catch (Exception e) {
e.printStackTrace();
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Error.");
}
}
}
class Profile14 {
private String ppl_row;
private String ppl_time;
private String ppat_id;
private String ppa_id;
private String ppl_LeadAssist;
public String getplRow() {
return ppl_row;
}
public void setplRow(String ppl_row) {
this.ppl_row = ppl_row;
}
public String getplTime() {
return ppl_time;
}
public void setplTime(String ppl_time) {
this.ppl_time = ppl_time;
}
public String getplActivityType() {
return ppat_id;
}
public void setplActivityType (String ppat_id) {
this.ppat_id = ppat_id;
}
public String getplActivity() {
return ppa_id;
}
public void setplActivity(String ppa_id) {
this.ppa_id = ppa_id;
}
public String getplLeadAssist() {
return ppl_LeadAssist;
}
public void setplLeadAssist(String ppl_LeadAssist) {
this.ppl_LeadAssist = ppl_LeadAssist;
}
#Override
public String toString() {
return "Profile14 [ppl_row=" + ppl_row + ", ppl_time=" + ppl_time + ", ppat_id=" + ppat_id
+ ", ppa_id=" + ppa_id + ", ppl_LeadAssist=" + ppl_LeadAssist + "]";
}
}
You aren't following JavaBean standards, and without explicit instructions Jackson doesn't know how to map your class.
The Java convention is to name properties like pplRow, and your JSON is using the alternate Ruby style of ppl_row. There are three options:
Switch the entire Jackson engine to use an alternate style. (Not a great idea since it tends to cause collisions.
Tell Jackson to use an alternate style for particular Java classes. (We'll do this.)
Annotate each property with #JsonProperty (works, but lots of extra effort).
Start by using standard Java naming for your properties:
class Profile14 {
private String pplRow;
public String getPplRow() {
return this.pplRow;
}
public void setPplRow(String s) {
this.pplRow = s;
}
}
Note that the naming of the methods is what defines the properties (since the backing field is private and technically doesn't have to exist). Your existing properties both don't match the names (pl instead of ppl) and don't have the proper capitalization.
Now add this annotation to your class:
#JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
This tells Jackson to use snake_case for naming all of the properties. This should be enough to get your mapping working.
I'm trying to integrate my application with Bukkit - A Minecraft Server API.
Basically, I'm trying to figure out how could I get functionality like this to work:
Reflections reflections = new Reflections("com.mycompany");
Set<Class<? extends BlockEvent>> classes = reflections.getSubTypesOf(BlockEvent.class);
for (Class<? extends BlockEvent> clazz : classes) {
getServer().getPluginManager().registerEvents(new BlockListener<clazz>(), this);
}
I want to register a listener for all event types that extend BlockEvent. Events are registered by passing an implemention of Listener into the registerEvents(Listener, Plugin) method exposed by the Bukkit API's PluginManager. Obviously clazz is not a type and cannot be used as such.
Here is the generic class:
public class BlockListener<T extends BlockEvent> implements Listener {
#EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
void onBlock(T event) {
System.out.println("Block Event");
Bukkit.getPluginManager().callEvent(new BlockChangeEvent(event.getBlock()));
}
}
Update
public Map<Class<? extends Event>, Set<RegisteredListener>> createRegisteredListeners(#NotNull Listener listener, #NotNull final Plugin plugin) {
Validate.notNull(plugin, "Plugin can not be null");
Validate.notNull(listener, "Listener can not be null");
boolean useTimings = server.getPluginManager().useTimings();
Map<Class<? extends Event>, Set<RegisteredListener>> ret = new HashMap<Class<? extends Event>, Set<RegisteredListener>>();
Set<Method> methods;
try {
Method[] publicMethods = listener.getClass().getMethods();
Method[] privateMethods = listener.getClass().getDeclaredMethods();
methods = new HashSet<Method>(publicMethods.length + privateMethods.length, 1.0f);
for (Method method : publicMethods) {
methods.add(method);
}
for (Method method : privateMethods) {
methods.add(method);
}
} catch (NoClassDefFoundError e) {
plugin.getLogger().severe("Plugin " + plugin.getDescription().getFullName() + " has failed to register events for " + listener.getClass() + " because " + e.getMessage() + " does not exist.");
return ret;
}
for (final Method method : methods) {
final EventHandler eh = method.getAnnotation(EventHandler.class);
if (eh == null) continue;
// Do not register bridge or synthetic methods to avoid event duplication
// Fixes SPIGOT-893
if (method.isBridge() || method.isSynthetic()) {
continue;
}
final Class<?> checkClass;
if (method.getParameterTypes().length != 1 || !Event.class.isAssignableFrom(checkClass = method.getParameterTypes()[0])) {
plugin.getLogger().severe(plugin.getDescription().getFullName() + " attempted to register an invalid EventHandler method signature \"" + method.toGenericString() + "\" in " + listener.getClass());
continue;
}
final Class<? extends Event> eventClass = checkClass.asSubclass(Event.class);
method.setAccessible(true);
Set<RegisteredListener> eventSet = ret.get(eventClass);
if (eventSet == null) {
eventSet = new HashSet<RegisteredListener>();
ret.put(eventClass, eventSet);
}
for (Class<?> clazz = eventClass; Event.class.isAssignableFrom(clazz); clazz = clazz.getSuperclass()) {
// This loop checks for extending deprecated events
if (clazz.getAnnotation(Deprecated.class) != null) {
Warning warning = clazz.getAnnotation(Warning.class);
WarningState warningState = server.getWarningState();
if (!warningState.printFor(warning)) {
break;
}
plugin.getLogger().log(
Level.WARNING,
String.format(
"\"%s\" has registered a listener for %s on method \"%s\", but the event is Deprecated. \"%s\"; please notify the authors %s.",
plugin.getDescription().getFullName(),
clazz.getName(),
method.toGenericString(),
(warning != null && warning.reason().length() != 0) ? warning.reason() : "Server performance will be affected",
Arrays.toString(plugin.getDescription().getAuthors().toArray())),
warningState == WarningState.ON ? new AuthorNagException(null) : null);
break;
}
}
final CustomTimingsHandler timings = new CustomTimingsHandler("Plugin: " + plugin.getDescription().getFullName() + " Event: " + listener.getClass().getName() + "::" + method.getName() + "(" + eventClass.getSimpleName() + ")", pluginParentTimer); // Spigot
EventExecutor executor = new EventExecutor() {
#Override
public void execute(#NotNull Listener listener, #NotNull Event event) throws EventException {
try {
if (!eventClass.isAssignableFrom(event.getClass())) {
return;
}
// Spigot start
boolean isAsync = event.isAsynchronous();
if (!isAsync) timings.startTiming();
method.invoke(listener, event);
if (!isAsync) timings.stopTiming();
// Spigot end
} catch (InvocationTargetException ex) {
throw new EventException(ex.getCause());
} catch (Throwable t) {
throw new EventException(t);
}
}
};
if (false) { // Spigot - RL handles useTimings check now
eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled()));
} else {
eventSet.add(new RegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled()));
}
}
return ret;
}
Specifically
method.getParameterTypes()[0]
Does not work with generics.
You can create a generic method which returns you the BlockEventListenerObject, something like this:
private static <T extends BlockEvent> BlockEventListener<T> getBlockEventListener(Class<T> clazz) {
return new BlockEventListener<T>();
}
Then you can call it from your loop,
getServer().getPluginManager().registerEvents(getBlockEventListener(clazz), this);
„…Basically how could I get functionality like this to work…“
Here is one way…
...
public void use( final Set< Class < ? extends BlockEvent > > classes, PluginManager pluginMgr ) throws ReflectiveOperationException {
for( Class < ? extends BlockEvent > clazz : ( classes ) ){
pluginMgr.registerEvents( new BlockListener< >( clazz.newInstance( ) ), this );
}
}
...
I've implemented some stand-in classes to make the experiment testable. I used the experimental classes like this…
...
final Set< Class < ? extends BlockEvent > > classes = new HashSet< >( );
classes.add( BlockParty.class );
final PluginManager pluginMgr = new PluginManager( );
final Deduper experimental = new DeduperAnswer( );
experimental.use( classes, pluginMgr );
...
Click the green Start button at the top of the page and observe this output…
BlockChangeEvent [ block: Block#404b9385 ]
Havana Block Party!
EXPERIMENT SUCCESSFUL
I have an class with "T extends StorageClass". You can extend this class and put another class instend of the "T" for example "GroupStorage extends Storage. In the "Storage" class is an method called "get". Now i want that method to convert json to the "T" class, in my case to the "Group" class. Maybe you will understand when you look to the code below.
public abstract class Storage<T extends StorageClass> {
// This should return whatever T is.
public T get(String groupName) {
T t = null;
File file = new File(this.groupFolderPath, groupName + ".json");
if (file.exists()) {
try {
FileReader reader = new FileReader(file);
// 'T.class' is not possible
t = Storage.GSON.fromJson(reader, T.class);
} catch (Exception e) {
e.printStackTrace();
Bukkit.getLogger().warning("Failed to read " + groupName + ".json!");
}
} else {
Bukkit.getLogger().warning("The group " + groupName + " does not exists!");
}
return t;
}
}
You would have to pass down the type of the class to your method as :
public T get(String groupName, Class<T> type)
and then use it as :
t = Storage.GSON.fromJson(reader, type);
I'm using UNIVOCITY-PARSERS for converting csv file rows into java objects.
while processing the file, if it encounters any problem any of the column in row, then it parsing getting stopped in that row and throwing exception. But i need something which will continue till end of the file just by skipping the row which has error. But i didn't any utility classes in the api.
MY Bean class
public class ItemcodeBean {
#Trim
#NullString(nulls = { " ", "" })
#Parsed(field = "ItemCode")
private String itemCode;
#Trim
#NullString(nulls = { " ", "" })
#Parsed(field = "PartNumber")
private String partNumber;
#Trim
#NullString(nulls = { " ", "" })
#Parsed(field = "ModelNumber")
private String modelNumber;
}
My Main Class
public class TestClass {
private BeanListProcessor<ItemcodeBean>
rowProcessor = null;
private CsvParser parser = null;
public static void main(String[] args) {
TestClass testClass = new TestClass();
testClass.init();
try{
ItemcodeBean itemcodeBean;
while ((itemcodeBean = testClass.getRowData()) != null){
System.out.println(itemcodeBean.toString());
}
}catch (Throwable ex){
System.out.println(ex.getLocalizedMessage());
}
}
private BeanListProcessor<ItemcodeBean> init() {
// BeanListProcessor converts each parsed row to an instance of a given class, then stores each instance into a list.
this.rowProcessor =
new BeanListProcessor<ItemcodeBean>(ItemcodeBean.class);
CsvParserSettings parserSettings = new CsvParserSettings();
parserSettings.setProcessor(rowProcessor);
parserSettings.setHeaderExtractionEnabled(true);
// skip leading whitespaces
parserSettings.setIgnoreLeadingWhitespaces(true);
//skip trailing whitespaces
parserSettings.setIgnoreTrailingWhitespaces(true);
//skip empty lines
parserSettings.setSkipEmptyLines(true);
File file = new File("C:\\Users\\abhishyam.c\\Downloads\\Itemcode_Template.csv");
this.parser = new CsvParser(parserSettings);
//parser.parse(file);
parser.beginParsing(file);
return rowProcessor;
}
private ItemcodeBean getRowData() throws Throwable {
String[] row;
try {
while ((row = parser.parseNext()) != null){
return rowProcessor.createBean(row, parser.getContext());
}
}catch (DataProcessingException e){
throw new DataProcessingException(e.getColumnName(),e);
}
// parser.stopParsing();
return null;
}
}
Just use an error handler and it will keep going unless you throw the exception yourself:
//Let's set a RowProcessorErrorHandler to log the error. The parser will keep running.
settings.setProcessorErrorHandler(new RowProcessorErrorHandler() {
#Override
public void handleError(DataProcessingException error, Object[] inputRow, ParsingContext context) {
println(out, "Error processing row: " + Arrays.toString(inputRow));
println(out, "Error details: column '" + error.getColumnName() + "' (index " + error.getColumnIndex() + ") has value '" + inputRow[error.getColumnIndex()] + "'");
}
});
UPDATE: You can prevent the row to be discarded by using a RetryableErrorHandler instead. This is a special implementation added to version 2.3.0, and allows the user to call the methods setDefaultValue() to assign a value to the problematic column, and keepRecord to prevent the record from being discarded.
Example:
settings.setProcessorErrorHandler(new RetryableErrorHandler<ParsingContext>() {
#Override
public void handleError(DataProcessingException error, Object[] inputRow, ParsingContext context) {
//if there's an error in the first column, assign 50 and proceed with the record.
if (error.getColumnIndex() == 0) {
setDefaultValue(50);
} else { //else keep the record anyway. Null will be used instead.
keepRecord();
}
}
});
Note that if error.getColumnIndex() returns -1, there's nothing that can be done to save the record, and it will be skipped regardless. You can use this to log the error details.
I have a very strange error, occurring only in chrome and safari.
I get an UmbrellaException when calling GWT.Create(foo.class); (Deferred binding)
Anyone any idea?
I figuerd out that java script throws an umbrella exception with the following javascript:
function entry_0(jsFunction){
return function(){
try {
return entry0(jsFunction, this, arguments);
}
catch (e) {
throw e;
Uncaught com.google.web.bindery.event.shared.UmbrellaException: Exception caught: Exception caught: null
}
}
;
}
In gwt its on the specific java code
IAmsPresenterFactory factory = (IAmsPresenterFactory) GWT.create(IReflectiveAmsFactory.class);
where IReflectiveAmsFactory is to create instances by class name (string)... (class for name gwt)
public class IReflectiveAmsFactory implements IAmsFactoryWrapper {
}
public interface IAmsPresenterFactory {
IDynamicAmsPresenter newInstance(String className, AmsClientFactory clientfactory, String id);
}
<generate-with class="ch.zhaw.ams.server.ams.AmsPresenterGenerator">
<when-type-assignable class="ch.zhaw.ams.client.ams.IAmsFactoryWrapper" />
</generate-with>
Full code snippet:
Request<IModuleBaseProxy> req = clientfactory.getRequestFactory().moduleRequest().findModuleBase(modtoken);
req.fire(new Receiver<IModuleBaseProxy>() {
#Override
public void onSuccess(IModuleBaseProxy response) {
System.out.println("found");
if (response != null) {
---> HERE
IAmsPresenterFactory factory = (IAmsPresenterFactory) GWT
---> ERROR .create(IReflectiveAmsFactory.class);
String clazz = response.getConfigSite();
AmsClientFactory apcf = null;
if (clientfactory == null) {
apcf = new AmsClientFactory();
} else {
apcf = clientfactory;
}
IDynamicAmsPresenter p = factory.newInstance(clazz, apcf, modtoken);
HasWidgets content = view.getContent();
// ContentPresenter contentPresenter = new
// ContentPresenter(apcf, p, new
// ContentView(modtoken));
p.go(content);
}
}
});
My Generator Class:
import java.io.PrintWriter;
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.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
public class AmsPresenterGenerator extends Generator {
#Override
public String generate(TreeLogger logger, GeneratorContext context, String typeName)
throws UnableToCompleteException {
logger.log(TreeLogger.INFO, "Generating source for " + typeName, null);
TypeOracle typeOracle = context.getTypeOracle();
JClassType clazz = typeOracle.findType(typeName);
if (clazz == null) {
logger.log(TreeLogger.ERROR, "Unable to find metadata for type '" + typeName + "'", null);
throw new UnableToCompleteException();
}
try {
logger.log(TreeLogger.INFO, "Generating source for " + clazz.getQualifiedSourceName(), null);
JClassType reflectableType = typeOracle.getType("ch.zhaw.ams.client.ams.IDynamicAmsPresenter");
SourceWriter sourceWriter = getSourceWriter(clazz, context, logger);
if (sourceWriter != null) {
sourceWriter.println("public " + reflectableType.getQualifiedSourceName()
+ " newInstance(String className, AmsClientFactory clientfactory, String id) {");
JClassType[] types = typeOracle.getTypes();
int count = 0;
for (int i = 0; i < types.length; i++) {
// System.out.println(""+types[i].getName());
if (types[i].isInterface() == null && types[i].isAssignableTo(reflectableType)) {
System.out.println("Done:" + types[i].getName());
if (count == 0) {
sourceWriter.println(" if(\"" + types[i].getQualifiedSourceName()
+ "\".equals(className)) {" + " return new " + types[i].getQualifiedSourceName()
+ "(clientfactory, id);" + "}");
} else {
sourceWriter.println(" else if(\"" + types[i].getQualifiedSourceName()
+ "\".equals(className)) {" + " return new " + types[i].getQualifiedSourceName()
+ "(clientfactory, id);" + "}");
}
count++;
}
}
sourceWriter.println("return null;");
sourceWriter.println("}");
sourceWriter.commit(logger);
logger.log(TreeLogger.INFO, "Done Generating source for " + clazz.getName(), null);
return clazz.getQualifiedSourceName() + "Wrapper";
}
} catch (NotFoundException e) {
e.printStackTrace();
}
return null;
}
public SourceWriter getSourceWriter(JClassType classType, GeneratorContext context, TreeLogger logger) {
String packageName = classType.getPackage().getName();
String simpleName = classType.getSimpleSourceName() + "Wrapper";
ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(packageName, simpleName);
composer.addImplementedInterface("ch.zhaw.ams.client.ams.IAmsPresenterFactory");
PrintWriter printWriter = context.tryCreate(logger, packageName, simpleName);
if (printWriter == null) {
return null;
} else {
SourceWriter sw = composer.createSourceWriter(context, printWriter);
return sw;
}
}
}
I solved the issue with upgrading to GWT 2.5.1
Having Compiler Arguments
-XdisableCastChecking
And VM Arguments
-Xmx512m -Xss16M
I think it is problem with Deferred Binding. it is very much browser dependent. As I know if you want to write any browser dependent or locale dependent code like GUI change, then you have to create instance of it instead of use different Deferred Binding.
As you say it works in firefox because it might compile with firefox and generating firefox versions of code at compile time. and loaded by a particular firefox during bootstrapping at runtime and not for others client.
Deferred binding is a feature of the GWT compiler that works by generating many versions of code at compile time, only one of which needs to be loaded by a particular client during bootstrapping at runtime.
Mostly internationalized applications or GWT RPC calls you will be using deferred binding
For more information check the GWT page on Deferred binding:
Coding Basics - Deferred Binding