Cant access success function when call recursive ajax - java

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.

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();
};
}

Related

Add an Telegram bot on Java to the group chat

I have a working Telegram bot that replies to my private messages. However, when I add it to my test chat and run the app, I get this error: 'Unexpected action from user'. I guess, it's a wrong way to create a bot for group chat, and maybe I shouldn't use TelegramLongPollingBot. Can you please help me to understand, how to create a group chat bot?
The Bot's class:
public class MessageCalculator extends TelegramLongPollingBot {
private PropertiesFileReader propertiesFileReader = new PropertiesFileReader();
private Properties prop;
{
try {
prop = propertiesFileReader.readPropertiesFile("src/main/resources/config.properties");
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
}
private static final Logger log = LoggerFactory.getLogger(Main.class);
private int messageCount = 0;
#Override
public String getBotUsername() {
return prop.getProperty("telegram.bot.username");
}
#Override
public String getBotToken() {
return prop.getProperty("telegram.bot.token");
}
#Override
public void onUpdateReceived(Update update) {
if (update.hasMessage() && update.getMessage().hasText()) {
String textFromUser = update.getMessage().getText();
Long userId = update.getMessage().getChatId();
String userFirstName = update.getMessage().getFrom().getFirstName();
log.info("[{}, {}] : {}", userId, userFirstName, textFromUser);
messageCount++;
SendMessage sendMessage = SendMessage.builder()
.chatId(userId.toString())
.text("Hello, " + userFirstName + "! Thank you for the message #" + messageCount ": " + textFromUser)
.build();
try {
this.sendApiMethod(sendMessage);
} catch (TelegramApiException e) {
log.error("Sending message error:\t", e);
}
} else {
//And I get this error message:
log.warn("Unexpected action from user");
}
}
}
I expect to create a chat bot that can count messages from each user later.

How do I get EventSource.onmessage to work?

How do I get EventSource.onmessage to work?
Here is my subscribe and pushevent code:
public SseEmitter subscribe() throws Exception {
SseEmitter emitter = new SseEmitter(1800000L);
emitters.add(emitter);
emitter.onCompletion(() -> {
synchronized (emitters) {
emitters.remove(emitter);
}
});
emitter.onTimeout(() -> {
emitter.complete();
emitters.remove(emitter);
});
return emitter;
}
#Async
public void pushEventMap(Map<String, Object> pushMap) throws IOException {
List<SseEmitter> deadEmitters = new ArrayList<>();
HashMap<String,Object> map = (HashMap<String,Object>) pushMap;
emitters.forEach(emitter -> {
try {
emitter.send(SseEmitter.event().name("myEvent").data(map));
} catch (Exception e) {
emitter.completeWithError(e);
logger_error.error("pushEvent Exception:" + e);
deadEmitters.add(emitter);
}
});
emitters.removeAll(deadEmitters);
}
The controller for the above service is:
#RequestMapping(value = "/subscribe", produces = "text/event-stream")
public ResponseEntity<SseEmitter> subscribe() throws Exception {
final SseEmitter emitter = eventService.subscribe();
return new ResponseEntity<>(emitter, HttpStatus.OK);
}
#RequestMapping(value = "/publish")
public void publish() throws IOException {
eventService.pushEventMap(pushMap);
}
I want the client to receive the data of event push through js.
const eventInit = () => {
console.log("eventInit called");
const url = 'http://localhost:8080/itf/subscribe';
const eventSource = new EventSource(url);
var httpRequest = new XMLHttpRequest();
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('===');
console.log(data);
}
eventSource.onopen = (event) => {
console.log('sse open');
console.log(event);
}
eventSource.onerror = (event) => {
if (event.readyState == EventSource.CLOSED) {
console.log('sse close');
} else {
console.log("onerror", e);
}
}
}
In this state, if I send event-generating data through postman, sse open appears on the console.
However, the result of the event is not displayed.
If I directly access /itf/subscribe through the url, the result of the event is displayed on the screen. However, I am not receiving the result of the event through event.onmessage.
What I want is to raise an event, and then receive the result of the event through the onmessage function.
I am wondering how can I get the result of the event.
best regards
There is no issue with code, the actual issue is when I am writing response to client my response message should look like as below.
PrintWriter out = response.write("data: message"+value+"\n\n");
out.flush(); //don't forget to flush
In my code I was missing the last part "\n\n" in response object so source.onmessage(datalist) in javascript didn't get hit.
eventSource.addEventListener('myEvent', function (event) {
console.log(event);
const data = JSON.parse(event.data);
console.log('addEventListener');
console.log(data);
// console.log(data.siteCode);
eventEffect(data);
}, false);
this is normally work!

