Our Craft

Making it better

Posts Tagged ‘experience’

I was using the wrong kind of SessionFactoryBean

Posted by danielmeyer on January 12, 2009

I was trying to change over from using a Hibernate mappings file to annotations, but my test kept blowing up while instantiating the Spring beans.

Then I realized that in my Spring bean file, my sessionFactory bean was declared as an org.springframework.orm.hibernate3.LocalSessionFactoryBean instead of an org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean.  The annotatedClasses property I was trying to set didn’t exist in the LocalSessionFactoryBean!

I had been focusing on how to specify the list of annotated classes (see this example in the Spring Javadoc) and hadn’t paid attention to what kind of SessionFactory bean I was working with.

Posted in Technical Stuff | Tagged: , , | Leave a Comment »

A simplifying regex

Posted by danielmeyer on January 9, 2009

Regular expressions can get pretty complex.  I’m in the process of trying to master them, but from time to time I worry that I should just give up on the concept — that perhaps there are generally easier ways of accomplishing the same thing, and regexes are a waste of time.

Then I see an example like today’s that renews my belief that  it’s worthwhile to master these regexes:

Background

A co-worker had a method that received a String of comma-separated values.  Inside the method, he did a split(), with a comma as the delimiter. A simplified version of the class function in question:


public class Splitter {
    public String[] split(String s) {
        return s.split(",");
    }
}

…and its test:


public class SplitterTest {
	@Test
	public void testSplitBasic() {
		List<String> splitString = new Splitter().splitBasic("bob, sam,harry");
		assertEquals(3, splitString.size());
		assertEquals("bob", splitString.get(0));
		assertEquals(" sam", splitString.get(1));
		assertEquals("harry", splitString.get(2));
	}
}

This test passes.  So far, so good.

The Problem

He wanted to enhance the split method to support escaping a comma within the string.  When the split method encountered an escaped comma (“\,”) , it should not consider the comma a delimiter (and it should eat the backslash).

So we would want this test to pass:


        List<String> splitString = new Splitter().splitSmart("bob\\, sam,harry");
        assertEquals(2, splitString.size());
        assertEquals("bob, sam", splitString.get(0));
        assertEquals("harry", splitString.get(1));

splitSmart(): a Non-Regex Implementation

He had a working implementation that looked something like this:


    public List<String> splitSmart(String s) {
        List<String> list = new ArrayList<String>();

        String concat = "";
        boolean concatenating = false;
        for (String x : s.split(",")) {
            if (x.endsWith("\\")) {
                concat += x.substring(0, x.length() - 1) + ",";
                concatenating = true;
            } else if (concatenating) {
                concat += x;
                list.add(concat);
                concatenating = false;
            } else {
                list.add(x);
                concatenating = false;
            }
        }
        return list;
    }

This makes the test pass, but my co-worker was not happy with it.  Too clunky.

A Simplification using a Regex

I had to think about it for a few minutes, but eventually it came to me that what we wanted as a delimiter was a comma not preceded by a backslash.  Looks like a great opportunity to use… negative lookbehind!

The regex way to say “a comma not preceded by a backslash” is:

(?<!\\),

…where (?<!X) is the regex way of saying “not preceded by X” (in this case, a backslash, which has to be escaped) and the comma is the thing to match.

Now we can simplify splitSmart() down to this:


    public List<String> splitSmart(String s) {
        List<String> list = new ArrayList<String>();

        for (String x : s.split("(?<!\\\\),")) {
            list.add(x.replace("\\,", ","));
        }
        return list;
    }

…and the tests still pass.

Note the double-escaped backslash in the split() call: the backslash already has to be escaped since the backslash is a regex metacharacter; but then each of these have to be escaped because backslash is also a Java String metacharacter.  The x.replace() line then just literal-text-replaces each backslash-comma pair with a comma; it could have been equivalently written

x.replaceAll("\\\\(?=,)", "")

…to more explicitly remove a backslash that is followed by a comma, using positive lookahead!

Conclusion

My co-worker was pleased to use the regex-totin’ split-n-replace version of the code.  We both agreed it looked cleaner and simpler, even with the somewhat odd-looking lookbehind syntax and the double-escaped backslashes.  For my part, I was happy to be able to apply my regex learning to help someone.  :)

Posted in Technical Stuff | Tagged: , | 2 Comments »

A problem that didn’t show up until later

Posted by danielmeyer on December 31, 2008

