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")