如何正确地将对象从scala转换为java?

时间:2018-02-23 18:50:29

标签: java scala quartz-scheduler

我们在Scala中开发,在我们的应用程序中,我们使用Quartz作为调度程序。

目前正在开发一个批量调度事物的函数,我遇到了将scala映射转换为java的问题,因此Quartz会接受它。

该功能如下所示:

private def rescheduleJobs(infos: List[TaskDueNotificationInfo]): Unit = {

    val jobDatas = infos.foldLeft(List.empty[TaskDueNotificationJobData]) { (datas, info) =>
      val taskIdStr = info.task.id.uuid.toString

      val triggerKey = new TriggerKey(taskIdStr, Group.TaskDueNotification.toString)
      val jobKey = new JobKey(taskIdStr, Group.TaskDueNotification.toString)
      val jobDetail =
        newJob(classOf[TaskDueNotificationJob]).withIdentity(jobKey).usingJobData("taskId", taskIdStr).build()

      val sysTz = DateTimeZone.getDefault
      val sysStartTime = info.task.dueDate match {
        case Some(dueDate) => new DateTime(dueDate, info.timeZone).toDateTime(sysTz)
        case None          => throw UnexpectedException("no due date set")
      }

      val triggerBuilder = newTrigger().withIdentity(triggerKey).forJob(jobKey).startAt(sysStartTime.toDate)
      val trigger = triggerBuilder.build()

      datas :+ TaskDueNotificationJobData(jobDetail, trigger)
    }

    val jobsMap = jobDatas.map(data => data.jobDetail -> Set(data.trigger).asJava).toMap.asJava

    Try {

      jobScheduler.scheduler.scheduleJobs(jobsMap, true)

    } match {

      case Success(_) => // All good

      case Failure(e) => logger.error(e.getMessage)

    }
  }

当我们用Date scheduleJob(JobDetail jobDetail, Trigger trigger)逐个安排时,我们最初创建java对象,一切正常。 在上面的代码中,我收到以下错误:

[error] /Users/ShurikAg/ProcessStreet/dev/process-street/app/scheduling/schedulers/TaskDueNotificationScheduler.scala:99: type mismatch;
[error]  found   : java.util.Map[org.quartz.JobDetail,java.util.Set[org.quartz.Trigger]]
[error]  required: java.util.Map[org.quartz.JobDetail,java.util.Set[_ <: org.quartz.Trigger]]
[error] Note: java.util.Set[org.quartz.Trigger] <: java.util.Set[_ <: org.quartz.Trigger], but Java-defined trait Map is invariant in type V.
[error] You may wish to investigate a wildcard type such as `_ <: java.util.Set[_ <: org.quartz.Trigger]`. (SLS 3.2.10)
[error]       jobScheduler.scheduler.scheduleJobs(jobsMap, true)

如果我将它转换为SimpleTrigger(就是这样):

val jobsMap =
      jobDatas.map(data => data.jobDetail -> Set(data.trigger.asInstanceOf[SimpleTrigger]).asJava).toMap.asJava

错误是一样的:

[error] /Users/ShurikAg/ProcessStreet/dev/process-street/app/scheduling/schedulers/TaskDueNotificationScheduler.scala:100: type mismatch;
[error]  found   : java.util.Map[org.quartz.JobDetail,java.util.Set[org.quartz.SimpleTrigger]]
[error]  required: java.util.Map[org.quartz.JobDetail,java.util.Set[_ <: org.quartz.Trigger]]
[error] Note: java.util.Set[org.quartz.SimpleTrigger] <: java.util.Set[_ <: org.quartz.Trigger], but Java-defined trait Map is invariant in type V.
[error] You may wish to investigate a wildcard type such as `_ <: java.util.Set[_ <: org.quartz.Trigger]`. (SLS 3.2.10)
[error]       jobScheduler.scheduler.scheduleJobs(jobsMap, true)

但是,SimpleTriggerTrigger延伸。

即使我像这样定义Set和Map的类型:

val jobsMap =
      jobDatas
        .map(data => data.jobDetail -> Set[SimpleTrigger](data.trigger.asInstanceOf[SimpleTrigger]).asJava)
        .toMap[JobDetail, java.util.Set[SimpleTrigger]]
        .asJava

没有帮助。

进行此类转换的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

一个稍微好一点的替代答案,但除此之外它是最合理的事情:

jobDatas
  .map(data => data.jobDetail -> (Set(data.trigger).asJava: java.util.Set[T] forSome { type T <: Trigger }))
  .toMap
  .asJava

它使用类型归档而不是强制转换,因此如果您稍后更改代码它会更安全(类型归属如果不正确则编译,编译将会出现);这种归属的类型更简单,范围更窄。

答案 1 :(得分:0)

我想我找到了一种方法来做到这一点;只是不确定这是否是最好的。

它的唯一工作方式(在此帖https://stackoverflow.com/a/33594711/1293827之后)是:

val jobsMap =
      jobDatas
        .map(data => data.jobDetail -> Set(data.trigger).asJava)
        .toMap
        .asJava
        .asInstanceOf[java.util.Map[JobDetail, java.util.Set[_ <: Trigger]]]