Posts in the “scala” category

Scala: How to find the keys that are common to two maps

As a quick tip, this method shows one way you can find the keys that are common to two Scala Maps:

/**
 * Find the list of keys that are common to two Maps.
 */
def commonMapKeys[A, B](a: Map[A, B], b: Map[A, B]): Set[A] = a.keySet.intersect(b.keySet)

Another Scala nested Option + flatMap example

After yesterday’s Scala nested Option + flatMap/for example, here’s another example of plowing through nested Options with flatMap. First, start with some nested options:

val o1 = Option(1)
val oo1 = Option(o1)
val ooo1 = Option(oo1)

Here are those same three lines, with the data type for each instance shown in the comments:

val o1 = Option(1)       // Option[Int]
val oo1 = Option(o1)     // Option[Option[Int]]
val ooo1 = Option(oo1)   // Option[Option[Option[Int]]]

With this setup, just like yesterday, I can dig my way through the Options to get to the enclosed value using flatMap calls:

ooo1 flatMap { oo1 =>
    oo1 flatMap { o1 =>
        o1
    }
}

Here’s what that code looks like in the Scala REPL:

scala> val o1 = Option(1)
o1: Option[Int] = Some(1)

scala> val oo1 = Option(o1)
oo1: Option[Option[Int]] = Some(Some(1))

scala> val ooo1 = Option(oo1)
ooo1: Option[Option[Option[Int]]] = Some(Some(Some(1)))

scala> ooo1 flatMap { oo1 =>
     |     oo1 flatMap { o1 =>
     |         o1
     |     }
     | }
res0: Option[Int] = Some(1)

As that shows, the final result of the flatMap calls is an Option[Int], specifically a Some(1).

Just like yesterday, you can also use for-expressions to get to the enclosed value, but for today I just wanted to show this as another flatMap example.

I’ll keep trying to make monads, flatMap, and for-expressions as easy as I can, but for now I hope that’s a simple example you can experiment. (At least the setup portion of it is simple.)

Scalameta, a metaprogramming library for Scala

If you’re interested in metaprogramming with Scala, Scalameta is “a modern metaprogramming library for Scala that supports a wide range of language versions and execution platforms. Originally, Scalameta was founded to become a better macro system for Scala, but over time we shifted focus to developer tools and spun off the new macro system into a separate project.”

Scala 3: Tasty, and the plan for macros

If you’re interested in the future of Scala, specifically Scala 3, the official Scala blog has an interesting article titled, Macros: The Plan for Scala 3. A beneficial part of reading at least part of the article is that you can learn a little bit about Tasty, “the high-level interchange format for Scala 3.”

Scala 2.13.0-M4 release notes (collections changes)

Under the covers — and sometimes above the covers — Scala is changing. These notes about Scala 2.13.0-M4 describe some of the changes coming to the Scala collections classes.

A few things not shown in the image are:

  • The scala-xml library is no longer bundled with the release
  • Procedure syntax (def m() { ... }) is deprecated
  • View bound syntax (A <% B) is deprecated
  • Assorted deprecated methods and classes have been removed

See the Scala 2.13.0-M4 release notes for more details.

Scala 3 becoming more “opinionated”

Via Kelley Robinson, one of Martin Odersky’s slides at ScalaDays (May, 2018) is titled, “Realizing Scala’s Potential,” with these bullet points:

  • become more opinionated
  • simplify
  • eliminate inconsistencies and puzzlers
  • build on strong foundations
  • consolidate language constructs to improve: consistency, safety, ergonomics, performance

As Ms. Robinson writes, “Scala was a language toolbox, and that leads to fragmentation. Scala 3 wants to become more opinionated.”

How to show Scala String and StringOps methods in the REPL

Just a quick note here today on how to show methods from the String class in the Scala REPL, as well as methods from the StringOps class, which aren't seen as easily.

First, if you've used tab completion in the REPL, you may already know that you can show many String class methods in the REPL. If you hit the [Tab] key once you'll see a short list of String methods:

Play Framework example: A controller action that handles a SQL exception, creates a new Form, and has custom error messages

If you need to handle a unique constraint in a database table field when writing an add or edit process in a Play Framework application, I hope this example will be helpful. In the end I’ll show:

  • How to write a Play Anorm query that performs a SQL INSERT on a database field that has a unique constraint
  • How to write a Play controller method (Action) that handles that SQL exception
  • How to create a new Form after you catch that exception
  • How to add custom error messages to that form
  • How to redirect control back to your Play template

If you need to see any of those things, I hope the following example is helpful.

The database method

In my case I’m writing a URL-shortening application and I have a unique constraint on a table column named short_uri, so I wrote my database-insert method with Anorm to look like this:

// uses Try b/c `short_uri` has a unique constraint, which can cause an exception
def insertNewUrl(u: Url): Try[Option[Long]] = db.withConnection { implicit c =>
    Try {
        val q = SQL"""
        insert into urls (user_id,long_url,short_uri,notes)
        values (1,${u.longUrl},${u.shortUrl},${u.notes})
    """
        q.executeInsert()  //returns the primary key as an Option
    }
}

