{"record":{"id":"bc137b9cfed7574a","repo":"jeecgboot/JeecgBoot","slug":"error-bc137b","errorCode":null,"errorMessage":"发送消息失败,消息内容为空！","messagePattern":"发送消息失败,消息内容为空！","errorType":"exception","errorClass":"JeecgBootException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysBaseApiImpl.java","lineNumber":1727,"sourceCode":"\t@Override\n\tpublic void sendTemplateMessage(MessageDTO message) {\n\t\tString messageType = message.getType();\n\t\tlog.debug(\" 【万能通用】推送消息 messageType = {}\", messageType);\n\t\t// 代码逻辑说明: 将模板解析代码移至消息发送, 而不是调用的地方\n\t\tString templateCode = message.getTemplateCode();\n\t\tif(oConvertUtils.isNotEmpty(templateCode)){\n\t\t\tSysMessageTemplate templateEntity = getTemplateEntity(templateCode);\n\t\t\tboolean isMarkdown = CommonConstant.MSG_TEMPLATE_TYPE_MD.equals(templateEntity.getTemplateType());\n\t\t\tString content = templateEntity.getTemplateContent();\n\t\t\tif(oConvertUtils.isNotEmpty(content) && null!=message.getData()){\n\t\t\t\tcontent = FreemarkerParseFactory.parseTemplateContent(content, message.getData(), isMarkdown);\n\t\t\t}\n\t\t\tmessage.setIsMarkdown(isMarkdown);\n\t\t\tmessage.setContent(content);\n\t\t}\n\t\tif(oConvertUtils.isEmpty(message.getContent())){\n\t\t\tlog.error(\"发送消息失败,消息内容为空！\");\n\t\t\tthrow new JeecgBootException(\"发送消息失败,消息内容为空！\");\n\t\t}\n\n\t\tif(MessageTypeEnum.XT.getType().equals(messageType)){\n\t\t\tif (message.isMarkdown()) {\n\t\t\t\t// 系统消息要解析Markdown\n\t\t\t\tmessage.setContent(HTMLUtils.parseMarkdown(message.getContent()));\n\t\t\t}\n\t\t\tsystemSendMsgHandle.sendMessage(message);\n\t\t}else if(MessageTypeEnum.YJ.getType().equals(messageType)){\n\t\t\tif (message.isMarkdown()) {\n\t\t\t\t// 邮件消息要解析Markdown\n\t\t\t\tmessage.setContent(HTMLUtils.parseMarkdown(message.getContent()));\n\t\t\t}\n\t\t\t// 代码逻辑说明: 【QQYUN-8523】敲敲云发邮件通知，不稳定---\n\t\t\tif(message.getIsTimeJob() != null && message.getIsTimeJob()){\n\t\t\t\temailSendMsgHandle.sendEmailMessage(message);\n\t\t\t}else{\n\t\t\t\temailSendMsgHandle.sendMessage(message);","sourceCodeStart":1709,"sourceCodeEnd":1745,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysBaseApiImpl.java#L1709-L1745","documentation":"After template selection, Freemarker parsing, and content assembly, sendMessage aborts if message.getContent() is still empty. This prevents blank notifications and surfaces misconfiguration: either no template was chosen and no raw content set, or the chosen template's content is empty / produced nothing after parsing.","triggerScenarios":"templateCode set but template.template_content is blank; Freemarker produced an empty string because required placeholders had null values; no templateCode and message content never assigned; message.getData() is null where the template references ${} keys.","commonSituations":"Template row exists but its content column is empty; the data DTO carries null fields referenced by placeholders; messageType path was set but content population was skipped.","solutions":["Confirm the selected template's template_content is non-empty in sys_sms_template.","Ensure message.getData() supplies every placeholder referenced by the template.","If sending without a template, set message.setContent(...) explicitly before sendMessage.","Log the templateCode and rendered content length to pinpoint the empty source."],"exampleFix":"// before\nMessage m = ...; // template chosen but content blank\nsysBaseApi.sendMessage(m); // -> 发送消息失败,消息内容为空！\n// after\nif (oConvertUtils.isEmpty(m.getContent())) {\n    log.warn(\"消息内容为空, templateCode={}, data={}\", m.getTemplateCode(), m.getData());\n    return; // skip send, or set a default body\n}\nsysBaseApi.sendMessage(m);","handlingStrategy":"validation","validationCode":"// Ensure content is non-empty before sending.\nif (oConvertUtils.isEmpty(message.getContent())) {\n    log.warn(\"消息内容为空, templateCode={}, data={}\", message.getTemplateCode(), message.getData());\n    return; // skip send\n}","typeGuard":"public boolean hasSendableContent(MessageDTO m) {\n    return oConvertUtils.isNotEmpty(m.getContent());\n}","tryCatchPattern":"try {\n    sysBaseApi.sendMessage(message);\n} catch (JeecgBootException e) {\n    if (\"发送消息失败,消息内容为空！\".equals(e.getMessage())) {\n        log.error(\"消息发送中止: 内容为空, templateCode={}\", message.getTemplateCode());\n        return; // don't propagate blank-message errors to the user flow\n    }\n    throw e;\n}","preventionTips":["Validate template_content is non-empty when creating templates in the UI.","Ensure data DTOs supply every placeholder referenced by the template.","Log templateCode and rendered length to diagnose empty renders."],"tags":["message","template","freemarker","validation"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}