viernes, 17 de abril de 2015

XPath and Name Spaces, don't you hate them too??

How about running a XPath expression from Java?
Pretty straight forward right, oh wait NAMESPACE!!!!

Here's a example on how to create your xpaht parser and the more complex Name Space Context.
Let's start with the NameSpaceContextImpl
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import org.apache.commons.lang.Validate;
public class NamespaceContextImpl implements NamespaceContext {
private Map<String, String> namespaceMap = new HashMap<String, String>();
public NamespaceContextImpl(Map<String, String> namespaceMap) {
this.namespaceMap = namespaceMap;
}
public void addNamespace(String prefix, String uri) {
Validate.notEmpty(prefix, "The prefix can not be null nor empty");
Validate.notEmpty(uri, "The uri can not be null nor empty");
this.namespaceMap.put(prefix, uri);
}
public String getNamespaceURI(String prefix) {
String uri = this.namespaceMap.get(prefix);
return uri == null ? XMLConstants.NULL_NS_URI : uri;
}
public String getPrefix(String namespace) {
for (String prefix : this.namespaceMap.keySet()) {
if (this.namespaceMap.get(prefix).equals(namespace)) {
return prefix;
}
}
return null;
}
public Iterator getPrefixes(String namespace) {
return null;
}
}

Now the actual Xpath parser imple:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true); // never forget this!
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new ByteArrayInputStream(xml.getBytes()));
// here's the fun part define your name spaces
Map<String, String> namesapaceMap = new HashMap<String, String>();
namesapaceMap.put("xmlns", "http://your.name.space.location.com/something/something");
// feed your context with the namespaces
NamespaceContext context = new NamespaceContextImpl(namesapaceMap);
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(context);
// run your xpath
System.out.println(xpath.compile("//Fields").evaluate(doc));
view raw gistfile1.java hosted with ❤ by GitHub
Hope it helps guy!!!

The famous Jar Hell issue

So I reckon I'm not the first one to have this problem. I'm certainly not the one who will tell you how to solve it BUT!!!!

Here is a really small example about using the JHades tool 

Why am I posting this?
Because the example in the home page is a little bit outdated and if you search JHades for the maven dependency the first 4 links you hit get it wrong.


Maven Dependency

<dependency>
<groupId>org.jhades</groupId>
<artifactId>jhades</artifactId>
<version>1.0.4</version>
</dependency>
view raw gistfile1 hosted with ❤ by GitHub

Java Code

import org.jhades.JHades;
new JHades()
.printClassLoaderNamess()
.printClasspath()
.overlappingJarsReport()
.multipleClassVersionsReport()
.findClassByName("org.jhades.SomeServiceImpl")
view raw gistfile1.java hosted with ❤ by GitHub
You should place this in some place that you are sure it'll get run during building.
If you have issues during tests. Just create a test where the test method has this code.

Hope this helps!