Question

We managed to create and run tests with internationalized stories using JBehave within eclipse. Everything went fine.

But when we tried to run them using the maven plug-in, we cannot get rud of the encoding problem (for example, instead of reading "scénario" from the story, it gets "Scénario" : clearly an UTF8 encoding problem).

Does someone have found a way to get JBehave to read the stories in UTF8 using the maven plug-in ?

What we already tried :

  • adding -Dfile.encoding=UTF-8 option
  • changing keyword file using UTF8
  • changing the whole project encoding in ISO => which works but isn't suitable for production part that need to display messages in UTF8

our Pom.xml

<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">
...

<properties>
    <jbehave.version>3.6.5</jbehave.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <resource.encoding>UTF-8</resource.encoding>
</properties>

<build>

    <testOutputDirectory>target/classes</testOutputDirectory>
    <testResources>
        <testResource>
            <directory>src/test/resources</directory>
        </testResource>
        <testResource>
            <directory>src/test/story</directory>
        </testResource>
    </testResources>
    <plugins>
        ...
        <plugin>
            <artifactId>maven-eclipse-plugin</artifactId>
            <version>2.8</version>
            <configuration>
                <downloadSources>true</downloadSources>
                <downloadJavadocs>true</downloadJavadocs>
                <additionalBuildcommands>
                    <buildcommand>com.google.gdt.eclipse.core.webAppProjectValidator</buildcommand>
                </additionalBuildcommands>
                <additionalProjectnatures>
                    <projectnature>com.google.gwt.eclipse.core.gwtNature</projectnature>
                </additionalProjectnatures>
                <classpathContainers>
                    <classpathContainer>org.eclipse.jdt.launching.JRE_CONTAINER</classpathContainer>
                </classpathContainers>
                <additionalConfig>
                    <file>
                        <name>.settings/org.eclipse.core.resources.prefs</name>
                        <content>
                           <![CDATA[eclipse.preferences.version=1
                           encoding/<project>=UTF-8]]>
                        </content>
                    </file>
                </additionalConfig>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.jbehave</groupId>
            <artifactId>jbehave-maven-plugin</artifactId>
            <version>${jbehave.version}</version>
            <executions>
                <execution>
                    <id>run-stories-as-embeddables</id>
                    <phase>test</phase>
                    <configuration>
                        <scope>test</scope>
                        <includes>
                            <include>**/*Story.java</include>
                        </includes>
                        <ignoreFailureInStories>true</ignoreFailureInStories>
                        <ignoreFailureInView>false</ignoreFailureInView>
                    </configuration>
                    <goals>
                        <goal>run-stories-as-embeddables</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>unpack-jbehave-site-resources</id>
                    <phase>generate-resources</phase>
                    <goals>
                        <goal>unpack</goal>
                    </goals>
                    <configuration>
                        <overwriteReleases>false</overwriteReleases>
                        <overwriteSnapshots>true</overwriteSnapshots>
                        <artifactItems>
                            <artifactItem>
                                <groupId>org.jbehave.site</groupId>
                                <artifactId>jbehave-site-resources</artifactId>
                                <version>3.1.1</version>
                                <type>zip</type>
                                <outputDirectory>
                                    ${project.build.directory}/jbehave/view
                                </outputDirectory>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
                <execution>
                    <id>unpack-jbehave-reports-resources</id>
                    <phase>generate-resources</phase>
                    <goals>
                        <goal>unpack</goal>
                    </goals>
                    <configuration>
                        <overwriteReleases>false</overwriteReleases>
                        <overwriteSnapshots>true</overwriteSnapshots>
                        <artifactItems>
                            <artifactItem>
                                <groupId>org.jbehave</groupId>
                                <artifactId>jbehave-core</artifactId>
                                <version>${jbehave.version}</version>
                                <outputDirectory>
                                    ${project.build.directory}/jbehave/view
                                </outputDirectory>
                                <includes>
                                    **\/*.css,**\/*.ftl,**\/*.js
                                </includes>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

<dependencies>
    ...

    <!-- JBehave Dependencies -->
    <dependency>
        <groupId>org.jbehave</groupId>
        <artifactId>jbehave-core</artifactId>
        <version>${jbehave.version}</version>
    </dependency>

    <!-- Test Frameworks Dependencies -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.8.2</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-all</artifactId>
        <version>1.8.4</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Was it helpful?

Solution

I have had some success subclassing the org.jbehave.core.io.LoadFromClasspath class, which I use in my configuration as the story loader, i.e.

MostUsefulConfiguration().useStoryLoader(new LoadFromClasspathUtf8());

here's my subclass with the proper method override:

import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.io.IOUtils;
import org.jbehave.core.io.InvalidStoryResource;
import org.jbehave.core.io.LoadFromClasspath;

public class LoadFromClasspathUtf8 extends LoadFromClasspath {

    public LoadFromClasspathUtf8(Class<?> loadFromClass) {
        super(loadFromClass);
    }

    public LoadFromClasspathUtf8(ClassLoader classLoader) {
        super(classLoader);
    }

    @Override
    public String loadResourceAsText(String resourcePath) {
        InputStream stream = resourceAsStream(resourcePath);
        try {
            return IOUtils.toString(stream, "UTF-8");
        } catch (IOException e) {
            throw new InvalidStoryResource(resourcePath, stream, e);
        }
    }
}

I say "I had some success" because when I look at the logs of my jbehave execution, accented french characters like è,à,é etc. are replaced by ?, but then, jbehave still matches this correctly to the steps using the regular RegexStoryParser. I didn't take time to investigate why this is, but I'm satisfied that my stories work correctly now.

I also added the file.encoding system property to my plugin configuration to make it clear that I intend to use UTF-8 encoding.

OTHER TIPS

Same problem here as well. Even after adding the "-Dfile.encoding=UTF-8" parameter to MAVEN_OPTS the problem persisted. Turn out that I had this line inside my ~/.mavenrc file:

export MAVEN_OPTS="-Xmx1024m"

What was happening is the MAVEN_OPTS variable got reset before executing the JVM.

After change the ~/.mavenrc file to:

export MAVEN_OPTS="$MAVEN_OPTS -Xmx1024m"

The problem was solved. The file encoding is set correct when running:

export MAVEN_OPTS="$MAVEN_OPTS -Dfile.encoding=UTF-8"
mvn clean integration-test

Since you have your stories in the "test" context rather than "main" (in another module) - I think that there is probably something going on when stories are copied to target/test-classes.

I had exactly the same problem. By default, JBehave doesn't honor platform encoding. In order to fix this, you can use this custom StoryLoader which honors file.encoding system property:

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

import org.apache.commons.io.IOUtils;
import org.jbehave.core.io.InvalidStoryResource;
import org.jbehave.core.io.LoadFromClasspath;

/**
 * @author cedric.vidal
 *
 */
