All Downloads are FREE. Search and download functionalities are using the official Maven repository.

akkeeper.api.CommonApi.scala Maven / Gradle / Ivy

There is a newer version: 0.3.3
Show newest version
/*
 * Copyright 2017-2018 Iaroslav Zeigerman
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package akkeeper.api

import akkeeper.common._
import spray.json._

/** The base interface for all messages that include unique request ID. */
trait WithRequestId {
  def requestId: RequestId
}

/** A response message that represents an arbitrary general error.
  * It's usually used when some unexpected or unhandled error occurs.
  *
  * @param requestId the ID of the original request that caused an operation
  *                  that failed.
  * @param cause the reason of the failure.
  */
case class OperationFailed(requestId: RequestId, cause: Throwable) extends WithRequestId

/** JSON (de)serialization for the Common API requests and responses. */
trait CommonApiJsonProtocol extends DefaultJsonProtocol with RequestIdJsonProtocol {

  implicit val operationFailedWriter = new RootJsonWriter[OperationFailed] {
    override def write(obj: OperationFailed): JsValue = {
      val requestIdField = obj.requestId.toJson
      val messageField = JsString(obj.cause.getMessage)
      val stackTraceField = JsArray(
        obj.cause.getStackTrace.map(s => JsString(s.toString)): _*
      )
      JsObject(
        "requestId" -> requestIdField,
        "message" -> messageField,
        "stackTrace" -> stackTraceField
      )
    }
  }
}

object CommonApiJsonProtocol extends CommonApiJsonProtocol

class AutoRequestIdFormat[T <: WithRequestId](original: JsonFormat[T])
  extends RootJsonFormat[T] {

  import RequestIdJsonProtocol._

  override def read(json: JsValue): T = {
    val jsObject = json.asJsObject
    val fields = jsObject.fields
    val updatedJsObject =
      if (!fields.contains("requestId")) {
        jsObject.copy(fields + ("requestId" -> RequestId().toJson))
      } else {
        jsObject
      }
    original.read(updatedJsObject)
  }

  override def write(obj: T): JsValue = original.write(obj)
}

object AutoRequestIdFormat {
  def apply[T <: WithRequestId](original: JsonFormat[T]): RootJsonFormat[T] = {
    new AutoRequestIdFormat(original)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy