Sunday, February 28, 2010

I've recently started barefoot running. Chi Running has been my injury-free savior for a few years but I feel like I need to do something extra to break out of my current form plateau. Barefoot certainly seems to be doing the trick. I can feel my form improve every time I do it.

But I can't always be barefoot. I don't want to blow it and cut my foot running through a field or whatever. So I bought a pair of Vibram Five-Finger TROs (VFF TROs) to protect my feet. They do a great job of protecting the bottom of my feet. I smacked into a little tree stump hidden under some leaves the other day and I'm sure the VFFs saved me from a nasty gouge.

But... My VFF TROs keep chaffing the inner sides of my feet. The chaffing happens right where the TROs strap blends/attaches with the sole. And it hurts!

The first time I wore my TROs I just ran too far. I read online the the chaffing was probably due to my lazy feet not being used to running barefoot. Seems ironic but you need to run barefoot for a while before using VFFs. OK. So I ran short barefoot runs a few times a week and built up to about 15 minutes. Then I started wearing my VFFs for sort runs after getting home from the barefoot runs. I built up to longer runs of around 30 minutes in my VFFs.

Then came yesterday. It was raining and even had some hale. So I headed out in my VFFs and had so much fun I didn't get back for an hour and 10 minutes! ... What a fun run! ... Anyway. I could tell the chaffing was happening but was surprised to find how much when I finally took of the VFFs. ... Ouch!

So maybe it's just me. Maybe it's that they aren't good for running when wet. May there's a design flaw in the strap-to-sole seam. I don't know.

I am having a blast. But I wish the chaffing would stop.

Monday, December 31, 2007

DWR, IE memory leak related to timeout setting

I've had a few time when I wanted to point out an IE memory leak with DWR but couldn't find a good link to an archive online. ... Please don't think I'm evangelizing against DWR. I like DWR plenty.

So. Here's a couple of emails I sent to the DWR list a while back. They never got a reply.


Christofer Jennings --- Sat, Jul 7, 2007 at 3:07 PM
To: users@dwr.dev.java.net

There might be an IE memory leak in engine.js related to timeout settings.

I've been chasing a memory leak for quite a while. After many tests, I
think I've isolated it to setting a timeout for a DWR call. Below is
the lines in dwr version 2.0.1's engine.js that I think look
suspicious because of the function block / closure (lines 634 - 635).
Below that is my jsp with a comment on the timeout line. The poll
method returns a response object with a message property, but
otherwise it's pretty straight forward. Attached is the Process
Explorer memory use graph showing slopes for when the timeout is set,
as well as no slope when timeout is not set.

My tests were all done using IE 7 (version 7.0.5730.11) on Windows XP,
but I've seen the (possibly) same leak in IE 6. I think they are the
same as far as this is concerned.

In any case, my next test will be to change the closure to a function reference.

Does this look right? Has anyone else had trouble with timeout
settings and IE memory leaks?

,chris


#### from engine.js ######
if (batch.timeout && batch.timeout != 0) {
batch.interval = setInterval(function() {
dwr.engine._abortRequest(batch); }, batch.timeout);
}

#### my jsp ############
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>DWR Poll Test</title>
<script type='text/javascript' src='../dwr/interface/MyObject.js'></script>
<script type="text/javascript">
function doPoll()
{
MyObject.poll(
{
timeout: 2000, /* removing this line stops the leak */
callback:function(response)
{
var now = new Date();
var msg = now + "\n----------------------";
msg += "\n message = " + response.message;
msg += "\n----------------------\n" + now;
dojo.byId("theTextArea").value = msg;
}
});
}

window.setInterval(doPoll, 1000);
</script>
</head>

<body>
<h2>DWR Poll Test</h2>
<textarea id="theTextArea" rows="10" cols="60"></textarea>
</body>
</html>




Christofer Jennings -- Sun, Jul 8, 2007 at 10:44 AM
To: users@dwr.dev.java.net

Using a function reference stopped the leak. It can probably be done
better, but the change I made for the test is below. The resulting
graph is attached.

#### from modified enjine.js ######
dwr.engine._chris_abort_batch;
dwr.engine._chris_abortRequest = function()
{
dwr.engine._abortRequest(dwr.engine._chris_abort_batch);
}

/** @private Actually send the block of data in the batch object. */
dwr.engine._sendData = function(batch) {
...
// Set a timeout
if (batch.timeout && batch.timeout != 0) {
dwr.engine._chris_abort_batch = batch;
batch.interval = setInterval(dwr.engine._chris_abortRequest, batch.timeout);
// batch.interval = setInterval(function() {
dwr.engine._abortRequest(batch); }, batch.timeout);
}
...




Final note: This "fix" is a complete HACK. I don't recommend it at all.

Friday, November 16, 2007

Subverted

I ended up installing subversion downloaded with an installer from open CollabNet. It set up everything I need. Then I followed the quick start guide in the svnbook to set up a local repository. TortoiseSVN was already installed so I used it to add my wickety project. Then I set up SCM in my maven pom to point to the local repository.

... Then Continuum was happy.

