I am trying to create a JUnit test to fire IOException during DocumentBuilder.parse(InputSource.class).
I not sure why my "doThrow" method is not firing IOException.
The source code is as below:
JUnit class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:META-INF/spring/test.xml" })
#Transactional
public class junitTestClass {
#InjectMocks
TargetClass target;
#Rule
public MockitoRule mockito = MockitoJUnit.rule();
#Mock
DocumentBuilder documentBuilder;
#Mock
DocumentBuilderFactory documentBuilderFactory;
#Mock
XPath xpath;
#Test
public void test01() throws InterruptedException, SAXException, IOException, ParserConfigurationException{
when(documentBuilderFactory.newDocumentBuilder()).thenReturn(documentBuilder);
doThrow(new IOException()).when(documentBuilder).parse(any(InputSource.class));
String xml = "<?xml version="1.0" encoding="UTF-8"?><aaa><bbb>123</bbb></aaa>";
String pattern = "//aaa/bbb";
try {
target.parseXML(xml, pattern);
}catch(Exception e) {
e.printStackTrace();
}
}
}
Main Class:
private String parseXML(String xml, String pattern) {
String itemValue ;
try {
DocumentBuilderFactory dFac = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dFac.newDocumentBuilder();
Document document = db.parse(new InputSource(new StringReader(xml)));
XPath xPath = XPathFactory.newInstance().newXPath();
Node msgId = (Node) xPath.compile(pattern).evaluate(document, XPathConstants.NODE);
itemValue = msgId.getTextContent();
} catch (XPathExpressionException | SAXException | ParserConfigurationException | IOException e) {
e.printStackTrace();
}
return itemValue;
}
You should use:
doThrow(IOException.class)
Instead of instantiating it.
Related
I convert an XML file to PDF, through XSL-LO.
This process involves a Transformer based on a XSLT file.
This is how I get the Transformer:
private void prepareTransformer(final TransformerFactory tFactory)
throws TransformerConfigurationException {
xmlTransformer = tFactory.newTransformer(
new StreamSource(getClass().getResourceAsStream(xsltPath)));
}
My problem is that if the XSLT is not well formed, then the above mentioned code would logs an exception but not throws it. This is the output in the console:
System-ID unbekannt; Zeilennummer328; Spaltennummer69; xsl:when ist an dieser Position in der Formatvorlage nicht zulässig!
System-ID unbekannt; Zeilennummer63; Spaltennummer54; org.xml.sax.SAXException: javax.xml.transform.TransformerException: ElemTemplateElement-Fehler: testcaseDetails
javax.xml.transform.TransformerException: ElemTemplateElement-Fehler: testcaseDetails
(Position des Fehlers unbekannt)org.apache.fop.fo.ValidationException: Dem Element "fo:simple-page-master" fehlt ein verlangtes Property "master-name"! (Keine Kontextinformationen verfügbar)
As no exception is thrown by the librairy, I can not so easily handle this situation.
Expected behaviour: #newTransformer(Source source) would throw an exception. Is there a way to achieve that?
EDIT: here the full class:
#Log
public class Report {
private final String xsltPath;
private FopFactory fopFactory;
private Transformer xmlTransformer;
private Report(final String xsltPath) {
this.xsltPath = xsltPath;
try {
prepareTransformer(createFobTransformer());
} catch (final SAXException | IOException | ConfigurationException |
TransformerConfigurationException ex) {
log.log(Level.SEVERE, null, ex);
throw new PdfReportException(ex);
}
}
public static Report getInstance() {
return new Report("/report/report-regd.xslt");
}
private void prepareTransformer(final TransformerFactory tFactory)
throws TransformerConfigurationException {
xmlTransformer = tFactory.newTransformer(
new StreamSource(getClass().getResourceAsStream(xsltPath)));
}
private TransformerFactory createFobTransformer()
throws SAXException, IOException, ConfigurationException {
final InputStream inFop = getClass().getResourceAsStream("/report/fop.xconf");
final var fopBuilder = new FopFactoryBuilder(new File(".").toURI(),
new ClasspathResolverURIAdapter());
final var cfgBuilder = new DefaultConfigurationBuilder();
final Configuration cfg = cfgBuilder.build(inFop);
fopBuilder.setConfiguration(cfg);
fopFactory = fopBuilder.build();
final TransformerFactory tFactory = TransformerFactory.newInstance();
tFactory.setURIResolver(new ClasspathURIResolver());
return tFactory;
}
public byte[] generatePDFReport(final String xml) {
final var out = new ByteArrayOutputStream();
final var agent = fopFactory.newFOUserAgent();
try {
final var fop = agent.newFop(MimeConstants.MIME_PDF, out);
final var result = new SAXResult(fop.getDefaultHandler());
final var src = new StreamSource(new StringReader(xml));
xmlTransformer.transform(src, result);
} catch (final FOPException | TransformerException e) {
throw new PdfReportException(e);
}
return out.toByteArray();
}
public static class PdfReportException extends RuntimeException {
private static final long serialVersionUID = 6009368304491510184L;
public PdfReportException(final Throwable cause) {
super(cause);
}
}
}
No exception is catched in Report constructor:
I want to run TestNG tests programmatically by pointing to a jar which contains the test classes. For this, firstly the testng.xml is parsed and the classes are taken. Then each class is loaded into the classpath using the URLCLassLoader. But this throws org.testng.TestNGException: Cannot find class in classpath: exception.
Below is the code I tried
public void execute() {
String testNGXmlPath = "/path/to/testng.xml";
try {
getClassesToLoad(testNGXmlPath);
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
TestNG testng = new TestNG();
List<String> suites = Lists.newArrayList();
suites.add(testNGXmlPath);
testng.setTestSuites(suites);
testng.run();
}
public void getClassesToLoad(String path) throws ParserConfigurationException, IOException, SAXException {
File inputFile = new File(path);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputFile);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName("class");
Element element;
Node node;
NamedNodeMap namedNodeMap;
int i, length;
length = nodeList.getLength();
for (int j=0; j < length; j++) {
element = (Element)nodeList.item(j);
namedNodeMap = element.getAttributes();
if (namedNodeMap != null) {
for (i=0; i<namedNodeMap.getLength(); i++) {
node = namedNodeMap.item(i);
if (node.getNodeName() == "name") {
try {
loadClass("/path/to/testng.sample-1.0-SNAPSHOT.jar", node.getNodeValue());
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
}
}
}
}
}
}
public static void loadClass(String jarFilePath, String className) throws MalformedURLException,
ClassNotFoundException {
File jarFile = new File(jarFilePath);
if (jarFile.isFile()) {
URL url = jarFile.toURL();
URL[] urls = new URL[] { url };
ClassLoader cl = new URLClassLoader(urls);
cl.loadClass(className);
}
}
You are loading the class loader using the URLClassLoader, but for the classes that were loaded by your class loader to be visible to the current ContextualClassLoader, you need to set it up.
Please try doing it via Thread.currentThread().setContextClassLoader(); within your loadClass() method and then try running your test. This would ensure that when TestNG kicks in, it uses the ContextClassLoader that you injected to the current thread, to be used to load classes and thus help you get past your ClassNotFoundException
If your intention is to run your tests from a jar, you can simply package them and run using your xml.
Refer to the commandline section of the testng documentation.
Can refer to these steps if yours is a maven project :
I have a Java class which implements an interface, this class have a constructor that takes a String value and all the methods is that class are rely on that value in order to get work, so, what can i do if i want to deal with the interface directly and access the methods from it and as you know the interfaces can't have constructors so i can't assign that string value from it.
The Class:
public class XmlSource implements XmlInterface{
XmlConf xconf = new XmlConf();
URLProcess urlp = new URLProcess();
private URL url;
private String surl;
public XmlSource(String surl) throws MalformedURLException {
this.surl = surl;
result = urlp.validate(surl);
if(result == true){
configure();
}
}
public boolean configure() throws MalformedURLException {
url = new URL(surl);
xconf.setUrl(url);
xconf.setParameters(urlp.parameters);
xconf.setUrlPath(urlp.path);
xconf.setHostName(urlp.hostName);
return result;
}
public Document load() throws IOException, ParserConfigurationException,
SAXException {
// encoding the URL
InputStream is = url.openStream();
// loading the XML
domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
builder = domFactory.newDocumentBuilder();
doc = builder.parse(is);
return doc;
}
}
The Interface:
public interface XmlInterface {
public boolean configure() throws Exception;
public Document load() throws Exception;
}
You can assign a XmlSource object to XmlInterface type reference variable and then use that reference variable to call methods.
XmlInterface obj = new XmlSource(surl);
try
{
boolean configure = obj.configure();
Document document = obj.load();
}
catch(Exception e){
// perform exception handling
}
I;m using XPath to parse XML document returned by a URL, when i run my code with given inputs it works but when giving it inputs as a user input it throws an exception.
The Code:
class{
private String generalQuery = "//#*";
method(){
System.out.println("Enter URL");
url = scan.nextLine();
URL oracle = new URL(url);
InputStream is = oracle.openStream();
org.w3c.dom.Document doc = null;
DocumentBuilderFactory domFactory;
DocumentBuilder builder;
try {
domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
builder = domFactory.newDocumentBuilder();
doc = builder.parse(is);
} catch (Exception ex) {
System.err.println("unable to load XML: " + ex);
}
Map <String, String> params = new HashMap<String, String> ();
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
xpath.setNamespaceContext(new NameSpaces(doc));
XPathExpression expr = xpath.compile(generalQuery);
Object result = expr.evaluate(doc, XPathConstants.NODESET); // exception thrown here
NodeList nl = (NodeList) result;
for (int i = 0 ; i < nl.getLength() ; i++){
Node n = (Node)nl.item(i);
params.put(n.getNodeName(), n.getNodeValue());
}
return params;
}
}
The Exception:
javax.xml.transform.TransformerException: Unable to evaluate expression using this context
The class NameSpaces :
import java.util.Iterator;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import org.w3c.dom.Document;
public class NameSpaces implements NamespaceContext {
private Document sourceDocument;
public NameSpaces(Document document) {
sourceDocument = document;
}
#Override
public String getNamespaceURI(String prefix) {
if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
return sourceDocument.lookupNamespaceURI(null);
} else {
return sourceDocument.lookupNamespaceURI(prefix);
}
}
#Override
public String getPrefix(String namespaceURI) {
return sourceDocument.lookupPrefix(namespaceURI);
}
#Override
public Iterator<String> getPrefixes(String namespaceURI) {
return null;
}
}
The exception "Unable to evaluate expression using this context" may also result from a null document when trying to evaluate an XPath expression. (I had the same error and it took me a while to figure out I did not initialize my document properly).
In your code you have
try {
// load document
}
catch (Exception ex) {
System.err.println("unable to load XML: " + ex);
}
// happily continue
This is a call for trouble. If an exception happens during initialization you should STOP right there and you should not continue. If you have absolutely no idea how to handle the error, use catch(Exception e) { throw new Error(e); }. This will cause exceptions to bubble up and hopefully be handled by the default exception handler which prints a stack trace and exits.
As the reader of your question I don't even know where the exception was thrown. You should provide this information. Note that you can also use someException.printStackTrace(); to get the stack trace which points you to the correct line.
What you seem to be missing is a NameSpaceContext that you can implement yourself.
Also see this thread: NamespaceContext and using namespaces with XPath
Example:
class NamespaceResolver implements NamespaceContext {
private final Document document;
public NamespaceResolver(Document document) {
this.document = document;
}
public String getNamespaceURI(String prefix) {
if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
return document.lookupNamespaceURI(null);
} else {
return document.lookupNamespaceURI(prefix);
}
}
public String getPrefix(String namespaceURI) {
return document.lookupPrefix(namespaceURI);
}
#SuppressWarnings("rawtypes")
public Iterator getPrefixes(String namespaceURI) {
// not implemented
return null;
}
}
Then you initiate the XPath instance like this:
getXPath().setNamespaceContext(new NamespaceResolver(doc));
In my case this was not due to a null document, but due to an empty document with no root element. Appending the latter solved the issue.
Here is my xml code...
<flow>
<TaskID>100</TaskID>
<TaskID>101</TaskID>
<TaskID>102</TaskID>
<TaskID>103</TaskID>
</flow>
I want to know how to get taskID values in a for loop in java. Please help me...
DOM parser solution, fairly simple, no extra libraries required.
public static void main(String[] args) throws SAXException, IOException,
ParserConfigurationException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
String input = "<outer>";
input += "<otherstuff><TaskID>123</TaskID></otherstuff>";
input += "<flow>";
input += "<TaskID>100</TaskID>";
input += "<TaskID>101</TaskID>";
input += "<TaskID>102</TaskID>";
input += "<TaskID>103</TaskID>";
input += "</flow>";
input += "</outer>";
Document document = builder.parse(new InputSource(new StringReader(
input)));
NodeList flowList = document.getElementsByTagName("flow");
for (int i = 0; i < flowList.getLength(); i++) {
NodeList childList = flowList.item(i).getChildNodes();
for (int j = 0; j < childList.getLength(); j++) {
Node childNode = childList.item(j);
if ("TaskID".equals(childNode.getNodeName())) {
System.out.println(childList.item(j).getTextContent()
.trim());
}
}
}
}
You'd need to use a FileReader instead if your input came from a file.
Document document = builder.parse(new InputSource(new FileReader(
new File("foo.xml"))));
An alternative to getElementsByTagName() is XPath, a query language for XML, this is particularly useful if you have complicated set of conditions to match.
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("//flow/TaskID/text()");
Object result = expr.evaluate(document, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
System.out.println(nodes.item(i).getTextContent());
}
If your XML file is large, like 100s of MB / GB or you're on a low memory platform then consider a SAX parser.
String input = "<flow><TaskID>100</TaskID><TaskID>101</TaskID><TaskID>102</TaskID><TaskID>103</TaskID></flow>";
SAXParser sax = SAXParserFactory.newInstance().newSAXParser();
DefaultHandler handler = new DefaultHandler() {
private StringBuilder buffer = new StringBuilder();
#Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if ("TaskID".equals(qName)) {
System.out.println(buffer);
buffer = new StringBuilder();
}
}
#Override
public void characters(char[] ch, int start, int length)
throws SAXException {
buffer.append(ch, start, length);
}
#Override
public void startElement(String uri, String localName,
String qName, Attributes attributes) throws SAXException {
buffer = new StringBuilder();
}
};
sax.parse(new InputSource(new StringReader(input)), handler);
Here's an example using JDOM, which provides a more pleasant API over existing Java XML parsers:
import java.io.File;
import org.jdom2.*;
import org.jdom2.input.*;
public class Test {
// TODO: More appropriate exception handling :)
public static void main (String[] args) throws Exception {
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(new File("test.xml"));
Element root = doc.getRootElement();
for (Element element : root.getChildren("TaskID")) {
System.out.println(element.getText());
}
}
}
Of course, this assumes that the XML document is small enough to be loaded into memory.
(Obviously you can use the built-in libraries too, and if you're not doing much XML work then that would be fine - I just find them a bit primitive if you're doing any significant amount of work.)
With xpath Here is more information:
http://www.vogella.com/articles/JavaXML/article.html
I personally use JDOM library for all my XML manipulation.. Below is how I would do it;
String xml = "<flow> " +
"<TaskID>100</TaskID>" +
"<TaskID>101</TaskID>" +
"<TaskID>102</TaskID>" +
"<TaskID>103</TaskID>" +
"</flow>";
org.jdom.Document doc = new SAXBuilder().build(new StringReader(xml));
org.jdom.Element rootElement = doc.getRootElement();
List<Element> eles = rootElement.getChildren("TaskID");
for(Element el : eles)
System.out.println(el.getName()+" : "+el.getValue());
You can get it's documentation here: http://www.jdom.org/
Read Xml Children with SAX
<?xml version="1.0"?>
<Patriarch>
<name>Bill</name>
<wife>
<name>Vi</name>
</wife>
<son>
<name>Bill</name>
</son>
<daughter>
<name>Jeri</name>
<husband>
<name>Mark</name>
</husband>
<son>
<name>Greg</name>
</son>
<son>
<name>Tim</name>
</son>
<son>
<name>Mark</name>
</son>
<son>
<name>Josh</name>
<wife>
<name>Kristine</name>
</wife>
<son>
<name>Blake</name>
</son>
<daughter>
<name>Liah</name>
</daughter>
</son>
</daughter>
</Patriarch>
And Java code:
public class ParseXmlSAX {
public static void main(String[] args) {
new ParseXmlSAX("file.xml");
}
public ParseXmlSAX(final String file) {
try {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
DefaultHandler handler = new DefaultHandler() {
String key = null;
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if (key == null)
key = "|";
else
key += qName + "|";
}
public void endElement(String uri, String localName, String qName) throws SAXException {
if (!key.equals("|"))
key = key.substring(0, key.lastIndexOf(qName));
}
public void characters(char ch[], int start, int length) throws SAXException {
String conteudo = new String(ch, start, length).trim();
if (!conteudo.isEmpty()) {
System.out.println(key + " = " + conteudo);
}
}
};
saxParser.parse(this.getClass().getResourceAsStream(file), handler);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class Modifier {
public void modifyXML() {
String strSrcFile = "E:\\projects\\input\\sample.xml";
String strOutputFile = "E:\\projects\\output\\sample.xml";
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(strSrcFile);
Node company = doc.getFirstChild();
System.out.println(company.hasChildNodes());
NodeList nl = company.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// System.out.println("inner node::"+node.getNodeName());
if (node.hasChildNodes()) {
System.out.println("outer node::" + node.getNodeName());
readChildNodes(node);
} else {
}
}
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(strOutputFile));
transformer.transform(source, result);
} catch (Exception ee) {
ee.printStackTrace();
}
// Get the root element
}
public void readChildNodes(Node node)
{
NodeList nl = node.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node innernode = nl.item(i);
//System.out.println("mediam stage node::"+innernode.getNodeName());
if (innernode.hasChildNodes()) {
System.out.println("inner node::"+innernode.getNodeName());
readChildNodes(innernode);
}
else{
System.out.println("node dont have childs node::"+innernode.getNodeName());
}
}
}
public void replaceGraphicCode(Node innernode) {
NamedNodeMap attr = innernode.getAttributes();
Node nodeAttr = attr.getNamedItem("id");
String IDvalue = nodeAttr.getTextContent();
// nodeAttr.setTextContent("2");
}
public void replaceOriginator(Node innernode) {
NamedNodeMap attr = innernode.getAttributes();
Node nodeAttr = attr.getNamedItem("enterpriseCode");
}
public static void main(String[] args) {
Modifier objModifier = new Modifier();
objModifier.modifyXML();
}
}