How can I sync due date between ServiceNow and Jira?

Originally asked by Robert Horan on 25 November 2021 (original question)


I am having serious issues trying to sync dates. SN has a field called due_date that we are trying to sync to due date in Jira. I am getting a cannot cast object error.

Error Detail Message:

Cannot cast object ‘01/03/2022 16:20:59’ with class ‘java.lang.String’ to class ‘java.util.Date’

Error line: 34

Error Stack Trace

com.exalate.api.exception.script.ScriptException: Cannot cast object ‘01/03/2022 16:20:59’ with class ‘java.lang.String’ to class ‘java.util.Date’ at com.exalate.error.services.ScriptExceptionCategoryService.categorizeProcessorAndIssueTrackerExceptionsIntoScriptExceptions(ScriptExceptionCategoryService.scala:40) at com.exalate.processor.ExalateProcessor.executeProcessor(ExalateProcessor.java:57) at com.exalate.replication.services.processor.CreateReplicaProcessor.$anonfun$executeScriptRules$2(CreateReplicaProcessor.scala:118) at scala.util.Try$.apply(Try.scala:213) at com.exalate.replication.services.processor.CreateReplicaProcessor.executeScriptRules(CreateReplicaProcessor.scala:116) at com.exalate.replication.services.processor.CreateReplicaProcessor.$anonfun$createHubReplica$2(CreateReplicaProcessor.scala:68) at scala.concurrent.Future.$anonfun$flatMap$1(Future.scala:307) at scala.concurrent.impl.Promise.$anonfun$transformWith$1(Promise.scala:41) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64) at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:56) at akka.dispatch.BatchingExecutor$BlockableBatch.$anonfun$run$1(BatchingExecutor.scala:93) at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23) at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:85) at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:93) at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:48) at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(ForkJoinExecutorConfigurator.scala:48) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020) at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656) at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183) Caused by: javax.script.ScriptException: javax.script.ScriptException: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object ‘01/03/2022 16:20:59’ with class ‘java.lang.String’ to class ‘java.util.Date’ at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:158) at java.scripting/javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264) at com.exalate.processor.ExalateProcessor.execute(ExalateProcessor.java:98) at com.exalate.processor.ExalateProcessor.executeProcessor(ExalateProcessor.java:55) … 19 more Caused by: javax.script.ScriptException: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object ‘01/03/2022 16:20:59’ with class ‘java.lang.String’ to class ‘java.util.Date’ at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:320) at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:155) … 22 more Caused by: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object ‘01/03/2022 16:20:59’ with class ‘java.lang.String’ to class ‘java.util.Date’ at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnSAM(DefaultTypeTransformation.java:415) at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.continueCastOnNumber(DefaultTypeTransformation.java:329) at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.castToType(DefaultTypeTransformation.java:243) at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:2744) at groovy.lang.MetaClassImpl.setProperty(MetaClassImpl.java:3809) at org.codehaus.groovy.runtime.InvokerHelper.setProperty(InvokerHelper.java:217) at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.setProperty(ScriptBytecodeAdapter.java:496) at Script320.run(Script320.groovy:34) at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:317) … 23 more


Comments:

Robert Horan commented on 25 November 2021

This was originally raised via support but I was asked to post here:

The error you are receiving seems to be a configuration problem we use a community site at community.exalate.com to discuss the configuration of the synchronization.

Kindly raise the question there, we will be responding shortly, the advantage is that other people can benefit from the effort.

Matias Vivas commented on 25 November 2021

i have the same with issue.created=replica.created. From Zendesk to Jira Cloud

Daniel Carvajal commented on 25 November 2021

Hi Robert Horan

What the error is stating is that the object being tried to pass to into the field is a String, while the field is expecting a Date format data, you can make this conversion the following way:

https://docs.idalko.com/exalate/x/BwCwB

Hope this is helpful,

Cheers,

Daniel

Robert Horan commented on 29 November 2021

Hi Daniel,

I have that document but it didn’t help. I don’t know enough about this tool to make that work. What needs to be added to the incoming/outgoing sync for ServiceNow? Jira?

According to https://docs.idalko.com/exalate/display/ED/How+to+synchronize+a+Due+Date+field+in+Jira+Cloud

Outgoing sync

To send the Due date use the code below

replica.due = issue.due

Incoming sync

To apply the received Due Date value on your side add the code below

issue.due = replica.due

It’s not clear to me how or even where this fits in. There could be multiple date fields, not to mention date and time fields.

Answer by Daniel Carvajal on 30 November 2021

Hi Robert Horan

The code mentioned in the document can be set at the beginning of your Jira’s Incoming Script(line 1) since what its gonna do is format the date to the expected data type.

We can see that the date format being received is a bit different from the one shown in the documentation example, the error shows the format as: ‘01/03/2022 16:20:59’, therefore we need to change the datePattern to match the received value:

from:

def datePattern = "yyyy-MM-dd HH:mm:ss.S"

to:

def datePattern = "dd-MM-yyyy HH:mm:ss.S"

Then we add the variable that actually contains the date which is the “replica.due” to the parser:

import java.text.SimpleDateFormat;
import java.text.DateFormat;
   
// define the desired date/time format
def datePattern = "dd-MM-yyyy HH:mm:ss.S";

        DateFormat formatter = new SimpleDateFormat(datePattern);

        date = formatter.parse(replica.due);

And then we can take the created variable that contains the formatted date and use it to fill the issue.due, this part can go anywhere as long as its after the code above:

issue.due = date

Since you mentioned there can be multiple date fields you can reuse the parser simply by changing the replica being applied so, let’s say you are sending from SNOW the following fields:

replica.due = issue.due
replica.veryDue = issue.veryDue
replica.reallyDueNow = issue.reallyDueNow

then in Jira incoming you could have them as:

date = formatter.parse(replica.due);
dateVeryDue = formatter.parse(replica.veryDue);
dateReallyDueNow = formatter.parse(replica.reallyDueNow);

...

issue.due = date
issue.veryDue = dateVeryDue
issue.reallyDueNow = dateReallyDueNow

So as you can see you can use the parser in your code as needed with that structure:

“variableName = formatter.parse(replica.ContainingTheTimeOrDate);”

I hope this information is helpful.

Cheers,

Daniel