Search code examples
javajqueryajaxjerseycomet

Cant access success function when call recursive ajax


I'm building a system which has push notification feature and use Jersey to create API.
I read an article about comet approach and end up with the following code:

Index.js

function checkExamNotification() {
    $.ajax({
        url: contextPath + '/api/notification/checkExamNotification',
        type: 'get',
        data: {
            accountId: accountId,
            sessionId: sessionId
        },
        success: function (res) {
            console.log("success");
            displayNumberOfNotification();
            checkExamNotification();
        },
        error: function (jqXHR, textStatus, errorThrown) {
            if (textStatus === "timeout") {
                checkExamNotification();
            }
        }
    });
}

$(document).ready(function () {
    $.ajaxSetup({
        timeout: 1000*60*3
    });
    checkExamNotification();
});

Check exam notification API

@GET
@Path("/checkExamNotification")
public Response checkExamNotification(@QueryParam("accountId") int accountId, @QueryParam("sessionId") String sessionId) throws InterruptedException {
    if (memCachedClient.checkSession(sessionId, accountId)) {
        while (!examNotificationQueue.hasItems()) {
            Thread.sleep(5000);
        }

        ExamNotificationQueueItemModel examNotificationQueueItemModel = examNotificationQueue.dequeue();
        if (examNotificationQueueItemModel.getAccountId() == accountId) {
            LOGGER.info("[START] Check exam notification API");
            LOGGER.info("Account ID: " + accountId);
            LOGGER.info("Get notification with exam ID: " + examNotificationQueueItemModel.getExamId());

            ExamEntity exam = examDAO.findById(examNotificationQueueItemModel.getExamId());
            NotificationEntity notification = notificationDAO.findByExamId(exam.getExamid());
            notification.setSend(1);
            notificationDAO.getEntityManager().getTransaction().begin();
            notificationDAO.update(notification);
            notificationDAO.getEntityManager().getTransaction().commit();

            LOGGER.info("[END]");
            String result = gson.toJson(examNotificationQueueItemModel);
            return Response.status(200).entity(result).build();
        } else {
            examNotificationQueue.enqueue(examNotificationQueueItemModel);
            Thread.sleep(5000);
            checkExamNotification(accountId, sessionId);
        }

    }
    return Response.status(200).entity(gson.toJson("timeout")).build();
}

From my debug, the API did finish return but the success event SOMETIMES didn't fire.
Yes, sometimes console log success but sometimes it doesn't.
Can anybody explain to me this case?
Thanks in advance. Any help would be appreciated.


Solution

  • Ok after following @peeskillet comment. Here is my finally code.

    Check exam notification API

    @GET
    @Produces(SseFeature.SERVER_SENT_EVENTS)
    @Path("/checkExamNotification")
    public EventOutput checkExamNotification(@QueryParam("accountId") final int accountId, @QueryParam("sessionId") final String sessionId) {
        final EventOutput eventOutput = new EventOutput();
        if (memCachedClient.checkSession(sessionId, accountId)) {
            new Thread(new Runnable() {
                public void run() {
                    try {
                        if (examNotificationQueue.hasItems()) {
                            ExamNotificationQueueItemModel examNotificationQueueItemModel = examNotificationQueue.dequeue();
                            if (examNotificationQueueItemModel.getAccountId() == accountId) {
                                LOGGER.info("[START] Check exam notification API");
                                LOGGER.info("Account ID: " + accountId);
                                LOGGER.info("Get notification with exam ID: " + examNotificationQueueItemModel.getExamName());
                                String result = gson.toJson(examNotificationQueueItemModel);
                                final OutboundEvent.Builder eventBuilder
                                        = new OutboundEvent.Builder();
                                eventBuilder.data(result);
                                final OutboundEvent event = eventBuilder.build();
                                eventOutput.write(event);
                                LOGGER.info("[END]");
                            } else {
                                examNotificationQueue.enqueue(examNotificationQueueItemModel);
                            }
                        }
    
                    } catch (IOException e) {
                        throw new RuntimeException(
                                "Error when writing the event.", e);
                    } finally {
                        try {
                            eventOutput.close();
                        } catch (IOException ioClose) {
                            throw new RuntimeException(
                                    "Error when closing the event output.", ioClose);
                        }
                    }
                }
            }).start();
        }
    
        return eventOutput;
    }
    

    Index.js

    function checkExamNotification() {
        var url = contextPath + '/api/notification/checkExamNotification?accountId=' + accountId + '&sessionId=' + sessionId;
        var source = new EventSource(url);
        source.onmessage = function (event) {
            displayNumberOfNotification();
        };
    }