Uploaded image for project: 'JIRA Service Desk Server'
  1. JIRA Service Desk Server
  2. JSDSERVER-5273

Notifications that contain only an image will break SD notification job when using Oracle database

    XMLWordPrintable

    Details

      Description

      Summary

      When running on Oracle database, JIRA Service Desk will insert NULL value to TEXT_CONTENT column of AO_4E8AE6_NOTIF_BATCH_QUEUE table when the notification in question does not contain any plain text.

      Environment

      • JIRA is running on Oracle database

      Steps to Reproduce

      1. Create a service desk project with sample data.
      2. Navigate to Project settings > Customer notifications and modify the template for "Public comment added" rule as shown below:
      3. Add a public comment which contains only an image to one of the ticket.
      4. Observing the data in AO_4E8AE6_NOTIF_BATCH_QUEUE table.

      Expected Results

      A new row with a empty string for TEXT_CONTENT column is inserted.

      Actual Results

      A new row with NULL for TEXT_CONTENT column is inserted.
      The below exception is thrown in the log file when JIRA tried to send notification :

      2017-07-18 14:58:58,666 Caesium-1-1 ERROR anonymous     [c.a.scheduler.core.JobLauncher] Scheduled job with ID 'sd.custom.notification.batch.send' failed
      java.lang.RuntimeException: no text content set
      	at com.atlassian.servicedesk.plugins.notifications.internal.dao.NotificationBatchQueueEntryBuilder.validate(NotificationBatchQueueEntryBuilder.java:111)
      	at com.atlassian.servicedesk.plugins.notifications.internal.dao.NotificationBatchQueueEntryBuilder.build(NotificationBatchQueueEntryBuilder.java:91)
      	at com.atlassian.servicedesk.plugins.notifications.internal.dao.NotificationBatchQueueDao.convertToEntry(NotificationBatchQueueDao.java:54)
      	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
      	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
      	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
      	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
      	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
      	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
      	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
      	at com.atlassian.servicedesk.plugins.notifications.internal.dao.NotificationBatchQueueDao.convertToEntries(NotificationBatchQueueDao.java:38)
      	at com.atlassian.servicedesk.plugins.notifications.internal.dao.NotificationBatchQueueDao.fetchUnsentEntries(NotificationBatchQueueDao.java:26)
      	at com.atlassian.pocketknife.internal.querydsl.DatabaseAccessorImpl.lambda$execute$0(DatabaseAccessorImpl.java:68)
      	at com.atlassian.sal.core.rdbms.DefaultTransactionalExecutor.executeInternal(DefaultTransactionalExecutor.java:91)
      	at com.atlassian.sal.core.rdbms.DefaultTransactionalExecutor$1.execute(DefaultTransactionalExecutor.java:45)
      	at com.atlassian.sal.jira.rdbms.JiraHostConnectionAccessor.lambda$borrowConnectionAndExecute$0(JiraHostConnectionAccessor.java:62)
      	at com.atlassian.jira.database.DatabaseAccessorImpl.executeQuery(DatabaseAccessorImpl.java:67)
      	... 2 filtered
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
      	at com.sun.proxy.$Proxy496.executeQuery(Unknown Source)
      	... 2 filtered
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at com.atlassian.plugin.osgi.bridge.external.HostComponentFactoryBean$DynamicServiceInvocationHandler.invoke(HostComponentFactoryBean.java:136)
      	at com.sun.proxy.$Proxy496.executeQuery(Unknown Source)
      	at com.atlassian.sal.jira.rdbms.JiraHostConnectionAccessor.borrowConnectionAndExecute(JiraHostConnectionAccessor.java:50)
      	at com.atlassian.sal.jira.rdbms.JiraHostConnectionAccessor.execute(JiraHostConnectionAccessor.java:35)
      	at com.atlassian.sal.core.rdbms.DefaultTransactionalExecutor.execute(DefaultTransactionalExecutor.java:42)
      	at com.atlassian.pocketknife.internal.querydsl.DatabaseAccessorImpl.execute(DatabaseAccessorImpl.java:66)
      	at com.atlassian.pocketknife.internal.querydsl.DatabaseAccessorImpl.runInNewTransaction(DatabaseAccessorImpl.java:37)
      	at com.atlassian.pocketknife.internal.querydsl.DatabaseAccessorImpl.run(DatabaseAccessorImpl.java:32)
      	at com.atlassian.servicedesk.plugins.notifications.internal.scheduler.NotificationBatchJobRunner.sendBatchedMails(NotificationBatchJobRunner.java:49)
      	at com.atlassian.servicedesk.plugins.notifications.internal.scheduler.NotificationBatchJobRunner.runJob(NotificationBatchJobRunner.java:41)
      	at com.atlassian.scheduler.core.JobLauncher.runJob(JobLauncher.java:153)
      	at com.atlassian.scheduler.core.JobLauncher.launchAndBuildResponse(JobLauncher.java:118)
      	at com.atlassian.scheduler.core.JobLauncher.launch(JobLauncher.java:97)
      	at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService.launchJob(CaesiumSchedulerService.java:443)
      	at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService.executeClusteredJob(CaesiumSchedulerService.java:438)
      	at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService.executeClusteredJobWithRecoveryGuard(CaesiumSchedulerService.java:462)
      	at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService.executeQueuedJob(CaesiumSchedulerService.java:390)
      	at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService$1.consume(CaesiumSchedulerService.java:285)
      	at com.atlassian.scheduler.caesium.impl.CaesiumSchedulerService$1.consume(CaesiumSchedulerService.java:282)
      	at com.atlassian.scheduler.caesium.impl.SchedulerQueueWorker.executeJob(SchedulerQueueWorker.java:65)
      	at com.atlassian.scheduler.caesium.impl.SchedulerQueueWorker.executeNextJob(SchedulerQueueWorker.java:59)
      	at com.atlassian.scheduler.caesium.impl.SchedulerQueueWorker.run(SchedulerQueueWorker.java:34)
      	at java.lang.Thread.run(Thread.java:745)
      

      Notes

      The issue cannot be reproduced on PostgreSQL database, in which two single quotes ('') are inserted to the database to represent an empty string instead of NULL.

      Workaround

      Modify the relevant notification template to include some plain text message or use the default template.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              agoldthorpe Aidan Goldthorpe
              Reporter:
              cmao Chen Mao (Inactive)
              Votes:
              4 Vote for this issue
              Watchers:
              5 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved: