0

I have a Spring Boot application developed in STS which connects to SAP through SAP Java connector. That connector comes in a jar whose rules forbid renaming or repackaging the archive.

Since the application must run on several platforms, I've locally repackaged the SAP JCO jars in a custom set of dependencies so shaped:

connectors-project
|   pom.xml
|       
+---sap-jco-api
|       pom.xml
|       sapjco3.jar
|
+---sap-jco-linux-x86_64
|   |   pom.xml
|   |       
|   \---src
|       \---main
|           \---resources
|                   libsapjco3.so
|                   Readme.txt
|                   sapjco3.jar
|                   sapjcomanifest.mf
|               
\---sap-jco-nt-amd64
    |   pom.xml
    |       
    \---src
        \---main
            \---resources
                    Readme.txt
                    sapjco3.dll
                    sapjco3.jar
                    sapjco3.pdb
                    sapjcomanifest.mf

The sap-jco-api module is used for compilation, the others for execution. Proper packaging is handled on a per-project basis, configuring the maven-dependency-plugin plugin each time.

For the Spring Boot application in question, here's the relevant portion of the POM:

<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>...</groupId>
    <artifactId>...</artifactId>
    <packaging>...</packaging>
    <version>...</version>

    <name>...</name>
    <description>...</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
    </parent>

  <properties />

    <build>

        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <Class-Path>sap-jco/sapjco3.jar</Class-Path>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>...</mainClass>
                    <excludeGroupIds>com.sap</excludeGroupIds>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                  <execution>
                    <id>unpack-dependencies-package</id>
                    <phase>package</phase>
                    <goals>
                      <goal>unpack-dependencies</goal>
                    </goals>
                    <configuration>
                        <excludeTransitive>true</excludeTransitive>
                        <includeGroupIds>com.sap</includeGroupIds>
                        <excludeArtifactIds>sap-jco-api</excludeArtifactIds>
                        <excludes>META-INF/**</excludes>
                      <outputDirectory>${project.build.directory}/sap-jco</outputDirectory>
                    </configuration>
                  </execution>
                </executions>
            </plugin>

        </plugins>

    </build>

    <dependencies>

        <!-- Spring Boot -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>...</artifactId>
        </dependency>

        <!-- SAP JCO connector -->
        <dependency>
            <groupId>com.sap</groupId>
            <artifactId>sap-jco-api</artifactId>
            <version>3.0.18</version> 
            <scope>provided</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>com.sap</groupId>
            <artifactId>sap-jco-nt-amd64</artifactId>
            <version>3.0.18</version>
            <scope>provided</scope>
        </dependency>

        <!--  other -->
        <dependency>...</dependency>

    </dependencies>

</project>

At package time, all SAP dependencies are excluded from the jar produced by spring-boot-maven-plugin and the platform-specific files are copied to a subdirectory made visible to the final jar by the MANIFEST Class-Path entry.

This is the Maven-created target folder for that POM:

application-project
|   
\---target
    |   application.jar
    |   
    \---sap-jco
            Readme.txt
            sapjco3.dll
            sapjco3.jar
            sapjco3.pdb
            sapjcomanifest.mf

The resulting jar works as expected when run with java -jar target\application.jar.

The problem arises in STS (or Eclipse), when I run the application with right click -> Run As -> Spring Boot App, the project seems to be packaged in a default way - thus with the SAP jar packaged - and execution breaks with:

JCo initialization failed with java.lang.ExceptionInInitializerError: Illegal JCo archive [...]. It is not allowed to rename or repackage the original archive "sapjco3.jar".

I guess I have to somehow replicate the Maven configuration within the IDE, but I can't find a way to do that. In "Run configurations" there doesn't seem to be a way to do this, nor does that menu command seem to run the Spring Boot Maven Plugin spring-boot:run goal, that I could configure inside the POM.

This is impeding me from debugging the application from inside the IDE and I'm also forced to manually package and run it from the command line, slowing down development.

What can I do?

Boghyon Hoffmann
  • 17,103
  • 12
  • 72
  • 170
watery
  • 5,026
  • 9
  • 52
  • 92
  • You can add the `lib.path` (or was it `path.lib`) to the arguments of the JVM pointing to the directory containing the needed jar. – M. Deinum Jan 23 '19 at 13:34
  • @M.Deinum I was expecting suggestions about how to configure the run, but I understand I must share more details. I need to gather them first though. – watery Jan 23 '19 at 13:37
  • Not sure which comment you react to (I deleted my initial comment). You should be able to specify the `loader.path` (not `lib.path`) pointing to a directory containing the external jar files. You would need to do something alike for actually packaging and running the application. – M. Deinum Jan 23 '19 at 13:38
  • @M.Deinum I saw both, but I felt an almost full rewrite was necessary. I've just done it. – watery Jan 24 '19 at 12:59

0 Answers0