Response object scala.Unit - scala

I have an action that returns Unit:
post("/settings") {
blahblahblah...
Unit
}
Previously, the client received an empty response.
But after I upgraded the Scalatra version from 2.5.0 to 2.7.1 and Java from 8 to 11, the response now contains the following text:
object scala.Unit
How can I fix this?

Return the Unit value () instead of the Unit companion object (which has type Unit.type and is not an instance of type Unit).
post("/settings") {
blahblahblah...
()
}
In scala 2.13 your code simply would not compile anymore. You get an error:
`Unit` companion object is not allowed in source; instead, use `()` for the unit value

Related

what is '???' in Scala?

I'm learning Scala using IntelliJ IDE.
When I subs class Element and override contents method, IDE provided default implementation for contents method with definition ???
Below code from the book Programming in Scala, 3rd edition
Element
abstract class Element {
def contents: Array[String]
def height = contents.length
def width = if (height == 0) 0 else contents(0).length
}
ArrayElement
class ArrayElement(cont: Array[String]) extends Element {
override def contents: Array[String] = ??? // impl provided by IDE
}
I don't see any issues in running the program but when I access the method I get below exception
Exception in thread "main" scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:284)
at org.saravana.scala.ArrayElement.contents(ScalaTest.scala:65)
Can someone explain what is ??? and use of it?
??? is designed as a placeholder and is a method defined in Predef (which is automatically imported by default)
It's definition is
def ??? : Nothing = throw new NotImplementedError
So it has return type Nothing and all it does is throw NotImplementedError. This definition allows it to used as a placeholder implementation for methods you defined but haven't implemented yet but still want to be able to compile your program.
Nothing is a subtype of every type, which makes ??? a valid implementation no matter what type is expected.

Scalamock: Unable to mock function with typed parameter and multiple implicit variables

