Wednesday, November 18, 2009

Random notes from Kynetx 2009

Phil Windley

Here are other projects in this same space as Kynetx:
  • Gist - Web content for your inbox via an Outlook plugin
  • Switch Book - Search Context
  • Adaptive Blue - Media Toolbars
  • Kynetx - Context Automation Framework
  • Google - SideWiki

"Content is less important than context."
  • Clay Shirky did an experiment: only 6% of his local newspaper was local content. And we wonder why newspapers are dying.
  • If content is so important, why does a Stephen King book cost the same as one by a first-time-author (pointed out by Paul Graham)?
Sam Currens

Where can Kynetx help with security, since it's all client-side and has the power to do very malicious things?
  • Kynetx can turn off malicious scripts.
  • Kynetx can create reputation and certification processes/systems for applications/organizations.
Dave McNamee

Endpoints

Who are the trust providers in the information card space? None needed: the stuff is encrypted.
Azigo Lite vs Azigo

Datasets
intrinsic, Ambient context vs active context
pick to parse out data

Sweetter - bookmarklet for recent tweets about a website
ClearPlay - to show if a movie from Netflix, IMDB, etc. is available on ClearPlay
SkullCandy - show on certain sites

Public apps (with source) are here: http://appdirectory.kynetx.com/

Doc Searls' talk about "The Intention Economy" at Kynetx 2009

He recommends the online comic "Gaping Point."

We're trapped into thinking that a "free market" means "your choice of captivity (vendor)".

Even with social media, each site is a silo. So how do we get to personal, and "prove that a free customer is more valuable than a captive one?"

VRM (vendor relationship management) is one approach for us consumers, the reciprocal of and complimentary to CRM.
  • manage our own health care data, eg. PHR (personal health records)
  • "personal RFP" for my personal needs
  • assert our own terms of service
  • "Have governance of and by - and not just for - the people"
(Take a look at public radio player, where the VRM "CD" logo gives their VRM compliance level.)

See projectvrm.org

"4th-party": someone who helps the buyer relate to the sellers (and their 3rd-parties).

(QOTD: "We're all climbing up the volcano of Google and allowing their free software to wash over us.")

(BTW, Doc never answered the question: "How do we prove that a free customer is more valuable than a captive one?")

Monday, November 16, 2009

Why does XML not allow nested comments?

I hate the fact that XML doesn't allow nested comments! Since I have comments in almost every source file I write, and since I frequently want to disable portions of my code, I hit this problem a lot

I finally found out why they don't allow nested comments, or any "--" inside: the original SGML has some complicated rules about double-dashes and how they change the parsing inside a comment, and the XML spec mandates that XML docs are valid SGML, so it is more restrictive and says that XML cannot contain any double-dashes.

So, basically, I want to throttle whoever came up with this complication in SGML. Maybe the person to blame actually introduced this in a previous spec... but anyone who puts this kind of trickiness into a standard should be blacklisted from IT work permanently. Argh!

Thursday, October 15, 2009

Java Tutorial for Absolute Beginners

(I want to give programming newbies an introduction to Java, but in a way that they can do it independently such that the tools won't get in the way (eg. 'javac' to compile, 'java' to run, avoiding classpath issues, and so on). I think the best fit is to have them use Eclipse (or another Java IDE), which will allow them to get to the code quickly; hopefully the IDE won't distract them. Unfortunately, I cannot find any existing tutorials that fit the bill, so here's a set of instructions that I hope will work better.)

  1. Complete steps 1-4 of the Eclipse Java IDE tutorial. I assume you will be able to find and install Java and Eclipse (which are installed separately); when you choose a Java or Eclipse download, just choose a "Java" version... there's no need for anything fancy like "Java EE".
  2. Jump into "Part 2: The Syntax" of Brewing Java: A Tutorial, but stop when you get to "Command Line Arguments".
  3. In Eclipse, try to run the "Command Line Arguments" example, but realize that you'll get an error.

    In order to supply run-time data to your program, you'll have to add an argument to run it: right-click on your program and select "Run As...", but then instead of "Java Application" choose "Run...", then click on the "Arguments" tab and fill in something (like your name) and click "Apply".

    Now "Run" your program and you should get some good output.
  4. Now you can continue with Brewing Java: A Tutorial. If you get this far, you should be able to do the rest of any other tutorial out there.
Good luck!

Sunday, October 4, 2009

Rubik's Cube Cheat Sheet

I finally sat down and followed instructions to solve a Rubik's Cube. I used Dan Brown's videos, and here is my summary of the instructions... useful for reference until I have them memorized.

(F=turn front side clockwise / U=up side / D=down side / L=left / R=right, with cc=counter-clockwise)


1) Goal: Top Cross
Move one into correct spot. If flipped, put in front then:
Fcc U Lcc Ucc

