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.