RequestParams params.put method doesn't receive integer

I'm using Rest service to get a list of States of a Country (countryid) from database. The service runs well in Tomcat but it doesn't run in Android. Below is the code to invoke the Rest service. The params.put("countryid",countryID) method doesn't receive integer. Could you please help me over come this issue?
public void getDataForStateSpinner(){
//new StateSpinnerAsync().execute();
System.out.println("getDataForStateSpinner(), spnCountry adapter: " + spnCountry);
System.out.println("spnCountry.getSelectedItem(): " + spnCountry.getSelectedItem());
if (spnCountry.getSelectedItem()!=null){
System.out.println("getDataForStateSpinner(), spnCountry adapter isn't empty");
final Country country = (Country) spnCountry.getSelectedItem();
int countryID = country.getCountryID();
RequestParams params = new RequestParams();
if (countryID>=0){
params.put("countryid", countryID);
invokeWS_State(params);
} else{
Toast.makeText(mParent.get(), "Can not get CountryID", Toast.LENGTH_LONG).show();
}
}
}
public void invokeWS_State(RequestParams params){
System.out.println("Inside invokeWS_State");
AsyncHttpClient client = new AsyncHttpClient();
System.out.println("Inside invokeWS_State, client: " + client);
System.out.println("Inside invokeWS_State onSuccess, params: " + params);
client.get(stateURL, params, new AsyncHttpResponseHandler(){
#Override
public void onSuccess(String respond){
try{
System.out.println("Inside invokeWS_State onSuccess, stateURL: " + stateURL);
System.out.println("Inside invokeWS_State onSuccess, respond:" + respond);
JSONArray jsonArr = new JSONArray(respond);
//JSONObject jsonObject = jsonArr.getJSONObject(0);
System.out.println("Inside invokeWS_State onSuccess jsonArr:" + jsonArr);
String stateList = jsonArr.toString();
System.out.println("Inside invokeWS_State onSuccess stateList:" + stateList);
states = (ArrayList<State>) fromJasonToJava_State(stateList);
for (State state : states) {
System.out.println("State id: " + state.getStateID() + " name: " + state.getStateName());
}
spnStateAdapter = new ArrayAdapter<State>(mParent.get(), android.R.layout.simple_spinner_dropdown_item, states);
spnStateAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spnState.setAdapter(spnStateAdapter);
} catch (JSONException e){
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onFailure(int statusCode, Throwable error, String content){
String resultString = null;
if (statusCode == 404){
resultString = "Requested resource not found";
Toast.makeText(mParent.get(), resultString, Toast.LENGTH_LONG).show();
} else if (statusCode == 500) {
resultString = "Something went wrong at server end!";
Toast.makeText(mParent.get(), resultString, Toast.LENGTH_LONG).show();
} else {
resultString = "Unexpected Error occcured! [Most common Error: Device might not be connected to Internet or remote server is not up and running]";
Toast.makeText(mParent.get(), resultString, Toast.LENGTH_LONG).show();
}
}
});
}
And below is the Rest service which runs well in Tomcat:
#Path("/State")
public class StatesResource {
#GET
#Path("/GetStates")
#Produces(MediaType.APPLICATION_JSON)
//http://localhost:8080/com.fms.FMSRestfulWS/State/GetStates?countryid=1
public String getStates(#DefaultValue("1") #QueryParam("countryid") int countryID){
String states = null;
try{
ArrayList<State> feedData = null;
StateLoading stateLoading = new StateLoading();
feedData = stateLoading.getAllStatesForCountry(countryID);
Gson gson = new Gson();
states = gson.toJson(feedData);
}catch (Exception e){
System.out.println("System Error " + e);
}
return states;
}
}
Do only one change, it will work perfect.
params.put("countryid", ""+countryID);

ElasticSearch index exists not working / reliable

I am writing a simple Java wrapper around ElasticSearch's admin client. To test it I have a main method that first checks if an index exists (IndicesExistsRequest), if so deletes it (DeleteIndexRequest), and creates the index again. See code below. Yet I consistently get an IndexAlreadyExistsException.
By the way I am trying to get a client for the node that you start from the command prompt (by simply typing "elastic search"). I have tried every combination of methods on nodeBuilder's fluent interface, but I can't seem to get one.
public static void main(String[] args) {
ElasticSearchJavaClient esjc = new ElasticSearchJavaClient("nda");
if (esjc.indexExists()) {
esjc.deleteIndex();
}
esjc.createIndex();
URL url = SchemaCreator.class.getResource("/elasticsearch/specimen.type.json");
String mappings = FileUtil.getContents(url);
esjc.createType("specimen", mappings);
}
final Client esClient;
final IndicesAdminClient adminClient;
final String indexName;
public ElasticSearchJavaClient(String indexName) {
this.indexName = indexName;
esClient = nodeBuilder().clusterName("elasticsearch").client(true).node().client();
adminClient = esClient.admin().indices();
}
public boolean deleteIndex() {
logger.info("Deleting index " + indexName);
DeleteIndexRequest request = new DeleteIndexRequest(indexName);
try {
DeleteIndexResponse response = adminClient.delete(request).actionGet();
if (!response.isAcknowledged()) {
throw new Exception("Failed to delete index " + indexName);
}
logger.info("Index deleted");
return true;
} catch (IndexMissingException e) {
logger.info("No such index: " + indexName);
return false;
}
}
public boolean indexExists() {
logger.info(String.format("Verifying existence of index \"%s\"", indexName));
IndicesExistsRequest request = new IndicesExistsRequest(indexName);
IndicesExistsResponse response = adminClient.exists(request).actionGet();
if (response.isExists()) {
logger.info("Index exists");
return true;
}
logger.info("No such index");
return false;
}
public void createIndex() {
logger.info("Creating index " + indexName);
CreateIndexRequest request = new CreateIndexRequest(indexName);
IndicesAdminClient iac = esClient.admin().indices();
CreateIndexResponse response = iac.create(request).actionGet();
if (!response.isAcknowledged()) {
throw new Exception("Failed to create index " + indexName);
}
logger.info("Index created");
}
You can also execute a synchronous request like this:
boolean exists = client.admin().indices()
.prepareExists(INDEX_NAME)
.execute().actionGet().isExists();
Here is my solution when using RestHighLevelClient client;
Here a code-snippet: :
public boolean checkIfIndexExists(String indexName) throws IOException {
Response response = client.getLowLevelClient().performRequest("HEAD", "/" + indexName);
int statusCode = response.getStatusLine().getStatusCode();
return (statusCode != 404);
}
A contribution for someone else !
The skgemini's answer is ok if you want to check if index is available by the actual index name or any of its aliases.
If you however want to check only by the index name, here is how.
public boolean checkIfIndexExists(String index) {
IndexMetaData indexMetaData = client.admin().cluster()
.state(Requests.clusterStateRequest())
.actionGet()
.getState()
.getMetaData()
.index(index);
return (indexMetaData != null);
}
OK, I figured out a solution. Since the java client's calls are done asynchronously you have to use the variant which takes an action listener. The solution still gets a bit contrived though:
// Inner class because it's just used to be thrown out of
// the action listener implementation to signal that the
// index exists
private class ExistsException extends RuntimeException {
}
public boolean exists() {
logger.info(String.format("Verifying existence of index \"%s\"", indexName));
IndicesExistsRequest request = new IndicesExistsRequest(indexName);
try {
adminClient.exists(request, new ActionListener<IndicesExistsResponse>() {
public void onResponse(IndicesExistsResponse response) {
if (response.isExists()) {
throw new ExistsException();
}
}
public void onFailure(Throwable e) {
ExceptionUtil.smash(e);
}
});
}
catch (ExistsException e) {
return true;
}
return false;
}
I had the same issue but i didn't like the solution which uses an ActionListener. ElasticSearch also offers a Future variant (at least at version 6.1.0).
Here a code-snippet:
public boolean doesIndexExists(String indexName, TransportClient client) {
IndicesExistsRequest request = new IndicesExistsRequest(indexName);
ActionFuture<IndicesExistsResponse> future = client.admin().indices().exists(request);
try {
IndicesExistsResponse response = future.get();
boolean result = response.isExists();
logger.info("Existence of index '" + indexName + "' result is " + result);
return result;
} catch (InterruptedException | ExecutionException e) {
logger.error("Exception at waiting for IndicesExistsResponse", e);
return false;//do some clever exception handling
}
}
May be this helps someone else too. Cheers!
This works on Elasticsearch 7.x:
public boolean indexExists(String indexName) throws IOException {
return client.indices().exists(new org.elasticsearch.client.indices.GetIndexRequest(indexName), RequestOptions.DEFAULT);
}

Firefox can't establish a connection to the server at ws://localhost:8080/websocket

First of all Sorry for duplicate question but i didn't get the answer I was looking for.I am getting the above error on console
Firefox can't establish a connection to the server at ws://localhost:8080/websocket.
here is my jsp page
var username;
var wsUri = "ws://localhost:8080/chat/websocket";
var websocket = new WebSocket(wsUri);
websocket.onopen = function (evt) {
onOpen(evt);
};
websocket.onmessage = function (evt) {
onMessage(evt);
};
websocket.onerror = function (evt) {
onError(evt);
};
var output = document.getElementById("output");
function join() {
alert('join start');
username = textField.value;
websocket.send(username + " joined");
alert('join end');
}
function send_message() {
alert('sendmessage start');
websocket.send(username + ": " + textField.value);
alert('sendmessage end');
}
function onOpen() {
alert('onopen start');
writeToScreen("Connected to " + wsUri);
alert('onopen end');
}
function onMessage(evt) {
console.log("onMessage");
writeToScreen("RECEIVED: " + evt.data);
if (evt.data.indexOf("joined") !== -1) {
userField.innerHTML += evt.data.substring(0, evt.data.indexOf(" joined")) + "\n";
} else {
chatlogField.innerHTML += evt.data + "\n";
}
}
function onError(evt) {
writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data);
}
function writeToScreen(message) {
output.innerHTML += message + "<br>";
}
Here is my java class
#ServerEndpoint(value = "/websocket")
public class ChatEndpoint {
private static final Set < Session > peers = Collections.synchronizedSet(new HashSet < Session > ());
#OnOpen
public void onOpen(Session peer) {
System.out.println("I am onOpen");
peers.add(peer);
}
#OnClose
public void onClose(Session peer) {
System.out.println("I am onClose");
peers.remove(peer);
}
#OnMessage
public void message(String message, Session client) throws IOException, EncodeException {
System.out.println("I am message");
for (Session peer: peers) {
peer.getBasicRemote().sendObject(message);
}
}
}
I am using Maven repository and trying to run this project for client to client interaction in java.

Categories

Resources