Setting it all up was a little tough because I didn't know what I was doing. The continuum mailing list was very very helpful though. Three people guided me through the setup within about 30 minutes of my first post! ... It's good to have fiends :)

One oddball thing that happened was that the Continuum-run Maven build needed the pom to explicitely declare that the source is java 1.5. Otherwise it complained and failed to compile because I'm using generics.

Thursday, November 15, 2007

Continuous Integration, not yet

OK. I got Continuum installed and running. That's really easy. Just download a zip, unzip it somewhere, go to it's bin directory (for your OS) and run it. The admin account setup is easy. And the continuum FAQ has info on how to allow files to be uploaded with the file protocol. Thanks to the mailing list for helping me remember to look at the FAQ :)

But then I ran into trouble. Since I'm just messing around with this little app, I don't have SCM set up. Problem is, Continuum expects the Maven POM to have SCM set up. ... I tried copying the SCM settings from the maven site, but the Continuum builds fail because I don't actually have SCM. Can't fake it. Darn.

So now I guess I need to set up subversion. I've never done that before.

Coverage

Yesterday I missed a test case. My tests passed but the web app failed. I don't want that to happen again so today I'm going to bring code-coverage to my wildly cravy-good app that shows a user's name!

Cobertura is a great free code coverage tool. I've used it a little in th past, but I'm rusty. It has a maven plugin too.

...

Aw. For cry'n out load. That was too easy! The maven integration really shined this time. All I had to do was go the the cobertura maven plugin page, grab some xml for my pom, then run mvn cobertura:cobertura and, ta-da, there's my coverage reports!

If you've never done code coverage before, you should. Especially when it's this easy!

But wait, I wasn't able to use it on my last project because it wasn't that easy. So what's the difference? Well, obviously, my little wickety app is dead simple. The other project had all sorts of things going on like JSPs, applets, web-services, JMS, legacy home grown persistence management, blah, blah. blah. Parts of it were designed to be tested with JUnit. Parts used home grown test classes. Most relied on human testing. Of the JUnit and test-class tests, most were stale and broken. Bottom line: TDD (and coverage etc.) was not part of the project culture and so it was like forcing a square peg in a round hole.

I'm starting on a new project next week. It is still in its early stages and looking very waterfall-ish. My intention is to bring TDD and automation in immediately so it has a chance to take root. One issue to be addressed is whether we will use wicket or JSF. Seen from a TDD perspective, I think it boils down to this: TDD can be done with either but will be more effective when there are less impediments. Supposedly JSF can be tested automatically, but only in a container so far. The TDD I did yesterday didn't need a container and, so, was very straight forward and clean. TDD has been part of the wicket culture since the beginning (as far as I know) and it shows.

So. Back to my little wickety app.

Code coverage is great. But so far I still need to run it manually. Not good. ... Time for continuous integration! (to come)

Wednesday, November 14, 2007

Wicket TDD fun

So I started trying to do Wicket TDD in IDEA today.

The maven archetype for the wicket quickstart app doesn't include dependencies for JUnit or EasyMock sjavascript:void(0)o I had to add those to the POM....

<dependency>
<groupId>easymock</groupId>
<artifactId>easymock</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
</dependency>


Then I got dumb for a few minutes and thought "how the heck do you sync up the IDEA project with the POM?".... Well, there's a sync button in the Maven Projects tool in IDEA. Click. Zing. Done. Nice. I haven't set the project to automatically download javadocs and sources so I had to click that button too. ... Why haven't I made it automatic? Good question. I'll do that now...

Once I had the dependencies in place I started writing a test. Ther are a couple of examples online that I'm using for reference. This one here is actually about testing wicket apps that use Spring. I might use Spring so it's interesting to see that option. Also, it uses JUnit and EasyMock which I do want now. Gotcha: this example uses some deprecated EasyMock stuff.

The other page about wicket testing just covers using WicketTester on its own.

I decided to TDD a user detail page. It's really dumb by design to start with and only requires that a name be displayed. (I guess I'm doing incremental design here.) To make it a little interesting I made an interface for a UserStore (think DAO if you must, think REPOSITORY if you know DDD) with just one method...

public interface UserStore {
public List getAllUsers();
}


Caveat: I went on a little exploration here to figure out how to do the next part. I actually goofed and made the test second, to be honest. After batting it around a little I got it to work.

Here's my user detail page test...

public class UserDetailPageTest {

private UserStore mock;
private WicketTester wicketTester;

@Before
public void setUp() throws Exception {
mock = createMock(UserStore.class);
wicketTester = new WicketTester();
}

@Test
public void testRender() throws Exception {
List users = new ArrayList();
users.add("joe");
users.add("bob");
users.add("ted");

mock.getAllUsers();
expectLastCall().andReturn(users);
replay(mock);

wicketTester.startPage(new ITestPageSource() {
public Page getTestPage() {
return new UserDetailPage(mock);
}
});
wicketTester.assertRenderedPage(UserDetailPage.class);
wicketTester.assertLabel("userName", "joe");

verify(mock);
}
}


