private RestDataProvider<JobNodeAndInfo, JobNodeAndInfoListResponse> buildDataProvider(
            final EventBus eventBus,
            final PagerViewWithHeading view,
            final RestFactory restFactory) {

        //noinspection Convert2Diamond
        return new RestDataProvider<JobNodeAndInfo, JobNodeAndInfoListResponse>(eventBus) {
            @Override
            protected void exec(final Range range,
                                final Consumer<JobNodeAndInfoListResponse> dataConsumer,
                                final RestErrorHandler errorHandler) {
                CriteriaUtil.setSortList(findJobNodeCriteria, dataGrid.getColumnSortList());

                // ON is show enabled only, OFF is show all states
                findJobNodeCriteria.setJobNodeEnabled(showEnabledToggleBtn.isOn()
                        ? true
                        : null);
                restFactory
                        .create(JOB_NODE_RESOURCE)
                        .method(res ->
                                res.find(findJobNodeCriteria))
                        .onSuccess(dataConsumer)
                        .onFailure(errorHandler)
                        .taskMonitorFactory(view)
                        .exec();
            }

            @Override
            protected void changeData(final JobNodeAndInfoListResponse data) {
                // Ping each node to get its jobNodeInfo, which is held in-memory by the node
                data.getValues().forEach(jobNodeAndInfo -> {
                    // The node that gave us the data should have also given us the info for
                    // its jobNodes, so no need to hit that node again
                    if (jobNodeAndInfo.getJobNodeInfo() == null) {
                        restFactory
                                .create(JOB_NODE_RESOURCE)
                                .method(res ->
                                        res.info(jobNodeAndInfo.getJobName(), jobNodeAndInfo.getNodeName()))
                                .onSuccess(info -> {
                                    jobNodeAndInfo.setJobNodeInfo(info);
                                    scheduleDataGridRedraw();
                                })
                                .onFailure(throwable -> {
                                    jobNodeAndInfo.clearJobNodeInfo();
                                    scheduleDataGridRedraw();
                                })
                                .taskMonitorFactory(getView())
                                .exec();
                    }
                });
                super.changeData(data);
            }
        };
    }
Bottom pane of JobPresenter (Jobs tab). Lists jobNodes for a single parent job.
stroom-core-client/src/main/java/stroom/job/client/presenter/JobNodeListPresenter.java