Nelz's Blog

18 October 2008

Compile-Time Dependencies

Filed under: Java — nelz9999 @ 11:57

When building out your architecture, I would encourage you to break out your APIs as first-class modules. (Sorry, a ‘module’ is Maven speak for the parts of a project that create their own artifacts such as JAR or WAR files.)

For an example of a simple suggested structure, look at the following image. (Arrows denote compile-time dependencies.):

IdealModule

In some of my recent projects I received some push-back on breaking out the APIs. The concern was that breaking them out as modules would add overhead to the build process. I do understand that concern, but I think it is a minimized threat if you are using a fairly sophisticated build system.

I acquiesced at the time, and now we have a structure that looks similar to the next image. (Can you see the problem already?):PreviousModule

The black arrow indicates just one of the weaknesses of this model. Here, you can see that a UI component can (at the least offensive) access the DAO API as well as (at the most offensive) access the concrete DAO implementations.

When you have a structure like this, the question is not if, but when will one of your fellow engineers take advantage of this and circumvent the nice functional striations that you have taken so much time to isolate?

14 October 2008

XMLUnit and TestNG

Filed under: Java — nelz9999 @ 17:50

Our entire testing system is based on TestNG, but one of our developers recently invoked XMLUnit to test some of the XML he was producing.

Now, XMLUnit is built to be used with JUnit (old JUnit… like 3.8.1 style JUnit…), which at first glance doesn’t seem to play well with TestNG test runners. (We were having some build timeouts and other mysterious behavior when trying to run these tests.)

To give you an idea, here is a snippet from the examples:

package net.nelz.test.xmlunit;
import org.custommonkey.xmlunit.XMLTestCase;
public class MyXMLTestCase extends XMLTestCase {
public MyXMLTestCase(String name) {
super(name);
}
public void testForEquality() throws Exception {
String myControlXML = "<msg><uuid>0x00435A8C</uuid></msg>";
String myTestXML = "<msg><localId>2376</localId></msg>";
assertXMLEqual("comparing test xml to control xml", myControlXML, myTestXML);
assertXMLNotEqual("test xml not similar to control xml", myControlXML, myTestXML);
}
}

If you look at that example, the only methods that seem to add any value are assertXMLEqual(...) and assertXMLNotEqual(...).

If you look at the source code for those methods, you’ll realize that they just delegate to parallel static methods in the class XMLAssert:

...
public void assertXMLEqual(String control, String test)
throws SAXException, IOException {
XMLAssert.assertXMLEqual(control, test);
}
...

What this all means is that XMLUnit already is TestNG friendly. Here’s what that snippet from XMLUnit’s example code would look like if it were rewritten to target TestNG.:

package net.nelz.test.xmlunit;
import org.custommonkey.xmlunit.XMLAssert;
import org.testng.annotations.Test;
public class MyXMLTestCase {
@Test
public void testForEquality() throws Exception {
String myControlXML = "<msg><uuid>0x00435A8C</uuid></msg>";
String myTestXML = "<msg><localId>2376</localId></msg>";
XMLAssert.assertXMLEqual("comparing test xml to control xml", myControlXML, myTestXML);
XMLAssert.assertXMLNotEqual("test xml not similar to control xml", myControlXML, myTestXML);
}
}

10 October 2008

Spring JMX Challenges

Filed under: Java — nelz9999 @ 13:33

Yesterday I started to do some clean-up work around how we are using Spring and JMX in some of our webapps.

We started off with a very basic configuration:

...
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="beans">
<map>
<entry key="OurApp:name=beanName" value-ref="beanReference"/>
...
</map>
</property>
</bean>
...

By default, this exposes all public methods for management, which is overkill for us. So I wanted to use the Java 5 Annotation capabilities to expose only those methods that are appropriate for management. This brought us to the following configuration:

...
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="assembler" ref="assembler"/>
<property name="beans">
<map>
<entry key="OurApp:name=beanName" value-ref="beanReference"/>
...
</map>
</property>
</bean>
<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
...

This worked for most of the beans, but when I tried to port this one bean to the new Annotation-based interface definition, I kept getting a nasty stack-trace upon startup, the root of which says "MetadataMBeanInfoAssembler does not support JDK dynamic proxies - export the target beans directly or use CGLIB proxies instead".

I couldn’t figure out for the life of me what the structural difference was between this one bean, and all the others… I tried changing around the other annotations in the class, substituting other beans from the same layer, everything. I couldn’t figure it out.

