0

我正在使用 jberet-ui(从https://github.com/jberet/jberet-ui.git的主分支构建)嵌入到与 jberet-rest-api、jberet-rest-common、jberet-schedule-executor 的阴影战争中和 jberet-schedule-timer 版本 1.4.0.Final 作为依赖项。

当我尝试创建基于日历的计划时,我从 api 收到 400 响应,错误响应并显示消息“无法为作业安排作业执行:ag-insurance-import-lisa-subscriptions。” 显示在页面底部,以及文本

Unrecognized field "hour" (class javax.ejb.ScheduleExpression), not marked as ignorable

在响应正文中。

这个 javax.ejb.ScheduleExpression 应该如何反序列化?它看起来不像是一个简单的 pojo,可以简单地绑定到 json 模型,而且我在 jberet-rest* 项目中找不到任何反序列化器。我应该提供自己的 json (de)serializers 吗?

4

2 回答 2

0

要解决此问题,目前,以下工作。

战争依赖:

     <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>8.0.1</version>
        <scope>provided</scope>
    </dependency>

    <dependency>
        <groupId>org.jberet</groupId>
        <artifactId>jberet-rest-commons</artifactId>
        <version>1.4.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jberet</groupId>
        <artifactId>jberet-schedule-executor</artifactId>
        <version>1.4.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jberet</groupId>
        <artifactId>jberet-schedule-timer</artifactId>
        <version>1.4.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.jberet</groupId>
        <artifactId>jberet-rest-api</artifactId>
        <version>1.4.0.Final</version>
    </dependency>

然后创建一个 json 反序列化器:

 public class ScheduleExpressionDeserializer extends JsonDeserializer<ScheduleExpression> {

    private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE;

    @Override
    public ScheduleExpression deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        ScheduleExpression scheduleExpression = new ScheduleExpression();

        // Payload example:
        // {"year":"1","month":"2","dayOfMonth":"3","dayOfWeek":"4",
        // "hour":"5","minute":"6","start":"2020-05-04T08:10:00.000Z",
        // "end":"2020-06-05T08:12:00.000Z","timezone":"Africa/Blantyre"}
        TreeNode treeNode = jsonParser.getCodec().readTree(jsonParser);

        Optional.ofNullable(treeNode.get("year"))
                .flatMap(this::parseIntegerNode)
                .ifPresent(scheduleExpression::year);

        Optional.ofNullable(treeNode.get("month"))
                .flatMap(this::parseIntegerNode)
                .ifPresent(scheduleExpression::month);

        Optional.ofNullable(treeNode.get("dayOfMonth"))
                .flatMap(this::parseIntegerNode)
                .ifPresent(scheduleExpression::dayOfMonth);

        Optional.ofNullable(treeNode.get("dayOfWeek"))
                .flatMap(this::parseIntegerNode)
                .ifPresent(scheduleExpression::dayOfWeek);

        Optional.ofNullable(treeNode.get("hour"))
                .flatMap(this::parseIntegerNode)
                .ifPresent(scheduleExpression::hour);

        Optional.ofNullable(treeNode.get("minute"))
                .flatMap(this::parseIntegerNode)
                .ifPresent(scheduleExpression::minute);


        Optional.ofNullable(treeNode.get("start"))
                .flatMap(this::parseDateTimeNode)
                .ifPresent(scheduleExpression::start);

        Optional.ofNullable(treeNode.get("end"))
                .flatMap(this::parseDateTimeNode)
                .ifPresent(scheduleExpression::end);

        Optional.ofNullable(treeNode.get("timezone"))
                .map(TreeNode::asToken)
                .map(JsonToken::asString)
                .ifPresent(scheduleExpression::timezone);

        return scheduleExpression;
    }

    private Optional<Integer> parseIntegerNode(TreeNode node) {
        if (node instanceof TextNode) {
            TextNode textNode = (TextNode) node;
            return Optional.of(textNode)
                    .map(TextNode::asInt);
        } else {
            return Optional.empty();
        }
    }


    private Optional<Date> parseDateTimeNode(TreeNode node) {
        if (node instanceof TextNode) {
            TextNode textNode = (TextNode) node;
            return Optional.of(textNode)
                    .map(TextNode::asText)
                    .map(s -> OffsetDateTime.parse(s, dateTimeFormatter))
                    .map(OffsetDateTime::toInstant)
                    .map(Date::from);
        } else {
            return Optional.empty();
        }
    }
}

并在 jax-rs 提供的 ObjectMapper 中使用它:

@Provider
public class JacksonMapperResolver implements ContextResolver<ObjectMapper> {

    @Override
    public ObjectMapper getContext(Class<?> type) {
        ObjectMapper mapper = new ObjectMapper();

        SimpleModule simpleModule = new SimpleModule("Custom deserializers");
        simpleModule.addDeserializer(ScheduleExpression.class, new ScheduleExpressionDeserializer());
        mapper.registerModule(simpleModule);
        return mapper;
    }
}
于 2020-05-22T13:33:29.677 回答
0

有一个带有 jberet-ui 的示例批处理应用程序 ( scheduleTimer ),您可能想查看它。

我以前从未见过这个错误。它可能与不同杰克逊库版本(用于 json 绑定)的一些更改有关。您可能想尝试上述 jberet 示例项目中使用的 jackson-* 依赖项的确切版本。

有问题的代码行在 JobScheduleConfig类中。

你能分享 WildFly server.log 中的错误详细信息和堆栈跟踪吗?

于 2020-05-22T13:03:42.527 回答