我们有一个使用JDK 11运行的非spring应用程序。在pom.xml文件中有以下内容:
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
我们有代码将java对象编组为xml,如下所示:
Marshaller marshaller = JAXBContext.newInstance(Ratings.class).createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, schemaLocation);
marshaller.setProperty(CharacterEscapeHandler.class.getName(),
new CDATACharacterEscapeHandler());
StringWriter writer = new StringWriter();
marshaller.marshal(ratings, writer);
return writer.toString();
当我们尝试设置CharacterEscapeHandler时,代码失败。我们得到以下错误:
Caused by: javax.xml.bind.PropertyException: name:
com.mycode.server.utils.CDATACharacterEscapeHandler value:
com.mycode.server.utils.CDATACharacterEscapeHandler@74921b67
at javax.xml.bind.helpers.AbstractMarshallerImpl.setProperty
(AbstractMarshallerImpl.java:343)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.setProperty
(MarshallerImpl.java:516)
我可以告诉你我们的自定义CDATACharacterEscapeHandler如下:
// this is the only class that I could find with this name.
// even when I pull in com.sun.xml.bind.jaxb-core 2.3.0
import org.glassfish.jaxb.core.marshaller.CharacterEscapeHandler;
public class CDATACharacterEscapeHandler implements CharacterEscapeHandler {
@Override
public void escape(char[] ch, int start, int length, boolean isAttVal, Writer writer) throws IOException
{
...
}
}
你可以看到我们的CDATACharacterEscapeHandler扩展了标准的CharacterEscapeHandler。
我花了大约5个小时研究stackoverflow和互联网之间的关系。我去过JAXB的官方网站。我知道我已经尝试了很多事情,比如:
marshaller.setProperty(CDATACharacterEscapeHandler.class.getName(), new CDATACharacterEscapeHandler());
marshaller.setProperty("com.sun.xml.bind.characterEscapeHandler", new CDATACharacterEscapeHandler());
似乎什么都不起作用。有一次,我尝试迁移到最新的3.0.2版本的代码,这也不起作用。这带来了更多的麻烦,因为java.xml.bind包被更改为jakarta.xml.bind,而且我不想在这个时候更新所有的代码。以后,可以另一个努力。
我在Stackoverflow上标记了其他人得到答案的其他问题,我尝试了这些努力,但这里似乎没有任何作用。
将编组器属性键从com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler
更新到org.glassfish.jaxb.characterEscapeHandler
可以解决新的JAXB glassfish实现的问题。
marshaller.setProperty("org.glassfish.jaxb.characterEscapeHandler", new NoEscapeHandler());
在我这边,我必须改变我的pom.xml配置:
<!-- JAXB -->
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<scope>compile</scope>
</dependency>
通过将jaxb-runtime
的原始范围从runtime
更改为compile
,然后在我的代码中,我有如下内容:
if (cdata) {
marshaller.setProperty(CharacterEscapeHandler.class.getName(),
new CharacterEscapeHandler() {
@Override
public void escape(char[] ac, int i, int j, boolean flag, Writer writer) throws IOException {
// some code here
writer.write(ac, i, j);
}
});
}
,我仍然有声纳警报,我正在使用
import com.sun.xml.bind.marshaller.CharacterEscapeHandler;
在我的导入,但我没有找到一个更好的方法来做java>= 11(目前工作在java 17)。