Netty-based safely network reconnection I am writing a TCP client app using netty

NettyConnectionManager.scala:

class NettyConnectionManager(val config : NettyConfig) extends ConnectionManager {
  @volatile private var connection: Option[Connected] = None

  def get() = {
    if(isConnected) {
      connection.get
    } else {
      synchronized {
        if(isConnected) {
          connection.get
        } else {
          val newConnection = new NettyConnection(config)
          newConnection.connect()
          connection = Some(newConnection)
          connection.get
        }
      }
    }
  }

  private def isConnected = {
    (for(c &lt;- connection if c.isConnected) yield true).getOrElse(false)
  }

  def close() {
    synchronized {
      if(isConnected) {
        connection.foreach(_.close())
      }
    }
  }
}


NettyConnection:

class NettyConnection(val config: NettyConfig) extends Connection {

  @volatile
  private var channel = None: Option[Channel]

  def connect() = {
    val channelFuture = bootstrap().connect(new java.net.InetSocketAddress(config.hostname, config.port))
    channelFuture.awaitUninterruptibly
    channel = Some(channelFuture.getChannel)
  }

  def isConnected = channel.map(_.isOpen).getOrElse(false)
  ...


I am trying to do auto-reconnect in NettyConnectionManager.

Now I have three questions:


Is channel.isOpen method reflect the channel states immediately?
Is NettyConnectionManager thread safe? (get method never return a closed connection more than one time).
Is there a better way doing such reconnect job?
A netty Channel can be open and not connected so your NettyConnection.isConnected is not correct. See this.
and 3.


It's pointless to write such code in scala. What you need is just a scala lazy val. Try this:

class NettyConnectionManager(val config: NettyConfig) extends ConnectionManager {
  lazy val connection = {
    val newConnection = new NettyConnection(config)
    newConnection.connect()
    newConnection
  }

  def close = connection.close
  def connected = connection.isConnected
}


scala lazy vals already use double check locking to initial the val only once, you don't have to do all the primitive stuff yourself as in NettyConnectionManager or NettyConnection. Next time you think about using var of Option, use lazy val instead. See SIP-20 to know more about how scala community is trying to improving this strategy.

And, wrapping a Channel in two classes like NettyConnection and NettyConnectionManager is also bad design decision. You gain little and add much unnecessary complexity.