JSON Feed – The New Way to Syndicate Posts

There’s a new way to provide syndication feeds for websites. JSONFeed does basically the same thing as the traditional RSS or Atom feed, but instead of using XML it uses JSON. The big advantage of this is that the file size of the feed is much smaller and processing of the feeds can be much more efficient. 

You can enable it now on WordPress using the JSONFeed Plugin for WordPress. You can find it by searching for JSONFeed via the Plugins->Add New option in the WordPress Administration Dashboard. 

Enabling the plugin will make your feed accessible via JSONFeed. You can see an example by viewing the davidfindlay.com.au JSONFeed. I’m not aware of any feed readers yet that use this, but you can be sure they’ll come soon. It’s a bit of a chicken and egg problem. I’m always keen on being an early adopter on things like this. 

My Site Moves to Amazon Web Services

I’ve finally moved my site onto Amazon Web Services. It’s now running on a t2.micro EC2 instance in Amazon’s Asia Pacific Sydney region. It’s using Amazon’s linux AMI, with Apache httpd. MySQL is served via an Amazon RDS MySQL instance. The domain is delegated to Route 53 for DNS. 

So far it seems to be faster than my traditional shared hosting and that’s without even looking at any particular optimisations yet. I’m going to try to get some metrics soon to prove it. I also plan to transition all my other sites across to this type of hosting. 

The only thing still running on the old hosting is email. Amazon still has a particular gap here. I could run my own email server, but I’d prefer not to. I’m going to look into some options though. 

Fitness and Swimming Goals

I’ve been pretty lazy and busy lately, so my fitness has dropped off. I got to 85kg, the heaviest I’ve ever been. So I’ve set a goal to get back to peak fitness again. 

Since I’ve been so busy with our baby, I’ve not been swimming as much. I used to swim at least twice a week and was state masters champion in some events. I’ve fallen a lot since then. In the last 12 months I have barely swum. For the last few months I’ve been swimming once a week when I can. Time to get back into it!

So as of today I’m 80kg, thanks to cutting back on sugar, particularly Coke, and walking a lot. I usually walk 8000 steps a day or 4-6km a day, according to my iPhone 6. 

Swimming Target

It’ll take a long time to get my distance swimming endurance back. However if I work hard on my strength and anaerobic fitness, I should be able to get back into sprinting quickly. I’ll need to improve my technique as well, as it’s not as good as it used to be. 

Here’s my goal:

To swim 50m in under 30 seconds by the end of 2017

I’ve never done it before. My personal best is 30.51 in the 50m Long Course at Somerville House on 17/03/2013 at the Masters Swimming Queensland State Championships. 

Bodyweight Fitness

I discussed Bodyweight Fitness in Reddit’s /r/bodyweightfitness. I quite like its philosophy. I’m planning to use it to improve my muscle strength. I’ve already started, using an iOS app by one of the people involved in the subreddit. You can find it here: The ultimate mobile app for Bodyweight Fitness.

Training partner

I did my first set using the app today, but didn’t make it all the way through. The exercises feel good though, and even my toddler daughter seemed to want to get in on it. Might have a training partner soon!

How I Made $1000 From Google AdSense on My Authority Site

AdSense mobile app
AdSense mobile app – $1000 lifetime earnings

On Thursday 5th of January 2017, I hit the $1000 mark on Lifetime earnings on Google AdSense. All but about $30 of that was earned in the immediately preceding 12 months. This is a tale of how you can have some minor success with time and effort. 

You can see a presentation on this in the presentation section at the bottom of the page.

I started my site, Digital TV Help, in February 2014 on the topic of Do It Yourself TV Antenna work and TV setup. It was something I had previously done as a self employed technician. 

Then I had basically zero traffic and zero income from the site. In the month of December 2016, according to Google Analytics, I had 9775 sessions with 8775 users. Last month I had estimated earnings of $102.42 Australian and just under a week later I reached $1000.11 lifetime estimated earnings.

How I got there

I started the site after discovering Pat Flynn’s Smart Passive Income podcast in December 2013. The site was created in January 2014.

Initially my site was very unfocused and I had the idea of educating both the DIYer and people entering the industry. I didn’t have a very good design, just a typical blog design, and I only had a few articles of poor quality. Didn’t have that many pictures either only the ones I’d taken while running my business.

In August 2014 I went to Pat Flynn and Chris Ducker’s 1 Day Business Breakthrough seminar at Problogger on the Gold Coast. The feedback I received there helped me to change to a narrower focus just on the do-it-yourselfer audience. Unfortunately it took me a long time to implement things suggested.

By December 2014 I had written 65 posts, ranging from articles about how things worked, to tip of the day articles and only a few how-to articles. I’ve always taken a publish first, improve later approach. In December 2014 I had 494 sessions and 437 users, with $2.19 of estimated earnings. In the whole year of 2014 I had estimate earnings of $11.18.

A bit demotivated and busy with full-time work, study, the birth of our first child and other commitments, I didn’t do much over the following year. After March 2015 I didn’t do anything to my site until March 2016. 

Monthly Sessions on Google Analytics
Monthly Sessions on Google Analytics

In January 2016 I discovered my site had received a huge increase of users and was earning me a lot more money suddenly. In that month I had estimated earnings of $7.56 from 4506 sessions and 4008 users. From January 2014 to December 2015 my estimated earnings were $33.70. 

