Windows Phone lacks developer experience first thinking.
Today I read that Apple iPhone makes more money than Microsoft does all up, that is to say the phone that Steve Ballmer the CEO of Microsoft used to mock – generates more revenue than his entire company does (who is laughing now).
It got me thinking, let us assume you were inside Microsoft today and you heard this news for the first time, how would you react? How would you adjust your core strategies overall and how do you think this will play out?
Inside Microsoft they have a vision, it centres on the Windows 8 or bust mentality, and that for me is something of a concern given, they really have not done anything new to be openly honest.
Yes, there is Metro which is new, well not really, the initial design execution is new but the concept of taking a minimalist approach to the desktop has been around for quite some time (Adobe really did this well with their CS5 and CS4 product UI’s which you’d be an idiot if you assumed had no influence in design today).
The web has been also doing grid based design for as long as I can remember, so that’s nothing pioneerish going on here either. The idea of some NUI effects and control, sure that’s new I guess but not enough to flip the world into a new way of doing software interaction and development in fact it probably falls down when it comes to data density.
What is new then? The most obvious piece to what is new in this saga is the reality that Microsoft faces around its future. The industry has grabbed Microsoft by the shirt and dragged them into focusing on User Experience first, Technology second and what is so striking about the metro + Microsoft story is that its hinting at some new thinking.
What hasn’t changed though is the technology first approach, Microsoft continues to retreat to its initial bad behaviour, that is to say it thinks in technical terms and not in experience terms. What hasn’t change is that each team is left to interpret the experience strategy and what hasn’t changed is that Product teams make, marketing / evangelism sustain and the divide occurs resulting in both teams looking at one another as if “its your fault we don’t have adoption”.
Allow me to illustrate.
Games make up for about 64% of the current Windows Phone 7 sales, which is a little bad given if you’re an Application developer depending on your category of choice you stand to only tap into around 8% of the audience purchasing power.
That aside, Games are the golden ticket in the Windows Phone 7 way of life. Ok, so let’s build a game? Open up your browser and start typing search terms for Windows Phone 7 game tutorials and XNA or whatever you feel is appropriate.
You should be coming up short on examples that mostly live in a small spread across Microsoft random websites that constantly change context and when you’re done there, you should also be drowning in blog posts that are either extremely detailed or very shallow (not quite in between).
That for me is a problem, if I were in the team I’d be looking at this from a perspective of two things. How can I market the potential of this platform in a game centric device world and secondly assuming that thread is off and running how can I sustain this momentum once the devs have taken the bait.
I’m not saying that the key to Windows Phone 7 overtaking the iPhone is games, there’s probably a thousand or more things that need to occur before you even embark on that discussion, what I am saying is the grass roots fundamentals aren’t in place.
Lets say I click my fingers and the $500million spent on marketing to date actually worked, you have an audience of Windows Phone 7 folks over the next 2 years running hot in potential sales of the device. Congrats, 1 in 5 mobile phones sold today are Windows Phone 7.
Now what.
How do you sustain that momentum, how do you encourage more and more solutions to be built for the phone and lastly how do you retain control over the entire experience.
This is a huge problem today within Windows itself, there is so much energy spent on promoting the entire vision of WinRT and its future(s) but there is no on ramping to help the solutions delivery for this vision. Instead, it is a lot of wait and see?
Android has had next to no marketing but yet its retaining a steady share and I’d argue that its developer base of java and mono geeks have really taken this bad boy out for a test drive. It’s not a huge learning curve either, in under a week I was mucking around with the Android development and I’d say the community backing for this phone is quite loud despite the randomness of Google.
It’s still just as bad as Windows Phone 7 but that’s fine, reason being this is typical with any Google solution – Microsoft however can be better than that? They can on board people faster and with more energy than their competitors do as they are staffed worldwide better.
If you ask me, the phone itself is one thing but if the experience at the developer to consumer is filled with random noise and less signal around getting solutions to a mature level of quality, then that’s just the first strike and more to come shall follow.
There is a reason why the Windows Phone 7 marketplace is filled with crappy games or apps, some are good but they aren’t as rich as the iPhone (even then iPhone has crap to).
I’d argue that the competitive advantage Microsoft has right now that isn’t being capitalised on is the stark reality that they have a development experience that is quite rich and inviting the downside is once you get past the Powerpoint style development and want to actually build a Minecraft / Voxel Engine on a phone well you come up short.
If Microsoft’s vision is to ramp developers onto C++ then where is the investment on learning C++? DirectX? XNA? OpenGL? Etc. etc.
This phone needs much more than guys dropping the phone in a urinal as way to entice the masses to the cause. It needs to start at the experience level and work its way back to the technical detail(s). Its not just about building yet another Microsoft website that doubles down on Tutorials its more about thinking and engaging developers in ways that they understand or need massive leaps in thinking around. If Windows 8 and its device strategy can’t sustain the developer base and relies heavily on the market to teach the masses, then its yet another failure on the horizon. Same tactics as last time only more glitter.
Related Posts:Sample Application with Angular.js
After I blogged a three-part Backbone.js tutorial (part 1, part 2, part 3), a number of people asked me to try Angular.js. So I decided to take it for a test drive. I thought it would be interesting to rebuild with Angular.js the Wine Cellar application I had built with Backbone.

If you are new to my Wine Cellar application, it is a simple CRUD app that allows you to manage (create, update, delete) wines in a Wine Cellar. The data is stored in a MySQL database that the client application accesses through a simple RESTful API. This seemed to be a good fit since CRUD applications are often positioned as the sweet spot for Angular.js.
You can run the application here. The UI is intentionally plain to keep the focus on the key learning points. For obvious reasons, this online version is “read-only”. You can download the fully enabled version here.
Application WalkthroughThe best way to get started with Angular.js is to go through the excellent tutorial that is part of the documentation, so I’ll only provide a high level overview of my code here.
Like the Backbone.js implementation, the Angular.js version is a deep-linkable single page application. index.html is defined as follows:
<!DOCTYPE HTML>
<html xmlns:ng="http://angularjs.org">
<head>
<title>Angular Cellar</title>
<link rel="stylesheet" href="css/styles.css" />
</head>
<body ng:controller="RouteCtrl">
<div id="header">
Angular Cellar
<button ng:click="addWine()">New Wine</button>
</div>
<div id="sidebar">
<ng:include src="'tpl/wine-list.html'"></ng:include>
</div>
<div id="content">
<ng:view></ng:view>
</div>
<script src="lib/angular-0.9.19.min.js" ng:autobind></script>
<script src="js/services.js"></script>
<script src="js/controllers.js"></script>
</body>
</html>
The application is driven by a set of Controllers that I defined in controllers.js as follows:
function RouteCtrl($route) {
var self = this;
$route.when('/wines', {template:'tpl/welcome.html'});
$route.when('/wines/:wineId', {template:'tpl/wine-details.html', controller:WineDetailCtrl});
$route.otherwise({redirectTo:'/wines'});
$route.onChange(function () {
self.params = $route.current.params;
});
$route.parent(this);
this.addWine = function () {
window.location = "#/wines/add";
};
}
function WineListCtrl(Wine) {
this.wines = Wine.query();
}
function WineDetailCtrl(Wine) {
this.wine = Wine.get({wineId:this.params.wineId});
this.saveWine = function () {
if (this.wine.id > 0)
this.wine.$update({wineId:this.wine.id});
else
this.wine.$save();
window.location = "#/wines";
}
this.deleteWine = function () {
this.wine.$delete({wineId:this.wine.id}, function() {
alert('Wine ' + wine.name + ' deleted')
window.location = "#/wines";
});
}
}
RouteCtrl defines the routes of the application. Each route is defined by a template that is rendered in <ng:view> inside index.html. There can only be one <ng:view> in a document (more on that later). For example, here is the wine-list.html template:
<ul ng:controller="WineListCtrl">
<li ng:repeat="wine in wines">
<a href='#/wines/{{ wine.id }}'>{{ wine.name }}</a>
</li>
</ul>
The WineListCtrl and WineDetailCtrl controllers provide access to the data using a service defined in services.js as follows:
angular.service('Wine', function ($resource) {
return $resource('api/wines/:wineId', {}, {
update: {method:'PUT'}
});
});
Services provide a great way to abstract your data access logic, and to easily change it without impacting the rest of the application. For example, you could easily change the Wine service to use a Mock service instead of a RESTful service.
ImpressionsI was able to build this application in a very limited amount of time with no prior knowledge of the framework. The data-binding implementation is nice, and, in general, the amount of boilerplate code you have to write is very limited. Frameworks are often a matter of style and personal preferences. Angular.js takes a more declarative approach than other frameworks. Based on this initial experience, I would also describe it as more prescriptive: I didn’t have to spend a lot of time wondering what was the best way to do things as Angular.js tends to have clear utilization patterns. I haven’t spend enough time with the framework to determine if that comes at the cost of less control, and I’d love to hear what other people are thinking.
The only problem I ran into while building the application is the “one route / one view” coupling I alluded to above. As suggested in this thread, you can use <ng:include> to bind partials in the page. The same thread also indicates that multiple <ng:views> per route definition will be supported in the future. I was able to handle the simple UI requirements of this app using one <ng:view> and one <ng:include>. For more complex applications, I’d love the routing infrastructure to allow me to easily and arbitrarily add, remove, change, or animate different elements of the DOM when the route changes in order to support deeper UI transformations. I’m sure there are ways to do this. If Angular.js folks are reading this post, I’d love to hear what they think and what’s coming.
DownloadThe application is available on GitHub here.
You will need the RESTful services to run this application. A PHP version (using the Slim framework) is available as part of the download. If you want to test the application with a Java back-end, you can download the Backbone version here, and reuse its JAX-RS back-end.
Retweet this Share on Facebook Follow @ccoenraets !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");Hoping for a Web App Future
If I think back to 2006/2007 I was very happy with how things were shaking out. The web was on the upswing and we were moving away from native applications. All of the great things about the web–its ubiquity, its freedom, its openness–were being harnessed to create native-like experiences that, I hoped at the time, would see us all do away with native apps. At the time, there wasn’t much (I thought) that web apps couldn’t do that we needed native apps for. How wrong I was. With the introduction of the iPhone, and subsequent smartphone releases, we’ve seen a huge shift back to native applications. Part of that is performance, right now native apps just feel better than mobile web apps, but it also came about because of just how many things native mobile apps could do. Geolocation, accelerometers, contact info–the smartphone showed how many things “apps” needed access to and for the most part those features have been exclusive to native applications. So just as the web was starting to really take off, we’ve slid back into native application territory.
It bummed me out, and still does. I thought AIR was an okay solution to the problem, but by the time AIR came around it was pretty clear that “the web” had come to mean HTML/JS, and I’m fine with that. So as PhoneGap started getting traction, and then Adobe took a major interest in the project, I was excited about the prospect of working on it as an Adobe evangelist, and more importantly, working with the teams behind it to see what else they had up their sleeves as the web moves forward.
But another side benefit is that it’s put me on what I’d consider the “right” side of the web argument. Two things got me thinking more about this. One was a very good post by a VC named Mark Suster, who while not telling his companies to focus exclusively on the web, has told them to make it a big part of what they do. So many startups nowadays are thinking completely mobile-first while ignoring the web, I’d say at their peril. When I think of my own usage, I’m still using a lot of native apps (for reasons I can’t quite figure out) but the ones I enjoy most have a web component that is well done and part of the overall experience. Yelp comes to mind. Another is Untappd. I can do almost anything I need to on the website version of Untappd so it’s not as though I’m getting a watered down experience. It more easily lets me move between contexts and devices while still using the service. I contrast that to something like Foursquare or Path. Both are mobile-centric, and with Foursquare I can’t check in because it wants to be sure that I am where I say I am (using GPS) but it still makes the web side of it less useful for me. Path is unusable when you’re not on a mobile device as far as I can tell. When I log in all I get is “download the app”. Which I hate. Mobile is clearly important but the web can’t be ignored.

