将项目迁移到JDK8时,会遇到Freemarker问题。
如果Freemarker声明
< #if response.matchedNames ??>
< #list response.matchedNames as matchedName>
在街区内
< #escape x as x?xml> ,
下面的Java异常将从freemarker-2.3.19.jar或更高版本中抛出。
引起:freemarker.template.TemplateModelException:?size不支持:freemarker.ext.beans.SimpleMethodModel
这些语句在JDK7中没有任何问题。调试应用程序后,可以找到一些相关信息和原因如下。 该物业" matchedNames"一个Java对象"响应"是一种数组类型。在JDK7中,属性" matchedNames"被处理为ArrayModel。但是在JDK8中,它被处理为SimpleMethodModel。
下面还提供了一些可能有助于调查的信息。 BeanInfo内省显示数组属性的属性类型是JDK中的java.beans.PropertyDescriptor。但是,在JDK8中,数组类型被解释为java.beans.IndexedPropertyDescriptor。 Freemarker似乎没有在JDK8中正确处理这个并且抛出"?大小不受支持"对于数组类型属性。我下载了几个更新版本的Freemarker jar(2.3.24 - 2.3.26),问题是一样的。
Freemarker与JDK8不兼容吗?有人可以帮忙吗?
非常感谢, 雷蒙德
============================================== <登记/> 添加Java类和freemarker模板文件的失败方案如下所示。
超级班:
public class SearchByNameRes {
protected String[] matchedNames;
public String[] getMatchedNames() {
return matchedNames;
}
public void setMatchedNames(String[] names) {
matchedNames = names;
}
}
子类:
public class SearchByAddressRes extends SearchByNameRes {
private String[] addresses;
public String[] getMatchedAddresses() {
return addresses;
}
public void setMatchedAddresses(String[] addrs) {
addresses = addrs;
}
}
模板response.ftl:
<Response>
<#escape x as x?xml>
<#if response.matchedNames??>
<#list response.matchedNames as matchedName>
</#list>
</#if>
</#escape>
</Response>
响应是子类SearchByAddressRes的对象实例。在这个简单的例子中,第3行和第4行可能抛出异常&#34; freemarker.template.TemplateModelException:?size不支持:freemarker.ext.beans.SimpleMethodModel&#34;。
=============================================== ======
完成的测试代码(由wsimport生成)如下所示。 String []类型的属性可以替换为其他Java类。
package test.jdk8.freemarker;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "response", propOrder = {
"matchedNames",
"matchedAddresses"
})
public class Response {
@XmlElement(nillable = true)
protected String[] matchedNames;
@XmlElement(nillable = true)
protected String[] matchedAddresses;
public String[] getMatchedNames() {
if (this.matchedNames == null) {
return new String[0];
}
String[] retVal = new String[this.matchedNames.length] ;
System.arraycopy(this.matchedNames, 0, retVal, 0, this.matchedNames.length);
return (retVal);
}
public String getMatchedNames(int idx) {
if (this.matchedNames == null) {
throw new IndexOutOfBoundsException();
}
return this.matchedNames[idx];
}
public int getMatchedNamesLength() {
if (this.matchedNames == null) {
return 0;
}
return this.matchedNames.length;
}
public void setMatchedNames(String[] values) {
int len = values.length;
this.matchedNames = ((String[]) new String[len] );
for (int i = 0; (i<len); i ++) {
this.matchedNames[i] = values[i];
}
}
public String setMatchedNames(int idx, String value) {
return this.matchedNames[idx] = value;
}
public String[] getMatchedAddresses() {
if (this.matchedAddresses == null) {
return new String[0];
}
String[] retVal = new String[this.matchedAddresses.length] ;
System.arraycopy(this.matchedAddresses, 0, retVal, 0, this.matchedAddresses.length);
return (retVal);
}
public String getMatchedAddresses(int idx) {
if (this.matchedAddresses == null) {
throw new IndexOutOfBoundsException();
}
return this.matchedAddresses[idx];
}
public int getMatchedAddressesLength() {
if (this.matchedAddresses == null) {
return 0;
}
return this.matchedAddresses.length;
}
public void setMatchedAddresses(String[] values) {
int len = values.length;
this.matchedAddresses = ((String[]) new String[len] );
for (int i = 0; (i<len); i ++) {
this.matchedAddresses[i] = values[i];
}
}
public String setMatchedAddresses(int idx, String value) {
return this.matchedAddresses[idx] = value;
}
}
答案 0 :(得分:1)
显然,{8}中java.beans.Introspector
的行为已发生变化,如果对于JavaBeans属性(在您的情况下为marchedNames
),则&#34;正常&#34;属性读取器(String[] getMatchedNames()
)和索引属性读取器(String getMatchedNames(int)
)。在这种情况下,在Java 7中,Introspector
仅报告&#34;正常&#34;属性读者,在Java 8中它报告&#34; normal&#34;和索引属性读者。不幸的是,当报告两者时,FreeMarker更喜欢最后一个,因此该属性变得不可列出。
怎么做......其中一个:
当FreeMarker 2.3.27出局时,将incompatibleImprovements
设置为2.3.27或更高以解决此问题。请注意,如果您未使用ObjectWrapper
的默认Configuration
,则需要设置正在使用的incompatibleImprovements
实例的ObjectWrapper
设置,而不是(只有Configuration
。
尝试告诉代码生成器不生成索引属性方法......但我不知道wsimport
中的此类选项。
使用response.getMatchedNames()
代替response.matchedNames
,至少最高2.3.26,作为解决方法。