I catch the possible unique constraint exception with Try. Because executeInsert returns the primary key inside an Option, this method returns the type Try[Option[Long]]. The key here for the purpose of this example is that the SQL INSERT can fail because of the unique constraint, so I handle the possible exception with Try.

The controller method/action

For me, the harder part in this case is to know what to do in your controller action code. I’m not going to try to explain it all, I’m just going to show my code, and then offer a little explanation:

def handleAddFormSubmission = authenticatedUserAction { implicit request =>
    val formDidNotValidateFunction = { formWithErrors: Form[Url] =>
        BadRequest(views.html.editUrl(0, formWithErrors, addFormSubmitUrl))
    }
    val formValidatedFunction = { data: Url =>
        // form data is valid, try saving to the database
        val url = Url(
            data.id,
            data.longUrl,
            data.shortUrl,
            data.notes
        )
        // there’s a Try here b/c a SQL INSERT can fail due to database constraints
        val pkInOptionInTry: Try[Option[Long]] = urlDao.insertNewUrl(url)
        pkInOptionInTry match {
            case Success(maybePk) => {
                // no exception was throw, so `maybePk` probably has the primary key
                Redirect(routes.UrlAdminController.list())
                    .flashing("info" -> s"URL '${data.shortUrl}' was added.")
            }
            case Failure(e) => {
                // an exception was thrown, so the SQL INSERT failed, probably a duplicate key error
                val formBuiltFromRequest: Form[Url] = form.bindFromRequest()
                val newForm = formBuiltFromRequest.copy(
                    errors = formBuiltFromRequest.errors ++ Seq(
                        FormError("short_uri", "Probably have a duplicate URI in the database."),
                        FormError("short_uri", e.getMessage)
                    )
                )
                BadRequest(views.html.editUrl(0, newForm, addFormSubmitUrl))
            }
        }
    }
    val formValidationResult: Form[Url] = form.bindFromRequest
    formValidationResult.fold(
        formDidNotValidateFunction,
        formValidatedFunction
    )
}

One big key in this method is knowing that you can use Try to easily handle the exception that can be returned by the database access method.

Creating a new Play Form after the error

A second big key is knowing that you can rebuild a Form with either of these two approaches:

val newForm: Form[Url] = form.bindFromRequest()
val newForm: Form[Url] = form.fill(data)

I haven’t looked into the differences between those two possible approaches, but it took me a while to figure out those approaches, so hopefully that knowledge will save someone else time in the future. The key here is that you need to build a new form after the exception that you can pass to your template, and this is how you do that.

Adding custom error messages to the form

Another big key was find out that methods like form.withError(...) and form.withGlobalError(...) don’t work as expected, so I had to write code like this to get my custom error messages to show up in the Play template:

val newForm = formBuiltFromRequest.copy(
    errors = formBuiltFromRequest.errors ++ Seq(
        FormError("short_uri", "Probably have a duplicate URI in the database."),
        FormError("short_uri", e.getMessage)
    )
)

You probably only need one error message there, but since I’m writing this application for myself I don’t mind seeing the output from e.getMessage. Note that this approach binds those error messages to the short_uri field in the template.

The Play template

You might not need to see the Play Framework template to understand what I just showed, but it may help to see the template code, so here it is:

@(
    urlId: Long,
    form: Form[Url],
    postUrl: Call
)(implicit request: RequestHeader, messagesProvider: MessagesProvider)

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
    <link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/admin.css")">
</head>

<body id="edit-url">
<div id="content">

    <div id="edit-url-form">

    <h1>URL Shortener</h1>

    @* Flash shows updates to a page *@
    @request.flash.data.map{ case (name, value) =>
        <div>@name: @value</div>
    }

    @* Global errors are not tied to any particular form field *@
    @if(form.hasGlobalErrors) {
        @form.globalErrors.map { error: FormError =>
            <div>
                Error: @error.key: @error.message
            </div>
        }
    }

    @helper.form(postUrl, 'id -> "blog-edit-form") {
        @helper.CSRF.formField

        @* id is 0 for 'add', and is set by the 'edit' process *@
        <input type="hidden" name="id" value='@urlId'>

        @helper.inputText(
            form("long_url"),
            '_label -> "Long URL",
            'placeholder -> "the original, long url",
            'id -> "long_url",
            'size -> 68
        )
        @helper.inputText(
            form("short_uri"),
            '_label -> "Short URI",
            'placeholder -> "the short uri you want",
            'id -> "short_uri",
            'size -> 68
        )
        @helper.textarea(
            form("notes"),
            '_label -> "Notes",
            'id -> "notes",
            'rows -> 5,
            'cols -> 60
        )
        <button>Save</button>
    }

    </div>

</div>

</body>
</html>

I’m not going to bother to explain that code at all, other than to say that the short_uri field in the template is where my custom error message will show up.

As a final note, here’s what those custom form error messages look like in the template (a data-entry form):

The Play Framework form template custom error messages

Summary

In summary, if you wanted to see how to handle Play Framework things like how to handle a SQL exception related to a unique constraint violation; how to create a new form after an exception like that; and how to add custom error messages to a Play form, I hope this example is helpful.