public class FixedStoryLoader extends LoadFromClasspath {

    public String loadResourceAsText(String resourcePath) {
        InputStream stream = resourceAsStream(resourcePath);
        try {
            return IOUtils.toString(stream, platformCharset().name());
        } catch (IOException e) {
            throw new InvalidStoryResource(resourcePath, stream, e);
        }
    }

    public static Charset platformCharset() {
        String csn = System.getProperty("file.encoding");
        Charset cs = Charset.forName(csn);
        if (cs == null) {
            cs = Charset.forName("UTF-8");
        }
        return cs;
    }

}

Register it in JBehave configuration with:

new MostUsefulConfiguration().useStoryLoader(new FixedStoryLoader());

Configure your POM to use UTF-8 in all respectfull plugins (will be used by m2eclipse too):

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

And tell the JBehave Maven Plugin to use it also (look for the systemProperties block):

        <plugin>
            <groupId>org.jbehave</groupId>
            <artifactId>jbehave-maven-plugin</artifactId>
            <version>${jbehave.core.version}</version>
            <executions>
                <execution>
                    <id>unpack-view-resources</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>unpack-view-resources</goal>
                    </goals>
                </execution>
                <execution>
                    <id>embeddable-stories</id>
                    <phase>integration-test</phase>
                    <configuration>
                        <includes>
                            <include>${embeddables}</include>
                        </includes>
                        <excludes/>
                        <systemProperties>
                            <property>
                                <name>file.encoding</name>
                                <value>${project.build.sourceEncoding}</value>
                            </property>
                        </systemProperties>
                        <ignoreFailureInStories>true</ignoreFailureInStories>
                        <ignoreFailureInView>false</ignoreFailureInView>
                        <threads>1</threads>
                        <metaFilters>
                            <metaFilter/>
                        </metaFilters>
                    </configuration>
                    <goals>
                        <goal>run-stories-as-embeddables</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top