使用 GluonhqConnect.Provider.RestClient 查询 ElasticSearch 正文

Query with ElasticSearch body using GluonhqConnect.Provider.RestClient

我正在尝试使用 com.gluonhq.connect.provider.RestClient 查询启用弹性搜索的 API。

Maven:
    <dependency>
        <groupId>com.gluonhq</groupId>
        <artifactId>connect</artifactId>
        <version>2.0.1</version>
    </dependency>

我尝试使用以下方式提出请求:

private GluonObservableObject<Item> getData() {
    RestClient myApiClient = RestClient.create()
            .method("POST")
            .host(applicationProperties.getAPIURL())
            .path("search")
            .header("accept", "application/json")
            .header("Content-type", "application/json")
            .queryParam("private_key", applicationProperties.getAPIKEY())
            .dataString(ITEMREQUEST);

    return DataProvider.retrieveObject(
            myApiClient.createObjectDataReader(Item.class));
}

...其中 dataString 是代表请求正文的 json 格式的字符串(我可以假设请求的格式正确,因为我在 Postman 中测试了它并且请求 return编辑了预期的数据)。 如果有帮助,这里是 elasticsearch 请求正文:

 {
  "indexes": "idx1, idx2",
  "columns": "col1,col2,col3,col4,col5",
  "body": {
    "query": {
      "bool": {
        "must": [
          {
            "wildcard": {
              "NameCombined_en": "*"
            }
          }
        ],
        "filter": [
          {
            "range": {
              "ID": {
                "gte": "20000"
              }
            }
          }
        ]
      }
    },
    "from": 0,
    "size": 100
  }
}

我遇到的问题是 (gluon) RestClient 以及 DataProvider.retrieveObject 方法 return 完全......没有。

我很确定我做错了什么,我很确定是 .dataString() 方法(它需要一个“实体”),但我还没有找到替代方法来用作将正文传递到请求中的方式。

使用 com.gluonhq.connect 库的原因是为了避免必须同时创建我自己的 Observable 列表(手动)——该库会自动吐出一个,提供数据的格式适当...并且存在。至少,我是这么理解的。

有人能指出我正确的方向吗?我没有找到关于如何使用此库执行 POST 请求的指示或解释。

更新 20220117

Main.java

public class Main extends Application {
ApplicationProperties applicationProperties = new ApplicationProperties();
private static final String RESTLIST_VIEW = HOME_VIEW;
private static final String RESTOBJECT_VIEW = "RestObjectView";


private final AppManager appManager = AppManager.initialize(this::postInit);

@Override
public void init() {
    appManager.addViewFactory(RESTOBJECT_VIEW, () -> new RestObjectView(applicationProperties.APIURL, applicationProperties.APIKEY));

    updateDrawer();
}

@Override
public void start(Stage stage) {
    appManager.start(stage);
}

private void postInit(Scene scene) {
    Swatch.BLUE.assignTo(scene);

    ((Stage) scene.getWindow()).getIcons().add(new Image(Objects.requireNonNull(Main.class.getResourceAsStream("/icon.png"))));
}

private void updateDrawer() {
    NavigationDrawer navigationDrawer = appManager.getDrawer();
    NavigationDrawer.Header header = new NavigationDrawer.Header("Gluon Mobile", "Gluon Connect Rest Provider Sample",
            new Avatar(21, new Image(getClass().getResourceAsStream("/icon.png"))));
    navigationDrawer.setHeader(header);
    NavigationDrawer.Item listItem = new NavigationDrawer.Item("List Viewer", MaterialDesignIcon.VIEW_LIST.graphic());
    NavigationDrawer.Item objectItem = new NavigationDrawer.Item("Object Viewer", MaterialDesignIcon.INSERT_DRIVE_FILE.graphic());
    navigationDrawer.getItems().addAll(listItem, objectItem);
    navigationDrawer.selectedItemProperty().addListener((obs, oldItem, newItem) -> {
        if (newItem.equals(listItem)) {
            appManager.switchView(RESTLIST_VIEW);
        } else if (newItem.equals(objectItem)) {
            appManager.switchView(RESTOBJECT_VIEW);
        }
    });
}

public static void main(String[] args) {
    System.setProperty("javafx.platform", "Desktop");

    launch(args);
}

RestObjectView.java

public class RestObjectView extends View {

public RestObjectView(String apiurl, String apikey) {

    Label lbItemId = new Label();
    Label lbName = new Label();
    Label lbDescription = new Label();
    Label lbLvlItem = new Label();
    Label lbLvlEquip = new Label();

    GridPane gridPane = new GridPane();
    gridPane.setVgap(5.0);
    gridPane.setHgap(5.0);
    gridPane.setPadding(new Insets(5.0));
    gridPane.addRow(0, new Label("Item ID:"), lbItemId);
    gridPane.addRow(1, new Label("Name:"), lbName);
    gridPane.addRow(2, new Label("Description:"), lbDescription);
    gridPane.addRow(3, new Label("Item Level:"), lbLvlItem);
    gridPane.addRow(4, new Label("Equip Level:"), lbLvlEquip);
    gridPane.getColumnConstraints().add(new ColumnConstraints(75));

    lbItemId.setWrapText(true);
    lbName.setWrapText(true);
    lbDescription.setWrapText(true);
    lbLvlItem.setWrapText(false);
    lbLvlEquip.setWrapText(false);

    setCenter(gridPane);

    // create a RestClient to the specific URL
    RestClient restClient = RestClient.create()
            .method("POST")
            .host(apiurl)
            .path("Item")
            .queryParam("private_key", apikey);

    // create a custom Converter that is able to parse the response into a single object
    InputStreamInputConverter<Item> converter = new SingleItemInputConverter<>(Item.class);

    // retrieve an object from the DataProvider
    GluonObservableObject<Item> item = DataProvider.retrieveObject(restClient.createObjectDataReader(converter));

    // when the object is initialized, bind its properties to the JavaFX UI controls
    item.initializedProperty().addListener((obs, oldValue, newValue) -> {
        if (newValue) {
            lbItemId.textProperty().bind(item.get().itemIdProperty().asString());
            lbName.textProperty().bind(item.get().nameProperty());
            lbDescription.textProperty().bind(item.get().descriptionProperty());
            lbLvlItem.textProperty().bind(item.get().levelItemProperty().asString());
            lbLvlEquip.textProperty().bind(item.get().levelEquipProperty().asString());
        }
    });
}

@Override
protected void updateAppBar(AppBar appBar) {
    appBar.setNavIcon(MaterialDesignIcon.MENU.button(e -> getAppManager().getDrawer().open()));
    appBar.setTitleText("Rest Object Viewer");
}

}

这是 RestClientGETPOST 的快速演示:

ToDoItem class:

public class ToDoItem {
    private int userId;
    private int id;
    private String title;
    private boolean completed;

    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public boolean isCompleted() {
        return completed;
    }