Earlier this fall, a problem showed up when the database guys first contributed Hibernate mappings.  It was unclear how the Hibernate mappings could be causing the error we were getting — and it turned out that they weren’t; rather, they were exposing a different error that had previously been there, undetected.

I find these types of things really annoying before they’re figured out, and fascinating afterward.  Here’s an email I sent out afterward:


From: Daniel Meyer
Sent: Wednesday, September 24, 2008 3:42 PM
Subject: RE: Build Failures: resolved

The “deployment fails the second time” issue has been resolved, and the CI servers are back in business.

For those who may be interested, the problem turned out to be a Maven config issue in [the functional test project]’s pom file.

(Note: you may need your techno-gibberish decoder goggles for the next details: )

In making ojdbc available to Liquibase for when we deliver schema changes, the ojdbc jar file got included in the war file.  The config has been this way for several weeks, but we didn’t notice it until we just in the last few days got to the point of contributing Hibernate mappings, which starts the Persistence service, which needs ojdbc to actually work.  At that time, the ojdbc jar in the war file fought with the ojdbc jar in JBoss’s server/default/lib directory, and just like when you were fighting with your sister over that cookie, nobody won and we got the NoClassDefFoundError.

(Or something vaguely similar to that.)

Thanks to [those who helped] for their help with this!

Now back to our regular programming…

-Daniel-

Posted in Technical Stuff | Tagged: , , , | Leave a Comment »

NullPointerException on my test’s first use of a mock

Posted by danielmeyer on November 3, 2008

This had happened before, but it got me again the other day: I was using Unitils‘ mock annotations (great stuff!) to set up my mocks, but my test failed with a NullPointerException the first place I tried to set an expection on the mock.  The reason being… I forgot to @RunWith(UnitilsJUnit4TestClassRunner.class) .  Sadly, I don’t think I was much faster diagnosing the problem this time than I was last time.

Goal: Next time this symptom appears, instantly suspect that I’m using the wrong runner!  :)

Posted in Technical Stuff | Tagged: , , , , | Leave a Comment »

I did it AGAIN!

Posted by danielmeyer on September 11, 2008

Arrgh!

I had my mocks set up to expect calls and return things, but the class under test wasn’t getting as far as it should have been, given those inputs.

I began to suspect many things, both plausible and im-:

  • “Maybe JUnit’s gone haywire!”
  • “The coverage tool must be malfunctioning.”
  • “Maybe Eclipse has gotten fouled up building my project due to that unimplemented method I’m calling far away in a different as-yet-unused part of the project”
  • Maybe a system property or environment variable is floating around, somehow interfering (though that shouldn’t matter since I’m mocking the reading of those…)
  • Maybe the mock framework isn’t working (though it seems to be doing fine for all the other test methods…)

Finally, after over an hour had passed, I noticed that in my test I was INSTANTIATING A NEW INSTANCE of my class under test… which of course then wasn’t being injected with my mocks.

I’ve written about this at least twice before…but apparently I haven’t learned my lesson yet!

Note to self: Remember not to instantiate these things manually.

Posted in Technical Stuff | Tagged: , | Leave a Comment »

Getting everything right

Posted by danielmeyer on August 15, 2008

There are sometimes a bunch of things that you have to get right, and getting any one of them wrong keeps you from being where you need to be.   (I guess it’s a lot worse for space shuttle engineers!)

Things I Had Wrong

Here are six issues, mostly from today, that all needed to be corrected for my project to work:

  1. I didn’t have a jndi.properties file with a java.naming.factory.initial setting pointing to the bitronix.tm.jndi.BitronixInitialContextFactory.  This was causing a NoInitialContextException.
  2. I didn’t realize that Bitronix Transaction Manager supports (at least) two types of config file: the transaction manager config file and the resource loader config file.  I was putting settings in the transaction manager config file (defaults to bitronix-default-config.properties) that belong in the release loader config file.  This caused those settings to be ignored by BTM (if my bitronix-default-config.properties file is being read at all, which I’m not sure of).
  3. The bitronix.tm.resource.configuration property by which you can specify a resource loader config file expects a path relative to the folder in which you started the virtual machine, not relative to the classpath, so my resource loader configuration was never being found (that’s also why I got a NullPointerException when I tried to set the resourceConfigurationFilename property on the btmConfig bean).
  4. The uniqueName I was using for the JMS ConnectionFactory was java:activemq/QueueConnectionFactory, but BTM’s JNDI implementation doesn’t support the colon-ized namespace (i.e., I needed to remove the “java:” from the JNDI-name).  [Update 8/26/2008: It turns out you can use the java:-prefixed with BTM if you do it right... ]
  5. I neglected to set the init-method and destroy-method on my PoolingConnectionFactory bean, so the my org.apache.activemq.ActiveMQXAConnectionFactory underlying my bitronix.tm.resource.jms.PoolingConnectionFactory never got initialized (causing the uniqueName to never be registered with the JNDI server).
  6. I misspelled the name of the underlying class for my connection factory bean — as  org.activemq.ActiveMQXAConnectionFactory, when it’s actually org.apache.activemq.ActiveMQXAConnectionFactory — so I got a “ResourceConfigurationException: cannot create JMS connection factory named QueueConnectionFactory” error that had as its cause farther down a “java.lang.ClassNotFoundException: org.activemq.ActiveMQXAConnectionFactory”

