Simpler SSH for Java

First public snapshot version of simple-ssh-client is now available. Have a look at the README for details. Issue reports and feature requests are welcomed.

Cheers,
Jukka

The @Configurable Holder pattern

We often use the @Configurable Holder pattern to build richer Java domain objects.

As an example, consider a Linux server entity that is able to patch itself using Ansible, enabling us to place the exact details of the patching process in an Ansible playbook.

package com.example;

public final class LinuxServer {

    public String host;

    // Constructor etc ...

    public void patch() {
        ansible().patch(this);
    }
    
    private Ansible ansible() {
        return new AnsibleHolder().ansible;
    }
    
    @Configurable
    private static class AnsibleHolder {
        @Autowired
        private Ansible ansible;
    }
}

A strategy interface for invoking Ansible:

package com.example;

public interface Ansible {
    void patch(LinuxServer server);
}

This could be implemented to talk to Ansible via SSH or by running it locally.

Now to make this work, simply build your code with the build tool of your choice,
utilizing AspectJ compile-time weaving and the spring-aspects aspect library. We typically use Maven and the aspectj-maven-plugin for this.

Then set up the necessary Spring configuration (here com.example.LocalAnsible implements com.example.Ansible):

<context:spring-configured />
<context:component-scan base-package="com.example" />
<bean class="com.example.LocalAnsible" />

Finally, go ahead and patch a server:

new LinuxServer("server.foo.dmz").patch();

HTH,
Jukka

JSON serialization with Java inner classes and Jackson

Here’s an example of providing a JSON view to (a part of) your data using an inner class and Jackson JSON mapper:

public final class FtpServer {
    public String host;
    public Integer port;
    public String secret;
}

public final class Environment {
   public String name;
   @JsonIgnore public String username;
   @JsonIgnore public FtpServer ftpServer;
   
   @JsonProperty("ftp")
   public FtpInfo ftpInfo() {
     return new FtpInfo();
   }

   @JsonAutoDetect(fieldVisibility = ANY)
   final class FtpInfo {
      String username = Environment.this.username;
      String hostname = Environment.this.ftpServer.host;
      Integer port = Environment.this.ftpServer.port;
   }
}

Which would render something like this:

{
  "name" : "Example",
  "ftp" : {
    "username" : bob,
    "hostname" : "example.com",
    "port" : 21    
  } 
}

Fairly concise, eh?

Spring MVC 3.1.x request mapping to URLs with a trailing .xxx (in a path variable)

Trouble mapping requests when a request URL ends with .xxx? If so, try this:

package spring;

public final class DoNotTruncateMyUrls implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof RequestMappingHandlerMapping) {
            ((RequestMappingHandlerMapping)bean).setUseSuffixPatternMatch(false);
        }
        return bean;
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

with

<bean class="spring.DoNotTruncateMyUrls" />

in your mvc bean configuration file. No need to remove <mvc:annotation-driven /> if it is being used (we are modifying the RequestMappingHandlerMapping bean registered by it).

Now you should be able to map e.g.

@RequestMapping(value = "/users/{email}", method = GET)

to

GET /users/foo@bar.com

HTH,
Jukka

Monitoring I/O with iostat

Say you’re running a load test (with a predefined duration) and want to monitor I/O on the system under test (a Linux machine).

First install the sysstat package and then, as you start the load test, run:

# iostat -N <test duration in seconds> 2

on the machine whose I/O you want to monitor. For NFS statistics, apply the -n switch.

The first report will display cumulative statistics since last reboot (which may or may not be useful), whereas the second report (that appears exactly <test duration in seconds> later) will display cumulative statistics for the duration of your test.

HTH,
Jukka

Running headless WebDriver tests with Firefox 10, Xvfb and Jenkins (all on RHEL 6)

If you ever need to run automated WebDriver (Selenium 2) tests with Jenkins on a headless CI machine running RHEL 6, with a recent version of Firefox, here’s how:

  1. Make yourself root
    $ su -
  2. Install JDK 6 and use it
    # yum -y install java-1.6.0-openjdk-devel
    # alternatives --config java
    # alternatives --config javac
  3. Install Jenkins CI server
    # wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
    # rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
    # yum -y install jenkins
  4. Install Xvfb (via the RHEL Server Optional repository)
    # yum -y install xorg-x11-server-Xvfb
    # yum -y install mesa-dri-drivers
    # yum -y install dbus-x11
    # dbus-uuidgen --ensure
  5. Setup Xvfb as a service
    # useradd xvfb
    # vim /etc/init.d/xvfb
    # chkconfig --add xvfb
    # chkconfig xvfb on
  6. Install Firefox 10
    # wget http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm
    # yum -y install epel-release-6-5.noarch.rpm
    # wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
    # yum -y install remi-release-6.rpm
    # yum -y --enablerepo=remi install firefox
  7. Configure Jenkins to use the appropriate virtual display
    # echo "export DISPLAY=:99" >> /etc/sysconfig/jenkins
  8. Start Xvfb and Jenkins
    # service xvfb start
    # service jenkins start
  9. Setup a test Maven project
    • Test dependencies in pom.xml
      <dependencies>
          <dependency>
              <groupId>junit</groupId>
              <artifactId>junit</artifactId>
              <version>4.9</version>
              <scope>test</scope>
          </dependency>
          <dependency>
              <groupId>org.seleniumhq.selenium</groupId>
              <artifactId>selenium-firefox-driver</artifactId>
              <version>2.19.0</version>
              <scope>test</scope>
          </dependency>
      </dependencies>
      
    • Create a test class
      package test;
      import org.junit.*;
      import org.openqa.selenium.WebDriver;
      import org.openqa.selenium.firefox.FirefoxDriver;
      public final class Test {
          
          private WebDriver driver;
          
          @Before
          public void before() {
              driver = new FirefoxDriver();
          }
          
          @Test
          public void test() {
              driver.get("http://www.google.fi");
          }
          
          @After
          public void after() {
              driver.close();
          }
      }
      
  10. Build the project on Jenkins with goals clean test

