在java-8中解组xml时出错“安全处理org.xml.sax.SAXNotRecognizedException导致java.lang.IllegalStateException”
以下代码在Java 7中运行良好
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; String xmlString = '<xml ..... '; StringReader reader = new StringReader(xmlString); JAXBContext jc = JAXBContext.newInstance(MyClass.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); MyClass myClass = (MyClass) unmarshaller.unmarshal(reader); ....
现在我们不得不升级到Java 8,现在我在执行代码时遇到了这个exception:
Sep 03, 2014 1:42:47 PM com.sun.xml.internal.bind.v2.util.XmlFactory createParserFactory SCHWERWIEGEND: null org.xml.sax.SAXNotRecognizedException: Feature: http://javax.xml.XMLConstants/feature/secure-processing at org.apache.xerces.jaxp.SAXParserFactoryImpl.setFeature(SAXParserFactoryImpl.java:100) at com.sun.xml.internal.bind.v2.util.XmlFactory.createParserFactory(XmlFactory.java:114) at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.getXMLReader(UnmarshallerImpl.java:139) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157) at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:214)
我知道有一个针对类似问题的问题,但回到java 7并不是我的解决方案。
我试图添加以下maven依赖项
javax.xml jaxp-api 1.4
但这没有改变结果,所以我删除了它(感谢@BlaiseDoughan提供的信息,这包含在Java 6中)
欢迎任何提示,非常感谢。
我们遇到了类似的问题 – 我们的开发人员找到了一个适合我们的解决方案。
我们将这个依赖项添加到了几个pom.xml文件中
对于那些关心的人来说,在声纳中失败的单位测试显然是失败的,因为Cobatura默认会拉出旧版本的xerces。 它所引入的版本与Java 8中的JAX-B不兼容。该库未用于生产代码 – 只是Cobatura。 因此,修复是在更新版本的xerces(2.11.0)上添加测试依赖项。 这是通过将依赖项添加到pom文件来完成的:
xerces xercesImpl 2.11.0 test
Xerces impl是这里的罪魁祸首。 去掉它。 Jdk内置了jaxb解析器,你不需要这个。
因此,如果在maven的情况下该依赖项来自父项目,则使用排除选项卡,以防您无法直接删除它。
xerces xercesImpl
这个问题很难被发现的原因是因为,当你经常写一个jaxb解编码时
你将在try块上进行解组,然后捕获jaxbexception,然后对错误做任何事情。
但是这个jar的罪魁祸首解析器(xercesimpl)会在中间抛出一个运行时exception,导致错误无法记录,只有在仔细调试后才能检测到。 请查看下面的代码段
try { JAXBContext context = JAXBContext.newInstance(YourClass.class); Unmarshaller unmarshaller = context.createUnmarshaller(); YourClass object = (YourClass)unmarshaller.unmarshal(new StringReader("SomeXmlInString")); } catch (JAXBException e){ e.printStackTrace(); }
这里xercesImpl导致unmarshaller使用其他一些sax解析器(而不是常规的jaxb解析器),导致它抛出不同的exception,这个exception不会在我们的catch块中捕获,它会遇到jaxbexception或它的一个子类。
另一种可能的解决方案是添加系统变量:
我在为我工作的maven tomcat插件中使用了这些:
com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl com.sun.org.apache.xerces.internal.parsers.SAXParser com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl
但是你也应该能够设置如下:
java -Dorg.xml.sax.parser="com.sun.org.apache.xerces.internal.parsers.SAXParser" \ -Djavax.xml.parsers.DocumentBuilderFactory="com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl" \ -Djavax.xml.parsers.SAXParserFactory="com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"
甚至使用System.setProperty:
System.setProperty("org.xml.sax.driver", "com.sun.org.apache.xerces.internal.parsers.SAXParser"); System.setProperty("javax.xml.parsers.DocumentBuilderFactory","com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl"); System.setProperty("javax.xml.parsers.SAXParserFactory","com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
这是一个依赖性问题。
以下是我解决问题的方法:
- 创建一个新的maven项目,使用下面附带的简单代码片段,程序正常崩溃并出现错误,结构无法解析,这是正常的。
-
将依赖项复制到项目pom.xml中,现在程序应该崩溃(如上所述)
-
不,你删除你喜欢的方法后的依赖关系(好猜测,Bisection,1-by-1 ..)来找到“坏”依赖。 也许某人有一个更好(更专业)的方法,这个方法对我有用。
现在你可以决定做什么了,也许有一个新版本可用,在我们的例子中,它是一个自己的大学包,其中包括一个大学的包,我可以排除。
public class Test { public Test() { } public static void main(String[] args) { try { StringReader reader = new StringReader(" "); JAXBContext jc = JAXBContext.newInstance(TestXML.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); TestXML testXMLs = (TestXML) unmarshaller.unmarshal(reader); } catch (JAXBException e) { e.printStackTrace(); } } }
和testXML类
@XmlRootElement(name="rss") @XmlAccessorType(XmlAccessType.FIELD) public class TestXML { public TestXML() { } @XmlElementWrapper(name="channel") @XmlElement(name="item") private int i ; public int getI() { return i; } public void setI(int i) { this.i = i; } }
顺便说一句:就我而言
jcs jcs 1.3
希望有所帮助。
自版本6以来,Java SE中已包含JAXB的实现。如果删除Maven依赖项(可能导致版本冲突),则一切都应该有效。
伯纳德和布莱斯的回答都非常有帮助。 在我的例子中,因为我使用的是JDK 7,所以解决方案是排除我的一个依赖项所包含的xerces子依赖项:
org.apache.axis axis 1.4.1-SNAPSHOT xerces xercesImpl xerces xmlParserAPIs
使用SAXparser可能是一场噩梦。 这是java中使用最广泛的XML解析器,每个都最终直接或间接使用。 JDK 8已经有了JAXB。 因此,如果您使用的是JDK 8,那么只有可能的方法才能删除maven依赖项。 我也有这个问题,所以我尝试删除maven依赖但没有发生。 然后我想为什么不恢复到旧版本如果java和VOILLA我成功了。 我目前正在使用jdk 7,我的测试运行顺利。 我想这是唯一的解决方案。
我使用第二个Mitch解决方案在我的项目中解决了这个问题,但只是
java -Djavax.xml.parsers.SAXParserFactory="com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"
尝试创建XML文档并解组它。 这对我有用。 JAXBContext jc = JAXBContext.newInstance(Message.class);
InputStream stream = new ByteArrayInputStream( string.getBytes( StandardCharsets.UTF_8 ) ); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse( stream ); Unmarshaller unmarshaller = jc.createUnmarshaller(); Message msg = ( Message ) unmarshaller.unmarshal( doc );
我们也遇到了这个问题,并注意到你需要保持jdk版本和jre版本相同,否则会出现版本不匹配导致的问题。
遇到这个问题的人使用jdk1.6和jre 1.8,当改为jdk1.6时,问题就消失了。
我遇到过类似的问题,当xerces jar和xercesImpl jar的版本存在很大差异时会出现这个问题。 为了解决这个问题,我使用了xerces-2.9.0和xercesImpl-2.9.1,问题就消失了。