Honorable Mention

I had also specified the wrong implementation of the slf4j-api (slf4j-jdk14 instead of slf4j-log4j12) in my pom file, which meant I didn’t see all of BTM’s messages when I set the logging level to DEBUG in log4j.properties.  This didn’t directly keep my project from doing what it oughta, but it might have slowed the problem analysis.

Unnecessary Changes

These are things that at one time or another I suspected I needed to change, but that ended up not being part of the problem:

  • Adding a jndiEnvironment section to the JndiObjectFactoryBean definition for the queueConnectionFactory.  This would have resulted in a queueConnectionFactory bean definition like this:
    <bean id="queueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:activemq/QueueConnectionFactory" />
    <property name="jndiEnvironment">
    <props>
    <prop key="java.naming.factory.initial">bitronix.tm.jndi.BitronixInitialContextFactory</prop>
        </props>
      </property>
    </bean>

    This was taken care of by having this setting in the jndi.properties file.

  • Adding a depends-on attribute to the BitronixTransactionManager bean and/or queueConnectionFactory JndiObjectFactoryBean explicitly telling Spring which other beans needed to be instantiated before these beans.  Seems to work fine without that.
  • Adding bitronix.tm.resource.bind = true to a bitronix-default-config.properties in the root of the classpath.  The JNDI lookup seems to be doing fine without explicitly setting this property.

Analysis

Two quick points:

  • Experience will be a great help here, as inexperience with JNDI and BTM were a big part of why I took all these wrong turns; and
  • Hallelujah that it’s Friday!  :)

Where We Are Now

I have JNDI lookup working on both a JTA transaction manager and a JMS connection factory, kicked off from a JUnit-based integration test.

Next Steps

I need to get my JDBC datasource hooked up similarly, on the way to getting my whole XA example working as a JUnit test — sending a message to the JMS queue, receiving it and writing to the database, demonstrating both the commit and a rollback situations.

Posted in Technical Stuff | Tagged: , , , | Leave a Comment »

Getting a little quicker with Maven

Posted by danielmeyer on August 12, 2008

I posted the following message to the Bitronix Transaction Manager user forum when I figured out what appears to be an error in the instructions for using pre-release versions of BTM with Maven 2.

The thing that encouraged me was that this time it didn’t take much time for me to figure out that <remoteRepository> looked strange, and didn’t fit the pom schema.  I checked the Maven local and global settings.xml files, but they didn’t seem to have a <remoteRepository> concept either.  So I used an existing <repository> definition in one of my settings.xml files as a guide and converted the <remoteRepository> to that format… and it worked!

Kind of a tiny thing, but sometimes it’s the little things that make you happy… :)

The message I posted is below.


I think the instructions for using pre-release versions of BTM with Maven 2 are a little wrong: They show that you should put this in your pom.xml file:

<remoteRepository>
    <key>codehaus-snapshots</key>
    <handleReleases>true</handleReleases>
    <handleSnapshots>false</handleSnapshots>
    <url>http://snapshots.repository.codehaus.org</url>
</remoteRepository>

But that is not valid syntax for the pom file (I think it’s the format you would use for an Ant task). I think this is what needs to be put in the pom file:

<repository>
    <id>codehaus-snapshots</id>
    <url>http://snapshots.repository.codehaus.org</url>
    <snapshots>
        <enabled>false</enabled>
    </snapshots>
</repository>

I tried this and it brought in the btm-1.3-RC2.jar as I hoped:

Downloading: http://snapshots.repository.codehaus.org/org/codehaus/btm/btm/1.3-RC2/btm-1.3-RC2.jar