2) Top Corners
Get one in or under spot, then:
Rcc Dcc R D

Now put the solved side on the bottom.

3 & 4) Middle Edges
Find one not matching now-top color, move by matching side color, then..
... if going left:
Ucc Lcc U L U F Ucc Fcc
... if going right:
U R Ucc Rcc Ucc Fcc U F

5) Cross
If "L" then put back-left, if line then put horizontally, then:
F R U Rcc Ucc Fcc

6) Match Edge Sides
Put one that matches side colors in back and the other to right or front, then:
R U Rcc U R U U Rcc

7) All Upper Edges in Correct Spots, Possibly Turned
If any in correct spot, put in front-right, then:
U R Ucc Lcc U Rcc Ucc L

8) Corners
Put any unsolved in front-right, then:
Rcc Dcc R D ... and maybe repeat until just that one is correct (even if the rest of the cube is messed up)
... and then Ucc and repeat for each unsolved upper corner

Wednesday, September 16, 2009

"That's Not My Name" lyrics

I finally found the full set of lyrics for "That's Not My Name" by The Ting Tings; I have been especially searching for the words from the guy (Jules) who sings lower underneath at the end, and here they are:

This song was in my head, now it's in my mind,
Call it, reach it, get some words and get some timing,
Though I realize, I cannot emphasize,
I'll stick around, but just a promise, nothing binding,
However can't you see, that you're so desperately,
A standing joker like a vocal one-liner,
Instead of sing-along, this song is monotone,
Gotta get some soul, gotta get some feeling....


I found them all on this YouTube video page, which Jessi S says is the "official video".

Wednesday, July 1, 2009

Consolidating Spreadsheet Lists

I sometimes have to get a list of unique items either by removing duplicates or by pulling the items from two lists (by finding the elements missing from one of them). These are easy to figure when you have the data in a SQL database, but it's a little tougher using only spreadsheet functions. Below are two example approaches.

Update: I just learned about the COUNTIF function that might help; check it out first. Another possibility may be to "Paste Special..." and "Skip empty cells", but that doesn't always work. Another possibility would be to make a database out of the data and search for non-empty cells, but this has proven tricky (and it's many steps, anyway).

Find the Unique Items

This is like the SQL "SELECT DISTINCT word FROM words" (Update: this may not work when 2 cells are skipped!)
  1. Put the list in column A starting in row 1.
  2. In column B next to each value, paste a function which detects whether the item is a desired one; in this case, it's the last item in each run:

    =NOT(EXACT(A1;A2))
  3. In Column C, put a counter down to each desired element:

    =IF(B1; 0; C2+1)
  4. In column D and row 1, paste this function to tell where the first element lies:

    =C1 + 1
  5. In column D in the other rows, paste this function to tell where the next element lies:

    =D1 + 1 + INDIRECT(ADDRESS(D1+1; 2))
  6. In column E in each row, paste this function to tell each unique item in succession:

    =INDIRECT(ADDRESS(D1; 1))

Find the Elements Missing (when compared to another list)

This is like the SQL "SELECT * FROM words WHERE word NOT IN ('forbidden', ...)"
  1. Paste the main list into column B and the sublist into column A.
  2. In column C, put the function to find the desired one (like step 2 above); in this case, VLOOKUP function to detect if the item from B exists in A:

    =ISERROR(VLOOKUP(B1; A$1:A$999; 1; 0))
  3. The rest of the steps are the same as steps 3-6 above. In column D, we count down to the desired element:

    =IF(C1;0;D2+1)
  4. In column E row 1, we put the row of the desired element:

    =D1 + 1
  5. In the rest of column E, we find each element:

    =E1 + 1+ INDIRECT(ADDRESS(E1+1;4))
  6. In column F, we find the value:

    =INDIRECT(ADDRESS(E1;2))

Monday, June 22, 2009

Base Test Class with Maven

