Find in What Jar a Class Is

Oh my. Somebody’s been excidingly verbose… Here’s another attempt:

Comment [1]

 
---

Java Annotations with JRuby: A Spring MVC Example

To illustrate the use of Java annotations with JRuby code, I have put together a little Spring MVC example. This is quite straightforward, especially if you are familiar with Spring MVC already.

The Controller in JRuby

The “heart” of the app is the Spring MVC controller which must be annotated with the Controller annotation, and its request path defined with the RequestMapping annotation:

We also put the class in the com.weblogism.myapp package, we’ll see why in a second.

Spring Configuration

The Spring MVC configuration is pretty much “standard”:

It defines the component-scan tag that will look for all the classes annotated with Controller in the com.weblogism.myapp; you now see why we used java_package for our controller.

Compiling

The compiling and packaging is done by Maven. Again, nothing really extraordinary in the pom.xml. The only unconventional feature is the use of the jruby-maven-plugin to compile our JRuby class into a Java class:

It generates its output into target/generate-sources/jruby, and compiles out class into target/classes, like any other Java class. The output of the build is a war file that can be deployed in a Java EE container.

Running

To see our amazing app in action, run Jetty:

 mvn jetty:run

Once Jetty is up, you can access the app at http://localhost:8080/welcome.html

Comment

 
---

Cucumber-jvm 1.1.3 issue with JSON formatter

I have been struggling with a weird cucumber issue today, as it took me some time to figure out what was going on, I thought I’d share this in case somebody is going down the same path.

It started when I decided to upgrade my cucumber-jvm example to the latest version (1.1.3). Quickly after upgrading, I hit that error:

java.lang.ArrayIndexOutOfBoundsException: -1
    at java.util.ArrayList.get(ArrayList.java:324)
    at gherkin.formatter.JSONFormatter.getFeatureElement(JSONFormatter.java:199)
    at gherkin.formatter.JSONFormatter.addHook(JSONFormatter.java:156)
    at gherkin.formatter.JSONFormatter.before(JSONFormatter.java:147)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

This is known issue, that has already been fixed in gherkin.

So I rebuilt gherkin locally, thinking it would solve all my problems, and I was still the exact same error, at the same line number. After changing version, deleting the jar from the Maven repository, I was still getting the same error, so it was clear that the class was being pulled from somewhere else.

It turns out the jar was being pulled from cucumber-picocontainer, which uses shade to create an über-jar with its dependencies, including gherkin. How did I figure that out? Using this piece of code:

        URL location = JSONFormatter.class.getProtectionDomain().getCodeSource().getLocation();
        System.err.println(location.getPath());

The solution to the problem is therefore to rebuild gherkin, then cucumber-picocontainer, and you’re sorted.

Alternatively you can also just rebuild gherkin, and then make sure it is defined before cucumber-picocontainer:

        <dependency>
          <groupId>info.cukes</groupId>
          <artifactId>gherkin</artifactId>
          <version>2.11.8</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>info.cukes</groupId>
          <artifactId>cucumber-picocontainer</artifactId>
          <version>1.1.3</version>
          <scope>test</scope>
        </dependency>


Comment

 
---

joblist.ie now live!

A new job website for Ireland IT companies has been launched; the frontend is HTML5 and Backbone.js. It is still work in progress, and lots of cool features are coming up.

Comment

 
---

How to use System Properties and Maven profiles to change Cucumber-jvm’s behaviour

In a previous post, I had shown how to use Maven profiles to execute integration tests with cucumber-jvm.

I have now updated the example to use WebDriver rather than selenium RC, and to show how to use the cucumber.options system properties to change the cucumber-jvm runtime behaviour.

To use cucumber.options and its default value, you create a variable:

that you can then use as a system variable for failsafe:

It is then straightforward to override these options using a profile to run different tags or produce different reports depending on the development cycle you are in:

It is also possible to override these options using the command line by executing:

mvn install -Dcucumber.options="--tags @foo --format pretty --monochrome"

Passing your own properties

