Skip to content

Commit

Permalink
118 json improvement (#121)
Browse files Browse the repository at this point in the history
* JSON: Make Json.arr work with and clean up a bit
* JSON: Add json"" and jsonArray"" interpolators
* Improve Json.obj, Json.arr and documentation
* Make asMap and asList convert recursively
* Implement Scala-ish JsonPointer
* Documentation for JsonPointer
* Fix link on README.adoc
  • Loading branch information
oliver-brm authored Jan 19, 2024
1 parent db15d62 commit 100b3fc
Show file tree
Hide file tree
Showing 15 changed files with 1,076 additions and 338 deletions.
2 changes: 1 addition & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Vert.x-Scala provides language bindings and helpers for using Scala with Vert.x.

Please see the main documentation on the web-site for a full description:

* https://vertx.io/docs/#scala[Web-site documentation]
* http://vert-x3.github.io/vertx-lang-scala/[Web-site documentation]
== Structure

Expand Down
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@
<artifactId>scalatest_3</artifactId>
<version>3.3.0-SNAP4</version>
</dependency>
<dependency>
<groupId>org.scalatestplus</groupId>
<artifactId>scalacheck-1-17_3</artifactId>
<version>3.2.17.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import org.scalatest.flatspec.AsyncFlatSpec
import scala.concurrent.Await
import scala.concurrent.duration.*
import scala.language.postfixOps
import scala.quoted.{Expr, Quotes, Type}
import scala.reflect.ClassTag
import scala.util.{Failure, Success}
import org.slf4j.Logger
import org.slf4j.LoggerFactory
Expand Down
3 changes: 2 additions & 1 deletion vertx-lang-scala/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ Compile / doc / scalacOptions ++= Seq(
"-Ygenerate-inkuire",
"-project-version", version.value,
"-project-logo", "src/main/markdown/_assets/images/vertx-logo.png",
"-project-footer", s"© $currentYear Eclipse Vert.x™"
"-project-footer", s"© $currentYear Eclipse Vert.x™",
"-project-url", "https://github.com/vert-x3/vertx-lang-scala",
)

lazy val root = project
Expand Down
19 changes: 4 additions & 15 deletions vertx-lang-scala/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -358,25 +358,14 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>

<dependency>
<groupId>co.helmethair</groupId>
<artifactId>scalatest-junit-runner</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<groupId>org.scalatest</groupId>
<artifactId>scalatest_3</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.scalatest</groupId>
<artifactId>scalatest_3</artifactId>
<groupId>org.scalatestplus</groupId>
<artifactId>scalacheck-1-17_3</artifactId>
<scope>test</scope>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,39 @@
title: Working with Futures
---

Almost every function of the Vert.x API wraps the result `T` of an operation in a `io.vertx.core.Future[T]`. This is very similar to Scala APIs returning`scala.concurrent.Future[T]`. Working with Scala Futures, however, bears some differences:
# Working with Futures

Almost every function of the Vert.x API wraps the result `T` of an operation in a
`io.vertx.core.Future[T]`. This is very similar to Scala APIs returning
`scala.concurrent.Future[T]`. Working with Scala Futures, however, bears some differences:

- _chaining_ Scala Futures can be expressed in an elegant way using `for`-comprehensions
- operations like `map` or `filter` require a (`given`) `ExecutionContext`

This page explains how Vert.x Futures can be converted to Scala Futures and how we deal with the `ExecutionContext`.

This page explains how Vert.x Futures can be converted to Scala Futures and how we deal
with the `ExecutionContext`.

# Implicit Conversion
## Implicit Conversion

The object [[io.vertx.lang.scala.ImplicitConversions]] provides _implicit conversions_. To use them, we need two imports:
The object [[io.vertx.lang.scala.ImplicitConversions]] provides _implicit conversions_.
To use them, we need two imports:

```scala
import io.vertx.lang.scala.ImplicitConversions.*
import scala.language.implicitConversions
```

The import `scala.language.implicitConversions` is required to indicate our will to use implicit conversions in the current scope, thus avoiding compiler warnings.
The import `scala.language.implicitConversions` is required to indicate our will to use
implicit conversions in the current scope, thus avoiding compiler warnings.

After that, the Scala compiler applies the conversion automatically if possible.
After that, the Scala compiler applies the conversion automatically if possible.

The following example loads a file from the file system and sends it over the Event Bus. There is an implicit conversion applied here, because
The following example loads a file from the file system and sends it over the Event Bus.
There is an implicit conversion applied here, because

1. loading a file with `vertx.fileSystem.readFile` results in a `io.vertx.core.Future[Buffer]`
2. the `for`-comprehension requires a `scala.concurrent.Future[_]`
3. the implicit conversion `vertxFutureToScalaFuture` is in scope
2. the `for`-comprehension requires a `scala.concurrent.Future[_]`
3. the implicit conversion `vertxFutureToScalaFuture` is in scope

```scala
//{
Expand All @@ -47,14 +54,16 @@ final class MyVerticle extends ScalaVerticle:
} yield ()
```

As explained in [The Scala 3 Reference](https://docs.scala-lang.org/scala3/reference/contextual/conversions.html), implicit conversions can not always be applied by the compiler. That's when we might want to use an explicit conversion.

As explained in [The Scala 3 Reference](https://docs.scala-lang.org/scala3/reference/contextual/conversions.html), implicit conversions can not always be applied
by the compiler. That's when we might want to use an explicit conversion.

# Explicit Conversion
## Explicit Conversion

When implicit conversions are not applicable and we still want to use Scala Futures, we can use extension methods.
When implicit conversions are not applicable and we still want to use Scala Futures, we can
use extension methods.

The following example shows usage of the extension method `asScala` which is defined on `io.vertx.core.Future` in the package object [[io.vertx.lang.scala]]:
The following example shows usage of the extension method `asScala` which is defined on
`io.vertx.core.Future` in the package object [[io.vertx.lang.scala]]:

```scala
//{
Expand All @@ -74,11 +83,15 @@ final class MyVerticle extends ScalaVerticle:
```


# Working with the `ExecutionContext`
## Working with the `ExecutionContext`

Interaction with Vert.x APIs is normally done in the scope of a Verticle. The base class [[io.vertx.lang.scala.ScalaVerticle]] already has a `given` `ExecutionContext`, so it is provided to any API requiring it as an implicit parameter. This means, as long as we are in the scope of a `ScalaVerticle`, we do not have to deal with the `ExecutionContext`.
Interaction with Vert.x APIs is normally done in the scope of a Verticle. The base class
[[io.vertx.lang.scala.ScalaVerticle]] already has a `given` `ExecutionContext`, so it is
provided to any API requiring it as an implicit parameter. This means, as long as we are
in the scope of a `ScalaVerticle`, we do not have to deal with the `ExecutionContext`.

For rare situations in which it is not possible to access `ScalaVerticle`'s `ExecutionContext`, we can construct one by our own:
For rare situations in which it is not possible to access `ScalaVerticle`'s `ExecutionContext`,
we can construct one by our own:

```scala
//{
Expand All @@ -91,4 +104,7 @@ import io.vertx.lang.scala.VertxExecutionContext
given ec: ExecutionContext = VertxExecutionContext(vertx, vertx.getOrCreateContext())
```

The `io.vertx.core.Context` is important for Vert.x in order to properly schedule asynchronous tasks, like accessing a database. Remember: All tasks started on the same Vert.x context, are also running on the same _thread_, which is good as it reduces expensive thread context switching and error-prone sharing of state.
The `io.vertx.core.Context` is important for Vert.x in order to properly schedule
asynchronous tasks, like accessing a database. Remember: All tasks started on the
same Vert.x context, are also running on the same _thread_, which is good as it
reduces expensive thread context switching and error-prone sharing of state.
Loading

0 comments on commit 100b3fc

Please sign in to comment.