API version may be set only once exception

I’m trying to run the a sample code in Scala. I could run it one time and after that, I get the following error:

import com.apple.foundationdb.Database;
import com.apple.foundationdb.FDB;
import com.apple.foundationdb.tuple.Tuple;

object FoundationDBTest extends App {
  println(s"is API version selected? ${FDB.isAPIVersionSelected()}")
  val fdb =
    if (!FDB.isAPIVersionSelected()) FDB.selectAPIVersion(620)
    else FDB.instance()

  def main(args: Array[String]) {

    try {
      val db = fdb.open()
      // Run an operation on the database
      db.run(tr => {
        tr.set(Tuple.from("hello").pack(), Tuple.from("world").pack())
        null
      })

      // Get the value of 'hello' from the database
      val hello = db.run(tr => {
        val result = tr.get(Tuple.from("hello").pack()).join()
        Tuple.fromBytes(result).getString(0)
      })

      println("Hello " + hello)
    } catch {
      case _ => println("error")

    }
  }
}

and exception:

[info] running FoundationDBTest
is API version selected? false
[error] (run-main-f) com.apple.foundationdb.FDBException: API version may be set only once
[error] com.apple.foundationdb.FDBException: API version may be set only once
[error] 	at com.apple.foundationdb.FDB.Select_API_version(Native Method)
[error] 	at com.apple.foundationdb.FDB.selectAPIVersion(FDB.java:199)
[error] 	at com.apple.foundationdb.FDB.selectAPIVersion(FDB.java:180)
[error] 	at FoundationDBTest$.delayedEndpoint$FoundationDBTest$1(FoundationDBTest.scala:8)
[error] 	at FoundationDBTest$delayedInit$body.apply(FoundationDBTest.scala:5)
[error] 	at scala.Function0.apply$mcV$sp(Function0.scala:39)
[error] 	at scala.Function0.apply$mcV$sp$(Function0.scala:39)
[error] 	at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
[error] 	at scala.App.$anonfun$main$1$adapted(App.scala:80)
[error] 	at scala.collection.immutable.List.foreach(List.scala:392)
[error] 	at scala.App.main(App.scala:80)
[error] 	at scala.App.main$(App.scala:78)
[error] 	at FoundationDBTest$.main(FoundationDBTest.scala:5)
[error] 	at FoundationDBTest.main(FoundationDBTest.scala)
[error] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[error] 	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[error] 	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[error] 	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
[error] stack trace is suppressed; run last Compile / bgRun for the full output
[error] Nonzero exit code: 1
[error] (Compile / run) Nonzero exit code: 1
[error] Total time: 2 s, completed Jul 1, 2020, 10:16:03 PM

You should reuse the db object across multiple transactions.

I am using almost the exact code from the documentation just converted to Scala. Here is the code I’m using: https://apple.github.io/foundationdb/javadoc/index.html

Which object should get reused? FDB? Exactly where?

I believe you should reuse all objects upto this point. Use the existing val db object for running transactions.

The exception message is about FDB selectAPIVersion. The second time running the code on JVM, I get the error message that API version should not get set more than one time.

I figured out how to solve it. Because FoundationDB has native binding and I was running the code in SBT (build tool for Scala) I had to make sure fork is enabled in the build file.

I solved this issue in the nodejs bindings by making it so subsequent calls to setAPIVersion which use the same version number do nothing.

The scala bindings should probably do the same thing.