CallbackApiLongPoll возвращает пустой объект Message
Описание проблемы.
Пишу бота для беседы с использованием Java SDK от VK. Использую версию com.vk.api.sdk 1.0.14. Хочу отлавливать сообщения, которые приходят (будь то личные сообщения сообществу или в беседе), для этого использую описанный способ на главной странице Java SDK - https://dev.vk.com/sdk/java. Дело в том, что ко мне приходят события, что сообщение новое пришло, а сам объект получается пустой. Все видно на скриншотах. Куски кода прилагаю.
Запуск handler'a в файле App.java:
//Init clients
TransportClient transportClient = new HttpTransportClient();
VkApiClient vkClient = new VkApiClient(transportClient);
//Create service actor
Integer groupId = {MyGroupId};
String accessToken = "{MyAccessToken}";
GroupActor actor = new GroupActor(groupId, accessToken);
vkClient.groups().setLongPollSettings(actor, groupId).enabled(true)
.messageNew(true)
.execute();
GroupLongPollApiHandler handler = new GroupLongPollApiHandler(vkClient, actor, 2000);
handler.run();
}}
Код в файле GroupLongPollApiHandler.java(наш handler):
public class GroupLongPollApiHandler extends GroupLongPollApi {
public GroupLongPollApiHandler(VkApiClient client, GroupActor actor, int waitTime) {
super(client, actor, waitTime);
}
@Override
public void messageNew(Integer groupId, Message message){
System.out.println("NEW MSG: "+message.toString());
System.out.println("NEW MSG: "+message.getText());
System.out.println("NEW MSG: "+message.getPeerId());
}}
Как видно, пустой объект приходит. У меня в коде класс GroupLongPollApi наследуется, а в примере CallbackApiLongPoll. Такое ощущение, что разницы никакой (исходники смотрел). Судя по всему второе это из старых версий, но и используя как в примере от VK тот же самый пустой объект приходит. Надеюсь понятно объяснил. Буду благодарен, если кто-то знает как получать нормальный объект с данными о сообщениb и поможет мне с этим.
UPD: заметил, что со временем выводится такая непонятная штучка

Ответы (2 шт):
Нашел решение проблемы.
Предполагаю, все пошло не по плану из-за неправильного timestamp (идентификатор, определяющий последнее событие).
Нашел страницу по Bots Long Poll API и обнаружил, что по запросу по ссылке {$server}?act=a_check&key={$key}&ts={$ts}&wait=25 приходит ответ в виде JSON, в котором можно забрать тип события и все что с ним связано, а также новый timestamp для следующего запроса. Также на этой странице можно увидеть какие объекты с какой структурой приходят в ответе.
Переписал код так:
TransportClient transportClient = new HttpTransportClient();
VkApiClient vk = new VkApiClient(transportClient);
GroupActor actor = new GroupActor(GROUP_ID, ACCESS_TOKEN);
GroupCommandHandler handler = new GroupCommandHandler(vk, actor);
GroupsGetLongPollServerQuery serverQuery = vk.groups().getLongPollServer(actor,GROUP_ID);
GetLongPollServerResponse response = serverQuery.execute();
String key = response.getKey();
String serverUrl = response.getServer();
Integer ts = Integer.valueOf(response.getTs());
while (true) {
Thread.sleep(2500);
url = serverUrl + "?act=a_check&key=" + key + "&ts=" + ts + "&wait=25";
String json = VkApiClientUtils.loadJson(url);
JsonObject messageObject = gs.fromJson(json, JsonObject.class);
ts = messageObject.get("ts").getAsInt();
JsonArray msg_array = messageObject.getAsJsonArray("updates");
for (JsonElement ob: msg_array) handler.handle(ob.getAsJsonObject());
}
Ответ получаю в методе loadJson(), откуда делаю запрос по этой ссылке. Потом преобразую из строки объект сообщений в Json объект. Дальше получаю массив событий и ловлю в handler'e, где происходит обработка. Объект сообщений, потому что в updates(событиях) приходит массив. updates (array) — массив, элементы которого содержат представление новых событий.
gs - ссылочная переменная на объект класса Gson, который помогает получить Json объект.
Код метода loadJson:
public static String loadJson(String url) throws IOException {
URL obj = new URL(url);
HttpURLConnection connection = (HttpURLConnection) obj.openConnection();
connection.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
Казалось бы, ничего сложного. Однако на странице JAVA SDK описан неработающий для меня способ, нужно было заглянуть в Bots Long Poll API. Буду рад, если у кого-то есть советы по упрощениям или улучшениям в коде.
На случай если кто-то ищет простой пример бота:
package ru.vk.mybot.adapter.in.sdk;
import java.util.Random;
import com.vk.api.sdk.client.TransportClient;
import com.vk.api.sdk.client.VkApiClient;
import com.vk.api.sdk.client.actors.GroupActor;
import com.vk.api.sdk.exceptions.ApiException;
import com.vk.api.sdk.exceptions.ClientException;
import com.vk.api.sdk.httpclient.HttpTransportClient;
import com.vk.api.sdk.queries.messages.MessagesGetLongPollHistoryQuery;
public class Bot {
public static void main(String[] args) throws ClientException,
ApiException,
InterruptedException {
TransportClient transportClient = new HttpTransportClient();
VkApiClient vk = new VkApiClient(transportClient);
Random random = new Random();
long groupId = 1234L;
String accessToken = "accessToken";
GroupActor actor = new GroupActor(groupId, accessToken);
Integer ts = vk.messages().getLongPollServer(actor).execute().getTs();
while (true) {
MessagesGetLongPollHistoryQuery historyQuery = vk.messages()
.getLongPollHistory(actor).ts(ts);
var messages = historyQuery.execute().getMessages().getItems();
if (!messages.isEmpty()) {
messages.forEach(message -> {
System.out.println(message.toString());
try {
if (message.getText().equals("Привет")) {
vk.messages()
.sendDeprecated(actor).message("Привет")
.userId(message.getFromId())
.randomId(random.nextInt(10000)).execute();
} else if (message.getText().equals("Кто я?")) {
vk.messages().sendDeprecated(actor).message(
"Ты хороший человек.").userId(message.getFromId())
.randomId(random.nextInt(10000)).execute();
} else {
vk.messages().sendDeprecated(actor).message(
"Я тебя не понял").userId(message.getFromId())
.randomId(random.nextInt(10000)).execute();
}
} catch (ApiException | ClientException e) {
e.printStackTrace();
}
});
}
ts = vk.messages().getLongPollServer(actor).execute().getTs();
Thread.sleep(500);
}
}
}
Для запуска нужно указать groupId и accessToken.


