JMX for configuing Spring?

Goal: be able to configure at startup, and modify at runtime, the configuration for Spring-managed beans.

For instance, say I have the following:

File: myapp.properties
------------------------------
processA.enabled = true
processA.path    = processA/destination

processB.enabled = true
processB.path    = processB/source
------------------------------

File: myapp-context.xml
------------------------------
<beans>
    <bean id="settings"
          class="com.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="myapp.properties" />
    </bean>
    <bean id="processA" class="myapp.ProcessA" singleton="true">
        <property name="enabled"   value="${processA.enabled}" />
        <property name="writePath" value="${processA.path}" />
    </bean>
    <bean id="processB" class="myapp.ProcessB" singleton="false">
        <property name="enabled"  value="${processB.enabled}" />
        <property name="readPath" value="${processB.path}" />
    </bean>
</beans>
------------------------------

The ${...} sequences will be replaced by the relevant values from the property file you reference. (You can also specify a replacement sequence per properties file if you wish.) This is great because Spring configuration files are not the same as application configuration files. The former are used by developers when building the application and wiring components together, the latter are used by a production team to tell your application how to work at runtime.[1]

The downside: what happens when you want to update your application while it's running? Editing the properties file takes care of the future, but AFAIK you need to restart the app to get Spring to re-read these new values and re-wire the values into its beans.

What I'd like to do is provide a configuration interface for our production team. Such an interface would write to both a persistent store (like the current properties file) as well as notify the Spring beans that there's new configuration data to pickup.

JMX seems like a perfect fit for this. The interface could write the data to a configuration object which then writes itself out to permanent storage (a properties file) as well as notifies JMX-enabled Spring beans to pick up their new configuration.

So what I'd like to do is something like:

File: myapp-context.xml
------------------------------
<beans>
    <-- defines the server from which we read configuration bean -->
    <bean id="jmxServer" class="..." />

    <-- defines the bean from which the configuration values are read -->
    <bean id="jmxConfigurationBean" class="..." />
        <property name="server" ref="jmxServer" />
        <property name="name"   value="accunurse:type=config,name=app" />
    </bean>

    <-- configurable beans, one singleton and one not -->
    <bean id="processA" class="myapp.ProcessA" singleton="true">
        <property name="enabled"   value="$jmx{processA.enabled}" />
        <property name="writePath" value="$jmx{processA.path}" />
    </bean>
    <bean id="processB" class="myapp.ProcessB" singleton="false">
        <property name="enabled"  value="$jmx{processB.enabled}" />
        <property name="readPath" value="$jmx{processB.path}" />
    </bean>
</beans>
------------------------------

The $jmx{...} would be replaced by a runtime lookup to a call to the referenced configuration bean, asking for the given property name. That referenced configuration bean would exist in JMX before Spring started up, sourced by the relevant properties file. In code this might look like the following, invoked by Spring:

MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
String configBeanName = "accunurse:type=config,name=app";
ObjectName objectName = ObjectName.getInstance( configBeanName );
Object value = mbeanServer.invoke( 
        objectName, "getValue", 
        new Object[] { "processA.enabled" },
        new String[] { "java.lang.String" } 
);
// ...inject 'value' to the 'enabled' property on the Spring bean

First, this doesn't seem possible with current Spring JMX support, which is focused on exposing your Spring beans via JMX rather than using JMX to inform your Spring beans. I've looked through a lot of documentation, blog entries and forum posts and have only seen this entry which after a quick read seems in the ballpark of what I want.

Second, this overhead isn't a big deal when there's only a singleton instance to inject the data into. But what happens when you've got a bean of prototype or other scope? Do you want to query JMX for the properties to inject every time?

I think not. So you'll almost certainly need to be able to set some sort of caching so that Spring keeps a copy of the last-seen data from JMX for a period of time. Alternatively you'll want to allow this layer to respond to JMX notifications that certain data have been changed and inject only as needed. (I like the latter approach better.)

It looks like there's an initial construct in Spring for doing so -- a beans.MutablePropertyValues class that encapsulates the properties associated with a bean. In theory you should be able to associate that with a JMX listener that watches for configuration events and routes them to the proper property values that Spring is using anyway.

So: crazy talk, or something useful?

