问题
This problem has been driving me mad. I'm trying to use Java in ColdFusion to create a Document object. When I do this:
nd = createObject("java","javax.xml.parsers.DocumentBuilder");
I can dump nd and see that it correctly loaded all the methods:
object of javax.xml.parsers.DocumentBuilder Class Name javax.xml.parsers.DocumentBuilder
Method / Return Type
getDOMImplementation() / org.w3c.dom.DOMImplementation
getSchema() / javax.xml.validation.Schema
isNamespaceAware() / boolean
isValidating() / boolean
isXIncludeAware() / boolean
newDocument() / org.w3c.dom.Document
parse(java.io.File) / org.w3c.dom.Document
parse(java.lang.String) / org.w3c.dom.Document
parse(org.xml.sax.InputSource) / org.w3c.dom.Document
parse(java.io.InputStream, java.lang.String) / org.w3c.dom.Document
parse(java.io.InputStream) / org.w3c.dom.Document
reset() / void
setEntityResolver(org.xml.sax.EntityResolver) / void
setErrorHandler(org.xml.sax.ErrorHandler) / void
I'm trying to call the newDocument() method. I've tried all the following in both cfscript and cfsets:
nd.newDocument();
nd.newDocument(JavaCast("null",""));
nd = createObject("java","javax.xml.parsers.DocumentBuilder").newDocument();
nd = createObject("java","javax.xml.parsers.DocumentBuilder").newDocument(JavaCast("null",""));
But, no matter what approach I try, I get this error:
Either there are no methods with the specified method name and argument types or the isNamespaceAware method is overloaded with argument types that ColdFusion cannot decipher reliably. ColdFusion found 0 methods that match the > provided arguments. If this is a Java object and you verified that the method > exists, use the javacast function to reduce ambiguity.
I can see that the method was loaded.. The method isn't overloaded.. It doesn't require any arguments.. And, even when I explicitly tell CF I'm passing in null, it can't find the method..
I tried accessing the other methods in the class - and it couldn't find those either.. I'm not sure why I can dump the contents of the class - and I can see all the methods.. But, somehow CF is getting confused and can't find them when I try to call them..
Any ideas would be super helpful..
Thanks!!
回答1:
You have to create a an object for documentBuilder factory. With an help of factory you can get the realted xml informations. Here I've created the object and call the parse method by using documentbuilderfactory. Also you have to inject a newInstance() then only you can access the newdocument() methods. My Xml Content : testParse.xml
<?xml version="1.0"?>
<company>
<staff id="1001">
<firstname>yong</firstname>
<lastname>mook kim</lastname>
<nickname>mkyong</nickname>
<salary>100000</salary>
</staff>
<staff id="2001">
<firstname>low</firstname>
<lastname>yin fong</lastname>
<nickname>fong fong</nickname>
<salary>200000</salary>
</staff>
</company>
*CF code :
<cfset myObj = createObject("java","javax.xml.parsers.DocumentBuilderFactory")>
<cfset createDocs = myObj.newInstance().newDocumentBuilder()>
<cfset parseDocs = createDocs.parse(expandpath('/testParse.xml'))>
<cfset getNodeName = parseDocs.getDocumentElement().getNodeName()>
<cfset getList = parseDocs.getElementsByTagName("staff")>
<cfloop index="i" from="1" to="#getList.getlength()#">
<!--- Do your business logic here --->
</cfloop>
I hope it will helps for you. Thanks.
回答2:
I tried accessing the other methods in the class - and it couldn't find those either.. I'm not sure why I can dump the contents of the class - and I can see all the methods.. But, somehow CF is getting confused and can't find them when I try to call them..
tldr;
To elaborate on "why", it's a red herring. The real cause of the error is that DocumentBuilder is abstract. You can't create an instance of an abstract class. As described in the existing answer, you can only create a new instance through DocumentBuilderFactory.
detail:
What CreateObject actually actually returns is a proxy for the java class. Although it may look like an instance of the java class, it isn't. It is just a wrapper. Notice a manually created proxy object looks identical to your variable in cfdump?
nd = createObject("java","javax.xml.parsers.DocumentBuilder");
proxy = createObject("java", "coldfusion.runtime.java.JavaProxy").init(nd.getClass());
writeDump(var=proxy, label="This is the JavaProxy");
writeDump(var=nd, label="This is the Variable 'nd'");
As to why CF "can't find the methods", well... that is misleading. What the error actually means (in this specific case) is that the method does exist, but .. you're not allowed to access it yet.
There's two relevant types of methods:
- instance methods: Belong to a specific instance of the class
- static methods: Belongs to the whole class and can be invoked without creating an instance of the class first
Due to how the JavaProxy works, until you create a new instance with init(..), you only have access to static methods.
The methods in your dump, like newInstance(), are all instance methods. Since your code doesn't call init(...), when CF searches the available methods, it doesn't find newInstance() and that's why you get the "method not found error".
Catch 22:
Of course if you'd tried to instantiate this particular class:
nd.init();
... it would've failed. The reason is that DocumentBuilder is an abstract class, so you can't instantiate it. However, it would've at least produced a slightly more accurate error message:
Unable to find a constructor for class javax.xml.parsers.DocumentBuilder that accepts parameters of type ('').
So long story short, the error message is misleading. The method really is there, it just wasn't accessible because you didn't have a proper "instance" of the class. As the existing answer explains, the only way to obtain a proper instance is through the DocumentBuilderFactory.
来源:https://stackoverflow.com/questions/51138765/coldfusion-java-method-not-found-exception