Tuesday, March 16, 2010

calcdeps.py "Missing provider" error

Today I was trying to use the Google Closure compiler to build a single .js file out of several source files and their closure library dependencies:

closure-library-read-only/closure/bin/calcdeps.py -p closure-library-read-only -i bar.js -i foo.js -o compiled -c closure-compiler/compiler.jar > compiled.js

I kept getting errors like this:

Exception: Missing provider for (foo.Foo)

That sucked, since foo.js with its goog.Provide("foo.Foo") was right in the same directory with bar.js, and I even specified it explicitly on the command line.

Turns out I needed to specify "-p ." so that it'd look in the current directory for the dependency. So with a command line of:

closure-library-read-only/closure/bin/calcdeps.py -p . -p closure-library-read-only -i bar.js -i foo.js -o compiled -c closure-compiler/compiler.jar > compiled.js

I got:

Exception: Duplicate provide (goog.async.DeferredList) in ...

That seemed even weirder. Turns out calcdeps doesn't like having the same subdirectory show up twice in -p arguments. That is, "-p ." and "-p closure-library-read-only" was causing it to find the closure library twice. Okay, so we take out the second -p:

closure-library-read-only/closure/bin/calcdeps.py -p . -i bar.js -i foo.js -o compiled -c closure-compiler/compiler.jar > compiled.js

Now I get:

ERROR - namespace "foo.Foo" cannot be provided twice

Almost there: it doesn't like having foo.js explicitly provided. This actually worked:

closure-library-read-only/closure/bin/calcdeps.py -p . -i bar.js -o compiled -c closure-compiler/compiler.jar > compiled.js

Sunday, March 14, 2010

Universal Muses

The universe halted. This would have been traumatic for its inhabitants, had they been able to notice. But their brains had halted along with everything else, so they didn't mind.

"More elevator music. I'm telling you, happiness doesn't make for good art," said Cyn.

"I suppose you're right. I guess I just have a soft spot for them." Fob sighed, twiddling the values in the configuration file.

He pressed a button and erased the 10e80 particle simulation. 175 billion galaxies ceased to be simulated.

Cyn softened. "Look at it this way:the suffering is what gives their lives meaning. No suffering means no art, and no art means there's no point wasting computer time on them." Cyn and Fob shared time on a supercomputer with 10^73 gigabytes of memory, or about 100 times the number of particles in our universe. It had been respectable when it was built, but was starting to show its age.

"Yeah, I guess," said Fob, distracted. "How about this? I'm going to restore the water planet from the pre-life checkpoint, but turn up the resource saturation and sunlight, so they'll really eat each other alive."

"If you really think that'll help. At least turn up the quantum granularity so it doesn't take forever to run."

Fob laughed. "Okay, okay. The poor physicists. Maybe they'll start writing requiems."

Life bloomed and ended. Then bloomed again, and ended. On the third try it caught.

"Giant lizards. Cute."

Cyn and Fob searched the history books, as soon as there were history books. "Hey, some of this architecture is pretty good."

Fob checked another result. "And check out the music. There's a whole cluster of them right around 1800."

"Meh, it's okay. Make this one go deaf and see what happens."

Monday, March 01, 2010

XMPP / asmack / android / Google Talk

OK, I finally figured out how to send and receive XMPP instant messages from my gmail account using asmack with an Android 2.1 AVD. For some reason, the event-driven message receive code doesn't work, but this polling example code does. Here's my latest source:


package com.example.HelloFormStuff;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ChatManager;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.FromContainsFilter;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;

public class HelloFormStuffActivity extends Activity {
public int state = 0;
private static final String TAG = "HelloFormStuffActivity";

/** Called when the activity is first created. */
public void onCreate(Bundle savedInstanceState) {

new Thread(new Runnable() {
public void run() {
//XMPPConnection xmpp = new XMPPConnection("jabber.iitsp.com");
XMPPConnection xmpp = new XMPPConnection("gmail.com");
try {

// for other jabber accounts, truncate after the @
//xmpp.login("username", "password");

// for gtalk / gmail, include the @
xmpp.login("your-gmail-account@gmail.com", "your-gmail-password");

} catch (XMPPException e) {
Log.v(TAG, "Failed to connect to " + xmpp.getHost());
ChatManager chatmanager = xmpp.getChatManager();
Chat newChat = chatmanager.createChat("friend@gmail.com", new MessageListener() {
public void processMessage(Chat chat, Message message) {
try {
Log.v(TAG, "Got:" + message.getBody());
} catch (XMPPException e) {
Log.v(TAG, "Couldn't respond:" + e);
Log.v(TAG, message.toString());

// Send something to friend@gmail.com
try {
} catch (XMPPException e) {
Log.v(TAG, "couldn't send:" + e.toString());

// Accept only messages from friend@gmail.com
PacketFilter filter
= new AndFilter(new PacketTypeFilter(Message.class),
new FromContainsFilter("friend@gmail.com"));

// Collect these messages
PacketCollector collector = xmpp.createPacketCollector(filter);

while(true) {
Packet packet = collector.nextResult();

if (packet instanceof Message) {
Message msg = (Message) packet;
// Process message
Log.v(TAG, "Got message:" + msg.getBody());