ThoughWorks Studios has released an ebook titled “How do you estimate on an Agile project?” where they explore common approaches and their adaptions from real-world projects. The book is comprised of several authors, most notably Martin Fowler. In this ebook they discuss why teams estimate, different methods that teams use to estimate, and provide a couple of case studies.
» Read more: ThoughtWorks releases ebook on Agile Project Estimation
ThoughtWorks releases ebook on Agile Project Estimation
June 14th, 2013 by Cecil Williams No comments »No Estimates?
June 14th, 2013 by Cecil Williams No comments »Over the last year or so software development estimates have become a popular topic. The popularity stems from the inherent fact that estimating software development is difficult. Some people are writing about ways to improve your estimates while others are writing about how to manage software development without estimates.
Code Quality Metrics with Sonar, Part III: Sonar in a Ant-based Java Project
June 1st, 2013 by Akrem Saed No comments »Now we will cover the fun stuff for which we’ve been waiting. In this post, I’ll go over how to setup Sonar for a Java project that utilizes Ant for its build. I’ll go through the basic steps for installing and running a Sonar instance, and how to use a MySQL database for collecting metrics. Then I’ll go into some details around analyzing a Java project using Ant and Sonar. This involves writing Ant script, pointing to the source codes, analyzing the binaries, analyzing JUnit test cases, analyzing Ecl Emma coverage, etc.
» Read more: Code Quality Metrics with Sonar, Part III: Sonar in a Ant-based Java Project
Agile Manifesto – Working Software Over Comprehensive Documentation
May 17th, 2013 by Cecil Williams No comments »Do you sometimes feel like your team spends more time documenting your system than building it? One of the biggest hindrances to progress in a software project is documentation. The Agile Manifesto prescribes that teams should value working software over comprehensive documentation. It doesn’t mean that you should not create documentation; it means you should create documentation that provides value and at the same time does not hinder the team’s progress.
» Read more: Agile Manifesto – Working Software Over Comprehensive Documentation
Code Quality Metrics with Sonar, Part II: Overview of Sonar features
May 14th, 2013 by Akrem Saed No comments »What we covered so far ?
In my previous post I covered the reasons why software quality metrics should be collected and why improvements to the code should be made based on those metrics. In this post I’ll be illustrating how Sonar can fulfill the job of collecting metrics and driving decisions.
Sonar goes beyond just collecting and displaying metrics:
- Sonar can answer the following questions:
- What are our most critical code quality issues?
- Where is the highest concentration of code issues?
- How many working hours will it take to fix the issues?
- What does the metrics trend look like over the past year?
- etc.
- Sonar can be used to track work tickets assigned to team members.
In short, Sonar helps us analyze the situation, take actions, and quantify the improvement.
» Read more: Code Quality Metrics with Sonar, Part II: Overview of Sonar features
Using Git with Subversion
May 1st, 2013 by Cecil Williams No comments »If you haven’t heard of Git or don’t understand why you should use it, checkout the talk given by the author to Google (Torvalds, 2007). Git is an excellent version control tool for agile software development. But many of us may not have the luxury of using Git because our company has deemed that we shall use Subversion. Now Subversion is not a bad tool and has added some nice features in version 1.7. But my preference is to use Git. » Read more: Using Git with Subversion
Agile Manifesto – Value individuals and interactions over processes and tools
April 10th, 2013 by Cecil Williams No comments »David Morgan and Cecil Williams, March 25, 2013
One of the biggest hindrances to progress in software projects is bureaucracy. Rigorous processes that must be followed unswervingly, deliverables changing hands between independent groups and required approvals – hand-offs, sign-offs, and stand-offs – all get in the way of software projects making valuable progress. So how would you change that? » Read more: Agile Manifesto – Value individuals and interactions over processes and tools
Java method breakpoints are evil
April 1st, 2013 by Cecil Williams 1 comment »I want to share an experience that my colleague, Travis Klotz, and I ran into recently.
I was trying to manually test a Java web application running in debug mode. It was running really slow, taking several minutes to launch after the compile was finished. And when it did eventually start, using the application was very slow. Pages would take almost a minute to render. So Travis and I started trying to determine the cause. » Read more: Java method breakpoints are evil
Manifesto for Agile Software Development
March 4th, 2013 by Cecil Williams No comments »David Morgan and Cecil Williams, February 25, 2013
How many times have you been presented with a phone book-sized printout of ambiguous yet carefully crafted requirements? How many times have you, swamped with remaining work and short of time, camped in your cubical to meet a looming deadline? Or seen your customers paralyzed by an approval process out of fear that they will not think of everything up front? Or witnessed an organization trying to contain costs “next time” by more strictly observing the same process as last thinking it wasn’t the process that led them astray but their lack of discipline?
If you’re answering yes to some or all of these questions, you’ve felt the pain that can happen during Waterfall (or defined process control) managed projects. » Read more: Manifesto for Agile Software Development
Getting Started With Camel: Marshalling
February 1st, 2013 by Ben Kiefer No comments »In my last post on Camel, I spent some time introducing you two of its biggest players, the Context and the Route, by means of a simple problem – processing data coming in via file. If all we had to do was move the file, we could call our job done and move on, but what if we need to do something with that information?
Here’s a quick recap of our problem from last time.
User puts file in directory.System reads file from directory.- System breaks each line into a separate record.
- System processes each record.
System archives the file.
I’ve marked off steps 1, 2, and 5 since we already took care of them with our simple implementation of the File Transfer pattern. Steps 3 and 4 offer us an opportunity to explore the Message Transformation Enterprise Integration Pattern (EIP), which covers interactions between systems that don’t share a common API (e.g, our file and a Java-based API that takes a plain-old-java-object (POJO)).
The Exchange
EIPs run on messages. They are read, sent, manipulated, and stored based on the individual needs of the system, and Camel’s API follows suit nicely. Remember our FileMover, the simple route we defined to grab a file out of a directory and park it somewhere else?
@Component public class FileMover extends SpringRouteBuilder { @Value("${camel.ride.app.output.directory}") private String outputDirectory; @Value("${camel.ride.app.input.directory}") private String inputDirectory; @Override public void configure() throws Exception { from("file:" + inputDirectory).to("file:" + outputDirectory); } }
We already covered that this little route is building a connection between two of Camel’s EndPoint classes, but what happens in the middle? To start, Camel builds an Exchange, which will facilitate the transfer of a Message from one endpoint to the other. The exchange contains all the interesting bits and pieces of your message. You can get at this content several ways, but the simplest by far is with a Processor.
The Processor Interface
Attaching a Processor to an Endpoint is an easy way to hook into a route and see what is going on because a Processor has one method, process, which takes an Exchange.
@Component public class SimpleProcessor implements Processor { @Override public void process(Exchange exchange) throws Exception { System.out.println("There is an exchange going on."); System.out.println(exchange.getIn().getHeader("CamelFileName")); System.out.println(exchange.getIn().getBody()); System.out.println(exchange.getIn().getBody().getClass()); } }
All that’s left now is to inject this processor into our File Mover route.
@Component public class FileMover extends SpringRouteBuilder { @Value("${camel.ride.app.output.directory}") private String outputDirectory; @Value("${camel.ride.app.input.directory}") S private String inputDirectory; @Autowired private SimpleProcessor simpleProcessor; @Override public void configure() throws Exception { from("file:" + inputDirectory).process(simpleProcessor).to("file:" + outputDirectory); } }
The above class gives one example of how we can solve our remaining steps, by grabbing the Body of the In message and breaking it into different objects, but there are better options, namely letting Camel marshal (or transform) that object from it’s incoming format into something we can use.
Marshalling to Spring Managed Beans
Camel’s marshalling functionality allows us to transform the data coming from our file in a variety of ways. For this example,
we’ll look specifically at comma-separate-value (CSV) file processing, but there are others available, most notably the ability to marshal to and from XML.
In a simple world, we might be handed a CSV file containing the following data:
John,Smith Sue,Anderson
As you might guess, the values in this file represent the first and last name of a person. If we were to use a processor, like our example above, we would need stream the contents of the file and build Strings for each of the fields in our CSV, and then set them on the appropriate POJO. Instead, we’ll let Camel do the work for us, so all we have to worry about is getting a list of Strings for each row.
CSV processing is a separate module in Camel. To use it, add the following to your Maven POM file.
<dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-csv</artifactId> <version>${camel.version}</version> </dependency>
Before we hook CSV processing into our route, we’ll need a bean to do something with the results. The Person class used here is just a POJO with a first and last name field.
public class CsvToPersonProcessor { public void process(List<List> csvRows) { for (List csvRow : csvRows) { Person person = new Person(); person.setFirstName(csvRow.get(0)); person.setLastName(csvRow.get(1)); doSomethingTo(person); } } }
One thing that’s a little odd here is the process method, which takes a list of a list of Strings. Why that particular method signature? The answer lies within Camel’s CSV library. Each row in our csv file is going to be broken into a list of Strings, and that list is going to be added into another list, so what you have at the end of the marshalling process is a list of all the rows from our CSV file. Yes, this means that your whole file will be in memory at once, which is bad, but hold on a second while we look at our new route definition, because we’ll get to that problem in a minute.
@Component public class FileMover extends SpringRouteBuilder { @Value("${camel.ride.app.output.directory}") private String outputDirectory; @Value("${camel.ride.app.input.directory}") private String inputDirectory; @Override public void configure() throws Exception { from("file:" + inputDirectory).to("file:" + outputDirectory) .unmarshal().csv().beanRef("csvToPersonProcessor", "process"); } }
Like before, we are picking up a file from one directory and moving it to another, but now, at the end, we are unmarshalling the CSV and sending the results to the process method of the bean we defined above. And like I said before, it’s going to do the entire file by default. So now, we need to stop doing that, before we run out of memory.
@Component public class FileMover extends SpringRouteBuilder { @Value("${camel.ride.app.output.directory}") private String outputDirectory; @Value("${camel.ride.app.input.directory}") private String inputDirectory; @Override public void configure() throws Exception { from("file:" + inputDirectory) .to("file:" + outputDirectory) .split(body().tokenize("\n")).streaming() .unmarshal().csv() .beanRef("csvToPersonProcessor", "process"); } }
In the class above, we are splitting the body of the message on each new line, and then streaming the result to the CSV unmarshalling process we had before. The big change here is that now our CsvToPersonProcessor is going to be invoked one time for each row in the CSV, which means our looming memory issue is gone.
Before I wrap everything up, you probably want to know what to do about the pesky column headers that come along with many CSV files. These are dealt with through an instance of the DataFormat interface injected into the marshalling/unmarshalling portion of your route. You are welcome to roll your own DataFormat, but the camel-csv module also includes a CsvDataFormat class which, as it turns out, you were using the whole time with your call to the csv() method. All you need to do is break it out as a variable, flip the “skipFirstLine” property, and inject the DataFormat into your unmarshal call.
@Component public class FileMover extends SpringRouteBuilder { @Value("${camel.ride.app.output.directory}") private String outputDirectory; @Value("${camel.ride.app.input.directory}") private String inputDirectory; @Override public void configure() throws Exception { CsvDataFormat format = new CsvDataFormat(); csv.setSkipFirstLine(true); from("file:" + inputDirectory) .to("file:" + outputDirectory) .split(body().tokenize("\n")).streaming() .unmarshal(csv) .beanRef("csvToPersonProcessor", "process"); } }
It’s probably worth noting here that because we were using Camel’s Java DSL for all of the above examples, we didn’t need to make any additional changes to the XML snippet we defined last time.
What’s Next?
Our problem is solved, but what happens when things don’t go according to plan? In my next post, I’ll cover some of the error handling techniques available in Camel. The full source for the code above, including test coverage, is out on the marshalling branch of the camel ride repository on GitHub. Go crazy.