[size=large][b]背景知识:Java 6提供对执行脚本语言的支持,这个支持来自于JSR223规范,对应的包是javax.script。默认情况下,Java 6只支持JavaScript脚本,它底层的实现是Mozilla Rhino,它是个纯Java的JavaScript实现。[/b]
详见: [url]http://developer.51cto.com/art/201007/208812.htm[/url][/size]
昨天运行ant脚本时触发了macros.js里这样一个js error: Uncaught TypeError: Cannot call method 'join' of undefined.
根据错误的line位置, 我查看了这个js
function concat(parts) {
[color=red]return parts.join('/');[/color]
}
很难看出来为什么红色这一行会有问题, 但以前没什么没发生呢. 什么地方的改动触发了这个error呢, 我今天的改动只不过是想把下面SilverFabricSDK和DSServer的version和location由4.1.0改为5.0.1, 就这么一个细小的改动跟上面的js有哪门子关系? 看上面js报错的地方实在是没头绪.
于是在js中打印一下parts试试看, 到底是个什么东西.
function concat(parts) {
[color=red]java.lang.System.out.println("**" + parts.toString());[/color]
return parts.join('/');
}
在没错误情况下打印会看得更清楚, 于是先把版本号改回4.1.0, 打印的结果显示原来是把location下的jar文件和版本号拼在一起, 拼成${basedir}/../../common/lib/sf/4.1.0/SilverFabricSDK-4.1.0.jar, 如果location下有这个文件就ok, 没有就会出现上面的error. 于是我又去${basedir}/../../common/lib/sf/5.0.1的下面, 发现SilverFabricSDK.jar这个jar原来不含版本号, 换句话说, 跟没本有${basedir}/../../common/lib/sf/5.0.1/SilverFabricSDK-5.0.1.jar
其实真正引起错误原因的位置并不是显示错误的哪一个行, 而是在下面这一个行时, 传入的参数就已经出问题了:
[color=red]add_element(path, filename, true);[/color]
由于上面找的${basedir}/../../common/lib/sf/5.0.1/SilverFabricSDK-5.0.1.jar不存在, 所以parts实际的类型是不是期望的字符串数组, 而是布尔类型, 因为[b]JavaScript 拥有动态类型,换句话说,相同的变量可用作不同的类型.[/b] 布尔类型自然没有数组的join()这个方法, 所以报Cannot call method 'join' of undefined.
最后还有一点补充, 如果这样打印
function concat(parts) {
[color=red]java.lang.System.out.println(parts);[/color]
return parts.join('/');
}
会遇到这样的Exception,
D:\cloudteam\SFAMX\bpm-server\container\build.xml:16: javax.script.ScriptExcepti
on: sun.org.mozilla.javascript.internal.EvaluatorException: Cannot convert sun.o
rg.mozilla.javascript.internal.NativeArray@7a1576 to char[] (<Unknown source>#13
9) in <Unknown source> at line number 139
其实本质上还是js类型的问题, 由于parts不出错情况下是js的字符串数组类型, 而java.lang.System.out.println()的参数是java的char[]类型, 这两个类型没法直接直接转化, 所以必须把parts.toString()或者用"+"连接一个字符串类型, 即java.lang.System.out.println("**"+parts); 这样parts才能从js数组类型转化成字符串类型, 供java.lang.System.out.println()使用.
[b]PS:jdk6有一个命令行工具:jrunscript
cd到jire的bin目录,默认为javascript语言,可以直接输入单行js脚本测试语法是否正确, 观察输出[/b]
详见: [url]http://developer.51cto.com/art/201007/208812.htm[/url][/size]
昨天运行ant脚本时触发了macros.js里这样一个js error: Uncaught TypeError: Cannot call method 'join' of undefined.
根据错误的line位置, 我查看了这个js
function concat(parts) {
[color=red]return parts.join('/');[/color]
}
很难看出来为什么红色这一行会有问题, 但以前没什么没发生呢. 什么地方的改动触发了这个error呢, 我今天的改动只不过是想把下面SilverFabricSDK和DSServer的version和location由4.1.0改为5.0.1, 就这么一个细小的改动跟上面的js有哪门子关系? 看上面js报错的地方实在是没头绪.
<target name="init">
<init />
<require name="sf-common" when="compile-and-runtime" type="jar"
version="${common_rel_ver}" build-number="${common_build_num}" location="${common.gridlib.dir}"/>
<require name="commons-io" when="compile-and-runtime" type="plain-jar"
version="2.0" location="${basedir}/../../common/lib/thirdparty"/>
<require name="json" when="runtime" type="plain-jar"
version="20080701" location="${basedir}/../../common/lib/thirdparty"/>
<require name="SilverFabricSDK" when="compile" type="plain-jar"
version="5.0.1" location="${basedir}/../../common/lib/sf/5.0.1"/>
<require name="DSServer" when="test" type="plain-jar"
version="4.1.0" location="${basedir}/../../common/lib/sf/4.1.0"/>
...
...
...
于是在js中打印一下parts试试看, 到底是个什么东西.
function concat(parts) {
[color=red]java.lang.System.out.println("**" + parts.toString());[/color]
return parts.join('/');
}
在没错误情况下打印会看得更清楚, 于是先把版本号改回4.1.0, 打印的结果显示原来是把location下的jar文件和版本号拼在一起, 拼成${basedir}/../../common/lib/sf/4.1.0/SilverFabricSDK-4.1.0.jar, 如果location下有这个文件就ok, 没有就会出现上面的error. 于是我又去${basedir}/../../common/lib/sf/5.0.1的下面, 发现SilverFabricSDK.jar这个jar原来不含版本号, 换句话说, 跟没本有${basedir}/../../common/lib/sf/5.0.1/SilverFabricSDK-5.0.1.jar
其实真正引起错误原因的位置并不是显示错误的哪一个行, 而是在下面这一个行时, 传入的参数就已经出问题了:
[color=red]add_element(path, filename, true);[/color]
由于上面找的${basedir}/../../common/lib/sf/5.0.1/SilverFabricSDK-5.0.1.jar不存在, 所以parts实际的类型是不是期望的字符串数组, 而是布尔类型, 因为[b]JavaScript 拥有动态类型,换句话说,相同的变量可用作不同的类型.[/b] 布尔类型自然没有数组的join()这个方法, 所以报Cannot call method 'join' of undefined.
function add_element(path, parts, required) {
file = new File(concat(parts));
if (required) {
file.exists() || self.fail('File [' + file.getAbsolutePath() + '] does`t not exist');
element = path.createPathElement();
element.setLocation(file);
} else {
if (file.exists()) {
element = path.createPathElement();
element.setLocation(file);
}
}
}
filename = exists([location, name + '-' + relVer + '.jar']) || exists([location, name + '_' + relVer + '.jar']);
add_element(path, filename, true);最后还有一点补充, 如果这样打印
function concat(parts) {
[color=red]java.lang.System.out.println(parts);[/color]
return parts.join('/');
}
会遇到这样的Exception,
D:\cloudteam\SFAMX\bpm-server\container\build.xml:16: javax.script.ScriptExcepti
on: sun.org.mozilla.javascript.internal.EvaluatorException: Cannot convert sun.o
rg.mozilla.javascript.internal.NativeArray@7a1576 to char[] (<Unknown source>#13
9) in <Unknown source> at line number 139
其实本质上还是js类型的问题, 由于parts不出错情况下是js的字符串数组类型, 而java.lang.System.out.println()的参数是java的char[]类型, 这两个类型没法直接直接转化, 所以必须把parts.toString()或者用"+"连接一个字符串类型, 即java.lang.System.out.println("**"+parts); 这样parts才能从js数组类型转化成字符串类型, 供java.lang.System.out.println()使用.
[b]PS:jdk6有一个命令行工具:jrunscript
cd到jire的bin目录,默认为javascript语言,可以直接输入单行js脚本测试语法是否正确, 观察输出[/b]
本文详细分析了在使用Java脚本时遇到的JS错误,特别是当尝试将SilverFabricSDK和DSServer的版本由4.1.0更改为5.0.1时引发的问题。通过打印变量内容,作者揭示了错误的根本原因在于版本更改导致的路径拼接错误,以及JavaScript的动态类型特性。文章进一步解释了如何通过调整路径拼接逻辑来解决该问题,并提供了使用jrunscript命令行工具测试脚本语法的方法。
1011

被折叠的 条评论
为什么被折叠?



