Hi Thorben,
let me make a step back and explain a little bit my requirement. For any Java API you have two sides - the implementers and the users. In case of Camunda API the default implementer is the engine and the default caller - a process application. Things change slightly if we speak about community extensions.
Let me give you some examples for implementer:
- Camunda BPM Mockito extension aims to provide mocks for Camunda API. In doing so it serves as an alternative implementer.
- Camunda Spring Boot REST extension aims to provide a client implementation of the API, which delegates all calls via REST to a remote engine - again, it is acting as an implementer.
Problem: in both cases you don’t need the entire Camunda Engine to be n the classpath, but only the API classes.
Most cases of being a call is not a problem, since you need the real implementer (the engine to work). Again a small example:
- Camunda BPM Data extension aims to provide a uniform access to variables (independent of the access scope). In doing so it provides factories to read/write variables from variable map (part of common-variables library), runtime service, task service, case service, external locked task, and variable scope. In doing so the user of the extension benefits from the fact that most methods are overloaded in a way, that you can provide any of the scopes mentioned above, from which you want to access variables.
Problem: On the binary level, it is only possibly to use the library if the classes representing the upper scope are on the class path - a small but ugly problem… If you want to work on Variable Map (valid in context of DMN engine without process engine) you need the process engine on the classpath…
Generally speaking, it is easier to provide the API for the client than for the implementer.
My idea was to try to separate the required classes to a separate artifact (maybe as additional artifact with a classifier as you mention, or as a separate build). The first thing I did was to decide what should be a part of it.
My first estimate is that it consists of:
- Service API (mainly of
org/camunda/bpm/engine/*Service.java
classes and everything they import directly)
- Delegation API (mainly
org/camunda/bpm/engine/delegate/**/*.java
)
Especially the service API imports classes out of the first-level packages of org/camunda/bpm/engine/
, but the main idea was to exclude the entire impl
package from being packed.
So I ended up in the following implementation idea for the moment… I take the engine JAR, unpack it providing a white list and a black list of classes and try to compile it. As a result, I could “draw a line” between API and implementation. There are few but pretty serious violations that I could identify. Some of them are pretty easy to fix, some of them not…
From the point of view of providing a separate API, the violations mean that the class is directly referenced by parts of the API (means it is a direct import of an API class and will be required by the implementers to be on the classpath) AND is in the same time an implementation class (referencing another dozen of implementation classes). As a first estimate (I believe we need something better here), I resolved this issue with the following approach: I excluded the class from the original and replaced it by the own empty implementation (throwing an exception on a call). I tried to draw the API line as close as possible to the Service and Delegation API, to make the module compile…
I could create a list of issues identified so far and we can discuss on them further. I think there is always a solution for any particular one.
What do you think?
Cheers,
Simon