Update: after thinking about this a little more I may be able to do this with a beans.factory.config.BeanPostProcessor implementation that (a) has a reference to the global configuration object (manipulated by the user interface I mentioned), and (b) references to all the named configuration options that we build at startup. We can then wire in configuration updates to the correct beans without too much effort, and JMX doesn't even enter into the picture.


[1] This echoes a distinction made by Michael Nygard in a recent podcast, one which I wish could have gone on for a couple more hours.

Permalink

Consuming big resultsets with JDBC

We ran into this recently at work and the answer wasn't immediately apparent via Google, so here's a summary.

If you execute a query that returns a large number of results (where 'large number' is dependent on the amount of memory you've allocated), you'll probably run into an OutOfMemoryError. The fix for this is likely different depending on the database you use. Our product is deployed on both MS SQL Server and PostgreSQL, so here's the solution for those.

MS SQL Server

Configuration fix. The JDBC connection property you're interested in is 'responseBuffering'. By default this is set to 'full', which means "the entire result set is read from the server when a statement is executed." However, you can set it to 'adaptive' so that "the minimum possible data is buffered when necessary. As far as I can tell you cannot configure what 'minimum possible' means.

Modify JDBC url to include the property:

jdbc:sqlserver://localhost:1433;databaseName=test;responseBuffering=adaptive

(See "Setting the Connection Properties")

PostgreSQL

Code fix. You need to use the 'fetchSize' property of the statement being executed to tell the JDBC driver to tell the server to use cursors. There are a few conditions where this cannot be used (autocommit mode, backward ResultSet scroll mode), but they didn't apply to us.

You should experiment in your app with the size to find a good balance between minimizing memory use and trips to the server to get more data.

Set the fetch size:

Statement st = connection.createStatement();
st.setFetchSize(2500);
ResultSet rs = st.executeQuery( "SELECT * FROM foo" );
...

(See "Getting results based on a cursor")

Permalink

Changing your approach

Last weekend during my ride I found I couldn't clip into my pedals. After I pulled over I figured out why: the cleat had come unscrewed from my shoe.[1] After screwing around with it for 10 minutes with the only tool I had on me (multi-hex wrench), I turned around and rode back to the car.[2]

I meant to take it to a shop during the week, but something always came up. And whenever I thought of taking it I made a mental checklist of the things I figured they might try:

  • hold pedal still and whack one edge of it with mallet + something hard,
  • try and seat the screws into my shoe enough to turn the cleat out,
  • grab the sides with pliers/vice grip and twist.

IMO this is a pretty limited list, and it gives you an idea of how clumsy I am in the physical world. Faced with a similar situation in code I'd have a half-dozen options at the ready and have a pretty good ranking of their effectiveness vs time to complete the task. Pretty much all by instinct.

'Instinct' isn't exactly the right word. The difference between the two is that with one I have very little practice, with the other I have loads. So it's not 'instinct' like a bird who knows how to build a nest. Instead it's an internalization of the space that the problem fits into and the associated solutions. So someone who works often with his hands, even if none of that experience is on bicycles, would have a very different result.

So Saturday I finally tried to fix it myself. I went through my checklist, quickly, with no results. Frustration grew. I then tried varying my earlier options, and the first step was to set the cleat toward one end of the clip so I could bang on it some more and hopefully pop it out. To do this I figured I could shove the cleat over with some leverage, and slid the edge of the large flathead screwdriver between the cleat and pedal, and twisted.

To my utter amazement, the back part of the cleat came loose! A few more twists and the cleat was free. I couldn't believe how easy the solution turned out to be, and how dumb I felt for not seeing it.

Looking back, I knew that I didn't know what I was doing, and compensated by trying to recreate how the cleat gets freed when it's screwed to a shoe. But I didn't know enough to take that lack of knowledge and readjust my approach. What I should have done is look at the stuck cleat in terms of the forces holding it in (the clips), and my options for exterting opposing forces for getting it out. I wasn't thinking of a general problem, but instead tryng to recreate a specific solution.

Generalizing, I think one of the reasons we tend to get stuck on a problem is that we cannot look at it in a sufficiently general way to compare it to other problems. So we focus on one aspect of the problem that looks like another problem we have -- oh, this use of localization in column headers reminds me of the time I used this cool AJAX live editable grid widget, so I'll do that again. And we don't really think about the problem and consider it on its own merits, so it remains unsolved.


[1] Of course, the first thing I did was grab my G1 and search for people who had the same problem. Nothing turned up. Hopefully future sufferers will find this reference to a cleat getting stuck in Time Atac pedals and be able to execute the simple solution (wedge something betweeen the cleat and pedal, and twist).

[2] Fortunately most of the return was downhill, so not being able to clip in and exert more pedal pressure didn't hurt me as much. It still took a little longer to get home, but that's a pretty small price to pay.

Permalink

Java validation framework in JavaScript?

It seems that being able to do client-side and server-side validation with the exact same code (plus extension points for implementation details) is a Good Thing. So is there a framework out there where I can write my validation rules in JavaScript and execute them either in the browser or on the server-side? My searches didn't find any, but using 'javascript validation' in your search brings in a lot of chaff.

Permalink

Ease up on coding horror

I've been meaning to post this for a while, but this mention of Jeff Atwood being annoying brought it back onto the radar.

Jeff and his site Coding Horror have been maligned as "script kiddie", "never done anything worthy of respect", and probably lots of other awful things that people would never say face-to-face. (And those are both from one set of comments!)

I had similar opinions (though not so rude or boorish) for a while. But I later had a few realizations that brought me around to Jeff's side.

First, after dropping off the blogging map for a while I have a much deeper appreciation for the amount of effort it takes to keep a blog going. It's relatively easy to write on the set of ten or twenty topics that you start with. But to publish non-trivial articles, week-in and week-out, shows real discipline and desire. And one of the things I've grown to understand over time (even before reading Outliers) is the value of discipline over intelligence/talent.[1] In one of the few interviews I've done I wasn't able to include Sim's thoughts on people hiting him up to publish their comic. He said something along the lines of (going through his side of the dialogue), "This looks nice. What else do you have? Oh, a few full-page drawings? Tell you what, go home and do a fully penciled, inked, colored and worded page a day for two months, then call me back." Nobody ever did. Doing anything creative on a regular basis is hard.

Put another way: it's easy to bitch from the cheap seats that something is dumb or simple. Fine, where's your output? Oh, you don't have time? Or you have a few drafts that aren't quite ready to publish because of your high standards? Yeah, thought so.

Second: When you write there's pressure to always have something new to say. But Jeff ignores that.[2] That's not to say he just copy-and-pastes other peoples' work. Instead, he looks at the things he does in his daily work or play and writes about them in his own voice. Is it "new" that running an antivirus program slows down your machine? Or making concrete some of the benefits of multiple cores? Of course not, technical hardware sites have done this stuff (dryly) for ages. But following through with numbers (along with how they're gathered, also useful), collecting information from other sites around the internet and weaving them into a narrative is valuable.

