home media server

March 29th, 2009 by Andrew Zuercher

problem definition

if some of you don’t know, i’ve just about had it with my satellite provider with their excessive charges and coupling of media with transport. i don’t like it that i don’t really own the content - if i abandon the satellite provider then all my recorded items on my DVR are no longer accessible, and unless i upgrade to their proprietary hardware then i cant access the stuff throughout my house.

there has got to be a better way of distributing my media in the house

apple tv

about 2 years ago i bought the apple tv and really liked it, but the interface kind of sucked and there weren’t a heck of a lot of items on there and HD was not an option. well, recently (about january) i upgraded the software and apple has done a really nice job of making a bunch of movies available, easy to order from my apple tv, and supporting HD format now. the one thing i was missing was a media server to run itunes centrally on. i have a mix of apple tvs that are on a 100MB wired and 802.11n wifi network and streaming is slick.

always looking for a value, i’ve purchased used (like new) additional apple tvs instead of paying the high value for a new console. they dont come with a remote or with power cables, but those are cheap to pick up as well. apple just announced a 160GB internal drive for the apple tvs, but i think that really is for those that are running just one apple tv w/o an itunes media server. if you have an itunes media server, then you can stream from that instead which is a better solution, leading into the next secttion……

imac itunes media server

when my laptop went kaput, i got a new imac with 1TB hard drive. thats a ton of storage - i’m currently at about 300GB used so far (and moving now). now with a mac in the mix, i’ve got a pretty good place to run itunes centrally and have dubbed it my new media server. the 24″ display is pretty big, so the couch i have in front of it sets it up as an additional place to watch videos if i want (along with some pretty good speakers to boot).

protect that content

i would hate to have a drive fail on my imac and lose all this awesomeness that i have setup, so i bought a WD 2TB external hard drive to protect my content. for what its worth, i’ve made the hd available via sharing so that i can mount it from my laptop and use it for backing up my laptop via the network to use for time machine on my laptop as well.

the wd hardrive i got supports firewire 800 (had to install the wd driver that came on the cd) which is really fast, much faster than usb2. the hard drive has 2 internal drives and you can setup RAID mirroring so that if it fails then you can just slap a new wd hd in and it will rebuild, running at risk until you do that (of course, this will cut your total capacity in half). striping against the 2 internal drives in the unit is standard which is a nice RAID entry level for the storage device. for now i dont need that much space (and mirroring my backup drive seems a bit excessive), so i just use it as a 2tb backup w/o RAID using time machine which is pretty sweet. if i use up the other 700GB of my primary drive then I’ll transfer my library to my external drive and use mirroring. note that a standard definition movie is about 1GB and a HD movie is about 3GB: i have a bit of time to think about this one….

laziness and terminal emulation

running up and down the stairs to get on my imac to enter in remote codes, and do other stuff with itunes on the machine was getting to be a pain. apple has a solution out there if you want to pay for it, but i looked to use a free solution for terminal emulation instead. i installed vine3 (vnc server) on my imac and run chicken of the vnc as a vnc client on my laptop. this works pretty well and is the right price - free.

ripping DVDs

you can pay for a converter/ripping application out there if you want, but i’ve decided to install handbrake and rip with their targeted profile of apple tv. its not super fast to rip, but the mp4 files it generates work perfectly on my apple tv.

using airtunes

you can setup your endpoints to be airtunes speakers which allows you to have central house audio. apple tv supports this (which is cool because i will shortly have 2 other rooms running apple tv in addition to my home theater and living room). whatever i play on my imac gets played on those other units as well.

to bring my personal stereo (just speakers, no display) into the mix, i’ve got an airtunes express coming in the mail which will allow me to have my personal stereo act as another speaker in the central house audio. the new unit runs on 802.11n which is nice since my wireless router supports it.

so now i will have the following:

  • kitchen personal stereo (airtunes speaker)
  • living room (airtunes speaker and apple tv)
  • master bedroom (airtunes speaker and apple tv)
  • home theater (airtunes speaker and apple tv)
  • guest room (airtunes speaker and apple tv)
  • imac basement (airtunes speaker and itunes display)