This question is an extension of the solved issue mentioned at https://github.com/paulbutcher/ScalaMock/issues/79
I have the following trait to mock:
trait HttpClient{
def deserialize[T](response: HttpResponse)
(implicit um: Unmarshaller[ResponseEntity, T],
executionContext: ExecutionContext): Future[T]
}
I'm trying to mock the HttpClient as follows
val client = mock[HttpClient]
case class SomeTypeT(name:String, id:Int)
implicit val someTypeTFormat = jsonFormat2(SomeTypeT) // to be able to marshal and unmarshal from JSON
(httpClient.deserialize[SomeTypeT](_: HttpResponse))
.expects(where {
(response: HttpResponse) => {
response.entity == ent
}
})
.returns(Unmarshal(response.entity).to[SomeTypeT])
The problem occurs when I try to mock the deserialize function. As above, the deserialize method consists of a Typed Parameter T and a single parameter of type HttpResponse, and 2 more implicit parameters used while unmarshalling the response.
The question, therefore, is how to use ScalaMock to mock the deserialize function and specify multiple implicit parameters while mocking. This does not work
// Both UnMarshaller & ExecutionContext are available here as implicits
(httpClient.deserialize[SomeTypeT](_: HttpResponse)(_: Unmarshaller[ResponseEntity, SomeTypeT](_: ExecutionContext))
The problem is I cannot use _ to specify both the implicit parameters. And I don't know how to achieve this. Please help how to mock the given function
I'm using the following libraries:
scala version 2.11.8
scalatest version 3.0.0
scalamock version 3.5.0
While the second attempt does not even compile due to multiple _ being used, the first one results in following exception:
org.scalamock.function.MockFunction3 cannot be cast to org.scalamock.function.MockFunction1
java.lang.ClassCastException: org.scalamock.function.MockFunction3 cannot be cast to org.scalamock.function.MockFunction1
Following the answer at GitHub that you linked, your code should be something like
(httpClient.deserialize[SomeTypeT](_: HttpResponse)(_: Unmarshaller[ResponseEntity, SomeTypeT], _:ExecutionContext))
.expects(where {
(response: HttpResponse, _: Unmarshaller[ResponseEntity, SomeTypeT], _:ExecutionContext) => {
response.entity == ent
}
})
.returns(Unmarshal(response.entity).to[SomeTypeT])
I.e. you explicitly put placeholders for implicit parameters in the call as a second group of parameters and in the where as additional parameters after all non-implicit.

Why is the Scala compiler giving me an error when passing a Kotlin sealed class into a constructor?

I have a sealed class, written in Kotlin:
sealed class Schema {
class RecordSchema(val fields: List<Field>): Schema()
class ArraySchema(val elementSchema: Schema): Schema()
...
}
And another class that takes RecordSchema as a parameter:
class Enrichment(config: Config, val schema: RecordSchema) { ... }
In Scala I have a class that, among other things, get an instance of the RecordSchema and then create an instance of the Enrichment.
object Job {
def main(args: Array[String]): Unit = {
/// some initializing of resources... and then...
val recordSchema = schemas.getSchema(id) // type is Schema.RecordSchema
val enrichment = Enrichment(config, recordSchema) // this is where scalac errors out
}
}
The scala compiler ends up printing this error message:
Error:(52, 62) type mismatch;
found : com.companyname.enricher.schemas.com.companyname.enricher.schemas.com.companyname.enricher.schemas.
required: com.companyname.enricher.schemas.(some other)com.companyname.enricher.schemas.com.companyname.enricher.schemas.
val enrichment = new Enrichment(config, recordSchema)
If I cast recordSchema using asInstanceOf I get another, not so useful, error:
Error:(52, 62) type mismatch;
found : com.companyname.enricher.schemas.Schema.RecordSchema
required: com.companyname.enricher.schemas.com.companyname.enricher.schemas.
val enrichment = new Enrichment(config, recordSchema.asInstanceOf[RecordSchema])
Overall, I have no idea why this is happening. If I make the constructor take the parent class as a parameter rather than nested class, it compiles just fine (which is my workaround for now). If I do the same type of thing, except having written the sourcecode in Java rather than Kotlin, this error does not happen. I am using Java 1.8, Kotlin 1.0.4, Scala 2.11.8.
UPDATE:
demonstrated bug here:
https://github.com/mjburghoffer/scala-kotlin-innerclass-bug/tree/master
Looks like Kotlin generates different number of classes for this case. I compiled Java and Kotlin sources and found that Java has additional file ParentSealedJava$1.class. Bytecode of Parent and Sealed classes in Java and Kotlin pretty the same (i inspect bytecode using javap -c), so i think Scala compiler relies somehow on this missing file in Kotlin.

Side-effecting nullary methods are discouraged: suggest defining as ... for IntelliJ

I executed this code block in a IntelliJ worksheet (Community Edition EAP 15#143.379.11 with Scala plugin 1.9.4 on JDK 1.8.0_66) ,
class Plant
class Fruit extends Plant
class Apple extends Fruit
class Box[T <: Fruit](var item: T) {
def get: T = item
def replace(item: T): Unit = this.item = item
}
val appleBox = new Box(new Apple)
println(appleBox.get) // error
and IntelliJ reported this error during worksheet compilation and stopped,
Error:(22, -59) side-effecting nullary methods are discouraged: suggest defining as `def get$$instance$$res0()` instead
println(appleBox.get);//
^
How do I disable this error or change it to warning and let me continue? I am using IntelliJ . Thanks
To avoid an error just remove println, Scala Worksheet will print the object for you.
val appleBox = new Box(new Apple)
appleBox.get
appleBox: Box[Apple] = Box#4109bbc4
res0: Apple = Apple#6e2e3a8b
PS: I do not get the error you are reporting in the latest EAP Scala Plugin (1.9.272)

Why does complete'ing requests where JavaUUID is used lead to compilation error?

I'm developing a project with Akka and Spray. It works fine except GETs that are handled with the following route:
class UserRoot extends Directives with DefaultJsonFormats with PerRequestCreator {
val route =
path("users" / JavaUUID / "activities") { userId =>
get {
complete {
createActorPerRequest(new StringUUID(userId), Props[LogicGetActivitiesFromUser])
}
}
}
def createActorPerRequest(entity: Entity, target: Props): Route =
context => perRequest(context, target, Work(entity))
}
The StringUUID class:
case class StringUUID(id: String) extends Entity // I also tried UUID instead of String
The code above errors with the following:
error: type mismatch;
found : java.util.UUID
required: String
createActorPerRequest(new StringUUID(userId), Props[LogicGetActivitiesFromUser])
But if I add import reflect.ClassTag (that I found this on the internet) it gives me another error:
error: could not find implicit value for evidence parameter of type spray.httpx.marshalling.Marshaller[spray.routing.RequestContext => Unit]
createActorPerRequest(new StringUUID(userId.toString), Props[LogicGetActivitiesFromUser])
Any idea?
Look at this Example. It doesn't have the complete.
The following route should fix the error:
val route =
path("pets") {
get {
petsWithOwner {
GetPetsWithOwners(List("Lassie"))
}
}
}
The issue is that the types don't match so the Scala compiler (not Spray or Akka or anything else) reports it as compilation error.
In the first version of the route code, mind the type of userId - it's java.util.UUID as the Scala compiler says. You can't use a val of java.util.UUID type where String is expected, in StringUUID for id input parameter.
In the second version of the code, in which you've used userId.toString the type String matches the expected type of the id input parameter. That led you to another issue where there was no implicit to marshall the response from createActorPerRequest as requested by complete.
You should let the spawn actor to complete the response or await a response from the actor (using the ask pattern) and pass it on as a response from complete. That also needs a marshaller (as were the code inside complete in the actor's receive).