How to lock documents in couchbase database and handle TemporaryLockFailureException - java

I am using Playframework(scalaVersion 2.12.4) with Java 1.8 and Couchbase(Couchbase java-client 2.4.2). I am fetching UserDetails document and updating the same document in the database.
My code is working in normal scenarios, couldn't test the conflicting edge cases. Hence, not sure whether my code will work or not.
How to handle TemporaryLockFailureException? My current exception handling seems to be wrong.
#Override
public void submitUsersDetails(DashboardRequest request) {
logger.debug("inside submitDashboardDetails");
CompletableFuture.runAsync(() -> {
try {
bucket = cluster.openBucket(config.getString(PctConstants.COUCHBASE_BUCKET_NAME),
config.getString(PctConstants.COUCHBASE_BUCKET_PASSWORD));
String documentID = PctConstants.USER_PROFILE;
JsonDocument retrievedJsonDocument = bucket.getAndLock(documentID, 5);
if (retrievedJsonDocument != null) {
JsonNode json = Json.parse(retrievedJsonDocument.content().toString());
UserDetails userDetails = Json.fromJson(json, UserDetails.class);
// UPDATING userDetails
JsonObject jsonObject = JsonObject.fromJson(Json.toJson(userDetails).toString());
bucket.replace(JsonDocument.create(documentID, jsonObject, retrievedJsonDocument.cas()));
logger.info("Successfully entered record into couchbase");
} else {
logger.error("Fetching User_details unsuccessful");
throw new DataNotFoundException("User_details data not found");
}
} catch (TemporaryLockFailureException e) {
try {
logger.debug("Inside lock failure **************************");
Thread.sleep(5000);
String documentID = PctConstants.USER_PROFILE;
JsonDocument retrievedJsonDocument = bucket.getAndLock(documentID, 5);
if (retrievedJsonDocument != null) {
JsonNode json = Json.parse(retrievedJsonDocument.content().toString());
UserDetails userDetails = Json.fromJson(json, UserDetails.class);
// UPDATING userDetails
JsonObject jsonObject = JsonObject.fromJson(Json.toJson(userDetails).toString());
bucket.replace(JsonDocument.create(documentID, jsonObject, retrievedJsonDocument.cas()));
logger.info("Successfully entered record into couchbase");
submitDashboardDetails(request);
} else {
logger.error("Fetching User_details unsuccessful");
throw new DataNotFoundException("User_details data not found");
}
} catch (InterruptedException e1) {
e1.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
try {
throw e;
} catch (Exception e1) {
e1.printStackTrace();
}
}
}, ec.current()).join();
}

Related

How do I save the id from chatid with the telegram api

Hello. I'm trying to solve this problem for a while now. For some
reason I keep getting null pointer exception when I try to save a
object in my repository. Below you can see what happens and my
functions.
java.lang.NullPointerException at com.br.einstein.api.service.ApiTelegram.sendMsg(ApiTelegram.java:104)
at
com.br.einstein.api.service.ApiTelegram.onUpdateReceived(ApiTelegram.java:81)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1541) at
org.telegram.telegrambots.meta.generics.LongPollingBot.onUpdatesReceived(LongPollingBot.java:27)
at
org.telegram.telegrambots.updatesreceivers.DefaultBotSession$HandlerThread.run(DefaultBotSession.java:317)
public void onUpdateReceived(Update update) {
ApiEinstein api = new ApiEinstein();
try {
JsonObject objSession = api.getSessionDetails();
String message = update.getMessage().getText();
api.sendChatRequest(objSession);
List < String > list = new ApiEinstein().ReadChatDetails(objSession);
sendMsg(update.getMessage().getChatId().toString(), list.toString());
new ApiEinstein().SendChatMessage(objSession, message);
api.syncChatSession(objSession);
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void sendMsg(String chatId, String s) {
SendMessage sendMessage = new SendMessage();
// sendMessage.enableMarkdown(true);
sendMessage.setChatId(chatId);
sendMessage.setText(s);
long id = Long.valueOf(chatId);
Telegram telegram = new Telegram();
telegram.setChatId(id);
repository.save(telegram);
try {
execute(sendMessage);
} catch (TelegramApiException e) {
e.printStackTrace();
}
} ```

Parsing String json to List<Model>

I just can not solve this problem. I get the data from the server, save them in shared preferences key = data value = "[.. json].
The structure and type of data can be seen in the screenshot.
How to correctly json in the List <User ..>. I use this code, in which it uses jackson2 library, but it does not work. I'm getting an error
JsonMappingException: Can not deserialize instance of com.example.dmitriysamoilov.filipapp.model.UserContactListModel out of START_ARRAY token
public List<UserContactListModel> getUserLocalContactsData() {
List<UserContactListModel> listModels = new ArrayList<>();
String json = "";
sharedPreferences = context.getSharedPreferences(ReservedName.USER_LOCAL_CONTACTS_DATA,
context.MODE_PRIVATE);
if (sharedPreferences.contains("json")) {
json = sharedPreferences.getString("json", "");
}else return listModels;
ObjectMapper mapper = new ObjectMapper();
try {
// Convert JSON string from file to Object
UserContactListModel l = mapper.readValue(json,UserContactListModel.class);
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return listModels;
}
I understand that the logic is not true, but I can not figure this out very long
Since your json is array, try as below
listModels = Arrays.asList(mapper.readValue(json, UserContactListModel[].class));
Giving a short example try to find out your result.
String jsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> cars1 = objectMapper.readValue(jsonArray, new TypeReference<List<Car>>(){});
Here for your code-
public List<UserContactListModel> getUserLocalContactsData() {
List<UserContactListModel> listModels = new ArrayList<>();
String json = "";
sharedPreferences = context.getSharedPreferences(ReservedName.USER_LOCAL_CONTACTS_DATA,
context.MODE_PRIVATE);
if (sharedPreferences.contains("json")) {
json = sharedPreferences.getString("json", "");
}else return listModels;
ObjectMapper mapper = new ObjectMapper();
try {
// Convert JSON string from file to Object
listModels = mapper.readValue(json,new TypeReference<List<UserContactListModel>>(){});
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return listModels;
}

JAVA Telegram bots api Error getting updates: Conflict: terminated by other long poll or webhook

I am using JAVA Telegram Bot API with Spring framework , I had a method in my HomeController and i had a class that handle all of the incoming messages from users. I got these errors in my spring log,then i got duplicated response from telegram bot API .whats is the problem ?
#PostConstruct
public void initBots() {
ApiContextInitializer.init();
TelegramBotsApi botsApi = new TelegramBotsApi();
BotService botService = new BotService();
try {
botsApi.registerBot(botService);
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
[abrsystem1_bot Telegram Connection] org.telegram.telegrambots.logging.BotLogger.severe
BOTSESSION
org.telegram.telegrambots.exceptions.TelegramApiRequestException:
Error getting updates: [409] Conflict: terminated by other long poll
or webhook at
org.telegram.telegrambots.api.methods.updates.GetUpdates.deserializeResponse(GetUpdates.java:119)
at
org.telegram.telegrambots.updatesreceivers.DefaultBotSession$ReaderThread.getUpdatesFromServer(DefaultBotSession.java:255)
at
org.telegram.telegrambots.updatesreceivers.DefaultBotSession$ReaderThread.run(DefaultBotSession.java:186)
#Override
public void onUpdateReceived(Update update) {
try {
if (update.hasMessage() && update.getMessage().hasText()) {
String message_text = update.getMessage().getText();
String wellcome_text = "برای ثبت نام در سایت شماره تلفن همراه خود را به اشتراک بگذارید";
long chat_id = update.getMessage().getChatId();
if (message_text.equals("/start")) {
try {
SendMessage message = new SendMessage()
.setChatId(chat_id)
.setText(wellcome_text);
ReplyKeyboardMarkup keyboardMarkup = new ReplyKeyboardMarkup();
List<KeyboardRow> keyboard = new ArrayList<KeyboardRow>();
KeyboardRow row = new KeyboardRow();
row.add((new KeyboardButton().setText("اشتراک شماره موبایل").setRequestContact(true)));
keyboard.add(row);
keyboardMarkup.setKeyboard(keyboard);
message.setReplyMarkup(keyboardMarkup);
try {
execute(message);
} catch (TelegramApiException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
} else if (message_text.equals("تایید مشخصات کاربری")) {
SendMessage sendMessage = new SendMessage();
sendMessage.setChatId(chat_id).setText("اطلاعات مورد تایید قرار گرفت");
try {
execute(sendMessage);
removeMarker(chat_id);
showContactInfo(chat_id, update);
} catch (Exception ex) {
ex.printStackTrace();
}
} else if (message_text.equals("تغییر مشخصات")) {
} else {
showUnknownCommand(chat_id);
}
} else if (update.getMessage().getContact() != null && update.getMessage().getChat() != null) {
long chat_id = update.getMessage().getChatId();
showContactInfo(chat_id, update);
}
} catch (Exception e) {
e.printStackTrace();
}
}
I finally solved my problem after a day!when i was debugging my project with intellij idea on my computer , i created many instances for debug so i got multiple response from same chat id in telegram bot.so boring problem....

Some server generated events do not get delivered to the client in production over websockets

Bottom line:
Some server generated events do not get delivered to the client in production over websockets. However, the websocket connections get established just fine.
Case study:
I open Google Chrome and connect to our server. Open the devtools. Under WS tab, I see that connection got established fine, but I receive no frames when, let’s say, server needs to update something on the page. I wait for a while and sometimes (only sometimes) I get some events with a huge amount of delay. This works as expected locally however.
Question:
Has anyone seen similar websocket behavior and has any suggestions on how to eliminate variables for this investigation.
Infrastructure:
Server: Linux Tomcat
Two servers that handle:
1. Traffic from Devices (Communicating over TCP/IP with the Server)
2. Traffic from Users
Users and Devices are many to many relationship. If a user gets connected to a server that doesn’t have a device connected. This server looks on the other server and handles the info exchange.
There is a firewall in front of the servers.
Code:
https://github.com/kino6052/websockets-issue
WebSocketServerEndpoint.java
#ServerEndpoint("/actions")
public class WebSocketServerEndpoint {
static private final org.slf4j.Logger logger = LoggerFactory.getLogger(WebSocketServerEndpoint.class);
#OnOpen
public void open(Session session) {
WebSocketSessionHandler.addSession(session);
}
#OnClose
public void close(Session session) {
WebSocketSessionHandler.removeSession(session);
}
#OnError
public void onError(Throwable error) {
//Logger.getLogger(WebSocketServerEndpoint.class.getName()).log(Level.SEVERE, null, error);
}
#OnMessage
public void handleMessage(String message, Session session) {
try (JsonReader reader = Json.createReader(new StringReader(message))) {
JsonObject jsonMessage = reader.readObject();
Long userId = null;
Long tenantId = null;
switch (WebSocketActions.valueOf(jsonMessage.getString("action"))){
case SaveUserId:
userId = getUserId(jsonMessage);
tenantId = getTenantId(jsonMessage);
Long userIdKey = WebSocketSessionHandler.saveUserId(userId, session);
Long tenantUserKey = WebSocketSessionHandler.saveTenantUser(tenantId, userId);
WebSocketSessionHandler.updateUserSessionKeys(session, tenantUserKey, userIdKey); // Needed for Making Weak Maps Keep Their Keys if Session is Currently Active
}
} catch (Exception e) {
logger.error(e.toString());
}
}
private Long getUserId(JsonObject jsonMessage) {
Long userId = null;
try {
userId = Long.parseLong(((Integer) jsonMessage.getInt("userId")).toString());
return userId;
} catch (Exception e) {
logger.error(e.getMessage());
return userId;
}
}
private Long getTenantId(JsonObject jsonMessage) {
Long tenantId = null;
try {
tenantId = Long.parseLong(((Integer) jsonMessage.getInt("tenantId")).toString());
return tenantId;
} catch (Exception e) {
logger.error(e.getMessage());
return tenantId;
}
}
}
WebSocketService.java
#Singleton
public class WebSocketService {
private static final Logger logger = LoggerFactory.getLogger(WebSocketService.class);
public enum WebSocketEvents{
OnConnection,
OnActivity,
OnAccesspointStatus,
OnClosedStatus,
OnConnectedStatus,
OnAlert,
OnSessionExpired
}
public enum WebSocketActions{
SaveUserId
}
#WebPost("/lookupWebSocketSessions")
public WebResponse lookupWebSocketSessions(#JsonArrayParam("userIds") List<Integer> userIds, #WebParam("message") String message){
try {
for (Integer userIdInt : userIds) {
Long userId = Long.parseLong(userIdInt.toString());
if (WebSocketSessionHandler.sendToUser(userId, message) == 0) {
} else {
//logger.debug("Couldn't Send to User");
}
}
} catch (ClassCastException e) {
//logger.error(e.getMessage());
return webResponseBuilder.fail(e);
} catch (Exception e) {
//logger.error(e.getMessage());
return webResponseBuilder.fail(e);
}
return webResponseBuilder.success(message);
}
#WebPost("/lookupWebSocketHistorySessions")
public WebResponse lookupWebSocketHistorySessions(#JsonArrayParam("userIds") List<Integer> userIds, #WebParam("message") String message){
try {
for (Integer userIdInt : userIds) {
Long userId = Long.parseLong(userIdInt.toString());
if (WebSocketHistorySessionHandler.sendToUser(userId, message) == 0) {
} else {
//logger.debug("Couldn't Send to User");
}
}
} catch (ClassCastException e) {
//logger.error(e.getMessage());
return webResponseBuilder.fail(e);
} catch (Exception e) {
//logger.error(e.getMessage());
return webResponseBuilder.fail(e);
}
return webResponseBuilder.success(message);
}
// Kick Out a User if Their Session is no Longer Valid
public void sendLogout(User user) {
try {
Long userId = user.getId();
List<Long> userIds = new ArrayList<>();
userIds.add(userId);
JSONObject result = new JSONObject();
result.put("userId", userId);
JSON message = WebSocketSessionHandler.createMessage(WebSocketEvents.OnSessionExpired, result);
lookOnOtherServers(userIds, message);
} catch (Exception e) {
logger.error("Couldn't Logout User");
}
}
// Send History after Processing Data
// Returns "0" if success, "-1" otherwise
public int sendHistory(Activity activity) {
try {
TimezoneService.TimeZoneConfig timeZoneConfig = timezoneService.getTimezoneConfigsByAp(null, activity.getAccesspointId());
JSONObject result = (JSONObject) JSONSerializer.toJSON(activity);
String timezoneId = timezoneService.convertTimezoneConfigToTimezoneId(timeZoneConfig);
result.put("timezoneString", timezoneId);
result.put(
"profileId",
userDao.getUserProfileId(activity.getUserId())
);
JSON message = WebSocketHistorySessionHandler.createMessage(WebSocketEvents.OnActivity, result);
List<Long> userIds = getUsersSubscribedToActivity(activity.getTenantId());
lookOnOtherServersHistory(userIds, message);
return 0;
} catch (Exception e) {
//logger.error("Couldn't Send History");
return -1;
}
}
// SendAlertUpdate after Processing Data
public void sendAlertUpdate(Alert alert) {
try {
List<Long> userIds = getUsersUnderTenantByAccesspointId(alert.getAccesspointId());
JSONObject result = JSONObject.fromObject(alert);
JSON message = WebSocketSessionHandler.createMessage(WebSocketEvents.OnAlert, result);
lookOnOtherServers(userIds, message);
} catch (Exception e) {
//logger.error("Couldn't Send Aleart");
}
}
// Send Connected Status after Processing Data
public void sendConnectedStatus(Long accesspointId, Boolean isConnected) {
try {
List<Long> userIds = getUsersUnderTenantByAccesspointId(accesspointId);
JSONObject result = new JSONObject();
result.put("accesspointId", accesspointId);
result.put("isConnected", isConnected);
JSON message = WebSocketSessionHandler.createMessage(WebSocketEvents.OnConnectedStatus, result);
lookOnOtherServers(userIds, message);
} catch (Exception e) {
//logger.error("Couldn't Send Connected Status");
}
}
public int sendHistory(CredentialActivity activity) {
try {
TimezoneService.TimeZoneConfig timeZoneConfig = timezoneService.getTimezoneConfigsByAp(null, activity.getAccesspointId());
JSONObject result = (JSONObject) JSONSerializer.toJSON(activity);
String timezoneId = timezoneService.convertTimezoneConfigToTimezoneId(timeZoneConfig);
result.put("timezoneString", timezoneId);
result.put(
"profileId",
userDao.getUserProfileId(activity.getUserId())
);
JSON message = WebSocketHistorySessionHandler.createMessage(WebSocketEvents.OnActivity, result);
List<Long> userIds = getUsersUnderTenantByAccesspointId(activity.getAccesspointId());
lookOnOtherServersHistory(userIds, message);
return 0;
} catch (Exception e) {
return -1;
}
}
public Boolean isUserSessionAvailable(Long id) {
return WebSocketSessionHandler.isUserSessionAvailable(id);
}
public void lookOnOtherServers(List<Long> userId, JSON data){
List<String> urls = awsService.getServerURLs();
for (String url : urls) {
postJSONDataToUrl(url, userId, data);
}
}
public void lookOnOtherServersHistory(List<Long> userId, JSON data){
List<String> urls = awsService.getServerURLsHistory();
for (String url : urls) {
postJSONDataToUrl(url, userId, data);
}
}
public int sendClosedStatus(AccesspointStatus accesspointStatus){
try {
JSONObject accesspointStatusJSON = new JSONObject();
accesspointStatusJSON.put("accesspointId", accesspointStatus.getAccesspointId());
accesspointStatusJSON.put("openStatus", accesspointStatus.getOpenStatus());
List<Long> userIds = getUsersUnderTenantByAccesspointId(accesspointStatus.getAccesspointId());
lookOnOtherServers(userIds, accesspointStatusJSON);
return 0;
} catch (Exception e) {
return -1;
}
}
public List<Long> getUsersSubscribedToActivity(Long tenantId) {
List<Long> userList = WebSocketSessionHandler.getUsersForTenant(tenantId);
return userList;
}
private List<Long> getUsersUnderTenantByAccesspointId(Long accesspointId) {
List<Long> userList = new ArrayList<>();
User user = userDao.getBackgroundUserByAccesspoint(accesspointId);
List<Record> recordList = tenantDao.getTenantsByUser(user, user.getId());
for (Record record : recordList) {
Long tenantId = (Long) record.get("id");
userList.addAll(getUsersSubscribedToActivity(tenantId));
}
return userList;
}
public void postJSONDataToUrl(String url, List<Long> userId, JSON data) throws AppException {
List<NameValuePair> parameters;
HttpResponse httpResponse;
HttpClientService.SimpleHttpClient simpleHttpClient = httpClientService.createHttpClient(url);
try {
parameters = httpClientService.convertJSONObjectToNameValuePair(userId, data);
} catch (Exception e) {
throw new AppException("Couldn't Convert Input Parameters");
}
try {
httpResponse = simpleHttpClient.sendHTTPPost(parameters);
} catch (Exception e) {
throw new AppException("Couldn't Get Data from the Server");
}
if (httpResponse == null) {
throw new AppException("Couldn't Send to Another Server");
} else {
//logger.error(httpResponse.getStatusLine().toString());
}
}
}
WebSocketSessionHandler.java
public class WebSocketSessionHandler {
// Apparently required to instantiate the dialogue,
// ideally it would be better to just create session map where sessions are mapped to userId,
// however, userId will be send only after the session is created.
// TODO: Investigate Instantiation of WebSocket Session Further
// WeakHashMap is Used for Automatic Memory Management (So That Removal of Keys That are no Longer Used Can be Automatically Performed)
// NOTE: However, it Requires Certain Precautions to Make Sure Their Keys Don't Expire Unexpectedly, Look for the Commented Code Below
private static final Map<Long, Set<Session>> sessionMap = new WeakHashMap<>();
private static final Map<Long, Set<Long>> tenantUserMap = new WeakHashMap<>();
public WebSocketSessionHandler() {}
public static List<Long> getUsersForTenant(Long tenantId) {
List<Long> userIds = new ArrayList<>();
Set<Long> userIdsSet = tenantUserMap.get(tenantId);
if (userIdsSet != null) {
for (Long userId : userIdsSet){
userIds.add(userId);
}
}
return userIds;
}
public static Boolean isUserSessionAvailable(Long id){
Set<Session> userSessions = sessionMap.get(id);
if (userSessions == null || userSessions.size() == 0) {
return false;
} else {
return true;
}
}
// addSession() should add "session" to "sessions" set
// returns: "0" if success and "-1" otherwise
public static int addSession(Session session) {
int output;
try {
final long ONE_DAY = 86400000;
session.setMaxIdleTimeout(ONE_DAY);
sessions.put(session, new ArrayList<>());
return sendToSession(session, createMessage(WebSocketEvents.OnConnection, "Successfully Connected"));
} catch (Exception e) {
logger.error("Couldn't Add Session");
return -1;
}
}
// removeSession() should remove "session" from "sessions" set
// Scenarios:
// sessions is null?
// returns: "0" if success and "-1" otherwise
public static int removeSession( Session session) {
try {
closeSessionProperly(session);
if (sessions.remove(session) != null) {
return 0;
} else {
return -1;
}
} catch (Exception e) {
logger.error("Couldn't Remove Session");
return -1;
}
}
private static void closeSessionProperly(Session session) {
try {
session.close();
} catch (IOException ex) {
}
}
public static Long getKeyFromMap(Map map, Long key){ // Needed for Weak Maps
Set<Long> keySet = map.keySet();
for (Long keyReference : keySet) {
if (keyReference == key) {
return keyReference;
}
}
return key; // If Not Found Return the Value Passed in
}
// saveUserId() should create an { userId -> session } entry in sessionMap
public static Long saveUserId(Long userId, Session session){
// Test Scenarios:
// Can userId be null or wrong?
// Can session be null or wrong?
try {
userId = getKeyFromMap(sessionMap, userId); // Required for Weak Maps to Work Correctly
Set<Session> sessionsForUser = sessionMap.get(userId);
if (sessionsForUser == null) {
sessionsForUser = new HashSet<>();
}
sessionsForUser.add(session);
sessionMap.put(userId, sessionsForUser);
return userId;
} catch (Exception e) {
logger.error("Couldn't Save User Id");
return null;
}
}
// saveUserId() should create an { userId -> session } entry in sessionMap
public static Long saveTenantUser(Long tenantId, Long userId){
// Test Scenarios:
// Can userId be null or wrong?
// Can session be null or wrong?
try {
tenantId = getKeyFromMap(tenantUserMap, tenantId); // Required for Weak Maps to Work Correctly
Set<Long> users = tenantUserMap.get(tenantId);
if (users == null) {
users = new HashSet<>();
}
users.add(userId);
tenantUserMap.put(tenantId, users);
return tenantId;
} catch (Exception e) {
logger.error("Couldn't Save Tenant User");
return null;
}
}
public static void updateUserSessionKeys(Session session, Long tenantId, Long userId) {
try {
List<Long> userSessionKeys = sessions.get(session);
userSessionKeys.add(0, tenantId);
userSessionKeys.add(1, userId);
} catch (Exception e) {
logger.error("Couldn't Update User Session Keys");
}
}
// removeUserId() should remove an { userId -> session } entry in sessionMap
// returns: "0" if success and "-1" otherwise
public static int removeUserId( Long userId) {
try {
sessionMap.remove(userId);
return 0;
} catch (Exception e) {
return -1;
}
}
// sendAccesspointStatus() should compose JSON message and pass it to sendToUser()
// returns: "0" if success and "-1" otherwise
public static int sendClosedStatus(Long userId, JSONObject accesspointStatus) {
try {
JSONObject accesspointStatusEventMessage = (JSONObject) createMessage(WebSocketEvents.OnClosedStatus, accesspointStatus);
sendToUser(userId, accesspointStatusEventMessage);
return 0;
} catch (Exception e) {
return -1;
}
}
// sendToUser() sends message to session that is mapped to userId
// returns: "0" if success and "-1" otherwise
public static int sendToUser( Long userId, JSON message) {
if (sessionMap.containsKey(userId)) {
Set<Session> sessionsForUser = sessionMap.get(userId);
for (Session session : sessionsForUser) {
if (!session.isOpen()) {
sessions.remove(session);
continue;
}
sendToSession(session, message);
}
return 0;
} else {
return -1;
}
}
// sendToSession() sends string message to session
// returns: "0" if success and "-1" otherwise
private static int sendToSession( Session session, JSON message){
try {
try {
Long tenantId = sessions.get(session).get(0);
((JSONObject) message).put("tenantId", tenantId);
} catch (Exception e) {
logger.error("No tenantId Found");
}
session.getBasicRemote().sendText(message.toString());
return 0;
} catch (IOException e) {
try {
session.close();
} catch (IOException ex) {
}
closeSessionProperly(session);
sessions.remove(session);
return -1;
}
}
// sendToSession() sends string message to session
// returns: "0" if success and "-1" otherwise
private static int sendToSession( Session session, String message){
try {
JSONObject newMessage = JSONObject.fromObject(message);
try {
Long tenantId = sessions.get(session).get(0);
newMessage.put("tenantId", tenantId);
} catch (Exception e) {
logger.error("No tenantId Found");
}
session.getBasicRemote().sendText(newMessage.toString());
return 0;
} catch (IOException e) {
closeSessionProperly(session);
sessions.remove(session);
return -1;
}
}
}
Probably not the only bug, but your WebSocketSessionHandler class is not thread-safe. It uses WeakHashMap internally which is not synchronized. Concurrent access to these maps may result in unexpected behavior, which may or may not cause the effects you are seeing.
Turns out this was a correct assumption. A general rule of thumb: Unexpected Behaviour ~ Race Condition
Probably not the only bug, but your WebSocketSessionHandler class is not thread-safe. It uses WeakHashMap internally which is not synchronized. Concurrent access to these maps may result in unexpected behavior, which may or may not cause the effects you are seeing.
(copied from my comment. Turns out this was the solution)

Error while joining MUC room in XMPP(smack)

I am trying to create a multi user chat. I am getting error while joining the room.
Method for creating chat room :
public void createMultiUserChatRoom(String roomName, String nickName) {
// Get the MultiUserChatManager
MultiUserChatManager multiUserChatManager = MultiUserChatManager.getInstanceFor(connection);
// Get a MultiUserChat using MultiUserChatManager
MultiUserChat multiUserChat = multiUserChatManager.getMultiUserChat(roomName+"#conference.localhost");
try {
multiUserChat.create(nickName);
Form form = multiUserChat.getConfigurationForm();
Form submitForm = form.createAnswerForm();
List<FormField> formFieldList = submitForm.getFields();
for (FormField formField : formFieldList) {
if(!FormField.Type.hidden.equals(formField.getType()) && formField.getVariable() != null) {
submitForm.setDefaultAnswer(formField.getVariable());
}
}
submitForm.setAnswer("muc#roomconfig_persistentroom", true);
submitForm.setAnswer("muc#roomconfig_publicroom", true);
multiUserChat.sendConfigurationForm(submitForm);
} catch (Exception e) {
e.printStackTrace();
}
}
Method for joining MUC room :
public void joinMultiUserChatRoom(String userName, String roomName) {
// Get the MultiUserChatManager
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);
// Create a MultiUserChat using an XMPPConnection for a room
MultiUserChat multiUserChat = manager.getMultiUserChat(roomName + "#conference.localhost");
DiscussionHistory history = new DiscussionHistory();
history.setMaxStanzas(-1);
try {
multiUserChat.join(userName, "", history, connection.getPacketReplyTimeout());
} catch (Exception e) {
e.printStackTrace();
}
}
Getting list of joined room by user :
public List<String> getJoinedGroupByUserName(String userName) {
// Get the MultiUserChatManager
MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);
List<String> joinedRooms = null;
try {
// Get the rooms where user3#host.org has joined
joinedRooms = manager.getJoinedRooms(userName+"#conference.localhost");
} catch (Exception e) {
e.printStackTrace();
}
return joinedRooms;
}
While user join the room i get this message : "This room is locked from entry until configuration is confirmed."
Room it's not really available (confirmed) after sending a configuration, the creator has to join after
multiUserChat.sendConfigurationForm(submitForm);
so basically creator must also
multiUserChat.join(username)
(if you don't need to stay inside, perform a muc.leave() after a join)

Categories

Resources