简体   繁体   中英

Can't compile with runtime dependency, but can with compile

I have a multi-module project, in one module I'm trying to add Okta-SDK dependency as described in the 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>

but it doesn't compile with mvn clean package -pl my-module , it fails with error:

[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 

This class OktaUsers has references to Okta-SDK classes. But if I change runtime scope to 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>

Then compiling finished fine: mvn clean package -pl my-module :

[INFO] BUILD SUCCESS

But final app is not working as expected because of dependency issues:

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)

I thought all dependencies with runtime scope should be available when compiling. But it seems that doesn't. How can I fix this issue? I need to have this dependency for compiling and for runtime both.


UPDATE:

I can't share sources from this project, since it's private, but here some lines from 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;
    }
}

I'm using classes from impl dependency here, since api dep doesn't have methods to manage Okta roles.


This code works fine with integration tests when running mvn verify -pl my-module


Maven version:

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"

Can you post the content of /some/path/OktaUsers.java ? It looks like this class is depending on classes from the Okta IMPL package. If I understand the Okta API correctly your own code is supposed to depend on/use only classes from the API module, NOT the impl modules. If you remove the dependency on the class from the impl module you should be fine.

Edit 1: I see two approaches. You could remove the dependency to 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;
}

The second approach is to find out, why the jvm cannot instantiate com.okta.sdk.impl.ds.DefaultDataStore . This can be a very tedious task as the jvm doesn't dive you a proper error message. I'd guess that a dependency is missing from the classpath. You need to look at the source of the class and make sure that all referenced classes (and all classes referenced by these classes and so on) are on the classpath. Doing so, you need to make sure that the correct versions of these classes are used, ie the same versions that the referencing classes were build against. For starters, make sure that org.slf4j.Logger and a single implementation of the logger is on the classpath and that it's properly configured.

The proper fix would be to change the api. There seems to be a solved issue in the okta issue list describing a similar problem. Maybe this can help you? If not, I suggest contacting the okta developer and asking them how to fix your problem.

A dependency with scope runtime is available at runtime only, not at compile time. This is meant for implementation jars and framework jars that should not be called directly.

A dependency with scope compile is available both at compile time and at runtime.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM