JWTSigner sign is not allowing Map[String, AnyRef] - scala

I am facing an issue when I am trying to implement "sign" method to generate JWT token using JWTSigner in scala. I am using com.oauth0.java-jwt-2.1.0.
"com.auth0" % "java-jwt" % "2.1.0"
Code:
class JWTUtil{
def sign: String = {
val signer = new JWTSigner("secret")
val map = Map("iss" -> Some, "aud" -> Some)
signer.sign(map) //"Cannot resolve the overloaded method sign"
}
}
I am getting error in calling "sign". It says "Cannot resolve the overloaded method sign". It accepts Map<String, Object>. Not sure if it will be applicable in scala too. I am pretty new to Scala. Thanks!

You are getting this error because sign method of JWTSigner class expecting Map from java util package and in here you are passing scala Map collection to the sign method. Also, you need to explicitly convert the Map to the Map[String, Object].
Following code snippet might help to solve your problem:
import java.util
import scala.jdk.CollectionConverters.MapHasAsJava
object JwtStackOverFlow extends App {
def sign: String = {
val signer = new JWTSigner("secret")
val d: util.Map[String, Object] = Map("one" -> 1, "two" -> "234").asInstanceOf[Map[String, Object]].asJava
signer.sign(d)
}
println(sign)
}

Related

How to get a classOf[Array[T]] in Scala