Between January and March 2016 I did some changes to my AdSense advertising based on research on various SEO sites. After checking my stats and doing some experimentation I determined that none of my AdSense income came from header or sidebar ads. All of it came from the ads in my articles. I eventually discovered best income came from 2 or 3 horizontal banners in my articles, one after the second paragraph, one before the last paragraph and maybe one in the middle.

Earnings steadily increased over following months until between March and July each month I had between $70 and $85 each month. I started receiving a bank transfer from Google every second month. Regaining motivation in March I started reviewing and improving some of my content and adding some new stuff. I now have 88 posts and about 6 videos. I still need to do a lot of work. (See SPI: 200 on Content Audits)

Eventually I started getting $100 or more a month in estimated earnings. From July to October I got a regular monthly payment of just over $100 from Google. A slight drop in earnings in November meant I didn’t get a December cheque. Since then the income seems to regained its losses. 

Month by Month Google AdSense Estimated Earnings
Month by Month Google AdSense Estimated Earnings

On January 5th 2017 I hit the $1000 lifetime estimated earnings mark. Finally! 

What Made the Difference?

The vast majority of my income has come from one post. It was post aimed at do-it-yourselfers. Over time it had just become my number one landing page with it’s acquisitions coming from Google. It seems I had just done a really good job of making that article. Over the whole time since I wrote it, the article has gradually increased in Google Search hits and income. 

Over the lifetime of the site, it had these stats:

  • 40655 pageviews (24.91% of site pageviews)
  • $215.71 Australian (30.19% of site income)

It is titled “DIY Antenna Alignment Methods for Digital TV”. This title immediately explains its usefulness to people as does the blurb. It matches pretty well to a search of “How to align a Digital TV Antenna” and the alternate searches people might use for that topic. It contains 756 words and is quite comprehensive on the topic. It has pictures, multiple headings and an embedded YouTube video. 

I believe it’s just a matter of that as more Google search traffic clicked that post, the higher the pagerank rose. The quality of the article got it into the search initially, but clicks brought higher pagerank and more clicks.

One thing I did do to the article in December 2014 was to add a strong first sentence. A member of the mastermind group I meet with pointed out that the blurb that appeared for the article on Google Search was “In a previous article blah blah blah…” It didn’t say anything about this article. I changed it to add a new first paragraph(which is still there). It now says exactly what the user will get from the article. I think it helped increase clicks, which as I say bring more clicks.

Other articles on the sites do get hits and income. The 2nd best article on the site is another How To article. However it gets only half the landings and income of the best article. The rest of the landings are spread across the site. 

I don’t get many landings on my front page(only 6%). Almost all my traffic comes from organic Google Search. I don’t do much social media promotion and no paid promotion.

How to do it yourself

These are my recommendations. I’m not an expert in SEO or writing. I’ve just followed what I’ve read from experts I follow and done some experiments. I certainly haven’t tried everything I could have tried and still have a lot of work to do to increase the quality of my site and increase my income. 

This is what I think works for me: 

  • Use the official Google AdSense WordPress plugin – it automatically makes ads responsive for mobile
  • Use only 2 or 3 horizontal banner ads, set between paragraphs of your posts
  • Allow graphics or text
  • Write lots of deep, quality content, including embedded video and photos
  • Write for people not search engines
  • Write useful articles, like do it yourself or how to content
  • Strong first sentence and paragraph – tell the user what they’ll get from your article – e.g. “Here are four methods to do blah blah blah….”
  • Wait

I think I could have reached where I am more quickly had written a lot more high quality do-it-yourself how-to articles earlier. Also more videos and social media promotion may have got me here quicker. 

My aim now is to follow a process of reviewing and improving my existing content. I’m looking to significantly increase the number of high quality how to articles and embedded videos I have. Hopefully this will get me to a level of income where it can become my day job. 


I’ve recently presented my story and Google AdSense advice on Network Live Virtually with Sabrina Watson.  You can see a replay here:



Sites with useful authority site information:

Here’s what I’ve used:

Skiiddii Bicycle Child Trailer Review

We purchased a trailer for our bikes to enable us to carry our toddler with us when we go for bike rides. We purchased the Skiidii Bicycle Trailer for $149 on eBay from seller Faji Plaza. The trailer has provision for two small children to ride on it side by side.

The trailer arrived in a flat square box weighing 17kg. We had ours delivered to our Australia Post postbox without any problems. Delivery occurred within a week of order.

On opening the box you find a large folded trailer body, some tubular sections, some wheels and other components. The tools required to assemble the trailer are provided with the kit, a couple of small spanners and an Allen key. I chose to use a socket set and ratchet spanner as this was easier. You’ll need an 11mm hex socket.

At first I thought no instructions were supplied and this made it difficult to figure out how to get the trailer properly assembled. However it turned out the instruction booklet had been wrapped up in the fabric cover for the trailer. Unfortunately, the instructions are pretty badly translated.

I started by unfolding the trailer body and installing the cross bar that supports the roof of the trailer and holds the uprights in the vertical position. It fits together using plastic brackets on each end and some locking pins.

Locking pin
Locking pin

After this I installed the axle(which required adjusting the holes it goes through). The wheels are locked into place with plastic clips that fit into retention grooves at the end of the axle. The diagrams in the assembly guide aren’t too helpful. Wheel protection bars are then connected which go around the outside of the wheels, retained by spring loaded locking pins.

The trailer can be used as a running pram, so either a front wheel or the tow bar can be attached. The tow bar attaches with two locking pins. You can then remove the bike attachment from the tow bar using its locking pin and install it on the bike’s rear axle. You simply remove one of the screws and put it on the axle before screwing it back on. I installed it on the side that didn’t have the gears.

