Thursday, November 27, 2008

Maven, Woodstock and Netbeans 6.5

I spent quite a bit of time trying to "mavenize" our woodstock based project. I am sure someone will point out how to do this easier, but I was unable to find a reference. This magic works for me and I haven't been able to find something simpler.

At the high level, what I did was create a standard webapp project with the option to create a dedicated library. I used the .jars in that directory to populate my own repository on my own web server (using mvn deploy:deploy-file). I created a maven webapp project, and edited the pom.xml to reference my repo. I then copied WEB-INF files from a working woodstock project into my new maven project WEB-INF. Then created a couple of VWJSF pages in the new project, with a couple of restarts and "make clean"s. It was most surprising that the first VWJSF page fails, bu subsequent ones work.

Thanks to Robert Hook for giving me the idea to use the .jars placed in the "Dedicated library". I tried the rest of the recipe without this step but it does not work. Most of the entries are probably irrelevant because the IDE puts its own entries in the pom.xml, copying SNAPSHOT versions of some of these files to your local repo. But which ones, I do not know. If I had more time and patience, I would pull out the ones that appear to be replicated and see if it works.



<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany</groupId>
<artifactId>Try999</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Try999 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.woodstock</groupId>
<artifactId>jsfcl</artifactId>
<version>6.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.woodstock</groupId>
<artifactId>appbase</artifactId>
<version>6.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.woodstock</groupId>
<artifactId>dataprovider</artifactId>
<version>6.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.woodstock</groupId>
<artifactId>sqlx</artifactId>
<version>6.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.woodstock</groupId>
<artifactId>webui</artifactId>
<version>6.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.woodstock</groupId>
<artifactId>commons-fileupload-1.0</artifactId>
<version>6.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.woodstock</groupId>
<artifactId>defaulttheme</artifactId>
<version>6.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.woodstock</groupId>
<artifactId>errorhandler</artifactId>
<version>6.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>1.2_04-p01</version>
</dependency>
<dependency>
<groupId>javax.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>1.2_04-p01</version>
</dependency>
<dependency>
<groupId>commons-digester</groupId>
<artifactId>commons-digester</artifactId>
<version>1.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>jsfcl</artifactId>
<version>SNAPSHOT</version>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>appbase</artifactId>
<version>SNAPSHOT</version>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>dataprovider</artifactId>
<version>SNAPSHOT</version>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>sqlx</artifactId>
<version>SNAPSHOT</version>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>webui-jsf</artifactId>
<version>SNAPSHOT</version>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>commons-fileupload-1.0</artifactId>
<version>SNAPSHOT</version>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>json-2</artifactId>
<version>SNAPSHOT</version>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>jsf-extensions-common-0.1</artifactId>
<version>SNAPSHOT</version>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>jsf-extensions-dynamic-faces-0.1</artifactId>
<version>SNAPSHOT</version>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>webui-jsf-suntheme</artifactId>
<version>SNAPSHOT</version>
</dependency>
<dependency>
<groupId>unknown.binary</groupId>
<artifactId>errorhandler</artifactId>
<version>SNAPSHOT</version>
</dependency>

</dependencies>

<repositories>
<repository>
<id>woodstock</id>
<name>woodstock</name>
<url>http://YOURREPO.COM/woodstock/</url>
</repository>
<repository>
<id>javanet</id>
<name>javanet</name>
<url>http://download.java.net/maven/2/</url>
</repository>
<repository>
<id>jsf12</id>
<name>Repository for library Library[jsf12]</name>
<url>http://download.java.net/maven/1</url>
<layout>legacy</layout>
</repository>
<repository>
<id>unknown-jars-temp-repo</id>
<name>A temporary repository created by NetBeans for libraries and jars it could not identify. Please replace the dependencies in this repository with correct ones and delete this repository.</name>
<url>file:${project.basedir}/lib</url>
</repository>
</repositories>

