Loading

Our Business

Code & Iron is a Toronto based development shop that produces handcrafted software. It was founded in 2013 by Matt Holtom, a software designer with 5 years of professional experience in the airline, energy, education, and payment industries.

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.
- Bill Gates

Our Promise

We believe that trust, strong relationships, and clear communication are the foundation of good business. Your faith in us will never be sacrificed for a short-term gain. Full stop.

CodeAndIronRust256
Any fool can write code that a computer can understand. Good programmers write code that humans can understand.
- Martin Fowler
wheel

Our Passion

Code & Iron specializes in building web-facing systems with strong, reliable backends. Whether you need a fully built solution, or just a nudge in the right direction, your first step is contacting us for a free consultation.

We’ve been very fortunate to undertake projects that we’re deeply passionate about. Unfortunately, some of them are private in nature, so we’re unable to give you the full details.

  Spectrum AHS

Spectrum AHS helps Health Care Professionals at Alberta Health Services easily parse complex information previously only available in tables and charts. It contains detailed and location-relevant information about Pathogens, Antimicrobials, and Syndromes, as well as handy calculators and tools. We are excited for the rollout of our Mobile webapp in early 2014. Code & Iron also created a JSON REST API that will provide reliable information updates to the existing iPhone version. This application was developed with Watermelon App Works.

  TPFFA Emergency Incidents Map

A publicly accessible source at the City of Toronto is continuously mined to present data about emergency incidents in a more digestible way. The main driver is to give the citizens of Toronto accurate information about the types and volume of calls that the Toronto Fire Services responds to. See it live here.

First make it possible. Then make it beautiful. Then make it fast.
- Nathan Marz

 Public Repositories

Take a glance at our public projects on GitHub.

octocat

 Areas of Expertise

We’re always expanding our technical point of view, but our go-to stacks are built on these foundations.

January 27, 2014

Sell to the Laggards

The technology adoption lifecycle is demarcated into Innovators, Early Adopters, Early/Late Majorities, and the Laggards. When I spend time with my family I ask them: What software are you using? What devices have you bought? Which can’t you live without? …

  Show More

The technology adoption lifecycle is demarcated into Innovators, Early Adopters, Early/Late Majorities, and the Laggards. When I spend time with my family I ask them:

What software are you using?
What devices have you bought?
Which can’t you live without?

It is my clearest barometer of how far a trend or technology has spread.

Sister

My Sister is an Early Adopter. She was quick to recognize social media as a platform for change. She is adamantly eco and social fairness conscious. She is a native on Facebook and Twitter, and is tethered to her laptop. She bought a quad-band phone on purpose.

Sell her:
- The ability to share her identity and message with her peers and the world at large
- Technology that respects our planet and the people that live here
- Devices with a 5 year+ lifespan

Mom

My Mom fits well into the Early Majority. She doesn’t know exactly what she wants, but is sure it’s new. She fears being left behind by technological advance. She has annoyances, and if solutions are made convenient and simple she will pay dearly for them. She owns an iPhone, an iPad, and is dead-set on switching to a MacBook when she retires.

Sell her:
- A service to scan, sort, backup, and beautify her existing collection of physical photos
- Anything that keeps our geographically dispersed family connected
- An all-in-one monthly subscription to unlimited high quality Music, Movies, Books, Audiobooks, and TV. (I’m looking at you Apple and Google)

Grandma

My Grandma is well into the Late Majority. A Skype user, an iPad owner (for the Casino and Solitaire games), and a snowbird. She does not actively seek out new technology, it intrudes into her life. If it is a friendly, simple force she will embrace it, otherwise she’s just as happy to maintain the status quo. She was born in 1928, the same year as the Cathode Ray Television.

Sell her:
- Assistive devices and services to maintain her daily dignity and independence
- Entertainment that stimulates and engages her mind
- A simple way to stay updated on her Family and their daily lives

Dad

My Dad is a proud technological Laggard. In his career as a Systems Engineer he touched applications that affect hundreds of users, often in safety and liability-critical environments. In his personal life? He owns a Nokia pay as you go brick with $100/year on it. He hasn’t needed a new TV in 15 years and our old family computer has been ticking along for 10. If I sound frustrated it’s because I am. He is fiercely, vehemently against newness.

