Java Ninja Chronicles By Norris Shelton

Things I learned in the pursuit of code

Strange Maven dependency resolution problems. How Springframework caused problems when they absorbed the APIs into an existing dependency.

java.lang.NoSuchMethodError: org.springframework.transaction.interceptor.TransactionAttribute.getQualifier()Ljava/lang/String;
	at org.springframework.test.context.transaction.TransactionalTestExecutionListener.beforeTestMethod(TransactionalTestExecutionListener.java:149)
	at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:374)
	at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:73)
	at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
	at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
	at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
	at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
	at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
	at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:35)
	at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:146)
	at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:97)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.maven.surefire.booter.ProviderFactory$ClassLoaderProxy.invoke(ProviderFactory.java:103)
	at $Proxy0.invoke(Unknown Source)
	at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:145)
	at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcess(SurefireStarter.java:87)
	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:69)

What the heck is this? Your library has this class and the method does exist and even takes a String. What makes it even weirder is that your tests run in your editor, but do not run from the Maven command line. How can this be?

Unknown to you, one of the dependencies that you are using is pulling spring-dao-2.0.x.jar (usually version 2.0.8, but not always). OK, but what is the problem with that? The code that was in that jar was absorbed by the spring-tx jar in the spring 2.5. There is no replacement for that jar, so even though you are using a much newer version of Spring, nothing says not to pull the old jar into your project. It is up to you to find any dependency that uses the jar and exclude it.

In Maven, it is done like this:

        <dependency>
            <groupId>com.bhsi</groupId>
            <artifactId>dao-user</artifactId>
            <version>1.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-dao</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

This has to be done for any dependency that has that jar as a transitive dependency.

Once that is done, you need to see if you have the replacement. In my specific case, my test class ran sometimes, but did not run other times. This was due to having spring-dao-2.0.8.jar and spring-tx-3.0.4-RELEASE.jar in my project classpath. If you don’t have the spring-tx jar, add it and you should be good to go.

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>

January 31st, 2011

Posted In: Java, JUnit, Maven, Spring

3 Comments

I haven’t had to do this in a while, but some co-workers were talking about two problems and they had HTML parsing in common. Dave Petersheim had already introduced jsoup into our project for just that purpose.

jsoup: Java HTML Parser

<dependency>
  <!-- jsoup HTML parser library @ http://jsoup.org/ -->
  <groupId>org.jsoup</groupId>
  <artifactId>jsoup</artifactId>
  <version>1.4.1</version>
</dependency>

Dave used it to parse through an HTML fragment, looking for a text node to serve as a summary. Here is how he did it.

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
 
 
/**
 * Extracts the first line of text from the supplied html.
 * @param content
 * @return The first line of text or empty string if one could not be found
 */
static String extractFirstText(String content) {
    Document doc = Jsoup.parse(content);
 
    for (org.jsoup.nodes.Element element : doc.getAllElements()) {
        if (element.hasText() &amp;&amp; !StringUtils.isEmpty(element.ownText())) {
            return element.ownText();
        }
    }
 
    return "";
}

I also ran across a blog post by Tom Czarniecki where he had a small JUnit snippet.

String html = response.getContentAsString();  
Document document = Jsoup.parse(html);  
  
Elements elements = document.select("#errorRef");  
assertThat(elements.size(), equalTo(1));  
  
assertThat(elements.first().text(), equalTo(errorRef));

While looking at their cookbook, I found that they have css (or jquery) like selectors.

File input = new File("/tmp/input.html");
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

Elements links = doc.select("a[href]"); // a with href
Elements pngs = doc.select("img[src$=.png]");
  // img with src ending .png

Element masthead = doc.select("div.masthead").first();
  // div with class=masthead

Elements resultLinks = doc.select("h3.r > a"); // direct a after h3

Their documentation says the select method is available in a Document, Element or in Elements

I ran across a html parser question on stackprinter.appspot.com which asked “What are the pros and cons of the leading Java HTML parsers?”

It had an excellent response by BalusC:
[+15] [2010-07-01 00:00:32] BalusC [ACCEPTED]
General

