Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Using Kotlin on the SAP Hybris Platform

DZone's Guide to

Using Kotlin on the SAP Hybris Platform

Sure you can use Groovy and Scala with SAP Hybris, but what about Kotlin? Here's what it takes to bring Kotlin to Hybris.

· Java Zone ·
Free Resource

Verify, standardize, and correct the Big 4 + more– name, email, phone and global addresses – try our Data Quality APIs now at Melissa Developer Portal!

Since I discovered Kotlin, I use it in all my personal projects. I’ve become quite fond of the language, and with good reason. However, there’s yet no integration with the Hybris platform — though there is with Groovy and Scala. This post aims at achieving just that, to be able to use Kotlin on Hybris projects.

Generate a New Extension

The first step on the journey is to create a new extension:

  1. Choose the yempty package
  2. Choose an adequate name, e.g. "kotlinfun"
  3. Choose a root package, e.g.ch.frankel.blog.kotlin

Don’t forget to add this new extension to the localextensions.xml file.

Add Libraries

Kotlin requires libraries, both to compile and to run. They include:

  • kotlin-ant.jar
  • kotlin-compiler.jar
  • kotlin-preloader.jar
  • kotlin-reflect.jar
  • kotlin-script-runtime.jar

Though it would be nice to use external-dependencies.xml, some JARs are not available as Maven dependencies (e.g.kotlin-ant.jar). Thus, it’s required to manually get the relevant Kotlin compiler and unpack it.

Create Folders

To help with the build, let’s create dedicated folders for sources and tests, respectively kotlinsrc and kotlintestsrc. Configure the module or the project accordingly — depending whether your IDE of choice is IntelliJ IDEA or Eclipse.

On the Hybris platform, both sources and tests will compile in the same folder.

Create simple Kotlin files in kotlinsrc and kotlintestsrc.

Configure Kotlin in the IDE

While we're at it, configure Kotlin for the IDE. IntelliJ IDEA will pop-up an alert box to do so if a Kotlin file is created anyway. I have no clue about Eclipse…

The Fun Part

Now that compiling works inside of the IDE, it should also be part of the standard command-line build. Fortunately, there are build hooks in the Hybris build pipeline. Those are configured inside the build_callbacks.xml file.

A naive first draft would look like:

<project name="kotlinfun_buildcallbacks">

    <property name="kotlin.lib.dir" location="${ext.kotlinfun.path}/lib"/>

    <taskdef resource="org/jetbrains/kotlin/ant/antlib.xml">
        <classpath>
            <pathelement location="${kotlin.lib.dir}/kotlin-ant.jar"/>
            <pathelement location="${kotlin.lib.dir}/kotlin-compiler.jar"/>
            <pathelement location="${kotlin.lib.dir}/kotlin-preloader.jar"/>
            <pathelement location="${kotlin.lib.dir}/kotlin-reflect.jar"/>
            <pathelement location="${kotlin.lib.dir}/kotlin-script-runtime.jar"/>
        </classpath>
    </taskdef>

    <macrodef name="kotlin_compile">
        <attribute name="srcdir"/>
        <attribute name="destdir"/>
        <attribute name="extname"/>

        <sequential>
            <echo message="compile kotlin sources for @{extname} using srcdir: @{srcdir}"/>
            <mkdir dir="@{destdir}"/>
            <kotlinc src="@{srcdir}" output="@{destdir}">
                <classpath>
                    <pathelement location="${kotlin.lib.dir}/kotlin-stdlib.jar"/>
                    <fileset dir="${ext.@{extname}.path}" erroronmissingdir="false">
                        <include name="${ext.@{extname}.additional.src.dir}/**"/>
                        <include name="${ext.@{extname}.additional.testsrc.dir}/**"/>
                    </fileset>
                    <pathelement path="${build.classpath}"/>
                    <pathelement path="${platformhome}/bootstrap/bin/models.jar" />
                    <fileset dir="${bundled.tomcat.home}">
                        <include name="lib/jsp-api.jar"/>
                        <include name="lib/servlet-api.jar"/>
                        <include name="lib/el-api.jar"/>
                        <include name="lib/wrapper*.jar"/>
                    </fileset>
                    <pathelement path="${ext.@{extname}.classpath}" />
                </classpath>
            </kotlinc>
        </sequential>
    </macrodef>

    <macrodef name="kotlinfun_compile_core">
        <attribute name="extname"/>
        <sequential>
            <if>
                <isset property="ext.@{extname}.coremodule.available"/>
                <then>
                    <if>
                        <istrue value="${ext.@{extname}.extension.coremodule.sourceavailable}"/>
                        <then>
                            <kotlin_compile srcdir="${ext.@{extname}.path}/kotlinsrc"
                                           destdir="${ext.@{extname}.path}/classes"
                                           extname="@{extname}"/>
                            <kotlin_compile srcdir="${ext.@{extname}.path}/kotlintestsrc"
                                           destdir="${ext.@{extname}.path}/classes"
                                           extname="@{extname}"/>
                        </then>
                    </if>
                </then>
            </if>
        </sequential>
    </macrodef>

    <macrodef name="kotlinfun_after_compile_core">
        <sequential>
            <kotlinfun_compile_core extname="kotlinfun"/>
        </sequential>
    </macrodef>
</project>


The above is configured for a simple core module, not a web one. It can be added afterward though.

Unfortunately, this doesn’t work. Launching the build with ant build will produce the following output:

/hybris/bin/platform/resources/ant/compiling.xml:530: java.lang.NoSuchMethodError:
 com.google.common.collect.Iterables.filter(Ljava/lang/Iterable;Lcom/google/common/base/Predicate;)Ljava/lang/Iterable;


Looking more closely at the kotlin-compiler.jar, one must notice it embeds Guava, which also happens to be on the hybris classpath. Hence, there’s a version conflict. Fortunately, there’s a smarter version of the compiler — kotlin-compiler-embeddedable.jar available on repo1 — that shades Guava, i.e. embeds it using a different package name, thus resolving the conflict. Just update the callback file with the new JAR name and you're done.

Now, the build produces a different output:

/hybris/bin/custom/kotlinfun/buildcallbacks.xml:34: java.lang.IllegalStateException:
 File is not found in the directory of Kotlin Ant task: kotlin-compiler.jar


For reasons unknown, the Ant task checks the existence of dependent libraries using their file names! Check the source code for proof. There’s an evil workaround: Rename the JAR as it’s expected. And update the build file back to the initial version…

At this point, it’s possible to build the platform with Kotlin files compiled.

Improvements

Though it works, there are a couple of possible improvements:

  • Change the lib folder to a dedicated folder e.g. compile, so as not to ship it in the distributed archive.
  • Add the configuration to also compile a web module.
  • Refactor the macros into a common extension so that different Kotlin extensions can use it.

In the end, nothing prevents you from using Kotlin on SAP Hybris right now!

Developers! Quickly and easily gain access to the tools and information you need! Explore, test and combine our data quality APIs at Melissa Developer Portal – home to tools that save time and boost revenue. 

Topics:
java ,kotlin ,sap hybris ,extension ,tutorial

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}