My dad is the ultimate litmus test for social acceptance of a technology. If you can make a product or service my Dad needs, and I mean really needs, you will be successful. Wildly, outrageously successful.

He recently asked me to install DropBox because he read about it in the Globe and Mail.

  Posted by Matt on January 27, 2014
January 14, 2014

Mimicking iOS 7 with jQM and Rails

iOS on the Web A client of mine needed a companion mobile web app that mimics their new iOS 7 app for their non-apple users. Their designer is also hugely passionate about user experience, and has built custom cells, icons, …

  Show More

iOS on the Web

A client of mine needed a companion mobile web app that mimics their new iOS 7 app for their non-apple users. Their designer is also hugely passionate about user experience, and has built custom cells, icons, and has high performance expectations for UI behaviour and response. I knew for him to be happy it needed to be as close as humanly possible to the real deal.

So here’s how to get that nice, smooth, Apple-y feel on the mobile web…

Modifying jQuery Mobile for Fun and Profit

Enter jQuery Mobile to take some of the load off. jQM is a responsive mobile web CSS and Javascript framework that just released stable version 1.4. It aims for a native app experience by offering persistent headers and footers, widgets for common UI paradigms, and AJAX enhancements. However, it maintains a look and feel distinct from all existing platforms. The reasoning behind this is to remain “seriously cross platform” (That list of browsers makes me tired just looking at it). To get around this (admittedly bland) skin, there is an online WYSIWYG editor called “ThemeRoller” that handles the basics. Beyond that, we’re on our own.

Order Matters

Rails 4 uses the asset pipeline, a way of compiling and combining assets to form the eventual CSS, Javascript, and images sent over the wire. It does this by using “manifest files” that send tendrils out to the other folders in your app. More specifically, the “require tree .” in your application.css will find everything under assets/stylesheets in app/ vendor/ and lib/. However, it does not guarantee the order in which they are loaded. This can lead to confusing and difficult to diagnose CSS bugs when dealing with a framework like jQM.

Here are the three CSS components that you need for a fully customized jQM app:

1. Download the minified, gzipped, themeless “structure” of jQM to vendor/assets/stylesheets, or use the jquery-mobile-rails gem.

2. Go to ThemeRoller to paint the broad strokes of your app, and download the original and minified versions to vendor/assets/stylesheets.

3. Finally, overrides of the jQM defaults and your custom CSS or SASS can go alongside your application.css file in app/assets/stylesheets.

Modify your application.css to load in this order:

*= require jquery.mobile.structure.min
*= require my-app-themeroller.min
*= require_self
*= require_tree .

You’re not !important, be more Specific

If you catch yourself rage-clearing your cache, shift/command refreshing, switching browers, or all of the above, you may try the sledgehammer of CSS. Appending !important to a css rule says “disregard any previous, more specific rules, use THIS one”. It has some uses (apparently), but by and large it will make later revisions to your code nightmarish. It’s like try… catch Exception e… swallow in Java. Respect the next developer, just don’t do it.

Instead, if your CSS just isn’t applying, you likely need a more specific CSS selector. CSS cascade and specificity rules are massively complex. Also, jQuery Mobile by convention is filled with very targeted selectors.

So don’t leave it up to chance. Use your Chrome Developer Tools or Safari Web Inspector. Find out the exact CSS selector used by jQM, and override that, it may be much  tighter than you expect. Here’s an example of me nullifying the standard listview borders:

.ui-listview > .ui-li-static, .ui-listview > .ui-li-divider, .ui-listview > li > a.ui-btn {
border: 0px;
}

If it looks like an Apple…

Now that we have our structure set up, what do we modify?

Here are some basic steps to getting that iOS 7 feel out of jQM:

1. Apple uses “Helvetica Neue Ultra Light” for headings and text to achieve that fresh, open air feel. We can mimic that easily on devices with this font pre-installed (Apple products, mainly). However, it’s important to degrade elegantly all the way to sans-serif just in case.

font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif
font-weight: lighter (or 100)

2. Eliminate unnecessary borders, backgrounds, and shadows. Whitespace and sharp contrasting colours are your friends here. Take a look at some of the stock iOS 7 apps for inspiration. Much of this work can be done in ThemeRoller

3. Custom icons on a flat background go a long way and are achieved in jQM via CSS classes with backgrounds

data-icon="carat-right" goes on your list item tag... and then:

.ui-icon-carat-right:after {
background-size: 70%;
background-image: image_url("carat-right.png");
}

So there! Go out into the world and modify jQuery Mobile to your hearts content! Down with the standard skin!

  Posted by Matt on January 14, 2014
August 27, 2013

Asynchronous Scheduling Options in a Rails Application

The stack behind torontofirecalls.com is not exciting, and that’s the way it should be. There are no outlandish requirements for throughput, response time, or searching. The app will never serve thousands of users at once. Sharding, clustering, caching, eventual consistency; …

  Show More

The stack behind torontofirecalls.com is not exciting, and that’s the way it should be.

There are no outlandish requirements for throughput, response time, or searching. The app will never serve thousands of users at once. Sharding, clustering, caching, eventual consistency; better left to start-uppy folks who are the next Twitter (or have deluded themselves as such).

Yes, it’s Rails.
Yes, it’s on Postgres.

Not much to talk about. So what to contribute?

Well, It’s been an absolute saga to schedule an asynchronous “every 5 minutes” job for this project. From that I ended up with a fairly good understanding of the options out there. Please learn from my pain. An alternate title to this article could be “Why Walled Gardens Eventually Suck”.

Req: Every 5 minutes the app shall update from the City of Toronto, parse the XML, and store the live events. If we miss an hour, that data is lost to us, possibly forever.

Scheduling Options on Heroku

1. Custom Rake Task and Heroku Scheduler
Pros – Free. Very easy setup. Create a custom rake task, and schedule/managed jobs in the web dashboard
Cons – Strictly limited to every 10 minutes, 1 Hour, 1 Day

heroku addons:add scheduler:standard

2. Clockwork and DelayedJob
Pros – Full, expressive DSL. Plays nice with Heroku Cedar. Excellent for applications deployed on multiple machines. Separates scheduling and performance of work (important). Works well when you have hundreds or thousands of jobs at once and need many workers.
Cons – $Expensive$ to run on Heroku, even for a few jobs. Requires one “clock” dyno for scheduling the work, and one “worker” dyno processing jobs. Adds $70 USD /mo to your app.

every(1.hour, 'feeds.refresh') { Feed.send_later(:refresh) }

3. Clockwork and DelayedJob with Workless
Pros – Workless Allows you to sleep a “worker” dyno until there’s something in the delayed_jobs table. Saves almost all the monthly costs of the worker dyno.
Cons – Unreliable. Uses heroku’s scaling API to sleep/awaken your worker(s). Often workers will die silently, or zombie with 0 jobs in the queue. Also, you still need a full-uptime clock dyno to schedule the delayed_jobs, so it still adds $35 USD/mo to your app.

In your production initializer:

config.after_initialize do
  Delayed::Job.scaler = :heroku_cedar
end

Then configure your scaler (to taste) with:

heroku config:add WORKLESS_MAX_WORKERS=1
heroku config:add WORKLESS_MIN_WORKERS=0
heroic config:add WORKLESS_WORKERS_RATIO=1

Scheduling Options off Heroku

* At this point, I got fed up with Heroku and it was time to move on. The Workless gem had failed to scale up/down multiple times. To stay reliable, I was running up an $70 USD/month bill just to process under 300 jobs a day. Not okay. I ported everything to WebFaction and within a few hours had a parallel instance running there.

4. Bare Cron
Pros – Expressive syntax. Full control. Literal decades of proven use. Available on most self hosted servers. Free as in beer.
Cons – Requirement of running the job is not stored alongside your code. Syntax can be intimidating for first time users. Heroku blocks it’s use. Is not ideal for multi-machine deployments/clusters.

Run crontab -e and:

17 8 * * * root echo "This command is run daily at 8:17 am"

5. Cron with Whenever
Pros – Simple, expressive DSL creates/updates jobs in your crontab with the “whenever” command. Requirement and changes to the jobs are stored inline with your code in SCM. Integration with Capistrano available for “update on deploy”. As available, sturdy, and free as cron (for Ruby apps).
Cons – … Heroku blocks its use. Is not ideal for multi-machine deployments/clusters.

In your schedule.rb file:

every :hour do
  runner "SomeModel.ladeeda"
end

Update your crontab using:

whenever -i

Solution #5 has been working very well for me, so the application will finish being ported to WebFaction, likely by the end of the week. It’s now costing ~$10 USD to host instead of ~$80 USD. Hopefully the above comparisons will help you make the right decision early by learning from my 4 mis-steps.

Next writeup will be a quick explanation of how I used the Google Maps for Rails gem and MapIcons by Nicolas Mollet to create the UI.

’till next time…

  Posted by Matt on August 27, 2013
July 24, 2013

Official Launch of torontofirecalls.com

We are extremely pleased to announce the launch of torontofirecalls.com in partnership with the Toronto Professional Firefighters Association!  In addition to being an internal tool for Toronto Firefighters, the application will give the Citizens of Toronto an accurate view of the types and volumes …

  Show More

We are extremely pleased to announce the launch of torontofirecalls.com in partnership with the Toronto Professional Firefighters Association!  In addition to being an internal tool for Toronto Firefighters, the application will give the Citizens of Toronto an accurate view of the types and volumes of calls that their Fire Service responds to.

This mobile-responsive web app was built to put an interesting, interactive GUI on the emergency incident data available from this City of Toronto website. The data source includes the category, location, dispatch time, alarm level, and responding apparatus for all current emergency incidents that Toronto Fire Services personnel are currently working at.

This data is scraped from the website at regular intervals and stored in our own database. A lookup is performed on the Google Geo-caching API v3 to find the latitude and longitude of the nearest intersection. Once this data is accumulated, two main views are presented to the end-user.

  1. Live Mode – a visual representation of the emergency incidents currently being worked at by TFS personnel. Updates automatically every 5 minutes with an asynchronous request for fresh JSON.
  2. History Mode – a historical search mode that allows the user to search by specifying the desired “Event types, Date Range, and Minimum Alarm Level”. Displays up to 1000 historical entries at a time.

We couldn’t be happier with the results, and we’d like to once again thank the Toronto Professional Firefighters Association for fully supporting this project and making it a reality.

A technical write up  of the design and coding will be coming soon, so stay tuned!

  Posted by Matt on July 24, 2013
May 18, 2012

Way Back When… My First Experience with Programming

I saw a post at HackerNews the other day from Justin Kan about his first experience with programming. Short story: he was asked to do something over and over. The pain that he felt when asked to do this caused …

  Show More

I saw a post at HackerNews the other day from Justin Kan about his first experience with programming. Short story: he was asked to do something over and over. The pain that he felt when asked to do this caused him to learn and apply a VB macro in the background of an excel sheet. My own experience was quite similar, and dredging it up was a fun trip down memory lane.

I worked a few summers at a manufacturing company that made manifolds and nozzles for plastic injection molding machines. I had some great experiences there (designing wooden trays to hold nozzles), and some weird ones (spray painting some 1300 of said trays). I think I was 15 at the time.

On a normal Friday afternoon during my first summer there, my immediate boss asked me to come in and sit down with with the “Consultants”. These were the type of “Efficiency Experts” that made $200 an hour, and only told you things about your company you should already know. These lean-manufacturing gurus were trying to figure out how to create a Just In Time machine cell using the existing metal mills. They knew that these machines could only accept manifolds under 90cm in width. Anything larger than that (or thicker than some number I can’t remember) would have to be routed to larger machines outside the normal flow.

“Sit down, Matt. Here is the first 120 pages of some 23,000 unique manifold descriptors dumped out of SAP. We need you to make a list of those manifolds that CAN go into the machine cell, and those that can’t. This can’t be a simple sort, because sometimes the dimensions can look like blah235blah, and sometimes they can look like 983yadda84. It’ll probably take you 6 hours Saturday and Sunday, for the next 2 weeks.”

Shit. I’m in trouble and in danger of losing my weekend. Time to figure out what makes Excel tick. 3 hours, and a lot of if else if else if else if else copy paste later, I had the 23,000 manifolds sorted and grouped by size. I ended up with a thrown together, hideous, disgusting abomination of code that took 10 minutes to run once. But. It worked, and never again needed to see the light of day. I still have the excel file but I won’t post it for fear it will be used against me later :D

“Here you go. See you next week!”

  Posted by Matt on May 18, 2012
April 2, 2012

Making the Leap: Log4J to SLF4J

So. The team lead has come to you and said “time to switch project X over to SLF4J“. Or you’re the team lead and you just realized all your log statements only work with Log4J? What if that project dies …

  Show More

So. The team lead has come to you and said “time to switch project X over to SLF4J“. Or you’re the team lead and you just realized all your log statements only work with Log4J? What if that project dies out?

Freaking out? Worried you will have to manually edit lines upon lines of code? Time to hire a coop? Fear not brave coder. We will bring the full power of bulk editing and unix “diff” to bear on this one. (And a really experienced colleague of mine who helped me through this!)

For those who are unfamiliar, SLF4J is the Simple Logging Facade for Java. It is a layer on top of Log4J, Logback, and others that allows you to decouple your log statements from your underlying implementation. SLF4J is to Log4J as JPA is to Hibernate.

Also the interface it provides is absolutely delicious. No more checking isDebugEnabled() before a log statement to avoid performance hits, SLF4J does so automatically. Also, no more complex string concatenation inside logger.info(). In SLF4J the info, debug, error, trace, and fatal methods take objects and plug them into message placeholders “{}” for you, calling the toString() methods as appropriate.

So let’s switch your project over. First, check out a fresh working copy of the project you need to modify, let’s call it project-logging-dirty. Next, check out another working copy of the same project, in directory project-logging-clean.

Download the SLF4J Migrator Tool here:
It’s perfectly suited to changing from Log4J to SLF4J, but it has one problem: It touches every single line of every single.java file in your project, and screws up the whitespace more often that not. I personally hate losing svn/git history due to whitespace mods. I want to know who to svn blame (lol, bad joke) when I’m looking at this project in 6 months.

Run the SLF4J migrator against project-logging-dirty.


java -jar slf4j-migrator-1.6.4.jar

If you do an svn diff you will see a HUGE number of lines changed (which are mostly whitespace modifications). Let’s pull those changes by making a unified diff of the two directories, ignoring .svn and whitespace mods, and forward the output to a new file called slf4j.patch.


diff -udrEbBw -x.svn project-logging-dirty project-logging-clean > slf4j.patch

Change to project-logging-clean so that it’s your present working directory, and apply the patch!


patch -p1 -ZEBw --ignore-whitespace < ../slf4j.patch

Run svn diff again in project-logging-clean. You should see a clean changeover to SLF4J including LoggerFactory.getLogger statements and all the rest. Commit project-logging-clean once you’ve run all integration tests against the build. Delete project-logging-dirty, to never be seen again.

Caveat: When doing thread-specific concurrent programming, you may be using NDC (Nested Diagnostic Context), a stack of context specific log message parameters. NDC is unsafe as the log parameter stack could theoretically grow without bounds (memory leak anyone?). SLF4J does not support NDC, and switches to MDC (Map based, which is much more forgiving if you are writing to the log parameters forget to remove). Caution should be exercised when doing any thread specific logging: each map.put should have a corresponding map.remove, in a finally block. BUT take note: The SLF4J Migrator Tool cannot change over your NDC statements to MDC, you will need to do this manually.

Best of luck, I hope you have as much fun with SLF4J as I do!

  Posted by Matt on April 2, 2012  /  Tags: , , , , ,
February 1, 2012

Over and Over: Parameterized Testing in JUnit

So you love creating meaningful test cases, right? You get jazzed about your software working, and even better; you can prove it. But here’s the issue: many of the test cases in that 100 page “test plan” are data-driven. You …

  Show More