Almost all known HTML parsers implements W3C DOM API [1] (part of JAXP, Java API for XML processing) and gives you a org.w3c.dom.Document [2] back. The major differences are usually to be found in the features of the parser in question. Most parsers are to a certain degree forgiving and lenient with non-wellformed HTML (“tagsoup”), like JTidy [3], HtmlCleaner [4] and TagSoup [5]. You usually use this kind of HTML parsers to “tidy” the HTML source so that you can traverse it “the usual way” using the W3C DOM and JAXP API.

The only ones which jumps out are HtmlUnit [6] and Jsoup [7].
HtmlUnit

HtmlUnit [8] provides a completely own API which gives you the possibility to act like a webbrowser programmatically. I.e. enter form values, click elements, invoke JavaScript, etcetera. It’s much more than alone a HTML parser. It’s a real “GUI-less webbrowser” and HTML unit testing tool.
Jsoup

Jsoup [9] also provides a completely own API. It gives you the possibility to select elements using jQuery [10]-like CSS selectors [11] and provides a very nice API to traverse the HTML DOM tree. It’s in my opinion a real revolution. Ones who have worked with org.w3c.dom.Document knows what a hell of pain it is to traverse the DOM to get the elements of interest using verbose NodeList [12] and Node [13] API’s. True, XPath [14] makes the life easier, but still, it’s another learning curve and it can end up to be pretty verbose.

Here’s an example which uses a “plain” W3C DOM parser like JTidy in combination with XPath to extract the first paragraph of your question and the names of all answerers (I am using XPath since without it, the code needed to gather the information of interest would otherwise grow up 10 times as big).

String url = “http://stackoverflow.com/questions/3152138”;
Document document = new Tidy().parseDOM(new URL(url).openStream(), null);
XPath xpath = XPathFactory.newInstance().newXPath();