Or maybe I’m misunderstanding what the instructions were trying to tell me? :)


Update 8/13/2008: Ludovic has updated his instructions.  Cool!

Posted in Technical Stuff | Tagged: , , | Leave a Comment »

Plurals and intuition

Posted by danielmeyer on August 12, 2008

I just downloaded the Bitronix Transaction Manager to try out its JNDI server (and probably also its transaction management).  The JNDI server is only in the yet-to-be-released version 1.3, so I needed to use a Subversion client to check out and build from source code*.  As this was (I think) my first time doing a checkout from an external Subversion repository (though I think I’ve checked out code from an external CVS repository once or twice), I wasn’t sure what I was doing…  I followed the instructions, but kept getting errors.

I decided to try checking out a project from somewhere else.  I tried the Maven 2.0 source and that checked out fine.  Hmm.

After hmm-ing for a moment or two, I noticed that the URL for the Maven source code used the https protocol, so on a hunch I tried modifying the Bitronix checkout URL to use https… it worked.

So, obviously I should have tried that, right?  :)

It’s an interest of mine when a hunch leads me to the right solution, to try to reverse engineer what made me think to try that hunch, to see if it’s something that could be taught to someone else.  In this case I was in the process of separating concerns (“Is it the remote server or my Subversion client that seems to be having the trouble?”), when I noticed that the protocols used were different.  So I guess part of it is noticing little details — or is it noticing important details and developing good judgment on when a detail might be important?

* Well… come to think of it I could have used the snapshot Maven repository… but I wanted to see the source and the tests, to get a better idea of what this is, and of its quality.

Posted in Technical Stuff | Tagged: , , | Leave a Comment »

Technological wanderings

Posted by danielmeyer on July 22, 2008

Why is it that questions can take a while to research these days — particularly, why is my XA example taking so long to implement?  I was thinking about this the other day, and I think there are a couple of different aspects to this.

First, there are just several technologies and products that are new to me: Spring, JBoss, ActiveMQ, JMS, XA, JCA, etc.

But the complicating factor is that when things don’t work, it could be a result of something I don’t yet know about one of these new technologies, or it could be due to the way one technology interacts with another.  So if (for random example) my XA transactions aren’t working like I expect, it may be that I’m missing an XA concept that I need to understand to make it work… or it could be that it’s something about how XA works with JBoss, or with JBoss and Spring, or with JBoss and Spring and JNDI; or something about how XA works with ActiveMQ.  Or maybe the problem is in my use of AOP, or particularly AOP as it relates to Spring; or it could be a Java classloader / application server interaction issue, like duplicate classes being deployed in my .war file!

I thought I’d summarize the wanderings idea with a picture :)
wanderings2.png

Posted in Technical Stuff | Tagged: | Leave a Comment »

CS848 – Heuristics of Enough

Posted by danielmeyer on June 26, 2008

In yesterday’s post, I mentioned that I found something in the XML schema that appeared to make it possible to configure how many times a message can be unsuccessfully sent before it will be discarded*. But it was taking time to actually get the setting set to test it out and make sure it works like it appears. So… here’s a recurring question that comes up for me when I’m doing new things:

How much research is enough?

There is danger on both sides. The cost of researching this now if it works like it appearsis is that it is taking time away from other research I need to get to and could make my schedule slip. But the potential cost of not researching it now if there’s not a good answer is invalidation of our messaging approach, which we would definitely want to know about now rather than wait.

The Current Example is Getting Easier To Assess…

In this case, the fact that there is a concept of a dead letter queue for messages to go into once they’ve reached their maximum redeliveries makes me feel confident enough that there is a solution that I think it will be best to move on to my next research topic (I’ll run that by my lead).

…But in General…

In general, though, you’re making an educated guess about the unknown. I imagine a graduate-level class titled “Heuristics of Enough” teaching how to weigh such risks and make good decisions. In reality though, I think this comes by experience.

Must it come by personal experience though? I bet well-written case studies of different situations would be helpful for others to learn from…

*And actually by now I realize (thanks to a question posted to a mailing list) that they’re only being discarded because I didn’t set up a dead letter queue for them to go into…

Update: Huh – they’re not being discarded at all… there’s an ActiveMQ.DLQ (Dead Letter Queue, get it? :) queue that has 16 messages in it.  When I thought the messages were being discarded, they were being put in there.

Posted in Technical Stuff | Tagged: , | Leave a Comment »