Hackintosh, one year later

In late 2012 I built myself a new workstation.

My previous home PC was a build-to-order PC from a shop in Akihabara (which has since gone out of business), built back in 2008. I had been patient and waited for 4 years before considering an upgrade.

I really like being able to build my own computer — it is a better value per dollar (or yen, in my case). It is also fun — yes, I am guilty of enjoying the process of choosing parts and weighing the costs and features of various video cards and motherboards.

However, in 2012 I really wanted a Macintosh at home. Windows is tired and generally crappy, and while OSX is far from perfect, it is leaps and bounds ahead of Microsoft. I just want something that works so I can get on with my life. However, Macs are not really compatible with building your own computer.

Enter tonymacx86.com.

The Hardware

These guys have done a real service. If you stick to the hardware they recommend, things are pretty smooth. Just don’t let yourself get sidetracked.

I initially got sidetracked with the idea that I could build a tiny Mini-ITX sized hackintosh. At the time, the recommended motherboard vendor Gigabyte did not have any supported Mini-ITX motherboards out there — I foolishly tried it with a Zotac board. It is possible, but it required hacking kexts — kernel extension files. And really — is this something you want to be doing, when you have better things to do? No.

So, I gave up on the mini-ITX and followed the hardware recommendations for one of the Golden Builds (I picked Slugnet’s Video Editor build). I got a nice big quiet case, a Fractal Design Define R4. Gigabyte motherboard, Ivy Bridge CPU, NVidia Video Card. And two SSDs, one for Mac and one for Windows.

Being able to follow the discussion around the golden build and see that lots of other people used the same hardware and techniques gave me a lot of confidence in my build. Follow the trailerblazers, I say.

Installing Mac OSX

Installing via the instructions and software on tonymacx86 was pretty straightforward and worked well. I set up some backups (manual) and felt pretty good.

I was also able to get Windows 7 to dual boot pretty easily. For games, of course.

Upgrades

The thing about a hackintosh though is upgrades. When Apple puts out a OSX upgrade you want to be careful and do it manually, rather than doing the automatic upgrade via the App Store.

When I had installed, I had created a custom DSDT and so was loathe to upgrade and hav to do that work again. So I skipped upgrading for a long time.

Upgrade to Mavericks

However Mavericks came out and I decided to give it a try. I waited until the first update to Mavericks, 10.9.1. But first I wanted to do a backup of my current boot drive, as all the guides recommended.

My boot drive was corrupted and failed.

I ran into a problem — somewhere along the line my Mac startup disk got corrupted. It was working fine but I was not able to back it up prior to the upgrade to Mavericks. Even worse, when running Disk Utility from a USB stick, Disk Utility tried to repair the disk, and failing to do so, rendered the start up disk useless. So I was unable to boot into the Mac.

However, I was lucky in two ways.

  1. I could still boot into Windows, so the computer was not completely useless.
  2. Losing the start up disk was not a big deal. Because I was using SSDs, I was not keeping data on the startup disk, using it only for the OS, configs, and applications. I would have to download and re-install all my apps. But my data was on other drives. And in the past, when I would have worried about all my emails, etc, now all that stuff lives in the cloud. Hurray for the cloud.

I did also have a backup of the start up disk, which unfortunately was rather old. (Note to self — manual backups are only as reliable as the guy who does them…). However it did have some vital configs backed up, and was useful as a list of what apps I needed to reinstall.

Installing Mavericks, from scratch

I decided I would just wipe my boot drive and install Mavericks from scratch.

  1. Use Unibeast to prepare a USB stick that can boot and install with Mavericks (on non-Apple hardware).
  2. Do the Mavericks install.
  3. Before rebooting, run Multibeast to run post-install configuration for my hardware setup.

It couldn’t be simpler, and I was done start-to-finish in just a couple hours. And it was easier than my previous (Mountain Lion) install. No custom DSDT, and now it is possible to save your Multibeast config for future reference.

My machine can’t compare to Apple’s new MacPro’s — but I have a fast, stable, flexible workstation that works really well, outperforms any Mac that was available in late 2012 (geek bench is around ~14,300), and cost less than $1000 to build.

Advice

If you are in the mood for building a workstation, and want to run Mac OSX, I think the recommendations at tonymacx86.com are great. Just stick to the common hardware configurations and you’ll be fine. Obviously, the aesthetics are not as nice as real Apple hardware, but the appeal for me was the fun of putting a machine together and in the exact configuration I wanted.

Ready to code

I’ve spent some time over the last couple of weeks getting my coding house in order. I’ve made two changes which I believe will make it easier and more productive to get some coding done this year.