Node question = (Node) xpath.compile(“//*[@id=’question’]//*[contains(@class,’post-text’)]//p[1]”).evaluate(document, XPathConstants.NODE);
System.out.println(“Question: ” + question.getFirstChild().getNodeValue());

NodeList answerers = (NodeList) xpath.compile(“//*[@id=’answers’]//*[contains(@class,’user-details’)]//a[1]”).evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < answerers.getLength(); i++) { System.out.println("Answerer: " + answerers.item(i).getFirstChild().getNodeValue()); } [/sourcecode] And here's an example how to do exactly the same with Jsoup: [sourcecode language="java"] String url = "http://stackoverflow.com/questions/3152138"; Document document = Jsoup.connect(url).get(); String question = document.select("#question .post-text p").first().text(); System.out.println("Question: " + question); Elements answerers = document.select("#answers .user-details a"); for (Element answerer : answerers) { System.out.println("Answerer: " + answerer.text()); } [/sourcecode] Do you see the difference? For me as being a webdeveloper with a decade of experience, Jsoup was easy to grasp thanks to the support for CSS selectors which I am already familiar with. Summary The pro's and cons of each should be obvious enough. If you just want to use a XML based tool to traverse it, then just go for the first mentioned group of parsers. Which one to choose depends on the features it provides and the robustness of the library (how often is it updated/maintained/fixed?). There are pretty a lot [15] of them. My personal preference of them is JTidy (HtmlCleaner is also nice, it was the best choice until JTidy finally updated their API last year after years of absence). If you like to unit test the HTML, then HtmlUnit is the way to go. If you like to extract specific data from the HTML, then Jsoup is the way to go. [1] http://java.sun.com/javase/6/docs/api/org/w3c/dom/package-summary.html [2] http://java.sun.com/javase/6/docs/api/org/w3c/dom/Document.html [3] http://jtidy.sourceforge.net/ [4] http://htmlcleaner.sourceforge.net/ [5] http://home.ccil.org/~cowan/XML/tagsoup/ [6] http://htmlunit.sourceforge.net/ [7] http://jsoup.org/ [8] http://htmlunit.sourceforge.net/ [9] http://jsoup.org/ [10] http://jquery.com [11] http://www.w3.org/TR/css3-selectors/ [12] http://java.sun.com/javase/6/docs/api/org/w3c/dom/NodeList.html [13] http://java.sun.com/javase/6/docs/api/org/w3c/dom/Node.html [14] http://java.sun.com/javase/6/docs/api/javax/xml/xpath/XPath.html [15] http://java-source.net/open-source/html-parsers (2) Wow, great answer. Thanks! - Avi Flax You're welcome. - BalusC

January 27th, 2011

Posted In: Java

2 Comments

Do you ever wish you can go in and change the number of days of local history to keep? Well, you are in luck.

CTRL+ ALT + SHIFT + /

The maintenance panel is displayed. Pick “registry”. Scroll down to the bottom and look for localHistory.daysToKeep. It defaults to 5. Change away!!!

January 20th, 2011

Posted In: IntelliJ

Leave a Comment

Creating a toString method used to be tedious and would lead to new properties being left out. Jakarta Commons solved that problem for us:

    /**
     * Returns a string representation of the object. In general, the <code>toString</code> method returns a string that
     * "textually represents" this object. 
     * @return a string representation of the object.
     */
    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

They also provide a HashCodeBuilder class to make creating a hash code easy

HashCodeBuilder hashCodeBuilder = new HashCodeBuilder();
hashCodeBuilder.append(myProperty).append(myOtherProperty).toHashCode();

Append as many properties as needed, then generate the value.

If you want to use all of the properties of the object to generate the hash code, then:

return HashCodeBuilder.reflectionHashCode(this);

The same functionality has been provided for equals() methods via the EqualsBuilder:

EqualsBuilder equalsBuilder = new EqualsBuilder();
equalsBuilder.appendSuper(super.equals(them));  // don't ignore the parent
equalsBuilder.append(myKey, them.getMyKey()).append(myOtherKey, them.getMyOtherKey()).isEquals();

If you want to use all of the properties of the object to generate the equals method, then:

EqualsBuilder.reflectionEquals(this, them);

January 11th, 2011

Posted In: Java

3 Comments

Sorting with Java Collections is easy. Collections.sort() does all of the work if you have defined a way to compare the objects. That works great … when they are of the same type. What happens if the objects are of different types?

Create an interface that all of the objects in the collection implement. Create a comparator for the interface type. Specify the comparator to the Collection.sort() method. This is especially useful when they classes can’t have a common parent type.

I didn’t get to run an example with this type of implementation, but it makes sense. Now, if I could just remember what triggered this idea.

January 11th, 2011

Posted In: Java

Leave a Comment

Your environment (env) isn’t the same environment you get when you ssh into a machine. It isn’t even the same environment you get when you rlogin into the same machine. Consider [sourcdcode language=”bash”]ssh host env[/sourcecode]. The list is much shorter.

To add to the ssh environment, modify

~/.ssh/environment

on the target host and add in the properties:

JAVA_HOME=$JAVA_HOME

Then turn on the ability to have a user defined ssh environment by modifying

/etc/ssh/sshd_config

Change “PermitUserEnvironment no” to “… yes”. You will then need to bounce the ssh service. It looks like the following commands should work:

/etc/init.d/sshd [restart | start | stop]

January 11th, 2011

Posted In: Bash, SSH

Leave a Comment

Here is what I started with, a hidden div containing data:

<div id="executive-dashboard-census-by-unit" style="display:none; padding-top:1.5em;">
    <executiveTags:census-by-unit census="${census}" now="${now}"/>
</div>

The data turned out to be too large for the amount of room that I was given to display in. Here is a good write-up, but his plugin did not work for me.
remy sharp’s b:log -> Fixing IE overflow problem

I resorted to adding the overflow:hidden to the style for the area.

January 11th, 2011

Posted In: HTML, IE

Leave a Comment

To parse a string into a DateTime object:

DateTimeFormatter fmt = DateTimeFormat.forPattern("MM/dd/yyyy");
DateTime dt = fmt.parseDateTime(strInputDateTime);

To output the formatted value of a DateTime object as a String:

fmt.print(myDateTime)

January 11th, 2011

Posted In: Collections, Java, Joda-Time

Leave a Comment

LinkedIn Auto Publish Powered By : XYZScripts.com