Pages

Friday, December 17, 2010

Maven 3 & profiles.xml

There are some pretty cool things in Maven 3 (although mixins and global dependency exclusions have been tabled until 3.1). Matt Raible talks about some of them here. Significant points include dramatically increased performance (50% to 400% faster), unspecified plugin versions will pull the latest version and not snapshot versions (though it's best to be explicit about plugin versions), also Sonatype has developed Maven Shell and polyglot Maven to work with Maven 3.

There are, however, some compatibility concerns when moving from Maven 2.x. And not all plugins work yet. (Most notably they're refactoring the Site Plugin so it's not completely working yet). But the Maven team intends the new release to be usable as a drop-in replacement for Maven 2 (though this won't be the case for Maven 3.1).

Most changes for compatibility seemed pretty trivial. The biggest thing I see preventing Maven 3 from being a drop-in replacement for Maven 2 was their decision to remove support for profiles.xml. This was documented in MNG-4060, though not much discussed there. A few people have complained about this already here and it was discussed a little here. I haven't seen much justification for this, other than it's supposed to be difficult to test. Though I'm not sure why it'd be much harder to test than the use of profiles in the pom.xml. But the Maven team seems for whatever reason fairly committed to this idea, despite one of their committers (Milos Kleint) disagreeing with their position.

People use profiles for a variety of things. Where I work, they are commonly used for environment settings. For example, which version of a particular web service or database to use in prod, qa, etc. But also for which version of that service or database to use for a particular developer's sandbox (another common difference between developers is their log level). These typically use Maven filtering in conjunction with external profiles to accomplish this. These profile properties are also kept in our SCM so if something used by all developer's sandbox, it is easily changeable and transparent to all developers on the project. It is currently impossible to run Maven 3 in this way.

We are not entirely without options when it comes to addressing this, but none of the solutions in my opinion is as nice as the stable, built-in profiles.xml feature. Recently, I've asked if there is some other mechanism I should be using to accomplish this. To date, I've not seen anyone fully explore this issue that I think is important for Maven 3 going forward. So that's what I did here. If you'd like any of the sample projects I created for this exploration, just drop me a line. Maybe I'll put them up on GitHub or something at some point. So without further ado, here are the options I've found and their pros & cons.

1. Fork Maven and put the feature back in
Maybe it's my cynical nature, but this was actually the first thing that came to my mind. But I don't know that very many people would feel comfortable running a patched version of Maven. Plus, I'd want to keep forking them to keep getting all the other goodies they add, which makes a lot of work for me. Then I thought of submitting a patch to Maven for this. But when I found out the decision was pretty deliberate and not simply a lack of resources, I backed off that idea.
Pros Cons
It's the way Maven should be A lot of work
Who's brave enough to use it?

2. Stick with Maven 2
Hey, there's nothing wrong with being old fashioned. There's strong logic to the "If it ain't broke, don't fix it" argument. Some people are even still happily on the 2.0.x branch rather than the 2.2.x branch.
Pros Cons
The least work of any other solution No Maven 3 goodies

3. Place all profiles properties in the POM
POMs in Maven 3 still use a <modelVersion>4.0.0</modelVersion>. There for you could put everything inside it like
pom.xml
<?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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.foo</groupId>
  <artifactId>pomProfileTest</artifactId>
  <version>1.0</version>

  <properties>
    <!-- these are defaults, they can be overridden with a settings.xml -->
    <javaVersion>1.5</javaVersion>
    <junitVersion>4.8.2</junitVersion>
    <sourceEncoding>UTF-8</sourceEncoding>
    <resourceEncoding>UTF-8</resourceEncoding>
    <profile>dev</profile>
    <prop1>null</prop1>
    <prop2>null</prop2>
  </properties>

  <profiles>
    <profile>
      <id>developer1</id>
      <properties>
        <prop1>prop1Value</prop1>
        <prop2>prop2Value</prop2>
      </properties>
    </profile>
    <profile>
      <id>developer2</id>
      <properties>
        <prop1>anotherProp1Value</prop1>
        <prop2>anotherProp2Value</prop2>
      </properties>
    </profile>
  </profiles>
<!-- ... -->
</project>
This could then be invoked in the standard way:
mvn -P developer1 <goal>
Pros Cons
Simple to implement: scripts can continue to invoke Maven in the current way Clutters POM, particularly troublesome since the POM is also deployed.
Also works with Maven 2
Variations
1. Multiple pom.xml files could be checked into the project to cut down on the clutter inside the main pom.xml.

4. Place all an environment's (or developer's) settings in a single settings.xml
This seems to be Maven's official answer on the subject. For things that are common across many projects, this might be a decent solution. But for the many project specific settings (e.g. a db.url property), you'd have to make sure they are named uniquely across all projects so as not to conflict with each other. This makes for a real maintenance problem.
As one commenter in the mailing list noted, some developers have a fear of changing their settings.xml (even if they should be comfortable with this) and would prefer to simply change a few properties. But this should make us pause to make sure there's nothing we're using profiles.xml for when we should actually be using settings.xml.
Pros Cons
Maven's official solution Uniquely named properties causes maintenance issues
Also works with Maven 2 Changes not normally visible to all developers

5. Use separate settings.xml files
You can specify a different user settings file with
mvn -s path/someSettingsFile.xml <goal>
and create a file like
developer1.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <profiles>
    <profile>
      <id>developer1</id>
      <properties>
        <!-- global properties -->
        <siteLocation>file://${user.dir}/site</siteLocation>

        <!-- project specific properties -->
        <prop1>prop1Value</prop1>
        <prop2>prop2Value</prop2>
      </properties>
      <!-- ... -->
    <profile>
  <profiles>
</settings>

Pros Cons
Little profile clutter in POM Massive clutter & overhead in profile settings file, as all your normal settings.xml things are now in each profile settings file
Checking all these settings files in allows developers to make sure they're all using and deploying to the same repos profile settings are machine-dependent since <localRepository/> is also in settings file.
Also works with Maven 2

6. Use the Properties Maven Plugin
The Properties Maven Plugin allows for properties files to be loaded (and saved) just as if you had used <properties/> in the pom.xml itself.
Pros Cons
Properties are cleanly externalized Plugin is considered an alpha version
Also works with Maven 2

Variations
1. Use profiles to select the properties file
This could be invoked in the standard way:
mvn -P developer1 <goal>
And your pom might look like
pom.xml
<?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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.foo</groupId>
  <artifactId>propertiesProfileTest</artifactId>
  <version>1.0</version>

  <properties>
    <!-- these are defaults, they can be overridden with a settings.xml -->
    <javaVersion>1.5</javaVersion>
    <junitVersion>4.8.2</junitVersion>
    <sourceEncoding>UTF-8</sourceEncoding>
    <resourceEncoding>UTF-8</resourceEncoding>
    <profile>dev</profile>
    <prop1>null</prop1>
    <prop2>null</prop2>
  </properties>

  <profiles>
    <profile>
      <id>developer1</id>
      <properties>
        <profile>developer1.properties</profile>
      </properties>
    </profile>
    <profile>
      <id>developer2</id>
      <properties>
        <profile>developer2.properties</profile>
      </properties>
    </profile>
  </profiles>

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>properties-maven-plugin</artifactId>
        <version>1.0-alpha-2</version>
        <executions>
          <execution>
            <phase>initialize</phase>
            <goals>
              <goal>read-project-properties</goal>
            </goals>
            <configuration>
              <files>
                <file>${project.basedir}/filters/${profile}</file>
              </files>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  <!-- ... -->
</project>
Pros Cons
Standard way for selecting profile POM now is cluttered with mapping profiles to properties files

2. Use a variable to select the properties file
In my sample, the invocation would be
mvn -Dprofile=developer1 <goal>
And the POM would be like
pom.xml
<?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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.foo</groupId>
  <artifactId>propertiesProfileTest</artifactId>
  <version>1.0</version>

  <properties>
    <!-- these are defaults, they can be overridden with a settings.xml -->
    <javaVersion>1.5</javaVersion>
    <junitVersion>4.8.2</junitVersion>
    <sourceEncoding>UTF-8</sourceEncoding>
    <resourceEncoding>UTF-8</resourceEncoding>
    <profile>dev</profile>
    <prop1>null</prop1>
    <prop2>null</prop2>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>properties-maven-plugin</artifactId>
        <version>1.0-alpha-2</version>
        <executions>
          <execution>
            <phase>initialize</phase>
            <goals>
              <goal>read-project-properties</goal>
            </goals>
            <configuration>
              <files>
                <file>${project.basedir}/filters/${profile}.properties</file>
              </files>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  <!-- ... -->
</project>
Pros Cons
Little profile clutter in POM No standard way of selecting profile

Conclusion
I still really wish the Maven folks would change their mind on this. But until then (unless you're sticking with Maven 2 -- which might not be a bad idea at least for now because of plugin incompatibilities), the best option seems to me to use the Maven Properties Plugin, either with a property or with a profile. (Personally, I'm leaning to the profile option beacuse I think the fact it can be invoked in a standard way is worth the extra POM clutter). Though it is technically an alpha version, it seemed to work fine for me and I believe Maven's decision to remove support for profiles.xml will cause people to flock to this plugin, and therefore likely to only increase its stability. Of course, IDE support for this practice is another question.

Conclusion Part 2
I do feel obligated to mention that the practice of using Maven filtering for things like database URLs where I work is actually changing to use runtime properties instead. (Generally by building a property reader class using java.util.Properties to read different properties files based on the name passed with -Denv=<environmentName>). This has the advantage (besides working with Maven 3) of not requiring separate deployments just for environment differences or redeploys for changes to an environment property.
I still think removing profiles.xml support is bad since the intent was to keep backward compatibility, thus making pointing my M2_HOME to Maven 3 a bit painful when working on old and new projects. It also seems a bit strange that they removed support for profiles.xml when they but not for profiles. It was nice to be able to have those external to the POM.
However, for my (and probably the gentleman on Nabble also) use case, Maven filtering with profiles probably may not have been the right idea in the first place.

Sunday, October 24, 2010

My Review of Medal of Honor (2010)

I was on the fence about getting this game.  If they didn't offer guns that were only available through pre-ordering, I may not have even gotten the game.  But this coupled with the bonus sniper rifle for having BC2 VIP, and my lack of interest in the upcoming CoD game nudged me to the purchasing side of the fence.  Oh, one other bonus is that you get in on the beta for Battlefield 3 (if that's important to you).  And probably there'll be other bonuses through EA's Gun Club.

