Mock测试中遇到找不到message properties文件问题解决过程
最近做iFix GVT测试工作,要测试中文的mock(关于Mock Testing,见附1)
可以发现部署好mock的测试环境后,不管是用IE还是FF都无法打开UI,错误异常信息如下:
Error page exception The server cannot use the error page specified for your application to handle the Original Exception printed below. Please see the Error Page Exception below for a description of the problem with the specified error page. Original Exception: Error Message: Can't find bundle for base name com.ibm.rfidic.messages.RFIDICUIMessages, locale Error Code: 500 Target Servlet: /jsp/RFIDICLogin.jsp Error Stack: java.util.MissingResourceException: Can't find bundle for base name com.ibm.rfidic.messages.RFIDICUIMessages, locale at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:853) at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:743) at java.util.ResourceBundle.getBundle(ResourceBundle.java:593) at com.ibm.rfidic.utils.messages.impl.MessageProvider.getResourceBundle(MessageProvider.java:142) at com.ibm.rfidic.utils.messages.impl.MessageProvider.getMessageString(MessageProvider.java:149) at com.ibm.rfidic.utils.messages.impl.Message.getMessage(Message.java:87) at com.ibm.rfidic.web.ui.admin.model.CommonGUIProvider.getMessage(CommonGUIProvider.java:545) at com.ibm.rfidic.web.ui.admin.model.CommonGUIProvider.getMessageEscapedForHTML(CommonGUIProvider.java:492) at com.ibm._jsp._RFIDICLogin._jspService(_RFIDICLogin.java:104) at com.ibm.ws.jsp.runtime.HttpJspBase.service(HttpJspBase.java:87) at javax.servlet.http.HttpServlet.service(HttpServlet.java:856) at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1146) at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1087) at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:145) at com.ibm.rfidic.web.ui.admin.filters.ServletFilter.doFilter(ServletFilter.java:65) at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190) at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:130) at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:87) at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:837) at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:680) at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:588) at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:481) at com.ibm.wsspi.webcontainer.servlet.GenericServletWrapper.handleRequest(GenericServletWrapper.java:122) at com.ibm.ws.jsp.webcontainerext.AbstractJSPExtensionServletWrapper.handleRequest(AbstractJSPExtensionServletWrapper.java:232) at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3507) at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:269) at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:815) at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1466) at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:122) at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:458) at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:387) at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.ready(HttpInboundLink.java:267) at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.sendToDiscriminators(NewConnectionInitialReadCallback.java:214) at com.ibm.ws.tcp.channel.impl.NewConnectionInitialReadCallback.complete(NewConnectionInitialReadCallback.java:113) at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165) at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217) at com.ibm.io.async.AsyncChannelFuture$1.run(AsyncChannelFuture.java:205) at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1497)
问题解决:
原来是IE和FF默认的语言选择成了en_US,而不是zh_CN。
以FF为例,“工具” -> “选项” -> “内容” -> “语言” ,将浏览器的默认语言改成“中文”即可解决。
问题分析:
java.util.MissingResourceException: Can’t find bundle for base name com.ibm.rfidic.messages.RFIDICUIMessages, locale
注意到此错误信息,提示找不到Base的properties文件,并且locale是空值?
Base的properties文件RFIDICUIMessages确实不存在,因为在做Mock的时候已经将其改为RFIDICUIMessages_zh_CN.properties文件了,为什么系统不会自动去找zh_CN呢?
走近源代码观察:
public class MessageProvider implements IMessageProvider { ..... //省略其他方法与变量 private ResourceBundle getResourceBundle(Message message) { Locale locale = message.getLocale(); if (locale.getLanguage().equals("en")) { // 肯定是message的locale设为了en_US才会导致locale重置为空!!!继续查找其他locale设置的方法LocaleContext类,见下。 locale = new Locale("", "", ""); } ResourceBundle resourceBundle = (this.loader != null) ? ResourceBundle.getBundle(this.messageConstants.getResourceName(message.getId()), locale, this.loader) : ResourceBundle.getBundle(this.messageConstants.getResourceName(message.getId()), locale); return resourceBundle; } protected String getMessageString(Message message) { ResourceBundle resourceBundle = getResourceBundle(message); return resourceBundle.getString(message.getMessageId()); } public IMessage getMessage(int messageId, Object[] args) { return getMessage(messageId, LocaleContext.current().getLocale(), args); }
public class LocaleContext { private Locale locale; private TimeZone timeZone; private static ThreadLocal currentPreference = new ThreadLocal(); public LocaleContext() { this(Locale.getDefault(), TimeZone.getDefault()); } public LocaleContext(Locale locale, TimeZone timeZone) { this.locale = locale; this.timeZone = timeZone; } public Locale getLocale() { return this.locale; } public TimeZone getTimeZone() { return this.timeZone; } public void reset() { this.locale = Locale.US; this.timeZone = TimeZone.getDefault(); } public void setLocale(Locale locale) { this.locale = locale; } public void setTimeZone(TimeZone zone) { this.timeZone = zone; } public static LocaleContext current() { LocaleContext localeContext = (LocaleContext)currentPreference.get(); if (localeContext == null) { localeContext = new LocaleContext(); bind(localeContext); } return localeContext; } public static void bind(LocaleContext localeContext) { currentPreference.set(localeContext); } public static void unbind() { currentPreference.set(null); } }
问题就在于浏览器发送的HTTP请求locale是en_US的,到了服务器端自动找默认的RFIDICUIMessages(不带任何后缀),发现没有此resource才抛错。
另外以此可以推断原来访问Google.com的规则,如果浏览器默认设置为中文,那么服务器端会判断时区然后自动重定向到Google.cn;相反如果浏览器设置为英文en_US,那么就是在访问Google.com
附1:Mock Testing简介
Mock Testing又叫做pseudo translation testing
1.检查点
1)检查text是否作了pseudo translated (即,是否做了mock. 主要是检查text是否被抽取从来到resource 文件)
2)检查text是否有concatenated(拼接,嵌套)的情况Example: [text] [other text] (拼接)Example: [I go to the [store]] (嵌套)一个句子不可以分为两条message. 如上面的example1。除非是有句号,问号等,标示是两个不同的句子。
3)检查text是否被corrupted(截断)
例如 text 在英文下是: sample messages
在做了mock以后是, [zh中国~~sample mes
则是message 被截断了。 这一般是由于developers给该message留的space不够长。
4)检查是否有Garbled Characters (即显示不正常的字符)例如: 做了mock 的message是:[zh中国~~sample messages ~~ CN]
但是在UI上’中国’这两个字显示的是乱码,或者问号,或者方框。这可能是由于被测产品对相应的字符不支持。
5)检查UI 的控件的显示是否正常例如一:这个控件显示不全
2.Pseudo Translation Testing Process 测试流程
1)安装做过pseudo translated 的build. (在我们的rfidic,因为主要的pII file 是一些properties 文件,RFIDICInternalMessages.properties, RFIDICIWEMessages.properties, RFIDICUIMessages.properties 。 这些文件在com.ibm.rfidic.messages.jar文件中。我们的做法是把这些文件取出来,作mock translation, 然后再打回这个jar 文件去,直接把新jar文件copy到server 的相应目录。)
2)把系统的locale切换为需要测试的locale
For RHEL:
查找
[root@localhost ~]# locale
[root@localhost ~]# locale -a |grep jp ((UNIX)grep:字符串查找)
设置
[root@localhost ~]# export LANG=ja_JP.utf8
[root@localhost ~]# export LC_ALL= ja_JP.utf8
For Linux RedHat server, the following steps are for setting locale to Ja_JP.utf-8.
(1) vi /etc/sysconfig/i18n
(2) modify the LANG=”ja_JP.UTF-8″
(3) reboot server
For AIX:
(1) Edit /etc/environment
(2) 修改 LANG=locale ,export LANG.locale 是你要修改的具体locale.
(3) 保存然后 reboot
3)开始测试(text, message, tips, controls,…)



最新留言