One, I decided that I wanted a virtual private server. Dreamhost isn’t cutting it for the types of projects I want to do these days. I want to have a place where I can run servers and do anything I want, without too much hassle.

I looked at hosting my own server in my apartment and decided against it. For the cost and hassle, it just isn’t worth it to buy hardware that will be out of date in a couple years. Instead, I went with a cheap VPS plan for Linode, because they have a new data center here in Tokyo, and they seem to be well recommended.

So far I love Linode. The only down side of VPS is that you don’t get a lot of memory on the cheapest plan — but still, it is more than enough for what I need. The pros are: they have Ubuntu, and using a virtual disk image is so much better than installing the OS yourself.

I am looking forward to playing with Java long running servers and nodejs on this node. And if I decide I don’t like it, I can always just cancel, and get a pro-rated refund for the months I don’t use.

Two, I decided to get my code projects online. I spent a lot of time trying to get Indefero installed. But once it was installed, I decided I didn’t like it. The install process was not pleasant, but more than that, the UI doesn’t really feel good. Sites like github and twitter’s Bootstrap framework have really raised the bar for web app design, and Indefero was lacking.

At any rate, I did what I should have done in the first place, which was sign up for Bitbucket instead.

So, ready to code. Here’s to lots of productive coding in 2012!

Continuing adventures with GWT

Well it is already the end of February. I’ve been silent all month–not because there is nothing to report but because I’ve been too busy to write it all down.

My adventures with Google Web Toolkit continue. I am still trying to get the hang of developing with the MVP-style development–particularly with UIBinder. I’m following the GWT group maillist pretty closely, and I am relieved to see that I am not the only one.  I think the biggest currently released source code for a GWT application might be the source for Speed Tracer–I downloaded it and took a look. It is not quite the MVP style that is in the MVP tutorial, but it is still an eyeopener. Unfortunately, I haven’t had time to go through it line by line yet.  I hope to put more work into building a more significant app with GWT in March.

That said, I am getting better at certain aspects of GWT. Cranking out UIBinder layouts is becoming second nature–mostly because I have probably created 15-20 GWT projects in the past 3 weeks. It wasn’t so easy at first, but I created a GWT maven archetype to create UIBinder-friendly default projects for myself. In the process I learned a lot about maven and the gwt-maven-plugin (from Codehaus), and creating maven archetypes. Unfortunately, right now the interaction between GWT and the gwt-maven-plugin is a little awkward. The good news is that the GWT Eclipse plugin team announced that they will be making some changes to make their plugin more flexible, so that it will work better with maven. When that happens, I plan on updating my archetypes and releasing them, as the one included with the current gwt-maven-plugin is dated and defaults to gwt 1.7.

One more thing about GWT. I wanted to create some charts and graphics in GWT. I’ve had this in the back of my mind since I read the article on the GWT blog about Hydro4ge using a JavaScriptObject wrapper around the Raphael graphics library. I was going to start on the wrapper for Raphael myself, but it turns out the Hydro4ge guys released their code which they wrote about as Raphaelgwt. I got a chance to check it out today. It is fantastic! Hopefully I’ll have a new gwt-raphael sketch up for you in March.

More on TabLayoutPanel

Okay, in the interest of moving on with my life, I am going to call the last couple days of GWT experiments to be over. But first! I am publishing a couple of code sketches of what I’ve been working on.

I think I have gotten the hang of working with TabLayoutPanel. (see my last post for lessons learned). Below are two demos of a financial app that I sketched out.

  1. The first demo has the TabLayoutPanel working.
  2. The second demo I have added icons to the TabLayoutPanel tabs, as well as adding click handlers to the buttons on the InfoBar and the “About” link in the header.

(Note: above doesn’t work on IE8. Not sure why, and I haven’t been testing on IE at all… well, these are just experiments to learn GWT, so, sorry about that. Moving on…)

I’m really not a designer, so forgive the ugly colors and css. But it does work, and it is pretty brilliant that thanks to GWT this will work across browser (although if you look at the demos in IE you will see that my header image isn’t working right… that’s ok, I was focused on the Tab layout in this experiment.)