I've got some base Test classes (with settings for Spring, Wicket, etc) that I want to reuse in my integration tests, and I've put them under a 'test' directory (instead of 'main'), but that means that they don't get built and included in the main artifact. Here's how I forced Maven to build it into a test artifact (in the build/plugins section):


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>


... and here's how I included it as a dependency in the other projects:


<dependency>
<groupId>com.max.services</groupId>
<artifactId>MaxServices</artifactId>
<version>1.0.2-SNAPSHOT</version>
</dependency>

Base Test Class for Spring

When using Spring to configure my web application, I usually want to employ the same XML configuration file as the application, especially for database access. So here is what I currently use as the base class for all my integration test cases.


public class ServicesTestBase extends AbstractTransactionalDataSourceSpringContextTests {

private static final String CONFIG_LOCATION = "/context/applicationContext.xml";

@Override
protected ConfigurableApplicationContext createApplicationContext(String[] locations) {
ConfigurableWebApplicationContext appContext = new XmlWebApplicationContext();

// this is org.springframework.mock.web.MockServletContext
MockServletContext servletContext = new MockServletContext();
servletContext.addInitParameter(JMXSpringMBeanNamingStrategy.CONFIG_INIT_PARAM_NAME, CONFIG_LOCATION);
appContext.setServletContext(servletContext);

appContext.setConfigLocations(locations);
appContext.refresh();
return appContext;
}

@Override
protected String[] getConfigLocations() {
return new String[]{ CONFIG_LOCATION };
}
}


In addition to those two methods, earlier projects have overridden the 'onSetupBeforeTransaction' method as follows, although I found I haven't had to do this for my plain old integration tests:


@Override
protected void onSetUpBeforeTransaction() throws Exception {
// this is our own home-grown class which you may not need; source may be available by request
StaticApplicationContext.setContext(this.applicationContext); // Do this BEFORE onSetUpBeforeTransaction()
super.onSetUpBeforeTransaction();
}


However, on my Wicket project, I did have to play around with it a bit, so here is what I created for the 'HomePageTest':


@Override
protected void onSetUpBeforeTransaction() throws Exception {

StaticApplicationContext.setContext(this.applicationContext); // Do this BEFORE onSetUpBeforeTransaction()

super.onSetUpBeforeTransaction();

AuthenticatedWebApplication authenticatedWebApp = new BackOfficeApplication() {
@Override
public void init() {
addComponentInstantiationListener(new SpringComponentInjector(this, HomePageTest.this.applicationContext));
initForAppAndAllTests();
}
};
tester = new WicketTester(authenticatedWebApp);
}


One thing you might have noticed is that JMXSpringMBeanNamingStrategy, so I'll explain real quick: it's to allow me to share the same applicationContext.xml file with all my web app contexts such that the JMX engine won't break due to duplicate names. It's inserted this way:


<!-- (Initially copied from http://static.springframework.org/spring/docs/2.0.x/reference/jmx.html ) -->
<!-- This bean must not be lazily initialized if the exporting is to happen. (comment from docs) -->
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
<property name="namingStrategy"><bean class="com.max.utils.JMXSpringMBeanNamingStrategy" /></property>
<property name="beans">
<map merge="true">
<entry key="com.max.services.forWebApp:name=data-source" value-ref="dataSource" />
<entry key="com.max.services.forWebApp:name=log4j-settings" value-ref="log4jBean" />
<entry key="com.max.services.forWebApp:name=test-settings" value-ref="dynamicTestSettings" />
</map>
</property>
</bean>


Here is how it's defined; you can tell that it's not ideal, but it's what I got:


public class JMXSpringMBeanNamingStrategy implements ObjectNamingStrategy, ServletContextAware {

public static final String CONFIG_INIT_PARAM_NAME = "contextConfigLocation";

private ServletContext context;

public void setServletContext(ServletContext _context) {
this.context = _context;
}

public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException {
// There's got to be a better way to get the context name of this app!
String springWebAppConfigFile = context.getInitParameter(CONFIG_INIT_PARAM_NAME);
String configName = springWebAppConfigFile;
configName = configName.replace("classpath", "");
configName = configName.replace("webapp", "");
configName = configName.replace("xml", "");
configName = configName.replace("context", "");
configName = configName.replaceAll("[\\:\\/\\.\\-]", "");
String newBeanKey = beanKey.replaceFirst("forWebApp", configName);
return new ObjectName(newBeanKey);
}

}

Tuesday, May 12, 2009

logging the XML payload with Axis, XFire

When using Axis to send data to a web service, you can set the logger level on org.apache.axis.transport.http.HTTPSender to DEBUG to see what's going out.

When using Xfire to receive data, you can set the logger level on org.apache.axis.transport.http.HTTPSender to DEBUG to see what's coming in.

Here's a sample in log4j.properties:


log4j.logger.org.apache.axis.transport.http.HTTPSender=DEBUG
log4j.logger.org.codehaus.xfire = DEBUG

Monday, May 4, 2009

My winner for to-do task lists: Toodledo

FYI: I've settled on Toodledo.com to manage all my tasks. It has a good interface and many ways to display my tasks, and there's an Android app for my G1 (even though I usually just browse to their web page). Oh, and it's got a free subscription level.

Here are the few improvements I'd like to see:
  • There's no "edit task" screen; you edit everything on the list page... which isn't necessarily bad, just something to get accustomed to... except that the next problem comes into play because...
  • You choose the fields to use, and that's what shows everywhere. When I hid some of the fields (like tags, because I didn't use them on the main screen), suddenly I couldn't edit the tags and I couldn't view by tag (across the top). This may not be a huge problem either since I can resize the columns on the list view; I'll just have to get used to it.
  • I'd like to have multiple (or hierarchial) contexts for a task, such as "shopping" and also "shopping-grocery" (vs. "shopping-auto"). So I'm actually using the tags to store my contexts.
  • I could use an Android app that sorts according to the Toodledo importance sorting.
