NodeList.getLength() 在 Java 11 中返回 0
NodeList.getLength() returning 0 in Java 11
我正在将我的应用程序从 Java 8 迁移到 Java 11。在 Java 8 中,我的输入 xml 文件解析正确,但在 Java 11 nodeList.getLength()
返回 0
.
请参考我总是收到错误的代码:Cannot find signature
.
我尝试使用 document.getElementsByTagName("Signature")
而不是 getElementsByTagNameNS()
,returns 正确 length
。然而,unmarshalXMLSignature()
方法会给出一个错误,即文档实现必须支持 DOM 级别 2 并且是命名空间感知的。
在 Java 11 中使用 getElementsByTagNameNS()
方法有什么挑战吗?
private DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
. . .
document = documentBuilderFactory.newDocumentBuilder().parse(input);
final NodeList nodeList = document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nodeList.getLength() == 0) {
throw new SecurityException("Cannot find signature");
}
final XMLValidateContext validateContext = new DOMValidateContext(newX509KeySelector(), nodeList.item(0));
final XMLSignature signature = getXMLSignatureFactory().unmarshalXMLSignature(validateContext);
. . .
编辑 1:输入 xml 是
<?xml version="1.0" encoding="UTF-8" standalone="no"?><License>
<id>999</id>
<companyName>TRXX</companyName>
<creationDate>01-01-2016</creationDate>
<expirationDate>never</expirationDate>
<features>
<feature>
<name>drwwy</name>
<value>true</value>
<description>drwwy module</description>
</feature>
<feature>
<name>pnp</name>
<value>true</value>
<description>Index Number Management module</description>
</feature>
</features>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI="">
<Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>l5Cl4E=</DigestValue></Reference></SignedInfo><SignatureValue>R3zBkE=</SignatureValue>
<KeyInfo><X509Data><X509SubjectName>CN=TRXX Inc,OU=Product Development,O=TRXX Inc,L=Scotle,ST=Atlanta,C=US</X509SubjectName><X509Certificate>MIY</X509Certificate>
</X509Data></KeyInfo></Signature></License>
编辑 2:我发现,早些时候我注入了 DocumentBuilderFactory,它是 JDK 的一部分,但在 Java 11 中不再允许。这就是为什么我使用 [= 实例化它32=](),但是有了这个,我的节点列表长度为零。我们可以使用任何其他方式来实例化 DocumentBuilderFactory 对象吗?
如果你使用 document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
你会得到一个空的 nodeList 并且提供的源代码会抛出你的 new SecurityException("Cannot find signature")
.
如果您 document.getElementsByTagName("Signature")
,已找到 Signature 元素但没有名称空间感知,稍后将抛出此异常:
javax.xml.crypto.MarshalException: Document implementation must support DOM Level 2 and be namespace aware
at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshal(DOMXMLSignatureFactory.java:189)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshalXMLSignature(DOMXMLSignatureFactory.java:150)
在研究术语 getElementsByTagNameNS(XMLSignature.XMLNS, "Signature")
时,我发现了一些代码示例,其中它们在 DocumentBuilderFactory 的新实例上手动激活名称空间感知:
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
这应该可以解决您的 new SecurityException("Cannot find signature")
问题。
关于 ,您不仅将 Java 8 迁移到 11,而且还迁移了 CDI API、OpenWebBeans、Apache Tomcat 以及其他模块,其他人必须之前已经为您完成了命名空间意识的激活。
或者换种说法 - 你 @Injected 一个命名空间感知的 DocumentBuilderFactory 实例。
编辑:
对于 DocumentBuilderFactory
的手动配置和注入,创建一个 @Produces
DocumentBuilderFactory
实例的方法,并提供该实例以在其他地方注入:
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import javax.xml.parsers.DocumentBuilderFactory;
@Dependent
public class DocumentBuilderFactoryProducer {
@Produces
@ApplicationScoped
public DocumentBuilderFactory createDocumentBuilderFactory() {
DocumentBuilderFactory result = DocumentBuilderFactory.newInstance();
result.setNamespaceAware(true);
// other customizations ...
return result;
}
}
这可以像这样注入到其他 bean 中:
@Inject
private DocumentBuilderFactory documentBuilderFactory;
我正在将我的应用程序从 Java 8 迁移到 Java 11。在 Java 8 中,我的输入 xml 文件解析正确,但在 Java 11 nodeList.getLength()
返回 0
.
请参考我总是收到错误的代码:Cannot find signature
.
我尝试使用 document.getElementsByTagName("Signature")
而不是 getElementsByTagNameNS()
,returns 正确 length
。然而,unmarshalXMLSignature()
方法会给出一个错误,即文档实现必须支持 DOM 级别 2 并且是命名空间感知的。
在 Java 11 中使用 getElementsByTagNameNS()
方法有什么挑战吗?
private DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
. . .
document = documentBuilderFactory.newDocumentBuilder().parse(input);
final NodeList nodeList = document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nodeList.getLength() == 0) {
throw new SecurityException("Cannot find signature");
}
final XMLValidateContext validateContext = new DOMValidateContext(newX509KeySelector(), nodeList.item(0));
final XMLSignature signature = getXMLSignatureFactory().unmarshalXMLSignature(validateContext);
. . .
编辑 1:输入 xml 是
<?xml version="1.0" encoding="UTF-8" standalone="no"?><License>
<id>999</id>
<companyName>TRXX</companyName>
<creationDate>01-01-2016</creationDate>
<expirationDate>never</expirationDate>
<features>
<feature>
<name>drwwy</name>
<value>true</value>
<description>drwwy module</description>
</feature>
<feature>
<name>pnp</name>
<value>true</value>
<description>Index Number Management module</description>
</feature>
</features>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><Reference URI="">
<Transforms><Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/></Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><DigestValue>l5Cl4E=</DigestValue></Reference></SignedInfo><SignatureValue>R3zBkE=</SignatureValue>
<KeyInfo><X509Data><X509SubjectName>CN=TRXX Inc,OU=Product Development,O=TRXX Inc,L=Scotle,ST=Atlanta,C=US</X509SubjectName><X509Certificate>MIY</X509Certificate>
</X509Data></KeyInfo></Signature></License>
编辑 2:我发现,早些时候我注入了 DocumentBuilderFactory,它是 JDK 的一部分,但在 Java 11 中不再允许。这就是为什么我使用 [= 实例化它32=](),但是有了这个,我的节点列表长度为零。我们可以使用任何其他方式来实例化 DocumentBuilderFactory 对象吗?
如果你使用 document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
你会得到一个空的 nodeList 并且提供的源代码会抛出你的 new SecurityException("Cannot find signature")
.
如果您 document.getElementsByTagName("Signature")
,已找到 Signature 元素但没有名称空间感知,稍后将抛出此异常:
javax.xml.crypto.MarshalException: Document implementation must support DOM Level 2 and be namespace aware
at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshal(DOMXMLSignatureFactory.java:189)
at org.jcp.xml.dsig.internal.dom.DOMXMLSignatureFactory.unmarshalXMLSignature(DOMXMLSignatureFactory.java:150)
在研究术语 getElementsByTagNameNS(XMLSignature.XMLNS, "Signature")
时,我发现了一些代码示例,其中它们在 DocumentBuilderFactory 的新实例上手动激活名称空间感知:
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
这应该可以解决您的 new SecurityException("Cannot find signature")
问题。
关于
编辑:
对于 DocumentBuilderFactory
的手动配置和注入,创建一个 @Produces
DocumentBuilderFactory
实例的方法,并提供该实例以在其他地方注入:
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import javax.xml.parsers.DocumentBuilderFactory;
@Dependent
public class DocumentBuilderFactoryProducer {
@Produces
@ApplicationScoped
public DocumentBuilderFactory createDocumentBuilderFactory() {
DocumentBuilderFactory result = DocumentBuilderFactory.newInstance();
result.setNamespaceAware(true);
// other customizations ...
return result;
}
}
这可以像这样注入到其他 bean 中:
@Inject
private DocumentBuilderFactory documentBuilderFactory;