Below are the UiBinder template I used for the tabs, and also the css:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
	xmlns:g="urn:import:com.google.gwt.user.client.ui"
	xmlns:trade="urn:import:org.filsa.gwt.tradedash.client.ui"
	>

	<ui:image field="rateTabLogo" src="chart_24x24.png"></ui:image>
	<ui:image field="listTabLogo" src="coins_24x24.png"></ui:image>
	<ui:image field="marketTabLogo" src="yen_24x24.png"></ui:image>

	<ui:style>
		.rateboardPanel {
			background: #efefef;
			border-right: 1px solid #cdcdcd;
			border-bottom: 1px solid #cdcdcd;
		}
		.tabCard {
			border: solid 3px #8d8d8d;
			height: 100%;
		}

		.tab { height: 100%;
  		    cursor: pointer;
		    text-shadow: rgba(255, 255, 255, 1) 0 1px 1px;
		    font-size: 1.2em;
		    font-weight: bold;
		    color: #000;
		    border-top: 1px solid #666;
		    border-left: 1px solid #999;
		    border-right: 1px solid #666;

		    vertical-align: middle;

		}

		@sprite .rateTab {gwt-image: "rateTabLogo";}
		@sprite .listTab {gwt-image: "listTabLogo";}
		@sprite .marketTab {gwt-image: "marketTabLogo";}

		.left {float: left;}

	</ui:style>
	<g:HTMLPanel addStyleNames="{style.rateboardPanel}">
		<g:TabLayoutPanel barHeight="40" barUnit="PX" ui:field="tabPanel">
		<g:tab>
			<g:header>
				<div class="{style.tab}">
					<span class="{style.rateTab} {style.left}"></span>
					<span>Rateboard</span>
				</div>
			</g:header>
			<g:Label addStyleNames="{style.tabCard}">RateBoard here.</g:Label>
		</g:tab>
		<g:tab>
			<g:header>
				<div class="{style.tab}">
					<span class="{style.listTab} {style.left}"></span>
					<span>RateList</span>
				</div>
			</g:header>
			<trade:RateListCard  addStyleNames="{style.tabCard}"></trade:RateListCard>
		</g:tab>
		<g:tab>
			<g:header>
				<div class="{style.tab}">
					<span class="{style.marketTab} {style.left}"></span>
					<span>MarketBoard</span>
				</div>
			</g:header>
			<g:Label addStyleNames="{style.tabCard}">MarketBoard here here.</g:Label>
		</g:tab>

		</g:TabLayoutPanel>

	</g:HTMLPanel>
</ui:UiBinder>

Note the highlighted span tags above. I used one span for the image, and one for the title of the tab. If there is a better way to do this I’m open to suggestions. Please leave a comment!

And the css I used for the gwt-TabLayoutPanel:

.gwt-TabLayoutPanel
{
	height: 100%;
}
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTabs
{}
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTab
{
		background: #a4a4a4;
		margin: 0px 5px;
}
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTab-selected
{
		background: #8d8d8d;
}
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTabInner
{
}

The height:100% is what makes the tab contents appear, otherwise the tab content area doesn’t show at all. Something to do with absolute positioning in CSS, from what I understand.

Hope this helps, and let me know if you have better suggestions.

GWT Notes: TabLayoutPanel

I’ve been putting in some time over the past week building UI’s with GoogleWebToolkit and the new UIBinder.

It is all very spiffy and so much easier to use than 1.7 was. Last summer I tried to put together some moderately complex UI’s and found that doing everything in Java to be slow and tedious.

I will cautiously say that I am getting the hang of UIBinder, and that is far and away my current favorite feature from the new 2.0.0 release.

That said, there are a few minor snags.

The new LayoutPanels are for fast, browser-rendered widgets, done in standards mode. I prefer them to the old Panels they replace because they don’t use tables, instead the layout is all clean css and <div>s.

But when I started working with the TabLayoutPanel, I ran into some problems which I’ve listed below.

The TabLayoutPanel doesn’t display at all, or you get a weird collapsed layout (if you’ve added css). Remember, you  must use standards mode <!DOCTYPE html> for LayoutPanels, and you have to use RootLayoutPanel.get() instead of the old RootPanel.get().

- There aren’t any default css styles. If all you see are the tabs titles with no styling… check the apidoc to see the css styles you need to add. This isn’t actually a bug, but without default css the class is pretty much worthless. (There is an issue for this.)
- The tabs display, but the tab widgets (content area) don’t. You need to set the  height of the .gwt-TabLayoutPanel.
- It doesn’ work in IE (what does?).  There’s a bug with TabLayoutPanel and IE, and a simple css workaround:
.gwt-TabLayoutPanel .gwt-TabLayoutPanelTab { float: left; }

Update: See my next post, More on TabLayoutPanel for some sample css and demos.

