Using system properties in with Spring

This is actually pretty easy to pull off. First you must use a property-placeholder like this:

<context:property-placeholder location="classpath:myapp.properties"
                                          system-properties-mode="ENVIRONMENT"/>

The system-properties-mode supports several options including:

  • FALLBACK – Indicates placeholders should be resolved against any local properties and then against system properties
  • NEVER – Indicates placeholders should be resolved only against local properties and never against system properties
  • OVERRIDE – Indicates placeholders should be resolved first against system properties and then against any local properties
  • ENVIRONMENT – Indicates placeholders should be resolved against the current Environment and against any local properties. This is the default.

The location is an optional parameter so depending on your needs you can skip configuring it.

There are some other optional parameters available including:

  • ignore-resource-not-found – Specifies if failure to find the property resource location should be ignored. Default is “false”, meaning that if there is no file in the location specified an exception will be raised at runtime.
  • ignore-unresolvable – Specifies if failure to find the property value to replace a key should be ignored. Default is “false”, meaning that this placeholder configurer will raise an exception if it cannot resolve a key. Set to “true” to allow the configurer to pass on the key to any others in the context that have not yet visited the key in question.

A system property can then be utilized like this:

<property name="username" value="#{systemProperties.username}"/>

The # is not a mistake; this indicates that the bean systemProperties should be used.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Script to get a localhost’s IP address in Linux

I’ll keep this snippet really short:

$ ifconfig eth0 | grep "inet addr:" | cut -d: -f2 | awk '{ print $1 }'

Which results in:

10.X.X.X
Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Using PowerMock to mock a call to super

Let’s say you are wanting to test UberEmployee below:

public class Employee {
  public int calculatePay() {
    return someComplexCalculations;
  }
}

public class UberEmployee {
  public static final long UBER_BONUS = 1000;
  @Override
  public int calculatePay() {
    return super.calculatePay() + 1000;
  }
}

Perhaps you can’t change Employee but you still want to test UberEmployee without your tests being unnecessarily coupled to the implementation of Employee. We can utilize PowerMock to mock the call to Employee.calculatePay(). It takes a little bit of voodoo but it can be done like this:

@RunWith(PowerMockRunner.class)
@PrepareForTest({Employee.class})
public class UberEmployeeTest {
  private UberEmployee uberEmployee = new UberEmployee();

  @Test
  public void calculatePayShouldGiveUberBonus() {
    final long pay = RandomUtils.nextLong();
    Method superCalculatePayMethod = Employee.class.getMethod("calculatePay");
    PowerMockito.replace(superCalculatePayMethod).with(new InvocationHandler() {
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return pay;
      }
    });

    assertThat(uberEmployee.calculatePay(), is(pay + UberEmployee.UBER_BONUS));
  }
}

It’s not really pretty but it does the trick whenever you don’t have any other choice.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Running a headless Virtual Box VM

I know I’m going to need to run a headless virtual machine using Virtual Box sometime in the future, so here’s a couple of commands on how to run and shutdown a headless VM. For all of these commands, replace with the name of the VM.

To start the VM headless, use this command:

VBoxManage startvm "<name>" --type headless

To power off the VM (allowing a proper shutdown), use this command:

VBoxManage controlvm "<name>" acpipowerbutton

To forcefully shutdown a VM, use this command:

VBoxManage controlvm "<name>" poweroff
Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Keeping passwords secret: Hudson plugin development

A common problem with several Hudson plugins is storing passwords and other sensitive data as plaintext as seen here, here, here, and here. There are more examples than I’d care to list here.

What prompted me to write this is a bug in the email-ext that I just fixed where credentials were being stored in plain text. The solution is so easy there’s no excuse not to do it.

The trick is to use hudson.util.Secret and the usage is dead simple:

public class MyPublisher extends Notifier {

  private Secret password;

  public String getSmtpAuthPassword() {
    return Secret.toString(smtpAuthPassword);
  }

  // ... snip ...

  public static final class DescriptorImpl extends BuildStepDescriptor<Publisher> {
    @Override
    public boolean configure(
                    StaplerRequest req, JSONObject formData) throws FormException {
      password = Secret.fromString(
                          nullify(req.getParameter("mypublisher.auth.password")));
      // ... snip ...
    }
  }
}

For what it’s worth, the docs for this class gives this notice:

Note that since the cryptography relies on hudson.model.Hudson.getSecretKey(), this is not meant as a protection against code running in the same VM, nor against an attacker who has local file system access.

So there you have it, there’s no good reason to not be reasonably secure.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

DB2 on Ubuntu: The database manager shared memory set cannot be allocated

I’ve been trying to get DB2 Express-C working on Ubuntu but I get an error when trying to start DB2:

ashlux@SERVER:~/java/db2exc$ db2
(c) Copyright IBM Corporation 1993,2007
Command Line Processor for DB2 Client 9.7.2

db2 => db2start
SQL1220N  The database manager shared memory set cannot be allocated.

After some searching I discovered that the problem is probably shmmax being too low. A site on tuning Oracle which shows how to increase shmmax:

sudo  -s "echo 2147483648 > /proc/sys/kernel/shmmax"

DB2 successfully starts up now.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Redirect root directory to a subdirectory using .htaccess

Every so often I need to redirect from the root directory http://www.someserver.com to http://www.someserver.com/blah. The first thing I try is always something like:

# This does not work
RedirectMatch permanent / /blah

This ends up not working with Firefox reporting “the page isn’t redirecting properly”. I guess the server gets confused and redirects indefinitely so you must do this instead:

# Redirect from / to /blah
RedirectMatch permanent ^/$ http://www.someserver.com/blah

*cheers*

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Triggering Hudson builds with Mercurial hooks

Mercurial offers a variety of hooks, powerful triggers that can be configured to automatically perform automated tasks after an event occurs in a repository. We can leverage Mercurial’s changegroup hook to make Hudson build a project without polling the version control system for changes. This offers some important advantages and disadvantages.

One advantages of triggering builds after hg push is to decrease the load on the Mercurial server and Hudson itself by not polling every 1-60 minutes and use the server when necessary. Of course the fewer projects you have the less this technique buys you. Another advantage is to lower the feedback loop from Hudson; every minute spent waiting for Hudson to poll Mercurial the longer the feedback loop gets.

There are some important disadvantages to this technique too by introducing additional coupling between your CI server and your version control server (VCS). While Hudson always knows about your VCS now your VCS knows about Hudson. Another disadvantage is most likely you already have Hudson setup to poll Mercurial, so there’s time to configure both ends of the process.

Configuring this Mercurial hook really is easy, just edit the file YOUR_REPO/.hg/hgrc located on your Mercurial server and add the following:

[hooks]
changegroup.hudson = curl http://hudson_url/job/project_name/build?delay=0sec

You will need to change hudson_url to the URL of your Hudson server and project_name to the Hudson project you wish to build.

Be sure to add a file, commit, and push to test your hook. You should see the project instantly added to the build queue.

If your Hudson installation is using security you will need to do things a little differently; see authenticating scripted clients for details. If your job is parameterized you can do that too.

Update 2010-07-14: Mirko has posted a variation to this post that is worthwhile.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Axis2, Maven, and java.net woes and why Maven sucks

I had some interesting problems trying to use the Axis2’s Maven plugin (1.5.1) for generating java code from a WSLD. Here’s what I did to get it working.

First thing’s first I had to define the plugin in my POM:

      <plugin>
        <groupId>org.apache.axis2</groupId>
        <artifactId>axis2-wsdl2code-maven-plugin</artifactId>
        <version>1.5.1</version>
        <executions>
          <execution>
            <phase>generate-sources</phase>
            <goals>
              <goal>wsdl2code</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <packageName>com.ashlux.myproject</packageName>
          <wsdlFile>src/main/wsdl/myproject.wsdl</wsdlFile>
          <databindingName>adb</databindingName>
        </configuration>
      </plugin>

And don’t forget the necessary Axis2 dependencies:

<dependency>
    <groupId>org.apache.axis2</groupId>
    <artifactId>axis2</artifactId>
    <version>1.5.1</version>
</dependency>
<dependency>
    <groupId>wsdl4j</groupId>
    <artifactId>wsdl4j</artifactId>
    <version>1.6.2</version>
</dependency>
<dependency>
    <groupId>org.apache.ws.commons.axiom</groupId>
    <artifactId>axiom-api</artifactId>
    <version>1.2.8</version>
</dependency>
<dependency>
    <groupId>org.apache.ws.commons.axiom</groupId>
    <artifactId>axiom-impl</artifactId>
    <version>1.2.8</version>
</dependency>

That’s more dependencies than I’d want to specify (can’t I just get axiom and wsdl4j transitively?) but otherwise so far so good. Here’s were things took a turn for the worst:

$ mvn clean install
[INFO] Scanning for projects…
[INFO] ————————————————————————
[INFO] Building Rally Java API
[INFO] task-segment: [clean, install]
[INFO] ————————————————————————
Downloading: http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-clean-plugin/2.2/maven-clean-plugin-2.2.pom

Downloading: http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-plugins/10/maven-plugins-10.pom

Downloading: http://repo1.maven.org/maven2/org/apache/maven/maven-parent/7/maven-parent-7.pom

