Getting temporary AWS credentials using Java SDK2 - aws-sdk

The AWS documentation seems still to refer to AWS Java SDK1 with regard to STS / assume role authentication.
If I have:
AWS Java SDK2 (v.2.5.49)
role-arn
external-id
..is there a way to create with those:
accessKey
secretKey
sessionToken

One should use StsAssumeRoleCredentialsProvider that does the refreshing of temporary tokens for you.
def apply(roleArn: String, externalId: String, expires: FiniteDuration, sessionName: String): StsAssumeRoleCredentialsProvider = {
val durationSecs: Int = expires.toSeconds.toInt
val stsClient: StsClient = StsClient.builder.build()
val req: AssumeRoleRequest = AssumeRoleRequest.builder
.roleArn(roleArn)
.externalId(externalId)
.durationSeconds(durationSecs)
.roleSessionName(sessionName)
.build()
StsAssumeRoleCredentialsProvider.builder
.stsClient(stsClient)
.refreshRequest(req)
.build()
}
Note that when calling .resolveCredentials() the AWS SDK 2 returns an AwsCredentials that does not provide the session token. The returned value can just be casted to AwsSessionCredentials which provides all the three.
val prov: AwsCredentialsProvider = ???
val creds: AwsSessionCredentials = prov.resolveCredentials().asInstanceOf[AwsSessionCredentials]

Related

MongoDB with Scala language

i am new to MongoDB and Scala language
i am using scala language to connect mongodb locally
i am using below dependency
//
https://mvnrepository.com/artifact/org.mongodb.scala/mongo-scala-driver
libraryDependencies += "org.mongodb.scala" %% "mongo-scala-driver" %
"4.2.3"
what I tried
object Demo extends App {
val mongoClient: MongoClient = MongoClient("mongodb://127.0.0.1:27017/")
val database: MongoDatabase = mongoClient.getDatabase("DemoDB")
println(database)
val collection: MongoCollection[Document] =database.getCollection("demodata");
val observable = collection.find();
}
the above code returning the data in below format
FindObservable(com.mongodb.reactivestreams.client.internal.FindPublisherImpl#6253c26)
I also tried with
observable.subscribe ( new Observer[Document] {
override def onNext(result: Document): Unit = println(result.toJson())
override def onError(e: Throwable): Unit = println("Failed" + e.getMessage)
override def onComplete(): Unit = println("Completed")
})
i also tried printResult() and printHeadResult() method also but none of the way is working
please help
thanks in advance
Mongo Scala driver works in a non-blocking manner by returning Observables which need to be Subsribed on to consume the published data.
When you are subscribing to the observable like following,
object Demo extends App {
val mongoClient: MongoClient = MongoClient("mongodb://127.0.0.1:27017/")
val database: MongoDatabase = mongoClient.getDatabase("DemoDB")
println(database)
val collection: MongoCollection[Document] = database.getCollection("demodata")
val observable = collection.find()
observable.subscribe ( new Observer[Document] {
override def onNext(result: Document): Unit = println(result.toJson())
override def onError(e: Throwable): Unit = println("Failed" + e.getMessage)
override def onComplete(): Unit = println("Completed")
})
}
Your code does not wait for observable to actually publish anything, it just finishes right after subscribing. Hence you don't get anything.
You can either add a Something like a Thread.sleep(5000) at the end to block and give the obeservable some time to (hopefully finish and) publish the data.
Or, you can add val resultSeq = observable.collect to block and collect all of published data in a single Sequence.
I found this link
it works for printResult() and printHeadResult() method
Printing query results from Mongodb in Scala using mongo-scala-driver

IllegalArgumentException Moshi thinks I'm using ArrayList(java) when I'm using List(Kotlin)

I'm new to Kotlin and I still don't fully get the syntax for some stuff, expecially inside a lambda. I'm trying to build a simple REST api for uni project, currently messing with ktor, exposed and moshi.
However I'm getting the following error:
java.lang.IllegalArgumentException: No JsonAdapter for class java.util.ArrayList, you should probably use List instead of ArrayList (Moshi only supports the collection interfaces by default) or else register a custom JsonAdapter.
I'm not sure how to solve that, because I do use a List, however my guess is that Kotlin lists are compiled down to java's ArrayList.
From from what I've googled, this should work and be enough, but I guess it's not the case:
val listType = Types.newParameterizedType(List::class.java, Author::class.java)
val moshi = Moshi.Builder().build()
val adapter: JsonAdapter<List<Author>> = moshi.adapter(listType)
Here is the full code (except the database settings/connection):
fun Application.module(testing: Boolean = false) {
install(CallLogging)
val listType = Types.newParameterizedType(List::class.java, Author::class.java)
val moshi = Moshi.Builder().build()
val adapter: JsonAdapter<List<Author>> = moshi.adapter(listType)
install(ContentNegotiation) {
/*gson {
setPrettyPrinting()
}*/
moshi(moshi)
}
routing {
get("/authors") {
val authorList = mutableListOf<Author>()
transaction(db) {
addLogger(StdOutSqlLogger)
SchemaUtils.create(Authors)
val query = "SELECT a.id, a.name, a.age, c.name as `country`\n" +
" FROM authors a, countries c\n" +
" WHERE a.country_id = c.id ORDER BY a.id";
TransactionManager.current().exec(query) { rs ->
while (rs.next()) {
authorList += Author(
id = rs.getInt("id"), name = rs.getString("name"),
age = rs.getInt("age"), country = rs.getString("country")
)
}
}
}
val result: List<Author> = authorList.toList()
adapter.toJson(result)
print("\n\n${result}\n\n")
call.respond(HttpStatusCode.OK, result)
}
}
}
My data class looks like this:
#JsonClass(generateAdapter = true)
data class Author(
val id: Int,
val name: String,
val age: Int,
val country: String
)
I do have the required dependencies to install moshi for ktor from here
If I try on single object it will probably work, but I need the whole list from the query output.
I also did try making a custom adapter as the error suggests, but then it couldn't find my #ToJson anotated method.
If I use GSON it just works magically, however I want to figure out how to do it with moshi. Any ideas?
I found out my mistake, it's probably really stupid, but due to the magic of gson I couldn't figure out how to use moshi properly. I really didn't expect that I have to use the adapter.
call.respond(HttpStatusCode.OK, result)
should be:
call.respond(HttpStatusCode.OK, adapter.toJson(result))

ObjectIds don't get retrieved from collection (Scala + MongoDB)

There is a MongoDB instance on my computer with a database. A couple of documents are present in one of the collections, I inserted them manually. There is a Scala application to manipulate the database. There is a case class called Location.
case class Location(_id: Option[ObjectId] = None, name: String) {
var visible: Boolean = false
}
This is the MongoDB configuration in the application.
private val customCodecs = fromProviders(
classOf[Location]
)
private val javaCodecs =
fromCodecs(new LocalDateTimeDateCodec(), new LocalDateDateCodec())
private val codecRegistry =
fromRegistries(customCodecs, javaCodecs,
DEFAULT_CODEC_REGISTRY)
val dbConnection = MongoClient(dbURI)
val database: MongoDatabase = dbConnection.getDatabase(dbName).withCodecRegistry(codecRegistry)
There are more classOf definitions in the customCodecs, just removed them. The dbURI string is retrieved from a config file.
There is a controller endpoint, which returns all Locations from the database. The result is this:
[{"_id":{},"name":"Hungary","visible":false},{"_id":{},"name":"Germany","visible":false},{"_id":{},"name":"France","visible":false},{"_id":{},"name":"Switzerland","visible":false},{"_id":{},"name":"Poland","visible":false}]
The documents in the database have ObjectId, since I entered them manually, and some documents should have the visibility property true. I suspect there is something wrong with the JSON serialization, but cannot figure it out what.
This is the code which queries the collection.
val query = collection.find().toFuture()
Await.result(query, 10.seconds).toList
The service method calls this code and passes the result to the controller.
import org.json4s.native.Serialization.write
val languages = enrollmentService.getAllLanguages
logger.info("GET all languages")
Ok(Json.parse(write[List[Language]](languages)))
I use json4s for JSON serialization / deserialization.
What could be the issue here?
Perhaps you need to include org.json4s.mongo.ObjectIdSerializer?

Kotlin/Android – KotlinReflectionInternalError in Data Class with a lambda

kotlin.reflect.jvm.internal.KotlinReflectionInternalError:
Introspecting local functions, lambdas, anonymous functions and local
variables is not yet fully supported in Kotlin reflection
This exception comes from toString() of a data class.
The data class contains a lambda.
I can't reproduce it in my environment.
Do I need to override toString() to exclude the lambda? Or lambdas are not allowed in data classes at all?
data class PersistJob(
private val id: Int,
private val delay: Long = 10_000L,
private val maxDelay: Long = 60_000L,
private val iteration: Int = 0,
private val block: suspend (Int) -> Boolean) {
fun getDelay() = minOf(delay, maxDelay)
fun withDelayIncreased() = copy(
delay = minOf(delay * 2, maxDelay),
iteration = iteration + 1)
suspend fun execute() = block(iteration)
}
Line producing the error:
val job: PersistJob = ...
log.debug("start job id($id): $job")`// job.toString()
Stack trace:
at kotlin.reflect.jvm.internal.EmptyContainerForLocal.fail(SourceFile:41)
at kotlin.reflect.jvm.internal.EmptyContainerForLocal.getFunctions(SourceFile:37)
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.findFunctionDescriptor(SourceFile:145)
at kotlin.reflect.jvm.internal.KFunctionImpl$descriptor$2.invoke(SourceFile:54)
at kotlin.reflect.jvm.internal.KFunctionImpl$descriptor$2.invoke(SourceFile:34)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(SourceFile:93)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(SourceFile:32)
at kotlin.reflect.jvm.internal.KFunctionImpl.getDescriptor(SourceFile)
at kotlin.reflect.jvm.internal.ReflectionFactoryImpl.renderLambdaToString(SourceFile:59)
at kotlin.jvm.internal.Reflection.renderLambdaToString(SourceFile:80)
at kotlin.jvm.internal.Lambda.toString(SourceFile:22)
at java.lang.String.valueOf(String.java:2683)
at java.lang.StringBuilder.append(StringBuilder.java:129)
It looks like a bug in Kotlin lambdas.
This code is enough to reproduce the exception:
({i: Int -> true}).toString()
I advice you post an issue on youtrack.jetbrains.com/issues/KT and see what the team says about it.

How can I programmatically create a validation contract at compile-time?

I apologize in advance if this is an XY problem.
tl;dr:
I'd like to have a compile-time map of type [Request.type, Response.type] so I can effectively say if I send message Request, a CLI should, at compile-time, know how to deserialize its expected Response, irrespective of the fact that it won't know what type of request is sent until runtime.
too long; still read:
I have a CLI which communicates with an HTTP server and depending on the type of message sent to the HTTP server, I'd like to validate the JSON response against a case case.
For instance, if I send the HTTP server an AddFoo message, I might want to validate that the JSON response can be deserialized into an AddedFoo, etc.
My current solution is quite hacky. Using play-json, I'm attempting to parse the JSON response using a mapping from config.mode (i.e., command issued to the CLI) to the expected responses' implicit Reads.
My code looks something like this:
val modeToResponseReads: Map[String, Reads[_]] = Map(
Modes.ADD_FOO -> AddedFoo.addedFooReads,
Modes.ADD_BOO -> AddedBoo.addedBooReads,
Modes.GET_WOO -> GetWooResponse.getWooReads,
)
parser.parse(args, MyConfig()) match {
case Some(config) => try {
val exec = new MyHttpExecutor(remoteUri, config)
val res = Await.result(exec.getResponse, 100.seconds)
// passing `Reads` to `as` because JsValue#as[T] cannot be
// applied at runtime -- only compile-time.
val _ = Json.parse(res.json.toString)
.as(modeToResponseReads(config.mode))
exec.actorSystem.terminate()
exec.wsClient.close()
} catch {
case t: Throwable => logger.error(t.getMessage)
}
case None => {
logger.error("Bad arguments.")
sys.exit(1)
}
}
While this works, it's an incredible kludge that becomes increasingly unmaintainable with an increasing number of messages. Further, I've found that this pattern will need to be replicated anywhere some type of validate or conversion will need to happen (e.g., Future[Any] being converted to Future[AddedFoo]).
Surely my approach isn't the right way... how is this traditionally done? If it is the right way (please no), are there optimizations that can be made?
I managed to accomplish this by encoding the contract directly into the child Request classes. Namely, the child Request classes would hold a ResponseType type with the base class enforcing the covariant type.
So I can do something like this:
abstract class Response
abstract class Request[+A <: Response]
case class Foo(id: String)
object Foo {
implicit val fooReads = Json.reads[Foo]
implicit val fooFormat = Json.format[Foo]
}
case class FooResponse(foo: Foo) extends Response {
def greet = println("woo hoo!")
}
object FooResponse {
implicit val fooRespReads = Json.reads[FooResponse]
implicit val fooRespFormat = Json.format[FooResponse]
}
case class FooRequest() extends Request[FooResponse] {
type ResponseType = FooResponse
}
object Main extends App {
val req: FooRequest = new FooRequest()
val foo = Foo("12345")
val resp = new FooResponse(foo)
val respJsonString = Json.toJson(resp).toString
println(Json.parse(respJsonString).as[req.ResponseType])
}