[ https://issues.apache.org/jira/browse/UIMA-4793?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15428270#comment-15428270 ]
Marshall Schor edited comment on UIMA-4793 at 8/19/16 2:41 PM: --------------------------------------------------------------- there's a problem - the exception gets created, but only later when the message is requested from the exception is the "locale" information available. So, at exception creation time, the locale is unknown. The same exception might be asked for its message in several "locales", even. The complete solution (following Richard's suggestion) is to capture the complete hierarchy of class loaders at construction time, and use those at message creation time to find the right bundle. This seems expensive to me. A fallback is to capture just the thread context class loader, and use the caller hierarchy loaders at the time the message is requested, plus the saved and current thread context class loaders, to locate the resource bundle. Is this adequate? was (Author: schor): there's a problem - the exception gets created, but only later when the message is requested from the exception is the "locale" information available. So, at exception creation time, the locale is unknown. The same exception might be asked for its message in several "locales", even. Change the solution to save at initialization time the current thread context class loader, not the resource bundle (which depends on the locale requested). > Unable to localize exceptions when using alternative classloader > ---------------------------------------------------------------- > > Key: UIMA-4793 > URL: https://issues.apache.org/jira/browse/UIMA-4793 > Project: UIMA > Issue Type: Bug > Components: Core Java Framework > Affects Versions: 2.8.1SDK > Reporter: Richard Eckart de Castilho > > If a component is initialized through a resource manager with a custom > classloader, then it may not have access to its localized exception message > bundles. > The reason is, that within the classloader chain, the CL which knows about > the Core UIMA framework is at a higher level than the CL used by the resource > manager that created the component. The component CL would have access to the > message bundle, but InterationalizedException uses it's own classloader (the > higher level one that knows about Core UIMA) to load message bundles: > {noformat} > // locate the resource bundle for this exception's messages > // turn over the classloader of the current object explicitly, so > that the > // message resolving also works for derived exception classes > ResourceBundle bundle = ResourceBundle.getBundle( > getResourceBundleName(), aLocale, this.getClass() > .getClassLoader()); > {noformat} > {noformat} > Thread [main] (Suspended (exception MissingResourceException)) > owns: PrintWriter (id=92) > owns: ThrowableInformation (id=93) > owns: ConsoleAppender (id=94) > owns: RootLogger (id=95) > ResourceBundle.throwMissingResourceException(String, Locale, Throwable) > line: 1564 > ResourceBundle.getBundleImpl(String, Locale, ClassLoader, > ResourceBundle$Control) line: 1387 > ResourceBundle.getBundle(String, Locale, ClassLoader) line: 1082 > > AnalysisEngineProcessException(InternationalizedException).getLocalizedMessage(Locale) > line: 240 > > AnalysisEngineProcessException(InternationalizedException).getLocalizedMessage() > line: 218 > AnalysisEngineProcessException(Throwable).toString() line: 480 > String.valueOf(Object) line: 2994 > PrintWriter.println(Object) line: 754 > Throwable$WrappedPrintWriter.println(Object) line: 764 > > AnalysisEngineProcessException(Throwable).printStackTrace(Throwable$PrintStreamOrWriter) > line: 655 > AnalysisEngineProcessException(Throwable).printStackTrace(PrintWriter) > line: 721 > DefaultThrowableRenderer.render(Throwable) line: 60 > ThrowableInformation.getThrowableStrRep() line: 87 > LoggingEvent.getThrowableStrRep() line: 413 > ConsoleAppender(WriterAppender).subAppend(LoggingEvent) line: 313 > ConsoleAppender(WriterAppender).append(LoggingEvent) line: 162 > ConsoleAppender(AppenderSkeleton).doAppend(LoggingEvent) line: 251 > AppenderAttachableImpl.appendLoopOnAppenders(LoggingEvent) line: 66 > Logger(Category).callAppenders(LoggingEvent) line: 206 > Logger(Category).forcedLog(String, Priority, Object, Throwable) line: > 391 > Logger(Category).log(String, Priority, Object, Throwable) line: 856 > Log4jLogger_impl.log(Level, String, Throwable) line: 272 > PrimitiveAnalysisEngine_impl.callAnalysisComponentProcess(CAS) line: > 417 > PrimitiveAnalysisEngine_impl.processAndOutputNewCASes(CAS) line: 308 > PrimitiveAnalysisEngine_impl(AnalysisEngineImplBase).process(CAS) line: > 269 > PrimitiveAnalysisEngine_impl(AnalysisEngineImplBase).process(JCas) > line: 284 > AnalysisEngine$process.call(Object, Object) line: not available > ... > {noformat} > The IMHO best way would be if UIMA would at try here to use the thread's > context classloader - and maybe that UIMA actually sets the thread context > classloader to the resource manager CL while running components... in my > case, I already do that outside UIMA atm, so searching the thread CL would be > sufficient for me atm. > See also: https://issues.apache.org/jira/browse/UIMA-3692 -- This message was sent by Atlassian JIRA (v6.3.4#6332)