Semi-automatic Circe decoder for JsonString of slick-pg

If you need a decoder for storing JSON to a database or implicit conversion of a com.github.tminglei.slickpg.JsonString, you can us the semi-automatic derivation of Circe.

The following imports are neccessary.

import com.github.tminglei.slickpg.JsonString
import io.circe.Decoder
import io.circe.generic.semiauto._

Let`s assume, we have the following case class:

final case class MyClass(
    myId: Long,
    desc: String,
    structure: JsonString
)

The following implicit decoder is semi-automatically derived by Circe.

/**
 * Implicit Decoder for decoding the JsonString value
 */
implicit val decodeMyClassStructureJsonString: Decoder[JsonString] = deriveDecoder[JsonString]

Decoder and Encoder

An implicit decoder and encoder for the case class could be as follows.

// Circe codec for decoding a MyClass from JSON.
  implicit val decodeMyClass: Decoder[MyClass] = (c: HCursor) =>
    for {
      myId      <- c.downField("myId").as[Long]
      desc      <- c.downField("desc").as[String]
      structure <- c.downField("structure").as[JsonString]
    } yield
      MyClass(
        myId,
        orgadescisationUuid,
        structure
    )

  // Circe codec for encoding a MyClass to JSON.
  implicit val encodeMyClass: Encoder[MyClass] = (a: MyClass) =>
    Json.obj(
      ("myId", a.myId.asJson),
      ("desc", a.desc.asJson),
      ("structure", a.structure.value.asJson)
  )

Current versions:

  • slick-pg 0.15.2
  • circe 0.8.0

Akka stream with Alpakka and FTP connector – close the stream

If you use an Alpakka FTP connector, you have to close the stream at the end to finish the connection correctly. The default behavior is to sent a `akka.actor.Status.Success` message to the ActorRef.

actor ! akka.actor.Status.Success

I got the following error message when sending the message like above.

java.lang.ClassCastException: akka.actor.Status$Success$ cannot be cast to akka.util.ByteString

The FTP connector requires a ByteString when writing content to the target of the stream.

The following code demonstrates a simple implementation of a FTP connector:

val uri: java.net.URI: = ...
val username = USERNAME
val password = PASSWORD
val DEFAULT_CHARSET = "UTF-8"

val byteSource: Source[ByteString, ActorRef] =
  Source.actorRef[ByteString](Int.MaxValue, OverflowStrategy.fail)

val host = InetAddress.getByName(uri.getHost)
val port = 21
val credentials = NonAnonFtpCredentials(username, password)

val settings =
  FtpSettings(
    host, port, credentials, binary = true, passiveMode = false
  )
val ftpConnection: Sink[ByteString, Future[IOResult]] = 
  Ftp.toPath(path, settings, append = true)

val writer = Flow[ByteString].to(ftpConnection).runWith(byteSource)

You can send a message to the stream in the following manner:

writer ! ByteString("MESSAGE".getBytes(DEFAULT_CHARSET))

Back to the `ClassCastException`. If you want to close the stream correctly, you have to send a close message with the correct data type that is expected by the stream. Example:

actor ! akka.actor.Status.Success("Success".getBytes(DEFAULT_CHARSET))

Create a new pair of ssh keys with a specific filename

If you need additional ssh keys for the work on external projects, you can create additional keys with the following command:

ssh-keygen -b 4096 -t rsa -C My-Email -f filename

If you have not executed the command within the .ssh folder, you should move the created files:

mv filename filename.pub .ssh

Finally, you can add the keys to you local Shell session with:

ssh-add .ssh/filename

Import external Ivy dependencies during ammonite session

You can import external Ivy dependencies during you ammonite session. First, you have to import the Ivy (SBT) dependency (The example imports the jBCrypt library from the Maven repository). Additional information can be found at https://github.com/svenkubiak/jBCrypt.

import $ivy.`de.svenkubiak::jBCrypt:0.4.1`

The required dependencies are downloaded during the session. Second, you have to import the BCrypt dependency that should be used.

import org.mindrot.jbcrypt.BCrypt

And use it:

BCrypt.hashpw("Foo-Bar-Password",BCrypt.gensalt())

Update Ammonite (ammonite.io)

If you want to update ammonite, you can do this in the following manner:

curl -L -o ~/bin/ammonite https://git.io/vdNv2

Note: The latest ammonite version can be found on http://ammonite.io. Just exchange the https-URL.

Store the ammonite executable to the local bin folder.

Delete the cache of former ammonite sessions:

rm -rf ~/.ammonite/cache

Create a predef.sc file that loads different dependencies during startup of ammonite.

vim ~/.ammonite/predef.sc
interp.load.ivy("com.lihaoyi" %% "ammonite-ops" % ammonite.Constants.version)
interp.load.ivy("org.typelevel" %% "cats-core"  % "1.0.1")
interp.load.ivy("org.typelevel" %% "cats-free"  % "1.0.1")
interp.load.ivy("io.monix"      %% "monix"      % "2.3.3")
interp.load.ivy("io.monix"      %% "monix-cats" % "2.3.3")

Traversing the alphabet in Scala

If you need to traverse the alphabet in Scala automatically, you can create a loop that proceses the single letters.

The following code was used in a Play Template (view) to traverse the alphabet and show the differnt links depending on the existence of a single letter in the cityLetters sequence. If the letter is in the sequence, the link is active, otherwise inactive.

@(cityLetters: Seq[String] = Seq.empty)

@defining('A' to 'Z'){ alphabet =>
  @for(l <- alphabet) {
    @defining(l.toString) { letter =>
      @if(cityLetters.contains(letter)) {
        <a class="btn btn-default" href="@routes.CityController.listing(letter)">@letter</a>
      } else {
        <a class="btn btn-default" disabled="disabled" href="#">@letter</a>
      }
    }
  }
}

Permission denied while trying to connect with Docker daemon via socket

The following error occured while trying to connect to the Docker daemon after installation.

Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Post [...]: dial unix /var/run/docker.sock: connect: permission denied.

The daemon was not accessible by the current user because of lack of permission. The solution is to add the current user to the docker group to gain permission for connection.

sudo usermod -a -G docker $USER

After executing the above command, log out from the current shell and log out from the account.

Tmux configuration and basic commands

Basic configuration for tmux

Tmux canbe configured via .tmux.conf file within the home directory. The following .tmux.conf contains a basic configuration.

# ~/.tmux.conf

set -g default-terminal "screen-256color"   # use 256 colors
set -g history-limit 65536                  # scrollback buffer n lines
set -g default-command zsh                  # disable login-shell

# Set the prefix to ^A.
unbind C-b
set -g prefix ^A
bind a send-prefix

# Bind appropriate commands similar to screen.
# lockscreen ^X x 
unbind ^X
bind ^X lock-server
unbind x
bind x lock-server

# screen ^C c 
unbind ^C
bind ^C new-window
unbind c
bind c new-window

# detach ^D d
unbind ^D
bind ^D detach

# displays * 
unbind *
bind * list-clients

# next ^@ ^N sp n 
unbind ^@
bind ^@ next-window
unbind ^N
bind ^N next-window
unbind " "
bind " " next-window
unbind n
bind n next-window

# title A
unbind A
bind A command-prompt "rename-window %%"

# other ^A
unbind ^A
bind ^A last-window

# prev ^H ^P p ^? 
unbind ^H
bind ^H previous-window
unbind ^P
bind ^P previous-window
unbind p
bind p previous-window
unbind BSpace
bind BSpace previous-window

# windows ^W w 
unbind ^W
bind ^W list-windows
unbind w
bind w list-windows

# quit \ 
unbind '\'
bind '\' confirm-before "kill-server"

# kill K k 
unbind K
bind K confirm-before "kill-window"
unbind k
bind k confirm-before "kill-window"

# redisplay ^L l 
unbind ^L
bind ^L refresh-client
unbind l
bind l refresh-client

# split -v |
unbind |
bind | split-window

# :kB: focus up
unbind Tab
bind Tab select-pane -t:.+
unbind BTab
bind BTab select-pane -t:.-

# " windowlist -b
unbind '"'
bind '"' choose-window

# Powerline
source-file ~/.local/lib/python2.7/site-packages/powerline/bindings/tmux/powerline.conf
# alternatively absolute path to HOME
# Rainbarf
set -g status-left '#(rainbarf --battery --remaining --rgb)'

Basic tmux commands

To start a new tmux terminal, the following command forces the terminal to assume that it supports 256 colors.

> tmux -2

The following commands represent a few basics (based on the configuration from above):

STRG-A This prefix key starts a new commands and will be followed by a command key. (Default prefix key is STRG-B)
STRG-A ↑(Picture upwards) Scrolling mode (Leave via `Enter`)
STRG-A D Detach to background (tmux -2 attach (hold back to foreground))
STRG-A C Create a new terminal witin tmux
STRG-A | Vertical split of the screen
STRG-A % Horizontal split of the screen
STRG-A(hold it) + ArrowKeys Change the size of the terminals