This post is definitely heavy on the criticism, but I highly recommend Toodledo.

Thursday, April 2, 2009

Is there an amendment to this Congressional bill or not?

First, a little motivation: I've been helping the Sunlight Foundation in their initiative to pass Senate bill 482, which forces Senators to submit their filings electronically like everyone else (eg. Representatives) which saves money and makes that information available in time for elections. They say that someone is going to attach an unpalatable amendment which will kill support for it. When I called my Senator's office, they said that there couldn't be an amendment yet because it wasn't out of the committee. OK, I believe her.

So here I am a few weeks later and I want to have all the information the next time I call. It looks like their claim about a "poison pill" amendment is based on heresay, and they even say that it's not proposed yet. It turns out that something happened with an amendment in the last congress (purportedly in a very secretive way) where the same bill was introduced as S 223... but that Open Congress listing does not show any amendments. What are they talking about? OK, so let's go to the source: thomas.loc.gov is the official Library of Congress site for these bills, and they have a page for S 223, but that doesn't show any amendments, either!

I must point out that this is the point where, after all the frustration of navigating through the details and speeches about this bill, I hit something interesting. (My frustrations include trying to find permanent links to this data, because they generate temporary files for your own search results. Ug!) I finally found where the drama comes to a head on the floor of the Senate: in the last 5 paragraphs on this page, you can see where they are asking to proceed with the bill, but someone says "on behalf of the Republican side, I object." And that's the end of it. Crazy! I guess that simple objection carries enough weight to kill the whole thing.

OK, so where is this fabled amendment that killed the bill? It's mentioned in the speeches, and in this comprehensive summary of the bill it says things like "reported with an amendment". But you can't find the thing.