apple remote

one of the best iphone applications out there for me is the apple remote. i can control my apple tvs independently and the central house audio, all through a pretty interface that makes the existing white apple remote that comes with my hw seem weak.

boxee

i was initially interested in boxee because it would allow me to get media for free and play it on my apple tv. well, hulu and boxee had a fight in february of this year and so now the integration plays hulu through the browser. i’m not realy happy about the resolution or the quality of the apple tv integration - it seems to wipe out my synching of the apple tv whenever i run it as well. bottom line - free comes with a price when it comes to boxee, so i doubt if i’ll ever use it. but hey i tried.

wrap up

so here is the bottom line, i hate the concept of having to put stupid dvds into a hardware device - it seems about as good as VHS was to me 28 years ago when microwaves first came out. i haven’t really been too keen on paying a chunk to get central house audio by implementing a hw scenario that was presented to me when i first moved into my house, the softer side over an IP network just seems like the right direction to go. now every room in the house gets to benefit from my music and video inventory and play in unison if i so desire.

cheers

Technorati Tags:

Barcamp 2008

October 29th, 2008 by Andrew Zuercher

Finally a week after barcamp altanta 2008 I have a second to write about the weekend - its been a crazy past few weeks for me. Barcamp was great, same as last year, but this time i knew a few more of the attendees (its a small world). Some of the highlights for me

  • jedi mind tricks - reciprocity, commitment & consistency, social proof, authority, scarcity, reactities, liking, contacts, and co-operation. Dont you think that those are some very keen tactics? answer “those are some very keen tactics.
  • an open source talk
  • a political discussion - i caught the end of it
  • a preso on fluid
  • iphone sdk 101
  • and my favorite poker till 4am - honed up my skills in omaha and texas hold-em

While there i presented a session on Appcelerator and TestMonkey. It was a great weekend and I really like our atlanta community and glad to see it unite for a weekend. Looking forward to atlanta startup weekend 2 here in a few weeks.

Technorati Tags:

No Fluff Just Stuff Atlanta Fall 2008

October 29th, 2008 by Andrew Zuercher

Friday through Sunday this week I attended no fluff just stuff in atlanta. Some of you may have seen some of my tweets. Some of the key sessions that I attended and really enjoyed:

  • Groovy by Scott Davis. Scott has a tremendous amount of energy and did a very good job of covering some of the lesser known aspects of groovy as well as grails
  • GWT by David Geary. David is local to Atlanta and provided some humor while explaining the internals of GWT
  • Agile and Architecture by David Hussman. David is an agile coach and had a very open and interactive session that was very enjoyable
  • Cloud Computing by Michael Nygard - helped answer a lot of my questions with practical examples. He knows his stuff and I cant wait to start using AWS on some of my upcoming projects.

While at the conference I ended up tweeting with some of the other attendees. That was pretty cool. It was a very long weekend and made for a tiring Monday, but I’m glad that I had the opportunity to attend the sessions.

Technorati Tags:

Zuercher Technologies Re-born

October 29th, 2008 by Andrew Zuercher

Zuercher Technologies is making a comeback. As many of you probably already know the Appcelerator Atlanta Office closed down. Some have asked me what is on the horizon and I’ve held back a little to make a formal announcement. Over the next couple of weeks I’ll be putting up a new web front for zuerchtech, but the premise is that I will be starting a services delivery company aimed at helping companies create RIA based web solutions as an Appcelerator partner. I’d like to thank all those who have offered their support over the past couple of weeks and am very excited with the opportunities to come in the near future!

Technorati Tags:

Dale Jarrett Racing Adventure

October 21st, 2008 by Andrew Zuercher

what a blast