If you need to define your own properties and want to pass them either from the command line with -D=, or from the <properties> tag, and want to be able to retrieve these system properties from your step definitions, you must add an entry in the systemPropertyVariables tag when configuring failsafe. For example, say you want to have a ui.language property, add that property to the properties tag:

<properties>
  <ui.language>FR</ui.language>
  . . .
  <cucumber.options>--format html:target/cucumber --tags @wip,@foo</cucumber.options>
</properties>

This will give you the “default” value for your property; then add it to systemPropertyVariables:

           <plugin>
            <artifactId>maven-failsafe-plugin</artifactId>
            <version>2.12</version>
            <executions>
              <execution>
                <goals>
                  <goal>integration-test</goal>
                  <goal>verify</goal>
                </goals>
              </execution>
            </executions>
           <configuration>
             <systemPropertyVariables>
               <cucumber.options>${cucumber.options}</cucumber.options>
               <ui.language>${ui.language}</ui.language>
            </systemPropertyVariables>
          </configuration>
         </plugin>

This will cause failsafe to pass on this property to the forked JVM running the tests. You can then override the “default” property either in a profile, or on the command line:

mvn install -Dui.language=EN

Note that this will work properly when cucumber-jvm 1.0.15 is released; until then you need to re-define the glue and path to features if you override cucumber.options, as setting that system properties clears all options set by the Cucumber.Options annotation.

Comment

 
---

Integration Tests with Cucumber-jvm, Selenium and Maven

This post will show how to use cucumber-jvm and Maven to run integration tests with Selenium on a regular webapp; as you’ll see, this is more of a Maven exercise than a cucumber-jvm one, as Cucumber tests are simply executed as JUnit tests. It can be a bit tricky as it requires a bit of Maven build lifecycle knowledge1, but once you get the idea, it all makes perfect sense.

For those only interested in the example, you will find it there.

The first thing we want to do is to segregate the integration tests from the unit tests. The reason for this is that it makes it easier to locate them, but also it allows you to run them separately: this is especially important if you want run the integration tests as part of your CI build. I personally prefer to have my integration tests under src/it/java, and suffixed with IT, so to do this, we first create a new profile and add the maven-failsafe-plugin:

The profile will be helpful to separate the integration tests execution if you want to run only in certain situations; it can also be used to define property values specifically for integration tests.

We then create the src/it/java and src/it/resources folders: src/it/resources will contain the feature files, whereas src/it/java will contain the step definitions and the JUnit test cases to be executed. We also need to add the new source folders to
the build with the build-helper-maven-plugin:

The JUnit test case is very simple:

It actually is empty: it cannot contain any method. It uses the Cucumber JUnit runner. The Cucumber.Options can be used to specify the format of the report created during the test, the feature files to execute, or the tags to run.

Next, the feature file is here somewhat trivial:

Finally, here are the step definitions:

As you can see, we are using the Selenium client in this step definition. We therefore need to add the dependencies to selenium (along with the cucumber-jvm ones) in our profile:

We also need to start the selenium server before the tests begin:

This plugin defines here two executions: start-selenium-server, which is executed before the integration tests during the phase called pre-integration-test, and calls the start goal, and stop-selenium-server called after the integration tests, during the post-integration-test phase, and that calls the stop goal of that plugin (for a reminder of the different phases of the build lifecycle, see the reference).

Finally, we configure the Jetty maven plugin to start and deploy the war we want to test:

Similarly to the selenium plugin, we start the Jetty server pre-integration-test (by running the run goal, and stop it post-integration-test with the stop goal.

We can now execute the tests by running:

 mvn clean verify -Pintegration-tests

The -P flag indicates that Maven must activate the integration-tests profile; as the plugins and dependencies are defined in that profile, the integration tests will only be executed if you activate that profile.

Summary

All the required “services” (Jetty, Selenium) are started during the pre-integration-test phase, and then stopped during the post-integration-test phase. The cucumber integration tests stored in src/it/java are executed during the integration-test phase by running the JUnit tests that use Cucumber.class as a runner.

To run the integration tests:

  • Create a new profile,
  • Add src/it/java as a test source folder,
  • Create your feature file,
  • Implement the step definitions,
  • Add the failsafe plugin,
  • Add the selenium server plugin,
  • Add the jetty plugin.

Hope this helps!

1 Once you’ve understood the build lifecycle, you understand Maven, so most definitely a knowledge worth having!

Comment [9]

 
---

5 March 2012

,

Example of .jrubyrc

I have put together an example of .jrubyrc, which can prove very useful when working on JRuby devs:

Comment

 
---

28 November 2011

,

Closed root in LaTeX

Stefan Kottwitz on how to make closed root symbols. Cool.

 
---

8 September 2011

,

Ruby, mongodb, genome... Cool.

Probably not what Mr. Yegge had in mind, but still inspiring all the same: analysing how many SNPs are in common between different populations using ruby and mongodb.

SNP (snip) stands for single-nucleotide polymorphism it is a variation of a single base pair amongst individuals of a species. SNPs can occur in coding and non-coding sequences, or between genes in the genome and can be used to identity genotypes.

(Pity MS isn’t a genetic condition)

On another note:

Comment [2]

 
---

31 August 2011

,

Sonar's "result returns more than one elements"

We have been hitting the dreaded Sonar error lately, resulting in constantly broken Hudson builds:

Caused by: javax.persistence.NonUniqueResultException: result returns more than one elements

The only workaround I could find was Pti’s database clean up. Doing this manually was a pain, especially after coming back from holidays, when a couple of weeks of records had been created.

So I have come up with a quick JRuby script to semi-automate this. And here is how to use it:

  • Save this script in clean_sonar.rb,
  • Update the Sonar database details with the correct values,
  • Download mysql connector jar, and save it in the same folder as your ruby script,
  • Backup your database,
  • Make sure your database backup is ok,
  • Check again (I guess you’re now warned),
  • Run the script as follows:
$ jruby clean_sonar.rb

And here is the (quick’n‘dirty) script.

Comment

 
---

UTF-8 Euro Symbol in LaTeX

XeLaTeX

XeLaTeX is the easiest approach, it works out of the box:

\documentclass[a4paper,10pt]{article}

\usepackage{xltxtra}
\usepackage[french]{polyglossia}

\begin{document}
Donne-moi 5\,€.
\end{document}

“Classic” LaTeX

LaTeX requires the use of textcomp to get the euro symbol:

\documentclass[a4paper,10pt]{article}

\usepackage[utf8]{inputenc}
\usepackage{textcomp}
\usepackage[frenchb]{babel}
\usepackage[T1]{fontenc}

\begin{document}
Donne-moi 5\,€.
\end{document}

Comment

 
---

6 March 2011

,

JMenuBar Support in Rubeus

I have added JMenuBar support to Rubeus. It is not released yet, but you can clone the git repo and play with it. The implementation is rather naive, but it works well for my needs.

Comment [1]

 
---

6 March 2011

,

Packaging EAR file for JBoss 5.1 with Maven

The dependencies in a JBoss ear file go into the lib folder at the root of the archive;

      <plugin>
        <artifactId>maven-ear-plugin</artifactId>
        <version>2.5</version>
        <configuration>
          <defaultLibBundleDir>lib</defaultLibBundleDir>
          <modules>
            <ejbModule>
              <groupId>com.example.core</groupId>
              <artifactId>core-business</artifactId>
            </ejbModule>
            <webModule>
              <groupId>${project.parent.groupId}</groupId>
              <artifactId>example-web</artifactId>
              <uri>mydnb-web.war</uri>
            </webModule>
          </modules>
          <jboss>
            <version>5</version>
            <loader-repository>${project.parent.groupId}:archive=example-ear.ear</loader-repository>
          </jboss>
        </configuration>
      </plugin>

defaultLibBundleDir ensures that the dependencies get copied into the lib folder, whilst leaving the modules core-business and example-web.war at the root.

Comment

 
---

21 February 2011

,

Look What Arrived Today?!

Yay!!

JRuby book cover

If only I had received it before my DnB JRuby presentation

Comment

 
---

Mrs Rabbit in Peppa Pig is a workaholic

And I’m glad I’m not the only one to worry about her numerous jobs: she sales ice cream, she is a librarian, she works at the fire station…

Comment

 
---

← Older