HTH,
Jukka

Automated WAR deployment

Say you’re building a WAR with Maven, and need to do automated deployment via SSH.

Here’s a working Maven antrun plugin def to get you going:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.6</version>
    <configuration>
        <target>  
            <echo message="Stopping test server ..." />
            <sshexec trust="true" host="test.example.com"
                username="root" keyfile="${user.home}/.ssh/id_rsa"
                command="service tomcat6 stop" />        
            <sleep seconds="10" />
            <echo message="Copying WAR to test server ..." />       
            <scp trust="yes"
                file="${project.build.directory}/${project.build.finalName}.war"
                keyfile="${user.home}/.ssh/id_rsa"
                remoteTofile="root@test.example.com:/usr/share/tomcat6/webapps/app.war" />    
            <echo message="Starting test server ..." />        
            <sshexec trust="true" host="test.example.com" username="root"
                keyfile="${user.home}/.ssh/id_rsa" command="service tomcat6 start" />
            <echo message="Waiting for app to get deployed ..." /> 
            <waitfor maxwait="1" maxwaitunit="minute" checkevery="10" checkeveryunit="second">
                <http url="http://test.example.com/app" />
            </waitfor>        
        </target>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.apache.ant</groupId>
            <artifactId>ant-jsch</artifactId>
            <version>1.8.2</version>
        </dependency>
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.44-1</version>
        </dependency>
    </dependencies>
</plugin>

This example uses SSH public key authentication (be sure to add the SSH public key of the user running the build, e.g. Jenkins, to the SSH authorized_keys file on the test server).

Tomcat (or whatever servlet container you’re using) is restarted to avoid perm gen errors (here we use an /etc/init.d script).

Now just run mvn clean package antrun:run as part of your CI (e.g. Jenkins) build to deploy.

HTH,
Jukka

DIY: Focus 2005 clutch pedal return spring replacement

Summary: this post describes how to install a new clutch pedal return spring for a Ford Focus 2005. Horrible job, but doable, and saves you approx. 80€ (in Finland).

  1. Buy a new spring from your Ford dealer, should be around 5€.
  2. Buy some washers that have approx. the same diameter as the spring (~1cm).
  3. Fit approx. 23 washers to each coil (on both sides) of the spring, to stretch it.
  4. Move the driver’s seat to its rearmost position to improve working conditions.
  5. Lift the steering wheel column to its upmost position to improve working conditions.
  6. Grab a flashlight, lay on your back, place your head next to the pedals and look up. Twist your arm to an akward position to be able to work.
  7. Fit the shorter hook of the spring to the metal plate on the chassis behind the pedal. The hole is barely visible. See rightmost arrow in Picture 2.
  8. Fit the longer hook of the spring to the top of the pedal (it has a small notch to keep the hook in place). See leftmost arrow in Picture 2.
  9. Depress the clutch pedal all the way down to remove the washers, then pull/push out any remaining ones that did not fall off.

Picture 1: Spring with washers (some have already fallen off at this point):
Hooks
Picture 2: Spring hooks in place (longer hook on the left, shorter hook on the right):
Hooks
Picture 3: Finished (with washers removed):
Done

Reference: http://www.fordownersclub.com/forums/topic/6944-clutch-pedal-return-spring/.

HTH,
Jukka

Yet another JUnit test pattern

Testing document templates: generate PDFs in a JUnit test and open them up in Acrobat for immediate visual feedback. Use a random temporary file to avoid file locking.

protected final void renderDocument(String template, Object model)
        throws IOException {
    File folder = new File("target/pdf"); folder.mkdir();
    File pdf = File.createTempFile("test", ".pdf", folder);
    FileOutputStream fos = new FileOutputStream(pdf);
    try {
        new Document()
            .model(model)
            .template(template)
            .renderer(Renderer.FO_TO_PDF)
            .renderTo(fos);
    } finally {
        IOUtils.closeQuietly(fos);
    }
    Assert.assertTrue(pdf.length() > 0);
    if (Desktop.isDesktopSupported()) {
        Desktop.getDesktop().open(pdf);
    }
}

Document uses a Freemarker template and the passed-in model to generate XSL-FO, which in turn is passed to Apache FOP for PDF generation.

-Jukka