Saturday, November 11, 2006

Core2 Mac Mini

There has been a fair amount of speculation about when/if Apple will release a version of the Mac Mini using the Core 2 Duo processor. For example:

Apple hints at Core 2 Duo Mac mini?

How Soon Will the Mac mini Go Core2?


Personally, I'm dying to see a Core2 Mini. At the moment, I'm stuck with a 800 Mhz G4 iMac that just doesn't cut it any more, but I can't afford a 20" Core2 Duo iMac.

For the sake of argument, why would Apple not update the Mini to the Core2? Part of that depends where Apple really sees the Mini. When the (G4) Mini first came out, one of the pitches was for PC developers to use it in addition to a PC via a KVM switch. In this scenario, it made sense for Apple to make it beefy.

When the first Intel Macs came out, the Mini had a Core processor (I'll call the Core processor the "Core1" just to be extra clear) just like the other Macs, in particular the iMac. They wanted the Core archiecture, but there weren't many of those processors, so the Mini and the iMac were pretty similar. Then the Core2 came out and Apple bumped the iMac to a Core2 but left the Mini at a Core1.

I take this to indicate that Apple is trying to create some diversity in the product line - i.e., the need to differentiate the Mini from the iMac. Thus, they need to keep the Mini crippled, and they're no longer pitching the Mini as a developer machine. This is (unfortunately) like the IBM PC Jr back in the day. Now, they have bumped both Mini models to a Core1 Duo, but it's still a Core1 not a Core2 - i.e., still crippled.

The other possible motive (for Apple) of keeping the Mini at Core1 is profit margin. When the Core2 came out, Intel slashed the price of the Core1, but Apple has not dropped the price of the Mini. If Apple had a big stock of Core1 processors (especially Core1 Duos) when the Core2 came out (not likely given how shrewd Apple often is), this gives them a way to flush their Core1 inventory. More likely, Apple is just making bank on the reduced cost of the inputs.

So, I can see a few reasons why Apple may not bump the Mini to a Core2 very soon. I hope I'm wrong it because I'd really like a Core2 Mini. The MacWorld release timeframe that is being rumored would fit my budget very nicely.

enjoy,
Charles.

Thursday, August 24, 2006

Flex: Debug Flash Player on OS X

As noted in "Building and Deploying Flex2 Applications" (Live Docs), the output of trace statements can be configured in the standalone debug version of the Flash player. The documentation describes the location of the mm.cfg file on Mac OS X using Mac-style (non-Unix) path notation with colons to separate directories.

I set up a config file, but for the life of me, I couldn't find the output file. Then, I found an old, pre-Flex2 blog post by Christian Cantrell which fills in two missing parts of the documentation. First of all, if no TraceOutputFileName directive is given, the trace output will go to flashlog.txt in the same directory as the config file - fair enough. Once I removed the directive, I found the output file.

Also, if a path name is given, the path must be specified in the old Mac-style notation (with colons) rather than Unix-style (with slashes). I suppose that's why they specified the location of the config file in that notation, but the significance of the colons was lost on me. One totally trivial tidbit correctly noted in Christian's blog post is that the directory name is "Macromedia" not "macromedia", as indicated by the docs. (Since the Mac's HFS+ file system is basically case insensitive, it doesn't really matter.)

Once I figured that stuff out, I could get my trace output and get on to fixing my bugs.

I do have (at least) one gripe with the debug Flash player on the Mac compared to the PC - it doesn't keep a history of recent URLs. So, every time you go to open an URL, you have to type it in again (or paste it from a browser, which does keep history.) Even if you keep the player running, it still doesn't remember the last URL it opened.

Enjoy,
Charles.

Wednesday, July 19, 2006

Flex: Sending Messages from Server-Side Java Code

I've been trying to figure out how to send messages from the depths of my Java application out to Flex clients. I'm not talking about messages that originate on a client, pass through the Java server, and then head back to the clients - that stuff is documented in the manual. I mean there is a process going on in the server that needs to send messages to the clients.

Of course, JMS and the JMS adapter would work, but I've been really leery of the complexity of JMS since it came out years ago. It has the advantage that it would allow my application to be separated from the Flex server, which would work well in terms of scaling. I may yet try JMS, but for the moment, I'm looking to avoid JMS.

So, I was thinking that writing a message service adapter would be the key. Adobe has a brief example of creating a custom Message Service adapter. It seems to be a complete example, but it left me with lots of questions. For example Message is an interface, which concrete class do we use? How do we construct it? What all can we do with the MessageService? What value are we returning from invoke?

After some digging around in the sample code, I came across a couple of Java classes associated with the dashboard sample application. So, I've taken the code from that example, paired it down a bit, and wrote a very simple, Soviet-style (butt-ass ugly but functional) Flex interface for it.

Below is the server-side Java code.

import java.util.*;
import flex.messaging.MessageBroker;
import flex.messaging.messages.AsyncMessage;
import flex.messaging.util.UUIDUtils;

public class FmsDateFeed
{
private static FeedThread thread;
public FmsDateFeed()
{
System.out.println("FmsDateFeed.ctor: " + this);
}

public static void main(String[] args)
{
FmsDateFeed feed = new FmsDateFeed();
feed.toggle();
}

public void toggle()
{
if (thread == null)
{
System.out.println("FmsDateFeed.toggle: starting...");
thread = new FeedThread();
thread.start();
}
else
{
System.out.println("FmsDateFeed.toggle: stopping...");
thread.running = false;
thread = null;
}
}
public static class FeedThread extends Thread
{
public boolean running = true;
public void run()
{
MessageBroker msgBroker = MessageBroker.getMessageBroker(null);
String clientID = UUIDUtils.createUUID(false);
System.out.println("FmsDateFeed.run: msgBroker=" + msgBroker + ", clientID=" + clientID);

Random random = new Random();
while (running)
{
Date now = new Date();

AsyncMessage msg = new AsyncMessage();
msg.setDestination("time_msgs");
msg.setClientId(clientID);
msg.setMessageId(UUIDUtils.createUUID(false));
msg.setTimestamp(System.currentTimeMillis());
HashMap body = new HashMap();
body.put("userId", "daemon");
body.put("msg", now.toString());
msg.setBody(body);
System.out.println("sending message: " + body);
msgBroker.routeMessageToService(msg, null);
try
{
long wait = random.nextInt(8000) + 3000;
System.out.println("sleeping: " + wait);
Thread.sleep(wait);
}
catch (InterruptedException e) { }
}
}
}
}


The toggle method is called from the client to turn the message stream on or off. When messages are turned on, a thread is created and the run method is called. It just loops creating Java Date objects and putting the String representation of the date into Flex messages - instances of AsynchMessage. The key for me was the routeMessageToService method on the MessageBroker class. When you have the class compiled, install the Java class file in samples/WEB_INF/classes.

The client is pretty simple, by comparison. It has two features: a button for turning the message stream on and off (via a RemoteObject call) and an event handler to process the incoming messages.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="#FFFFFF"
creationComplete="initComp()">
<mx:Script>
public function initComp():void {
consumer.subscribe();
}
public function toggle():void {
feeder.toggle();
}
import mx.rpc.events.ResultEvent;
import mx.messaging.events.MessageEvent;
public function messageHandler(event:MessageEvent):void {
var body:Object = event.message.body;
output.text += body.userId + ": " + body.msg + "\n";
}
</mx:Script>

<mx:RemoteObject id="feeder" destination="time_msgs">
<mx:method name="toggle"/>
</mx:RemoteObject>
<mx:Consumer id="consumer" destination="time_msgs" message="messageHandler(event)"/>

<mx:Form>
<mx:FormItem>
<mx:Button label="Toggle Date Feed" click="toggle()"/>
</mx:FormItem>
<mx:FormItem label="Output Message">
<mx:TextArea id="output" width="250" height="150" />
</mx:FormItem>
</mx:Form>
</mx:Application>

The interesting features are the configuration information for the RemoteObject and the message Consumer. These correspond to destinations configured on the server (see below). When the toggle button is pressed, we just call the toggle ActionScript method, which make a call on our RemoteObject, feeder; we don't care about a return value, which simplifies things.

We configure the Consumer to call our messageHandler method when new messages arrive. It just gets the message body and appends it to our text box. Install this file in somewhere in the samples directory - I created my own subdirectory for the dumb, little programs like this.

To configure the server, edit messaging-config.xml in samples/WEB-INF/flex and clone the destination for "dashboard_chat" and call the new version "time_msgs". You could change the Java and MXML to use the existing dashboard_chat destination (which is what I did initially), but a) you could end up with a conflict with the Flex demos, and b) writing to messaging-config.xml (or any of those other config files) is a convenient way to get the server to restart and see your new Java class.

