我们在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)
但是,SimpleTrigger
从Trigger
延伸。
即使我像这样定义Set和Map的类型:
val jobsMap =
jobDatas
.map(data => data.jobDetail -> Set[SimpleTrigger](data.trigger.asInstanceOf[SimpleTrigger]).asJava)
.toMap[JobDetail, java.util.Set[SimpleTrigger]]
.asJava
没有帮助。
进行此类转换的正确方法是什么?
答案 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]]]