The plastic brackets for the jogging handle are then installed, but I didn’t install the handle as I won’t be jogging with it. An orange safety flag is also provided. The fabric cover is attached with velcro at the front and back and provides a weathershield as well. There is pretty good visibility for your child to be able to see out.

Assembly took me about 45 minutes in total. Once done I attached it to the bike and gave it a try. At first I accidentally knocked the bike over but the trailer stayed upright. I was happy about that. Riding around with the trailer empty it bounces around quite a lot. With our toddler aboard it still bounces a lot but not too badly. The wheel protection bars do rattle a lot however. They don’t fit snuggly into their slots. So while they won’t fall off, they do make a bit of noise. I may look at putting some thin rubber in the slots so they don’t rattle.

Bike and trailer
Bike and trailer

The child harness isn’t particularly fancy, just being a strap system. This may be a bit of an issue for younger children. Our baby has no problems walking or sitting up but did tend to end up slumping down on the seat. For larger babies I don’t think this will be a problem.

Baby in trailer harness
Baby in trailer harness

Overall I’m happy with the Skiidii Bicycle Trailer so far. We haven’t taken it on long rides yet, but will in coming weeks. Build quality is pretty good for the price. The only real issue is the rattling of the wheel protection bars. I’m sure more expensive models would be much more solid. As noted the assembly manual isn’t too good either.

One other issue we did have was finding a suitable helmet. It seems they start at 48cm at the smallest. A smaller one would have been better for us.

Against Anti-Doping

It’s time to end anti-doping efforts. They have failed. More than that they are immoral.

Anti-doping regulations apply to all levels of sport, from junior, to elite professional, to masters. Yet we only test a small group of our elite athletes. Elite sport is only a tiny proportion of the actual sporting community. Who is checking that a junior soccer player isn’t being given a performance enhancing substance? Who is checking that a local B grade rugby league player isn’t taking performance enhancing substances.

I am an administrator of swimming at the masters level. We are an amateur sporting organisation, providing age group competition from ages 18 to 100 and higher. We are also covered by anti-doping rules. Just recently Lance Armstrong was prevented from competing as a masters swimmer because of his life time drugs ban.

Yet it’s likely that many masters athletes are taking prescription medications from the banned list. The banned list includes many medications such as vasodilators, stimulants, asthma treatments and growth factors.

Technically they’re supposed to provide us evidence of a medical need, but rarely do we get such evidence. Athletes could be taking a performance enhancing substance for a medical reason or not, but we have no way of knowing.

Why should we anyway? The medical conditions of amateur sports people should be their own business, nothing to do with us.

Advancing medical technology is one of the biggest arguments against our current anti-doping efforts. Several billion dollar companies are now working on anti-aging technologies and early indications are promising. In the past year Google has started a subsidiary named Calico Labs with the sole purpose of extending the human life span.

Already several medications are in testing that slow effects of aging. By definition these will be performance enhancing, allowing athletes to continue to perform like a young person as they age.