After a bit, I decided to give up on adding the Annotations to that one bean, but I still wanted to expose the bean. I couldn’t find documentation on this, but it turns out that you are completely able to have multiple "exporters" invoked in your Spring configuration files. This gave me a configuration like this:

...
<bean id="exporter1" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="assembler" ref="assembler"/>
<property name="beans">
<map>
<entry key="OurApp:name=beanName" value-ref="beanReference"/>
...
</map>
</property>
</bean>
<bean id="exporter2" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="beans">
<map>
<entry key="OurApp:name=problemBeanName" value-ref="problemBeanReference"/>
</map>
</property>
</bean>
<bean id="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
...

Great. This worked. I was able to manage the problem bean, and I was able to define the interface to all the other beans via the Annotations. But, when I went to manage the problem bean via the JMX console, there were all sort of dynamic proxy methods exposed…

This got me thinking back to the stack trace:

~MetadataMBeanInfoAssembler does not support JDK dynamic proxies - export the target beans directly or use CGLIB proxies instead

… I definitely see other traces of dynamic proxying in the JMX interface itself.

Then it hit me: AOP. The one thing that was different between the problem bean and all the other beans is that the problem bean is being AOP’ed.

Doing some research on that stack trace error message, I found this discussion. They seem to have figured out there’s a conflict with the MetadataMBeanInfoAssembler and dynamically proxied classes, but I’m still unclear (until further testing) if the suggestion to "set the proxyTargetClass property of your ProxyFactoryBean to true" will work.

In summation, here are the learnings:

  1. MetadataMBeanInfoAssembler is challenged with defining an interface based on Annotations of an AOP’ed class.
  2. It is trivial to define multiple MBeanExporter‘s with different configurations if you need to.

9 September 2008

Back in Action!

Filed under: Java — nelz9999 @ 20:11

I am now back from Burning Man, and having a fairly smooth re-adjustment to this so called real world.

Spring AOP and Internal Method Calls

When using AspectJ with Spring’s AOP framework, I didn’t realize that there were challenges getting AOP to work when a member method calls to a sibling method.

Here’s an example I’ve borrowed from some discussion of this phenomenon:

public class MyService {
public methodA()
{
//do something
methodB();
//do something
}
public methodB()
{
//do something else
}
}

Now both the method in the service have been AOPed, and when I call the methodA() on the proxied instance, the methodA() will have the benefit of the aspect, but when the methodB() gets called from methodA(), it would not get that benefit of AOP.

Used strategically, I think this can be a benefit. When I came upon this problem, I basically used it as an opportunity to refactor "methodB" (and it’s associated overhead) into a new stand-alone class. This may not always solve your specific problem, but it worked in my one case so far.

21 May 2008

Applying the Java Keyword ‘final’ To Classes

Filed under: Java — nelz9999 @ 18:11

I was ponderin’ the usages of the final keyword as applied to classes in Java.

I have heard before that all classes should be defined as final by default. The theory goes that unless you are specifically designing (and testing) your classes as potentially extensible, the final class modifier is a nice ‘pertinent negative’.

In practice, this theory falls apart.

If you are exposing your concrete classes to other clients, a final class can neuter the consumer’s ability to mock your class for testing purposes. (I ran into this at one point when using Lucene at work, and tried to mock out a class.)

Another problem that arises, even if you have hidden all your concrete classes behind a nice API, is that final classes are not accessible by AOP. (At least, not in the framework that I looked into.)

13 May 2008

Revelation of the Day

Filed under: Java — nelz9999 @ 23:36

This revelation hit me (and my coworkers) today: Caching is a cross-cutting concern

You many not understand the implications of that phrase, but it leads to some interesting stuff

11 May 2008

Tomcat ROOT Context

Filed under: Java — nelz9999 @ 11:04

I’ve been fighting with Tomcat a bunch this week.

My specific challenges have been around configuring a webapp to have the context root of "/", without having to name it ROOT.war…

The documentation page on context configuration says that "Context elements may be explicitly defined":

  • in the $CATALINA_HOME/conf/context.xml file- the Context element information will be loaded by all webapps
  • in the $CATALINA_HOME/conf/[enginename]/[hostname]/context.xml.default file- the Context element information will be loaded by all webapps of that host
  • in individual files (with a .xml extension) in the $CATALINA_HOME/conf/[enginename]/[hostname]/ directory. The name of the file (less the .xml) extension will be used as the context path. Multi-level context paths may be defined using #, e.g. context#path.xml. The default web application may be defined by using a file called ROOT.xml.
  • if the previous file was not found for this application, in an individual file at /META-INF/context.xml inside the application files
  • inside a Host element in the main conf/server.xml