<build>
<finalName>Try999</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.2</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<netbeans.hint.deploy.server>Tomcat60</netbeans.hint.deploy.server>
</properties>
</project>

Saturday, July 05, 2008

Saving Energy with Wake-on-LAN

Another tech posting, nothing about leadership today.

I confess: have a lot of computers. Two of them are on full time - one hosts a web site and one hosts a development repository using SVN over an SSH tunnel. After two years of the SVN machine being on 24x7, I wondered if I could put it to sleep and just wake it up when needed. This led me to the Wake-On-LAN feature which was a little harder than I first thought.

First of all, the SVN host is a Apple G5 running 10.4. That matters because I also have the machine set to require a password to access the machine when it wakes up from sleep or screen saver. It turns out that if you remotely wake up your mac under this setting, when the login dialog times out and would normally go back to screen saver, it goes back to sleep mode. I haven't figured out a way to fix this remotely - you would need to login very quickly using VNC or something. The workaround is to never go into sleep mode unless you are at the main login window (you can get there using the "switch user" button or click on the user name in the upper right and then select "login screen"). This realistically prevents me from setting the machine to automaticaly sleep.

Secondly, even though I am providing the ethernet mac address directly in the wakeup utility, the SVN host machine is a gateway and a switch away from the source. I was really frustrated because my laptop running Dirk Lembens' Wake-On-LAN utility would always work, but if I tried a web site or a local linux machine to send the magic wake-on-lan packet, it would only work shortly after the SVN host was put into sleep mode. After thinking about it a bit, I proved that it started to fail when the ARP entry was removed. Only then did I find some resources for the problem.