Hm. I just found that there is one published amendment: when I click on the "Text of Legislation" on the search results page, I end up at something that lists two versions of the bill, and the second one shows that some of the text has been stricken out (and it's especially obvious in the PDF Display). Very well. But that's not the amendment that killed it.

As my last gasp for enlightenment, I go back to the blog entry that gives more details about the behind-the-scenes action, plus the subsequent plea to stop the obstruction, and it appears that we have no real record of who did what and why. It's helpful to look through some of the other items "In The News" for this bill on OpenCongress.org; one of them is even an online appeal for help by the bill's sponsor. So I guess there isn't really any proposed amendment in writing; someone just wielded some operational rule and single-handedly killed it before it got to a vote.

I still haven't found the trail leading back to the McConnell Amendment. Time to try and ask questions to the bloggers at Open Congress... if I can find a way to log in...

(Any other suggestions?)

Wish me luck!

UPDATE (2009/04/16)

I found the introduction of this bill to the floor of the senate, where there was the original objection "on behalf of a Republican Senator". For some reason, they must "ask unanimous consent that the Senate proceed to the immediate consideration"; "unanimous consent" is for bypassing rules to expedite some action, but why do we need to bypass rules to call this to a vote? Aren't there some normal rules we can follow to get this passed, so that one Senator can't block this thing?

BTW, it was very difficult to find a bookmarkable link to these pages; luckily I found one in my earlier searches, and I tweaked that because I couldn't find any way to get that link again. Anyway, I guessed at URL changes to find one that gets me to a list of pages for that day's business; other pages show the full text, but every once in a while you're stuck with one like this that just has links, and I cannot see why. So, here is the link; you can see the session as "110", the Senate as "S" (vs. House as "H"), the date of 17 Apr 2007 as "17AP7", and the page as "0018":

http://thomas.loc.gov/cgi-bin/query/z?r110:S17AP7-0018:

Tuesday, February 24, 2009

Carrying around my Dropbox (on removable media)

I keep a small set of files with me at all times; these are my essential files I keep backed-up so even if my computer dies, I can recover my basic information... my personal to-do list, contact list, etc. I can access these files at work, at home, and even on my phone. (Unfortunately, I just learned that a Mac will not read the file system, so I've got to find a way to deal with that). I've tried a few tools to help me keep my files in sync (Darcs, SVN), but recently I switched to Dropbox; it does a fantastic, trustworthy job automatically, so I highly recommend it.

Unfortunately, I've hit a couple of snags trying to keep these files with me. This post is all about what I've done to solve these problems.



I need to access my Dropbox files from removable media (even on Windows).

I read (and edit) my files on my phone sometimes; I haven't had a data-plan, so I've been copying files on and off an SD (or recently a microSD) card that I can edit on-the-go. By default, Dropbox will not allow you to install your files on a removable drive, so I cannot put these files on my micro SD card that I keep with me and use on my phone. (Actually, I could copy the files, but now that I can edit files on my phone I want to be able to plug the card into a computer and let it sync them all automatically.)

On *nix and the Mac, there's no problem installing to a different location.

On Windows, things are tricky. There are 3 tools on the Dropbox site that might help with this: Dropboxen, DropboxPath, and DropboxDataWrapper. I finally got DropboxDataWrapper to do what I want:

  1. Shutdown your running Dropbox.
  2. Run DropboxDataWrapper as indicated and specify the path on the external drive where you want the files.
  3. At the end, be sure NOT to check the box saying "I want to choose the location"; after you click "go to my dropbox" it'll complain about not finding things in the default location, but you'll see it running and you'll see it download things just fine to the path you specified. Note that if you right-click on the Dropbox service and select "Open My Dropbox", you'll get an error about the wrong location, so you'll always have to browse to that folder manually.
So by default, Dropbox will sync up my files from my default location, but then I can stop Dropbox, plug in my card, and run DropboxDataWrapper to sync it up.

(FYI: I couldn't get Dropboxen to work at all, and DropboxPath just changed my current path but didn't allow me to run Dropbox for my both removable disk and the default location.)

This isn't perfect: I've found a computer where DropboxDataWrapper didn't work right the first time, but I didn't have time to investigate so I quickly gave up and tried something else.





I need to be able to update my removable media from any OS (Linux and Windows).

After I saved my files to my card, things are great except that I had 2 versions of my Dropbox on there, one for Windows and one for Linux. Thankfully, each OS uses different configuration files, so I found I could put them all in one location and things are working; when I get on Windows and plug in, my files sync up, and then later when I get on Linux they sync up there, too. Here's how I set it up:

  1. Change all your Windows files and directories to writable. I did this at the level of my Dropbox folder:
    chmod -R u+w .

  2. Copy the .dropbox files from your Linux files on the external card into the same place in the Windows files on the external card. I only had three: one at the same level as Dropbox, one under Photos, and one under Public.
  3. Make a folder somewhere else to hold your Dropbox files. (You cannot do this on your card if it's formatted with a Windows filesystem because the next step will fail; Linux won't allow you to create the symbolic link.)
  4. Inside that folder, create a symbolic link to the Windows "My Dropbox" folder.
  5. Copy the .dropbox folder from your Linux files on the external card (at the same level as the Dropbox folder) into the Windows files on the external card (at the same level as the "My Dropbox" folder).

Now, it looks like each OS has a different version of some .dropbox files when I have shared folders, so we'll see what happens with those.




Hope this helps. I'll update this post if I learn more.