首页 > 解决方案 > 无法使用运行时依赖进行编译,但可以使用 compile

问题描述

我有一个多模块项目,在一个模块中我试图添加Okta-SDK依赖项,如自述文件中所述:

<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 

此类OktaUsers引用了 Okta-SDK 类。但是,如果我将runtime范围更改compileokta-sdk-impl工件:

<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类的行:

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这里使用依赖项中的类,因为apidep 没有管理 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"

标签: javamavenokta

解决方案


可以发一下内容/some/path/OktaUsers.java吗?看起来这个类依赖于 Okta IMPL 包中的类。如果我正确理解 Okta API,您自己的代码应该只依赖/使用 API 模块中的类,而不是 impl 模块。如果你从 impl 模块中删除对类的依赖,你应该没问题。

编辑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 不会向您发送正确的错误消息。我猜想类路径中缺少依赖项。您需要查看类的来源并确保所有引用的类(以及这些类引用的所有类等)都在类路径中。这样做,您需要确保使用这些类的正确版本,即构建引用类的相同版本。对于初学者,请确保org.slf4j.Logger记录器的单个实现位于类路径上并且已正确配置。

正确的解决方法是更改​​ api。在描述类似问题的 okta 问题列表中似乎有一个已解决的问题。也许这可以帮助你?如果没有,我建议联系 okta 开发人员并询问他们如何解决您的问题。


推荐阅读