We are using Google App Engine to publish some flat data from our application in a csv format. Google's DataTable and CsvRenderer from visualization-datasource library made the conversion of our data easy and testing succeeded in the local appengine development server.
Deploying to our appspot instance exposed that App Engine does not like the way IBM's ICU library is Logging:
Google App Engine does not support subclasses of java.util.logging.Logger: com/ibm/icu/impl/ICULogger
The stack trace shows the point of origin:
Caused by: java.lang.SecurityException: Google App Engine does not support subclasses of java.util.logging.Logger: com/ibm/icu/impl/ICULogger
at com.google.appengine.runtime.Request.process-0b3cd097cad783e6(Request.java)
at java.lang.ClassLoader.loadClass(ClassLoader.java:360)
at com.ibm.icu.util.TimeZone.<clinit>(TimeZone.java:114)
Line 114 of TimeZone:
/**
* {@icu} A logger for TimeZone. Will be null if logging is not on by way of system
* property: "icu4j.debug.logging"
* @draft ICU 4.4
* @provisional This API might change or be removed in a future release.
*/
public static ICULogger TimeZoneLogger = ICULogger.getICULogger(TimeZone.class.getName());
I put a breakpoint in Eclipse and ran the unit tests in the debugger and TimeZoneLogger is being assigned null since there is no System property turning on the logging as seen further:
/**
* Instantiates a new ICULogger object with logging turned off by default
* unless the system property "icu4j.debug.logging" is set to "all"
*
* @param name to be use by the logger (usually is the class name)
* @param resourceBundleName name to localize messages (can be null)
* @return a new ICULogger object
* @draft ICU 4.4
* @provisional This API might change or be removed in a future release.
*/
public static ICULogger getICULogger(String name, String resourceBundleName) {
LOGGER_STATUS flag = checkGlobalLoggingFlag();
if (flag != LOGGER_STATUS.NULL) {
ICULogger logger = new ICULogger(name, resourceBundleName);
/* Add a default handler to logger*/
logger.addHandler(new ConsoleHandler());
/* Turn off logging by default unless SYSTEM_PROP_LOGGER property is set to "all" */
if (flag == LOGGER_STATUS.ON) {
logger.turnOnLogging();
} else {
logger.turnOffLogging();
}
return logger;
}
return null;
}
I put in some logging statements to see if TimeZoneLogger was being instantiated and it shows it is not.
[INFO] Oct 29, 2013 8:45:39 AM com.example.SomeClass
[INFO] WARNING: icu4j.debug.logging = null
[INFO] Oct 29, 2013 8:45:39 AM com.example.SomeClass
[INFO] WARNING: Time Zone Logger = null
This shows that it's not the instantiation that App Engine doesn't like, but simply the reference to the class that causes the problem.
At this point all I can think of is to write my own CSV Renderer which is the class using the violating code. The effort would not be significant, but I would prefer to use existing libraries...especially when the library and platform both come from Google.
Any other suggestions?