If this is what I see when I log into your site, you're too mobile-first.
The second thing that got me thinking more about this was something Brian Leroux pointed to on the Cordova mailing list, a post by Tim Berners-Lee about Installable Web Apps. This is a model I would love to see take hold. As Tim notes, there are a few things that users need to have when they’re installing web apps, and some trust/permissions issues that need to be figured out. Right now, I think PhoneGap is closest to this model, but a huge, huge, part of me wishes PhoneGap didn’t need to exist. If we could somehow skip the native shim and just take for granted that every platform supported, and at its core used, installable web apps. Maybe something like the WebOS model. But we’re not there yet. So for now, I’m glad I get to work with PhoneGap and build apps with web technologies. Eventually though I think PhoneGap can be used as inspiration for installable web apps. This is kind of how the standards world moves, as more and more people adopt something, people find ways to bring that something back into the standards. I think some of PhoneGap’s APIs and methodologies would make a great start at the idea of installable web apps. And I think the guys behind PhoneGap will be at the forefront of making those things happen, which means Adobe is going to be a really cool place to be over the next few years. It feels like there is a lot of potential to change the world and while I miss spending time with Flash, I feel like the HTML/JS/CSS work I’ve been doing and that Adobe is investing in, will make a similar impact on the web down the road.
TweetLooping Audio in Flash, part 2
this is a follow up post to this one.
I’ve continued building on http://blog.andre-michelle.com/2010/playback-mp3-loop-gapless/ . And I’ve come up with some improvements:
- make the loop a separate class
- allow switching from one loop to another seamlessly.
- fix a bug that what harmless in a browser but that broke the app on an iphone. In certain cases the previous “extract” method would read beyond the buffer causing the looping to stop.
See below for the code.
I apologize for the formatting, just copy and paste it and you should be able to read it properly.
To use it you still need to calculate the number of samples (see previous post).
For example:
const out: Sound = new Sound(); // Use for output stream
var loop:Mp3Loop = new Mp3Loop(out);
loop.loadMp3(“yourloop.mp3″, 213120l);
package
{
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.MouseEvent;
import flash.events.ProgressEvent;
import flash.events.SampleDataEvent;
import flash.media.Sound;
import flash.net.URLRequest;
import flash.utils.ByteArray;
public class Mp3Loop
{
private const MAGIC_DELAY:Number = 2257.0; // LAME 3.98.2 + flash.media.Sound Delay
private const BUFFER_SIZE: int = 4096; // Stable playback
// Use for decoding
private var _activeMp3: Sound;
private var _inactiveMp3: Sound;
private var _inactiveMp3SamplesTotal:uint;
private var _activeMp3SamplesTotal:uint;
// Use for output stream
private var _out: Sound;
private var _samplesPosition: int = 0;
private var _swapPending:Boolean;
private var _isPlaying:Boolean;
public function Mp3Loop(outputSound:Sound)
{
_out = outputSound;
_out.addEventListener( SampleDataEvent.SAMPLE_DATA, sampleData );
_out.play();
}
public function loadMp3(url:String, samplesTotal:uint):void{
_inactiveMp3SamplesTotal = samplesTotal;
_inactiveMp3 = new Sound();
_inactiveMp3.addEventListener( Event.COMPLETE, mp3Loaded, false, 0, true );
_inactiveMp3.addEventListener( IOErrorEvent.IO_ERROR, mp3Error, false, 0, true );
_inactiveMp3.load( new URLRequest(url) );
}
private function swap():void{
_swapPending = false;
_activeMp3 = _inactiveMp3;
_inactiveMp3 = null;
_activeMp3SamplesTotal = _inactiveMp3SamplesTotal;
_inactiveMp3SamplesTotal = 0;
}
private function mp3Loaded( event:Event ):void
{
if(!_isPlaying){
swap();
_isPlaying = true;
}else{
//loop is playing, wait for end
_swapPending = true;
}
}
private function sampleData( event:SampleDataEvent ):void
{
if(_isPlaying )
{
extract( event.data, BUFFER_SIZE );
}
else
{
silent( event.data, BUFFER_SIZE );
}
}
/**
* This methods extracts audio data from the mp3 and wraps it automatically with respect to encoder delay
*
* @param target The ByteArray where to write the audio data
* @param length The amount of samples to be read
*/
private function extract( target: ByteArray, length:int ):void
{
while( 0 &amp;lt; length )
{
if( _samplesPosition + length + MAGIC_DELAY &amp;gt; _activeMp3SamplesTotal )
{
var read: int = _activeMp3SamplesTotal - _samplesPosition - MAGIC_DELAY;
_activeMp3.extract( target, read, _samplesPosition + MAGIC_DELAY );
_samplesPosition += read;
length -= read;
}
else
{
_activeMp3.extract( target, length, _samplesPosition + MAGIC_DELAY );
_samplesPosition += length;
length = 0;
}
if( _samplesPosition == _activeMp3SamplesTotal - MAGIC_DELAY) // END OF LOOP &amp;gt; WRAP
{
_samplesPosition = 0;
if(_swapPending){
swap();
}
}
}
}
private function silent( target:ByteArray, length:int ):void
{
target.position = 0;
while( length-- )
{
target.writeFloat( 0.0 );
target.writeFloat( 0.0 );
}
}
private function mp3Error( event:IOErrorEvent ):void
{
trace( event );
}
public function get isPlaying():Boolean
{
return _isPlaying;
}
public function stop():void{
_inactiveMp3 = _activeMp3 = null;
_inactiveMp3SamplesTotal = _activeMp3SamplesTotal = 0;
_isPlaying = false;
_samplesPosition = 0;
}
}
}
Heroku at Jfokus and Spring I/O 2012
In just a few weeks I’ll be over in Europe presenting about Heroku at two fantastic Java conferences. First up is Jfokus in Stockholm! On February 14 at 20:00 I will be leading a Cloud Conversations BoF. Then on February 15 at 11:10 I will be speaking about how to “git push” Java & Play! Apps to the Cloud. This will be my first time speaking at Jfokus and I’m really excited because I’ve heard such great things.
On Thursday Feb 16 I will be at Spring I/O in Madrid speaking about Running Spring Apps on the Cloud with Heroku at 12:40.
Hope to see you there!
Book Review: JBoss AS 7: Configuration, Deployment, and Administration
I eagerly accepted Packt Publishing's invitation to review JBoss AS 7: Configuration, Deployment, and Administration because it has been several years since I last used JBoss and I was curious to learn more about JBoss AS 7. I have already written about my First Impressions of Book 'JBoss AS 7 Configuration, Deployment and Administration' and in this post I review the book in greater detail while attempting to minimize how much I repeat from that post. My review is based on an electronic (PDF) copy of JBoss AS 7: Configuration, Deployment, and Administration.
General FeaturesJBoss AS 7: Configuration, Deployment, and Administration highlights particularly important notes and warnings within boxing that makes them obvious and with an icon representing a pencil and paper. Similarly, tips and tricks also attract special attention with similar boxing and with a light bulb icon. It is helpful to have the most important notes and tips and tricks highlighted like this.
It didn't take much reading of this book to realize how significantly new JBoss AS 7's architecture is. One of the strengths of JBoss AS 7: Configuration, Deployment, and Administration is its comparisons of previous versions of JBoss AS to JBoss AS 7. These comparisons help to understand how changed JBoss AS 7 is and should be especially helpful to anyone migrating to JBoss AS 7 from a previous version.
This book provides several tables of various configuration options and their descriptions. These tables provide easy reference for various configuration options. Although I mostly just skimmed these as I read this book, I noted their existence for future reference when configuring various parts of JBoss AS 7.
Command line interfaces and script-based configuration and administration are emphasized throughout the book. I appreciate this because I tend to use command line approaches far more frequently than I use graphical tools, but some books focus almost exclusively on the graphical tools.
Perhaps the greatest strength of JBoss AS 7: Configuration, Deployment, and Administration is its focus on what its title promises: configuration, deployment, and administration. Although this book does provide brief introductory details about Java EE, the book assumes that the reader will look to focused books or tutorials for detailed information on Java EE. This allows the book to focus on administration and configuration of and deployment to JBoss AS 7.
Although examples in the book specifically use Eclipse, MySQL, and Windows, the descriptions and explanations are broad enough to cover other choices of IDE, database, and operating system respectively. The illustrations assuming one of these are relatively rare and most of the discussion is more general to JBoss AS 7 rather than to any of these supporting products. In many of these cases, alternatives (and how to use those alternatives) are mentioned. The final chapter (cloud computing with OpenShift) and the Appendix (common commands and operations) provide Linux-based examples.
There is a small number of typos and a few instances of questionable sentence structure, but the author's writing style generally flows easily and is easy to follow. There are numerous drawings, tables, and screen snapshots to illustrate points and highlight the more important details. I like the significant white space and the call outs for special notes and observations.
Chapter 1: Installing JBoss AS 7Because I have not used JBoss for several years, I needed to install JBoss AS 7 and this chapter provides an easy guide to doing that. The chapter begins with brief coverage of the usefulness of Java EE application servers and of JBoss AS 7's high-level design. It then moves into the practical steps necessary for installing JBoss AS 7. The author recommends in one of the "important notes" that readers download and use the Java 6 SDK, but does acknowledge that Java SE 7 SDK is available and should work fine with JBoss AS 7. The chapter discusses installation on Windows and Linux/Unix and even includes a "tip/trick" highlighting of installation on Windows Vista. The chapter goes beyond basic installation (which amounts to uncompressing archive files) to discuss starting and stopping JBoss AS 7 and using Command Line Interface (CLI) to connect to it locally and remotely.
The initial chapter also discusses installation of Eclipse ("the development environment used in this book"). Besides downloading and installing Eclipse (Indigo), the chapter also discusses installation of the JBoss AS plugins (part of JBoss Tools) for Eclipse.
One of my favorite parts of this initial chapter is its coverage of the application server's directory structure and differentiation of JBoss AS 7's "standalone servers and domain servers." This was an important distinction for me coming back to JBoss after such a long period of time, but was an easy one to grasp because of my familiarity with GlassFish. After differentiating between the types of servers supported in JBoss AS 7, the section concludes with coverage of several significant directories/folders in the JBoss AS 7 installation.
Chapter 2: Configuring the Application ServerWith JBoss AS 7 and tools (Eclipse) installed, it is natural to move onto configuring the JBoss AS 7 instance. This chapter had some surprises for me, including starting with this: "The application configuration has also been renewed, moving from a large set of XML files to a single monolithic file." The chapter discusses this single file and covers its default names (depending on server configuration). It goes through the configuration file one major section at a time, detailing how to configure the server in each area. There is quite a bit in this chapter on configuring logging. Another thing I learned here that has changed in JBoss in recent years is default use of its own logging framework.
Chapter 3: Configuring Enterprise ServicesThe third chapter is on configuring enterprise services. This chapter specifically focuses on configuring database connectivity, EJB container, messaging service, and transaction service.
The section of Chapter 3 on configuring database connectivity mentions that JBoss AS 7 comes with the H2 open source database server built in, but then uses MySQL for its examples. I liked how this chapter compared and contrasted how database configuration was performed in previous versions of JBoss AS to how it is now done in JBoss AS 7. The chapter demonstrates XML-based configuration of a data source (and how it was similar to that used in previous versions of the JBoss application server), but then also shows how to use the Java EE 6 annotation @DataSourceDefinition to programmatically configure the data source in conjunction with an EJB 3.1 Singleton EJB.
Chapter 3's section on configuring the EJB container starts by introducing the basics of EJBs with specific introductory focus on the "new EJB 3.1 variants introduced by Java EE 6": Singleton EJB, No-Interface EJB, and Asynchronous EJB. The chapter discusses in detail how to configure the different types of EJBs. It also points out the built-in JMS support in JBoss AS 7 provided by HornetQ. It also covers configuration related to JBoss AS 7's/HornetQ's use of Netty.
The section of Chapter 3 on configuring transactions introduces the Java Transaction API. It then explains how to configure the JTA support for timeouts and statistics gathering.
Chapter 4: JBoss Web Server ConfigurationThe focus of the fourth chapter of JBoss AS 7: Configuration, Deployment, and Administration is on configuration of the JBoss web server (JBoss Web), which is based on a fork of Tomcat 7. The chapter discusses HTTP connectors, including JBoss Web's built-in Coyote HTTP 1.1 connector and the Apache Portable Runtime (APR) connector. The chapter shows how to separately download and use the ARP connector with JBoss AS 7.
The chapter of JBoss Web server covers configuration of static (HTML/images) and dynamic (JSP) resources and then moves onto discussion of deploying JavaServer Faces (JSF)-based applications on JBoss AS 7. The author points out: "Currently, JBoss AS 7 supports the JSF release 2.1 using the Mojarra implementation, although there are plans for supporting MyFaces implementation too." The chapter then demonstrates using Eclipse to create a JSF project and adding an EJB layer to that application. The chapter also demonstrates adding JPA-based persistence (including how to switch the JPA provider from default Hibernate 4), setting a custom web context, and deploying the web application.
Chapter 5: Configuring a JBoss AS DomainThe fifth chapter concludes the chapters on configuration by providing a more detailed look at configuring JBoss AS 7 domains. Of particular interest to me is the sections on configuring the JVM and providing JVM options. I also found the author's use of VisualVM to be helpful. This detailed chapter introduces domain terminology, explains what a domain is, and explains why a domain does not provide the same functionality or purpose as node clustering. It provides thorough detail on configuring domains.
Chapter 6: Deploying Applications on JBoss AS 7Deployment to JBoss AS 7 is the focus of Chapter 6. The chapter begins with an introduction to JAR, WAR, EAR, RAR, and SAR files and then goes onto more detailed (but still thankfully brief) coverage of the first three types of archive files.
After covering JAR, WAR, and EAR, the chapter moves onto coverage of manual and automatic deployments to JBoss AS 7. I was happy to see coverage of using CLI to deploy from the command line, but fans of deploying via web page will be happy to know that there is also coverage of deploying from the web administration console. The chapter also demonstrates deploying from the Eclipse IDE.
The most significant bane of my Java development experience has probably been classloaders, which become tricky when application servers, IDEs, and frameworks like Spring are involved. With this in mind, I was happy to see a section in the sixth chapter called "JBoss AS 7 classloading explained." Several pages are devoted to using JBoss's provided mechanism for appropriately dealing with classes used by the application server as well as the deployed applications. The chapter also talks about using Java EE's standard approach of specifying Class-Path in the MANIFEST.MF file.
Chapter 7: Managing the Application ServerThe seventh chapter focuses on managing JBoss AS 7 via the command line-based CLI tool and the web-based Web admin console. Differentiation is made between CLI commands and CLI operations. I find the sections "Executing CLI scripts in batch" and "Executing scripts in a file" to be particularly interesting from a CLI perspective. The first section talks about CLI support for a group of commands as an atomic unit and the second section talks about writing file-based administration scripts. The book further peaks my interest in CLI by explaining how to take snapshots in CLI and how to display CLI history.
Although I find that I use command line-based tools for configuration, administration, and deployment of an application server in the long-run, web-based or other graphically-oriented tools are often nice when first using an application server or when trying to figure new things out. In other words, I prefer command line scripting for routine tasks and prefer graphically-oriented administrative tools for new or unusual tasks. The second half of Chapter 7 covers using "The new Web admin console."
Chapter 7's coverage of the history of JBoss's web administrative consoles is a good example of how the overall book does a nice job of comparing and contrasting different versions of JBoss tools. The chapter points out the advantages and limitations of the jmx-console approach (versions of JBoss up to JBoss 4.x) and the Seam-based Web admin console (JBoss 5.x and 6.x) before covering JBoss AS 7's GWT-based Web admin console. As one would expect, the section on Web admin console is filled with screen snapshots demonstrating the Web admin console in action.
Chapter 8: ClusteringOne of the things many of us want from our application server is clustering functionality, which is the theme of Chapter 8 (load balancing of web applications is covered in the next chapter). The chapter points out several facets of clustering that have changed in JBoss AS 7. It also covers how JGroups and Infinispan are used to implement JBoss clustering. This is an information--packed chapter that I will be sure to read again before using JBoss AS 7 clustering.
Chapter 9: Load-balancing Web ApplicationsChapter 9 covers load-balancing of web applications. The chapter only briefly covers installation of Tomcat's mod_jk and Apache's mod_proxy to connect the Apache web server to JBoss AS 7 because "the installation of either mod_jk or mod_proxy does not differ from earlier AS releases." The remainder of the chapter focused on load balancing covers mod_cluster (new to JBoss AS 7). The chapter concludes by returning to discussion of clustering. The author references the JBoss AS 7.1 High Availability Guide for continuing developments related to JBoss AS 7's clustering support.
Chapter 10: Securing JBoss AS 7Chapter 10 of JBoss AS 7: Configuration, Deployment, and Administration is focused on security, an increasingly popular topic. Reading about security is often my best cure for insomnia, but there were some interesting nuggets in this chapter that kept my attention.
The chapter introduces PicketBox (formerly known as JBoss Security), the security framework upon which JBoss AS 7's security is built. It then provides a basic overview of Java's security API and provide definitions of key security terms in a Java EE context. This thorough chapter covers a wide range of security-related topics as they pertain to JBoss AS 7.
Chapter 11: Taking JBoss AS 7 in the CloudThe final chapter is devoted to the trendiest topic of them all: cloud computing. The central focus of this chapter is Red Hat's OpenShift (PaaS). The author does as good a job as I have seen of describing cloud computing and I particularly liked the contrasting of cloud computing to grid computing. The majority of the chapter discusses starting with OpenShift Express and then transitioning to OpenShift Flex.
AppendixThe Appendix is six pages of "common commands and operations" that provides an easy access reference. Although the shown commands use Linux script jboss-admin.sh, the alternative for Windows (jboss-admin.bat) is shown at the beginning of the appendix. The subsections of the appendix are Startup Options, General Commands, Domain Mode, JMS, Data sources, mod_cluster, Batch, and Snapshots.
ConclusionJBoss AS 7: Configuration, Deployment, and Administration delivers what it's title promises: an introduction and in-depth coverage of configuring and administrating and deploying to JBoss AS 7. Along the way, the book manages to provide differences in JBoss AS 7 from previous versions and to provide introductory details about aspects of Java EE supported in JBoss AS 7. This is not the book one would learn how to write JavaServer Pages, JavaServer Faces applications, EJBs, or other Java EE code from. However, it is the book one would learn how to deploy a Java EE application to JBoss AS 7 and how to maintain and configure JBoss AS 7 to most efficiently support Java EE applications.
Other ReviewsOther reviews of JBoss AS 7: Configuration, Deployment, and Administration are available. These include Markus Eisele's Review: "JBoss AS7 Configuration, Deployment and Administration" by Francesco Marchioni, Rick Wagner's Book Review for "JBoss AS 7 Configuration Deployment and Administration" (unfinished version of the book), Maksim Sorokin's [PACKT] JBoss AS 7 Configuration, Deployment and Administration (announcing review coming), and David Salter's Forthcoming Book Review (announcing review coming).
Original posting available at http://marxsoftware.blogspot.com/ (Inspired by Actual Events)
Displaying static maps on the Windows Phone for performance and scenario wins
One of the nice visuals of 4th & Mayor is the animation and display of a simple area map whenever you view a place in the app.
Unfortunately, most map controls, such as the Bing Maps control included with the platform, are highly sophisticated: they let you have a bunch of pushpins, gather information about bounding boxes, etc. This awesome feature set can have a negative effect on performance.
2/1/2012 Update: Thanks to Tim Heuer, who just provided a pull request that adds an OpenStreetMap provider, MapQuest provider, offers the ability to add an authentication key optionally as a property on the control, and to specify the type of maps. I’ve updated NuGet to 1.1 with these contributions, thanks!
My static map control is simple but nice because it’s an easy replacement, can be used in Panorama/Pivots, and overall still has a great, high-speed experience that your users will enjoy.
A sample static Bing Map from 4th & Mayor: touching the map takes you to an interactive map view page allow for directions, panning, etc.
I’ve refactored one of the libraries used in my app to be general enough for others to use: it offers simple static map code in the form of a “StaticMap” control: just drop it into your XAML page and you’re mostly good to go.
The MapCenter property takes a GeoCoordinate, either data bind it or set the property as the page is navigated to.
Over time I’ll consider adding more of the functionality I’ve had to the library, including the interactive libraries.
Get the libraryI’m using my favorite pair of deployment places for this library: GitHub for source, NuGet for binaries.
NuGetThe library is JeffWilcox.Maps
Source on GitHubFork the repo, wp-maps
Offering an interactive experienceTo optimize the maps experience, I instead decided to use the static map REST APIs from Bing Maps for my mobile application: this lets me perform a HTTP request, grab the image, and data bind it into my display.
I then place it inside a borderless, retemplated Button control, so that touching the map takes you to a new page: an experience where I can show the real Bing Maps control, your current position, as well as the location of the place you are trying to go. By moving this to a separate assembly, I get great performance wins: the Bing Maps control and other code needed to offer the rich interactive experience is delay loaded and only there when needed.
Properties on the controlThese properties are on the initial version of the control:
Foreground is supported and used for the implicit, centered point: it’s Black by default to match the Windows Phone’s “Maps” app, but I find that using {StaticResource PhoneAccentBrush} looks great in my opinion.
MapCenter takes a GeoCoordinate, this is a key property.
ZoomLevel sets the zoom level (default of 15 I think) for the map. 1 effectively shows a bunch of the world, and 21 shows street level sizes. The zoom levels for Goog and Bing are pretty similar.
MapCenterVisibility defaults to Visible, and if you decide you don’t want the center point to be on the view, just set this to Collapsed.
IsSensorCoordinate should be data bound, some APIs (like Google’s) require that the API call identify whether it’s a position from a sensor, or a database. In my case, sensor is used for any GeoCoordinateWatcher/LocationService code, while I set it to False for data from the Foursquare venues database where I get info about a place.
Provider sets the static map provider to use.
The height and width are automatically identified by the system, but many APIs limit the width and height to small numbers (typically <= 640 pixels in any direction), FYI.
Bing Maps API KeyIf you’re using Bing Maps, you’ll need a Bing Maps API key and to make sure that your app is compliant with the requirements of its terms and conditions. This is the same key you use with the Bing Maps control.
For this first version you have to set the API key as a string resource inside your App.xaml file.
Here’s how you would go about this: add the namespace and set the string – I’ve put a comment where your key should go in App.xaml:
<Application
x:Class="StaticMapSample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:core="clr-namespace:System;assembly=mscorlib">
<!--Application Resources-->
<Application.Resources>
<core:String x:Key="BingMapsKey"><!-- Place your Bing Maps API key here--></core:String>
</Application.Resources>
<Application.ApplicationLifetimeObjects>
<!--Required object that handles lifetime events for the application-->
<shell:PhoneApplicationService
Launching="Application_Launching" Closing="Application_Closing"
Activated="Application_Activated" Deactivated="Application_Deactivated"/>
</Application.ApplicationLifetimeObjects>
</Application>
I haven’t decided if this is better or worse than just exposing an API key property for you to bind or set on the page, but I really like just having one central place in an app to put the key.
Static map providersThe initial implementation has a simple enum for chosing between two provider choices, Bing Maps and Google Maps. I’ve decided to include Google Maps because it turns out that in some parts of the world, Google Maps are much better, and I’ve had hundreds of app users ask for a setting to instead use Google Maps. There are slightly different requirements for its API, such as exposing an “open in web browser” function so that the user could decide to open the same map view in the browser on the phone.
Just set the Provider property on the StaticMap to either Bing or Google. The default is Bing, as it should be!
Here’s a screenshot of the sample app I’ve included in the GitHub repo (though if you use it, remember to put your Bing Maps API key inside of the App.xaml file first!) – it has both Bing and Google Maps, and the application bar is hooked up to events to open the Maps app on the phone or to open the browser with the appropriate map page. Take a look.
On the right, the expanded app bar: your app may need to expose the “open in browser” option to comply with the terms and conditions that you interpret on the maps API of your choice. Also, the “open in maps app” is a nice function to provide users who want to open the location in the main OS’s Maps app.
Design note: flush mapsOne design technique that I use in my app, as does the “Local Scout” app in Mango, is having a “flush” map experience: the map extends to the edge of the phone, instead of the standard spacing with margins from the edges of the phone.
This visual effect looks great, and can in general be created by setting the Margin of the control to “-12,0,-12,0”.
Hope this helps.
Yet Another Podcast #58–Julie Lerman and EF/CF
For the complete article and hyperlinks, please visit my blog at http://JesseLiberty.com
I Hear Voices: JavaFX 2.1 Developer Preview for Linux
Backbone.js Lessons Learned and Improved Sample App
A few weeks ago, I posted a three-part Backbone.js tutorial (part 1, part 2, part 3). Since then, I spent more time building a real-life application with Backbone. I ran into a number of interesting problems, spent time thinking about solutions, and decided to write them down in this post. These are not definitive answers, just my current thoughts… and as always, I value your input.
Based on this new experience, I revisited the Wine Cellar application used in my tutorial. You can find the improved version here (PHP back-end) or here (Java back-end).
Externalizing TemplatesIn the initial implementation of my wine cellar app, I “inlined” my templates in a succession of <script> tags like the one below inside index.html.
<script type="text/template" id="wine-list-item"> <li><a href='#wines/<%= id %>'><%= name %></a></li> </script>
This approach works fine for a simple application with a limited number of templates. In a larger project, it makes templates hard to maintain. It also makes it difficult for multiple developers to work on different templates at the same time. Removing the script body and adding a src attribute to point to an external file didn’t seem to work to load HTML templates.
In this StackOverflow thread, Brian Genisio suggests loading external templates as string variables in a .js file. Using this approach, a template definition looks like this:
app.templates.view = " \
<h3>something code</h3> \
";
That’s certainly a valid approach, but depending on your circumstances, it may still not be the ideal solution: long string concatenation is painful (especially for larger templates). In addition, if you define HTML in string variables, you will probably not be able to benefit from the HTML capabilities of your editor.
Other people load external templates using Require.js and the text plugin, which is definitely an approach worth considering for larger projects. In my case, I didn’t feel that the size of my project mandated it.
In the end, I decided to write my own simple template loader. It is implemented as follows:
tpl = {
// Hash of preloaded templates for the app
templates: {},
// Recursively pre-load all the templates for the app.
// This implementation should be changed in a production environment:
// All the template files should be concatenated in a single file.
loadTemplates: function(names, callback) {
var that = this;
var loadTemplate = function(index) {
var name = names[index];
console.log('Loading template: ' + name);
$.get('tpl/' + name + '.html', function(data) {
that.templates[name] = data;
index++;
if (index < names.length) {
loadTemplate(index);
} else {
callback();
}
});
}
loadTemplate(0);
},
// Get template by name from hash of preloaded templates
get: function(name) {
return this.templates[name];
}
};
I use it to preload all my templates before bootstrapping Backbone:
tpl.loadTemplates(['header', 'wine-details', 'wine-list-item'], function() {
app = new AppRouter();
Backbone.history.start();
});
Loading templates separately is great during development: you can modify and test individual templates without requiring a “build” or the concatenation of multiple template files. In production however, loading dozens of templates as separate HTTP requests can be a serious bottleneck. So when you are ready to move to production, it’s a good idea to somehow combine all your templates in a single file so that you can load them all with a single HTTP request.

