Back in Cuba platform I used the JMX console and got a persistence object and i was able to load and test JPQL queries from within the admin screen. How can I do the same with JMIX?
thank you.
You can do even better in your project.
Create a simple screen with SourceCodeEditor component:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<window xmlns="http://jmix.io/schema/ui/window"
caption="msg://queryTestScreen.caption">
<layout expand="codeField" spacing="true">
<sourceCodeEditor id="codeField" width="100%"/>
<comboBox id="entityComboBox" caption="Entity"/>
<button id="testBtn" caption="Test"/>
</layout>
</window>
Add code completion and data loading to it:
@UiController("QueryTestScreen")
@UiDescriptor("query-test-screen.xml")
public class QueryTestScreen extends Screen {
@Autowired
private SourceCodeEditor codeField;
@Autowired
private JpqlUiSuggestionProvider jpqlUiSuggestionProvider;
@Autowired
private DataManager dataManager;
@Autowired
private ComboBox<Class<?>> entityComboBox;
@Autowired
private MetadataTools metadataTools;
@Subscribe
public void onInit(InitEvent event) {
codeField.setSuggester((source, text, cursorPosition) -> {
if (codeField.getValue() == null) {
return Collections.emptyList();
}
return jpqlUiSuggestionProvider.getSuggestions(
codeField.getValue(),
cursorPosition - 1,
codeField.getAutoCompleteSupport()
);
});
Map<String, Class<?>> entities = new TreeMap<>();
for (MetaClass metaClass : metadataTools.getAllJpaEntityMetaClasses()) {
entities.put(metaClass.getName(), metaClass.getJavaClass());
}
entityComboBox.setOptionsMap(entities);
}
@Subscribe("testBtn")
public void onTestBtnClick(Button.ClickEvent event) {
if (codeField.getValue() != null) {
List<?> list;
if (entityComboBox.getValue() != null) {
list = dataManager.load(entityComboBox.getValue()).query(codeField.getValue()).list();
} else {
list = dataManager.loadValues(codeField.getValue()).list();
}
System.out.println("Query results: " + list);
}
}
}
Moreover, you can add a user selection field and test query execution for different roles, by wrapping dataManager.load() with System Authentication.
2 Likes
Hi, is it possible to have this solution with JMIX 2.0?
Sure. Jmix 2 provides similar features:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<view xmlns="http://jmix.io/schema/flowui/view"
title="msg://jpqlTestView.title">
<layout>
<codeEditor id="codeField" width="100%"/>
<hbox>
<comboBox id="entityComboBox" label="Entity"/>
<button id="testBtn" text="Test" alignSelf="END"/>
</hbox>
<textArea id="resultsField" width="100%" minHeight="5em" height="100%"/>
</layout>
</view>
package com.company.sample.view.jpqltest;
import com.company.sample.view.main.MainView;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.data.provider.DataProvider;
import com.vaadin.flow.data.provider.DataProviderListener;
import com.vaadin.flow.data.provider.Query;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.shared.Registration;
import io.jmix.core.DataManager;
import io.jmix.core.MetadataTools;
import io.jmix.core.metamodel.model.MetaClass;
import io.jmix.flowui.component.codeeditor.CodeEditor;
import io.jmix.flowui.component.codeeditor.autocomplete.JpqlUiSuggestionProvider;
import io.jmix.flowui.component.combobox.JmixComboBox;
import io.jmix.flowui.component.textarea.JmixTextArea;
import io.jmix.flowui.kit.component.ComponentUtils;
import io.jmix.flowui.kit.component.button.JmixButton;
import io.jmix.flowui.view.*;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Route(value = "jpql-test-view", layout = MainView.class)
@ViewController(id = "JpqlTestView")
@ViewDescriptor(path = "jpql-test-view.xml")
public class JpqlTestView extends StandardView {
@Autowired
private JpqlUiSuggestionProvider jpqlSuggestionProvider;
@Autowired
private MetadataTools metadataTools;
@Autowired
private DataManager dataManager;
@ViewComponent
private CodeEditor codeField;
@ViewComponent
private JmixComboBox<Class<?>> entityComboBox;
@ViewComponent
private JmixTextArea resultsField;
@Subscribe
public void onInit(final InitEvent event) {
codeField.setSuggester(context ->
jpqlSuggestionProvider.getSuggestions(
context,
context.getText(),
context.getCursorPosition() - 1
)
);
Map<Class<?>, String> entities = new LinkedHashMap<>();
for (MetaClass metaClass : metadataTools.getAllJpaEntityMetaClasses()) {
entities.put(metaClass.getJavaClass(), metaClass.getName());
}
ComponentUtils.setItemsMap(entityComboBox, entities);
}
@Subscribe(id = "testBtn", subject = "clickListener")
public void onTestBtnClick(final ClickEvent<JmixButton> event) {
if (codeField.getValue() != null) {
List<?> list;
if (entityComboBox.getValue() != null) {
list = dataManager.load(entityComboBox.getValue()).query(codeField.getValue()).list();
} else {
list = dataManager.loadValues(codeField.getValue()).list();
}
resultsField.setValue(list.stream().map(Object::toString).collect(Collectors.joining("\n")));
System.out.println("Query results: " + list);
}
}
}

Regards,
Konstantin
1 Like