So you love creating meaningful test cases, right? You get jazzed about your software working, and even better; you can prove it. But here’s the issue: many of the test cases in that 100 page “test plan” are data-driven. You find yourself creating the same test method over and over again with the only difference being the in’s and out’s. You don’t repeat yourself in the src/main directory, so why should it be okay in the src/test directory?

Don’t get W.E.T., D.R.Y. it up! No, there’s no need to create a .properties file of your data set to be read into the tests. Don’t you dare create a custom XML schema, XML files and parser. Stop right there! I see you over there creating your own XML-based testing suite. You aren’t the first person to try this… it’s been done, and done well!

The custom Parameterized runner in JUnit 4 is ideal for when you want to execute the same test method many times with varying inputs and varying expected outputs. Below I’ve set up a basic test class that confirms the operation of a web page that will sum any two values. It uses the Selenium Webdriver page objects pattern, but that’s a discussion for another day.

@RunWith(Parameterized.class)
public class ValidInputValueTests {
	
	private String inputValue1;
	private String inputValue2;	
	
	public ValidInputValueTests(String inputValue1, String inputValue2, String outputValue){		
		this.inputValue1 = inputValue1;
		this.inputValue2 = inputValue2;
                this.outputValue = outputValue;
	}	
	
	@Parameters
	public static Collection<Object[]> generateData() {
		return Arrays.asList(new Object[][] {				 
				 {"10.00", "", "10.00"},
				 {"10.00", "10.00", "20.00"},
				 {"", "10.00", "10.00"}
				 });
	}
	
	@Test
	public void TC2_4_2PerformThisTestForParameters(){		
		InputPage inputPage = certainNextPage.enterValuesAndClickNext(inputValue1, inputValue2);
		FinalPage finalPage = inputPage.enterStandardInfoAndSubmit();
		
		Assert.assertEquals("Actual value does not match expected value on finalPage", outputValue, finalPage.getResult());
	}
}

Instead I’ll discuss each part in detail as pertains to JUnit Parameterized tests. First off, import and add the annotation to RunWith the Parameterized custom runner from the JUnit 4 API. This is how JUnit knows to scan the test class for the @Parameters within it.

@RunWith(Parameterized.class)
public class ValidInputValueTests {

Next, the class must have a publicly visible constructor with the same number of arguments as parameters.

	public ValidInputValueTests(String inputValue1, String inputValue2, String outputValue){		
		this.inputValue1 = inputValue1;
		this.inputValue2 = inputValue2;
                this.outputValue = outputValue;
	}

Then tell JUnit where your parameters are residing by annotating a static method called generateData that returns a collection of object arrays (don’t ask, this is a weird quirk of the Parameterized class IMO). These will be injected into the test class constructor by Parameterized. To date I’ve only used Java standard types and primitives (Strings, boolean, etc.) as parameters and haven’t experimented with passing custom objects.

	@Parameters
	public static Collection<Object[]> generateData() {
		return Arrays.asList(new Object[][] {				 
				 {"10.00", ""},
				 {"10.00", "10.00"},
				 {"", "10.00"}
				 });
	}

Now let’s set up our test method. Note that you could put as many methods in this test class as you want. They will all be executed in turn with the set of parameters above, making the Parameterized runner VERY powerful, talking N X M powerful. It effectively generates a test method instance for every result in the cross product of parameter sets and test methods.

	@Test
	public void TC2_4_2PerformThisTestForParameters(){	
		...
		InputPage inputPage = certainNextPage.enterValuesAndClickNext(inputValue1, inputValue2);
		FinalPage finalPage = inputPage.enterStandardInfoAndSubmit();
		
		Assert.assertEquals("Actual value does not match expected value on finalPage", outputValue, finalPage.getResult());
	}

Note that in the above test method, we have access to our inputValue 1 and 2, and our output value, trusting in Parameterized.class to populate these variables with our test data.

So why not create some data driven tests for your system today! Super simple, super quick, super powerful, god I love JUnit.

Take care,
Matt

  Posted by Matt on February 1, 2012
January 25, 2012

The Maven Dependency Plugin, It’s Tree Time.

I recently inherited an external testing project that is about 6 months stale. It was written by a co-op who left a while ago. For those of your playing the home game, neither of these are good signs. It’s a …