Third: the dude has a thick skin. In the typical net fashion people talk as if they know him and malign his work and personality, spewing out bile that you know would never be vented in the real world, face to face. Me? I'd probably get sick of the bastards after a while, tell everyone to go pound sand and close up shop. But he keeps chugging along, banging out short items on twitter and long blog posts.

Finally: you'd barely know from his output he's got a new infant in the house. I was just able to keep up with my day job and have an occasional adult conversation with my wife for the first month or two after Ella came, much less actually write something in my spare time.

I don't agree with everything he says, and his Windows-centrism can get annoying (particularly when it's combined with ignorant Java-negativism), but I appreciate his work for what it is and hope he's able to keep it up.


[1] Don't willfully misinterpret this to mean that I think Jeff is stupid.

[2] And rightly so, in my opinion. People wind up either not publishing because they think they don't have anything original to say, or saying something 'edgy' but stupid because it has to be original. There are very few people doing anything original. Most of us are working on the same shit as everyone else, with minor variations. You are not a unique snowflake.

Permalink

Pretend is real

This weekend we switched a bunch of rooms around, including Ella's. During the move all the stuffed animals previously on top of her closet were on the floor, and at one point I decided to pile them all on top of Ella on her bed.

They stayed for a while, and later Ella developed out a story of going to the animal show. This went through different versions (going to the Elmo show, going to the duck pond to see Dora and the animals, going with Elmo to the duck pond to see ducks). Regardless, there was a big production about getting the animals to wherever we were going -- all the animals on her bed were assigned to different cars. At one point I had the green car with six animals, Ella had yellow with eight. Our cars changed colors and occupants several times during the trip. We never actually arrived.

Later, Barb took her out to the grocery so I could put my mad IKEA skills to work on the last piece of furniture. But when they got home Barb gave me a look, and Ella had tears running down her face.

I quizzed her with my eyebrows. "She thought we were going to the Elmo show after the grocery," Barb said, picking up Ella from the carseat.

This blew me away. She made up a show, then got upset because she wasn't going. Was this why we never made it to the show when we were playing, because she thought we'd be going for real?

And then it struck me how concrete the pretend world can be for kids her age. Just talking about something can make it so. That's a wonderful and scary idea.

Permalink

First ride in 2.5 years

Yesterday I took my first bike ride in over 2.5 years. There were a number of uncertainties going in:

  • I had a new pair of shoes along with new cleats, picked up in anticipation of riding in 2007 that never happened. I remember having a little trouble getting used to the clipless pedals and my muscle memory for getting in and out was gone. So I anticipated at least one tip-over where I'd need to stop but forget to twist my heel.
  • My bike had been in the basement for the whole time; what crud had it accumulated? Would the tubes and tires be in good shape?
  • Physically, I've been exercising fairly regularly since early February. But running on a treadmill and riding a sit-down exercise bike is very different than being in the real world.
  • Stuff I didn't know I didn't know.

I went on my normal path of the Montour Trail. Typically I'll get on just off the Montour Run exit from the Parkway, but the Parkway was closed this weekend from 79 westbound, so instead I drove up to Coraopolis.

One thing I'd forgotten was that the trail goes slowly but steadily uphill. I used the My Tracks application on my phone to plot the course; it told me the elevation change from start to midway was about 350 meters. Fortnately, that means that the ride back was downhill.

Another thing I'd forgotten was how to downshift! Seriously. I'd only ridden this bike a handful of times after I got it in 2006, and it's the first road bike I've had. Eventually I figured out that moving the brake lever inward (for the rear gear) downshifted. Dumb.

I wound up covering nearly 22 miles in 1.75 hours. Not a great pace, but better than I expected. No tip-overs. And physically things were okay, though I'm a little sore the next day. But it's a good sore, like a "my muscles are there" sore, vs. a "I don't want to move" one.

Permalink

Hello, Miss Understanding

This is mildly embarrassing, but I've been misunderstanding a common slang phrase for as long as I've known it. The phrase is "butterface," which is a rude way of referring to a woman with a nice body but a not-so-nice face. (Not sure what the male equivalent is.)

I'd thought it was making some comparison to actual butter -- does that mean she's greasy? Or mushy? Or that she goes well with toast? Every once in a while I'd hear it on the radio and went over the possibilities in my head, but in the end, I figured it was a reference to some pop culture thing that I just didn't get, being on the custom of old-dudeness.

The other night we went out to get ice cream, and Barb mentioned some woman with a cute body. The woman walked past and (being a good husband) said, "You're much cuter than her. She's a butterface."

"What's that?"

"Someone who has a nice body but not a great face. I don't quite get what it means, how a face is like butter..."

She started laughing, "But her face, get it?"

"Oh... yeah," I said sheepishly.

"Now you have something to blog about," she said.

Permalink

REST talk at PittJUG tonight

I'll be talking tonight at the Pittsburgh Java Users Group on REST, giving examples in Jersey. (See invite if you want to come but haven't signed up yet.) As with most talks I spent too much time reading and thinking in preparation and not enough on the talk itself. It probably suffers from too much content, but I have no problem skipping over sections that people don't find interesting.

Slides, my dorky little sample application, and a bunch of links I found useful will be posted later today.

If you attend the talk and want to give me public feedback, this is as good a place as any to do it.

Permalink

My hair isn't that bad

A colleague last week:

Colleague: Did you get your hair cut?

(She said it as if a 'finally' was between 'you' and 'get', which was well deserved.)

Me: Yeah, I needed it.

...pause...

Colleague: Did you get it cut at the mall?

Ouch! Even worse: she wasn't trying to be snarky.

Permalink