Oh yeah, you also need to edit remoting-config.xml to contain a RemoteObject destination also called "time_msgs". (You could use separate names for the two destinations, and it would probably be less confusing, but I was too unimaginative.)

If all goes well, you should get messages with the current time showing up randomly in the Flash client.


Enjoy,
Charles.

Wednesday, July 12, 2006

Flex: The Second Simplest Example of RemoteObject

(Update: I wrote this some time ago, and I don't have access to the source code any more. Therefore, I can't send it to you. And, I don't know about newer versions of Flex.)

In a previous post, we developed what I claim to be the world's simplest example of using the RemoteObject facility in Flex 2 to invoke a method on a Java object using the RPC services. In that example, we just had a button on a Flash application that called a method on the server. All the method did was print a message. Although we passed a message into the server method, that message was hard-coded in the ActionScript, and no results were passed back.

In this post, we will build on that to pass some user data into the server and get a response back. In theory, this ought to be very simple: the user data just comes from an input box, and the result will just be displayed in a text box.

Java Code


Below is a simple function that you can add to the SimpleRemoteObject from the previous example:

public String echoMessage(String msg)
{
System.out.println("SimpleRemoteObject.echo: " + msg);
return "The RemoteObject says: " + msg;
}

As you can see, the method writes the message to the console (like before), and returns the message with a little text prepended to it. Pretty simple.

Flash Client


The user interface is pretty simple, and I just added it to the form in the previous example. We have a TextInput to enter data, a Button to invoke the method, and TextArea to display the result from the server.

<mx:FormItem label="Input Message">
<mx:TextInput id="input"/>
</mx:FormItem>
<mx:FormItem>
<mx:Button label="Echo Message" click="echoMessage()"/>
</mx:FormItem>
<mx:FormItem label="Output Message">
<mx:TextArea id="output"/>
</mx:FormItem>

So far, so good. The button calls an ActionScript method (echoMessage) to call the server - just like the previous example:

public function echoMessage():void {
remoteObj.echoMessage(input.text);
}


We just get the text from the TextInput object (input) and call the method on the server. (Note that although I named the ActionScript method the same as the Java method - echoMessage - this isn't necessary; I'm just not creative enough to think of anything else.) But wait, something is missing: what about the message coming back from the server? Based on my experience with Java (and dozens of other languages), I would expect to see code that looks like:

output.text = remoteObj.echoMessage(input.text);

But, that's not how it works in Flash. Flash makes RPC calls asynchronously. This means that Flash doesn't wait for the result to come back from the server, and that's actually "a good thing." Without asynchronous server calls, the Flash client would hang during a (potentially long) server call, and that would be a bad thing.

OK, so how do we get the result back from the server? This introduces some additional complexity, but it's still tractable. It begins in the MXML to describe the server method:

<mx:method name="echoMessage" result="displayResponse(event)"/>

This says that when the echoMessage method on the Java server object is called, and the result arrives at some later time, the displayResponse ActionScript method will be called.

This method is pretty simple, too:

import mx.rpc.events.ResultEvent;
public function displayResponse(event:ResultEvent):void {
output.data = event.result;
}

That's all there is. Note that we don't even have to update the remoting-config.xml file on the server. This is because we are not creating a new destination; we're just using the same Java class - SimpleRemoteObject.

When you run the application in the browser, enter a message in the input area, click the button, and the response will eventually appear in the output area.

If you need the complete code, let me know - post a comment. At the moment, I'm too busy to put together a zip file and post it somewhere.

enjoy,
Charles.

Flex: The World's Simplest Example of RemoteObject

Here is a very, very simple example of using the RemoteObject RPC services in Flex 2 to invoke methods on a Java object. I came up with this because I was struggling to figure out all the stuff needed to do this. In theory, it's pretty simple, but there are a number of components to deal with, and they all get put in different places on the server, and a bunch of those places look very similar to other places on the server.

Introduction


It was especially difficult for me because I'm new to Flex, and I'm coming at it from a server-side background in Java. I don't care about making pretty user interfaces (that's someone else's job) - I'm the guy who has to make the server code work. However, most of the documentation assumes that you're coming at it from the other end - the client side.

I couldn't find any simple examples of using RPC in Flex 2.0. I foolishly started with Flex 1.5 example and wasted a bunch of time updating the syntax in it in order to get it to compile.

After I got that to compile (from the command line - I'm old school), it wouldn't run. After I got the Flash debugger working, I could see that the messaging destination didn't exist, but I couldn't figure out why. So far as I could tell, I had configured it correctly, but there was no indication that things were making it to the server. Finally, I gave up my command line and put the MXML file on the server, and just let the web-tier compiler do it for me.

And, it just worked! The documentation makes reference to using the SDK compiler versus the web-tier compiler, but it just didn't click with me. But, it was still more complicated than I needed. So, I created the following, to prove that I could do it, and that I knew all the voodoo needed.

I will assume that you have the Flex Data Services demo server with Jrun installed an running. I will specify all paths from the root of the jrun server.

Java Code


Let's start with the simplest function in a Java file - basically, "hello world."


public class SimpleRemoteObject
{
public void writeToConsole(String msg)
{
System.out.println("SimpleRemoteObject.write: " + msg);
}
}


This will just write a message to the server console window. (We don't even have to use any fancy Java logging.)

Compile that file and put the SimpleRemoteObject.class file in the directory jrun4/servers/default/samples/WEB-INF/classes on the server. (Note that since the class is in the unnamed, default package, we put the class file in classes, not a subdirectory.)

Flash Client


Now, we need a simple Flash app. Here's a simple MXML file:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
backgroundColor="#FFFFFF"
initialize="initApp()">
<mx:Script>
public function initApp():void {
}

public function writeToConsole():void {
remoteObj.writeToConsole("hello from Flash client");
}
</mx:Script>

<mx:RemoteObject id="remoteObj" destination="sro">
<mx:method name="writeToConsole"/>
</mx:RemoteObject>

<mx:Form>
<mx:FormItem>
<mx:Button label="Write To Server Console" click="writeToConsole()"/>
</mx:FormItem>
</mx:Form>
</mx:Application>

Create a directory called sro under jrun4/servers/default/samples and put the MXML file there.

Now, we can compile the file by loading it in the browser with a URL like:
http://192.168.123.130:8700/samples/sro/SimpleRemoteObject.mxml
(The key is that the file is under /samples/sro based on where we copied the file.)

Don't click the button yet! We still have to configure the FMS destination. Just make sure it compiles correctly.

Configure the Server


Add the following XML code to jrun4/servers/default/samples/WEB-INF/flex/remoting-config.xml. Just put it within the service tag for the remoting-service - e.g., near one of the other FMS destinations.

<destination id="sro">
<properties>
<source>SimpleRemoteObject</source>
</properties>
</destination>

And now, if you press the "Write to Server Console" button, the message, "hello from Flash client" will appear in the Jrun server window.

That's it. It really is as easy as Adobe says it is...
once you figure it all out.

enjoy,
Charles.

Friday, July 07, 2006

Tip: Managing Applications on OS X

I've heard that some people complain that Mac OS X doesn't have anything comparable to the "Start" button on Windows. I've never felt that way, but I have to admit, I'm amazed that some people always use the Finder to navigate to the Applications folder to launch application. If that's your way of starting applications, then I can see why you'd think you need a start button.

Below are some really simple tips to manage the applications and get the "Start button" functionality using the existing Dock.


  1. Put Applications in the Dock: Begin by dragging the Applications folder to the dock. Open a Finder window, grab the Applications folder, drag it down to the dock, and let go of it to the left of the vertical bar that separates the applications from the Trash Can. Now, you have a "Start button." To use it, bring the mouse down to the dock, position it over the Applications folder, click and hold (for a second or two), and the list of applications will shoot up from the folder. Move the mouse over the application you want to launch and (finally) let go of the mouse button.
    I've used this from the very beginning of when I started using OS X. It's so simple, but it makes the system so much easier to use. It drives me up the wall to work on a stock OS X system where you have to use the Finder to go to Applications to launch an application.

  2. Create local applications folder: Once you've installed more than a few applications on your Mac, the "start button" we created above will be too big - you'll have to scroll to find the application you're looking for. What you need is to organize the applications in the Applications folder by creating some folders within the Applications folder. Therefore, create a folder for your new applications. I called my folder "Local Applications." Anytime you install new applications, put them in there instead of Application.
    If you have a bunch of existing applications, it seems to be OK to just move them into your folder. However, take it from me: do not move any of the Apple applications - when Software Update runs, it will install things in the original location. Now, those applications are available from the "start button" under the name for your folder - e.g., "Local Applications."

  3. Create a short list of favorite applications: Even with the benefits of the organization we set up above, the list is still long, and it contains a bunch of applications that you hardly, if ever, use. Create a new folder pretty much anywhere - e.g., in your home directory. Open a separate window in the Finder and navigate over to Applications. For any applications that you use regularly (either in Applications or Local Applications) create an alias of the application (right click/control click on the application icon and choose "Make alias") and drag the new alias into your new application folder. I also include aliases to Applications, Utilities, and Local Applications in my folder.
    Finally, drag your new folder into the Dock (and optionally remove the original Applications folder you put there). From this new "start button," you can quickly reach the applications you use regularly, and if you included Applications in your folder, you can reach everything else, too - the best of both worlds: quick access and complete access.

  4. Change the icon: Optionally you can change the icon of your applications folder - I copied the icon from the original Applications folder into my personal applications folder, but you can use almost icon.
enjoy,
Charles.

Monday, June 26, 2006

Book: File System Forensic Analysis

File System Forensics by Brian Carrier. ISBN: 0321268172.


To my way of thinking, this is a really good book about file systems, that just happens to use forensics as a unifying theme and framework under which to study the file systems. The book provides the most detailed coverage of file systems I've seen, short of reading the source code. I used it as a textbook in an advanced operating systems class, but it is not really a textbook, per se.

The author begins with an introduction to the concepts behind digital forensic investigations. He continues with a ground-up introduction to disk drive technology and how disks are used in computer systems. The introductory material concludes with a generic framework for discussing the components and characteristics of file systems.

With all the groundwork laid, the meat of the book consists of detailed discussions of FAT, NTFS, Ext, and UFS file systems. Each file system is presented at a high level first, followed by a detailed description of the structures on disk. The high level information is presented with pictures and via output from the author's file system toolkit (The Sleuth Kit). The details are presented with tables of structure members without resorting to C code, which makes it easier to see the trees rather than the forest, especially for non-programmers.

I found the information about the Microsoft file systems (FAT and NTFS) especially useful, since there isn't much real documentation on those file systems available, and a lot of what is available seems like rumors spread at recess in a schoolyard.

In conclusion, this is a really good, perhaps even the best, book on file systems, even if you're not into forensics. If you're looking for serious details about file systems or forensic analysis of file systems, this is your book.

Enjoy,
Charles.


Wednesday, June 14, 2006

Welcome to Western Skies

Welcome to the Western Skies technology blog. The purpose is to share information related to the technologies that I am involved with. Eventually, this will grow into the corporate web site for the Western Skies Technology Group with a real domain name, but that will require paying off the domain squatters that have the domains I'm interested in.