last saturday i headed on over to talladegha for the Dale Jarrett Racing Adventure. i got to drive 6 laps around talladegha in a nascar racing car as fast as i wanted (with an instructor sitting next to me). yes there were other cars on the track at the same time. anyway, i’m going to do it again because i think that i learned a lot between the laps. well that and it was frigging awesome and a huge rush. in case you are interested, i’ve put the footage of the dashboard up on my website for you to download and watch djra.mp4 (143MB ~ 12 mins)

Technorati Tags:

Using Appcelerator Interceptors for I18N, L10N, G11N

October 13th, 2008 by Andrew Zuercher

What’s the problem?

Just implementing resource bundles to localize your application doesn’t quite cut it. You need to do things like work with localized dates in the browser (including formatting), numbers, currencies, and who knows what else to munge your data. It sure would be nice if there were a way to transparently make this happen in a message oriented way that does not require server side awareness for services, can you help me with this problem? sure.

Built in ‘ization’ support in Appcelerator

Globalization (G11N) and Localization (L10N) both get lumped into Internationalization (I18N) - how to deal with languages, time, data formats and everything else that goes on making it so that people in different places in the world can use your glorious application. Appcelerator localization helps you out with this on some really simple levels with the langid attribute:

  <span langid="account.number.title"></span>:<input type="text"></input>

This should arm you successfully with an ability to deal with things like simple messages and labeling in your application. Now if you want to blend in your data payload to render localized text, you can make use of appcelerator javascript functions Appcelerator.Localization.get and the more powerful but less documented Appcelerator.Localization.getWithFormat.