    public void setCompleted(boolean completed) {
        this.completed = completed;
    }

    @Override
    public String toString() {
        return "ToDoItem{" +
                "userId=" + userId +
                ", id=" + id +
                ", title='" + title + '\'' +
                ", completed=" + completed +
                '}';
    }
}

GET 测试:

public void getTest() {

        RestClient restClient = RestClient.create()
                .method("GET")
                .host("http://jsonplaceholder.typicode.com")
                .path("/todos/1");

        GluonObservableObject<ToDoItem> singleToDoItem = 
            DataProvider.retrieveObject(
                restClient.createObjectDataReader(ToDoItem.class));

        singleToDoItem.setOnSucceeded(e -> 
            System.out.println("ToDoItem successfully retrieved: " + singleToDoItem.get()));
        singleToDoItem.setOnFailed(e -> {
            System.out.println("ToDoItem GET error");
            if (singleToDoItem.getException() != null) {
                singleToDoItem.getException().printStackTrace();
            }
        });
    }

POST 测试:

public void postTest() {
        ToDoItem toDoItem = new ToDoItem();
        toDoItem.setCompleted(Math.random() > 0.5);
        toDoItem.setTitle(UUID.randomUUID().toString());
        toDoItem.setUserId(1);

        // write a new todo item to a rest source
        RestClient restClient = RestClient.create()
                .method("POST")
                .contentType("application/json")
                .host("http://jsonplaceholder.typicode.com")
                .path("/todos");

        GluonObservableObject<ToDoItem> obsToDoItem = 
                DataProvider.storeObject(toDoItem,
                    restClient.createObjectDataWriter(ToDoItem.class));

        obsToDoItem.setOnSucceeded(e -> 
            System.out.println("ToDoItem successfully written: " + obsToDoItem.get()));
        obsToDoItem.setOnFailed(e -> {
                System.out.println("ToDoItem POST error");
                if (obsToDoItem.getException() != null) {
                    obsToDoItem.getException().printStackTrace();
                }
            });
    }

运行 两者都应该给你这样的东西:

ToDoItem successfully retrieved: ToDoItem{userId=1, id=1, title='delectus aut autem', completed=false}

ToDoItem successfully written: ToDoItem{userId=1, id=201, title='6977035b-7a0c-4e6a-82e5-141b414db92a', completed=false}