In my experience this week, the option of creating the file $CATALINA_HOME/conf/[enginename]/[hostname]/ROOT.xml didn’t work for me.

But, one of my coworkers (Chris) found some other resource somewhere that said you could create a $CATALINA_HOME/webapps/ROOT.xml that looked like this:

<?xml version='1.0' encoding='utf-8'?>
<Context docBase="/absolute/path/to/your/webapp/dir">
</Context>

Chris tried this setup, and it seemed to work for him. Here’s my caveats:

  1. I haven’t verified this myself yet.
  2. I’m not sure if it has to be an exploded WAR file structure, or if it can be a WAR file itself.

I will update if I find that this actually does work.

30 April 2008

Helpful Maven Command: “mvn dependency:tree”

Filed under: Java — nelz9999 @ 16:49

Sometimes you need to peruse the dependencies (and transitive dependencies) within your Maven project. The "mvn site" command generates a pretty nice version of this in HTML. (Example: Jetty Maven Plugin – Depenencies Report.)

Well, the good news is that you don’t need to go through the whole "mvn site" generation to find out this information, as the "dependency" plugin can provide this information to you via the command-line.

% mvn dependency:tree

Here is (a part) of the output from one of the projects I’m working on:

[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'dependency'.
[INFO] ------------------------------------------------------------------------
[INFO] Building SomeCompany :: Main Webapp
[INFO]    task-segment: [dependency:tree]
[INFO] ------------------------------------------------------------------------
[INFO] [dependency:tree]
[INFO] com.somecompany:somecompany:war:1.0-SNAPSHOT
[INFO] +- com.somecompany:backend:jar:1.0-SNAPSHOT:compile
[INFO] |  +- mysql:mysql-connector-java:jar:5.0.4:runtime
[INFO] |  +- antlr:antlr:jar:2.7.6:compile
[INFO] |  +- commons-codec:commons-codec:jar:1.3:compile
[INFO] |  +- commons-dbcp:commons-dbcp:jar:1.2.1:compile
[INFO] |  |  \- xml-apis:xml-apis:jar:1.0.b2:compile
[INFO] |  +- commons-httpclient:commons-httpclient:jar:3.0:compile
[INFO] |  |  \- junit:junit:jar:3.8.1:compile
[INFO] |  +- commons-lang:commons-lang:jar:2.3:compile
[INFO] |  +- commons-logging:commons-logging:jar:1.0.4:compile
[INFO] |  +- commons-pool:commons-pool:jar:1.3:compile
[INFO] |  +- dom4j:dom4j:jar:1.6:compile
[INFO] |  +- net.sf.ehcache:ehcache:jar:1.4.0:compile
[INFO] |  |  +- net.sf.jsr107cache:jsr107cache:jar:1.0:compile
[INFO] |  |  \- backport-util-concurrent:backport-util-concurrent:jar:3.1:compile
[INFO] |  +- org.hibernate:hibernate-annotations:jar:3.2.0.ga:compile
[INFO] |  |  +- org.hibernate:hibernate:jar:3.2.0.ga:compile
[INFO] |  |  |  +- javax.transaction:jta:jar:1.0.1B:compile
[INFO] |  |  |  +- asm:asm-attrs:jar:1.5.3:compile
[INFO] |  |  |  +- cglib:cglib:jar:2.1_3:compile
[INFO] |  |  |  \- asm:asm:jar:1.5.3:compile
[INFO] |  |  \- javax.persistence:persistence-api:jar:1.0:compile
[INFO] |  +- jdom:jdom:jar:1.0:compile
[INFO] |  +- ognl:ognl:jar:2.6.7:compile
[INFO] |  +- rome:rome:jar:0.9:compile
[INFO] |  +- org.springframework:spring:jar:1.2.7:compile
[INFO] |  +- net.sourceforge.stripes:stripes:jar:1.4.3:compile
[INFO] |  +- velocity:velocity:jar:1.5:compile
[INFO] |  |  \- oro:oro:jar:2.0.8:compile
[INFO] |  +- org.json:json:jar:20070829:compile
[INFO] |  +- org.htmlparser:htmlparser:jar:1.6:compile
[INFO] |  +- javax.mail:mail:jar:1.4:compile
[INFO] |  |  \- javax.activation:activation:jar:1.1:compile
[INFO] |  \- org.safehaus:jug:jar:2.0.0:compile
[INFO] +- javax.servlet:jstl:jar:1.1.2:compile
[INFO] +- taglibs:standard:jar:1.1.2:compile
[INFO] +- javax.servlet:servlet-api:jar:2.5:compile
[INFO] +- com.oreilly.servlet:cos:jar:1.0:compile
[INFO] +- c3p0:c3p0:jar:0.9.1.2:compile
[INFO] +- jaxen:jaxen:jar:1.1-beta-7:compile
[INFO] |  +- xerces:xmlParserAPIs:jar:2.6.2:compile
[INFO] |  +- xerces:xercesImpl:jar:2.6.2:compile
[INFO] |  \- xom:xom:jar:1.0b3:compile
[INFO] |     +- com.ibm.icu:icu4j:jar:2.6.1:compile
[INFO] |     +- xalan:xalan:jar:2.6.0:compile
[INFO] |     \- org.ccil.cowan.tagsoup:tagsoup:jar:0.9.7:compile
[INFO] +- javax.sql:jdbc-stdext:jar:2.0:compile
[INFO] +- org.apache.lucene:lucene-core:jar:1.9.1:compile
[INFO] +- quartz:quartz:jar:1.5.1:compile
[INFO] +- commons-collections:commons-collections:jar:3.2:compile
[INFO] +- org.apache.avalon.logkit:avalon-logkit:jar:2.2.1:compile
[INFO] +- jgroups:jgroups-all:jar:2.6.1:compile
[INFO] \- log4j:log4j:jar:1.2.11:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4 seconds
[INFO] Finished at: Wed Apr 30 16:40:42 PDT 2008
[INFO] Final Memory: 12M/508M
[INFO] ------------------------------------------------------------------------

16 April 2008

Java 5 FOREACH Syntax

Filed under: Java — nelz9999 @ 21:35

For those that don’t currently use the new Java 5 "foreach" syntax, you are missing out.

I got to a point today where I wanted to verify that the construct is doing the intelligent thing, so I wrote the following unit test:

@Test
public void forEachLoop() {
for (String str : doHeavyWeigthMethod()) {
System.out.println(str);
}
}
private List<String> doHeavyWeigthMethod() {
System.out.println("heavyMethod");
final List<String> results = new ArrayList<String>();
results.add("one");
results.add("two");
results.add("three");
return results;
}

I was psyched to see the output:

heavyMethod
one
two
three

Basically, this shows that the foreach construct only evaluates the collection once and caches the value to be used in each iteration.

However, the construct is not without some pitfalls. I would have expected the new construct to be programmed more defensively, but it is still susceptible to NullPointerException. Running the following throws the NPE:

@Test
public void forEachLoop() {
for (String str : doHeavyWeigthMethod()) {
System.out.println(str);
}
}
private List<String> doHeavyWeigthMethod() {
return null;
}

So, unless you know you are in control of the method you are calling in the expression part of the "foreach" construct, you still need to defensively check for null. And, we all know how much I love that, right?

11 April 2008

Heavyweight Syntax

Filed under: Java — nelz9999 @ 11:33

Method chaining seems like such a good idea. And Java supports it, always has. However, if you have been bitten in the butt too often by code you can’t (or don’t) control, you learn the value of defensive programming.

Whereas, I want to write code like this:

public String getDeepString(ComplexObjectA a) {
return a.getComplexObjectB().toString();
}

… I can’t. Or at least it’s not a good idea to write it like that. To protect myself, or classes that utilize my method, I have to write it like this:

public String getDeepString(ComplexObjectA a) {
String result = null;
if (a != null) {
ComplexObjectB b = a.getComplexObjectB();
if (b != null) {
result = b.toString();
}
}
return result;
}

Wash. Rinse. Repeat. Over and over and over, I’m checking for null. And, I’m getting kind of tired of it.

But wait, what light over yon hill breaks? Is it Groovy?!? Groovy provides a fantastic "?." construct, which can reduce the above noisy code to nearly what I was hoping for in my first example:

public String getDeepString(ComplexObjectA a) {
return a?.getComplexObjectB()?.toString();
}

I showed the "Unadulterated Java is so groovy" post to some of my coworkers, and the "?." construct is the single most talked about benefit of potentially adopting Groovy.

No, we haven’t adopted Groovy yet. We’ve got some work to do, including moving toward a Maven (2) build system. But from what I hear the Groovy plugins to Maven and IntelliJ make dropping in Groovy transparent and easy. We may become a Groovy shop yet!

« Newer PostsOlder Posts »

Theme: Silver is the New Black. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.