<script>
  var en_lang_bundle = {
	"invalidlogin.message": "Dear sir/madame, the username you provided '#{username}' does not exist:"
  }
  Appcelerator.Localization.addLanguageBundle("en",English",$H(en_lang_bundle));
</script>
<span on="l:invalidlogin.response then value[text]"></span>
<app:script on="r:invalidlogin.response then execute">
  var text = Appcelerator.Localization.getWithFormat('invalidlogin.message',null,null,{username:'azuercher'});
  $MQ('l:invalidlogin.response',{text:text});
</app:script>

This is a nice way to use message indirection for munging messages, but really is quite messy and anything but transparent. There must be a better way!

Interceptors

A lesser known feature of Appcelerator is the concept of interceptors - client side behavior that you can have play in-between the delivery of queued messages to their recipients. In the case for client-2-server orchestration all server requests and their corresponding response messages are enqueued and subject to perversion by interceptors. You just have to know how to implement them. Lets say that whenever I send a CRUD request to the server called ‘r:createorder.request’ I want to add a new attribute called last_modified_utc which is a numerical representation of a utc date as a long. I can add that to the payload to the back end service completely transparently with the Appcelerator.Util.ServiceBroker.addInterceptor method - the method takes a callback to the following:

  • interceptQueue - where requests from client to server are intercepted
  • interceptSendToListener - where responses from server to client are intercepted

In the example below I

  • add ‘last_modified_utc’ as a current utc long to r:createorder.request which is consumed by my back end service
  • transform ‘last_modified_utc’ in the r:createorder.response from utc to a localized string in the browser
<app:script>
	var interceptor = {
	    interceptQueue: function(msg, callback, messageType, scope) {
			if (messageType=='remote:createorder.request') {
				msg.data.last_modified_utc = new Date().getTime();
			}
	        return true;
	    },
	    interceptDispatch: function (requestid, type, data, datatype) {
	        return true;
	    },
	    interceptSendToListener: function (listener, messageType, data, datatype) {
			if (messageType=='createorder.response') {
				date = new Date(data.last_modified_utc);
				data.last_modified = date.toString();
			}
	        return true;
	    }
	};
	Appcelerator.Util.ServiceBroker.addInterceptor(interceptor);
	$MQ('r:createorder.request',{hi:'there'});
</app:script>

Obviously, you can take this a step further and then add interceptors that munge your data conditionally based on the current locale defined in Appcelerator.Localization. The benefit here is that this data transformation happens at a layer outside of my normal pub/sub for messages in Appceleator - the normal pattern is to either replace or add attributes in the payload.

wrap up

Although not a shrink wrapped solution for I18N in all its glory, its not hard to implement interceptors to do so. Beyond I18N, a lot of other aspects for your messages can be mutated in the browser non-intrusively. Although the key demonstration here is data transformation, you would potentially add other horizontal services into your application.

this article cross posted at http://www.appcelerant.com/using-appcelerator-interceptors-for-i18n-l10n-g11n.html

Technorati Tags: , ,

wordpress migration

October 6th, 2008 by Andrew Zuercher

zuerchtech.com has moved to use the wordpress engine, to view the earlier version and previous posts you can do so at http://oldblog.zuerchtech.com. more will be updated soon

Technorati Tags: ,

Appcelerator Remote Routes for Service Integration

October 5th, 2008 by Andrew Zuercher

Problem definition

A few weeks ago i started a thread on the Appcelerator development network about remote routes. The thread got a bit of attention and ultimately meant different things to different people.

web 1.0 transformations

When I get in front of customers today that have an existing web solution in place, they tend to ask some simple questions:

  • What do I have to do to implement a service in <backend framework>?
  • I’ve already got a bunch of web services, can I use them as is?
  • My website has a traditional web 1.0 implementation, will i have to throw away and start over?

Primary focus: cost to implement seems to be the main chasm for them to hurdle.

REST zealots

A bunch of the developers out there are jazzed about building RESTfull services to remotely expose an endpoint for integration. Re-using these endpoints is a natural fit for them and paramount to their needs.

Primary focus: A clean single place to define their services.

back end framework architects

Then there are the framework guys that are out there that have the need to add Appcelerator to extend their portfolio. Recently I helped out with implementing an Appcelerator service for grails. To facilitate the framework integration I write a similar service broker in grails much akin to what we have done for the other platforms. The controller would discover the Appcelerator services written in grails and then invoke them directly. The downside is that:

  • grails developers like to integrate at the controller level and not the service level
  • grails itself makes responding to and rendering JSON very easy
  • grails already has routing and discovery built into the framework

Primary focus: not duplicating existing framework functionality in a way that is consistent with their architecture

Previous approaches

In the past I’ve prescribed a 4-tiered strategy for those that are out there that are interested in integrating their existing application using Appcelerator;

  • create new Appcelerator-specific remote services that reuse existing code inline if possible
  • use an ESB to route to your existing services
  • use the app:http written by Mr. Hashemi as mash-up in the client
  • do not use remote services, but allow Appcelerator to add richness to your application locally in the browser

Solution

Instead of writing remote services that are Appcelerator specific and restrictive, an implicit contract is adhered to. This means that back end services can be written in any language or platform so long as they are able to consume and render in an approved format (for example ‘application/json’).

Traditional

Here is a simple example for a traditional service.

class MyService &lt; Appcelerator::Service
Service 'order.create.request', :create_order, 'order.create.response'
 
def create_order
order = Order.new(params["amount"])
order.save
{'success'=&gt;true, 'id'=&gt;order.id}
end
end

Using remote routes

And now we make use of controllers as well as remote routes. Here is the controller

class OrderController &lt; ApplicationController
def create
order = Order.new(params["amount"])
order.save
respond_to do |format|
format.json { render :json =&gt; {:success =&gt; true, :id =&gt; order.id} }
end
end
end

And now in the client we include the following in our javascript (there are a ton of ways to implement this, but here is an example for now)

	$MQR('r:create.order.request','/order/create','post',
'r:create.order.response');

trade offs

Item Remote Routes Appcelerator Service app:http
Web controllers Yes No, must be appcelerator services. Yes
Message Mapping Yes, client side as javascript to define routes. Concise and not too terribly tedious and can be done in exactly one place. Server side using annotations to map methods to message types. Yes, client side widget declarations per message type.
Message Multiplexing One-2-One: a given request message is associated with a single response message and are processed one at a time. Many-2-Many: this is a big upside for the existing service brokers is that groups of messages can be delivered to the back end at a given time and different types of messages can respond to them One-2-One: a given request message is associated with a single response message and are processed one at a time.
Service Endpoints Multiple can be supported, the target url is an aspect of the message mapping Fixed, all requests go through specifically one exposed endpoint (service broker) Multiple can be supported, the target url is an aspect of the message mapping
External Services Yes No Yes
Serialization Up to back end service to implementor Appcelerator remote service takes care of it for you Up to back end service to implementor

Wrap up

Understanding the trade-offs for the different service routing opportunities should be considered when you architect your solution. At the core of it, Appcelerator provides you with options and leaves that decision up to you, empowering you to make that choice for yourself.

this blog has beeen cross-posted at http://www.appcelerant.com/appcelerator-remote-routes-for-service-integration.html

Technorati Tags: , , ,

SOAP orchestration with java:axis2

August 29th, 2008 by Andrew Zuercher

Problem Definition

Are you considering integrating a bunch of web services together but may not feel too comfortable with the vulnerabilities of a mash-up approach, the overhead of setting up and using an ESB, or writing a bunch of mind numbing spilling crushing service transformation code? If thats what you want then, yeah sure that would work for a problem definition.

How does it do it?

The java:axis2 plugin (an appcelerator plugin) installs an appcelerator command that can be run either silently or prompt for input to generate and build axis2 stubs from your WSDL url. Once the stubs have been built, the command then creates a java appceleator-based class with services for each corresponding soap endpoint. The solution makes use of code generation so that you may enhace the services should you so desire. Serialization is also taken care of by transforming to/from the JSON model to the Axis2 model so that making the changes to the service mapping is clean and simple.

How would 1 set it up?

Before you can use the plugin, you need to download axis2 and setup your path appropriately. Its pretty easy, just extract axis2 and set your AXIS2_HOME environment variable. Now you can add the plugin to your java project (named $PROJECT):

app install:plugin java:axis2
cd $PROJECT
app add:plugin java:axis2

How do I use it?

Now that you’ve added the plugin, you can now implement the service orchestration for invoking a SOAP endpoint. Lets assume that your wsdl is at http://localhost:8080/axis/services/QueryPort?wsdl. This is how it would flow for you in prompted mode

app gen:axis2
Whats the url for your wsdl?
http://LODVM1044:8080/axis/services/QueryPort?wsdl
What directory do you want to use for storing the axis stubs? [src/axissource]
src/axissource/queryport
What package name do you want to use for your axis stubs? [my.axis]
queryport.axis
What directory do you want to generate the services to? [app/services]
app/services
What package name do you want to use for your appcelerator services? [my.service]
queryport

Alternatively you could run this silently:

app gen:axis2 --axisdir=src/axissource/queryport --axispackage=queryport.axis \
--wsdl=http://localhost:8080/axis/services/QueryPort?wsdl --silent=true --appcpackage=queryport

Here is a sample snippet of the code that will be generated to map your appcelerator services to a web service call:

package cmdb.service;
 
import org.appcelerator.annotation.Service;
import org.appcelerator.messaging.Message;
 
public class QueryService {
 
	@Service(request = "graphQuery.request", response = "graphQuery.response")
	public void graphQuery(Message request, Message response) throws Exception {
		uery param = (axis.query.QueryServiceStub$Query) AxisUtil.toAxisObject(request, axis.query.QueryServiceStub$Query.class, "param");
		axis.query.QueryServiceStub$QueryResult result = new axis.query.QueryServiceStub().graphQuery(param);
		response.getData().put("result",AxisUtil.toMessageDataObject(result));
	}
}

Note that for this to work you will have to upgrade your Appcelerator installer to 1.1.20+ (next release to be out shortly), I’ve updated mine off of the svn trunk. To check your installer:

app --version

Some more details on how to test

Now the question is, how do i know how to construct my request parameters? You can use the AxisUtil class to help you out, here is a sample snippet for my parameter into the web service, the model class Query:

Query param = createQuery(); //however you want to create your model object
System.out.println(AxisUtil.toJSONObject(param).toString());

the request body will directly reflect that ex:

{"query":{"itemTemplate":[{"contentSelector":null,"id":{"value":"ALL_CI1s"},
 
 
 
 
"instanceIdConstraint":null,"recordConstraint":[],"suppressFromResult":false,
"xpathExpression":[]},{"contentSelector":null,"id":{"value":"ALL_CI2s"},"instanceIdConstraint":null,
"recordConstraint":[],"suppressFromResult":false,"xpathExpression":[]}],
"relationshipTemplate":[{"contentSelector":null,"depthLimit":null,
"id":{"value":"ALL_Relations"},"instanceIdConstraint":null,"recordConstraint":[],
"sourceTemplate":{"maximum":22,"minimum":0,"ref":{"value":"ALL_CI1s"}},
"suppressFromResult":false,"targetTemplate":{"maximum":0,"minimum":0,"ref":{"value":"ALL_CI2s"}},
"xpathExpression":[]}]}}

This utility will help you to see how the data is structured. For a more detailed example unit test check out SerializationTest.java

Wrap Up
In this post we demonstrated:

  • what the plugin does and the problems it solves
  • how to set it up and use it, as well as how to test

this blog cross-posted at http://www.appcelerant.com/java_axis2.html

Technorati Tags: , , , ,

Implementing an Appcelerator Plugin

March 4th, 2008 by Andrew Zuercher

Purpose

The Appcelerator framework allows for the extension of the build and deployment process so that you can add components and modify the behavior of your service implementations. It is quite powerful and not only restricted to services, plugins for example could span across to the modification of applications and the entire build and deployment process for that matter. For simplicity, this article will identify how to create a new component added to our java service for monitoring performance.

Install Appcelerator

I’ve assumed that you’ve successfully downloaded and installed Appcelerator from http://www.appcelerator.org/products. Once you’ve gone through the installer you can get the java service

1
  app install:service java

You may want to get an existing plugin (I needed the java:spring plugin to implement my plugin):

1
  app install:plugin java:spring

Plugin Creation

Lets assume that our plugin is going to be called java:perf, to create the plugin project:

1
2
  cd $HOME/workspace
  app create:plugin . java:perf

This will create a sub directory named java_perf, now you will want to create a proper license entry in your build.yml for example check out build.yml. You now have the opportunity to modify the entry points in your java_perf.rb. I personally wanted to setup my install script so that:

  • it dynamically builds the jar when we add the plugin to a project
  • modifies the spring.xml to include the bean entries for my component

All of this is in before_add_plugin(event) callback. If you want to see where this is called, check out add_plugin.rb. Once my coding is complete (added my source files to java_perf/src), I created the plugin distribution:

1
rake zip

Install the plugin

As you noticed, I haven’t covered debugging the plugin just yet, this is because I want to first set up the plugin for installation and then work with it in my install directory. Lets install it to the local machine:

1
app install:plugin java_perf.zip

Add the plugin to my project

I thought that I’d create a blank java project real quick

1
2
cd workspace
app create:project . myproject java

now we can add the spring plugin and our new java:perf plugin to our project

1
2
3
cd myproject
app add:plugin java:spring
app add:plugin java:perf

You can now directly modify the java_perf.rb file in your install directory

  • windows: c:/Program Files/Appcelerator/releases/plugin/java_perf/1.0
  • unix: /usr/local/Appcelerator/releases/plugin/java_perf/1.0
  • mac os: /Library/Appcelerator/releases/plugin/java_perf/1.0

I suggest that you continue to modify the java_perf.rb this way to debug it and then finalize by copying back over to $HOME/workspace/java_perf

Next Steps

As a final parting you can release your new plugin so that others may be able to leverage it

1
2
cd $HOME/workspace/java_perf
app release java_perf.zip

-andrew

this article is cross posted at:
http://zuerchtech.com/2008/3/4/implementing-an-appcelerator-plugin

Technorati Tags: , ,