client_java icon indicating copy to clipboard operation
client_java copied to clipboard

Split package in simpleclient.servlet and simpleclient.pushgateway

Open agavrilov76 opened this issue 3 years ago • 9 comments

Modules simpleclient.servlet and simpleclient.pushgateway are exporting classes from the same package io.prometheus.client.exporter causing troubles when building Java modular applications due to a split package error:

java: the unnamed module reads package io.prometheus.client.exporter from both simpleclient.servlet and simpleclient.pushgateway

To reproduce the problem create a module-info.java like this:

module test {
  requires simpleclient.pushgateway;
  requires simpleclient.servlet;
}

agavrilov76 avatar Nov 28 '20 19:11 agavrilov76

I'm not familiar with this, can you explain in exactly what systems this is a problem?

Renaming these would likely cause widespread breakage to existing code, so a split is not likely.

brian-brazil avatar Nov 28 '20 19:11 brian-brazil

Basically you cannot build a modular Java application having a module which imports classes from both simpleclient.pushgateway and simpleclient.servlet modules

Here a repo reproducing the problem: https://github.com/Alexey1Gavrilov/java-module-issues/tree/master/promethues The compilation fails with the following error:

> mvn compile
...
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] the unnamed module reads package io.prometheus.client.exporter from both simpleclient.servlet and simpleclient.pushgateway
[ERROR] module simpleclient.pushgateway reads package io.prometheus.client.exporter from both simpleclient.servlet and simpleclient.pushgateway
[ERROR] module simpleclient.servlet reads package io.prometheus.client.exporter from both simpleclient.pushgateway and simpleclient.servlet
[ERROR] module simpleclient reads package io.prometheus.client.exporter from both simpleclient.servlet and simpleclient.pushgateway
[ERROR] /Users/agavrilov/Work/git/java-module-issues/promethues/src/main/java/module-info.java:[1,1] module javamodule.promethues reads package io.prometheus.client.exporter from both simpleclient.servlet and simpleclient.pushgateway
[INFO] 5 errors

A possible workaround for a modular application is to avoid importing from both in the one application module, ie have a two separate submodules requiring one of simpleclient.pushgateway or simpleclient.servlet.

Generally speaking splitting packages across .jar files should be avoided. This SO question is a good source of info.
I think it makes sense to rename the package in a major version update. Should not cause much troubles to the users.

agavrilov76 avatar Dec 05 '20 19:12 agavrilov76

Ah, so this is yet another backwards incompatible change added in newer Java versions. As with all the other ways that Java is making supporting multiple versions challenging, I'm open to solutions that don't involve breaking existing users.

Should not cause much troubles to the users.

It's still a breaking change for something that affects presumably very few of them, considering this code has been here for 6 years and this is the first time this has come up.

brian-brazil avatar Dec 06 '20 09:12 brian-brazil

I understand that changing the package name will have user impact but I believe making such a change in a major version update (like 1.0) is quite natural.

agavrilov76 avatar Jan 11 '21 09:01 agavrilov76

Even with a major version change, disruption should be minimised to only what is completely essential - and we're pre 1.0 anyway. Only if non-breaking ways to resolve this have been exhausted would a breaking change be considered.

brian-brazil avatar Jan 11 '21 10:01 brian-brazil

Btw, this is also forbidden in OSGi since ever :) So at least if the client is used in an OSGi env this has never worked.

Two possible options to fix this would be

  1. Merge the two sub modules into one essentially eliminating the split package at the price of a higher footprint
  2. Actually keep both Jars, but offer a third variant with both. So if someone needs both the combined Jar can be used, while allowing consumers which only need one or the other to have their minimal footprint...

svogt avatar May 04 '21 05:05 svogt

Hi, I've also found a similar problem when using simpleclient_hotspot and simpleclient_servlet on version 0.12.0 available from the maven repo.

My module info:

module test.prometheus {
    requires simpleclient;
    requires simpleclient.servlet;
    requires simpleclient.hotspot;
}

Pom:

<dependency>
    <groupId>io.prometheus</groupId>
    <artifactId>simpleclient_hotspot</artifactId>
    <version>0.12.0</version>
</dependency>
<dependency>
  <groupId>io.prometheus</groupId>
  <artifactId>simpleclient_servlet</artifactId>
  <version>0.12.0</version>
</dependency>

Error:

module test.prometheus reads package io.prometheus.client from both simpleclient and simpleclient.servlet

Note that this error is NOT present on version 0.11.0 (which I have rolled back to) - so it has been introduced in the newer version.

Thanks, Evynglais

Evynglais avatar Oct 11 '21 22:10 Evynglais

I'm also having trouble using Prometheus in modular Java. There is a simple solution that would not break anyone. Just build a giant jar with everything in it and give it a proper module name like "io.prometheus.all". The split packages will all be unified and modular Java will be happy. My problem has to do with the activation dependency. Activation has been removed since Java 9. This Uber-jar could fix that problem too by simply relocating that package to another name with maven shading. Suggest creating a top-level project that builds last and does nothing but cram all the jars into one big jar with a module-info.java. Prometheus is pretty much a server thing. Probably people using Java 9+ care a lot more about easy integration than they do about jar file size. For myself, the jar size is not an issue.

jonathanl-telenav avatar Oct 26 '21 18:10 jonathanl-telenav

module test.prometheus reads package io.prometheus.client from both simpleclient and simpleclient.servlet

I'm not familiar with the Java module system, but reading this message I'm wondering: Is it really necessary to read io.prometheus.client from simpleclient_servlet? The MetricsServlet lives in io.prometheus.client.exporter and the MetricsFilter lives in io.prometheus.client.filter. There is a helper class in io.prometheus.client, but normally you would not use this directly. Is there a way of using simpleclient_servlet with Java modules without reading io.prometheus.client?

fstab avatar Oct 26 '21 20:10 fstab