For instance, currently there is research going on into anti-aging effects that may be attributed to the diabetes drug Metformin. Belgian researchers found that mice treated with it lived 40% longer. The studies showed reduction in age related illness.(http://www.telegraph.co.uk/science/2016/03/12/worlds-first-anti-ageing-drug-could-see-humans-live-to-120/)

How could we possibly deny our athletes access to this technology? Are we going to say that if you want to be an athlete, sorry you have to age naturally? It would be absurd to even ask athletes to deny themselves access to anti-aging treatments that the rest of the community can access.

How is this any different to athletes using performance enhancing drugs available now?

One of the arguments often cited is the dangers to the athlete, particularly in relation to drugs that are not highly tested or administered in ways they’re not listed for. This is a case where the prohibition creates additional danger. If such drugs were not being administered secretively, proper clinical research could be undertaken and everyone would benefit.

It’s time to end this expensive, failing and misguided war on doping. We can replace it with scientific advancement of performance and anti-aging science that can benefit everyone.


Arlec 20W LED Security Sensor Flood Light Review

We needed a sensor security light for our front yard at our new place. My first thought was the typical standard dual PAR38 sensor flood light setup. These use 2x 150 Watt PAR38 halogen globes. However at Bunnings we saw a new version with 2x 10 Watt PAR38 LED globes. This is a significant power saving over the traditional type.

The version we purchased required electrician installation, but was an easy install for our electrician because the cabling was already in place. The unit is IP44 rated, so is weather proof for outdoor installation. It does need to be out of direct rain though. Ours is installed under the eaves. They can be wall mounted too.

Arlec MAL300 20W LED Sensor Light Installed
Arlec MAL300 20W LED Sensor Light Installed

I was concerned that it might not be as bright as the traditional 150W globes. It is somewhat slightly dimmer than the traditional flood lights, but is still more than adequate for our needs. The dual unit sufficiently lights up our entire front yard, which is about 6m across.

The default twilight setting was fine for making sure the unit didn’t activate during daylight. The default duration time was 2 minutes 45 seconds, which I’ve left alone. I also didn’t have to touch the sensitivity setting. It does activate sometimes when ceiling fans are turned on or off in the house. There are also some other inadvertent activations for no real reason. I’ve been quite happy with it’s operation though. I’ve been able to set it to activate only when someone enters the front yard, or leaves the front door.

Adjustment controls on the sensor light
Adjustment controls on the sensor light

It’s also useful that the unit is rated for 150W globes, so if you do decide that the 10W LED ones aren’t enough, you can swap them out. I bought ours on special for $29.95 at Bunnings.

Front of Arlec MAL300 Box
Front of Arlec MAL300 Box
Side of Arlec MAL300 Box
Side of Arlec MAL300 Box

Handy Storage Rack It Shelving Review

I had the need to store a lot of tools and other junk in my garage and didn’t want to build my own shelves from scratch. So after seeing a relative’s installation, I bought two sets of Handy Storage Rack It shelves from Bunnings. I’ve now had these shelves for two years and can thoroughly recommend them as a great product. I’ve reviewed the Handy Storage Rack It Work Bench Kit previously.

Connecting the side beam to the end frame
Connecting the shelving beam to the end upright

These don’t come in a kit, so you purchase each component separately based on your needs. At a minimum you’ll need two Double Sided End Uprights and four Shelving Beams. The end uprights come in two different widths, 450mm or 600mm. There are different heights ranging from 900mm, 1800mm and 2100mm. I chose the 600mm wide 2100mm high variety which fit under typical garage ceilings.

Assembled Rack It Shelf Frame
Assembled Rack It Shelf Frame

The shelving beams come in a range of lengths to suit your needs. I chose the longest ones, 2400mm. You also get a choice of shelf materials. There is MDF sheets or metal mesh shelves. You can get a range of attachments and accessories such as hooks, small shelves and drawers. I chose the MDF shelves as I had a lot of small items I wanted to store, which would just fall through the metal mesh shelves.

Retaining pin holds the side beam to the end shelf
Retaining pin holds the shelving beam to the end upright

The construction is simple and tool free. You could do it yourself, but it’s much easier if you have a second person to help you out holding frames and the like. The end uprights have slots and the shelving beams have tabs, so you just slot it together and ram it home. A hammer and block of wood is helpful here to get a firm fit, but you could just do it by hand or foot. Metal retaining hooks slot into holes to keep it all safe.

Tensioning straps between sidebeams are hard to attach without weight
Support braces between shelving beams are hard to attach without weight

The most frustrating part of construction is inserting the shelf tensioning straps. These go between the shelving beams on the longer shelves to keep the shelving beams from bending apart under load. The problem is that when there is no weight on the shelves they keep falling out. They do tend to vary in length a bit as well. The easiest way to get them in is to wait until you’ve put the entire shelf unit together and put a bit of weight on it. Then they’ll hold in position.

After a couple of years of use MDF sheets are somewhat warped
After a couple of years of use MDF sheets are somewhat warped

The coating of the metal frames of my shelves has held up pretty well, but there are some scuffs and scratches from moves. Nothing has bent or broken yet though. The MDF sheets shelves I’ve got have sagged a bit where I’ve had heavy items on them. In my latest move I just turned them over so they’ll bend back the other way. Fortunately it’s cheap enough to replace them when they eventually get too saggy. The other problem with the MDF is that it will swell when it gets wet. So just keep them in a dry spot and don’t put leaky things on it.

You could easily make your own ply shelves if you wanted to, but for the cost it may not be worth it. My relatives who have the metal mesh shelves have not had any problems with them.

The completed Bunnings Rack It Shelf unit
The completed Bunnings Rack It Shelf unit

The Bunnings Handy Storage Rack It shelves are very easily configurable and reconfigurable to any needs, much more so than home built shelves. I’d strongly recommend them to anyone who needs shelving in their garage or shed. You’d be hard pressed to do better with a custom constructed shelf.

Below I’ve listed the items required to build the shelf I show in this review.

Rack It Shelf Unit Bill of Materials

Price(as of 19/02/2016)
Total Cost:
Rack It 2100mm x 600mm Black Double End Upright
Rack It 2400mm Black Shelving Box Beam
Rack It 1200 x 600mm MDF Timber Shelf
Rack It Safety Pin - 20 Pack
Rack It 600mm Black Beam Support Brace
Items required to build shelf unit the same as mine in the review.

Study Notes for Java SE 7 Programer II

Here are my study notes for the Java SE 7 Programmer II to get the Oracle Certified Professional, Java SE 7 Programmer certification. This is based on the topics in Oracle published syllabus for the exam.

This page is a work in progress, so come back for more details as I go.

See also my Study Notes for Java SE 7 Programmer I OCA.

Note: I accept no liability for any inaccuracy or mistakes in this document. If you find any errors, please let me know so I can correct it!

Java Class Design

  • Use access modifiers:
    • private
      • only accessible within class
    • protected
      • only accessible with package and subclasses
    • public
      • world accessible
    • default
      • package-private
      • accessible within package
  • Override methods
  • Overload constructors and methods
    • Overloaded method use the number and types of arguments to determine which version of the overloaded method to call
    • Return type are not used to determine which overloaded method to call.
    • If a class will be inherited, a no argument constructor should be supplied. This will be called when a subclass is instantiated.
  • instanceof operator
    • Comparison between object and specified type.
    • Will return true when an object is:
      • An instance of the specified class
      • An instance of a subclass of the specified class
      • An instance of a class that implements the specified interface
    • Will return false when an object is:
      • An instance of a parent class of the specified class
      • A reference to null
    • Will not compile if comparing neither a subtype or supertype
      • Will produce compilation error: Unresolved compilation problem: Incompatible conditional operand types.
    • Often over-used and can be replaced by polymorphism
  • Casting
    • Used with superclass reference types allow access to subclass properties and methods
    • Uses syntax (MyClass)myInstance.
  • Virtual method invocation
    • Used when multiple subclasses override the same method
    • The object type’s implementation of the overriden method is used, not the reference type method
    • Important part of polymorphism
  • Override methods from Object class:
    • hashCode
      • Must consistently return the same integer for the same object each time invoked, provided information used by equals method is not changed.
      • If two objects are not equal they should not return the same integer value
    • equals
      • Compares two objects
      • Must be reflexive, symmetric, transitive and consistent
      • Comparing to null should return false
    • toString
      • Must return a string that represents the object as text
      • Recommended that all subclasses override this method
  • package statement
    • The package statement must be the first executable line of the source file, preceding any import statements.
    • Creates a package, put package statement with the name of the package at the top of every source file that contains types(classes, interfaces, enumerations and annotations) to be part of the package.
    • Without a package statement the type becomes part of an unnamed package.
  • import statement
    • Import a package member using import package.Member;
    • Import an entire package by using import package.*;
      • Packages are not hierarchical, importing package.* will not import package.subpackage.*
      • Where members of two or more imported packages have the same name, the fully qualified member name must be used.
    • import static statement allows you to reference constants and static methods from a class without prefixing the class name.

Advanced Class Design

  • Abstract classes
    • Cannot be instantiated but can be subclassed
    • May or may not include abstract methods
    • Subclass must provide implementations for all abstract methods of parent, otherwise must also be abstract.
  • static keyword
    • Static methods must use object reference to access instance variables or methods.
    • Static methods cannot use this keyword.
    • Static methods can be hidden by a static method with the same signature
      • Differs from overriding because the version of the static method that is invoked depends on the reference type from which it is invoked
    • static keyword is used to declare a class variable, which is part of the class not the object instance
    • Class variables are shared between all instances of the class
  • final keyword
  • Create top-level classes
    • Top level classes expected to be inherited by subclasses should have a default no-arg constructor.
    • The default no-arg constructor cannot be used if the class has any constructors defined.
  • Create nested classes
    • Static Nested classes
      • Declared using static keyword
      • Do not have access to members of enclosing class
    • Non-static nested classes
      • Known as inner classes
      • Have access to members of enclosing class, including private members
      • Cannot define any static members
    • May be private, public, protected or package-private
  • Enumerated types
    • Allows a variable to be set equal to one of a set of predefined constant values.
    • Is a class which extends java.lang.Enum.
    • Constructor must be package-private or private.
    • Java compiler adds a values() method at compile time which returns an array of values in the enum.

Object-Oriented Design Principles

  • Interfaces
    • Declaring
    • Implementing
    • Extending
  • Interface inheritance or class inheritance
    • Multiple interfaces can be implemented
    • Multiple unrelated classes can inherit interfaces.
  • Applying
    • Cohesion
      • The degree to which the elements of a class belong together
      • Cohesion in a class is increased if the functions within a class have a lot in common and perform a small number of related tasks.
      • Advantages:
        • Reduced complexity
        • Increased maintainability
        • Increased reusability
    • Low-coupling
      • The degree to which each component uses and has knowledge of other components.
      • Advantages:
        • Components from a low-coupling system can be replaced with alternative implementations that provide the same functions.
        • Components may be implemented with different platforms, using different languages, operating systems or build environments.
    • IS-A
      • Can be identified by a class using the extends or implements keywords.
    • HAS-A relationship
      • A class uses HAS-A relationship by composition, by having an instance of another class and using it.
  • Object composition principles
  • Singleton design pattern
    • Only one instance of the object is created.
    • Possible implementations:
  • Data Access Object(DAO) design pattern
    • Consists of:
      • A Data Access Object Interface
      • A Data Access Object concrete class that implements the DAO interface
      • A Model object, containing get/set methods for the data
  • Factory pattern
    • Consists of:
      • 1 or more concrete classes that implement a common interface
      • A common interface
      • A factory class which returns a new instance of one of the concrete classes


Generics and Collections

  • Generics allow the creation of classes, interfaces and methods where the type is specified as a parameter.
  • Generic classes
    • Declared using <> symbols
  • Diamond for type inference
    • Means that the new statement to instantiate the object and call the constructor doesn’t require repetition of the type(s) from the reference declaration.
    • The compiler infers the type from the declaration.
    • e.g. ArrayList<string> myList = new ArrayList<>();
  • Raw types
    • A raw type is a generic class or interface without a type parameter supplied
    • A parameterized generic type may be assigned to it’s raw type
    • Assigning a raw type to a parameterized type will produce a warning
    • Using a raw type to invoke generic methods will produce a warning
  • Collections using raw and generic types
  • Wildcards
  • Wrapper classes
    • The type argument of a generic cannot be a primative type, they must be object types
    • Always declare generics using object types.
    • Using a primative type will cause a compile error
  • Autoboxing
    • Autoboxing will automatically convert a primative variable to the corresponding type wrapper.
    • e.g. an int value can be assigned to ArrayList<Integer> myVals
  • Unboxing
    • Unboxing means that a type wrapper object value can be automatically converted to a primative value when assigning a value copied from the type wrapper object.
  • Implementations of:
    • List
    • Set
    • Deque
    • Map
      • Sorted Maps
        • TreeMap
        • NavigableMap
      • HashTable
      • HashMap
  • Use java.util.Comparator
  • Use java.lang.Comparable
    • Must provide a method int compareTo(T o) which returns -1,  or 1.
  • Sort and search arrays and lists
    • To be sorted in collections, the objects contained within must implement the Comparable interface.

String Processing

  • Scanner
    • Constructor may take File, InputStream, Path, Readable, ReadableBytChannel and String
    • Can parse text into primitive types and strings using regular expressions
    • useDelimiter method accepts a regular expression as a Pattern or a String to use as a delimiter between fields in the text
    • has and next functions exist for each primitive type and some others
    • nextLine advances to the next text line and returns the current one as a String.
  • StringTokenizer
    • Constructors:
      • StringTokenizer(String str) – uses default delimiters – space, tab, newline, carriage return, form feed.
      • StringTokenizer(String str, String delim) – Uses specified delimiter in delim
      • StringTokenizer(String str, String delim, boolean returnDelims) – if returnDelims is true, include the delimiters in the tokens
    • nextElement() returns the next token
    • nextToken() returns the next token or thorws NoSuchElementException
    • countToken() calculates the number of times nextToken can be called before an exception
    • hasMoreTokens() returns true if there is at least one more token after current token
  • StringBuilder
    • Constructors:
      • StringBuilder() – creates a blank String Builder
      • StringBuilder(CharSequence seq) – creates a StringBuilder with the same characters as the seq
      • StringBuilder(int capacity) creates a StringBuilder with capacity set
      • StringBuilder(String str) creates a StringBuilder with the contents of the String
    • append(T x) methods exist for all primatives, CharSequence, String and StringBuffer
    • charAt(int index) returns a char from the specified index
    • delete(int start, int end) deletes characters from start to end.
    • insert(int offset, T x) methods exist to insert primatives at an offset
    • substring(int start) returns a String containing all characters from start to the end of the StringBuilder
    • substring(int start, int end) returns a String containing characters from start to end.
    • toString() returns the StringBuiler as a string.
  • String
  • Formatter
    • Interprets printf style format strings
    • Example: Formatter formatter = new Formatter(sb, Locale.US);
  • String processing with regular expressions
    • Used by Pattern and Matcher classes.
    • PatternSyntaxException indicates that a syntax error has occurred in a regular expression pattern.
    • Syntax:
      • ^ – matches beginning of line
      • $ – matches end of line
      • . – matches any single character except newline
      • […] – matches any single character in brackets
      • [^…]- matches any single character not in brackets
      • \A – Beginning of entire string
      • \z – End of entire string
      • \Z – End of entire string except final line terminator
      • a|b – matches either a or b
      • \w – matches word characters
      • \W – matches nonword characters
      • \s – matches whitespace
      • \S – matches non whitespace
      • \d – matches digits, same as [0-9]
      • \D – matches nondigits
      • \n – matches newlines
      • \t – matches tabs
  • Format strings
    • See Formatter javadoc
    • %n is used for platform appropriate new line
    • %d is used for a decimal integer
    • %f is use for float
    • a leading 0 after %d indicates use of leading zeroes
    • a number flag indicates characters in width, e.g. 10.3 is ten characters wide with three places after decimal point
    • + indicates use sign, positive or negative
    • , indicates locale specific grouping characters
    • – indicates left justified
    • defaults to right justified
    • To use a % sign in a formatted number for instance for a percentage, use %%.

Exceptions and Assertions

  • Each try statement requires at least one catch or a finally block.
  • catch statement
    • Once one catch statement executes the otheres are bypassed.
    • Exception subclasses must come before their superclasses. Otherwise an unreachable code error will occur at compile time.
  • throw statement
    • thrown object must be of type Thowable or a subclass of it.
    • Execution immediately stops and control is passed to the nearest matching catch statement.
  • throws statement
    • Lists the exception types the method may throw.
    • Required for all thrown exceptions except Error or RuntimeException and their subclasses.
  • Multiple Exception types in single catch block
    • Called multi-catch
    • Use pipe symbol
    • e.g. catch(FileNotFoundException | IOException e)
  • try-with-resources statements
  • finally statement
    • Executes regardless of whether or not an exceptions has been thrown.
    • If exception has been thrown executes after the relevant catch block.
  • Custom exceptions
  • Test invariants by using assertions

Java I/O Fundamentals

  • Read and write data from the console
    • Get a Console object with System.console() method.
    • System.console().readPassword() retrieves user input without echoing typed characters.
    • The Java platform supports three standard streams:
      • Standard input – stdin – using System.in
      • Standard output – stdout – using System.out
        • System.setOut may be use to redirect output to a different stream
      • Standard error – stderr – using System.err
    • Can be read using BufferedReader or Scanner
  • Using streams to read and write files with:
    • BufferedReader
      • Implements Closeable, AutoCloseable, Readable
      • read() reads a single character – returns -1 if end of stream is reached
      • ready() returns true or false
      • skip(long n) skip n characters
      • Methods throw IOException
    • BufferedWriter
    • File
    • FileReader
    • FileWriter
      • Implements Closeable, Flushable, Appendable, AutoCloseable
      • Defaults to overwrite an existing file use FileWriter(File file, boolean append) constructor with append set to true to append to an existing file.
      • Inherits methods from Writer.
    • RandomAccessFile
      • Implements DataOutput, DataInput, Closeable
      • readUTF reads the file into a String
      • writeUTF writes a String to the file
      • Maintains a cursor also known as a current file pointer marking the current location in the file.
      • seek(long pos) sets the cursor location/file pointer, measured in bytes from beginning of file.
      • read and write methods are provided for all primatives
      • readLine reads bytes from the file, starting from current file pointer and ending at the end of the current line. Line terminating characters are not included.
    • FileInputStream
      • Implements Closeable, AutoCloseable
      • read() reads a single byte or -1 if end of file
      • read(byte[] b]) reads b.length bytes of data into an array of bytes
      • read(byte[] b, int off, int len) reads len bytes starting at offset off into an array of bytes
      • skip(long n) skips n bytes
    • DataInputStream
    • DataOutputStream
    • ObjectOutputStream
    • ObjectInputStream
    • PrintWriter
  • Serializable interface
    • Enables a class to be serialized
    • Always include a serialVersionUID field
    • static and transient fields are not serialized
    • Superclass fields are only serialized if the superclass also implements Serializable