  Show More

I recently inherited an external testing project that is about 6 months stale. It was written by a co-op who left a while ago. For those of your playing the home game, neither of these are good signs. It’s a suite of tests packaged in an executable jar that use selenium to automate a firefox (or any) browser. Its purpose is to automatically verify there have been no regressions in the target project since the last major feature set. Nifty right?

Only one issue. The project was started in, and run exclusively out of, eclipse. Specifically, all of the dependency information was created by modifying the eclipse build path settings. This means that a ton of relevant project information is stored in the .classpath file on a specific computer. To make matters worse, the .classpath, .settings, and .project files are commonly ignored globally by users of svn or git, to avoid muddying up the repository. If that one computer has a hard drive crash, or the co-op quits, dies, or goes on a road trip, we’re scuppered. The project now requires a goat sacrifice as part of the build process, it’s arcane magicka twisting just outside our mortal comprehension.

For the record: I have nothing against eclipse. I think it is a great IDE, and I use it every day. However, it is not, and never will be an enterprise level build/dependency management tool.

Enter the POM (Project Object Model). The pom.xml file is your first step to using Maven as a build and dependency management tool.

Create a basic pom.xml file at the root of your project, and make sure your directory conforms to the “convention over configuration” maven directory structure.

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
</project>

From there, you can take advantage of the fact that every pom.xml automatically inherits all of the behaviour of the standard “super pom”, and bango, without even realizing it you’re using a fully featured build tool. To add a dependency (i.e. the junit 4 api) reference its groupId, artifactId, and version as follows:

<dependencies>
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.8.2</version>
  </dependency>
</dependencies>

Go ahead and build your project with the command:

mvn install

Notice that the dependency is downloaded, along with any other dependencies that IT in turn depends on, magic! No more DLL Hell for us (well, JAR hell, but you get the picture)! For the interested, this is called transitive dependency management: a->b->c therefore a->c.

Let’s take this one step further. To see a nicely formatted tree of your newly downloaded dependencies, add the maven dependency plugin to your pom.xml as follows:

    <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.4</version>
        </plugin>
    </plugins>
    <sourceDirectory>src/</sourceDirectory>
    </build>

Now try the command:

mvn dependency:tree

You should be looking at a somewhat simpler version of this:

[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building Test MPG 1.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.4:tree (default-cli) @ test-mpg ---
[INFO] com.acme.myproj:test-proj:jar:1.0.0-SNAPSHOT
[INFO] +- junit:junit:jar:4.8.2:compile
[INFO] +- org.slf4j:slf4j-log4j12:jar:1.6.3:compile
[INFO] |  +- org.slf4j:slf4j-api:jar:1.6.3:compile
[INFO] |  - log4j:log4j:jar:1.2.16:compile
[INFO] +- org.seleniumhq.selenium:selenium-firefox-driver:jar:2.12.0:compile
[INFO] |  +- org.seleniumhq.selenium:selenium-remote-driver:jar:2.12.0:compile
[INFO] |  |  +- cglib:cglib-nodep:jar:2.1_3:compile
[INFO] |  |  - org.json:json:jar:20080701:compile
[INFO] |  - commons-io:commons-io:jar:2.0.1:compile
[INFO] +- org.seleniumhq.selenium:selenium-htmlunit-driver:jar:2.12.0:compile
[INFO] |  +- org.seleniumhq.selenium:selenium-api:jar:2.12.0:compile
[INFO] |  |  - com.google.guava:guava:jar:10.0.1:compile
[INFO] |  |     - com.google.code.findbugs:jsr305:jar:1.3.9:compile
[INFO] |  +- net.sourceforge.htmlunit:htmlunit:jar:2.9:compile
[INFO] |  |  +- xalan:xalan:jar:2.7.1:compile
[INFO] |  |  |  - xalan:serializer:jar:2.7.1:compile
[INFO] |  |  +- commons-collections:commons-collections:jar:3.2.1:compile
[INFO] |  |  +- commons-lang:commons-lang:jar:2.6:compile
[INFO] |  |  +- org.apache.httpcomponents:httpmime:jar:4.1.2:compile
[INFO] |  |  +- commons-codec:commons-codec:jar:1.4:compile
[INFO] |  |  +- net.sourceforge.htmlunit:htmlunit-core-js:jar:2.9:compile
[INFO] |  |  +- xerces:xercesImpl:jar:2.9.1:compile
[INFO] |  |  |  - xml-apis:xml-apis:jar:1.3.04:compile
[INFO] |  |  +- net.sourceforge.nekohtml:nekohtml:jar:1.9.15:compile
[INFO] |  |  +- net.sourceforge.cssparser:cssparser:jar:0.9.5:compile
[INFO] |  |  |  - org.w3c.css:sac:jar:1.3:compile
[INFO] |  |  - commons-logging:commons-logging:jar:1.1.1:compile
[INFO] |  - org.apache.httpcomponents:httpclient:jar:4.1.2:compile
[INFO] |     - org.apache.httpcomponents:httpcore:jar:4.1.2:compile
[INFO] - org.seleniumhq.selenium:selenium-java:jar:2.12.0:compile
[INFO]    +- org.seleniumhq.selenium:selenium-android-driver:jar:2.12.0:compile
[INFO]    +- org.seleniumhq.selenium:selenium-chrome-driver:jar:2.12.0:compile
[INFO]    +- org.seleniumhq.selenium:selenium-ie-driver:jar:2.12.0:compile
[INFO]    |  - net.java.dev.jna:jna:jar:3.3.0:compile
[INFO]    +- org.seleniumhq.selenium:selenium-iphone-driver:jar:2.12.0:compile
[INFO]    - org.seleniumhq.selenium:selenium-support:jar:2.12.0:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.051s
[INFO] Finished at: Wed Jan 25 00:18:37 EST 2012
[INFO] Final Memory: 6M/81M
[INFO] ------------------------------------------------------------------------

Pretty cool right? Check that pom.xml into the repository, and bask in the fact that anyone in your organization can check your project out and build it straight out of the gate. Now say three Hail Mary’s and ten Bless Me Father’s, and swear off eclipse dependency management for good. No seriously, please don’t do it, or it might be you we sacrifice next time instead of the goat :D

Take care,
Matt

  Posted by Matt on January 25, 2012  /  Tags: , ,
January 23, 2012

Source to the World!

Okay, time to really put wordpress through its paces. Let’s try a tad of java with *gasp* syntax highlighting! Here goes! That’s all folks, Take care, Matt

  Show More

Okay, time to really put wordpress through its paces. Let’s try a tad of java with *gasp* syntax highlighting!

Here goes!

//HelloWorld.java
public class HelloWorld{
  public static void main(String args[]){
    System.out.println("Hello World");
  }
}

That’s all folks, Take care,

Matt

  Posted by Matt on January 23, 2012  /  Tags:
January 23, 2012

Welcome

Hello World! (couldn’t resist) Welcome to the center of my personal software space. This will be a one stop shop for all things code, so if you came here expecting anything else; flee screaming. I’m planning on using this site as …

  Show More

Hello World! (couldn’t resist)

Welcome to the center of my personal software space. This will be a one stop shop for all things code, so if you came here expecting anything else; flee screaming.

I’m planning on using this site as a repository for my thoughts on crafting and testing solid software. Hopefully someone out there in the great “Blue Nowhere” will find them useful. It will also be a place to store useful scripts, commands, and tools I’m likely to forget about. For those of you who don’t know me personally, I have the memory of a goldfish.

That’s all for now, planning on changing the WordPress theme in a minute, so expect this site to be in-flux for the next few days as I play around. I know I should probably be writing my own CSS from scratch, but when I see a screw I choose a screwdriver over my fingernails every time.

Take care,

Matt

  Posted by Matt on January 23, 2012

We’d love to talk shop with you.
Drop us a line.

Code & Iron

23 Oriole Road – Unit 111
Toronto, ON
M4V 2E6

hello@codeandiron.com
Follow us on Twitter
Fork us on GitHub





Your Name (required)

Your Email (required)

Subject

Your Message