Decouple Views from other DOM elementsIn the initial version of my application, I didn’t pay much attention to the way I chose the “el” or “tagName” of my Views. I often assigned the View’s “el” to an existing element of the document.
“Before” code:
window.WineView = Backbone.View.extend({
el: $('#content'),
render: function(eventName) {
$(this.el).html(this.template(this.model.toJSON()));
return this;
}
});
… and here is the Router’s code that instantiated and displayed a WineView:
new WineView().render();
After more careful consideration, I realized that this approach wasn’t very good. The View is not fully encapsulated: it “reaches out” to an attribute (element) of the containing document (‘#mainArea’), creating an undesirable dependency. A better approach is to make sure a View doesn’t know about its hosting document. It should not know about (or assume the presence) of other elements in the document. The knowledge of the View should be limited to the elements in its own template. That will make the view reusable in many different contexts. The corollary of this rule is that a View shouldn’t attach itself to a DOM element in its render() method. The render() method should be limited to populating its own “detached” el attribute. The code that invokes the View’s render() method can then decide what to do with the View’s HTML fragment: attach it, append it, etc. The View is therefore more reusable and more versatile.
“After” code:
window.WineView = Backbone.View.extend({
tagName: "div", // Not required since 'div' is the default if no el or tagName specified
render: function(eventName) {
$(this.el).html(this.template(this.model.toJSON()));
return this;
}
});
… and here is the Router’s code that instantiates and displays a WineView defined as above:
$('#content').html( new WineView().render().el );
Cleaning Up: Avoiding Memory Leaks and Ghost Views
Before getting rid of a view, you need to clean up, which mainly consists of removing the bindings that could prevent the View from being properly destroyed. A View that is not properly destroyed becomes a “Ghost View”: you don’t see it, you think it’s gone, but it still manifests itself in some unpleasant ways: its events are still firing and it still uses memory (memory leaks). Ghost Views often first manifest themselves in the form of events firing multiple times.
In my initial implementation, I provided views with a close() method that took care of cleaning up. There was nothing wrong with that approach except that you had to remember to call the close() method!
Derick Bailey has a great post on this topic and provides a more generalized approach: It consists of adding a generic close() method to the Backbone View prototype. I borrowed Derick’s approach and implemented my generic close() method as follows:
Backbone.View.prototype.close = function () {
if (this.beforeClose) {
this.beforeClose();
}
this.remove();
this.unbind();
};
The call to beforeClose() (if it exists in the view) is a hook to add some view-specific cleanup code if required.
In your Router, you then create new Views by invoking a custom showView() method that invokes close() on the currentView before replacing it with the new View.
showView: function(selector, view) {
if (this.currentView)
this.currentView.close();
$(selector).html(view.render().el);
this.currentView = view;
return view;
}
Note that this is only part of the solution. For example, if you have composite views (views containing other views), you still have to make sure you close the “child” views when the parent view is closed. A good approach here is for the parent view to keep track of its child views so that it can call their respective close() methods when its own close() method is invoked. The beforeClose() method (explained above) of the parent View is a good place to close the child Views.
Route pre-processing (aka Filters)Backbone’s Router is great at routing requests to the important/stateful/bookmarkable locations in your application.
When defining the routes in my application, I sometimes find myself in a situation where a pre-condition has to be met before a route can be taken.
For example:
- Some routes may require the user to be authenticated.
- Some routes may require some data to be loaded.
It’s easy to verify the pre-condition in the method that implements a specific route. That’s what I did in the initial version of my application. But in a larger application, this approach will quickly start cluttering your route methods.
My instinct was to look for a “Filter” feature in the Backbone Router API, but it doesn’t currently exist out-of-the-box, and in this thread, Jeremy makes the case that the same result can be achieved using underscore’s _.wrap() method.
_.wrap() didn’t work for me because my pre-condition involved asynchronous processing and I can only pass control back to the routing method after the successful completion of my async code.
In the end, I implemented a simple/low-tech before() method that is somewhat similar to wrap() but supports async chaining.
var AppRouter = Backbone.Router.extend({
routes: {
"wines/:id" : "wineDetails"
},
wineDetails: function(id) {
this.before(function() {
var wine = app.wineList.get(id);
app.showView( '#content', new WineView({model: wine}) );
});
},
showView: function(selector, view) {
if (this.currentView)
this.currentView.close();
$(selector).html(view.render().el);
this.currentView = view;
return view;
},
before: function(callback) {
if (this.wineList) {
if (callback) callback();
} else {
this.wineList = new WineCollection();
this.wineList.fetch({success: function() {
$('#sidebar').html( new WineListView({model: app.wineList}).render().el );
if (callback) callback();
}});
}
}
});
This solution is not as “decoupled” as a traditional filter implementation would be, but it allowed me to unclutter my code in a way that was suitable for my requirements. Jake Dempsey
has built a more traditional filter implementation here that you may want to take a look at.
The source code for this application is hosted on GitHub. The application uses RESTful services to access the data.
For a version of this application using a PHP back-end, use this project (use the ‘final’ folder for the version of the application discussed in this article.
For a version of this application using a Java back-end (using JAX-RS), use this project.
Retweet this Share on Facebook Follow @ccoenraets !function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");Try the New Play Framework Heroku Plugin
I just published a Heroku Plugin for Play Framework. Right now it just deploys a Play app to Heroku. Try it out:
- Signup for a Heroku account
- Install the Heroku plugin locally:
$ play install heroku
- Create a Play (1.2.3 or 1.2.4) app:
$ play new foo --with heroku
- Deploy the app:
$ play heroku:deploy foo
You should see something like:
~ _ _ ~ _ __ | | __ _ _ _| | ~ | '_ \| |/ _' | || |_| ~ | __/|_|\____|\__ (_) ~ |_| |__/ ~ ~ play! 1.2.4, http://www.playframework.org ~ ~ Deploying app to Heroku Listening for transport dt_socket at address: 8000 Project directory: /home/jamesw/Desktop/foo Read Heroku API key from /home/jamesw/.heroku/credentials Created new ssh key pair (heroku_rsa) in: /home/jamesw/.ssh Added the heroku_rsa.pub ssh public key to your Heroku account Created a .git directory for your project Added and committed all of the local changes to the git repo Created app: cold-night-1511 http://cold-night-1511.herokuapp.com/ Added git remote: git@heroku.com:cold-night-1511.git Deploying application via git push Application deployed ~ App Deployed
Note: I haven’t figured out how to pipe the git push output to the screen yet, so be patient when the app is being git pushed. It’s working, just takes a minute.
- Check out your Play app running on the cloud! Use the URL in the “heroku:deploy” output. This should work with new and existing Play apps.
All of the code for the Heroku Play module is on GitHub. There is more I want to do with this (scaling, logs, etc) and your contributions are certainly welcome! Keep checking back here for updates and let me know how it goes!
JavaFX 2 Presents the Quadratic Formula
I recently needed to check some homework answers related to use of the quadratic formula. After realizing that it was getting tedious to do these by hand, I thought of using my calculator to solve them. However, I realized that I could write a simple application using JavaFX to calculate the results and that approach seemed more interesting than using the calculator. This post demonstrates that simple application and provides the relatively straightforward code required to make it happen.
The next couple of screen snapshots demonstrate the simple application in example. They include the initial appearance of the application followed by a couple images showing different values calculated by the application.
The last screen snapshot shows the output when one of the coefficients provided does not allow the quadratic formula to be applied. To provide this application slightly broader application than solely quadratic equation solving, I have added code to detect when the 'a' coefficient is zero and the 'b' coefficient is non-zero. This is a linear equation and the simple application solves it as well as the quadratic equations provided. The next screen snapshot demonstrates the output when coefficients for a linear equation are provided.
The first code listing has nothing to do with the JavaFX presentation layer, but is instead a simple call that provides the basic back-end quadratic formula calculations. I include it here because it is use by the JavaFX example application. It is somewhat interesting in its own right because there are so many ways to calculate a square root in Java. The best-known approach is to use Math.sqrt(double), but the choices are often more varied when using BigDecimal instead of double. Because the purpose of my post is to focus on the JavaFX aspect of this and because my chosen approach is accurate enough for its purposes, I've taken the "easy way" out here and simply use Math.sqrt(double).
SimplisticQuadraticFormula.java
package dustin.examples;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
/**
* Class encapsulating quadratic formula implementation.
*
* @author Dustin
*/
public class SimplisticQuadraticFormula
{
/** Default precision used for specifying scale. */
private static final int DEFAULT_PRECISION = MathContext.DECIMAL64.getPrecision();
/** Convenient representation of zero as BigDecimal. */
private static final BigDecimal ZERO = new BigDecimal("0");
/** Convenient representation of two as BigDecimal. */
private static final BigDecimal TWO = new BigDecimal("2");
/** Convenient representation of four as BigDecimal. */
private static final BigDecimal FOUR = new BigDecimal("4");
/**
* Calculate intercepts with x-axis.
*
* @param a Coefficient 'a' from a quadratic equation to be solved.
* @param b Coefficient 'b' from a quadratic equation to be solved.
* @param c Coefficient 'c' from a quadratic equation to be solved.
* @return The x-intercepts or solutions to the quadratic equation (two values)
* or a single value if solution to a linear equation. Note that two
* solutions are always provided for quadratic equations even if they are
* the same.
* @throws NumberFormatException Thrown when x-intercepts cannot be calculated.
*/
public static List<BigDecimal> calculateXIntercepts(
final BigDecimal a, final BigDecimal b, final BigDecimal c)
{
final List<BigDecimal> intercepts = new ArrayList<BigDecimal>();
if (a.compareTo(ZERO) == 0 && b.compareTo(ZERO) == 0)
{
// neither quadratic nor linear
throw new NumberFormatException("Must have coefficient for one of x terms.");
}
else if (a.compareTo(ZERO) == 0) // linear equation
{
intercepts.add(c.setScale(DEFAULT_PRECISION).negate().divide(b, RoundingMode.HALF_UP));
}
else
{
final BigDecimal intercept1 =
calculateNumeratorWithAddition(a, b, c)
.divide(calculateDenominator(a), RoundingMode.HALF_UP);
intercepts.add(intercept1);
final BigDecimal intercept2 =
calculateNumeratorWithSubtraction(a, b, c)
.divide(calculateDenominator(a), RoundingMode.HALF_DOWN);
intercepts.add(intercept2);
}
return intercepts;
}
/**
* Calculate axis of symmetry, if applicable.
*
* @param a Coefficient 'a' from a quadratic equation to be solved.
* @param b Coefficient 'b' from a quadratic equation to be solved.
* @return The "x" axis of symmetry.
* @throws NumberFormatException Thrown if the provided 'a' coefficient is
* zero because cannot divide by zero.
*/
public static BigDecimal calculateAxisOfSymmetry(final BigDecimal a, final BigDecimal b)
{
if (a.compareTo(ZERO) == 0)
{
throw new NumberFormatException(
"Cannot calculate axis of symmetry based on x-intercepts when a is zero.");
}
return b.setScale(DEFAULT_PRECISION).negate().divide(a.multiply(TWO), RoundingMode.HALF_UP);
}
/**
* Calculate numerator of quadratic formula where the terms are added.
*
* @param a Coefficient 'a' from a quadratic equation to be solved.
* @param b Coefficient 'b' from a quadratic equation to be solved.
* @param c Coefficient 'c' from a quadratic equation to be solved.
* @return Value of numerator in quadratic formula where terms are added.
* @throws NumberFormatException Thrown if no real solution is available.
*/
private static BigDecimal calculateNumeratorWithAddition(
final BigDecimal a, final BigDecimal b, final BigDecimal c)
{
return b.negate().add(calculateSquareRootPortion(a, b, c));
}
/**
* Calculate numerator of quadratic formula where the terms are subtracted.
*
* @param a Coefficient 'a' from a quadratic equation to be solved.
* @param b Coefficient 'b' from a quadratic equation to be solved.
* @param c Coefficient 'c' from a quadratic equation to be solved.
* @return Value of numerator in quadratic formula where terms are subtracted.
* @throws NumberFormatException Thrown if no real solution is available.
*/
private static BigDecimal calculateNumeratorWithSubtraction(
final BigDecimal a, final BigDecimal b, final BigDecimal c)
{
return b.negate().subtract(calculateSquareRootPortion(a, b, c));
}
/**
* Calculate denominator of quadratic formula.
*
* @param a Coefficient of 'a' from a quadratic equation to be solved.
* @return Value of denominator in quadratic formula.
* @throws NumberFormatException Thrown in 0 is provided for coefficient 'a'
* because denominator cannot be zero.
*/
private static BigDecimal calculateDenominator(final BigDecimal a)
{
if (a.compareTo(ZERO) == 0)
{
throw new NumberFormatException("Denominator cannot be zero.");
}
return a.multiply(TWO);
}
/**
* Calculates value of square root portion of quadratic formula.
*
* @param a Coefficient 'a' from a quadratic equation to be solved.
* @param b Coefficient 'b' from a quadratic equation to be solved.
* @param c Coefficient 'c' from a quadratic equation to be solved.
* @return The square root portion of the quadratic formula applied with
* the three provided co-efficients.
* @throws NumberFormatException Thrown if there is no solution (no
* intersection of the x-axis) or if a number is encountered that cannot
* be handled with BigDecmal return type.
*/
private static BigDecimal calculateSquareRootPortion(
final BigDecimal a, final BigDecimal b, final BigDecimal c)
{
BigDecimal sqrt;
final BigDecimal subtrahend = a.multiply(c).multiply(FOUR);
final BigDecimal insideSqrt = b.pow(2).subtract(subtrahend);
if (insideSqrt.compareTo(ZERO) < 0)
{
throw new NumberFormatException("Cannot be solved: no x-intercepts.");
}
else
{
final double value = insideSqrt.doubleValue();
final double sqrtDouble = Math.sqrt(value);
sqrt = new BigDecimal(sqrtDouble); // may throw NumberFormatException
}
return sqrt;
}
}
With the calculations portion in place, it is time to move to the focus of this post (the presentation via JavaFX 2). The following code listing provides the JavaFX 2 class (written in pure Java) used for the application. Note that much of this presentation layer code could have been written using FXML.
QuadraticCalculator.java
package dustin.examples;
import java.math.BigDecimal;
import java.util.List;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFieldBuilder;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
/**
* JavaFX-based application for solving quadratic equations.
*
* @author Dustin
*/
public class QuadraticCalculator extends Application
{
/** Coefficient A used in quadratic formula. */
private TextField coefficientA =
TextFieldBuilder.create().promptText("Enter Coefficient A").build();
/** Coeffecient B used in quadratic forumal. */
private TextField coefficientB =
TextFieldBuilder.create().promptText("Enter Coefficient B").build();
/** Coeffecient C (constant) used in quadratic formula. */
private TextField coefficientC =
TextFieldBuilder.create().promptText("Enter Coefficient C").build();
/** First x-intercept. */
private TextField xIntercept1 =
TextFieldBuilder.create().disable(true).editable(false).build();
/** Second x-intercept. */
private TextField xIntercept2 =
TextFieldBuilder.create().disable(true).editable(false).build();
/** Axis of symmetry. */
private TextField symmetryAxis =
TextFieldBuilder.create().disable(true).editable(false).build();
/**
* Extract Image with provided name.
*
* @param imageName Name of image to be provided.
* @return Loaded image.
*/
private Image getImage(final String imageName)
{
final String jarFileUrl =
this.getClass().getProtectionDomain().getCodeSource().getLocation().toString();
final String url = "jar:" + jarFileUrl + "!/" + imageName;
System.out.println(url);
return new Image(url, true);
}
/**
* Provide a read-only horizontal box with quadratic equation and quadratic
* formula and with a button that can be clicked to calculate solution to
* quadration equation with provided coefficients.
*
* @return Horizontal box with quadratic equation and quadratic formula.
*/
private HBox buildEquationsBox()
{
final HBox equationsBox = new HBox();
equationsBox.setAlignment(Pos.CENTER);
equationsBox.setSpacing(50);
final Image quadraticEquation = getImage("quadraticEquation-transparent.png");
final ImageView equationView = new ImageView(quadraticEquation);
equationsBox.getChildren().add(equationView);
final Image quadraticFormula = getImage("quadraticFormula-transparent.png");
final ImageView formulaView = new ImageView(quadraticFormula);
equationsBox.getChildren().add(formulaView);
final Button calculateButton = new Button("Calculate");
calculateButton.setOnAction(
new EventHandler<ActionEvent>()
{
public void handle(ActionEvent t)
{
final BigDecimal a = extractBigDecimal(coefficientA.getText());
final BigDecimal b = extractBigDecimal(coefficientB.getText());
final BigDecimal c = extractBigDecimal(coefficientC.getText());
try
{
final List<BigDecimal> intercepts =
SimplisticQuadraticFormula.calculateXIntercepts(a, b, c);
xIntercept1.setText(intercepts.get(0).toPlainString());
xIntercept1.setDisable(false);
if (intercepts.size() > 1)
{
xIntercept2.setText(intercepts.get(1).toEngineeringString());
xIntercept2.setDisable(false);
}
else
{
xIntercept2.setText("-");
xIntercept2.setDisable(true);
}
if (a.compareTo(new BigDecimal("0")) != 0)
{
final BigDecimal axis =
SimplisticQuadraticFormula.calculateAxisOfSymmetry(a, b);
symmetryAxis.setText(axis.toPlainString());
symmetryAxis.setDisable(false);
}
else
{
symmetryAxis.setText("-");
symmetryAxis.setDisable(true);
}
}
catch (NumberFormatException nfe)
{
xIntercept1.setText("-");
xIntercept1.setDisable(true);
xIntercept2.setText("-");
xIntercept2.setDisable(true);
symmetryAxis.setText("-");
symmetryAxis.setDisable(true);
}
}
});
equationsBox.getChildren().add(calculateButton);
return equationsBox;
}
/**
* Converts provided String to BigDecimal.
*
* @param possibleNumber String to be converted to an instance of BigDecimal.
* @return The BigDecimal corresponding to the provided String or Double.NaN
* if the conversion cannot be performed.
*/
private BigDecimal extractBigDecimal(final String possibleNumber)
{
BigDecimal extractedNumber;
try
{
extractedNumber = new BigDecimal(possibleNumber);
}
catch (NumberFormatException nfe)
{
extractedNumber = null;
}
return extractedNumber;
}
/**
* Provide horizontal box with labels of coefficients and fields to enter
* coefficient values.
*
* @return Horizontal box for entering coefficients.
*/
private HBox buildEntryBox()
{
final HBox entryBox = new HBox();
entryBox.setSpacing(10);
final Label aCoeff = new Label("a = ");
entryBox.getChildren().add(aCoeff);
entryBox.getChildren().add(this.coefficientA);
final Label bCoeff = new Label("b = ");
entryBox.getChildren().add(bCoeff);
entryBox.getChildren().add(this.coefficientB);
final Label cCoeff = new Label("c = ");
entryBox.getChildren().add(cCoeff);
entryBox.getChildren().add(this.coefficientC);
return entryBox;
}
/**
* Construct the output box with solutions based on quadratic formula.
*
* @return Output box with solutions of applying quadratic formula given
* provided input coefficients.
*/
private HBox buildOutputBox()
{
final HBox outputBox = new HBox();
outputBox.setSpacing(10);
final Label x1 = new Label("x1 = ");
outputBox.getChildren().add(x1);
outputBox.getChildren().add(this.xIntercept1);
final Label x2 = new Label("x2 = ");
outputBox.getChildren().add(x2);
outputBox.getChildren().add(this.xIntercept2);
final Label axis = new Label("axis = ");
outputBox.getChildren().add(axis);
outputBox.getChildren().add(this.symmetryAxis);
return outputBox;
}
/**
* Build overall presentation of application.
*
* @return Vertical box representing input and output of application.
*/
private VBox buildOverallVerticalLayout()
{
final VBox vbox = new VBox();
vbox.setSpacing(25);
vbox.getChildren().add(buildEquationsBox());
vbox.getChildren().add(buildEntryBox());
vbox.getChildren().add(buildOutputBox());
vbox.setAlignment(Pos.CENTER);
return vbox;
}
/**
* Start the JavaFX application for solving quadratic equations.
*
* @param stage Primary stage.
* @throws Exception JavaFX-related exception.
*/
@Override
public void start(final Stage stage) throws Exception
{
final Group groupRoot = new Group();
groupRoot.getChildren().add(buildOverallVerticalLayout());
final Scene scene = new Scene(groupRoot, 600, 150, Color.LIGHTGRAY);
stage.setTitle("Quadratic Formula: JavaFX Style");
stage.setScene(scene);
stage.show();
}
/**
* Main function for running the JavaFX-based quadratic equation solver.
*
* @param arguments
*/
public static void main(final String[] arguments)
{
Application.launch(arguments);
}
}
The JavaFX 2 code above loads two images with transparent backgrounds to display the standard form of a quadratic equation and to display the quadratic formula. In a previous post, I loaded these images from an external URL, but I loaded them from the application's JAR in this example. These images are shown next independent of the application.
quadraticEquation-transparent.pngThere are several ways this simplistic application could be improved. One improvement would be to make sizes adjustable and bound to one another so the window could be dragged larger or smaller and still look good. Another improvement would be to provide some type of status message on the interface, especially for situations where solutions could not be calculated. A third improvement that would be to present a graph of the quadratic equation specified with the provided coefficients to visually indicate the x-intercepts and axis of symmetry.
JavaFX 2 makes it fairly straight-forward to write simple, user-friendly applications.
Original posting available at http://marxsoftware.blogspot.com/ (Inspired by Actual Events)
Windows Phone apps, built out of “the 3 P’s”: Panoramas, Pivots, and Pages
I can’t post a new component or library every day, but I can point you at other great blogs and folks on Twitter that would be super useful to app devs and teams building on the Microsoft stack.
This afternoon I read another of Arturo Toledo’s amazing series on Windows Phone Design – and it’s a simple but important point: apps are not just a choice between a Page, a Panorama, or a Pivot: many apps have aspects of all of these. The Music+Videos hub on the phone is built of all 3, and your app can pull that off, too: just understand the ideal content and purposes of these different types of core experiences.
31 Weeks of Windows Phone Metro Design | #5 Choosing between Panoramas, Pivots and/or Pages
Arturo Toledo
Senior User Experience Designer – Windows Phone Team at Microsoft
I “borrowed” this image from Arturo’s post.
He’s had other great posts in the past, too, and expect great content to come.
Dealing with Binary Data from a Canvas Object using JavaScript TypedArrays
I’m not sure how helpful this will be for anyone, but during the process of doing a binary WebSocket demo I found myself learning a lot about JavaScript typed arrays and how that translates into binary data. The demo I wrote took Canvas image data and sent it over a binary WebSocket connection. The WebSocket server took that data and sent it out to all of the connected clients, who would then render the Canvas data as a PNG. It’s kind of a niche use case but I wanted to specifically create a binary WebSocket demo. It also was a more efficient way to send image data than doing something like base64 encoding it. First off, the Mozilla documentation was REALLY helpful. Major props to them.
Translating Canvas Data Into a Binary FormatCanvas has a getImageData() method that gives you an ImageData object. Within that ImageData object is a data property, which has the actual array data of the image. Normally I would have been able to stop right there because that would (in theory) have the information I needed. But what I had to get at was the ArrayBuffer. The way the spec has been implemented you can’t do anything with the ArrayBuffer. Instead you have to use an ArrayBufferView, which takes the form of TypedArrays in JavaScript. Luckily, to get the actual buffer you can just call the buffer property on any of the typed arrays and do what you want with it. But Canvas (at least in Chrome) is slightly different. The object you get from the ArrayBuffer of ImageData.data is something called CanvasPixelArray. Currently CanvasPixelArray doesn’t behave like a regular typed array, it looks like it will become a Uint8ClampedArray but the way it works in Chrome right now the CanvasPixelArray doesn’t provide access to a buffer property so you can’t send/access the ArrayBuffer data. Luckily getting that data into a Uint8Array, which you can get the buffer data from is pretty easy:
imagedata = context.getImageData(0, 0, imagewidth,imageheight);
var canvaspixelarray = imagedata.data;
var canvaspixellen = canvaspixelarray.length;
var bytearray = new Uint8Array(canvaspixellen);
for (var i=0;i<canvaspixellen;++i) {
bytearray[i] = canvaspixelarray[i];
}
With that new Uint8Array all that we have to do is grab the buffer property and we can send it across the wire (beyond this post, but I’m planning on writing up the binary WebSocket info).
Reassembling the piecesNow what I wanted to do was take that binary data from my Canvas and render it as a PNG file on the screen. The first step is to use a Canvas object to render out a PNG. But before that we have to get the data into a Canvas. In theory, you should be able to just do what happened above in reverse. But it’s not quite that simple. Once you get back the binary data from somewhere (WebSocket say), you’ve got an ArrayBuffer that you have to deal with. There is a putImageData() that takes an ImageData object, and we can create an ImageData object a few different ways, but you can’t set the data property of it. It’s read only. So we can’t take our data from the ArrayBuffer and just put it into our Canvas. We have to manually loop through the data property and line-by-line change the data.
var bytearray = new Uint8Array(event.data);
var tempcanvas = document.createElement('canvas');
tempcanvas.height = imageheight;
tempcanvas.width = imagewidth;
var tempcontext = tempcanvas.getContext('2d');
var imgdata = tempcontext.getImageData(0,0,imagewidth,imageheight);
var imgdatalen = imgdata.data.length;
for(var i=8;i<imgdatalen;i++)
{
imgdata.data[i] = bytearray[i];
}
tempcontext.putImageData(imgdata,0,0);
If the above isn’t clear, basically I’m just creating a new Uint8Array with the data from the server, then creating the temporary Canvas so I can get image data from it, and when I have that, I’m looping through the data property and inserting my own data from the Uint8Array.
Rendering it as a PNGSo now we have a Canvas (not being displayed) that has all of the data from our server, so it’s an exact graphical copy of the info we received. Turning that into a PNG is actually pretty easy because HTML is awesome. Canvas has a toDataURL() method that will take whatever is in the Canvas and create a string that can be put into the src property of an image. Then putting that image somewhere on the DOM will display the data as an image.
var img = document.createElement('img');
img.height = imageheight;
img.width = imagewidth;
img.src = tempcanvas.toDataURL();
Fin
Now that I’ve gotten my head around binary data a lot more, I’m kind of excited about JavaScript typed arrays. Looking through the list it looks like the typed arrays will help a lot with byte manipulation because of the different types. It also looks like they’re pretty fast (at least the fastest option at the time of that post).
TweetPlaying A Sound, Simplified
For the complete article and hyperlinks, please visit my blog at http://JesseLiberty.com
JavaFX 2.1: JavaFX 2's @DefaultProperty Annotation with FXML
I'm glad that Mihai posted this response for several reasons. First, it will help anyone else reading my post to be aware of that issue. Second, it has allowed me to speculate on the cause of this message in this blog post.
My first thought at reading Mihai's comment was that perhaps the difference was that I was using JavaFX 2.1 (still beta) when I ran the example and perhaps Mihai was using production-ready JavaFX 2.0. Assuming this is the case, the next question was, "What changed in JavaFX 2.1 to make this example work without the children element? Feeling that I need to balance out recent cogitations on my blog with rampant speculation, I decided to do some of that speculation in this post. I speculate that JavaFX 2.1 has applied @DefaultProperty to more controls than in JavaFX 2.0 and that VBox was one of these which now has it applied.
The Javadoc description of the DefaultProperty annotation states, "Specifies a property to which child elements will be added or set when an explicit property is not given." The "Default Properties" section of the highly useful Introducing FXML adds:
A class may define a "default property" using the @DefaultProperty annotation defined in the javafx.fxml package. If present, the sub-element representing the default property can be omitted from the markup. For example, if the Group class were to define a default property of "children", the <children> element would no longer be required.My speculation was that JavaFX 2.1 had added @DefaultProperty annotation to the VBox (among others) control. Although the Javadoc for JavaFX 2.1's VBox does not show this annotation applied, the JavaFX 2.1 Javadoc documentation for its parent class, Pane, does indicate the presence of the annotation (and the @DefaultProperty annotation is itself marked @Inherited). The next image shows Pane JavaFX 2.0 and JavaFX 2.1 Javadoc versions side-by-side.
The circled portion of the JavaFX 2.1 API documentation for Pane shows that this control (and controls inheriting from it such as VBox) have children as the component's default property. This explains why children must be explicitly specified in JavaFX 2.0, but is optional for VBox in JavaFX 2.1.
The @DefaultProperty annotation has also been applied to the MenuBar control in JavaFX 2.1. Comparing Javadoc for MenuBar in JavaFX 2.0 to the Javadoc for MenuBar in 2.1 proves this. The next screen snapshot shows them side-by-side.
The circled portion of the JavaFX 2.1 API documentation shows that an annotation has been added in JavaFX 2.1 to the MenuBar class to specify that the default sub-element for MenuBar is now "menus" in JavaFX 2.1. Incidentally, Menu also has a new @DefaultProperty with "items" as its default property. With the @DefaultProperty annotation of MenuBar, I decided to try removing the <menus> elements from my FXML and this appeared to work fine, removing a couple lines of XML from my source FXML and allowing many lines to be less indented. It worked and I had a little more concise of an FXML representation of the same menus application layout.
The more widespread use of the @DefaultProperty annotation is a small, but very welcome addition to JavaFX 2.1. Although adding opening and closing "children" tags adds only two lines per use, it does increase the indentation as well for a well-formatted FXML file. FXML can be appealing because of its visual similarity to the presentation itself and having fewer "extra" lines for common cases can make it even more readable. Although the @DefaultProperty annotation itself was available in JavaFX 2.0, it's much more widely applied and can be more widely used in FXML when using JavaFX 2.1.
Original posting available at http://marxsoftware.blogspot.com/ (Inspired by Actual Events)
HTML5 for App Developers: Debugger

Below is the third episode of my HTML5 for App Developers series. In this episode, I cover how you can debug your JavaScript applications inside of Eclipse.
Debugging is available through a set of plugins that are available for Eclipse from the ChromeDevTools project on Google Code. So, you will need either Google Chrome or Chromium to make it all work.
PhoneThemeManager: allow your app to have the Light, Dark, or Inverted theme with 1 line of code
I’ve just pushed a small library that I created this evening to the world and wanted to share details on the short project in this post. (NuGet assembly, NuGet source, project on GitHub)
One of the most common feature requests that I receive for 4th & Mayor is a setting in the app to force it to always use the “Light” theme, overriding the dark/light theme that the user’s set for their theme.
Having a light background is a nice contrasting design look for the phone, and the Mail application always does this. I personally always submit mostly light theme screen shots for my applications to the Windows Phone Marketplace, it just looks better and nice to me – but I rarely use all-light themed apps other than Mail.

In preparing for the next update of my app, v3.3, I’ve coded up this capability and I’m sharing it ahead of time.
Technical OverviewIn 7.0 there were a few ways to do theme overriding, sometimes through a few silly platform bugs that we left in there – but it’s actually not an easy thing to do, and many people end up overriding every single style in their app to get the effect that they are going for.
This helper library is designed for altering the entire application’s running instance, not for providing per-page theme overriding.
In researching possible ways to solve this, I did come across this page on windowsphonegeek that talks about ways to merge in styles or to programmatically override resources that are brushes.
I decided to create a system to walk through the known values and names for all the core theme resources of colors, brushes, plus the light/dark theme visibility and opacity properties.
In your app, you simply call `ThemeManager.ToLightTheme()`, `ThemeManager.ToDarkTheme()`, `ThemeManager.InvertTheme`, to force this. You need to have this call happen inside your App.xaml.cs file, in the constructor, after the Initialize calls.
You cannot change or call this more than once, so if you offer a setting for users to “Force Light”, use a MessageBox to inform them that their setting will be used the next time they start the app. You will have to read their setting right away when they start up the app. Once styles start applying the values, you could start to get inconsistent results.
The code walks and updates the Color instances, then walks the Brush resources and sets their Colors to be the original Color instances, just in case.
I have placed the ThemeManager class within the Microsoft.Phone.Controls namespace for this to be easy to add to your App.xaml.cs file.
You should have an App constructor like this:
/// <summary>
/// Constructor for the Application object.
/// </summary>
public App()
{
// Global handler for uncaught exceptions.
UnhandledException += Application_UnhandledException;
// Standard Silverlight initialization
InitializeComponent();
// Phone-specific initialization
InitializePhoneApplication();
ThemeManager.ToLightTheme();
// Other code that might be here already...
}
What’s themed
By default this is what happens:
- The resources for foreground, background, all the contrast/chrome/etc. colors and brushes are updated
- The light and dark theme visibility and opacity resources are updated
- The background brush of the Frame is set explicitly to the color (may have a negative performance impact!)
- The System Tray whenever a page navigation completes
- The ApplicationBar of a page if set immediately
I’ve added a simple OverrideOptions enum (static) to the ThemeManager that can be used to disable the auto-behaviors I’ve added.
Newing up AppBarsIf you have code in your app like “var ab = new ApplicationBar”, beware that that application bar will take on the system’s actual theme colors by default, and not the overridden light/dark coloring that happens with the app.
If you need to new up an ApplicationBar, you should use the convenience method of `ThemeManager.CreateApplicationBar()` or use the extension method on app bar that I added, `MatchOverriddenTheme`, to set the color values.
What’s not themedUnfortunately this cannot theme MessageBox at all.
Talking about fill rate performanceI’ve designed the system so that resources are only overridden when needed.
If your app uses ToLightTheme to force the light theme, and the user is running the Light theme already, nothing happens – it’s a no-op.
Although updating resources has no negative effect really on the app’s performance, the trouble is setting the Background color of the phone application’s frame.
The frame is always present and may add a fill count of 1.0 to every single page in your app.
Anything above a fill rate of 2-3 is not a good thing, so you may notice a degraded experience. Might want to inform your users of that when providing the option to force the light theme, for example.
A note about your batteryMany Windows Phones use AMOLED or similar technology where bright colors, such as the background color used in the Light theme, will use a lot of power. Please respect your users and realize that long-running apps probably should not force the Light option.
Consider only making such a “Force Light Theme” option as a setting that users opt-in to, as opposed to always overriding the theme.
About custom themesWhen I designed this library, I thought about offering a ton of capability in it for using “branding” colors, modifying the accent brush, etc., but instead decided to tackle just one thing. So the name ThemeManager is a little overkill maybe, but it’s where we are for now.
Get the bitsNuGet Binary
The binary is super easy to use. With NuGet just add the PhoneThemeManager package reference.
NuGet Source File
Instead of adding yet another assembly to your project, just add the single source file (or add it to your existing shared library, etc.) by using the PhoneThemeManager.Source package.
GitHub Repo
Fork and enjoy https://github.com/jeffwilcox/wp-thememanager
Hope this helps.
Java on Heroku at CinJUG, Detroit JUG, and MongoDB Boulder
Over the next few days I’ll be presenting about Java, Play Framework, and Scala on Heroku at a couple Java User Groups and a MongoDB conference:
Hope to see you there!
HTML5 for App Developers: Eclipse

Below you will find the second episode of my HTML5 for App Developers series. In this episode, I cover how you can use Eclipse, which is a free and open source IDE, to do your HTML5, JavaScript, and CSS work.
In the video, I point out a small bug that comes with Mac version of Eclipse. To download the patch you can use this link. You can find Eclipse itself here; I encourage you to download the Eclipse IDE for JavaScript Web Developers version.