Java File I/O (NIO.2)

  • Path class
    • Paths.get returns a Path object
    • resolve(Path p) appends a relative path p to this path. If p is an absolute path then p is returned.
    • relativize(Path p) returns a relative path from this path to path p
    • getName(int index) returns the name of the component of the path at that index
    • getRoot() returns root component
  • Files class
    • Atomic operations
      • An atomic file operation cannot be interrupted or partially completed.
      • Entire operation is completed or fails.
    • move method supports atomic moves and replacing existing files by means of options provided
  • Interfaces:
    • BasicFileAttributes
      • creationTime() returns creation time as a FileTime object
      • fileKey() returns an object that uniquely identifies the file
      • isDirectory() returns true if the file is a director, false otherwise
      • isOther() returns true if the file not a regular file, directory or symbolic link
      • isRegularFile() returns true if the file is a regular file
      • isSymbolicLink() returns true if the file is a symbolic link
      • lastAccessTime() returns the last access time as a FileTime object
      • lastModifiedTime() returns the last modification time as a FileTime object
    • BasicFileAttributeView
      • readAttributes() method returns a BasicFileAttributes object
      • setTimes() allows any or all of a file’s last modified time, last access time and create times to be updated.
    • DosFileAttributes
      • Provides ability to read legacy MS DOS file attributes
      • Provides isArchive(), isHidden(), isReadOnly, isSystem() attributes
    • DosFileAttributeView
      • Provides readAttributes which returns a DosFileAttributes object
      • Provides setArchive(boolean value), setHidden(boolean value), setReadOnly(boolean value), setSystem(boolean value)
    • PosixFileAttributes
      • Provides ability to read file attributes from POSIX operating system file systems. Typically these are Unix, Linux or Mac OS X systems.
    • DirectoryStream
    • FileVisitor
    • PathMatcher
      • Instantiate with for example:
        • PathMatcher matcher = Filesystems.getDefault().getPathMatcher(“glob:*.{txt,doc}”);
      • Uses glob patterns
    • WatchService
      • Watches registered objects for changes and events.
      • May be used to monitor directories or files for changes.
      • If the file system does not support file change notifications the API will poll the file system for changes.

