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

Что выводит метод MessageNew: Вывод в консоли

Как видно, пустой объект приходит. У меня в коде класс GroupLongPollApi наследуется, а в примере CallbackApiLongPoll. Такое ощущение, что разницы никакой (исходники смотрел). Судя по всему второе это из старых версий, но и используя как в примере от VK тот же самый пустой объект приходит. Надеюсь понятно объяснил. Буду благодарен, если кто-то знает как получать нормальный объект с данными о сообщениb и поможет мне с этим.

UPD: заметил, что со временем выводится такая непонятная штучка введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения


Ответы (2 шт):

Автор решения: Ovsenka

Нашел решение проблемы.

Предполагаю, все пошло не по плану из-за неправильного 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. Буду рад, если у кого-то есть советы по упрощениям или улучшениям в коде.

→ Ссылка
Автор решения: Alex Po

На случай если кто-то ищет простой пример бота:

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.

→ Ссылка