最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - JwkSet gives Cannot resolve constructor 'JWKSet(List<RSAKey>)' - Stream.collect(Collectors.

programmeradmin2浏览0评论

In our code, we use JWKset from the nimbus-jose-jwt library in a method that creates a map that we use for stuff. As you can see in the return, we use a stream that calls map on a list of RSAkey, and then we create a List from that, which is used to create a JWKSet. We use collect(Collections.toList()) and that works, but when I tried to change this to use toList() which our SonarQube suggested we should, it does not work.

The compiler error is:

Cannot resolve constructor 'JWKSet(List)

I also get the suggestion to 'cast argument to JWK'. But RSAKey is a class that extends the abstract class JWK if you look at the documentation .java

I do not see how the two method calls, which create the same type of output, do not work the same here.

final List<RSAKey> keys = Collections.singletonList(identityToRSAKey(certificate));
    
// Evidence the methold calls create the same type of output
List<RSAKey> list = keys.stream().map(RSAKey::toPublicJWK).toList();
List<RSAKey> collect = keys.stream().map(RSAKey::toPublicJWK).collect(Collectors.toList());

//This works
JWKSet mySet = new JWKSet(keys
        .stream()
        .map(RSAKey::toPublicJWK)
        .collect(Collectors.toList()));

//This does not work
JWKSet mySet2 = new JWKSet(keys
        .stream()
        .map(RSAKey::toPublicJWK)
        .toList() );

// Where we actually use the code
return new JWKSet(keys
    .stream()
    .map(RSAKey::toPublicJWK)
    .collect(Collectors.toList() ))
    .toPublicJWKSet()
.toJSONObject();

Constructor in JWKSet that we try to invoke

public JWKSet(List<JWK> keys) {
    this(keys, Collections.emptyMap());
}

In our code, we use JWKset from the nimbus-jose-jwt library in a method that creates a map that we use for stuff. As you can see in the return, we use a stream that calls map on a list of RSAkey, and then we create a List from that, which is used to create a JWKSet. We use collect(Collections.toList()) and that works, but when I tried to change this to use toList() which our SonarQube suggested we should, it does not work.

The compiler error is:

Cannot resolve constructor 'JWKSet(List)

I also get the suggestion to 'cast argument to JWK'. But RSAKey is a class that extends the abstract class JWK if you look at the documentation https://github/felx/nimbus-jose-jwt/blob/master/src/main/java/com/nimbusds/jose/jwk/RSAKey.java

I do not see how the two method calls, which create the same type of output, do not work the same here.

final List<RSAKey> keys = Collections.singletonList(identityToRSAKey(certificate));
    
// Evidence the methold calls create the same type of output
List<RSAKey> list = keys.stream().map(RSAKey::toPublicJWK).toList();
List<RSAKey> collect = keys.stream().map(RSAKey::toPublicJWK).collect(Collectors.toList());

//This works
JWKSet mySet = new JWKSet(keys
        .stream()
        .map(RSAKey::toPublicJWK)
        .collect(Collectors.toList()));

//This does not work
JWKSet mySet2 = new JWKSet(keys
        .stream()
        .map(RSAKey::toPublicJWK)
        .toList() );

// Where we actually use the code
return new JWKSet(keys
    .stream()
    .map(RSAKey::toPublicJWK)
    .collect(Collectors.toList() ))
    .toPublicJWKSet()
.toJSONObject();

Constructor in JWKSet that we try to invoke

public JWKSet(List<JWK> keys) {
    this(keys, Collections.emptyMap());
}
Share Improve this question edited Mar 19 at 14:12 dani-vta 7,5357 gold badges49 silver badges65 bronze badges asked Mar 17 at 12:28 Mattias GradinMattias Gradin 354 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 2

The compiler error Cannot resolve constructor 'JWKSet(List<RSAKey>)' is caused by the different signatures of collect() and toList().

<R,A> R collect(Collector<? super T,A,R> collector)
List<T> toList()

The terminal operation collect() accepts a Collector, which is simply a mutable reduction operation, that starts from a type T (in your case, RSAKey), and returns a container R of accumulated transformed results.

accumulates input elements into a mutable result container, optionally transforming the accumulated result into a final representation after all input elements have been processed

When you assign the result of the stream to List<RSAKey> collect, no transformation is performed on the RSAKey elements. The end result R basically corresponds to a list of the supplied elements (List<T>, in your case List<RSAKey>). However, when the same stream appears as an argument for JWKSet's constructor, the compiler tries to find a matching signature, and the only one available is JWKSet(List<JWK>). Therefore, every RSAKey element of the stream is transformed (upcast) to JWK, returning List<JWK>.

On the other hand, toList() simply returns a List of the elements streamed. Therefore, the list you're obtaining is List<RSAKey>, and not List<JWK>. This is because toPublicJWK() return type is RSAKey (not JWK), and since List<RSAKey> is not a subtype of List<JWK> (even though RSAKey is a subtype of JWK), you're receiving a compiler error when providing the stream to JWKSet's constructor. For more details about subtyping with generics, I recommend this article by Angelika Langer.

In your case, I would just stick with collect(), but if you really want (or need) to use toList(), you can simply cast each element of the stream to JWK.

JWKSet mySet = new JWKSet(keys
    .stream()
    .map(RSAKey::toPublicJWK)   // I've left this invocation, because I don't know if it's really necessary to what you're doing
    .map(JWK.class::cast)
    .toList());

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论