Category: Java

Finding real object under spring proxies

As part of detecting side effects across tests, we needed to inspect some objects in tests autowired by spring. Unfortunately these objects were automatically proxied with the current configuration (and needed by some tests) so we needed some way of accessing the underlying proxied objects.

We didn’t really find many good examples of how to go about bypassing the spring proxies created through AOP. Doing a bit of debugging we found that spring used CGLib to generate its proxies and there is fortunately a method made accessible called getTargetSource() that gives you the underlying object. Here’s the helper class we wrote to extract it.

public class CglibHelper {
    private final Object proxied;

    public CglibHelper(Object proxied) {
        this.proxied = proxied;
    }

    public Object getTargetObject() {
        String name = proxied.getClass().getName();
        if (name.toLowerCase().contains("cglib")) {
            return extractTargetObject(proxied);
        }
        return proxied;
    }

    private Object extractTargetObject(Object proxied) {
        try {
            return findSpringTargetSource(proxied).getTarget();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private TargetSource findSpringTargetSource(Object proxied) {
        Method[] methods = proxied.getClass().getDeclaredMethods();
        Method targetSourceMethod = findTargetSourceMethod(methods);
        targetSourceMethod.setAccessible(true);
        try {
            return (TargetSource)targetSourceMethod.invoke(proxied);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private Method findTargetSourceMethod(Method[] methods) {
        for (Method method : methods) {
            if (method.getName().endsWith("getTargetSource")) {
                return method;
            }
        }
        throw new IllegalStateException(
                "Could not find target source method on proxied object [" 
                        + proxied.getClass() + "]");
    }
}

Clearing In-Memory Messages held in ActiveMQ

One of the major troubles with integration tests are the tradeoffs you get with speed and feedback. As systems get larger, the more integration tests you have, and the more chance you might preserve state. I’ve been fighting a build inherited by our team where intermittent integration tests prove troublesome. In the next series of posts, I’ll detail some of the issues we’ve found and some of the fixes.

Our current system uses JMS for messaging and one of the first stateful problems we found were messages being left over from previous test runs in our ActiveMQ instance. We had a few options for doing it out of memory including a purge script and a call to deleteAllMessages though the latter failed because we stored messages only in memory.

Instead we worked out how it stores messages, and wrote a class to go through and clean them all up.

public class ActiveMqHelper {

    public void removeAllMessages() {
        Map<String,BrokerService> brokers = BrokerRegistry
                .getInstance().getBrokers();
        try {
            for (BrokerService brokerService : brokers.values()) {
                Broker broker = brokerService.getBroker();
                new ActiveMQBrokerExtension(broker).clearAllMessages();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private class ActiveMQBrokerExtension {
        private final Broker broker;

        public ActiveMQBrokerExtension(Broker broker) {
            this.broker = broker;
        }

        public void clearAllMessages() throws Exception {
            Map<ActiveMQDestination, Destination> destinationMap 
                = broker.getDestinationMap();
            for (Destination destination : destinationMap.values()) {
                ActiveMQDestination activeMQDestination 
                        = destination.getActiveMQDestination();
                if (activeMQDestination.isTopic()) {
                    clearAllMessages((Topic)destination);
                } else if (activeMQDestination.isQueue()) {
                    clearAllMessages((Queue) destination);
                }
            }
        }

        private void clearAllMessages(Topic topic) throws IOException {
            List<Subscription> consumers = topic.getConsumers();
            for (Subscription consumer : consumers) {
                ConnectionContext consumerContext = consumer.getContext();
                MessageStore messageStore = topic.getMessageStore();
                messageStore.removeAllMessages(consumerContext);
            }
        }
        private void clearAllMessages(Queue queue) throws Exception {
            queue.purge();
        }
    }
}

Someone might one day benefit from this.

Another maven workaround – Disabling parent defined plugins from running

Perfect. Just what we need when someone forces a parent pom onto your project…

<build>
  <plugins>
     <plugin>
        <artifactId>thePluginArtifact</artifactId>
        <groupId>thePluginGroup</groupId>
        <executions>
           <execution>
              <id>the-execution-id</id>
              <phase>none</phase>
           </execution>
        </executions>
     </plugin>
  </plugins>
</build>

Details provided from here.

Testing Pattern: Exploratory API via the Web

Last year I was working with Tiest, a former colleague of mine at a bank working on a system with an internal API. It was quite an experience, though I will save that for another (set of?) blog posts for another time. The application was centrally hosted with a client API that allowed people to interact with the server side. The testers needed something to help them do more exploratory testing and my former colleague came up with a great solution to this problem that I thought would be worth recording here for posterity.

Our solution had these characteristics:

  • Provided through a web browser – Installing items onto the testers machines became a bit laborious, namely because they didn’t have rights to install, change or run anything with administrator privileges. It was easier to deploy the tool centrally, and then let the testers prod from afar. This was as simple as writing a page that submitted some code to a web server, that than executed it and returned the results back to the client.
  • Supported dynamic execution – We could have written a web layer on top of the client API but we didn’t really want to add another layer for maintenance. We simply used the javax.script package to turn our standard POJOs into a scriptable/dynamically invokable system.
  • Built in reflection functions – Using the scripting interface meant that the server would not store any state. So the server had a number of built in functions such as a listAll(object) that would show all available property/methods to the user
  • Example queries stored on a wiki – When a tester would ask for something to be checked against the test environment, I would convert it into an appropriate query they could paste into the query browser window. They could then execute it, tweaking parameters, etc and learn to compose things. They didn’t have to really understand how java (as script) worked, just build on what was there.

Although I won’t be reaching into my testing patterns toolkit for this pattern too often, I feel it worked well to enable our non-technical testers to get at something given a number of environmental constraints.

Swarming on Stories

On leading a new team, I’m definitely trying to be as open to trying new practices particularly as I feel it is an important part of The Beginner’s Mind (topic to be talked about at InfoQ). One of the new practices we tried last week was swarming work on a user story.

Normally, our natural work in progress limit for development is limited by the number of pairs we have on the team (although not all tasks need pair programming). This time, I’m the odd one out, acting as tech lead and needing to do a handful of other activities including working to maintain constant flow between our BA and QA functions and guiding the development in the right direction. In a different world, I would have started a story and with other duties, probably be quite interrupted in flow to completion.

This time, we broke down a story into as many tiny tasks as possible, discussing those that needed some design elements, or identifying those tasks that could be taken in solo (such as knowledge gathering with report back) and the three of us worked on the same story. The result was a very minimal work in progress limit and actually, we made a lot of progress in a rich environment where we are learning about not only the constraints of the current build and development systems, but working out the best ways to implement what we need and deliver value.

I’m quite happy to report that I’m really liking the swarming on stories. It helps me feel involved in the way that things are going, rather than keeping on top of too many ongoing threads. I do wonder how many people it would be to scale to, but for now, it’s working for us. Inspect and amplify, or inspect and adapt!

Picture kindly borrowed from Max xx’s Flickr stream under the Creative Commons licence.

java.io.tmpdir on Mac JDK1.6

Diagnosing a test failure on a new machine today, I stumbled across this different behaviour in JDK1.6 on my Mac, running OSX10.6.6 where:

System.getProperty("java.io.tmpdir")

was returning a strange value of /var/folders/Ob/Ob-aqIAEG2WzgTa5ezd5qU+++TM/-Tmp-/ (note the plus characters) instead of the normal value of /tmp it used to return. Fortunately this property can also be set at on JVM start, by passing it in as an environment variable

-Djava.io.tmpdir=/tmp

UTF-8 not supported by ResourceBundleMessageSource

Every time I return to Java, I’m reminded by how hard simple things seem to be. Localisation is often quite important for applications, so I expected UTF-8 support out of the box with Spring Framework and Java via their ResourceBundleMessageSource and standard ResourceBundle classes.

Things are never that simple as pointed out by the following articles:

Despite the poor documentation not noting this, there are work arounds described in the links above. Alternatives include using the, much longer named, ReloadableResourceBundleMessageSource and InputStreamReader classes.

Disabling Flip Screen

When using R#, or IntelliJ, the keyboard shortcuts often involving hitting some combination of CTRL, ALT, SHIFT. Unfortunately my laptop (using an Intel graphics card) for Windows 7 has CTRL+ALT+UP and CTRL+ALT+DOWN bound to flipping the screen.

Really surprising the first time and grew troublesome when I wanted to rearrange the order of some methods.

Disable this keyboard short cut on the dialog as shown above. This was accessed via the Control Panel – Intel (R) GMA Driver for Mobile.

Thoughts On Øredev

Last week Sweden’s Malmö hosted Øredev for the sixth time. I believe it attracted more than 1400 people, all with varying backgrounds and interests. Unsurprisingly, the majority of attendees turned out to be Swedish and Danish people (with Malmö very well connected to Denmark via their famous Baltic Ocean crossing train).

The Cultural Experiences
Being held in Sweden, the organising committee did well to treat us to some cultural delights including the Swedish sauna-Baltic Ocean run followed up by a delicious traditional fish meal). One of the organising members even welcomed us into their home for drinks before the speakers’ dinner where Glögg continued to keep the cold at bay. The difference of soaking raisins and almonds really surprised me. Malmö’s deputy mayor then welcomed us at their majestic townhall where all the speakers unanimously marvelled at the decadent surroundings. The meal stayed true to the region with first, a regional speciality, black soup (and yes, like black pudding, it has a very special ingredient) before following that up with a hearty roast goose meal and a spiced apple pudding for dessert.

Logistics and Organisation
The organisers impressed me with how smoothly the entire conference ran. Malmö’s Slagthuset (slaughterhouse) hosted the conference for the first time and although not all the spaces turned out ideal (with small walkways between some major rooms), I think it contributed to the friendliness and openness I discovered.

The organisers also did a fabulous job responding to attendee’s needs. For example, on Monday they moved a number of tutorials to warmer rooms after realising the strong draughts let in by workmen who still needed to complete their work. Another example is when they quickly disabled the authentication on the wi-fi when it proved to be another barrier to being connected. Unfortunately the wi-fi turned out to be a little bit flakier throughout the conference.

I also really enjoyed the evening entertainment that flowed into the venue rather than the “move to another location and lose people” approach several other conferences do. This helped to keep the conversation flowing (and we all love our flow!).

Topics
Øredev offered a huge variety of interesting topics with tracks covering mainstream languages such as Java/.Net, NoSQL, Agile & Lean, Collaboration, Patterns, Smart Phones and Architecture with lots of really interesting topics. I’d keep an eye out for their website and trawl the twitterverse (#oredev) for the interesting discussions.

The keynote presenters also turned out really well.

Dr Jeffrey Norris presented what he thought as agile values leading to mission critical success at NASA (Vision, Risk and Commitment) demonstrating through a “wow” 3D demonstration using the ARToolKit. He used the stories of famous inventors, particularly the rise of Graham Alexander Bell to emphasis these elements very effectively.

I saw John Seddon a few months ago and although I’d heard him present pretty much the same talk, appreciated his message was an important one that more people really needed to hear. I think there is great value in spreading his emphasis on holistic system thinking even further in the work that we do. Entertaining and very British, Seddon completed his keynote without leaning on any slides and to a very positive reaction from the audience.

I missed Henrik Kniberg‘s keynote so can’t really comment.

The final keynote came from Atari Corporation geek legend Nolan Bushnell envisaging what the next key software projects would be in the future. I think everyone enjoyed the talk simply because it was Nolan though I think wasn’t as executed as professionally as it could have been.

People to meet
One of the really great parts of Øredev was all the people around you. As one person put it, you could be talking to a person and then suddenly realise that they created X (where X = language, framework, tool, etc) or someone who wrote a lot of the blog entries that you’ve been reading. I think that the conference does a wonderful job of creating a really relaxed atmosphere for people to converse and the speakers are all really approachable and involved in all of the sessions as well.

I have to admit I also really appreciated the opportunities to connect to a number of fellow ThoughtWorks colleagues (both past and present) who I’d either not got a chance to meet, or hadn’t seen for a very long time. This is one of the consequences of working for a global consultancy – you get to communicate and build relationships for a distance yet rarely get to meet people face to face.

iPad observations
One huge point worth noting was the large role that the iPad played during this developer conference. Obviously, being fairly geeky I hadn’t expected so many of them yet it proved to be one of the best devices for capturing notes & particularly useful for reading and contributing tweets. Laptops lose out on both portability and, on average, a very so-so battery life.

Reading tweets to view session using the native iPad twitter client also worked really well without having to use the keyboard or mouse – this is where gestures and multi touch really shined.

My session
Chris Hedgate, organiser for the track on collaboration invited me to speak. Titled, “Tightening the Feedback Loop“, I spoke about how to give and receive more effective interpersonal feedback. I had some great tweets in response and some great feedback on the presentation (meta!) I’m encouraged that more people will be better equipped in their professional and personal life after attending.

Conclusion
I highly recommend presenting and/or attending Oredev. You’ll meet a whole heap of really interesting people and, no doubt, come away with at least an idea or two.