What I ended up doing is using a perl version of a wake-on-lan utility (runs on OSX as well as linux by the way), and preceded it with an "arp -s" call to seed the ARP cache (I assume Dirk's utility does this also). I stuck the script on the linux box that hosts our web site; my partners can run the script via ssh. So with a simple script to provide the details, they can now wake up the SVN server from anywhere in the world, and I can save a few watts and CO2 in the process.

Only thing left to do is figure out how to remotely put it to sleep. Dirk's utility does this via applescript for Apple machines only, but it doesn't seem to be working for me. Also, this could run into trouble with the problem I mentioned regarding the login timeouts.

Saturday, May 10, 2008

Repairing an 85W Magsafe Power Adapter

A little different post today - not about leadership, process, or some great new technology. It's about fixing something yourself; fixing things sometimes pleases me almost as much as creating things. After you read this, go get a copy of Sam Martin's How to Mow The Lawn.

I love my Macbook Pro. I like the idea of the Magsafe adapter, but I'm not happy with the fact that it's single sourced. I guess iGo hasn't reached a licensing agreement with Apple for the technology, because it isn't as complex as you might think. Since it's expensive, I carried around the one adapter I have. That is ... until the cord wore out - the wrapping and unwrapping of the magsafe side eventually wore out the cable. When I took it to the Apple store I learned it wasn't repairable (don't get me started on sustainability concerns). I bought another adapter, and was hoping I might be able to fix the one I have so I don't have to repeat this problem.

I was expecting a lot of complexity in that cable, since it has numerous pins at the laptop end, and operates the little orange/green LED somehow. However, this is a no brainer to fix electrically, it's really a packaging problem, because the case was not designed to be disassembled (or re-assembled). So I thought I'd document what I did so others can keep these little guys out of the landfill, and maybe save $60 in the process. The one I repaired was the older, larger adapter.

The case appears to be a press fit with some glue. I couldn't pry it open with a screwdriver or putty knife, and since I wasn't expecting this to be so successful, I very quickly pulled out the Dremel tool cutting wheel. I arbitrarily chose the side with the metal post -- which turns out to be the best place to start. There is a heat sink behind this side that won't get hurt if you cut into it a little bit. I cut into it and started to pry.




I was doing pretty well - the sides opened up pretty easily, but was afraid to crack the case so decided to cut a little bit into the opposite side.





At this point I was a little exuberant and let the corner pieces fall out when I finally got the case open. Not a big deal but pay attention to how they fit. There are three pieces per corner where the cord wrapper device is.

This is where the real surprise hit me. There are only two wires in the coaxial cable. The white one goes down the middle and the black one is the wrapper. I was expecting the little cord protector to just slide off, but it won't.

So rather than unsolder the wires and resolder the cable to the board, I decided to use a razor knife and cut away the cord protector. This turned out to be pretty easy. After stripping away the insulation I soldered the wires to each other, and wrapped in electrician's tape (I was too lazy to find the heat shrink tubing - but that is the correct way to do it - get some at Radio Shack).


I then tested the beast before physically reassembling the case. Be careful here - I felt a slight shock when I touched the metal parts. It worked.

I superglued the case together and added hot glue where I had a large gap from the first cut, as well as around the hole where the cord comes out. I clamped it together in a vise to let it dry. Here I apparently didn't have one of the corner pieces in completely right and I broke a pin off. I used a palm sander to clean up the case exterior (and learned, by the way, that hot glue doesn't sand very well - keep it neat and remove excess with a razor. Not beautiful, and probably no longer rugged enough for travel, but it is safe and it works.

Level of Difficulty: Low
Time: 30 minutes if you don't break anything
Tools: soldering iron, Dremel with cutting wheel, #10 and #16 wirestrippers, hot glue gun, sander, vise (or clamps or rubber bands), screwdriver or putty knife, Box Cutter or Xacto
Supplies: Solder, Electrical Tape (or Heat Shrink Tubing), hot glue, superglue

Sunday, March 30, 2008

ACM queucast

The Association for Computing Machinery (ACM) has a podcast series called "queuecast". It's a fairly quiet feed since many of them are "premium". But I very much enjoyed the recent queuecast featuring Jason Hoffman, CTO of Joyent. In the first segment, he talks about how he "isn't interested in evolution", in response to his developers saying they want to iterate and evolve the product. His reasoning is simple and sound: evolution is about survival, not optimization. Survival means anything that works survives; it doesn't mean that you'll be the best in your class, and it doesn't mean you will use resources most efficiently.

Monday, January 21, 2008

Vicious Measurement

ACM's Queue magazine features a regular Q&A column by someone with the pseudonym Kode Vicious. This month he talks about measurement, in a humorous and short story entitled "Take a Freakin' Measurement". He makes the case that you should measure as much as it takes to reach your desired level of confidence, but that anything less isn't science. His style is different than mine, but I think the message is right on: measure what you need to know and do it well enough to suit the need.

Wednesday, January 09, 2008

Active Design Reviews: So sensible

I'm often embarrassed when I discover a method that has been around for decades, makes perfectly good sense, but I haven't seen it practiced and didn't know about it. Active Design Reviews (ADR) are such a method. First described in 1985 by Parnas and Weiss, they devised a system which mitigates non-participation in design reviews.

ADR changes yes/no questions asked in a design review (e.g. "do you understand it?" and "will this work?") to a set of questions that require understanding to answer. An easy example is "write down the exceptions that can happen with [insert component here]". You can't fake the answer to that - you need to have read and understood the design, and actually put your understanding into practice. The reader will necessarily provide better feedback, although more focused - "higher fidelity" in the words of Clements.

Those of you who are up on the latest techniques probably know that SEI developed ARID, which is a hybrid of ADR and ATAM. ARID takes ADR a step further, by allowing the reviewers to pose the questions rather than the designers, through the choice of "scenarios". This enables focus on a particular area of concern by the people that need to understand it.

So sensible.

Somewhat tangential to this, but this paper about a sane design process, written by Parnas of ADR fame and Clements of ARID and SPL fame, is a great reference for artifacts and process one should think about when creating a design process.