Search code examples
javamavengradledroolskie

Kie uses substring to extract its module name. But calls it wrongly?


So I am doing a project that involves a Java implementation of Drools client running up against a KIE service with Drools-WorkBench.

I've started building the final project, though I'm running into some troubles, as the URL of the KIE jar path, seems to have some issues.

So in the meat of the ServiceDiscoveryImpl the application tries to get its module name. This it does with the following commands:

    private static String getModuleName(URL url) {
        String s = url.toString();
        int moduleStart = s.indexOf("META-INF/kie") + "META-INF/kie".length() + 1;
        return s.substring(moduleStart, s.length() - ("kie.conf".length() + 1));
    }

Now in my case the value of s is jar:file:/C:/SLP/Drools/target/war.jar!/META-INF/kie.conf. resulting in the value of moduleStart to be 53

and thus we make a call to String.substring with the value (53, 48). Causing the exception java.lang.StringIndexOutOfBoundsException: begin 53, end 48, length 57

Stacktrace:

java.lang.StringIndexOutOfBoundsException: begin 53, end 48, length 57
    java.base/java.lang.String.checkBoundsBeginEnd(String.java:3319)
    java.base/java.lang.String.substring(String.java:1874)
    org.kie.api.internal.utils.ServiceDiscoveryImpl.getModuleName(ServiceDiscoveryImpl.java:346)
    java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
    java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:913)
    java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)
    org.kie.api.internal.utils.ServiceDiscoveryImpl.findKieConfUrls(ServiceDiscoveryImpl.java:290)
    org.kie.api.internal.utils.ServiceDiscoveryImpl.loadKieConfs(ServiceDiscoveryImpl.java:212)
    java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    java.base/java.util.Spliterators$ArraySpliterator.tryAdvance(Spliterators.java:958)
    java.base/java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:127)
    java.base/java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:502)
    java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:488)
    java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    java.base/java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:150)
    java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    java.base/java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:543)
    org.kie.api.internal.utils.ServiceDiscoveryImpl.getKieConfs(ServiceDiscoveryImpl.java:204)
    org.kie.api.internal.utils.ServiceDiscoveryImpl.getServices(ServiceDiscoveryImpl.java:103)
    org.kie.api.internal.utils.ServiceRegistry$Impl.<init>(ServiceRegistry.java:62)
    org.drools.dynamic.DynamicServiceRegistrySupplier$LazyHolder.<clinit>(DynamicServiceRegistrySupplier.java:27)
    org.drools.dynamic.DynamicServiceRegistrySupplier.get(DynamicServiceRegistrySupplier.java:32)
    org.drools.dynamic.DynamicServiceRegistrySupplier.get(DynamicServiceRegistrySupplier.java:23)
    org.kie.api.internal.utils.ServiceRegistry$Impl.getServiceRegistry(ServiceRegistry.java:90)
    org.kie.api.internal.utils.ServiceRegistry$ServiceRegistryHolder.<clinit>(ServiceRegistry.java:49)
    org.kie.api.internal.utils.ServiceRegistry.getInstance(ServiceRegistry.java:41)
    org.kie.api.internal.utils.ServiceRegistry.getService(ServiceRegistry.java:37)
    org.kie.api.KieServices$Factory$LazyHolder.<clinit>(KieServices.java:358)
    org.kie.api.KieServices$Factory.get(KieServices.java:365)
    utils.KieServerAccessor.validate(KieServerAccessor.java:73) // I call it here
    module.RabbitMQConsumer.handleDrools(RabbitMQConsumer.java:112)
    module.RabbitMQConsumer.access$000(RabbitMQConsumer.java:18)
    module.RabbitMQConsumer$1.lambda$handleDelivery$0(RabbitMQConsumer.java:79)
    java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
    java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
    java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    java.base/java.lang.Thread.run(Thread.java:829)
    

This seems like an oversight from the KIE team, and I would submit it as an issue, if not for the fact that this exception only occurs when running the .jar file, after building.

I have no ide as to how IDEA compiles / runs a java application, but whenever I use that feature, this exception does not occur. So I'm a bit confused whether this is actually a bug in the KIE java client, or just me who did something wrong with my building.