Downloading: http://repo1.maven.org/maven2/org/apache/apache/4/apache-4.pom

Downloading: http://repo1.maven.org/maven2/org/apache/maven/plugins/maven-clean-plugin/2.2/maven-clean-plugin-2.2.jar

Downloading: http://repo1.maven.org/maven2/org/apache/axis2/axis2-wsdl2code-maven-plugin/1.5.1/axis2-wsdl2code-maven-plugin-1.5.1.pom

Downloading: http://repo1.maven.org/maven2/org/apache/axis2/axis2-parent/1.5.1/axis2-parent-1.5.1.pom

Downloading: http://ws.zones.apache.org/repository2/org/apache/apache/3/apache-3.pom
[INFO] Unable to find resource ‘org.apache:apache:pom:3′ in repository apache-ws-snapshots2 (http://ws.zones.apache.org/repository2)
Downloading: http://tomcat.apache.org/dev/dist/m2-repository/org/apache/apache/3/apache-3.pom
[INFO] Unable to find resource ‘org.apache:apache:pom:3′ in repository tomcat-repository (http://tomcat.apache.org/dev/dist/m2-repository)
Downloading: http://repo1.maven.org/eclipse/org/apache/apache/3/apache-3.pom
[INFO] Unable to find resource ‘org.apache:apache:pom:3′ in repository eclipse-repo (http://repo1.maven.org/eclipse)
Downloading: https://maven-repository.dev.java.net/nonav/repository//org.apache/poms/apache-3.pom
349b downloaded (apache-3.pom)
[WARNING] *** CHECKSUM FAILED – Checksum failed on download: local = ‘0f56ee033ef4b78d33722aceb71a09c7ed68183f’; remote = ‘ Downloading: https://maven-repository.dev.java.net/nonav/repository//org.apache/poms/apache-3.pom
349b downloaded (apache-3.pom)
[WARNING] *** CHECKSUM FAILED - Checksum failed on download: local = '0f56ee033ef4b78d33722aceb71a09c7ed68183f'; remote = ' [INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Error building POM (may not be this project's POM).

Project ID: org.apache.axis2:axis2-parent:pom:1.5.1

Reason: Cannot find parent: org.apache:apache for project: org.apache.axis2:axis2-parent:pom:1.5.1 for project org.apache.axis2:axis2-parent:pom:1.5.1

[INFO] ------------------------------------------------------------------------
[INFO] For more information, run Maven with the -e switch
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 17 seconds
[INFO] Finished at: Mon Jun 14 20:10:40 CDT 2010
[INFO] Final Memory: 3M/15M
[INFO] ------------------------------------------------------------------------

Uh oh, clearly org.apache:apache:pom:3 does exist, so what went wrong? This portion of the Maven output is suspicious:

[WARNING] *** CHECKSUM FAILED – Checksum failed on download: local = ‘0f56ee033ef4b78d33722aceb71a09c7ed68183f’; remote = ‘ Downloading: https://maven-repository.dev.java.net/nonav/repository//org.apache/poms/apache-3.pom

That is some checksum coming from https://maven-repository.dev.java.net/nonav/repository, definitely can’t be right! The culprit lies in org.apache.axis2:axis2-parent:1.5.1:

        <repository>
            <id>java.net</id>
            <url>https://maven-repository.dev.java.net/nonav/repository/</url>
            <layout>legacy</layout>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
            <releases>
                <enabled>true</enabled>
            </releases>
        </repository>

The problem is Maven does not support permanent redirects (301). There are several workarounds, from modifying your local repository to adding a mirror for java.net for your settings.xml, none of which I find appropriate since builds are unnecessarily broken for new developers. I chose the settings.xml since I think it’s the cleanest out of all of them:

<settings>
  ...
  <mirrors>
    ...
    <mirror>
      <id>java.net.2</id>
      <name>java.net Mirror of http://repo1.maven.org/maven2/</name>
      <url>http://download.java.net/maven/2/</url>
      <mirrorOf>java.net</mirrorOf>
    </mirror>
  </mirrors>
</settings>

Times like this I think we’d be better off we “all made a big mistake in coming down from the trees in the first place.” I heard some guys on the Java Posse arguing arguing that “even the trees had been a bad move, and that no one should ever have left the oceans.”

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis
 

Suppressing SSH banners

SSH banners are easy to suppress by editing ~/.ssh/config (create it if it doesn’t exist) and adding this line:

LogLevel quiet

Now when I work with CVS over SSH things will be more peaceful.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • StumbleUpon
  • Reddit
  • Bloglines
  • Google Bookmarks
  • Technorati
  • TwitThis