JavaFX и Lucene

#java #javafx #lucene

Вопрос:

Я создаю проект типа поисковой системы, в котором мне нужно создать пользовательский интерфейс в JavaFX и использовать Apache Lucene для запросов. Я нахожусь на стадии, когда пользовательский интерфейс в JavaFX отлично работает сам по себе(без вызова каких-либо методов Lucene), и запросы для Lucene также отлично работают сами по себе(в отдельном проекте Java). Когда я пытаюсь объединить их, создав объект Lucene в действии, выполняемом при нажатии кнопки ВВОДА, он сильно падает, и исключение далеко не сбивает с толку.

Я предоставляю код как для моего Window , так и для моих LuceneTester классов, а также для исключения.

Основной класс:

 public class Main extends Application {
    
    @Override
    public void start(Stage primaryStage) {
        new Window(primaryStage);
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}
 

Класс окна

 public class Window{

    public Window(Stage primaryStage) {
        VBox root = new VBox();
        root.getChildren().addAll(setSearch(), setBody());
        
        Scene scene = new Scene(root);
        primaryStage.setTitle("The Reuters Search Assistant");
        primaryStage.getIcons().add(new Image(getClass().getResourceAsStream("icon.png")));
        primaryStage.requestFocus();
        primaryStage.setMinWidth(1280);
        primaryStage.setMinHeight(720);
        primaryStage.setResizable(false);
        primaryStage.setScene(scene);
        primaryStage.show();
    }
    
    private VBox setSearch() {
        Label search = new Label("Search");
        search.setFont(new Font("arial", 30));
        search.setPadding(new Insets(5.0, 5.0, 5.0, 5.0));
        search.setAlignment(Pos.CENTER_LEFT);
        search.setTextAlignment(TextAlignment.LEFT);
        
        TextField searchBar = new TextField();
        searchBar.setFont(new Font("arial", 14));
        searchBar.setPromptText("type here");
        searchBar.setAlignment(Pos.CENTER_LEFT);
        searchBar.setOnKeyPressed(event -> {
            if (event.getCode() == KeyCode.ENTER) {
                searchAction(searchBar.getText());
            }
        });
        
        Separator separator = new Separator();
        separator.setOrientation(Orientation.HORIZONTAL);
        separator.setPadding(new Insets(5.0, 0, 0, 0));
        
        VBox searchPanel = new VBox();
        searchPanel.setAlignment(Pos.TOP_LEFT);
        searchPanel.setPadding(new Insets(5.0, 5.0, 0 ,5.0));
        searchPanel.setSpacing(5.0);
        searchPanel.fillWidthProperty();
        searchPanel.getChildren().addAll(search, searchBar, separator);
        return searchPanel;
    }
    
    private HBox setBody() {
        Button addBtn = new Button("Add Article");
        addBtn.setFont(new Font("arial", 20));
        addBtn.setMinWidth(170);
        addBtn.setOnMouseClicked(e -> {
            addArticleAction();
        });
        
        Button editBtn = new Button("Edit Article");
        editBtn.setFont(new Font("arial", 20));
        editBtn.setMinWidth(170);
        editBtn.setOnMouseClicked(e -> {
            editArticleAction();
        });
        
        Button delBtn = new Button("Delete Article");
        delBtn.setFont(new Font("arial", 20));
        delBtn.setMinWidth(170);
        delBtn.setOnMouseClicked(e -> {
            delArticleAction();
        });
        
        VBox buttonsBox = new VBox();
        buttonsBox.setAlignment(Pos.TOP_CENTER);
        buttonsBox.setMinWidth(200);
        buttonsBox.setPadding(new Insets(15.0, 5.0, 5.0, 5.0));
        buttonsBox.setSpacing(20.0);
        buttonsBox.getChildren().addAll(addBtn, editBtn, delBtn);
        
        Separator separator = new Separator();
        separator.setOrientation(Orientation.VERTICAL);
        
        ListView listView = new ListView();
        listView.setMinWidth(1050);
        listView.setMinHeight(574);
        
        VBox listViewBox = new VBox();
        listViewBox.setPadding(new Insets(5.0, 0, 0, 1.0));
        listViewBox.getChildren().add(listView);
        
        HBox bodyPanel = new HBox();
        bodyPanel.getChildren().addAll(buttonsBox, separator, listViewBox);
        return bodyPanel;
    }
    
    private void searchAction(String searchString) {
        System.out.println("Searching for : "   searchString);
        // Here is where the exception occurs.
        LuceneTester search = new LuceneTester(searchString);
    }
    
    private void addArticleAction() {
        System.out.println("add article");
    }
    
    private void editArticleAction() {
        System.out.println("edit article");
    }
    
    private void delArticleAction() {
        System.out.println("delete article");
    }
}
 

Класс LuceneTester

 public class LuceneTester {
    
    String indexDir = "C:\Users\stefa\eclipse-workspace\TReSA\index";
    String dataDir = "C:\Users\stefa\eclipse-workspace\TReSA\data";
    Indexer indexer;
    Searcher searcher;
    
    public LuceneTester(String searchString) {
        try {
            this.createIndex();
            this.search(searchString);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
    
    private void createIndex() throws IOException {
        indexer = new Indexer(indexDir);
        int numIndexed;
        long startTime = System.currentTimeMillis();
        numIndexed = indexer.createIndex(dataDir, new TextFileFilter());
        long endTime = System.currentTimeMillis();
        indexer.close();
        System.out.println(numIndexed   " File(s) indexed, time taken: "   (endTime-startTime)   " ms");
    }
    
    private void search(String searchQuery) throws IOException, ParseException {
        searcher = new Searcher(indexDir);
        long startTime = System.currentTimeMillis();
        TopDocs hits = searcher.search(searchQuery);
        long endTime = System.currentTimeMillis();
        System.out.println(hits.totalHits  " found. Time : "   (endTime - startTime)   " ms");
        for(ScoreDoc scoreDoc : hits.scoreDocs) {
            Document doc = searcher.getDocument(scoreDoc);
            System.out.println("File: "   doc.get(LuceneConstants.FILE_PATH));
        }
    }
}
 

Исключение

 Exception in thread "JavaFX Application Thread" java.lang.NoClassDefFoundError: org/apache/lucene/queryparser/classic/ParseException
    at com.TReSA.main.Window.searchAction(Window.java:116)
    at com.TReSA.main.Window.lambda$0(Window.java:52)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
    at javafx.graphics/javafx.scene.Scene$KeyHandler.process(Scene.java:4105)
    at javafx.graphics/javafx.scene.Scene.processKeyEvent(Scene.java:2156)
    at javafx.graphics/javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2630)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:218)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:150)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$1(GlassViewEventHandler.java:250)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
    at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:249)
    at javafx.graphics/com.sun.glass.ui.View.handleKeyEvent(View.java:548)
    at javafx.graphics/com.sun.glass.ui.View.notifyKey(View.java:972)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.ClassNotFoundException: org.apache.lucene.queryparser.classic.ParseException
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
    ... 29 more
 

Заранее спасибо.

Ответ №1:

Это ClassNotFoundException: org.apache.lucene.queryparser.classic.ParseException означает, что отсутствует зависимость от Lucene, поэтому вам следует проверить настройки инструментов сборки.

Но это также означает, что произошло исключение, поэтому вы можете дважды проверить, действительно ли работает код только для Lucene.

Комментарии:

1. Я снова проверил свой код, и, похоже, он работает нормально. В моем пути сборки Java я включаю lucene.core и lucene. библиотеки анализаторов запросов. Должен ли я включить еще один, который поддерживает JavaFX для работы? И если да, то какой именно?

2. Там нет конкретного пакета JavaFX, который был бы необходим. По крайней мере, это не то, на что указывает эта ошибка. Вам нужно будет показать, как вы создаете и включаете эти зависимости. FWIW вам, вероятно, было бы лучше переключиться на Maven или Gradle для управления своими зависимостями, так как похоже, что вы пытаетесь сделать это вручную. Это значительно облегчит вашу жизнь в долгосрочной перспективе.

3. Я только что понял, что мое затмение отключило библиотеки в разделе зависимостей. С перезагрузкой и после переустановки все работало отлично. Большое спасибо!