user15826601
user15826601

Reputation: 69

How to call a method defined in Java from Scala program?

I'm new to Scala, in below code I want to return a tokenRequest, but I got error "Cannot resolve overloaded constructor TokenRequest", what is the correct way to do that?

private def makeTokenRequest(format: String, provider: String, scopes: String, audience: String, clientAuthentication: ClientAuthentication): TokenRequest = {
        val tokenRequest: TokenRequest = null
        val uri = new URI(baseUrl + "?provider=" + provider + "&format=" + format)
        val params = new ConcurrentHashMap[String, List[String]]
        if (audience != null) {
            params.put("audience", List(audience))
        }
        if (scopes != null) {
            tokenRequest = new TokenRequest(uri, clientAuthentication, new ClientCredentialsGrant, Scope.parse(""), null, params)
//Cannot resolve overloaded constructor `TokenRequest`
        } else {
            tokenRequest = new TokenRequest(uri, clientAuthentication, new ClientCredentialsGrant, null, null, params)
//Cannot resolve overloaded constructor `TokenRequest`
        }
        tokenRequest
    }

This is the correct doc https://www.javadoc.io/doc/com.nimbusds/oauth2-oidc-sdk/6.23/com/nimbusds/oauth2/sdk/TokenRequest.html#%3Cinit%3E(java.net.URI,com.nimbusds.oauth2.sdk.auth.ClientAuthentication,com.nimbusds.oauth2.sdk.AuthorizationGrant,com.nimbusds.oauth2.sdk.Scope,java.util.List,java.util.Map)

Upvotes: 1

Views: 191

Answers (1)

Tim Moore
Tim Moore

Reputation: 9482

When I added this code and dependency to my own IDE (IntelliJ IDEA), I also see the error "Cannot resolve overloaded constructor TokenRequest".

Running sbt compile reveals different errors:

  1. First: "reassignment to val" (as Levi Ramsey pointed out in the comments on the question):

    [error] /Users/tmoore/Projects/scala-scratch/src/main/scala/Test.scala:21:20: reassignment to val
    [error]       tokenRequest = new TokenRequest(uri, clientAuthentication, new ClientCredentialsGrant, Scope.parse(""), null, params)
    [error]                    ^
    [error] /Users/tmoore/Projects/scala-scratch/src/main/scala/Test.scala:24:20: reassignment to val
    [error]       tokenRequest = new TokenRequest(uri, clientAuthentication, new ClientCredentialsGrant, null, null, params)
    [error]                    ^
    [error] two errors found
    [error] (Compile / compileIncremental) Compilation failed
    

    This can fixed by changing tokenRequest to a var, or more idiomatically, removing the declaration for tokenRequest and allowing it to be returned directly from the if/else expressions.

  2. Type mismatch for params:

    [error] /Users/tmoore/Projects/scala-scratch/src/main/scala/Test.scala:20:102: type mismatch;
    [error]  found   : java.util.concurrent.ConcurrentHashMap[String,List[String]]
    [error]  required: java.util.Map[String,java.util.List[String]]
    [error]       new TokenRequest(uri, clientAuthentication, new ClientCredentialsGrant, Scope.parse(""), null, params)
    [error]                                                                                                      ^
    [error] /Users/tmoore/Projects/scala-scratch/src/main/scala/Test.scala:23:91: type mismatch;
    [error]  found   : java.util.concurrent.ConcurrentHashMap[String,List[String]]
    [error]  required: java.util.Map[String,java.util.List[String]]
    [error]       new TokenRequest(uri, clientAuthentication, new ClientCredentialsGrant, null, null, params)
    [error]                                                                                           ^
    [error] two errors found
    

    This happens because params.put("audience", List(audience)) uses scala.collection.immutable.List, which does not implement java.util.List. You'll need to change the type of params to new ConcurrentHashMap[String, java.util.List[String]].

    You can convert List(audience) to a Java list by importing the conversion with import scala.jdk.CollectionConverters._ and then calling List(audience).asJava. See the Scala documentation on Conversions Between Java and Scala Collections for details.

    Alternatively, you could build a Java list in the first place by importing java.util.Collections and using Collections.singletonList. For this example, I'm using this approach.

Here's the final code, which compiles in sbt and shows no errors in the editor:

import com.nimbusds.oauth2.sdk.{ClientCredentialsGrant, Scope, TokenRequest}
import com.nimbusds.oauth2.sdk.auth.ClientAuthentication

import java.net.URI
import java.util.Collections
import java.util.concurrent.ConcurrentHashMap

class Test {
  val baseUrl: String = ???

  private def makeTokenRequest(format: String, provider: String, scopes: String, audience: String, clientAuthentication: ClientAuthentication): TokenRequest = {
    val uri = new URI(baseUrl + "?provider=" + provider + "&format=" + format)
    val params = new ConcurrentHashMap[String, java.util.List[String]]
    if (audience != null) {
      params.put("audience", Collections.singletonList(audience))
    }
    if (scopes != null) {
      new TokenRequest(uri, clientAuthentication, new ClientCredentialsGrant, Scope.parse(""), null, params)
    } else {
      new TokenRequest(uri, clientAuthentication, new ClientCredentialsGrant, null, null, params)
    }
  }
}

Upvotes: 2

Related Questions