I have a method (scala 2.12) that does look like the following.
The goal is to pass to the method readValue from objectMapper (jackson) a string and a class that the string needs to be casted, which in this case is an Array[T].
T can be two different case classes and therefore that is the reason of why I try to parametrize it.
private def fromSeqToCastedSeq[T](files: Seq[File]): Seq[T] = {
files flatMap (file => {
val maps = objectMapper.readValue(file, classOf[Map[String, Any]])
val combinedString = objectMapper.writeValueAsString(maps.get("sqlDefinitions"))
val o = objectMapper.readValue(combinedString, classOf[Array[T]])
o})
Currently this does not compile with a scala.MatchError because it is not able to cast it at runtime.
Could someone help me understand if what I'm trying to achieve is possible?
Thanks.
As answered in Discord, you should be able to do this:
import scala.reflect.ClassTag
private def fromSeqToCastedSeq[T](files: Seq[File])(implicit ct: ClassTag[T]): Seq[T] = {
val arrayTClass = ct.wrap.runtimeClass.asInstanceOf[Class[Array[T]]]
files.flatMap { file =>
val maps = objectMapper.readValue(file, classOf[Map[String, Any]])
val combinedString = objectMapper.writeValueAsString(maps.get("sqlDefinitions"))
objectMapper.readValue(combinedString, arrayTClass)
}
}
Now, no idea if this will crash at runtime, is highly probably given this piece of code is extremely unsafe and unidiomatic.

Scala, cats - convert FUUID with Circe

I use this library https://christopherdavenport.github.io/fuuid/ for creating ID of custom object and persist them into databse.
I have a simple case class which is my model:
import io.chrisdavenport.fuuid.FUUID
case class Bet(
betId: Option[FUUID],
home: String,
away: String,
stake: BigDecimal,
betType: String)
I used FUUID here as an Option parameter. I have also a routes created with Http4s which should take json from input and map it into model:
class BettingRoutes[F[_] : Async](service: BettingService[F]) extends Http4sDsl[F] {
def routes: HttpRoutes[F] = HttpRoutes.of[F] {
case req#PUT -> Root / "bets" =>
for {
bet <- req.as[Bet]
created <- service.put(bet)
response <- Created(created)
} yield response
}
}
I also added some implicits to encode and decode from Circe:
object jsons {
implicit def circeDecoder[A[_] : Sync, B: Decoder]: EntityDecoder[A, B] = jsonOf[A, B]
implicit def circeEncoder[A[_] : Sync, B: Encoder]: EntityEncoder[A, B] = jsonEncoderOf[A, B]
}
The problem is - when I want to compile project, I got an errors like this in route class:
Error:(23, 22) Cannot decode into a value of type model.Bet, because no EntityDecoder[F, model.Bet] instance could be found.
bet <- req.as[Bet]
Error:(23, 22) not enough arguments for method as: (implicit F: cats.Functor[F], implicit decoder: org.http4s.EntityDecoder[F,model.Bet])F[model.Bet].
Unspecified value parameter decoder.
bet <- req.as[Bet]
Error:(25, 28) Cannot convert from model.Bet to an Entity, because no EntityEncoder[F, model.Bet] instance could be found.
response <- Created(created)
etc. I investigated it and it appears because of using FUUID. I changed all FUUID classes to Long and after this just to java's UUID and then everything compile correctly without errors. The problem is only with FUUID and probably with conversion of it. I tried to use Circe Integration as It was shown in FUUID link above, but it did not help. Do you know how to fix this code to compile everything with fuuid and circe?
I am new to cats and connected libs, so maybe it is a simple mistake, but it is not trivial for me now.
In order to have EntityDecoder[F, Bet] via jsons.circeDecoder we firstly need Decoder[Bet]. It can be auto-generated by Circe if we have decoders for all fields. The thing is there is Decoder[UUID] but no Decoder[FUUID].
So just define necessary implicit
implicit val fuuidDecoder: Decoder[FUUID] = Decoder[UUID].map(FUUID.fromUUID)
Similarly for encoders
implicit val fuuidEncoder: Encoder[FUUID] = Encoder[UUID].contramap(FUUID.Unsafe.toUUID)

Transforming Scala case class into JSON

I have two case classes. The main one, Request, contains two maps.
The first map has a string for both key and value.
The second map has a string key, and value which is an instance of the second case class, KVMapList.
case class Request (var parameters:MutableMap[String, String] = MutableMap[String, String](), var deps:MutableMap[String, KVMapList] = MutableMap[String, KVMapList]())
case class KVMapList(kvMap:MutableMap[String, String], list:ListBuffer[MutableMap[String, String]])
The requirement is to transform Request into a JSON representation.
The following code is trying to do this:
import com.fasterxml.jackson.annotation.PropertyAccessor
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility
import com.fasterxml.jackson.databind.ObjectMapper
def test(req:Request):String {
val mapper = new ObjectMapper() with ScalaObjectMapper
mapper.setVisibility(PropertyAccessor.ALL, Visibility.ANY)
var jsonInString: String = null
try {
jsonInString = mapper.writeValueAsString(request)
}
catch {
=case e: IOException => {
e.printStackTrace
}
jsonString
}
This however is not working. Even when the Request class is populated, the output is :
{"parameters":{"underlying":{"some-value":""},"empty":false,"traversableAgain":true},"deps":{"sizeMapDefined":false,"empty":false,"traversableAgain":true}}
Using the JSON object mapper with corresponding Java classes is straightforward, but have not yet got it working in Scala. Any assistance is very much appreciated.
Jackson is more of a bad old memory in Scala to some degree. You should use a native Scala library for JSON processing, particularly one really good at compile time derivation of JSON serializers, such as circe.
I'm aware this doesn't directly answer your question, but after using circe I would never go back to anything else.
import io.circe.generic.auto._
import io.circe.parser._
import io.circe.syntax._
val req = new Request(...)
val json = req.asJson.noSpaces
val reparsed = decode[Request](json)
On a different note, using mutable maps inside case classes is as non-idiomatic as it gets, and it should be quite trivial to implement immutable ops for your maps using the auto-generated copy method.
case class Request(parameters: Map[String, String] {
def +(key: String, value: String): Request = {
this.copy(parameters = parameters + (key -> value))
}
}
You should really avoid mutability wherever possible, and it looks like avoiding it here wouldn't be much work at all.
I am not sure what this ScalaObjectMapper does, doesn't look like it is useful.
If you add mapper.registerModule(DefaultScalaModule) in the beginning, it should work ... assuming that by MutableMap you mean mutable.Map, and not some sort of home-made class (because, if you do, you'd have to provide a serializer for it yourself).
(DefaultScalaModule is in jackson-module-scala library. Just add it to your build if you don't already have it).

Scala Map to Arbitrary Class (Scala Reflection)

If I have a Scala Map
val map = Map("a" -> true,
"b" -> "hello"
"c" -> 5)
Is there a way I can convert this to an object (case class, regular class, anything really) such that I can access the field like this:
val obj = map.toObj
println(obj.a)
println(obj.b)
Without knowing what the parameters will be ahead of time?
Or even better, can it be an instance variable of the class I'm currently working with?
So I could actually just have
println(a)
println(b)
Have a look at Dynamic:
import scala.language.dynamics
class Wrapper(m: Map[String, Any]) extends Dynamic {
def selectDynamic(name: String) = {
m(name)
}
}
object Demo {
def main(args: Array[String]) {
val map = Map("a" -> true,
"b" -> "hello",
"c" -> 5)
val w = new Wrapper(map)
println(w.a)
println(w.b)
}
}
Dynamic gives you "properties on demand".
But it's not type-safe. In the snippet above, if you try to access a non-existing key in the map, a NoSuchElementException will be thrown. And you get the Any type, so you have to use asInstanceOf at the caller's side, for example.
Dynamic has further methods, so have a closer look at the documentation of Dynamic
I hope you understand by asking this question that you will loose all compile time guarantees when you rely on runtime data. If this is really what you want then you can rely on Dynamic:
object X extends App {
import scala.language.dynamics
class D(fields: Map[String, Any]) extends Dynamic {
def selectDynamic(str: String): Any =
fields.getOrElse(str, throw new NoSuchFieldException(str))
}
val fields = Map[String, Any]("a" -> true, "b" -> "hello")
val obj = new D(fields)
println(obj.a)
println(obj.b)
}
Dynamic is a compiler feature that translates all field/method calls to a call to the *Dynamic* methods. Because the compiler can't know anything about your program (how should it?), the return type you get here is Any and when you call a field/method that does not exist you get an exception at runtime instead of a compile time error. When some fields/methods are known to compile time you can combine Dynamic with macros to get at least some compile time checking (such a method is described in the linked answer).
Beside from that, that is the only syntax you can enable in Scala. If return types are important to you, you can at least add them as type parameter:
object X extends App {
import scala.language.dynamics
class D(fields: Map[String, Any]) extends Dynamic {
def selectDynamic[A : reflect.ClassTag](str: String): A =
fields.get(str) match {
case Some(f: A) => f
case _ => throw new NoSuchFieldException(str)
}
}
val fields = Map[String, Any]("a" -> true, "b" -> "hello")
val obj = new D(fields)
println(obj.a[Boolean])
println(obj.b[String])
}

JSON deserialization using reflection

Hi I am trying to extract a JSON using reflection
import net.liftweb.json._
case class Bike(make: String, price: Int) {
def this(price: Int) = this("Trek", price)
}
val cls = Class.forName("Bike")
val manifest = Manifest.classType(cls)
val parsedData =net.liftweb.json.JsonParser.parse(json)
JsonParser.parse(""" {"price":350} """).extract[manifest]
however I am getting this error:
not found: type manifest
JsonParser.parse(""" {"price":350} """).extract[manifest]
^
although manifest is from type Manifest
You can extract directly into a case class
val json = "the json";
val bike = parse(json).extract[Bike];
JSON parsing is done through reflection.
If the class is a runtime construct, create a TypeInfo instance and pass that to the extract method.
There is a variation of the extract() method that might work for you, if you provide it with a TypeInfo instance.
See here: https://github.com/lift/lift/blob/master/framework/lift-base/lift-json/src/main/scala/net/liftweb/json/Extraction.scala#L178