无法使用运行时依赖项进行编译,但可以进行编译
Can't compile with runtime dependency, but can with compile
我有一个多模块项目,我试图在一个模块中添加 Okta-SDK 依赖项,如 README 中所述:
<properties>
<okta.version>1.5.4</okta.version>
</properties>
<dependency>
<groupId>com.okta.sdk</groupId>
<artifactId>okta-sdk-api</artifactId>
<version>${okta.version}</version>
</dependency>
<dependency>
<groupId>com.okta.sdk</groupId>
<artifactId>okta-sdk-impl</artifactId>
<version>${okta.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.okta.sdk</groupId>
<artifactId>okta-sdk-httpclient</artifactId>
<version>${okta.version}</version>
<scope>runtime</scope>
</dependency>
但它不能用 mvn clean package -pl my-module
编译,它失败并出现错误:
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /some/path/OktaUsers.java:[9,38] error: package com.okta.sdk.impl.resource.user does not exist
[ERROR] /some/path/OktaUsers.java:[96,14] error: cannot find symbol
[ERROR] class OktaUsers
/some/path/OktaUsers.java:[97,13] error: cannot find symbol
[INFO] 3 errors
此 class OktaUsers
引用了 Okta-SDK classes。但是如果我将 runtime
范围更改为 compile
for okta-sdk-impl
artifact:
<dependency>
<groupId>com.okta.sdk</groupId>
<artifactId>okta-sdk-impl</artifactId>
<version>${okta.version}</version>
<scope>compile</scope>
</dependency>
然后编译成功:mvn clean package -pl my-module
:
[INFO] BUILD SUCCESS
但由于依赖性问题,最终应用程序未按预期运行:
java.lang.NoClassDefFoundError: Could not initialize class com.okta.sdk.impl.ds.DefaultDataStore
at com.okta.sdk.impl.client.AbstractClient.createDataStore(AbstractClient.java:73)
at com.okta.sdk.impl.client.AbstractClient.<init>(AbstractClient.java:68)
at com.okta.sdk.impl.client.DefaultClient.<init>(DefaultClient.java:99)
at com.okta.sdk.impl.client.DefaultClientBuilder.build(DefaultClientBuilder.java:305)
我认为所有具有 runtime
范围的依赖项在编译时都应该可用。但似乎并没有。我该如何解决这个问题?我需要对编译和运行时都具有这种依赖性。
更新:
我不能分享这个项目的资源,因为它是私人的,但这里有一些来自 OktaUser
class:
的行
import com.okta.sdk.client.Client;
import com.okta.sdk.impl.resource.user.DefaultRole;
import com.okta.sdk.resource.group.Group;
import com.okta.sdk.resource.group.GroupBuilder;
import com.okta.sdk.resource.user.Role;
import com.okta.sdk.resource.user.RoleStatus;
import com.okta.sdk.resource.user.UserBuilder;
import com.okta.sdk.resource.user.UserProfile;
public final class OktaUsers implements Users {
private final Client okta;
// line 95:
private Role adminRole() {
final DefaultRole role =
(DefaultRole) this.okta.instantiate(Role.class);
role.setProperty("type", "USER_ADMIN");
role.setProperty("status", RoleStatus.ACTIVE);
return role;
}
}
我在这里使用来自 impl
依赖项的 classes,因为 api
dep 没有管理 Okta 角色的方法。
当 运行 mvn verify -pl my-module
时,此代码在集成测试中运行良好
Maven 版本:
Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-04T22:00:29+03:00)
Maven home: /usr/share/maven-bin-3.6
Java version: 1.8.0_212, vendor: IcedTea, runtime: /opt/icedtea-bin-3.12.0/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.19.44-gentoo", arch: "amd64", family: "unix"
你能post/some/path/OktaUsers.java
的内容吗?看起来这个 class 依赖于 Okta IMPL 包中的 classes。如果我正确理解 Okta API,您自己的代码应该仅依赖 on/use 来自 API 模块的 classes,而不是 impl 模块。如果你从 impl 模块中删除对 class 的依赖,你应该没问题。
编辑 1:
我看到两种方法。您可以删除对 DefaultRole 的依赖。
// line 95:
private Role adminRole() {
Role role = this.okta.instantiate(Role.class);
role.setType("USER_ADMIN");
// use reflection to check if there is a setProperty() method
// and call it if it's really necessary
// role.setProperty("status", RoleStatus.ACTIVE);
return role;
}
第二种方法是找出为什么jvm不能实例化com.okta.sdk.impl.ds.DefaultDataStore
。这可能是一项非常乏味的任务,因为 jvm 不会为您提供正确的错误消息。我猜 class 路径中缺少依赖项。您需要查看 class 的来源并确保所有引用的 classes(以及这些 classes 引用的所有 classes 等等)都已打开class路径。这样做时,您需要确保使用这些 classes 的正确版本,即与构建引用 classes 所针对的版本相同。对于初学者,请确保 org.slf4j.Logger
和记录器的单个实现在 class 路径上并且配置正确。
正确的解决方法是更改 api。在描述类似问题的 okta 问题列表中似乎有一个已解决的 issue。也许这可以帮助你?如果没有,我建议联系 okta 开发人员并询问他们如何解决您的问题。
范围为 runtime
的依赖项仅在运行时可用,在编译时不可用。这适用于不应直接调用的实现 jar 和框架 jar。
范围为 compile
的依赖项在编译时和运行时均可用。
我有一个多模块项目,我试图在一个模块中添加 Okta-SDK 依赖项,如 README 中所述:
<properties>
<okta.version>1.5.4</okta.version>
</properties>
<dependency>
<groupId>com.okta.sdk</groupId>
<artifactId>okta-sdk-api</artifactId>
<version>${okta.version}</version>
</dependency>
<dependency>
<groupId>com.okta.sdk</groupId>
<artifactId>okta-sdk-impl</artifactId>
<version>${okta.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.okta.sdk</groupId>
<artifactId>okta-sdk-httpclient</artifactId>
<version>${okta.version}</version>
<scope>runtime</scope>
</dependency>
但它不能用 mvn clean package -pl my-module
编译,它失败并出现错误:
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] /some/path/OktaUsers.java:[9,38] error: package com.okta.sdk.impl.resource.user does not exist
[ERROR] /some/path/OktaUsers.java:[96,14] error: cannot find symbol
[ERROR] class OktaUsers
/some/path/OktaUsers.java:[97,13] error: cannot find symbol
[INFO] 3 errors
此 class OktaUsers
引用了 Okta-SDK classes。但是如果我将 runtime
范围更改为 compile
for okta-sdk-impl
artifact:
<dependency>
<groupId>com.okta.sdk</groupId>
<artifactId>okta-sdk-impl</artifactId>
<version>${okta.version}</version>
<scope>compile</scope>
</dependency>
然后编译成功:mvn clean package -pl my-module
:
[INFO] BUILD SUCCESS
但由于依赖性问题,最终应用程序未按预期运行:
java.lang.NoClassDefFoundError: Could not initialize class com.okta.sdk.impl.ds.DefaultDataStore
at com.okta.sdk.impl.client.AbstractClient.createDataStore(AbstractClient.java:73)
at com.okta.sdk.impl.client.AbstractClient.<init>(AbstractClient.java:68)
at com.okta.sdk.impl.client.DefaultClient.<init>(DefaultClient.java:99)
at com.okta.sdk.impl.client.DefaultClientBuilder.build(DefaultClientBuilder.java:305)
我认为所有具有 runtime
范围的依赖项在编译时都应该可用。但似乎并没有。我该如何解决这个问题?我需要对编译和运行时都具有这种依赖性。
更新:
我不能分享这个项目的资源,因为它是私人的,但这里有一些来自 OktaUser
class:
import com.okta.sdk.client.Client;
import com.okta.sdk.impl.resource.user.DefaultRole;
import com.okta.sdk.resource.group.Group;
import com.okta.sdk.resource.group.GroupBuilder;
import com.okta.sdk.resource.user.Role;
import com.okta.sdk.resource.user.RoleStatus;
import com.okta.sdk.resource.user.UserBuilder;
import com.okta.sdk.resource.user.UserProfile;
public final class OktaUsers implements Users {
private final Client okta;
// line 95:
private Role adminRole() {
final DefaultRole role =
(DefaultRole) this.okta.instantiate(Role.class);
role.setProperty("type", "USER_ADMIN");
role.setProperty("status", RoleStatus.ACTIVE);
return role;
}
}
我在这里使用来自 impl
依赖项的 classes,因为 api
dep 没有管理 Okta 角色的方法。
当 运行 mvn verify -pl my-module
Maven 版本:
Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-04T22:00:29+03:00)
Maven home: /usr/share/maven-bin-3.6
Java version: 1.8.0_212, vendor: IcedTea, runtime: /opt/icedtea-bin-3.12.0/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "4.19.44-gentoo", arch: "amd64", family: "unix"
你能post/some/path/OktaUsers.java
的内容吗?看起来这个 class 依赖于 Okta IMPL 包中的 classes。如果我正确理解 Okta API,您自己的代码应该仅依赖 on/use 来自 API 模块的 classes,而不是 impl 模块。如果你从 impl 模块中删除对 class 的依赖,你应该没问题。
编辑 1: 我看到两种方法。您可以删除对 DefaultRole 的依赖。
// line 95:
private Role adminRole() {
Role role = this.okta.instantiate(Role.class);
role.setType("USER_ADMIN");
// use reflection to check if there is a setProperty() method
// and call it if it's really necessary
// role.setProperty("status", RoleStatus.ACTIVE);
return role;
}
第二种方法是找出为什么jvm不能实例化com.okta.sdk.impl.ds.DefaultDataStore
。这可能是一项非常乏味的任务,因为 jvm 不会为您提供正确的错误消息。我猜 class 路径中缺少依赖项。您需要查看 class 的来源并确保所有引用的 classes(以及这些 classes 引用的所有 classes 等等)都已打开class路径。这样做时,您需要确保使用这些 classes 的正确版本,即与构建引用 classes 所针对的版本相同。对于初学者,请确保 org.slf4j.Logger
和记录器的单个实现在 class 路径上并且配置正确。
正确的解决方法是更改 api。在描述类似问题的 okta 问题列表中似乎有一个已解决的 issue。也许这可以帮助你?如果没有,我建议联系 okta 开发人员并询问他们如何解决您的问题。
范围为 runtime
的依赖项仅在运行时可用,在编译时不可用。这适用于不应直接调用的实现 jar 和框架 jar。
范围为 compile
的依赖项在编译时和运行时均可用。