Building Database Applications with JDBC

  • JDBC Drivers must include Statement, ResultSet and Connection objects
  • JDBC Driver Types:
    • Type 1
      • Not pure Java
      • Require native libraries
      • Use bridging to data source
    • Type 4
      • Are pure Java
      • Use direct connections to data source
      • Can use network protocols
  • Core interfaces:
    • Driver
      • acceptsURL(String url) method checks whether the driver thinks it can open a connection to the url.
      • connect(String url) is the most basic way to start a connection
      • connect(String url, Properties info) method tries to start a connection
      • connect(String url, String user, String password) also tries to start a connection
      • url is in format: jdbc:subprotocol:subname
      • getMajorVersion() and getMinorVersion() get the major and minor version numbers respectively
      • SQLException is thrown for most database access errors.
      • See Javadoc for other methods.
    • Connection
      • Connections are AutoCloseable
      • Use DriverManager.getConnection() and DataSource.getConnection() to establish a connection using a JDBC driver
      • Use setAutoCommit(false) to turn off auto commiting of updates
      • Use commit() to commit updates when auto committing is off.
    • Statement
      • Statements default to being commited automatically
    • ResultSet
      • Maintains a pointer/cursor to the current row.
      • next method moves to next row, but returns false if there a no more rows.
      • Current row pointer is initially set before the first row, so will require a next to reach the first row.
      • By default is only cursor only moves forward
      • By default ResultSet is not updateable
      • A ResultSet may be set to be updateable and scrollable.
  • Connect to database using DriverManager class
  • Submit queries and read results
  • Use JDBC transactions
    • Disable auto-commit mode using setAutoCommit(false);
    • Commit changes using commit();
    • Rollback changes rollback() if a SQLException is thrown.
    • setSavepoint() sets a Savepoint within the current transaction. Use rollback(Savepoint s) to rollback to that savepoint.
    • Disable auto-commit only during transaction mode.
    • Savepoint interface
      • Represents a point that can be returned to by the Connection.rollback method.
      • releaseSavepoint(Savepoint s) removes the Savepoint from the current transaction.
  • Construct and Use RowSet objects with RowSetProvider class and RowSetFactory interface
    • Get a RowSetFactory using RowSetFactory factory = RowSetProvider.newFactory();
    • Get a JdbcRowSet using JdbcRowSet rs = factory.createJdbcRowSet();
    • A JdbcRowSet can also be obtained by using JdbcRowSet rs = new JdbcRowSetImpl();
  • CachedRowSet interfaces
    • These are disconnected RowSets – connected only when reading data and propagating changes to the data source
    • WebRowSet interface
      • Allows a RowSet to be read or written in XML format.
    • FilteredRowSet interface
      • Allows disconnected filtering of a RowSet using a Predicate object
  • Statement object
    • Supports only simple SQL statements without parameters
    • Support only a single result set open
  • PreparedStatement object
    • Supports only input parameters
  • CallableStatement object
    • Supports input and output parameters because they contain stored procedures


  • Create and use Thread class and Runnable interface
  • Manage and control thread lifecycle
    • Threads may be paused in execution using Thead.sleep(long milliseconds) which throws an InterruptedException
    • isAlive() method returns true if the thread is still running
    • join() method waits for a thread to finish execution
  • Synchronise thread access to shared data
  • Identify code that may not execute correctly in a multi-threaded environment


  • Collections from java.util.concurrent package
    • BlockingQueue provides a first-in-first-out queue data structure
    • ConcurrentMap interface has atomic operations to remove or replace a key-value pair if it’s present or add a key-value pair if it is absent. Has implementation ConcurrentHashMap.
      • ConcurrentHashMap is similar to HashMap
      • ConcurrentNavigableMap is sub-interface supporting approximate matches.
        • Standard implementation is ConcurrentSkipListMap which is similar to TreeMap.
    • These collections try to avoid Memory Consistency Errors using a happens-before relationship.
  • Use
    • Lock interface
      • lock() acquires the lock
      • unlock() releases the lock
    • ReadWriteLock interface
      • Separate locks for reading and writing
      • Read lock may be held by multiple reader threads at the same time if there are no writers
      • Write lock may only be held by one thread
    • ReentrantLock
      • Mutual exclusion lock – both reading and writing are locked.
      • lock() returns immediately if the lock is acquired, disables thread and waits if lock is not available.
      • Optional constructor Boolean fairness parameter, when set to true locks favour the longest-waiting thread.
    • Executor interface
      • execute(Runnable r) method creates a thread of Runnable object r.
      • May use a worker thread or put Runnable object r in a queue waiting for a worker thread.
    • ExecutorService subinterface of Executor
      • Provides features to manage lifecycle of tasks and Executor
    • Executors
      • Factory and utility methods for Executor, ExecutorService, ScheduledExecutorService, ThreadFactory, Callable.
      • Provides methods for creating a thread pool: newCachedThreadPool, newFixedThreadPool, newScheduledThreadPool, newSingleThreadExecutor, newSinglethreadScheduledExecutor, newWorkStealingPool.
      • Allow separation of thread management and creation from the rest of application.
    • Callable interface
      • Implementations must define a method call with no arguments that returns a result of a generic type. May thrown an exception if unable to produce a result.
    • Future interface
      • Represents the result of an asynchronous computation.
      • Provides method to check for completion, to wait and to retrieve results.
  • Use parallel Fork/Join Framework
    • Implementation of ExecutorService interface
    • Uses work-stealing algorithm
    • Extend ForkJoinTask or a more specialised subclass such as RecursiveTask or RecursiveAction
    • RecursiveTask returns a result.
    • RecursiveAction does not return a result.


  • Read and set locale with Locale object
    • Use Locale constructors
    • Use constants in Locale class
    • Use Locale.forLangaugeTag factory method
    • Locale.Builder class
      • Create a Locale variable with the Locale.Builder class: Locale loc = Locale.Builder().setLangauge(“en”).setScript(“Latn”).setRegion(“AU”).build();
      • build method must be called to create a Locale object withtthe Locale.Builder class.
  • Build a resource bundle for each locale
    • Resource bundles stored in properties files using name=value pairs
    • Properties files must be in the CLASSPATH
    • There must be an individual properties file for each language supported
  • Call a resource bundle from an application
    • Identified by family name/base name and may have a two character language code.
    • e.g. Sample_en_AU where en is the language code and AU is the country code for Australia
    • Create a local object for the language, country and platform appropriate
    • Load bundle using
      • Locale myLocale = new Locale(“fr”, “CA”, “UNIX”)
      • ResourceBundle myBundle = ResourceBundle.getBundle(“Sample”, myLocale);
      • will search for classes in this order:
        1. Sample_fr_CA_UNIX
        2. Sample_fr_CA
        3. Sample_fr
        4. Sample_en_US
        5. Sample_en
        6. Sample
    • Resource bundle may be stored in classes extending ListResourceBundle, PropertyResourceBundle or a properties file.
  • Format dates, numbers and currency values with NumberFormat and DateFormat classes
    • Use DateFormat myDateFormat = DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.US); to format a date to US format.
  • Advantages of localising an application
  • Define a locale with language and country codes

Trade a Park No One Uses for a Useful Carpark

The Woody Point Village has rapidly become more and more popular in recent years. On any given weekend you will find that all the on and off street parking is completely full. With more high-rise developments, shops and cafe’s planned in the future this problem is only going to get worse.

Google Earth image showing the proposed carpark location
Google Earth image showing the proposed carpark location

Just behind the Woody Point Village shops and Belvedere hotel there is a small park called Lion’s Park. I have never once seen a person in that park. It’s really just a space for an open air storm water drain to flow.

Instead of being wasted space, this space could be used for a multi-level carpark. Two covered levels and 1 open air level would provide a huge boost to the parking capacity of the area. I know carparks aren’t popular, but they are a necessary evil. The Lions Park location is close enough to Woody Point Village to significantly help the area out, with no significant loss of amenity.