First off: everything mediocre I've read about this game is true.  The single player is unremarkable in almost every way, it does suffer from a few scripting issues (I don't think worst than other MoH titles I've played, but our standards have gone up since then), and the graphics stutter in a few places (seemed to me to be mostly around save points).  On the plus side, the sliding into cover system they have in single player is pretty cool.  Unfortunately, this isn't available in multiplayer.  Which is the other unfortunate thing about this game: how disconnected the singleplayer is from the multiplayer.  It was done by two teams, in two countries, with two different engines, and they seemed to communicate very little between them during development.  It's amazing how much time (3 years) was spent on the singleplayer and yet it still rings pretty hollow at the end of the day.  Interestingly, EA's stock dropped 6% on launch day, due to investors being worried by the mediocre reviews.  There are a couple of interesting levels, but nothing we haven't really seen before and no level sticks out in my memory as "woah, that was awesome!".  There's a level where you get to use attack helicopters, a sniping level, a level with ATVs, and the cinematics are pretty good (and you could skip them if you wanted to, which I've not seen in recent games).  The storyline could have been a little tighter (for example the incompetent, friendly-fire causing general is all but forgotten later in the game), but I did like that it was grittier and had fewer Jack Bauer-esque moments than MW2's storyline.

For the mulitiplayer side: It's actually pretty good, and I've found the description as a hybrid of BC2 and MW2 to be true.  This game differs from BC2 in that there is limited destructibility (one of the coolest things about BC2), and most game modes don't have any vehicles (the other really cool thing about BC2), although there are light tanks in one of the modes.  There are perks like in MW2, but you don't roll through them in the frantic pace that seems to dominate MW2.  The guns do seem more balanced than either of the other 2 games.  The maps are bigger than MW2, but smaller than BC2.  One thing that is unique about their perk system is that every time you unlock a perk, you can choose between a defensive and an offensive action.  Defensive actions include stuff like enemy radar and flak vests for your buddies, and offensive actions involve things like mortar strikes and rocket strikes.  But unlike MW2, then chain of perks is not configurable.  Like BC2 and MW2, you unlock new guns and stuff for your guns as you progress ranks by earning points.  The number of rounds to take down an opponent is about the same as BC2 (they have a hardcore mode too, which I haven't tried yet).
The only major downside to the multiplayer is the spawn points.  They're awful.  In BC2, you'd only get popped on spawn if you spawned on a buddy about to get pwnd. In this game I find myself spawning into a mortar strike or into a gang of enemies fairly often.  Which, needless to say, is intensely aggravating (particularly after it happens 4 times in a row -- not uncommon since kills with a perk count towards the next perk).  In some modes, you can spawn back to your base instead of the front, but not all modes have this idea (for example their version of Death Match).  But sometimes you can use this to your advantage.  On some maps, I've been able to run up to one of their spawn points with my M60 a few seconds into the game and wipe half their team before they can put a stop to my mayhem.  A dirty trick, but it made me giggle.

Overall, if you have to choose between this game and BC2 and MW2, I'd say get either BC2 or MW2 (depending on your playing style).  But if you already have those games and are looking for something with a little less Vietnam and RC cars, this might make for a good distraction until something better comes along.  It's definitely not a terrible game, but its not an amazing game either.  The worst thing about it is realizing what could have been...

Bad Company 2 vs Modern Warfare 2

I'd played and loved Modern Warfare 2. I still believe it to be the best multilayer first person shooter I've ever played. That said, when MW2 released their so-called stimulus package at a rate of $15, I felt like that was kind of an insult to their playerbase, which helped them to record-breaking profits in the midst of a recession (particularly when 3 of the maps weren't even new). When I saw that BC2 offered new maps for free (and had already released 2), and claims some were making that it was a better game than MW2, I had to give it a try. What follows is my impressions in contrast to MW2.

When I first started playing the game, I felt a bit underwhelmed. The single player in MW2 is short, but intense. The single player in BC2 might be worth playing to get a feel for the characters, but its a pretty forgettable experience. But the singleplayer isn't why you bought the game anyway.

The sound is great, the graphics look not quite as nice as MW2 in particular with regard to weapon detail, but I think some of this is the scaling. My impression is that BC2 drew humans with a more realistic relative size, this coupled with that the maps are much larger makes everything seem a bit smaller, and perhaps not as graphically wowing. But if you look at the water, buildings, and people (up close), the graphics actually are pretty good.  You just might not notice it at first.

There's also some fun stuff about BC2's personality. In singleplayer, whilst riding some 4-wheelers, they comment how much more awesome 4-wheelers are than snowmobiles. While heading into a mission, one says that they want to go in first, because otherwise they'll send some pansy special ops group with rifles and heartbeat sensors. All, of course, references to Modern Warfare 2's singleplayer campaign.

Gameplay: I'd have to say neither are 'better' than the other. BC2 is a different kind of game than MW2. MW2 is a run & gun fragging game, with BC2 there's more strategy. MW2 is on smaller maps, where people routinely camp in predictable places. BC2 has huge maps where camping is largely meaningless. MW2 lets you build a custom warrior with a wide array of addons and perks. BC2 has some customization, but not as large as MW2, and only within your class (rifleman, recon, medic, and engineer). There are no perks like MW2 has after a certain number of kills. BC2 has vehicles prominently featured in combat. MW2 does not. BC2 has destructible environments. MW2 does not. (As a MW2 player, you'll be really lost at first 'How the hell am I supposed to take cover? Everything is exploding!').
I also really love what they've done with the sniper, calling it recon.  This makes the role more useful than some griefer only contributing a few kills, because they can call out enemy positions they observe through their scope and place motion sensors.

There are some minor gripes I have with BC2. Such as the repeating sound on the unlock page once you unlock everything for a class, the small and difficult to read menus when not displayed on a widescreen TV, the awful guns you start with in assault class, the unskippable cinematics when you start the game and at the end of each round of multiplayer.

They do seem to have taken a cue from MW2 when it comes to unlocks. You'll be able to win new guns and gadgets as you play along in multiplayer. The pace seemed slower to me than MW2 because there weren't a lot of little things that you unlocked like MW2. But many people find 'the hump' less than MW2. I'd say the guns are more balanced overall (with the exception of the M80 for the medic class). One thing I don't get is the pins you win for doing things like getting a revenge kill, being thrifty with your LMG ammo, etc. They award them to you, but you can't really do anything with them. It was nice in MW2 to be able to brag about them by putting them up with your nametag.

What others have said about BC2 being more strategy and team oriented is true. You can't win the game by yourself. While they do have a deathmatch, I play (and most others too I think) rush or conquest, mostly rush in my case. It doesn't matter if you go around slaughtering the other team (although I think you'll find that more difficult to pull off in this game). If your buddies don't have your back, your team will still lose (and you will probably die).

I didn't feel like BC2 was a better game, especially with respect to single player. And while instinctively I'd say buy MW2 before buying BC2, I also have to recall that since getting BC2 I've barely touched MW2. I certainly don't miss the camping, lag & DCs. If you have a preference for fragging games, get MW2. If you enjoy multiplayer shooters that involve a little more strategy, get BC2. If you've got enough money, get both. They each have something different to offer, and having both provides for a good change of pace.

Sunday, July 18, 2010

Cousins Cousins Cousins

I consistently forget the difference between the various kinds of cousins you can have. Fortunately, I recently found a chart that explains it all (and not just cousins) on Wikipedia:
http://upload.wikimedia.org/wikipedia/commons/0/00/Relatives_Chart.svg

Wednesday, July 14, 2010

I opened a new IntelliJ issue

I opened an issue for IntelliJ IDEA to highlight TODOs in blue in gsp files like they do for other files tonight. Vote if you're interested.

Tuesday, July 13, 2010

Greasemonkey and local files

I'm a big fan of the Javadoc Search Frame userscript. Today's apperent outage of the Javadoc page has forced me to use a local copy of the documentation. I did some poking around on the Greasemonkey mailing list and found that if you still want to run this userscript (or any other userscript) on local files, you will need to edit your about:config. An update changed the default greasemonkey.fileIsGreaseable in about:config from true to false for security reasons. If you want to run Greasemonkey on local files, simply change that value to true.

Also, if you're using the shiny new Scriptish, the value to set to true is extensions.scriptish.fileIsGreaseable.

Cheers!

Monday, July 12, 2010

BASH Colors

I was messing with my .dir_colors file (about.com also has a good article on this) and wanted a chart to help me pick out my colors. So I modified the popular script that is floating around on the internet to display every possible combination in a graphical chart.
The way it is read is foreground and effect is on the row titles and the backgrounds are on the column titles. Hopefully someone else will find this useful.

#!/bin/bash
#
#  This file echoes a bunch of color codes to the 
#  terminal to demonstrate what's available.  Each 
#  line is the color code of one forground color,
#  out of 17 (default + 16 escapes), followed by a 
#  test use of that color on all nine background 
#  colors (default + 8 escapes).
# 
#  Attribute codes: 
#   00=none 01=bold 04=underscore 05=blink 07=reverse 08=concealed
#  Text color codes:
#   30=black 31=red 32=green 33=yellow 34=blue 35=magenta 36=cyan 37=white
#  Background color codes:
#   40=black 41=red 42=green 43=yellow 44=blue 45=magenta 46=cyan 47=white
#
#  A quick test can be done by echo -e "\033[<color code><test text>\033[0m"
#   e.g. echo -e "\033[01;32mHello World\033[0m"
#
#  Modified from: http://tldp.org/HOWTO/Bash-Prompt-HOWTO/x329.html

T='gYw'   # The test text

# smaller set without attribute codes commented out below
#echo -e "\n                 40m     41m     42m     43m     44m     45m" \
#        "    46m     47m";
#for FGs in '    m' '   1m' '  30m' '  31m' '  32m' '  33m' '  34m' '  35m' \
#           '  36m' '  37m' ;
echo -e "\n                  40m     41m     42m     43m     44m     45m" \
        "    46m     47m";
for FGs in '     m' '    1m' \
           '   30m' '01;30m' '02;30m' '03;30m' '05;30m' '07;30m' '08;30m' \
           '   31m' '01;31m' '02;31m' '03;31m' '05;31m' '07;31m' '08;31m' \
           '   32m' '01;32m' '02;32m' '03;32m' '05;32m' '07;32m' '08;32m' \
           '   33m' '01;33m' '02;33m' '03;33m' '05;33m' '07;33m' '08;33m' \
           '   34m' '01;34m' '02;34m' '03;34m' '05;34m' '07;34m' '08;34m' \
           '   35m' '01;35m' '02;35m' '03;35m' '05;35m' '07;35m' '08;35m' \
           '   36m' '01;36m' '02;36m' '03;36m' '05;36m' '07;36m' '08;36m' \
           '   37m' '01;37m' '02;37m' '03;37m' '05;37m' '07;37m' '08;37m';
  do FG=${FGs// /}  
  echo -en " $FGs \033[$FG  $T  "
  for BG in '40m' '41m' '42m' '43m' '44m' '45m' '46m' '47m';
    do echo -en "$EINS \033[$FG\033[$BG  $T  \033[0m";
  done
  echo;
done
echo

As a side note, for those who may be like myself and didn't see any logic to the codes used for colors, ls and most terminals use the ANSI escape codes (ECMA-48), which is where the numbers come from.

Monday, June 7, 2010

Snapshots of Wave Robot API Now Available

I've Mavenized the Wave Robot API and the Wave model portion of Wave Protocol, a dependency of Wave Robot API and deployed snapshots to my public repository. Currently, I've only deployed snapshots since the use of this artifact is completely untested. I'm working on creating a Maven archetype for Wave robots (which will use this repository until Google uploads it somewhere), and an example using the archetype. After I've done this and am sure it works (and that I haven't done anything stupid with Maven), then I will tag a release and put it on my release repository.

If anyone would like to try it out in the mean time, your feedback would be most appreciated! Here is what you would need in your pom.xml:

<dependencies>
    <dependency>
        <groupId>com.google.wave</groupId>
        <artifactId>wave-robot-api</artifactId>
        <version>20100408-SNAPSHOT</version>
    </dependency>
</dependencies>
<repositories>
    <repository>
        <id>public-repo_maven2-repository</id>
        <url>http://public-repo.googlecode.com/svn/repository/</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
        <releases>
            <enabled>true</enabled>
        </releases>
    </repository>
    <repository>
        <id>public-repo_maven2-snapshots</id>
        <url>http://public-repo.googlecode.com/svn/snapshots/</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
        <releases>
            <enabled>false</enabled>
        </releases>
    </repository>
</repositories>

Some stuff I picked up along the way:
  • When using the WebDAV wagon with Google Code, make sure you use https, otherwise you're liable to get a 405 method not allowed error on a deploy.
  • There's an interesting bug with the Robot API's EventSerializerTest. The behavior is different in Javac 1.5 vs 1.6 but compile fine with the Eclipse compiler. There is bug report for Javac here (fixed in 1.7). I opened a ticket for Google to explicitly cast this in the method so the compiler doesn't have to do any inference, so that way it will build fine with Javac even if they're using JDK 1.6. In the mean time, I've opted to use the Eclipse compiler in the pom rather than altering my local copy of the source. My goal is to make this an exact match to the class files in the zip they've distributed.
  • Guava, the successor to Google Collections (as a backwards compatible superset) and dependency of the Wave model API is on Maven central, but not on Google's repository. It's a little odd, but shouldn't cause any issues.

A special thanks to Jurgen and commenters for the helpful post that got me started.

Friday, June 4, 2010

Bots updated to v2 API

I've updated WorldCat-Bot and Yodaspeakify to v2 of the Wave API, which boasts some fantastic new features, including an easier way to do annotations, doing away with Cron, no need for a separate profile servlet, and the capabilities.xml is automatically generated for you using annotations.

One thing I voted for as an improvement was to use regular expressions in this method. I'm not sure what the author of the issue was talking about with iterating over Elements since, as I understand, these don't include text. The artifacts are still not on Google's repository and I'm getting pretty tired of a 5 minute commit time when I change some jars around.  I'm working on using Google Code as a repository and adding these artifacts after I mavenize them, then I'll create archetypes for Wave -- watch for an update on this soon, now that my bots are done this is the next project.

Some snags I ran into:
The .replace() of BlipContentRefs doesn't work the way you'd think it would. I thought I could do
BlipContentRefs content = blip.first(originalText).replace(newText);
But the BlipContentRefs will be empty. I got a hint for how to do this from wadrobotframework's BlipUtils:
public static void replaceBlipContent(Blip bleep, String nextContent) {
    BlipContentRefs bcr = bleep.all();
    if (bcr != null) {
        bcr.delete();
        bleep.append(nextContent);
    }
}
Thanks, wadael!

Another issue was when I used DocumentChangedEvent and then did a .getBlip() it would return a null Blip. My understanding of the JavaDoc was that it would return the root blip if no Blip was associated with that event, but this didn't seem to be happening. So, I opted for a BlipSubmittedEvent instead. Which, now that I think about it, is probably the desired behavior anyway.

Another issue was when I was trying to take advantage of the cool new filtering options. WorldCat-Bot used to surround it's searches with angle brackets (<>), but when I tried to filter on this
@Capability(filter = "<.*>")
@Override
public void onDocumentChanged(DocumentChangedEvent event) {
  ...
}
It didn't work because the capabilities.xml that was generated was not well formed. I also tried the escaped version
@Capability(filter = "&lt;.*&gt;")
@Override
public void onDocumentChanged(DocumentChangedEvent event) {
  ...
}
But this didn't work either, it looked for the entire literal not the unescaped form. I don't think this is currently possible to do, so I now use square brackets ([]) to filter on.

While trying to debug this, I set up logging (GAE supports JUL), but I learned it only logs things with INFO, WARN, and SEVERE levels (though I couldn't get INFO to work even with the logging.properties file with .level = ALL. Maybe something else is misconfigured).

But overall, the new API has been a very positive experience.

Wednesday, June 2, 2010

GMaven & source encodings

I'm re-posting this because I made some more discoveries after I had initially posted it.

I discovered apparently SourceEncoding is completely broken in GMaven. I tried on Linux where the platform default encoding is UTF-8 and on Windows XP where the platform default encoding is Windows-1252. In both cases, it used ISO-8859-1 as the encoding of the class file it generated, despite the fact the source was encoded in the platform default encoding. I tested this with version 1.2 of the plugin and Groovy 1.7.0. Why this is happening makes no sense to me; I could understand if it used the platform default...but why always ISO-8859-1? I think this is the Jira for this: http://jira.codehaus.org/browse/GMAVEN-13.
I find it shockingly disappointing that a 'critical' issue can go unassigned for almost an entire year. I wonder if it is working in Ant. Their documentation seems to suggest that it does. If that's true, it might tell us something about where the Groovy team's priorities are.

In practice, this often is not problem, since if you're only using ASCII characters in your source code, the first 128 bytes have identical mappings in UTF-8, ISO-8859-1, and Windows-1252, so it won't matter which of those the plugin tries to use. However, I view this as a major obstacle to Groovy's gaining dominance, as it should support Maven (since for better or worst it's become the leading standard) and it should support encodings to support global growth.

Am I missing something? Any good workarounds? I'm also happy to share my experiment project with anyone who wants to play with it.

I've also discovered yet another way in which GMaven's documentation is fail. I was trying to get my project to work with the latest version of Groovy, when I came across this unrelated StackOverflow discussion which use the new 1.2 version of the plugin (which isn't in the archetype or anywhere documented as released -- I thought the artifacts were released by mistake since nothing has even been tagged in their repository for 1.1 or 1.2, although IntelliJ already supports it, plus nabble and some blogs talk about it so I guess it is released). Here are the needed bits from the pom:
<dependencies>
    <dependency>
        <groupId>org.codehaus.gmaven.runtime</groupId>
        <artifactId>gmaven-runtime-1.7</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>1.7.0</version>
    </dependency>
<dependencies>
<plugins>
    <plugin>
        <groupId>org.codehaus.gmaven</groupId>
        <artifactId>gmaven-plugin</artifactId>
        <version>1.2</version>        
        <configuration> 
            <providerSelection>1.7</providerSelection>         
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>generateStubs</goal>
                    <goal>compile</goal>
                    <goal>generateTestStubs</goal>
                    <goal>testCompile</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3</version>
        <configuration>
            <source>1.6</source>
            <target>1.6</target>
        </configuration>
    </plugin>
</plugins>

Update: According to this Jira, this is fixed in the 1.3 release. And it appears from my tests that this is the case.

Friday, May 28, 2010

Firefox vs Chrome Performance: A language difference?

Like many folks, I've been pretty blown away by the speed of Chrome (especially with respect to running JavaScript intensive sites). Currently, I use both Firefox and Chrome (depending on what I'm doing), but primarily Firefox as there are still some addons I can't live without.

Though I am excited to see the Out Of Process (OOP) Electrolysis project (which is now in beta) and the upcoming JägerMonkey JavaScript engine, I've begun to wonder if some of the performance differences we're seeing are more deeply rooted. Now I do know there are things that are supposedly not possible with Chrome's extension support, and of course with greater functionality comes reduced performance. But I've lately been wondering if the differences are at the language level. Does the language each was written in greatly alter performance? Have a look at this graphic
Source: Ohloh

Just look at all that JavaScript! While some sources favor JavaScript as a "first-class language" (and maybe I'm misinterpreting their meaning here), I'm not convinced that makes sense for desktop applications. There are some advantages to having portions of Firefox be in a web language, it makes it easy for web developers to extend & theme. But I'm not sure it makes sense to use it as extensively as they appear to have done.

For example, it would seem that the addon manager (nsExtensionManager.js) and session storage (sessionStore.js) are both JavaScript. How do I know these are their names? I didn't look at the code, but apparently I was putting Firefox under a bit too much pressure and I got the message saying these scripts had stopped responding (not at the same time). (Though this does happen less often with my portable Firefox, so maybe I need to clear out the profile).

It will of course help when we have the content and the UI in separate processes, and maybe help some more when Firefox gets a faster JavaScript engine, but I wonder if you can ever get really good performance from a language like JavaScript. I'm not saying to write the thing in assembly, I'm just saying maybe it makes sense to write the lower level components in a lower level language. What do you think?

As two somewhat unrelated sidenotes: What do you think the impact on Firefox's future will be with the loss of their tech lead? And do you think Google will finance Mozilla now that they're in some competition with each other?

Friday, May 21, 2010

Syntax Highlighting in Blogger: Round 2

So I'm now able to use the popular SyntaxHighlighter that most blogs use. I don't know what was stopping me before: maybe I've gone up in intelligence or they've fixed some bug. There's excellent instructions here. I think I'm going to make the move to this, since it's easier to read, has more features, and is more standard that the Prettify script I was using before. And one additional nice feature is I don't have to manually set my style="overflow:auto;", instead I just do
<pre class="brush:xml; wrap-lines:false">
And there's no longer a need to do an onLoad in the body tag, and a Groovy brush!
I've gone back to old posts and switched the styles, let me know if I've missed any.

Edit: Actually I think maybe the reason was my own lack of attention. I think I forgot to add 'alexgorbatchev.com' to NoScript's whitelist, and that's the host the scripts are currently hosted on, and it magically started working for me because I was in Chrome instead of Firefox. Doh! ... Doh? Who knows for sure?

Edit: The instructions aren't really up to date anymore, as new brushes have been added. Here is an updated example (note this uses the default theme, but you can choose to use other themes):
<link href="http://alexgorbatchev.com/pub/sh/current/styles/shCore.css" rel="stylesheet" type="text/css"></link>
<link href="http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css" rel="stylesheet" type="text/css"></link>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js" type="text/javascript">
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushAS3.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushColdFusion.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCpp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCSharp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushCss.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDelphi.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushDiff.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushErlang.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushGroovy.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJava.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJavaFX.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPerl.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPlain.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPowerShell.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPython.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushRuby.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushScala.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushSql.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushVb.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shBrushXml.js' type='text/javascript'/>
<script language='javascript'>
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.config.clipboardSwf = 'http://alexgorbatchev.com/pub/sh/current/scripts/clipboard.swf';
SyntaxHighlighter.all();
</script>
This still goes inside the header area of the template, which means you'll still need to manually edit the HTML.

OK Maven, You Win

So, I've tried every combination of dependencySets, fileSets, and copyDependencies I could think of, nothing I did seems to work. All I wanted was to have a runnable jar with its dependencies in unexploded jars (something I've done before when making a jar by hand, although I used the default package in that case, not sure if that makes a difference). When I failed in this, I tried to have a runnable jar with its dependencies exploded into a lib directory. I failed in this as well. The only thing that seems to work is to have everything exploded into the same level. I tried this briefly with the shade plugin, but have mostly been trying with the assembly plugin. I give up, Maven. You win.
I've seen this mentioned fairly often on the web. If someone has a working example of a Groovy project compiled into a runnable uber-jar, I'd love to see it.

Friday, February 26, 2010

Workaround for JRA-19248: 401 on Jira Gadgets

Here is a workaround for JRA-19248: Dashboard widgets fail with HTTP 401 malformed security token, when left unattended for some time. Set the 'Refresh Interval' on the gadgets to 1hr (or less).  It's worked for me so far.
Edit: Well, it worked for several days, but apperently 1hr wasn't quite often enough. I'm trying with 30min, someone else reported having to use 15min. One more thing to note is that this issue is fixed with Jira 4.1.

Tuesday, February 9, 2010

Windows Profile Woes

After struggling for months with folders magically changing ownership (first noticed when iTunes couldn't save podcasts) and messages saying the roaming profile did not synchronize completely, I believe I've found the problem. Apparently, Windows profiles changed (though I don't understand how this affects me since although I did an upgrade install of Win7 from Vista, my machine never ran XP or earlier). The migration was failing because there wasn't enough hard drive space to copy all my music, documents, everything twice to do the migration. Though even once I resolved the issues preventing the sync (by moving to a temporary folder in C), it still didn't perform the sync. What I ended up having to do is create a new user, then copy everything over, take ownership, then delete the old user. This problem was also the cause of the mysterious S-{A bunch of meaningless numbers} user and the messages saying I wasn't the owner even though the username of the owner was my username. This was my user account's SID, which it apparently uses as part of the migration.
 
I also learned that there is no Windows equivalent of Linux's usermod (let alone a GUI like Gnome and KDE have) when it comes to renaming accounts and their homes. My plan was to create a new account named Keegan2 then delete the original and rename the new to the old name after I was sure everything was moved over. While you can rename accounts in Windows, it doesn't change the profile path as part of the renaming. There is a registry hack that can be done, but this method gave me issues (all kinds of software installed for all users was still looking in the old place). When I tested this with XP, when I removed the renamed user it didn't remove the files. It would seem like it should be possible to run a script similar to the initialization Windows does the first time a user logs in before migrating to the new name.  This explains the laptop that was re-purposed a few times, but still had all the old usernames in 'Documents and Settings'.

It's a Windows world, but I find the longer I live in it, the more I suffer. Vive Linux!

Monday, February 1, 2010

Aero and LogMeIn

I've had the problem on Vista and Win7 of having Aero disabled after a remote LogMeIn session, even after changing themes to an aero theme and rebooting (the only thing that worked was uninstalling and reinstalling LogMeIn). After having no luck searching the LogMeIn community forums, I finally stumbled across a tip from the folks at Windows 7 Forums:
  1. Uncheck the 'Disable wallpaper and user interface effects on the host computer' in the LogMeIn preferences.
  2. Uncheck the 'Use display accelerator' setting in LogMeIn preferences.
  3. Disable the mirror display device in device manager.
That should do the trick! (Note that this will probably significantly reduce the responsiveness).

Sunday, January 17, 2010

Prevent OpenDNS From Redirecting Google Searches – Fix for Firefox & IE Address Bar

For those of us who enjoy the protection of OpenDNS, but don't want to use the OpenDNS guide, change the value of keyword.url in your about.config to http://www.google.com/search?q=. Thanks to digital inspiration for the tip.

Thursday, January 14, 2010

Wednesday, January 13, 2010

VirtualBox Tips

I've been experimenting a bit with Sun's VirtualBox over the last few days. For the most part, its been pretty smooth. I now use this instead of VMware. I thought I'd pass along a few snags I ran into to save someone else some trouble. When upgrading, uninstall the previous version first (they claim it can be installed over the old version, but its given me problems both times I've tried to upgrade that way). It won't delete your VMs. Also, for those running Vista/Win7, when installing, run the installer in administrator mode otherwise it seems to fail when trying to install the virtual network devices. I'm not sure why they don't have their installer set to require these permissions, and it doesn't seem to write a log either when it fails, making debugging difficult.

Tuesday, January 12, 2010

GoogleMonkeyR and SkipScreen Incompatibility

I'm a user of the GoogleMonkeyR userscript, and for a few months I had been thinking that Google had changed something that caused the script to have the first result right-aligned instead of left-aligned. It turns out, the problem is actually because I'm also a user of SkipScreen. The problem lies in the 'search refinements' setting, it must be disabled for GoogleMonkeyR to work properly, either do this from the GUI SkipScreen options dialog, or change the value extensions.skipscreen.searchrefinementsactive to false. Hopefully, this saves someone else some confusion.

Monday, January 11, 2010

More Groovy Bugs

While trying to add some sorting to my ValidateMe script, I discovered a Groovy bug that someone else reported on Thursday. It appears that although inner classes are supposed to be supported in the new Groovy 1.7, calling methods on enums inside a class do not. I've also created another suggestion for a reverse() method on Maps. I did add the changes I wanted to ValidateMe without these Jiras being addressed. What I did for the reverse was do something like
theMap.reverse{it.value}