Update 2: GWT version 2.0.1 address the problems with IE and provides a default CSS style. You still have to remember to use RootLayoutPanel, and standards mode doctype, when using a LayoutPanel.

Whoa, StackOverflow error

I totally cracked myself up at work yesterday. I managed to run some code that threw a StackOverflow error.

It was something along the lines of:


public String getSender() { return this.getSender(); }

I had copy-and-pasted some class template code from elsewhere in the (huge, sprawling) code base. Which contained this error, but was not ever called in the that location, so it never showed up. (So it’s not my fault really, but I should have caught it. Oh wait, I did!)

Oh, the dangers of copy and paste.

Code Sketch: System Tray in Java

As I mentioned a week or so ago, this year I am going to release whatever I am working on, on a regular basis. The idea is that even if I fail or release something that is half finished, I can learn more by turning it out to the wild than if I never share it with anyone.

These bits of code are not big enough to be called apps, and don’t have enough explanatory text to call them demos or tutorials (although I want to do that as well). I’ll call them…. code sketches!

The first one I worked on over the New Year break. It’s code for a simple system tray, done in Java. The code is available from scn, and the license is GPL.

Java allows access to native System Tray notifications.

You can check it out here, on the code sketch page: /code/sketches/system-tray

ConcurrentModificationError Mystery

So, today I got bit by the ConcurrentModificationError. I had some code which had a bit of a bad smell but was working fine. The class is a batch process, that processes a request. Based on the request, a particular subset of accounts are processed. The method below gets the target accounts based on the request, and additionally filters out corporate accounts. And the ConcurrentModificationError happens on line 9:

	/**
	 * Get accounts to process based on BatchRequest, filtering out corporate accounts.
	 * @param request
	 */
	public void getAccounts (BatchRequest request) {

		List<Account> accounts = AccountManager.getAccounts(request);

		for (Account oneAccount : accounts) {
			if (isCorporateAccount(oneAccounts)) {
				accounts.remove(oneAccount);
			}
		}

	}

The List which the AccountManager is passing back has a fail-fast iterator, which detects that it is being modified in line 11, and thus failing. The mystery is–this has been working in production for months. Today, on UAT we tested a second batch job with very similar data (for all intents and purposes it is completely the same request, just a different group of accounts) and on the second pass only, the ConcurrentModificationError gets thrown. The first pass through it is fine.

Color me confused. It should work both times, or fail both times. And yes, the data is basically the same–I triple checked that today. But it works the first time, and fails the second.

Rather than spend more time wondering why it works once and fails the second time, I figure I should just eliminate the possibility of the ConcurrentModificationException entirely.  I had to make changes to the AccountManager module, which I hadn’t had the chance to change before. But it is definitely a cleaner solution. By adding a signature to the AccountManager.getAccounts(BatchRequest request, boolean includeCorporateAccounts) I was able to simplify the code to something like this:


	private static final boolean EXCLUDE_CORPORATE_ACCTS_FLAG = false;

	/**
	 * Get accounts to process based on BatchRequest, filtering out corporate accounts.
	 * @param request
	 */
	public void getAccounts (BatchRequest request) {

		return AccountManager.getAccounts(request, EXCLUDE_CORPORATE_ACCTS_FLAG);

	}

Hello, 2010!

Well, 2009 was an eventful year for me, but not so much for the blog. I am hoping to change that in this brand new decade, with the idea that I can learn and improve faster if I am writing down and sharing what I am learning. In the last couple years the blog has mostly been a place for me to make note of a solution to a technical problem I had encountered–a backup brain of technical stuff  I found useful and was likely to forget. I’ll probably keep doing that, but also want to write some beefier articles and how-tos and especially post code I’ve written.

I definitely want to code more little projects. I’ve decided I’d rather just create some things and put them out into the world without too much worry about who they will impress or their ultimate usefulness. It’s better to ship software rather than just have big plans. Just like exercise–no one will raise an eyebrow at my glacial running pace but really, it’s for my benefit not everyone else’s. The same thinking applies to this blog as well.

For those of you who choose to read (hi mom!…. mom?) thanks for hanging with me and I hope to have something more substantial for you to read in this new year.

Cheers!

Reading Linux ext2 Disks in Windows

Sometimes, you need to be able to read a Linux filesystem from Windows. Either you are dual-booting, or perhaps like me you are trying to get some data off some old hard disks that have been in a box for a couple years.

There’s a handy driver that will mount ext2 disks on Windows available from http://www.fs-driver.org/. Install it, and when you have attached the drive, use the Control Panel “IFS Drives” item to select a drive letter for your volume.

Works great, and transparently in Windows.