I hope some of you might be able to help explain why KIE does what they do, and how it is me building the jar wrongly that causes the exception.

My pom.xml file is atrocious, but here it is;

<?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/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>dk.slp</groupId>
  <artifactId>DroolsWrapper</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>Drools :: Wrapper</name>
  <description>
    The Wrapper Program which handel validations on received objects from RabbitMQ, and send the result to the output queue.
  </description>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.junit</groupId>
        <artifactId>junit-bom</artifactId>
        <version>5.8.2</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <properties>
    <runtime.version>7.59.0.Final</runtime.version>
    <java.version>8</java.version>
    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>

  </properties>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.22.2</version>
        <configuration>
          <skipTests>true</skipTests>
        </configuration>
      </plugin>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-assembly-plugin</artifactId>
      <executions>
        <execution>
          <phase>package</phase>
          <goals>
            <goal>single</goal>
          </goals>
          <configuration>
            <finalName>war</finalName>
            <archive>
              <manifest>
                <mainClass>
                  SLPDrools
                </mainClass>
              </manifest>
            </archive>
            <descriptorRefs>
              <descriptorRef>jar-with-dependencies</descriptorRef>
            </descriptorRefs>
            <appendAssemblyId>false</appendAssemblyId>
          </configuration>
        </execution>
      </executions>
    </plugin>
    </plugins>
  </build>
  <repositories>
    <repository>
      <id>jboss-public-repository-group</id>
      <name>JBoss Public Repository Group</name>
      <url>http://repository.jboss.org/nexus/content/groups/public/</url>
      <releases>
        <enabled>true</enabled>
        <updatePolicy>never</updatePolicy>
      </releases>
      <snapshots>
        <enabled>true</enabled>
        <updatePolicy>daily</updatePolicy>
      </snapshots>
    </repository>
  </repositories>

  <dependencies>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-core</artifactId>
      <version>${runtime.version}</version>
    </dependency>
    <dependency>
      <groupId>org.drools</groupId>
      <artifactId>drools-decisiontables</artifactId>
      <version>${runtime.version}</version>
    </dependency>
    <dependency>
      <groupId>org.jbpm</groupId>
      <artifactId>jbpm-test</artifactId>
      <version>${runtime.version}</version>
    </dependency>
    <dependency>
      <groupId>org.kie.server</groupId>
      <artifactId>kie-server-client</artifactId>
      <version>${runtime.version}</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>ch.qos.logback</groupId>
      <artifactId>logback-classic</artifactId>
      <version>1.2.10</version>
    </dependency>
    <dependency>
      <groupId>com.rabbitmq</groupId>
      <artifactId>amqp-client</artifactId>
      <version>5.13.1</version>
    </dependency>
    <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-all</artifactId>
      <version>1.10.19</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.droolsassert</groupId>
      <artifactId>droolsassert</artifactId>
      <version>3.0.8</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.junit.jupiter</groupId>
      <artifactId>junit-jupiter</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>failureaccess</artifactId>
      <version>1.0.1</version>
    </dependency>
  </dependencies>

</project>


EDIT:

So I narrowed down the problem a bit further, by trying to build with gradle instead using this process

jar {
    manifest {
        attributes "Main-Class": "$mainClassName"
    }

    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

and it displays this error message;

Caused by: org.gradle.api.GradleException: Could not expand ZIP 'C:\Users\asger.weirsoe\.m2\repository\org\kie\kie-ci\7.59.0.Final\kie-ci-7.59.0.Final.jar'.

Now I'm no expert, and getting a bit frustrated in the JAVA building mechanism. But I think this might be my issue, that some library that I need, which is fetched in the background is not baked into the .jar file. Resulting in my issues.

I googled this and found this in the documentation for KIE. But tbh it just made me more confused than gave me answers.


Solution

  • The problem was in regards to how KIE manages its dependencies.

    The solution was to instead not build everything into the same jar, as some of the dependencies that KIE has packaged some dependencies with the same name but different functionalities, which were overwriting each other.