Yeah. Pretty lame. I mean, why the heck does "joe" just show up. But the point is that it got me to figure out how to do it. One thing that got me was that I tried to inject the UserStore with a setter but there seemed to be no step allowing me to call the setter. So I inject it in the constructor and use ITestPageSource. Supposedly Spring injection can help so I'll have to try that out (later).

My page looks like this (java, then html)...

public class UserDetailPage extends WebPage {

private UserStore userStore;

public UserDetailPage(UserStore userStore) {
this.userStore = userStore;
add(new Label("userName", userStore.getAllUsers().get(0)));
}
}

---------------------

<html xmlns:wicket="http://wicket.sourceforge.net/">
<head>
<title>User Detail</title>
</head>
<body>
<h2>User Detail</h2>
<span wicket:id="userName">[user name will go here]</span>
</body>
</html>


Yippee. I learned some stuff today. Now I'm adding a link from the quickstart's HomePage to my UserDetailPage with TDD...

I already made a HomePageTest class so I just added a test method to it...

@Test
public void testUserDetailLink() throws Exception {
wicketTester.startPage(HomePage.class);
wicketTester.assertRenderedPage(HomePage.class);
wicketTester.assertPageLink("linkToUserDetail", UserDetailPage.class);
}


Which dutifully failed with org.apache.wicket.WicketRuntimeException: path: 'linkToUserDetail' does not exist for page: HomePage

So I add it.

<html xmlns:wicket="http://wicket.sourceforge.net/">
<head>
<title>Wicket Quickstart Archetype Homepage</title>
</head>
<body>
<strong>Wicket Quickstart Archetype Homepage</strong>
<br/><br/>
<span wicket:id="message">message will be here</span>
<br/>
<a href="#" wicket:id="linkToUserDetail">[go to user detail]</a>
</body>
</html>


But then the test fails because Wicket instantiates the UserDetailsPage with reflection but there's no empty constructor. So I add that. But that means I have to set the UserStore to something in the empty constructor.... So I decide to set it to null and add a bit of smarts to avoid an NPE...

public class UserDetailPage extends WebPage {

private UserStore userStore;

public UserDetailPage() {
this(null);
}

public UserDetailPage(UserStore userStore) {
this.userStore = userStore;
String userName = (userStore!= null && !userStore.getAllUsers().isEmpty()) ?
userStore.getAllUsers().get(0) : "No User Found";
add(new Label("userName", userStore.getAllUsers().get(0)));
}
}


And that almost works but ... EasyMock complains because it only expects on call to the UserStore mock but now there are two. So I tell it to expect any number of calls like so (in UserDetailPageTest)...

mock.getAllUsers();
expectLastCall().andReturn(users).anyTimes();
replay(mock);


And it works!!

OK. I learned some stuff today! I dropped the ball a bit and didn't really do test-first when starting the user detail page development. But I did do it for the link and it lead to interesting stuff. Also, using TDD has really got me a better understanding of Wicket.

Weird thing is. I am totally confident the page and link will work even though I never deployed the application. ... Hmmmm. "Totally confident" I better check that.

Launch Jetty from in IDEA and...

HA! It failed. I got an NPE on the UserDetailPage because I never tested how it rendered if using the empty constructor. Back in a minute....

So I made this test in UserDetailPageTest, letting wicket use reflection on the empty constructor...


@Test
public void testRenderWithoutUsers() throws Exception {
wicketTester.startPage(UserDetailPage.class);
wicketTester.assertRenderedPage(UserDetailPage.class);
wicketTester.assertLabel("userName", "No User Found");
}


It of course fails. So I follow the stacktrace and discover that I forgot to use the reults of the nifty avoid-the-NPE code I put in. Silly me. Actually, IDEA was giving me warnings too. More silly me.

So this....


public UserDetailPage(UserStore userStore) {
this.userStore = userStore;
String userName = (userStore!= null && !userStore.getAllUsers().isEmpty()) ?
userStore.getAllUsers().get(0) : "No User Found";
add(new Label("userName", userStore.getAllUsers().get(0)));
}


Becomes this...


public UserDetailPage(UserStore userStore) {
this.userStore = userStore;
String userName = (userStore!= null && !userStore.getAllUsers().isEmpty()) ?
userStore.getAllUsers().get(0) : "No User Found";
add(new Label("userName", userName));
}


And the tests all pass, and the web app runs in Jetty as expected.

So. for one last time I'll say it... Hey! I learned some stuff today!

This is the best TDD experience I've ever had with a web application. Thank you Wicketeers!

Monday, November 12, 2007

Before I go on ... Seaside


By the way. I wish I was doing this application with Seaside. I finally got around to trying out Sqeak and Seaside a few months ago, after wondering about it for two years at least. Smalltalk is a great environment (more than just a language) and Seaside is a great web app framework. I haven't had the chance to work with eather for anything substantial, but just going through examples and trying it out opened my eyes to how much better software development can be. ... But there's no way my current project would go for it! Java has been chosen. Period. ... Wicket is the closest thing in Java that I know of to Seaside. Frankly, that's part of why I'm pitching it.

Hat's off to the Smalltalk, Squeak & Seaside communities. Keep showing the light.

Don't get me wrong. Wicket rocks. It's Java that gets a little clunky sometimes IMHO.