From 25c33bc4a445484d6e3fa413ac1385229fc75fd7 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Thu, 3 Nov 2022 19:38:05 +0100 Subject: [PATCH 01/61] Update to Spring Boot 2.5.14 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a3cc346a8e..beda3e6ad0 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.5.12 + 2.5.14 From bffdbedf8c5a7dde15e214f665d49c8700f62d2b Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Thu, 3 Nov 2022 20:21:05 +0100 Subject: [PATCH 02/61] Upgrade to Spring Booot 2.7.5 --- pom.xml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index beda3e6ad0..325ee1e093 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.5.14 + 2.7.5 @@ -575,6 +575,11 @@ com.fasterxml.jackson.dataformat jackson-dataformat-toml + + + com.fasterxml.jackson.module + jackson-module-jaxb-annotations + org.apache.commons From f3424281d764071f52f4b5acd1eaadf8ed36fbd2 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Thu, 3 Nov 2022 20:24:48 +0100 Subject: [PATCH 03/61] Don't configure kotlin stdlib manually --- pom.xml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pom.xml b/pom.xml index 325ee1e093..b05e1e784b 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,6 @@ server 1.5.24 1.8.4 - 1.6.0 @@ -528,13 +527,6 @@ compile - - org.jetbrains.kotlin - kotlin-stdlib - ${kotlin.version} - test - - org.apache.httpcomponents httpclient From 403ed4e834ffea3a5c21bc2105a5980619aa07aa Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Thu, 3 Nov 2022 21:04:32 +0100 Subject: [PATCH 04/61] Configure OpenApi to generate the Spring WebClient (does not compile yet) The WebClient is a Spring class that can support automatic refreshing of the token. But using this new API means we have to change all calls to the (possible blocking) WebFlux calls. --- pom.xml | 1429 +++++++++-------- .../annis/gui/CorpusBrowserPanel.java | 16 +- 2 files changed, 726 insertions(+), 719 deletions(-) diff --git a/pom.xml b/pom.xml index b05e1e784b..3c028fc5c8 100644 --- a/pom.xml +++ b/pom.xml @@ -1,726 +1,737 @@ - 4.0.0 - - - org.springframework.boot - spring-boot-starter-parent - 2.7.5 - - - - org.corpus-tools - annis - 4.10.1-SNAPSHOT - ANNIS user interface - jar - - scm:git:https://github.com/korpling/ANNIS.git - scm:git:git@github.com:korpling/ANNIS.git - https://github.com/korpling/ANNIS - v4.5.3 - - - - Corpuslinguistic working group Humboldt University Berlin - http://www.linguistik.hu-berlin.de/institut/professuren/korpuslinguistik/ - - - - The Apache Software License, Version 2.0 - http://www.apache.org/licenses/LICENSE-2.0.txt - - - - - UTF-8 - 1.8 - 8.14.3 - true - org.corpus_tools.annis.gui.AnnisUiApplication - 2.4.0 - 4.7.2 - server - 1.5.24 - 1.8.4 - - - - - vaadin-snapshots - https://oss.sonatype.org/content/repositories/vaadin-snapshots/ - - false - - - true - - - - vaadin-addons - https://maven.vaadin.com/vaadin-addons - - - - - - - src/main/resources - false - - - src/main/resources - true - - **/*.properties - - - - src/main/webapp - - - ${project.build.directory}/native/ - - - - - - - org.jacoco - jacoco-maven-plugin - 0.8.6 - - - VAADIN/** - - - - - pre-unit-test - - prepare-agent - - - jacoco.agent.arg - - - - report - verify - - report - - - - - - org.springframework.boot - spring-boot-maven-plugin - - ${start-class} - - - - repackage - - repackage - - - ${spring.profiles.active} - true - - - - - - org.corpus-tools - cff-maven-plugin - 0.5.0 - - ${project.basedir}/misc/cff-templates/CITATION_input.yml - false - - - - - - - - co.enear.maven.plugins - keepachangelog-maven-plugin - 2.1.1 - - - org.apache.maven.plugins - maven-release-plugin - - clean verify keepachangelog:release cff:create cff:third-party-folder scm:add scm:checkin - v@{project.version} - install - - - - org.apache.maven.plugins - maven-scm-plugin - 1.11.3 - - CHANGELOG.md,CITATION.cff,THIRD-PARTY/**,src/main/webapp/VAADIN/help/** - Files updated in release process - - - - com.vaadin - vaadin-maven-plugin - ${vaadin.version} - - - - update-theme - update-widgetset - compile - compile-theme - - - - - 9 - - - - - - org.antlr - antlr4-maven-plugin - ${antlr4.version} - - src/main/antlr4 - - - - - antlr4 - - - - - - - org.codehaus.mojo - buildnumber-maven-plugin - 1.4 - - - validate - - create - - - - - false - false - {0, time, yyyy-MM-dd_HH-mm-ss} - 10 - - - - org.apache.maven.plugins - maven-surefire-plugin - - ${jacoco.agent.arg} - - - - org.springframework.boot - spring-boot-maven-plugin - - - org.apache.maven.plugins - maven-site-plugin - 3.9.1 - - - com.googlecode.maven-download-plugin - download-maven-plugin - 1.6.0 - - - download-linux-binaries - generate-resources - - wget - - - https://github.com/korpling/graphANNIS/releases/download/v${graphannis.version}/graphannis-webservice - ${project.build.directory}/native/linux-x86-64/ - 1ba957fb9137ce6c8a8d53a9d941f96ab4834ed3e55c183be5367db87ef57ea3 - - - - download-windows-binaries - generate-resources - - wget - - - https://github.com/korpling/graphANNIS/releases/download/v${graphannis.version}/graphannis-webservice.exe - ${project.build.directory}/native/win32-x86-64/ - 3b7fc6fc40662b9ae833489a111968d6149d1c16f1d3731accc99cff58c97d92 - - - - download-mac-binaries - generate-resources - - wget - - - https://github.com/korpling/graphANNIS/releases/download/v${graphannis.version}/graphannis-webservice.osx - ${project.build.directory}/native/darwin/ - c0a5c299fad646afeecb6527a195645a121bd85425e658f42f946ec67e7b06eb - - - - - - org.openapitools - openapi-generator-maven-plugin - 5.0.1 - - - - generate - - - + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.7.5 + + + + org.corpus-tools + annis + 4.10.1-SNAPSHOT + ANNIS user interface + jar + + scm:git:https://github.com/korpling/ANNIS.git + scm:git:git@github.com:korpling/ANNIS.git + https://github.com/korpling/ANNIS + v4.5.3 + + + + Corpuslinguistic working group Humboldt University Berlin + http://www.linguistik.hu-berlin.de/institut/professuren/korpuslinguistik/ + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + UTF-8 + 1.8 + 8.14.3 + true + org.corpus_tools.annis.gui.AnnisUiApplication + 2.4.0 + 4.7.2 + server + 1.5.24 + 1.8.4 + + + + + vaadin-snapshots + https://oss.sonatype.org/content/repositories/vaadin-snapshots/ + + false + + + true + + + + vaadin-addons + https://maven.vaadin.com/vaadin-addons + + + + + + + src/main/resources + false + + + src/main/resources + true + + **/*.properties + + + + src/main/webapp + + + ${project.build.directory}/native/ + + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.6 + + + VAADIN/** + + + + + pre-unit-test + + prepare-agent + + + jacoco.agent.arg + + + + report + verify + + report + + + + + + org.springframework.boot + spring-boot-maven-plugin + + ${start-class} + + + + repackage + + repackage + + + ${spring.profiles.active} + true + + + + + + org.corpus-tools + cff-maven-plugin + 0.5.0 + + ${project.basedir}/misc/cff-templates/CITATION_input.yml + false + + + + + + + + co.enear.maven.plugins + keepachangelog-maven-plugin + 2.1.1 + + + org.apache.maven.plugins + maven-release-plugin + + clean verify keepachangelog:release cff:create cff:third-party-folder scm:add scm:checkin + v@{project.version} + install + + + + org.apache.maven.plugins + maven-scm-plugin + 1.11.3 + + CHANGELOG.md,CITATION.cff,THIRD-PARTY/**,src/main/webapp/VAADIN/help/** + Files updated in release process + + + + com.vaadin + vaadin-maven-plugin + ${vaadin.version} + + + + update-theme + update-widgetset + compile + compile-theme + + + + + 9 + + + + + + org.antlr + antlr4-maven-plugin + ${antlr4.version} + + src/main/antlr4 + + + + + antlr4 + + + + + + + org.codehaus.mojo + buildnumber-maven-plugin + 1.4 + + + validate + + create + + + + + false + false + {0, time, yyyy-MM-dd_HH-mm-ss} + 10 + + + + org.apache.maven.plugins + maven-surefire-plugin + + ${jacoco.agent.arg} + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-site-plugin + 3.9.1 + + + com.googlecode.maven-download-plugin + download-maven-plugin + 1.6.0 + + + download-linux-binaries + generate-resources + + wget + + + https://github.com/korpling/graphANNIS/releases/download/v${graphannis.version}/graphannis-webservice + ${project.build.directory}/native/linux-x86-64/ + 1ba957fb9137ce6c8a8d53a9d941f96ab4834ed3e55c183be5367db87ef57ea3 + + + + download-windows-binaries + generate-resources + + wget + + + https://github.com/korpling/graphANNIS/releases/download/v${graphannis.version}/graphannis-webservice.exe + ${project.build.directory}/native/win32-x86-64/ + 3b7fc6fc40662b9ae833489a111968d6149d1c16f1d3731accc99cff58c97d92 + + + + download-mac-binaries + generate-resources + + wget + + + https://github.com/korpling/graphANNIS/releases/download/v${graphannis.version}/graphannis-webservice.osx + ${project.build.directory}/native/darwin/ + c0a5c299fad646afeecb6527a195645a121bd85425e658f42f946ec67e7b06eb + + + + + + org.openapitools + openapi-generator-maven-plugin + 6.0.0 + + + + generate + + + ${project.basedir}/src/main/resources/openapi.yml - java - org.corpus_tools.annis.api - org.corpus_tools.annis.api.model - true - ApiResponse.java,ApiException.java,ApiCallback.java,Pair.java,ApiClient.java,Configuration.java,ProgressRequestBody.java,JSON.java,Authentication.java,StringUtil.java,ApiKeyAuth.java,HttpBasicAuth.java,ProgressResponseBody.java,HttpBearerAuth.java - false - false - false - false - - true - java8 - - serializableModel=true - - - - - - - - - - - com.vaadin - vaadin-bom - ${vaadin.version} - pom - import - - - org.keycloak.bom - keycloak-adapter-bom - 11.0.2 - pom - import - - - - - - - - com.vaadin - vaadin-spring-boot-starter - - - - com.vaadin - vaadin-push - - - - com.vaadin - vaadin-compatibility-server - - - com.vaadin - vaadin-compatibility-themes - - - com.vaadin - vaadin-compatibility-client - provided - - - com.vaadin - vaadin-compatibility-client-compiled - - - - org.springframework.boot - spring-boot-starter-test - test - - - org.junit.vintage - junit-vintage-engine - - - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - - org.springframework.boot - spring-boot-starter-oauth2-client - - - - org.springframework.boot - spring-boot-configuration-processor - - - - org.springframework.security - spring-security-crypto - - - - com.github.jjYBdx4IL.utils - swing-utils - 1.0 - - - - com.h2database - h2 - runtime - - - - org.corpus-tools - salt-api - 3.4.2 - - - - com.google.guava - guava - - - - - - io.swagger - swagger-annotations - ${swagger-core-version} - - - - com.squareup.okhttp3 - okhttp - - - - com.squareup.okhttp3 - mockwebserver - test - - - - com.squareup.okhttp3 - logging-interceptor - - - - com.google.code.gson - gson - - - io.gsonfire - gson-fire - ${gson-fire-version} - - - - javax.ws.rs - jsr311-api - 1.1.1 - - - + + com.google.guava + guava + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + + com.squareup.okhttp3 + okhttp + + + + com.squareup.okhttp3 + mockwebserver + test + + + + com.squareup.okhttp3 + logging-interceptor + + + + com.google.code.gson + gson + + + io.gsonfire + gson-fire + ${gson-fire-version} + + + + javax.ws.rs + jsr311-api + 1.1.1 + + + - - javax.interceptor - javax.interceptor-api - 1.2.2 - - - - - com.github.vaadin4qbanos - jsclipboard - 1.0.12 - - - com.vaadin - vaadin-server - - - - - - net.sf.opencsv - opencsv - 2.3 - jar - - - - com.auth0 - java-jwt - 3.10.3 - - - - - net.sf.jung - jung-api - 2.0.1 - - - net.sf.jung - jung-graph-impl - 2.0.1 - - - - com.hp.gagawa - gagawa - 1.0.1 - compile - - - - org.antlr - antlr4 - ${antlr4.version} - compile - - - - org.antlr - antlr4-runtime - ${antlr4.version} - compile - - - - org.apache.httpcomponents - httpclient - - - - com.github.romankh3 - image-comparison - 4.3.0 - test - - - - org.jsoup - jsoup - 1.15.3 - - - - org.aeonbits.owner - owner - 1.0.10 - - - - org.apache.tika - tika-core - 1.24.1 - - - - joda-time - joda-time - 2.10.6 - - - - com.fasterxml.jackson.dataformat - jackson-dataformat-toml - - + + javax.interceptor + javax.interceptor-api + 1.2.2 + + + + + com.github.vaadin4qbanos + jsclipboard + 1.0.12 + + + com.vaadin + vaadin-server + + + + + + net.sf.opencsv + opencsv + 2.3 + jar + + + + com.auth0 + java-jwt + 3.10.3 + + + + + net.sf.jung + jung-api + 2.0.1 + + + net.sf.jung + jung-graph-impl + 2.0.1 + + + + com.hp.gagawa + gagawa + 1.0.1 + compile + + + + org.antlr + antlr4 + ${antlr4.version} + compile + + + + org.antlr + antlr4-runtime + ${antlr4.version} + compile + + + + org.apache.httpcomponents + httpclient + + + + com.github.romankh3 + image-comparison + 4.3.0 + test + + + + org.jsoup + jsoup + 1.15.3 + + + + org.aeonbits.owner + owner + 1.0.10 + + + + org.apache.tika + tika-core + 1.24.1 + + + + joda-time + joda-time + 2.10.6 + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-toml + + com.fasterxml.jackson.module jackson-module-jaxb-annotations - - org.apache.commons - commons-email - 1.5 - compile - - - - commons-io - commons-io - 2.7 - compile - - - + + org.apache.commons + commons-email + 1.5 + compile + + + + commons-io + commons-io + 2.7 + compile + + + org.apache.commons commons-text [1.10.0,) compile - - commons-codec - commons-codec - compile - - - - com.fasterxml.jackson.dataformat - jackson-dataformat-xml - - - - com.google.guava - guava-gwt - 20.0 - - - - com.google.code.findbugs - jsr305 - 3.0.2 - - - - com.github.mvysny.kaributesting - karibu-testing-v8 - 1.3.17 - test - - - - - org.vaadin.addons - popupbutton - 3.0.0 - - - - - org.vaadin.extension - GridScrollExtension - 2.5.1 - - - - - - coverage - - - - org.jacoco - jacoco-maven-plugin - - - - - - desktop - - desktop - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - BOOT-INF/classes/splashscreen.gif - - - - - - - - - mdbook - - - ${user.home}/.cargo/bin/mdbook - - - - - - - - org.codehaus.mojo - exec-maven-plugin - 3.0.0 - - - compile-online-help - compile - - exec - - - ${user.home}/.cargo/bin/mdbook - ${project.build.directory} - - build - -d - ${project.basedir}/src/main/webapp/VAADIN/help/ - ${project.basedir}/docs/online-help/ - - - - - - - - maven-clean-plugin - - - - ${project.basedir}/src/main/webapp/VAADIN/help/ - false - - - - - - - - + + commons-codec + commons-codec + compile + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + + + + com.google.guava + guava-gwt + 20.0 + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + + com.github.mvysny.kaributesting + karibu-testing-v8 + 1.3.17 + test + + + + + org.vaadin.addons + popupbutton + 3.0.0 + + + + + org.vaadin.extension + GridScrollExtension + 2.5.1 + + + + + + coverage + + + + org.jacoco + jacoco-maven-plugin + + + + + + desktop + + desktop + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + BOOT-INF/classes/splashscreen.gif + + + + + + + + + mdbook + + + ${user.home}/.cargo/bin/mdbook + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.0.0 + + + compile-online-help + compile + + exec + + + ${user.home}/.cargo/bin/mdbook + ${project.build.directory} + + build + -d + ${project.basedir}/src/main/webapp/VAADIN/help/ + ${project.basedir}/docs/online-help/ + + + + + + + + maven-clean-plugin + + + + ${project.basedir}/src/main/webapp/VAADIN/help/ + false + + + + + + + + diff --git a/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java b/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java index 7e6e613860..00c42581c4 100644 --- a/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java @@ -33,7 +33,6 @@ import java.util.Optional; import java.util.Set; import java.util.TreeSet; -import java.util.stream.Collectors; import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.AnnoKey; @@ -183,10 +182,10 @@ private void fetchAnnotationsInBackground(UI ui) { CorporaApi api = new CorporaApi(Helper.getClient(ui)); try { - final List nodeAnnos = api.nodeAnnotations(corpus, true, true).stream() + final List nodeAnnos = api.nodeAnnotations(corpus, true, true) .filter(a -> !Objects.equals(a.getKey().getNs(), "annis") && !Objects.equals(a.getKey().getName(), "tok")) - .collect(Collectors.toList()); + .collectList().block(); final List metaAnnos = new LinkedList<>(nodeAnnos); @@ -194,19 +193,16 @@ private void fetchAnnotationsInBackground(UI ui) { nodeAnnos.removeIf(anno -> metaAnnoKeys.contains(anno.getKey())); metaAnnos.removeIf(anno -> !metaAnnoKeys.contains(anno.getKey())); - final List components = api.components(corpus, "Dominance", null); + final List components = + api.components(corpus, "Dominance", null).collectList().block(); final List allEdgeAnnos = new LinkedList<>(); final Map> edgeAnnosByComponent = new LinkedHashMap<>(); - components.addAll(api.components(corpus, "Pointing", null)); + components.addAll(api.components(corpus, "Pointing", null).collectList().block()); for (Component c : components) { - try { List annos = api.edgeAnnotations(corpus, c.getType().getValue(), c.getLayer(), - c.getName(), true, true); + c.getName(), true, true).collectList().block(); edgeAnnosByComponent.put(c, annos); allEdgeAnnos.addAll(annos); - } catch (ApiException ex) { - // Ignore any not found errors - } } getUI().access(() -> { From b0d0e37022f3b020088ad369aa0d0a3c551f155e Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Wed, 9 Nov 2022 15:36:37 +0100 Subject: [PATCH 05/61] Fix more of the compilation issues from changing to Spring WebClient --- .../annis/gui/CorpusBrowserPanel.java | 5 +++++ .../org/corpus_tools/annis/gui/SearchView.java | 11 ++++++----- .../annis/gui/admin/model/CorpusManagement.java | 8 +++++--- .../annis/gui/admin/reflinks/MigrationPanel.java | 2 +- .../gui/controlpanel/SearchOptionsPanel.java | 11 +++++++---- .../annis/gui/exporter/ExportHelper.java | 16 ++++++---------- .../annis/gui/exporter/GeneralTextExporter.java | 2 +- .../gui/flatquerybuilder/FlatQueryBuilder.java | 9 +++++---- .../querybuilder/TigerQueryBuilderCanvas.java | 6 +++--- .../visualizers/component/pdf/PDFPanelTest.java | 8 +++----- 10 files changed, 42 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java b/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java index 00c42581c4..4a2dfdd04f 100644 --- a/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java @@ -43,6 +43,7 @@ import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.objects.Query; import org.corpus_tools.annis.gui.objects.QueryLanguage; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -199,10 +200,14 @@ private void fetchAnnotationsInBackground(UI ui) { final Map> edgeAnnosByComponent = new LinkedHashMap<>(); components.addAll(api.components(corpus, "Pointing", null).collectList().block()); for (Component c : components) { + try { List annos = api.edgeAnnotations(corpus, c.getType().getValue(), c.getLayer(), c.getName(), true, true).collectList().block(); edgeAnnosByComponent.put(c, annos); allEdgeAnnos.addAll(annos); + } catch (WebClientResponseException ex) { + // Ignore any not found errors + } } getUI().access(() -> { diff --git a/src/main/java/org/corpus_tools/annis/gui/SearchView.java b/src/main/java/org/corpus_tools/annis/gui/SearchView.java index 5344613e9e..9d7ea24802 100644 --- a/src/main/java/org/corpus_tools/annis/gui/SearchView.java +++ b/src/main/java/org/corpus_tools/annis/gui/SearchView.java @@ -46,7 +46,6 @@ import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.controlpanel.ControlPanel; @@ -63,6 +62,7 @@ import org.corpus_tools.annis.gui.objects.QueryLanguage; import org.corpus_tools.annis.gui.resultview.ResultViewPanel; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * The view which shows the search interface. @@ -243,9 +243,9 @@ public void evaluateCitation(String relativeUri) { // later CorporaApi api = new CorporaApi(Helper.getClient(ui)); try { - List userCorpora = api.listCorpora(); + List userCorpora = api.listCorpora().collectList().block(); selectedCorpora.retainAll(userCorpora); - } catch (ApiException ex) { + } catch (WebClientResponseException ex) { log.error("Could not get list of corpora", ex); } @@ -291,9 +291,10 @@ private void evaluateFragment(String fragment) { // Remove all corpora we don't have the access right to try { CorporaApi api = new CorporaApi(Helper.getClient(ui)); - Set availableCorpora = new HashSet<>(api.listCorpora()); + Set availableCorpora = + new HashSet<>(api.listCorpora().collectList().block()); corpora.removeIf(c -> !availableCorpora.contains(c)); - } catch (ApiException e) { + } catch (WebClientResponseException e) { ExceptionDialog.show(e, "Could not get corpus list", ui); } diff --git a/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java b/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java index 6c1ca8dbd1..ce8fca2266 100644 --- a/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java +++ b/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java @@ -23,6 +23,8 @@ import org.corpus_tools.annis.gui.ServiceQueryException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * A model that handles the corpus list @@ -69,9 +71,9 @@ public void fetchFromService() throws CriticalServiceQueryException, ServiceQuer CorporaApi api = new CorporaApi(clientProvider.getClient()); try { - corpora.addAll(api.listCorpora()); - } catch (ApiException ex) { - if (ex.getCode() == Response.Status.UNAUTHORIZED.getStatusCode()) { + corpora.addAll(api.listCorpora().collectList().block()); + } catch (WebClientResponseException ex) { + if (ex.getStatusCode() == HttpStatus.UNAUTHORIZED) { throw new CriticalServiceQueryException("You are not authorized to get the corpus list."); } else { log.error(null, ex); diff --git a/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java b/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java index cc57177817..3175d553a6 100644 --- a/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java @@ -304,7 +304,7 @@ private int migrateUrlShortener(String serviceURL, String username, String passw ApiClient apiClient = Helper.getClient(ui); CorporaApi corporaApi = new CorporaApi(apiClient); SearchApi searchApi = new SearchApi(apiClient); - Set knownCorpora = new HashSet<>(corporaApi.listCorpora()); + Set knownCorpora = new HashSet<>(corporaApi.listCorpora().collectList().block()); Optional client = createClient(serviceURL, username, password); diff --git a/src/main/java/org/corpus_tools/annis/gui/controlpanel/SearchOptionsPanel.java b/src/main/java/org/corpus_tools/annis/gui/controlpanel/SearchOptionsPanel.java index ad57eca6ce..0f8d5633d1 100644 --- a/src/main/java/org/corpus_tools/annis/gui/controlpanel/SearchOptionsPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/controlpanel/SearchOptionsPanel.java @@ -31,7 +31,6 @@ import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.AnnotationComponentType; import org.corpus_tools.annis.api.model.Component; @@ -46,6 +45,8 @@ import org.corpus_tools.annis.gui.objects.QueryUIState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -140,13 +141,15 @@ private static List getSegmentationNamesFromService(Collection c for (String corpus : corpora) { try { // Get all ordering components - for(Component c : corporaApi.components(corpus, AnnotationComponentType.ORDERING.getValue(), null)) { + for (Component c : corporaApi + .components(corpus, AnnotationComponentType.ORDERING.getValue(), null).collectList() + .block()) { if (!c.getName().isEmpty() && !"annis".equals(c.getLayer())) { segNames.add(c.getName()); } } - } catch (ApiException ex) { - if (ex.getCode() == 403) { + } catch (WebClientResponseException ex) { + if (ex.getStatusCode() == HttpStatus.FORBIDDEN) { log.debug("Did not have access rights to query segmentation names for corpus", ex); } else { log.warn("Could not query segmentation names for corpus", ex); diff --git a/src/main/java/org/corpus_tools/annis/gui/exporter/ExportHelper.java b/src/main/java/org/corpus_tools/annis/gui/exporter/ExportHelper.java index 03e023b01b..ae83c8d0e2 100644 --- a/src/main/java/org/corpus_tools/annis/gui/exporter/ExportHelper.java +++ b/src/main/java/org/corpus_tools/annis/gui/exporter/ExportHelper.java @@ -16,7 +16,6 @@ import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.AnnotationComponentType; -import org.corpus_tools.annis.api.model.Component; import org.corpus_tools.annis.api.model.CorpusConfiguration; import org.corpus_tools.annis.api.model.CorpusConfigurationViewTimelineStrategy.StrategyEnum; import org.corpus_tools.annis.api.model.SubgraphWithContext; @@ -76,15 +75,12 @@ private static void recreateTimelineIfNecessary(SaltProject p, CorporaApi corpor } // Get all segmentation names - Set segNames = new TreeSet<>(); - for (Component c : corporaApi.components(firstCorpusName, - AnnotationComponentType.ORDERING.getValue(), null)) { - if (!c.getName().isEmpty() && !"annis".equals(c.getLayer())) { - segNames.add(c.getName()); - } - } + List segNames = corporaApi.components(firstCorpusName, + AnnotationComponentType.ORDERING.getValue(), null) + .filter(c -> !c.getName().isEmpty() && !"annis".equals(c.getLayer())).map(c -> c.getName()) + .collectList().block(); - recreateTimeline(p, timelineStrategy, segNames, config); + recreateTimeline(p, timelineStrategy, new TreeSet<>(segNames), config); } private static void recreateTimeline(SaltProject p, StrategyEnum timelineStrategy, @@ -143,7 +139,7 @@ protected static Optional getSubgraphForMatch(String match, Corpora subgraphQuery.setSegmentation(args.get(SEGMENTATION_KEY)); } - File graphML = corporaApi.subgraphForNodes(corpusNameForMatch, subgraphQuery); + File graphML = corporaApi.subgraphForNodes(corpusNameForMatch, subgraphQuery).block(); SDocumentGraph docGraph = DocumentGraphMapper.map(graphML); SaltProject p = documentGraphToProject(docGraph, corpusPathForMatch); diff --git a/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java b/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java index f439c99874..2b07159d7d 100644 --- a/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java +++ b/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java @@ -232,7 +232,7 @@ protected List getAllAnnotationsAsExporterKey(Collection corpora List attributes = new LinkedList<>(); for (String corpus : corpora) { - attributes.addAll(api.nodeAnnotations(corpus, false, false)); + attributes.addAll(api.nodeAnnotations(corpus, false, false).collectList().block()); } for (Annotation a : attributes) { diff --git a/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java b/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java index 7ba034fc33..b80e940942 100644 --- a/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java +++ b/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java @@ -46,6 +46,7 @@ import org.corpus_tools.annis.gui.objects.QueryUIState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; /* * @author martin klotz (martin.klotz@hu-berlin.de) @@ -335,14 +336,14 @@ public Collection getAvailableAnnotationLevels(String meta) { try { List atts = new LinkedList<>(); for (String corpus : corpusSelection) { - atts.addAll(api.nodeAnnotations(corpus, true, false)); + atts.addAll(api.nodeAnnotations(corpus, true, false).collectList().block()); } for (Annotation a : atts) { if (a.getKey().getName().equals(meta)) { result.add(a.getVal()); } } - } catch (ApiException ex) { + } catch (WebClientResponseException ex) { log.error(null, ex); } @@ -356,11 +357,11 @@ public Set getAvailableAnnotationNames() { CorporaApi api = new CorporaApi(Helper.getClient(UI.getCurrent())); try { for (String corpus : corpusSelection) { - for (Annotation a : api.nodeAnnotations(corpus, false, false)) { + for (Annotation a : api.nodeAnnotations(corpus, false, false).collectList().block()) { result.add(a.getKey().getName()); } } - } catch (ApiException ex) { + } catch (WebClientResponseException ex) { log.error(null, ex); } result.add("tok"); diff --git a/src/main/java/org/corpus_tools/annis/gui/querybuilder/TigerQueryBuilderCanvas.java b/src/main/java/org/corpus_tools/annis/gui/querybuilder/TigerQueryBuilderCanvas.java index 1fae58e0d0..1be530e07c 100644 --- a/src/main/java/org/corpus_tools/annis/gui/querybuilder/TigerQueryBuilderCanvas.java +++ b/src/main/java/org/corpus_tools/annis/gui/querybuilder/TigerQueryBuilderCanvas.java @@ -34,7 +34,6 @@ import java.util.Map; import java.util.Set; import java.util.TreeSet; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.Annotation; import org.corpus_tools.annis.gui.Helper; @@ -42,6 +41,7 @@ import org.corpus_tools.annis.gui.widgets.GripDragComponent; import org.corpus_tools.annis.gui.widgets.SimpleCanvas; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -320,10 +320,10 @@ public Set getAvailableAnnotationNames() { if (corpusSelection != null) { for (String corpus : corpusSelection) { try { - for (Annotation anno : api.nodeAnnotations(corpus, false, true)) { + for (Annotation anno : api.nodeAnnotations(corpus, false, true).collectList().block()) { result.add(anno.getKey().getName()); } - } catch (ApiException ex) { + } catch (WebClientResponseException ex) { log.error("Could not get node annotations for corpus " + corpus, ex); } } diff --git a/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java b/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java index 51016677c1..ddbeb46acc 100644 --- a/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java +++ b/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java @@ -9,19 +9,17 @@ import java.awt.FontFormatException; import java.io.IOException; -import java.util.Arrays; -import java.util.LinkedList; import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.AnnisUI; import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.visualizers.VisualizerInput; -import org.corpus_tools.annis.gui.visualizers.component.pdf.PDFPanel; import org.corpus_tools.salt.common.SCorpusGraph; import org.corpus_tools.salt.common.SDocument; import org.corpus_tools.salt.samples.SampleGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import reactor.core.publisher.Flux; class PDFPanelTest { @@ -51,7 +49,7 @@ void testBinaryPathOneFile() throws ApiException { // Make sure the document has an assigned PDF file CorporaApi api = mock(CorporaApi.class); when(api.listFiles(anyString(), anyString())) - .thenReturn(Arrays.asList("notapdf.webm", "test.pdf")); + .thenReturn(Flux.just("notapdf.webm", "test.pdf")); assertEquals("/context/Binary?toplevelCorpusName=rootCorpus&file=test.pdf", fixture.getBinaryPath(api)); @@ -67,7 +65,7 @@ void testBinaryPathNoFile() throws ApiException { // Make sure the document has an assigned PDF file CorporaApi api = mock(CorporaApi.class); - when(api.listFiles(anyString(), anyString())).thenReturn(new LinkedList<>()); + when(api.listFiles(anyString(), anyString())).thenReturn(Flux.just()); assertEquals("", fixture.getBinaryPath(api)); } From 811d77c25ed1d9d27c7518736856a52e9572b68c Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Wed, 9 Nov 2022 15:40:25 +0100 Subject: [PATCH 06/61] Use WebClientResponseException --- .../annis/gui/admin/model/CorpusManagement.java | 8 +++----- .../annis/gui/admin/model/GroupManagement.java | 5 +++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java b/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java index ce8fca2266..9a5c809074 100644 --- a/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java +++ b/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java @@ -16,8 +16,6 @@ import com.google.common.collect.ImmutableList; import java.io.Serializable; import java.util.TreeSet; -import javax.ws.rs.core.Response; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.CriticalServiceQueryException; import org.corpus_tools.annis.gui.ServiceQueryException; @@ -51,10 +49,10 @@ public void delete(String corpusName) CorporaApi api = new CorporaApi(clientProvider.getClient()); try { api.deleteCorpus(corpusName); - } catch (ApiException ex) { - if (ex.getCode() == Response.Status.UNAUTHORIZED.getStatusCode()) { + } catch (WebClientResponseException ex) { + if (ex.getStatusCode() == HttpStatus.UNAUTHORIZED) { throw new CriticalServiceQueryException("You are not authorized to delete a corpus"); - } else if (ex.getCode() == Response.Status.NOT_FOUND.getStatusCode()) { + } else if (ex.getStatusCode() == HttpStatus.NOT_FOUND) { throw new ServiceQueryException("Corpus with name " + corpusName + " not found"); } else { log.error(null, ex); diff --git a/src/main/java/org/corpus_tools/annis/gui/admin/model/GroupManagement.java b/src/main/java/org/corpus_tools/annis/gui/admin/model/GroupManagement.java index bda08db6ce..09badf091c 100644 --- a/src/main/java/org/corpus_tools/annis/gui/admin/model/GroupManagement.java +++ b/src/main/java/org/corpus_tools/annis/gui/admin/model/GroupManagement.java @@ -26,6 +26,7 @@ import org.corpus_tools.annis.gui.CaseSensitiveOrder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * A model for groups. @@ -52,7 +53,7 @@ public void createOrUpdateGroup(Group newGroup) { try { api.putGroup(newGroup.getName(), newGroup); groups.put(newGroup.getName(), newGroup); - } catch (ApiException ex) { + } catch (WebClientResponseException ex) { log.warn("Could not update group", ex); } @@ -65,7 +66,7 @@ public void deleteGroup(String groupName) { try { api.deleteGroup(groupName); groups.remove(groupName); - } catch (ApiException ex) { + } catch (WebClientResponseException ex) { log.warn("Could not update group", ex); } From 00b4bb68775b5f14e98325aff280abe73b68a28b Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Wed, 9 Nov 2022 15:46:20 +0100 Subject: [PATCH 07/61] Add block() to several of the more straight forward synchronous calls to get a file --- .../org/corpus_tools/annis/gui/Helper.java | 11 +++++----- .../gui/docbrowser/DocBrowserController.java | 6 +++--- .../annis/gui/docbrowser/DocBrowserPanel.java | 17 ++++++++------- .../gui/exporter/BaseMatrixExporter.java | 2 +- .../gui/exporter/GeneralTextExporter.java | 2 +- .../annis/gui/resultview/VisualizerPanel.java | 7 ++++--- .../gui/visualizers/htmlvis/HTMLVis.java | 21 ++++++++++--------- 7 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/Helper.java b/src/main/java/org/corpus_tools/annis/gui/Helper.java index 3ba2dd7fc0..7869aadf72 100644 --- a/src/main/java/org/corpus_tools/annis/gui/Helper.java +++ b/src/main/java/org/corpus_tools/annis/gui/Helper.java @@ -112,6 +112,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.oauth2.core.oidc.StandardClaimNames; import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -526,7 +527,7 @@ private static boolean annotationIsMetadata(String corpus, String annotationName q.setOffset(0); q.setQueryLanguage(QueryLanguage.AQL); - final File findResult = search.find(q); + final File findResult = search.find(q).block(); if (findResult != null && findResult.isFile()) try { try (Stream lines = Files.lines(findResult.toPath(), StandardCharsets.UTF_8)) { @@ -717,9 +718,9 @@ public static SCorpusGraph getMetaData(final String toplevelCorpusName, + AQL_REGEX_VALUE_ESCAPER.escape(toplevelCorpusName) + "/"; } final File graphML = api.subgraphForQuery(toplevelCorpusName, aql, QueryLanguage.AQL, - AnnotationComponentType.PARTOF); + AnnotationComponentType.PARTOF).block(); return CorpusGraphMapper.map(graphML); - } catch (ApiException | XMLStreamException | IOException ex) { + } catch (WebClientResponseException | XMLStreamException | IOException ex) { log.error(null, ex); ui.access(() -> ExceptionDialog.show(ex, "Could not retrieve metadata", ui)); } @@ -745,7 +746,7 @@ public static List getMetaDataDoc(final String toplevelCorpusNa final File graphML = api.subgraphForQuery(toplevelCorpusName, "annis:node_type=\"corpus\" _ident_ annis:doc=/" + AQL_REGEX_VALUE_ESCAPER.escape(documentName) + "/", - QueryLanguage.AQL, AnnotationComponentType.PARTOF); + QueryLanguage.AQL, AnnotationComponentType.PARTOF).block(); final SCorpusGraph cg = CorpusGraphMapper.map(graphML); @@ -753,7 +754,7 @@ public static List getMetaDataDoc(final String toplevelCorpusNa result.addAll(n.getMetaAnnotations()); } - } catch (ApiException | XMLStreamException | IOException ex) { + } catch (WebClientResponseException | XMLStreamException | IOException ex) { ui.access(() -> ExceptionDialog.show(ex, "Could not retrieve metadata for document", ui)); } diff --git a/src/main/java/org/corpus_tools/annis/gui/docbrowser/DocBrowserController.java b/src/main/java/org/corpus_tools/annis/gui/docbrowser/DocBrowserController.java index 83a984517e..973e8574e9 100644 --- a/src/main/java/org/corpus_tools/annis/gui/docbrowser/DocBrowserController.java +++ b/src/main/java/org/corpus_tools/annis/gui/docbrowser/DocBrowserController.java @@ -36,7 +36,6 @@ import java.util.Optional; import javax.xml.stream.XMLStreamException; import org.apache.commons.lang3.StringUtils; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.QueryLanguage; import org.corpus_tools.annis.api.model.VisualizerRule; @@ -58,6 +57,7 @@ import org.eclipse.emf.common.util.URI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * Represents a global controller for the doc browser feature. @@ -200,7 +200,7 @@ public static VisualizerInput createInput(String corpus, String documentNodeName // Build a query that includes all (possible filtered by name) node of the document String aql = Helper.buildDocumentQuery(documentNodeName, nodeAnnoFilter, useRawText); - File graphML = api.subgraphForQuery(corpus, aql, QueryLanguage.AQL, null); + File graphML = api.subgraphForQuery(corpus, aql, QueryLanguage.AQL, null).block(); SDocumentGraph docGraph = DocumentGraphMapper.map(graphML); doc.setDocumentGraph(docGraph); @@ -208,7 +208,7 @@ public static VisualizerInput createInput(String corpus, String documentNodeName if (useRawText) { input.setRawText(new RawTextWrapper(docGraph)); } - } catch (ApiException e) { + } catch (WebClientResponseException e) { log.error("General remote service exception", e); } catch (XMLStreamException | IOException ex) { log.error("Could not map GraphML to Salt", ex); diff --git a/src/main/java/org/corpus_tools/annis/gui/docbrowser/DocBrowserPanel.java b/src/main/java/org/corpus_tools/annis/gui/docbrowser/DocBrowserPanel.java index 88a707c115..32eb62b02a 100644 --- a/src/main/java/org/corpus_tools/annis/gui/docbrowser/DocBrowserPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/docbrowser/DocBrowserPanel.java @@ -31,7 +31,6 @@ import java.util.Arrays; import java.util.List; import javax.xml.stream.XMLStreamException; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.AnnotationComponentType; import org.corpus_tools.annis.api.model.QueryLanguage; @@ -45,6 +44,8 @@ import org.corpus_tools.annis.gui.objects.Visualizer; import org.corpus_tools.salt.common.SCorpusGraph; import org.corpus_tools.salt.common.SDocument; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -61,7 +62,7 @@ public void run() { try { File graphML = api.subgraphForQuery(corpus, "annis:node_type=\"corpus\"", - QueryLanguage.AQL, AnnotationComponentType.PARTOF); + QueryLanguage.AQL, AnnotationComponentType.PARTOF).block(); SCorpusGraph graph = CorpusGraphMapper.map(graphML); List docs = graph.getDocuments(); @@ -86,7 +87,7 @@ public void run() { table.setDocuments(docs); }); - } catch (ApiException | IOException | XMLStreamException ex) { + } catch (WebClientResponseException | IOException | XMLStreamException ex) { ui.access(() -> { ExceptionDialog.show(ex, ui); }); @@ -170,17 +171,17 @@ public DocumentBrowserConfig getDocBrowserConfig() { try { File result = api.getFile(getCorpus(), - urlPathEscape.escape(getCorpus()) + "/document_browser.json"); + urlPathEscape.escape(getCorpus()) + "/document_browser.json").block(); try(FileInputStream is = new FileInputStream(result)) { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); DocumentBrowserConfig config = mapper.readValue(is, DocumentBrowserConfig.class); return config; } - } catch (ApiException ex) { - if (ex.getCode() != 404) { - ExceptionDialog - .show(ex, "Could not get the document browser configuration file from the backend.", ui); + } catch (WebClientResponseException ex) { + if (ex.getStatusCode() != HttpStatus.NOT_FOUND) { + ExceptionDialog.show(ex, + "Could not get the document browser configuration file from the backend.", ui); } } catch (IOException ex) { diff --git a/src/main/java/org/corpus_tools/annis/gui/exporter/BaseMatrixExporter.java b/src/main/java/org/corpus_tools/annis/gui/exporter/BaseMatrixExporter.java index e88250d87a..98faf70f18 100644 --- a/src/main/java/org/corpus_tools/annis/gui/exporter/BaseMatrixExporter.java +++ b/src/main/java/org/corpus_tools/annis/gui/exporter/BaseMatrixExporter.java @@ -142,7 +142,7 @@ public Exception convertText(String queryAnnisQL, QueryLanguage queryLanguage, i query.setQueryLanguage(queryLanguage); query.setQuery(queryAnnisQL); try { - File matches = searchApi.find(query); + File matches = searchApi.find(query).block(); // Get the node count for the query by parsing it List nodeDescriptions = diff --git a/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java b/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java index 2b07159d7d..1336e2ced7 100644 --- a/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java +++ b/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java @@ -173,7 +173,7 @@ public Exception convertText(String queryAnnisQL, QueryLanguage queryLanguage, i query.setQuery(queryAnnisQL); final AtomicInteger offset = new AtomicInteger(); - File matches = searchApi.find(query); + File matches = searchApi.find(query).block(); // 2. iterate over all matches and get the sub-graph for them try (LineIterator lines = FileUtils.lineIterator(matches, StandardCharsets.UTF_8.name())) { while (lines.hasNext()) { diff --git a/src/main/java/org/corpus_tools/annis/gui/resultview/VisualizerPanel.java b/src/main/java/org/corpus_tools/annis/gui/resultview/VisualizerPanel.java index e35d2db63f..ddc8624e20 100644 --- a/src/main/java/org/corpus_tools/annis/gui/resultview/VisualizerPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/resultview/VisualizerPanel.java @@ -40,7 +40,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import javax.xml.stream.XMLStreamException; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.QueryLanguage; import org.corpus_tools.annis.api.model.VisualizerRule; @@ -69,6 +68,7 @@ import org.eclipse.emf.common.util.URI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * Controls the visibility of visualizer plugins and provides some control methods for the media @@ -401,7 +401,8 @@ private SaltProject getDocument(List nodeAnnoFilter, boolean useRawText, String documentNodeName = Joiner.on('/').join(documentPathRaw); String aql = Helper.buildDocumentQuery(documentNodeName, nodeAnnoFilter, useRawText); - File graphML = api.subgraphForQuery(documentPathDecoded.get(0), aql, QueryLanguage.AQL, null); + File graphML = + api.subgraphForQuery(documentPathDecoded.get(0), aql, QueryLanguage.AQL, null).block(); try { final SaltProject p = SaltFactory.createSaltProject(); SCorpusGraph cg = p.createCorpusGraph(); @@ -415,7 +416,7 @@ private SaltProject getDocument(List nodeAnnoFilter, boolean useRawText, log.error("Could not map GraphML to Salt", ex); ui.access(() -> ExceptionDialog.show(ex, "Could not map GraphML to Salt", ui)); } - } catch (ApiException e) { + } catch (WebClientResponseException e) { log.error("General remote service exception", e); } return null; diff --git a/src/main/java/org/corpus_tools/annis/gui/visualizers/htmlvis/HTMLVis.java b/src/main/java/org/corpus_tools/annis/gui/visualizers/htmlvis/HTMLVis.java index fa2ee09fa6..a4e188c90a 100644 --- a/src/main/java/org/corpus_tools/annis/gui/visualizers/htmlvis/HTMLVis.java +++ b/src/main/java/org/corpus_tools/annis/gui/visualizers/htmlvis/HTMLVis.java @@ -45,7 +45,6 @@ import java.util.TreeMap; import java.util.TreeSet; import org.apache.commons.io.IOUtils; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.AnnisBaseUI; import org.corpus_tools.annis.gui.Helper; @@ -60,7 +59,9 @@ import org.corpus_tools.salt.core.SNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -433,13 +434,13 @@ private void injectCSS(String visConfigName, String corpusName, String corpusNod inStreamCSSRaw = HTMLVis.class.getResourceAsStream("htmlvis.css"); } else { try { - File f = api.getFile(corpusName, corpusNodeId + "/" + visConfigName + ".css"); + File f = api.getFile(corpusName, corpusNodeId + "/" + visConfigName + ".css").block(); f.deleteOnExit(); inStreamCSSRaw = new FileInputStream(f); - } catch (ApiException ex) { - if (ex.getCode() != 404) { + } catch (WebClientResponseException ex) { + if (ex.getStatusCode() != HttpStatus.NOT_FOUND) { log.error("Could not retrieve the HTML visualizer web-font configuration file", ex); ui.access(() -> { Notification.show("Could not retrieve the HTML visualizer web-font configuration file", @@ -471,7 +472,7 @@ protected void injectWebFonts(String visConfigName, String corpusName, String co CorporaApi api) { try { - File f = api.getFile(corpusName, corpusNodeId + "/" + visConfigName + ".fonts.json"); + File f = api.getFile(corpusName, corpusNodeId + "/" + visConfigName + ".fonts.json").block(); f.deleteOnExit(); try (FileInputStream inStreamJSON = new FileInputStream(f)) { ObjectMapper mapper = createJsonMapper(); @@ -490,8 +491,8 @@ protected void injectWebFonts(String visConfigName, String corpusName, String co } } catch (IOException ex) { log.error("Unexpected input/output exception", ex); - } catch (ApiException ex) { - if (ex.getCode() != 404) { + } catch (WebClientResponseException ex) { + if (ex.getStatusCode() != HttpStatus.NOT_FOUND) { log.error("Could not retrieve the HTML visualizer web-font configuration file", ex); ui.access(() -> { new Notification("Could not retrieve the HTML visualizer web-font configuration file", @@ -548,10 +549,10 @@ private VisualizationDefinition[] parseDefinitions(String corpusName, String cor CorporaApi api = new CorporaApi(Helper.getClient(ui)); try { - File file = api.getFile(corpusName, corpusNodeId + "/" + visConfigName + ".config"); + File file = api.getFile(corpusName, corpusNodeId + "/" + visConfigName + ".config").block(); inStreamConfigRaw = new FileInputStream(file); - } catch (ApiException e) { - if (e.getCode() != 404) { + } catch (WebClientResponseException e) { + if (e.getStatusCode() != HttpStatus.NOT_FOUND) { log.error("Exception while getting the HTML visualizer configuration", e); } } catch (IOException e) { From b8ad22a1f061e8321597aa6058e20ad122f76019 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Fri, 11 Nov 2022 10:53:12 +0100 Subject: [PATCH 08/61] Replace some of the occurences of "collectList().block()" with "toIterable()" --- .../gui/controlpanel/SearchOptionsPanel.java | 3 +- .../flatquerybuilder/FlatQueryBuilder.java | 28 +++++++++---------- .../querybuilder/TigerQueryBuilderCanvas.java | 2 +- .../visualizers/component/pdf/PDFPanel.java | 7 ++--- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/controlpanel/SearchOptionsPanel.java b/src/main/java/org/corpus_tools/annis/gui/controlpanel/SearchOptionsPanel.java index 0f8d5633d1..2d53606a49 100644 --- a/src/main/java/org/corpus_tools/annis/gui/controlpanel/SearchOptionsPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/controlpanel/SearchOptionsPanel.java @@ -142,8 +142,7 @@ private static List getSegmentationNamesFromService(Collection c try { // Get all ordering components for (Component c : corporaApi - .components(corpus, AnnotationComponentType.ORDERING.getValue(), null).collectList() - .block()) { + .components(corpus, AnnotationComponentType.ORDERING.getValue(), null).toIterable()) { if (!c.getName().isEmpty() && !"annis".equals(c.getLayer())) { segNames.add(c.getName()); } diff --git a/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java b/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java index b80e940942..0b2e5c1a3c 100644 --- a/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java +++ b/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java @@ -351,21 +351,21 @@ public Collection getAvailableAnnotationLevels(String meta) { } public Set getAvailableAnnotationNames() { - Set result = new TreeSet<>(); - // get current corpus selection - Collection corpusSelection = cp.getState().getSelectedCorpora(); - CorporaApi api = new CorporaApi(Helper.getClient(UI.getCurrent())); - try { - for (String corpus : corpusSelection) { - for (Annotation a : api.nodeAnnotations(corpus, false, false).collectList().block()) { - result.add(a.getKey().getName()); - } - } - } catch (WebClientResponseException ex) { - log.error(null, ex); + Set result = new TreeSet<>(); + // get current corpus selection + Collection corpusSelection = cp.getState().getSelectedCorpora(); + CorporaApi api = new CorporaApi(Helper.getClient(UI.getCurrent())); + try { + for (String corpus : corpusSelection) { + for (Annotation a : api.nodeAnnotations(corpus, false, false).toIterable()) { + result.add(a.getKey().getName()); + } } - result.add("tok"); - return result; + } catch (WebClientResponseException ex) { + log.error(null, ex); + } + result.add("tok"); + return result; } public Set getAvailableMetaNames() { diff --git a/src/main/java/org/corpus_tools/annis/gui/querybuilder/TigerQueryBuilderCanvas.java b/src/main/java/org/corpus_tools/annis/gui/querybuilder/TigerQueryBuilderCanvas.java index 1be530e07c..bc792ebe08 100644 --- a/src/main/java/org/corpus_tools/annis/gui/querybuilder/TigerQueryBuilderCanvas.java +++ b/src/main/java/org/corpus_tools/annis/gui/querybuilder/TigerQueryBuilderCanvas.java @@ -320,7 +320,7 @@ public Set getAvailableAnnotationNames() { if (corpusSelection != null) { for (String corpus : corpusSelection) { try { - for (Annotation anno : api.nodeAnnotations(corpus, false, true).collectList().block()) { + for (Annotation anno : api.nodeAnnotations(corpus, false, true).toIterable()) { result.add(anno.getKey().getName()); } } catch (WebClientResponseException ex) { diff --git a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanel.java b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanel.java index 4a6aab8981..73e8888d65 100644 --- a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanel.java @@ -24,11 +24,11 @@ import java.util.Collections; import java.util.List; import java.util.UUID; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.Helper; import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.visualizers.VisualizerInput; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * Inits the wrapper for the pdf visualization. Neccesary steps for this are: @@ -101,15 +101,14 @@ protected String getBinaryPath(CorporaApi api) { String corpusName = corpusPath.get(0); try { - List files = api.listFiles(corpusName, Joiner.on('/').join(corpusPath)); - for (String f : files) { + for (String f : api.listFiles(corpusName, Joiner.on('/').join(corpusPath)).toIterable()) { if (f.endsWith(".pdf")) { // Create an URL how to featch the PDF file return input.getContextPath() + "/Binary?" + "toplevelCorpusName=" + urlParamEscape.escape(corpusName) + "&file=" + urlParamEscape.escape(f); } } - } catch (ApiException e) { + } catch (WebClientResponseException e) { ExceptionDialog.show(e, input.getUI()); } From d6861a77d45cd96695102a7be461f34c5393fa9f Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Fri, 11 Nov 2022 16:19:27 +0100 Subject: [PATCH 09/61] Fix remaining compilation issues regarding the new WebClient --- pom.xml | 5 - .../org/corpus_tools/annis/gui/CommonUI.java | 11 +- .../annis/gui/CorpusBrowserPanel.java | 3 +- .../corpus_tools/annis/gui/EmbeddedVisUI.java | 100 +++++++++-------- .../annis/gui/ExampleQueriesPanel.java | 6 +- .../org/corpus_tools/annis/gui/Helper.java | 13 +-- .../annis/gui/QueryController.java | 62 ++++------- .../annis/gui/admin/ImportPanel.java | 44 ++++---- .../gui/admin/model/GroupManagement.java | 7 +- .../gui/admin/reflinks/MigrationPanel.java | 6 +- .../reflinks/URLShortenerDefinition.java | 21 ++-- .../annis/gui/controller/CountCallback.java | 105 ++++++++++-------- .../gui/controller/ExportBackgroundJob.java | 11 +- .../controller/FrequencyBackgroundJob.java | 12 +- .../gui/controller/ValidateCallback.java | 59 ++++++++++ .../gui/controlpanel/CorpusListPanel.java | 8 +- .../gui/exporter/BaseMatrixExporter.java | 20 ++-- .../annis/gui/exporter/CSVExporter.java | 3 +- .../annis/gui/exporter/ExportHelper.java | 6 +- .../gui/exporter/GeneralTextExporter.java | 6 +- .../gui/exporter/TextColumnExporter.java | 5 +- .../flatquerybuilder/FlatQueryBuilder.java | 3 +- .../gui/frequency/FrequencyQueryPanel.java | 11 +- .../annis/gui/objects/QueryUIState.java | 6 +- .../requesthandler/BinaryRequestHandler.java | 70 +++++------- .../annis/gui/resultfetch/ResultFetchJob.java | 24 ++-- .../gui/resultfetch/SingleResultFetchJob.java | 2 +- .../gui/security/AutoTokenRefreshClient.java | 19 ---- .../component/AudioVisualizer.java | 7 +- .../component/VideoVisualizer.java | 7 +- src/main/resources/openapi.yml | 18 +-- .../component/pdf/PDFPanelTest.java | 10 +- .../gui/visualizers/htmlvis/HTMLVisTest.java | 14 ++- 33 files changed, 362 insertions(+), 342 deletions(-) create mode 100644 src/main/java/org/corpus_tools/annis/gui/controller/ValidateCallback.java diff --git a/pom.xml b/pom.xml index 3c028fc5c8..cd6e74ab41 100644 --- a/pom.xml +++ b/pom.xml @@ -299,11 +299,6 @@ org.corpus_tools.annis.api org.corpus_tools.annis.api.model true - ApiResponse.java,ApiException.java,ApiCallback.java, - Pair.java,ApiClient.java,Configuration.java,ProgressRequestBody.java, - JSON.java,Authentication.java,StringUtil.java,ApiKeyAuth.java, - HttpBasicAuth.java,ProgressResponseBody.java,HttpBearerAuth.java, - JavaTimeFormatter.java,RFC3339DateFormat.java false false false diff --git a/src/main/java/org/corpus_tools/annis/gui/CommonUI.java b/src/main/java/org/corpus_tools/annis/gui/CommonUI.java index 23fd8c16e8..d5739fb5b2 100644 --- a/src/main/java/org/corpus_tools/annis/gui/CommonUI.java +++ b/src/main/java/org/corpus_tools/annis/gui/CommonUI.java @@ -22,7 +22,6 @@ import java.util.Optional; import javax.servlet.ServletContext; import org.corpus_tools.annis.ApiClient; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.gui.components.SettingsStorage; import org.corpus_tools.annis.gui.requesthandler.ResourceRequestHandler; import org.corpus_tools.annis.gui.security.AuthenticationSuccessListener; @@ -30,9 +29,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties; +import org.springframework.http.HttpStatus; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -194,10 +195,10 @@ public boolean handleCommonError(Throwable ex, String action) { rootCause = rootCause.getCause(); } - if (rootCause instanceof ApiException) { - ApiException apiEx = (ApiException) rootCause; + if (rootCause instanceof WebClientResponseException) { + WebClientResponseException apiEx = (WebClientResponseException) rootCause; - if (apiEx.getCode() == 503) { + if (apiEx.getStatusCode() == HttpStatus.SERVICE_UNAVAILABLE) { // database connection error Notification n = new Notification( "Can't execute " + (action == null ? "" : "\"" + action + "\"") @@ -214,7 +215,7 @@ public boolean handleCommonError(Throwable ex, String action) { n.show(this.getPage()); return true; - } else if (apiEx.getCode() == 401) { + } else if (apiEx.getStatusCode() == HttpStatus.UNAUTHORIZED) { redirectToLogin(); return true; } diff --git a/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java b/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java index 4a2dfdd04f..f6ef2acb0d 100644 --- a/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/CorpusBrowserPanel.java @@ -33,7 +33,6 @@ import java.util.Optional; import java.util.Set; import java.util.TreeSet; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.AnnoKey; import org.corpus_tools.annis.api.model.Annotation; @@ -351,7 +350,7 @@ private void fetchAnnotationsInBackground(UI ui) { }); - } catch (ApiException e) { + } catch (WebClientResponseException e) { getUI().access(() -> { ExceptionDialog.show(e, "Error fetching corpus annotations", getUI()); }); diff --git a/src/main/java/org/corpus_tools/annis/gui/EmbeddedVisUI.java b/src/main/java/org/corpus_tools/annis/gui/EmbeddedVisUI.java index 9244fbc851..c590cd32be 100644 --- a/src/main/java/org/corpus_tools/annis/gui/EmbeddedVisUI.java +++ b/src/main/java/org/corpus_tools/annis/gui/EmbeddedVisUI.java @@ -16,7 +16,6 @@ import com.google.common.base.Joiner; import com.google.common.base.Objects; import com.google.common.base.Splitter; -import com.google.common.util.concurrent.FutureCallback; import com.vaadin.annotations.Push; import com.vaadin.annotations.Theme; import com.vaadin.annotations.Widgetset; @@ -31,10 +30,12 @@ import com.vaadin.ui.Label; import com.vaadin.ui.Link; import com.vaadin.ui.Panel; +import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; @@ -46,7 +47,6 @@ import javax.servlet.ServletContext; import javax.xml.stream.XMLStreamException; import okhttp3.Request; -import okhttp3.Response; import org.apache.commons.io.IOUtils; import org.corpus_tools.annis.ApiClient; import org.corpus_tools.annis.api.CorporaApi; @@ -69,6 +69,7 @@ import org.corpus_tools.salt.common.SDocumentGraph; import org.corpus_tools.salt.common.SaltProject; import org.corpus_tools.salt.core.SNode; +import org.reactivestreams.Subscription; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -84,41 +85,57 @@ @Widgetset("org.corpus_tools.annis.gui.widgets.gwt.AnnisWidgetSet") public class EmbeddedVisUI extends CommonUI { - private class GraphMLLoaderCallback implements FutureCallback { + private class GraphMLLoaderCallback implements org.reactivestreams.Subscriber { private final String corpusNodeId; private final VisualizerPlugin visPlugin; private final Map args; + private final UI ui; GraphMLLoaderCallback(String corpusNodeId, VisualizerPlugin visPlugin, - Map args) { + Map args, UI ui) { this.visPlugin = visPlugin; this.args = args; this.corpusNodeId = corpusNodeId; + this.ui = ui; } - @Override - public void onFailure(Throwable t) { - log.error("Could not query graph for embedded visualization.", t); - displayMessage("Could not query the result.", t.getMessage()); - } @Override - public void onSuccess(File result) { + public void onNext(File item) { try { final SaltProject p = SaltFactory.createSaltProject(); SCorpusGraph cg = p.createCorpusGraph(); org.eclipse.emf.common.util.URI docURI = org.eclipse.emf.common.util.URI.createURI("salt:/" + corpusNodeId); SDocument doc = cg.createDocument(docURI); - SDocumentGraph docGraph = DocumentGraphMapper.map(result); + SDocumentGraph docGraph = DocumentGraphMapper.map(item); doc.setDocumentGraph(docGraph); - generateVisualizerFromDocument(doc, args, visPlugin); + ui.access(() -> generateVisualizerFromDocument(doc, args, visPlugin)); } catch (IOException | XMLStreamException ex) { log.error("Could not parse GraphML", ex); displayMessage("Could not parse GraphML", ex.toString()); } + + } + + @Override + public void onError(Throwable t) { + log.error("Could not query graph for embedded visualization.", t); + ui.access(() -> displayMessage("Could not query the result.", t.getMessage())); + } + + @Override + public void onComplete() { + // Nothing to do + } + + + @Override + public void onSubscribe(Subscription s) { + // TODO Auto-generated method stub + } } @@ -229,10 +246,11 @@ private void generateVisFromParameters(final String visName, Map api.subgraphForQuery(toplevelCorpus, aql, QueryLanguage.AQL, null), - new GraphMLLoaderCallback(corpusNodeId, visPlugin.get(), args)); - + GraphMLLoaderCallback callback = + new GraphMLLoaderCallback(corpusNodeId, visPlugin.get(), args, UI.getCurrent()); + + api.subgraphForQuery(toplevelCorpus, aql, QueryLanguage.AQL, null).subscribe(callback); + } else { SubgraphWithContext subgraphQuery = new SubgraphWithContext(); @@ -245,9 +263,8 @@ private void generateVisFromParameters(final String visName, Map api.subgraphForNodes(toplevelCorpus, subgraphQuery), - new GraphMLLoaderCallback(corpusNodeId, visPlugin.get(), args)); + GraphMLLoaderCallback callback = new GraphMLLoaderCallback(corpusNodeId, visPlugin.get(), args, UI.getCurrent()); + api.subgraphForNodes(toplevelCorpus, subgraphQuery).subscribe(callback); } } @@ -362,36 +379,27 @@ private void generateVisFromRemoteSaltURL(final String visName, final String raw final Map argsCopy = new LinkedHashMap<>(args); Request request = new okhttp3.Request.Builder().url(uri.toASCIIString()).build(); - Background.runWithCallback(() -> client.getHttpClient().newCall(request).execute(), - new FutureCallback() { - @Override - public void onFailure(Throwable t) { - log.error("Could not query Salt graph for embedded visualization.", t); - displayMessage("Could not query the result.", t.getMessage()); - } - - @Override - public void onSuccess(Response response) { - try { - File tmpFile = File.createTempFile("embeddded-vis-fetched-result-", ".salt"); - try (FileOutputStream out = new FileOutputStream(tmpFile)) { - IOUtils.copy(response.body().byteStream(), out); - } catch (IOException ex) { - log.error("Could not copy fetched GraphML file:", ex); - } - - SDocument doc = SaltFactory.createSDocument(); - doc.loadDocumentGraph( - org.eclipse.emf.common.util.URI.createFileURI(tmpFile.getAbsolutePath())); - generateVisualizerFromDocument(doc, argsCopy, visPlugin); - + final UI ui = UI.getCurrent(); + client.getWebClient().get().uri(uri).retrieve().toEntity(InputStream.class) + .subscribe(body -> ui.access(() -> { + try { + File tmpFile = File.createTempFile("embeddded-vis-fetched-result-", ".salt"); + try (FileOutputStream out = new FileOutputStream(tmpFile)) { + IOUtils.copy(body.getBody(), out); } catch (IOException ex) { - log.error("Could not parse Salt XML", ex); - displayMessage("Could not parse Salt XML", ex.toString()); + log.error("Could not copy fetched GraphML file:", ex); } - } - }); + SDocument doc = SaltFactory.createSDocument(); + doc.loadDocumentGraph( + org.eclipse.emf.common.util.URI.createFileURI(tmpFile.getAbsolutePath())); + generateVisualizerFromDocument(doc, argsCopy, visPlugin); + + } catch (IOException ex) { + log.error("Could not parse Salt XML", ex); + displayMessage("Could not parse Salt XML", ex.toString()); + } + })); } else { displayMessage("Unknown visualizer \"" + visName + "\"", "This ANNIS instance does not know the given visualizer."); diff --git a/src/main/java/org/corpus_tools/annis/gui/ExampleQueriesPanel.java b/src/main/java/org/corpus_tools/annis/gui/ExampleQueriesPanel.java index d3abc17ea6..e969b4ab15 100644 --- a/src/main/java/org/corpus_tools/annis/gui/ExampleQueriesPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/ExampleQueriesPanel.java @@ -31,7 +31,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Set; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.CorpusConfiguration; import org.corpus_tools.annis.api.model.ExampleQuery; @@ -43,6 +42,7 @@ import org.corpus_tools.annis.gui.resultview.ResultViewPanel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * Wraps the auto generated queries. @@ -113,7 +113,7 @@ private static List loadExamplesFromRemote(Set corpusNames, UI ui try { if (corpusNames != null && !corpusNames.isEmpty()) { for (String c : corpusNames) { - CorpusConfiguration config = api.corpusConfiguration(c); + CorpusConfiguration config = api.corpusConfiguration(c).block(); if(config.getExampleQueries() != null) { for (ExampleQuery q : config.getExampleQueries()) { Entry e = new Entry(); @@ -124,7 +124,7 @@ private static List loadExamplesFromRemote(Set corpusNames, UI ui } } } - } catch (ApiException ex) { + } catch (WebClientResponseException ex) { log.error("problems with getting example queries from remote for {}", corpusNames, ex); } return result; diff --git a/src/main/java/org/corpus_tools/annis/gui/Helper.java b/src/main/java/org/corpus_tools/annis/gui/Helper.java index 7869aadf72..044b1e9dbc 100644 --- a/src/main/java/org/corpus_tools/annis/gui/Helper.java +++ b/src/main/java/org/corpus_tools/annis/gui/Helper.java @@ -62,7 +62,6 @@ import org.apache.commons.mail.EmailException; import org.apache.commons.mail.MultiPartEmail; import org.corpus_tools.annis.ApiClient; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.SearchApi; import org.corpus_tools.annis.api.model.AnnoKey; @@ -487,15 +486,15 @@ public static ApiClient getClient(final UI ui) { } public static Set getMetaAnnotationNames(final String corpus, final UI ui) - throws ApiException { + throws WebClientResponseException { final CorporaApi api = new CorporaApi(getClient(ui)); final SearchApi search = new SearchApi(getClient(ui)); final List nodeAnnos = - api.nodeAnnotations(corpus, false, true).stream() + api.nodeAnnotations(corpus, false, true) .filter(a -> !Objects.equals(a.getKey().getNs(), "annis") && !Objects.equals(a.getKey().getName(), "tok")) - .collect(Collectors.toList()); + .collectList().block(); final Set metaAnnos = new HashSet<>(); // Check for each annotation if its actually a meta-annotation @@ -511,7 +510,7 @@ public static Set getMetaAnnotationNames(final String corpus, final UI } private static boolean annotationIsMetadata(String corpus, String annotationName, - SearchApi search) throws ApiException { + SearchApi search) throws WebClientResponseException { if (!validQNamePattern.matcher(annotationName).matches()) { return false; } @@ -645,8 +644,8 @@ public static CorpusConfiguration getCorpusConfig(final String corpus, final UI final CorporaApi api = new CorporaApi(getClient(ui)); try { - corpusConfig = api.corpusConfiguration(corpus); - } catch (final ApiException ex) { + corpusConfig = api.corpusConfiguration(corpus).block(); + } catch (final WebClientResponseException ex) { ui.access(() -> ExceptionDialog.show(ex, ERROR_MESSAGE_CORPUS_PROPS_HEADER, ui)); } diff --git a/src/main/java/org/corpus_tools/annis/gui/QueryController.java b/src/main/java/org/corpus_tools/annis/gui/QueryController.java index 71e3587ef8..be186cb82e 100644 --- a/src/main/java/org/corpus_tools/annis/gui/QueryController.java +++ b/src/main/java/org/corpus_tools/annis/gui/QueryController.java @@ -15,6 +15,7 @@ import com.google.common.eventbus.EventBus; import com.google.common.util.concurrent.FutureCallback; +import com.google.gson.Gson; import com.vaadin.data.Binder; import com.vaadin.data.provider.ListDataProvider; import com.vaadin.server.FontAwesome; @@ -37,19 +38,16 @@ import java.util.Set; import java.util.TreeSet; import java.util.concurrent.Future; -import okhttp3.Call; -import org.corpus_tools.annis.ApiException; -import org.corpus_tools.annis.JSON; import org.corpus_tools.annis.api.SearchApi; import org.corpus_tools.annis.api.model.BadRequestError; import org.corpus_tools.annis.api.model.CorpusConfiguration; import org.corpus_tools.annis.api.model.CountQuery; -import org.corpus_tools.annis.api.model.QueryAttributeDescription; import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.controller.CountCallback; import org.corpus_tools.annis.gui.controller.ExportBackgroundJob; import org.corpus_tools.annis.gui.controller.FrequencyBackgroundJob; import org.corpus_tools.annis.gui.controller.SpecificPagingCallback; +import org.corpus_tools.annis.gui.controller.ValidateCallback; import org.corpus_tools.annis.gui.controlpanel.QueryPanel; import org.corpus_tools.annis.gui.exporter.ExporterPlugin; import org.corpus_tools.annis.gui.frequency.FrequencyQueryPanel; @@ -74,6 +72,7 @@ import org.corpus_tools.salt.common.SaltProject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * A controller to modifiy the query UI state. s @@ -429,11 +428,12 @@ public void executeSearch(boolean replaceOldTab, boolean freshQuery) { countQuery.setQuery(displayedQuery.getQuery()); countQuery.setQueryLanguage(displayedQuery.getApiQueryLanguage()); try { - Call call = api.countAsync(countQuery, - new CountCallback(newResultView, displayedQuery.getLimit(), annisUI)); + CountCallback callback = + new CountCallback(newResultView, displayedQuery.getLimit(), annisUI); + api.count(countQuery).single().subscribe(callback); - state.getExecutedCalls().put(QueryUIState.QueryType.COUNT, call); - } catch (ApiException ex) { + state.getExecutedCalls().put(QueryUIState.QueryType.COUNT, callback); + } catch (WebClientResponseException ex) { ExceptionDialog.show(ex, ui); } } @@ -492,17 +492,19 @@ public QueryUIState getState() { * @param showNotification If true a notification is shown instead of only displaying the error in * the status label. */ - public void reportServiceException(ApiException ex, boolean showNotification) { + public void reportServiceException(WebClientResponseException ex, boolean showNotification) { QueryPanel qp = searchView.getControlPanel().getQueryPanel(); String caption = null; String description = null; if (!ui.handleCommonError(ex, "execute query")) { - switch (ex.getCode()) { - case 400: + switch (ex.getStatusCode()) { + case BAD_REQUEST: + + Gson gson = new Gson(); BadRequestError error = - JSON.createGson().create().fromJson(ex.getResponseBody(), BadRequestError.class); + gson.fromJson(ex.getResponseBodyAsString(), BadRequestError.class); caption = "Parsing error"; if (error.getAqLSyntaxError() != null) { @@ -517,12 +519,12 @@ public void reportServiceException(ApiException ex, boolean showNotification) { qp.setError(error); qp.setStatus(description); break; - case 504: + case GATEWAY_TIMEOUT: caption = "Timeout"; description = "Query execution took too long."; qp.setStatus(caption + ": " + description); break; - case 403: + case FORBIDDEN: if (!Helper.getUser(ui.getSecurityContext()).isPresent()) { // not logged in qp.setStatus("You don't have the access rights to query this corpus. " @@ -620,36 +622,12 @@ public void validateQuery() { String query = state.getAql().getValue(); if (query == null || query.isEmpty()) { qp.setStatus("Empty query"); - } else { // validate query - UI ui = UI.getCurrent(); - Background.runWithCallback(() -> { - SearchApi api = new SearchApi(Helper.getClient(ui)); - return api.nodeDescriptions(query, org.corpus_tools.annis.api.model.QueryLanguage.AQL); - }, new FutureCallback>() { - - @Override - public void onSuccess(List nodes) { - qp.setNodes(nodes); - - if (state.getSelectedCorpora() == null || state.getSelectedCorpora().isEmpty()) { - qp.setStatus("Please select a corpus from the list below, then click on \"Search\"."); - } else { - qp.setStatus("Valid query, click on \"Search\" to start searching."); - } - - } - - @Override - public void onFailure(Throwable t) { - if (t instanceof ApiException) { - reportServiceException((ApiException) t, false); - } - } - - }); - + final UI ui = UI.getCurrent(); + SearchApi api = new SearchApi(Helper.getClient(ui)); + api.nodeDescriptions(query, org.corpus_tools.annis.api.model.QueryLanguage.AQL) + .subscribe(new ValidateCallback(qp, this, ui)); } } diff --git a/src/main/java/org/corpus_tools/annis/gui/admin/ImportPanel.java b/src/main/java/org/corpus_tools/annis/gui/admin/ImportPanel.java index b1e121764f..1dcf3a6f34 100644 --- a/src/main/java/org/corpus_tools/annis/gui/admin/ImportPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/admin/ImportPanel.java @@ -13,6 +13,7 @@ */ package org.corpus_tools.annis.gui.admin; +import com.google.gson.Gson; import com.vaadin.icons.VaadinIcons; import com.vaadin.ui.Alignment; import com.vaadin.ui.Button; @@ -33,9 +34,6 @@ import java.io.OutputStream; import java.text.DecimalFormat; import java.util.List; -import org.corpus_tools.annis.ApiException; -import org.corpus_tools.annis.ApiResponse; -import org.corpus_tools.annis.JSON; import org.corpus_tools.annis.api.AdministrationApi; import org.corpus_tools.annis.api.model.ImportResult; import org.corpus_tools.annis.api.model.Job; @@ -46,6 +44,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -59,12 +59,12 @@ private class WaitForFinishRunner implements Runnable { private final String uuid; private int currentMessageIndex = 0; - private JSON json; + private Gson json; public WaitForFinishRunner(String uuid, UI ui) { this.ui = ui; this.uuid = uuid; - this.json = new JSON(); + this.json = new Gson(); } private void appendFromBackground(List message) { @@ -96,18 +96,17 @@ public void run() { try { do { job = null; - ApiResponse response = - api.getApiClient().execute(api.getJobCall(uuid, null), String.class); + ResponseEntity response = api.getJobWithHttpInfo(uuid).block(); // If the response type returns an object of type Job, get it here - int statusCode = response.getStatusCode(); - if (statusCode == HttpStatus.ACCEPTED.value()) { - job = json.deserialize(response.getData(), Job.class); + HttpStatus statusCode = response.getStatusCode(); + if (statusCode == HttpStatus.ACCEPTED) { + job = json.fromJson(response.getBody(), Job.class); outputNewMessages(job.getMessages()); - } else if (statusCode == HttpStatus.OK.value()) { + } else if (statusCode == HttpStatus.OK) { // The last messages are given as array of strings - String[] finishMessages = json.deserialize(response.getData(), String[].class); + String[] finishMessages = json.fromJson(response.getBody(), String[].class); for (int i = 0; i < finishMessages.length; i++) { appendFromBackground(finishMessages[i]); } @@ -137,15 +136,15 @@ public void run() { } catch (InterruptedException ex) { log.error(null, ex); Thread.currentThread().interrupt(); - } catch (ApiException ex) { - if (ex.getCode() == HttpStatus.GONE.value()) { + } catch (WebClientResponseException ex) { + if (ex.getStatusCode() == HttpStatus.GONE) { // Decode the Job object with its included error messages - job = json.deserialize(ex.getResponseBody(), Job.class); + job = json.fromJson(ex.getResponseBodyAsString(), Job.class); outputNewMessages(job.getMessages()); } else { appendFromBackground( "Exception while polling for import status: " + ex.getMessage() + "\n" - + ex.getResponseBody()); + + ex.getResponseBodyAsString()); } ui.access(() -> { progress.setVisible(false); @@ -293,12 +292,12 @@ private void startImport() { AdministrationApi api = new AdministrationApi(Helper.getClient(UI.getCurrent())); try { - ApiResponse response = - api.importPostWithHttpInfo(temporaryCorpusFile, cbOverwrite.getValue()); + ResponseEntity response = + api.importPostWithHttpInfo(temporaryCorpusFile, cbOverwrite.getValue()).block(); - if (response.getStatusCode() == HttpStatus.ACCEPTED.value()) { - String uuid = response.getData().getUuid(); + if (response.getStatusCode() == HttpStatus.ACCEPTED) { + String uuid = response.getBody().getUuid(); appendMessage("Import requested, update UUID is " + uuid); UI ui = UI.getCurrent(); @@ -309,10 +308,11 @@ private void startImport() { progress.setVisible(false); appendMessage("Error (response code " + response.getStatusCode() + ")"); } - } catch (ApiException ex) { + } catch (WebClientResponseException ex) { upload.setEnabled(true); progress.setVisible(false); - appendMessage("Error (response code " + ex.getCode() + "): " + ex.getResponseBody()); + appendMessage( + "Error (response code " + ex.getRawStatusCode() + "): " + ex.getResponseBodyAsString()); } diff --git a/src/main/java/org/corpus_tools/annis/gui/admin/model/GroupManagement.java b/src/main/java/org/corpus_tools/annis/gui/admin/model/GroupManagement.java index 09badf091c..7d04d7f27b 100644 --- a/src/main/java/org/corpus_tools/annis/gui/admin/model/GroupManagement.java +++ b/src/main/java/org/corpus_tools/annis/gui/admin/model/GroupManagement.java @@ -17,10 +17,8 @@ import com.google.common.collect.ImmutableSet; import java.io.Serializable; import java.util.Collection; -import java.util.List; import java.util.Map; import java.util.TreeMap; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.AdministrationApi; import org.corpus_tools.annis.api.model.Group; import org.corpus_tools.annis.gui.CaseSensitiveOrder; @@ -79,12 +77,11 @@ public boolean fetchFromService() { groups.clear(); try { - List list = api.listGroups(); - for (Group g : list) { + for (Group g : api.listGroups().toIterable()) { groups.put(g.getName(), g); } return true; - } catch (ApiException ex) { + } catch (WebClientResponseException ex) { log.error("Could not get the list of groups", ex); } } diff --git a/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java b/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java index 3175d553a6..313390a467 100644 --- a/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java @@ -39,7 +39,6 @@ import okhttp3.Request; import okhttp3.Response; import org.corpus_tools.annis.ApiClient; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.SearchApi; import org.corpus_tools.annis.gui.AnnisUI; @@ -48,6 +47,7 @@ import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.query_references.UrlShortener; import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.web.reactive.function.client.WebClientResponseException; import org.springframework.web.util.UriComponentsBuilder; public class MigrationPanel extends Panel @@ -94,7 +94,7 @@ public MigrationPanel() { Background.runWithCallback(() -> { try { return migrateUrlShortener(url, username, password, skip, failedQueries); - } catch (ApiException | IOException ex) { + } catch (WebClientResponseException | IOException ex) { ExceptionDialog.show(ex, "Migrating URL shortener table failed", ui); return 0; } @@ -292,7 +292,7 @@ public Response intercept(Chain chain) throws IOException { private int migrateUrlShortener(String serviceURL, String username, String password, boolean skipExisting, Multimap failedQueries) - throws ApiException, IOException { + throws WebClientResponseException, IOException { int successfulQueries = 0; diff --git a/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/URLShortenerDefinition.java b/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/URLShortenerDefinition.java index b3f79b9060..7851fd7310 100644 --- a/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/URLShortenerDefinition.java +++ b/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/URLShortenerDefinition.java @@ -24,7 +24,6 @@ import okhttp3.Response; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.SearchApi; import org.corpus_tools.annis.api.model.CountExtra; import org.corpus_tools.annis.api.model.CountQuery; @@ -42,6 +41,8 @@ import org.joda.time.format.DateTimeParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.WebClientResponseException; import org.springframework.web.util.UriComponentsBuilder; public class URLShortenerDefinition { @@ -182,11 +183,12 @@ public void addUnknownCorpus(String corpus) { } private QueryStatus testFind(SearchApi searchApi, OkHttpClient client, - HttpUrl annisSearchServiceBaseUrl) throws IOException, ApiException { + HttpUrl annisSearchServiceBaseUrl) throws IOException, WebClientResponseException { // Create a file with the matches according to the new graphANNIS based implementation File matchesGraphANNISFile = searchApi.find(new FindQuery().query(query.getQuery()) - .corpora(new LinkedList<>(query.getCorpora())).queryLanguage(query.getApiQueryLanguage())); + .corpora(new LinkedList<>(query.getCorpora())).queryLanguage(query.getApiQueryLanguage())) + .block(); HttpUrl findUrl = annisSearchServiceBaseUrl.newBuilder().addPathSegment("find") @@ -284,12 +286,13 @@ private QueryStatus testQuirksMode(SearchApi searchApi, OkHttpClient client, private QueryStatus testCountAndFind(SearchApi searchApi, OkHttpClient client, - HttpUrl annisSearchServiceBaseUrl) throws IOException, ApiException { + HttpUrl annisSearchServiceBaseUrl) throws IOException, WebClientResponseException { try { // check count first (also warmup for the corpus) int countLegacy = getLegacyCount(client, annisSearchServiceBaseUrl); int countGraphANNIS = searchApi.count(new CountQuery().query(query.getQuery()) .queryLanguage(query.getApiQueryLanguage()).corpora(new LinkedList<>(query.getCorpora()))) + .block() .getMatchCount(); if (countGraphANNIS != countLegacy) { this.errorMsg = "should have been " + countLegacy + " but was " + countGraphANNIS; @@ -300,8 +303,9 @@ private QueryStatus testCountAndFind(SearchApi searchApi, OkHttpClient client, // When count is the same and non-empty test if the returned IDs are the same return testFind(searchApi, client, annisSearchServiceBaseUrl); } - } catch (ApiException ex) { - if (ex.getCode() == 400 && this.query.getQueryLanguage() == QueryLanguage.AQL) { + } catch (WebClientResponseException ex) { + if (ex.getStatusCode() == HttpStatus.BAD_REQUEST + && this.query.getQueryLanguage() == QueryLanguage.AQL) { // Bad requests means the query was invalid, return error instead of throwing exception this.errorMsg = ex.toString(); return QueryStatus.FAILED; @@ -328,8 +332,9 @@ public QueryStatus test(SearchApi searchApi, OkHttpClient client, } return status; - } catch (ApiException ex) { - if (ex.getCode() == 408 || ex.getCode() == 504) { + } catch (WebClientResponseException ex) { + if (ex.getStatusCode() == HttpStatus.REQUEST_TIMEOUT + || ex.getStatusCode() == HttpStatus.GATEWAY_TIMEOUT) { this.errorMsg = "Timeout in graphANNIS"; return QueryStatus.TIMEOUT; } else { diff --git a/src/main/java/org/corpus_tools/annis/gui/controller/CountCallback.java b/src/main/java/org/corpus_tools/annis/gui/controller/CountCallback.java index 02e11d90ab..8d453bd00e 100644 --- a/src/main/java/org/corpus_tools/annis/gui/controller/CountCallback.java +++ b/src/main/java/org/corpus_tools/annis/gui/controller/CountCallback.java @@ -13,70 +13,87 @@ */ package org.corpus_tools.annis.gui.controller; -import java.util.List; -import java.util.Map; -import org.corpus_tools.annis.ApiCallback; -import org.corpus_tools.annis.ApiException; +import org.apache.http.concurrent.Cancellable; import org.corpus_tools.annis.api.model.CountExtra; import org.corpus_tools.annis.gui.AnnisUI; import org.corpus_tools.annis.gui.objects.QueryUIState; import org.corpus_tools.annis.gui.resultview.ResultViewPanel; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * * @author Thomas Krause {@literal } */ -public class CountCallback implements ApiCallback { - private final ResultViewPanel panel; +public class CountCallback implements Subscriber, Cancellable { - private final int pageSize; + private static final Logger log = LoggerFactory.getLogger(CountCallback.class); - private final AnnisUI ui; + private final ResultViewPanel panel; + private final int pageSize; + private final AnnisUI ui; + private Subscription subscription; - public CountCallback(ResultViewPanel panel, int pageSize, AnnisUI ui) { - this.panel = panel; - this.pageSize = pageSize; - this.ui = ui; - } - - @Override - public void onFailure(ApiException e, int statusCode, - Map> responseHeaders) { - ui.access(() -> { - ui.getQueryState().getExecutedTasks().remove(QueryUIState.QueryType.COUNT); - ui.getQueryController().reportServiceException(e, true); - }); + public CountCallback(ResultViewPanel panel, int pageSize, AnnisUI ui) { + this.panel = panel; + this.pageSize = pageSize; + this.ui = ui; + } - } + @Override + public void onSubscribe(Subscription s) { + this.subscription = s; + } - @Override - public void onSuccess(CountExtra result, int statusCode, - Map> responseHeaders) { - ui.access(() -> { - ui.getQueryState().getExecutedTasks().remove(QueryUIState.QueryType.COUNT); - - String documentString = result.getDocumentCount() > 1 ? "documents" : "document"; - String matchesString = result.getMatchCount() > 1 ? "matches" : "match"; - ui.getSearchView().getControlPanel().getQueryPanel() - .setStatus("" + result.getMatchCount() + " " + matchesString + "\nin " - + result.getDocumentCount() + " " + documentString); - if (result.getMatchCount() > 0 && panel != null) { - panel.getPaging().setPageSize(pageSize, false); - panel.setCount(result.getMatchCount()); - } - ui.getSearchView().getControlPanel().getQueryPanel().setCountIndicatorEnabled(false); - }); - } + @Override + public void onNext(CountExtra result) { + ui.access(() -> { + ui.getQueryState().getExecutedTasks().remove(QueryUIState.QueryType.COUNT); - @Override - public void onUploadProgress(long bytesWritten, long contentLength, boolean done) { + String documentString = result.getDocumentCount() > 1 ? "documents" : "document"; + String matchesString = result.getMatchCount() > 1 ? "matches" : "match"; + ui.getSearchView().getControlPanel().getQueryPanel().setStatus("" + result.getMatchCount() + + " " + matchesString + "\nin " + result.getDocumentCount() + " " + documentString); + if (result.getMatchCount() > 0 && panel != null) { + panel.getPaging().setPageSize(pageSize, false); + panel.setCount(result.getMatchCount()); + } + ui.getSearchView().getControlPanel().getQueryPanel().setCountIndicatorEnabled(false); + }); + } + @Override + public void onError(Throwable t) { + ui.access(() -> { + ui.getQueryState().getExecutedTasks().remove(QueryUIState.QueryType.COUNT); + if (t instanceof WebClientResponseException) { + ui.getQueryController().reportServiceException((WebClientResponseException) t, true); + } else { + log.error("Could not get count result", t); + } + }); } - @Override - public void onDownloadProgress(long bytesRead, long contentLength, boolean done) { + @Override + public void onComplete() { + // nothing to do + } + public Subscription getSubscription() { + return subscription; + } + @Override + public boolean cancel() { + if (subscription == null) { + return false; + } else { + subscription.cancel(); + return true; } + } } diff --git a/src/main/java/org/corpus_tools/annis/gui/controller/ExportBackgroundJob.java b/src/main/java/org/corpus_tools/annis/gui/controller/ExportBackgroundJob.java index c631d2abb6..ba9ec28e47 100644 --- a/src/main/java/org/corpus_tools/annis/gui/controller/ExportBackgroundJob.java +++ b/src/main/java/org/corpus_tools/annis/gui/controller/ExportBackgroundJob.java @@ -15,21 +15,19 @@ */ package org.corpus_tools.annis.gui.controller; +import com.google.common.eventbus.EventBus; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.Callable; - -import com.google.common.eventbus.EventBus; - -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.model.CorpusConfiguration; import org.corpus_tools.annis.gui.AnnisUI; import org.corpus_tools.annis.gui.ExportPanel; import org.corpus_tools.annis.gui.exporter.ExporterPlugin; import org.corpus_tools.annis.gui.objects.ExportQuery; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -84,8 +82,9 @@ public File call() throws Exception { if (panel != null) { panel.showResult(currentTmpFile, exportError); } - if (exportError instanceof ApiException) { - ui.getQueryController().reportServiceException((ApiException) exportError, true); + if (exportError instanceof WebClientResponseException) { + ui.getQueryController() + .reportServiceException((WebClientResponseException) exportError, true); } }); } diff --git a/src/main/java/org/corpus_tools/annis/gui/controller/FrequencyBackgroundJob.java b/src/main/java/org/corpus_tools/annis/gui/controller/FrequencyBackgroundJob.java index 417016f97b..f98e4a8f94 100644 --- a/src/main/java/org/corpus_tools/annis/gui/controller/FrequencyBackgroundJob.java +++ b/src/main/java/org/corpus_tools/annis/gui/controller/FrequencyBackgroundJob.java @@ -19,10 +19,9 @@ import java.util.List; import java.util.concurrent.Callable; import org.apache.commons.lang3.tuple.Pair; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.SearchApi; import org.corpus_tools.annis.api.model.FrequencyQuery; -import org.corpus_tools.annis.api.model.FrequencyQueryDefinition; +import org.corpus_tools.annis.api.model.FrequencyQueryDefinitionInner; import org.corpus_tools.annis.api.model.FrequencyTableRow; import org.corpus_tools.annis.gui.Helper; import org.corpus_tools.annis.gui.QueryController; @@ -31,6 +30,7 @@ import org.corpus_tools.salt.util.SaltUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -69,9 +69,9 @@ private List loadBeans() { frequencyQuery.setQuery(query.getQuery()); frequencyQuery.setCorpora(new LinkedList<>(query.getCorpora())); frequencyQuery.setQueryLanguage(query.getApiQueryLanguage()); - List freqDef = new LinkedList(); + List freqDef = new LinkedList(); for (FrequencyTableEntry e : query.getFrequencyDefinition()) { - FrequencyQueryDefinition d = new FrequencyQueryDefinition(); + FrequencyQueryDefinitionInner d = new FrequencyQueryDefinitionInner(); d.setNodeRef(e.getReferencedNode()); switch (e.getType()) { case span: @@ -91,8 +91,8 @@ private List loadBeans() { freqDef.add(d); } frequencyQuery.setDefinition(freqDef); - result = api.frequency(frequencyQuery); - } catch (final ApiException ex) { + result = api.frequency(frequencyQuery).collectList().block(); + } catch (final WebClientResponseException ex) { ui.access(() -> queryController.reportServiceException(ex, true)); } return result; diff --git a/src/main/java/org/corpus_tools/annis/gui/controller/ValidateCallback.java b/src/main/java/org/corpus_tools/annis/gui/controller/ValidateCallback.java new file mode 100644 index 0000000000..b8d4975f5e --- /dev/null +++ b/src/main/java/org/corpus_tools/annis/gui/controller/ValidateCallback.java @@ -0,0 +1,59 @@ +package org.corpus_tools.annis.gui.controller; + +import com.vaadin.ui.UI; +import java.util.LinkedList; +import java.util.List; +import org.corpus_tools.annis.api.model.QueryAttributeDescription; +import org.corpus_tools.annis.gui.QueryController; +import org.corpus_tools.annis.gui.controlpanel.QueryPanel; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.springframework.web.reactive.function.client.WebClientResponseException; + +public class ValidateCallback implements Subscriber { + + private List result; + + private final UI ui; + private final QueryPanel qp; + private final QueryController controller; + + public ValidateCallback(QueryPanel qp, QueryController controller, UI ui) { + this.qp = qp; + this.controller = controller; + this.ui = ui; + } + + @Override + public void onSubscribe(Subscription s) { + result = new LinkedList<>(); + } + + @Override + public void onNext(QueryAttributeDescription attDesc) { + result.add(attDesc); + + } + + @Override + public void onError(Throwable t) { + if (t instanceof WebClientResponseException) { + controller.reportServiceException((WebClientResponseException) t, false); + } + } + + @Override + public void onComplete() { + + ui.access(() -> { + qp.setNodes(result); + if (controller.getState().getSelectedCorpora() == null + || controller.getState().getSelectedCorpora().isEmpty()) { + qp.setStatus("Please select a corpus from the list below, then click on \"Search\"."); + } else { + qp.setStatus("Valid query, click on \"Search\" to start searching."); + } + }); + } + +} diff --git a/src/main/java/org/corpus_tools/annis/gui/controlpanel/CorpusListPanel.java b/src/main/java/org/corpus_tools/annis/gui/controlpanel/CorpusListPanel.java index 3e464925b9..d1d717bd38 100644 --- a/src/main/java/org/corpus_tools/annis/gui/controlpanel/CorpusListPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/controlpanel/CorpusListPanel.java @@ -42,7 +42,6 @@ import java.util.List; import java.util.TreeSet; import java.util.stream.Collectors; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.AnnisUI; import org.corpus_tools.annis.gui.Background; @@ -54,6 +53,7 @@ import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.objects.QueryUIState; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; import org.vaadin.extension.gridscroll.GridScrollExtension; /** @@ -80,7 +80,7 @@ public void run() { // query in background CorporaApi api = new CorporaApi(Helper.getClient(ui)); - List corpora = api.listCorpora(); + List corpora = api.listCorpora().collectList().block(); // update the GUI ui.access(() -> { @@ -299,7 +299,7 @@ public void attach() { CorporaApi api = new CorporaApi(Helper.getClient(ui)); try { - List corpora = api.listCorpora(); + List corpora = api.listCorpora().collectList().block(); availableCorpora = new ListDataProvider<>(corpora); availableCorpora.setFilter(filter); tblCorpora.setDataProvider(availableCorpora); @@ -322,7 +322,7 @@ public void attach() { } - } catch (ApiException e) { + } catch (WebClientResponseException e) { ExceptionDialog.show(e, "Could not get corpus list", getUI()); } diff --git a/src/main/java/org/corpus_tools/annis/gui/exporter/BaseMatrixExporter.java b/src/main/java/org/corpus_tools/annis/gui/exporter/BaseMatrixExporter.java index 98faf70f18..5f68c06312 100644 --- a/src/main/java/org/corpus_tools/annis/gui/exporter/BaseMatrixExporter.java +++ b/src/main/java/org/corpus_tools/annis/gui/exporter/BaseMatrixExporter.java @@ -32,13 +32,11 @@ import javax.xml.stream.XMLStreamException; import org.apache.commons.io.FileUtils; import org.apache.commons.io.LineIterator; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.SearchApi; import org.corpus_tools.annis.api.model.AnnotationComponentType; import org.corpus_tools.annis.api.model.CorpusConfiguration; import org.corpus_tools.annis.api.model.FindQuery; -import org.corpus_tools.annis.api.model.QueryAttributeDescription; import org.corpus_tools.annis.api.model.QueryLanguage; import org.corpus_tools.annis.gui.Helper; import org.corpus_tools.salt.common.SCorpusGraph; @@ -48,6 +46,8 @@ import org.hibernate.cache.CacheException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * An abstract base class for exporters that use Salt subgraphs to some kind of matrix output @@ -71,7 +71,7 @@ public abstract class BaseMatrixExporter implements ExporterPlugin, Serializable * @param args * @param offset */ - private void processFirstPass(SaltProject p, Map args, int offset, int nodeCount) + private void processFirstPass(SaltProject p, Map args, int offset, long nodeCount) throws IOException { int recordNumber = offset; if (p != null && p.getCorpusGraphs() != null) { @@ -92,11 +92,11 @@ private static boolean segmentationNameIsValid(Collection corpora, Strin for (String corpus : corpora) { try { if (corporaApi.components(corpus, AnnotationComponentType.ORDERING.getValue(), segmentation) - .isEmpty()) { + .count().block() == 0) { return false; } - } catch (ApiException ex) { - if (ex.getCode() == 403) { + } catch (WebClientResponseException ex) { + if (ex.getStatusCode() == HttpStatus.FORBIDDEN) { log.debug("Did not have access rights to query segmentation names for corpus", ex); } else { log.warn("Could not query segmentation names for corpus", ex); @@ -145,9 +145,7 @@ public Exception convertText(String queryAnnisQL, QueryLanguage queryLanguage, i File matches = searchApi.find(query).block(); // Get the node count for the query by parsing it - List nodeDescriptions = - searchApi.nodeDescriptions(queryAnnisQL, queryLanguage); - Integer nodeCount = nodeDescriptions.size(); + Long nodeCount = searchApi.nodeDescriptions(queryAnnisQL, queryLanguage).count().block(); List listOfKeys = new ArrayList<>(); @@ -211,7 +209,7 @@ public Exception convertText(String queryAnnisQL, QueryLanguage queryLanguage, i return null; - } catch (ApiException | IOException | CacheException | IllegalStateException + } catch (WebClientResponseException | IOException | CacheException | IllegalStateException | ClassCastException | XMLStreamException ex) { return ex; } @@ -219,7 +217,7 @@ public Exception convertText(String queryAnnisQL, QueryLanguage queryLanguage, i } public abstract void createAdjacencyMatrix(SDocumentGraph graph, Map args, - int recordNumber, int nodeCount) throws IOException; + int recordNumber, long nodeCount) throws IOException; /** * Specifies the ending of export file. diff --git a/src/main/java/org/corpus_tools/annis/gui/exporter/CSVExporter.java b/src/main/java/org/corpus_tools/annis/gui/exporter/CSVExporter.java index 0866fc88ae..8303d3f3da 100644 --- a/src/main/java/org/corpus_tools/annis/gui/exporter/CSVExporter.java +++ b/src/main/java/org/corpus_tools/annis/gui/exporter/CSVExporter.java @@ -76,7 +76,8 @@ public class CSVExporter extends BaseMatrixExporter { * */ @Override - public void createAdjacencyMatrix(SDocumentGraph graph, Map args, int matchNumber, int nodeCount) + public void createAdjacencyMatrix(SDocumentGraph graph, Map args, + int matchNumber, long nodeCount) throws IOException, IllegalArgumentException { // first match if (matchNumber == 0) { diff --git a/src/main/java/org/corpus_tools/annis/gui/exporter/ExportHelper.java b/src/main/java/org/corpus_tools/annis/gui/exporter/ExportHelper.java index ae83c8d0e2..8e5bb00f0b 100644 --- a/src/main/java/org/corpus_tools/annis/gui/exporter/ExportHelper.java +++ b/src/main/java/org/corpus_tools/annis/gui/exporter/ExportHelper.java @@ -13,7 +13,6 @@ import java.util.TreeMap; import java.util.TreeSet; import javax.xml.stream.XMLStreamException; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.AnnotationComponentType; import org.corpus_tools.annis.api.model.CorpusConfiguration; @@ -29,6 +28,7 @@ import org.corpus_tools.salt.common.SDocumentGraph; import org.corpus_tools.salt.common.SaltProject; import org.eclipse.emf.common.util.URI; +import org.springframework.web.reactive.function.client.WebClientResponseException; public class ExportHelper { @@ -51,7 +51,7 @@ protected static SaltProject documentGraphToProject(SDocumentGraph graph, private static void recreateTimelineIfNecessary(SaltProject p, CorporaApi corporaApi, Map corpusConfigs) - throws ApiException, UnsupportedEncodingException { + throws WebClientResponseException, UnsupportedEncodingException { Set corpusNames = Helper.getToplevelCorpusNames(p); @@ -119,7 +119,7 @@ private static void recreateTimeline(SaltProject p, StrategyEnum timelineStrateg protected static Optional getSubgraphForMatch(String match, CorporaApi corporaApi, int contextLeft, int contextRight, Map args, Map corpusConfigs) - throws ApiException, IOException, XMLStreamException { + throws WebClientResponseException, IOException, XMLStreamException { // iterate over all matches and get the sub-graph for a group of matches Match parsedMatch = Match.parseFromString(match); diff --git a/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java b/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java index 1336e2ced7..4484ab2192 100644 --- a/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java +++ b/src/main/java/org/corpus_tools/annis/gui/exporter/GeneralTextExporter.java @@ -36,7 +36,6 @@ import javax.xml.stream.XMLStreamException; import org.apache.commons.io.FileUtils; import org.apache.commons.io.LineIterator; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.SearchApi; import org.corpus_tools.annis.api.model.Annotation; @@ -52,6 +51,7 @@ import org.corpus_tools.salt.core.SFeature; import org.corpus_tools.salt.core.SMetaAnnotation; import org.corpus_tools.salt.core.SNode; +import org.springframework.web.reactive.function.client.WebClientResponseException; public abstract class GeneralTextExporter implements ExporterPlugin, Serializable { @@ -197,7 +197,7 @@ public Exception convertText(String queryAnnisQL, QueryLanguage queryLanguage, i return null; - } catch (ApiException | IOException | XMLStreamException ex) { + } catch (WebClientResponseException | IOException | XMLStreamException ex) { return ex; } } @@ -226,7 +226,7 @@ public boolean needsContext() { * @throws ApiException */ protected List getAllAnnotationsAsExporterKey(Collection corpora, - CorporaApi api) throws ApiException { + CorporaApi api) throws WebClientResponseException { LinkedList keys = new LinkedList<>(); keys.add("tok"); List attributes = new LinkedList<>(); diff --git a/src/main/java/org/corpus_tools/annis/gui/exporter/TextColumnExporter.java b/src/main/java/org/corpus_tools/annis/gui/exporter/TextColumnExporter.java index 939e9ccea4..ac8e862895 100644 --- a/src/main/java/org/corpus_tools/annis/gui/exporter/TextColumnExporter.java +++ b/src/main/java/org/corpus_tools/annis/gui/exporter/TextColumnExporter.java @@ -280,7 +280,8 @@ private List calculateOrderedMatchNumbersGlobally(int[][] adjacencyMatrix, * returned for the user query */ @Override - public void createAdjacencyMatrix(SDocumentGraph graph, Map args, int recordNumber, int nodeCount) + public void createAdjacencyMatrix(SDocumentGraph graph, Map args, + int recordNumber, long nodeCount) throws IOException { String currSpeakerName = ""; String prevSpeakerName = ""; @@ -294,7 +295,7 @@ public void createAdjacencyMatrix(SDocumentGraph graph, Map args filterNumbersSetByUser.clear(); filterNumbersIsEmpty = true; listOfMetakeys.clear(); - adjacencyMatrix = new int[nodeCount][nodeCount]; + adjacencyMatrix = new int[(int) nodeCount][(int) nodeCount]; matrixIsFilled = false; singleMatchesGlobal.clear(); orderedMatchNumbersGlobal.clear(); diff --git a/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java b/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java index 0b2e5c1a3c..59365ed020 100644 --- a/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java +++ b/src/main/java/org/corpus_tools/annis/gui/flatquerybuilder/FlatQueryBuilder.java @@ -34,7 +34,6 @@ import java.util.List; import java.util.Set; import java.util.TreeSet; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.AnnoKey; import org.corpus_tools.annis.api.model.Annotation; @@ -379,7 +378,7 @@ public Set getAvailableMetaNames() { } } - } catch (ApiException ex) { + } catch (WebClientResponseException ex) { log.error(null, ex); } diff --git a/src/main/java/org/corpus_tools/annis/gui/frequency/FrequencyQueryPanel.java b/src/main/java/org/corpus_tools/annis/gui/frequency/FrequencyQueryPanel.java index 3a4951461a..8551b43b57 100644 --- a/src/main/java/org/corpus_tools/annis/gui/frequency/FrequencyQueryPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/frequency/FrequencyQueryPanel.java @@ -43,7 +43,6 @@ import java.util.List; import java.util.Set; import java.util.WeakHashMap; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.SearchApi; import org.corpus_tools.annis.api.model.FrequencyTableRow; import org.corpus_tools.annis.api.model.QueryAttributeDescription; @@ -54,6 +53,7 @@ import org.corpus_tools.annis.gui.objects.QueryUIState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -239,7 +239,7 @@ public FrequencyQueryPanel(final QueryController controller, QueryUIState state) try { nodes = parseQuery(FrequencyQueryPanel.this.state.getAql().getValue(), FrequencyQueryPanel.this.state.getQueryLanguage()); - } catch (ApiException e) { + } catch (WebClientResponseException e) { // Ignore } nr = Math.min(nr, nodes.size() - 1); @@ -447,7 +447,7 @@ private void createAutomaticEntriesForQuery(String query, } } } - } catch (ApiException ex) { + } catch (WebClientResponseException ex) { // non-valid query, ignore } @@ -466,13 +466,14 @@ public void notifiyQueryFinished() { } private List parseQuery(String query, QueryLanguage queryLanguage) - throws ApiException { + throws WebClientResponseException { if (query == null || query.isEmpty()) { return new LinkedList<>(); } // let the service parse the query SearchApi api = new SearchApi(Helper.getClient(UI.getCurrent())); - List nodes = api.nodeDescriptions(query, queryLanguage); + List nodes = + api.nodeDescriptions(query, queryLanguage).collectList().block(); return nodes; } diff --git a/src/main/java/org/corpus_tools/annis/gui/objects/QueryUIState.java b/src/main/java/org/corpus_tools/annis/gui/objects/QueryUIState.java index 783e5a5b9d..ff92aee17e 100644 --- a/src/main/java/org/corpus_tools/annis/gui/objects/QueryUIState.java +++ b/src/main/java/org/corpus_tools/annis/gui/objects/QueryUIState.java @@ -26,7 +26,7 @@ import java.util.Set; import java.util.TreeSet; import java.util.concurrent.Future; -import okhttp3.Call; +import org.apache.http.concurrent.Cancellable; import org.corpus_tools.annis.api.model.FindQuery.OrderEnum; import org.corpus_tools.annis.api.model.QueryLanguage; import org.corpus_tools.annis.gui.exporter.CSVExporter; @@ -79,7 +79,7 @@ public enum QueryType { private transient Map> executedTasks; - private transient Map executedCalls; + private transient Map executedCalls; private final BeanContainer frequencyTableDefinition = new BeanContainer<>(UserGeneratedFrequencyEntry.class); @@ -110,7 +110,7 @@ public Map> getExecutedTasks() { return executedTasks; } - public Map getExecutedCalls() { + public Map getExecutedCalls() { return executedCalls; } diff --git a/src/main/java/org/corpus_tools/annis/gui/requesthandler/BinaryRequestHandler.java b/src/main/java/org/corpus_tools/annis/gui/requesthandler/BinaryRequestHandler.java index ce9f7062e5..d3ea112f86 100644 --- a/src/main/java/org/corpus_tools/annis/gui/requesthandler/BinaryRequestHandler.java +++ b/src/main/java/org/corpus_tools/annis/gui/requesthandler/BinaryRequestHandler.java @@ -21,21 +21,19 @@ import com.vaadin.server.VaadinServletResponse; import com.vaadin.server.VaadinSession; import java.io.IOException; -import java.util.ArrayList; import java.util.Enumeration; -import java.util.HashMap; import java.util.List; import java.util.Map; -import okhttp3.Call; -import okhttp3.Response; import org.apache.commons.io.IOUtils; import org.corpus_tools.annis.ApiClient; -import org.corpus_tools.annis.ApiException; -import org.corpus_tools.annis.Pair; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.CommonUI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * This request handler provides binary-files. It will proxy all requests to the REST service. Since @@ -100,54 +98,42 @@ public void sendResponse(VaadinSession session, VaadinRequest request, CorporaApi api = new CorporaApi(ui.getClient()); ApiClient client = api.getApiClient(); - // create path and map variables - String localVarPath = "/corpora/{corpus}/files/{name}" - .replaceAll("\\{" + "corpus" + "\\}", client.escapeString(toplevelCorpusName)) - .replaceAll("\\{" + "name" + "\\}", client.escapeString(filePath)); - - List localVarQueryParams = new ArrayList(); - List localVarCollectionQueryParams = new ArrayList(); - Map localVarHeaderParams = new HashMap(); - Map localVarCookieParams = new HashMap(); - Map localVarFormParams = new HashMap(); - - Enumeration originalHeaderNames = request.getHeaderNames(); - while (originalHeaderNames.hasMoreElements()) { - String headerName = originalHeaderNames.nextElement(); - String headerValue = request.getHeader(headerName); - localVarHeaderParams.put(headerName, headerValue); - } final String[] localVarAccepts = {"default"}; - final String localVarAccept = client.selectHeaderAccept(localVarAccepts); - if (localVarAccept != null) { - localVarHeaderParams.put("Accept", localVarAccept); - } + List localVarAccept = client.selectHeaderAccept(localVarAccepts); - final String[] localVarContentTypes = {}; - final String localVarContentType = client.selectHeaderContentType(localVarContentTypes); - localVarHeaderParams.put("Content-Type", localVarContentType); - String[] localVarAuthNames = new String[] {"bearerAuth"}; + final String[] localVarContentTypes = {}; + MediaType localVarContentType = client.selectHeaderContentType(localVarContentTypes); + // Execute the call and return the response - Call call; try { - call = client.buildCall(localVarPath, "GET", localVarQueryParams, - localVarCollectionQueryParams, null, localVarHeaderParams, localVarCookieParams, - localVarFormParams, localVarAuthNames, null); + ResponseEntity proxyResponse = client.getWebClient().get() + .uri("/corpora/{top}/files/{path}", toplevelCorpusName, filePath) + .accept(localVarAccept.toArray(new MediaType[0])).headers(httpHeaders -> { + Enumeration originalHeaderNames = request.getHeaderNames(); + while (originalHeaderNames.hasMoreElements()) { + String headerName = originalHeaderNames.nextElement(); + String headerValue = request.getHeader(headerName); + httpHeaders.set(headerName, headerValue); + httpHeaders.set("Content-Type", localVarContentType.toString()); + } + }).retrieve().toEntity(DataBuffer.class).block(); - Response proxyResponse = call.execute(); // Copy response headers - for (String headerName : proxyResponse.headers().names()) { - response.setHeader(headerName, proxyResponse.header(headerName)); + for (String headerName : proxyResponse.getHeaders().keySet()) { + List headerValues = proxyResponse.getHeaders().getValuesAsList(headerName); + if(!headerValues.isEmpty()) { + response.setHeader(headerName, headerValues.get(0)); + } } // Copy response body - response.setStatus(proxyResponse.code()); - IOUtils.copy(proxyResponse.body().byteStream(), response.getOutputStream()); - } catch (ApiException e) { + response.setStatus(proxyResponse.getStatusCodeValue()); + IOUtils.copy(proxyResponse.getBody().asInputStream(), response.getOutputStream()); + } catch (WebClientResponseException e) { log.error("Could not get binary data from service", e); - response.sendError(e.getCode(), e.getMessage()); + response.sendError(e.getStatusCode().value(), e.getMessage()); } } diff --git a/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java b/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java index 4cce9fecb0..408ac7ea54 100644 --- a/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java +++ b/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java @@ -14,6 +14,7 @@ package org.corpus_tools.annis.gui.resultfetch; import com.google.common.base.Joiner; +import com.google.gson.Gson; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; @@ -24,8 +25,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import javax.xml.stream.XMLStreamException; -import org.corpus_tools.annis.ApiException; -import org.corpus_tools.annis.JSON; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.SearchApi; import org.corpus_tools.annis.api.model.BadRequestError; @@ -49,6 +48,8 @@ import org.eclipse.emf.common.util.URI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * A thread that queries for the matches, fetches the the subgraph for the matches and updates the @@ -98,7 +99,7 @@ public void run() { q.setLimit(query.getLimit()); q.setQueryLanguage(query.getApiQueryLanguage()); q.setOrder(query.getOrder()); - File findResult = search.find(q); + File findResult = search.find(q).block(); try (Stream findResultLines = Files.lines(findResult.toPath(), StandardCharsets.UTF_8)) { findResultLines.forEachOrdered(line -> { @@ -150,14 +151,15 @@ public void run() { } } // end if no results - } catch (final ApiException ex) { + } catch (final WebClientResponseException ex) { ui.access(() -> { if (resultPanel != null && resultPanel.getPaging() != null) { PagingComponent paging = resultPanel.getPaging(); - if (ex.getCode() == 400) { - JSON json = new JSON(); - BadRequestError error = json.deserialize(ex.getResponseBody(), BadRequestError.class); + if (ex.getStatusCode() == HttpStatus.BAD_REQUEST) { + Gson json = new Gson(); + BadRequestError error = + json.fromJson(ex.getResponseBodyAsString(), BadRequestError.class); String errMsg = ""; if (error.getAqLSyntaxError() != null) { @@ -168,9 +170,9 @@ public void run() { } paging.setInfo("parsing error: " + errMsg); - } else if (ex.getCode() == 504) { + } else if (ex.getStatusCode() == HttpStatus.GATEWAY_TIMEOUT) { paging.setInfo("Timeout: query execution took too long"); - } else if (ex.getCode() == 403) { + } else if (ex.getStatusCode() == HttpStatus.FORBIDDEN) { paging.setInfo("Not authorized to query this corpus."); } else { ExceptionDialog.show(ex, ui); @@ -185,13 +187,13 @@ public void run() { } private SaltProject createSaltFromMatch(Match m, SubgraphWithContext arg, int currentMatchNumber, - CorporaApi api) throws ApiException { + CorporaApi api) throws WebClientResponseException { List corpusPathRaw = Helper.getCorpusPath(m.getSaltIDs().get(0), false); List corpusPathDecoded = Helper.getCorpusPath(m.getSaltIDs().get(0), true); final SaltProject p = SaltFactory.createSaltProject(); if (!corpusPathRaw.isEmpty()) { - File graphML = api.subgraphForNodes(corpusPathDecoded.get(0), arg); + File graphML = api.subgraphForNodes(corpusPathDecoded.get(0), arg).block(); try { final SCorpusGraph cg = p.createCorpusGraph(); diff --git a/src/main/java/org/corpus_tools/annis/gui/resultfetch/SingleResultFetchJob.java b/src/main/java/org/corpus_tools/annis/gui/resultfetch/SingleResultFetchJob.java index 7ad30b6bf8..4e43ce6cc2 100644 --- a/src/main/java/org/corpus_tools/annis/gui/resultfetch/SingleResultFetchJob.java +++ b/src/main/java/org/corpus_tools/annis/gui/resultfetch/SingleResultFetchJob.java @@ -76,7 +76,7 @@ public SaltProject call() throws Exception { SCorpusGraph cg = p.createCorpusGraph(); if (!corpusPath.isEmpty()) { - File graphML = api.subgraphForNodes(corpusPath.get(0), subgraphQuery); + File graphML = api.subgraphForNodes(corpusPath.get(0), subgraphQuery).block(); URI docURI = URI.createURI("salt:/" + Joiner.on('/').join(corpusPath)); SDocument doc = cg.createDocument(docURI); SDocumentGraph docGraph = DocumentGraphMapper.map(graphML); diff --git a/src/main/java/org/corpus_tools/annis/gui/security/AutoTokenRefreshClient.java b/src/main/java/org/corpus_tools/annis/gui/security/AutoTokenRefreshClient.java index fd641bd38e..f578f7e0f1 100644 --- a/src/main/java/org/corpus_tools/annis/gui/security/AutoTokenRefreshClient.java +++ b/src/main/java/org/corpus_tools/annis/gui/security/AutoTokenRefreshClient.java @@ -1,12 +1,7 @@ package org.corpus_tools.annis.gui.security; -import java.lang.reflect.Type; import java.util.Optional; -import okhttp3.Call; -import org.corpus_tools.annis.ApiCallback; import org.corpus_tools.annis.ApiClient; -import org.corpus_tools.annis.ApiException; -import org.corpus_tools.annis.ApiResponse; import org.corpus_tools.annis.gui.CommonUI; import org.corpus_tools.annis.gui.Helper; import org.springframework.security.oauth2.core.user.OAuth2User; @@ -21,12 +16,9 @@ public AutoTokenRefreshClient(CommonUI ui, AuthenticationSuccessListener authLis this.ui = ui; this.authListener = authListener; - setReadTimeout(0); - // Use the configuration to allow changing the path to the web-service setBasePath(ui.getConfig().getWebserviceUrl()); - updateToken(); } @@ -39,15 +31,4 @@ private void updateToken() { } } - @Override - public ApiResponse execute(Call call, Type returnType) throws ApiException { - updateToken(); - return super.execute(call, returnType); - } - - @Override - public void executeAsync(Call call, Type returnType, ApiCallback callback) { - updateToken(); - super.executeAsync(call, returnType, callback); - } } diff --git a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/AudioVisualizer.java b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/AudioVisualizer.java index 1d711c7f7a..78148b76e0 100644 --- a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/AudioVisualizer.java +++ b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/AudioVisualizer.java @@ -21,7 +21,6 @@ import com.vaadin.ui.UI; import java.util.List; import org.apache.tika.Tika; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.Helper; import org.corpus_tools.annis.gui.VisualizationToggle; @@ -32,6 +31,7 @@ import org.corpus_tools.annis.gui.visualizers.AbstractVisualizer; import org.corpus_tools.annis.gui.visualizers.VisualizerInput; import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -61,7 +61,8 @@ public MediaElementPlayer createComponent(VisualizerInput input, VisualizationTo CorporaApi api = new CorporaApi(Helper.getClient(input.getUI())); try { List files = - api.listFiles(corpusName, Joiner.on('/').join(Lists.reverse(corpusPath))); + api.listFiles(corpusName, Joiner.on('/').join(Lists.reverse(corpusPath))).collectList() + .block(); for (String f : files) { String guessedMimeType = tika.detect(f); if (guessedMimeType != null && guessedMimeType.startsWith("audio/")) { @@ -71,7 +72,7 @@ public MediaElementPlayer createComponent(VisualizerInput input, VisualizationTo mimeType = guessedMimeType; } } - } catch (ApiException e) { + } catch (WebClientResponseException e) { ExceptionDialog.show(e, UI.getCurrent()); } diff --git a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/VideoVisualizer.java b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/VideoVisualizer.java index 6a3dc974fd..52f405f610 100644 --- a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/VideoVisualizer.java +++ b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/VideoVisualizer.java @@ -21,7 +21,6 @@ import com.vaadin.ui.UI; import java.util.List; import org.apache.tika.Tika; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.Helper; import org.corpus_tools.annis.gui.VisualizationToggle; @@ -32,6 +31,7 @@ import org.corpus_tools.annis.gui.visualizers.AbstractVisualizer; import org.corpus_tools.annis.gui.visualizers.VisualizerInput; import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.WebClientResponseException; /** * @@ -61,7 +61,8 @@ public MediaElementPlayer createComponent(VisualizerInput input, VisualizationTo CorporaApi api = new CorporaApi(Helper.getClient(input.getUI())); try { List files = - api.listFiles(corpusName, Joiner.on('/').join(Lists.reverse(corpusPath))); + api.listFiles(corpusName, Joiner.on('/').join(Lists.reverse(corpusPath))).collectList() + .block(); for (String f : files) { String guessedMimeType = tika.detect(f); if (guessedMimeType != null && guessedMimeType.startsWith("video/")) { @@ -71,7 +72,7 @@ public MediaElementPlayer createComponent(VisualizerInput input, VisualizationTo mimeType = guessedMimeType; } } - } catch (ApiException e) { + } catch (WebClientResponseException e) { ExceptionDialog.show(e, UI.getCurrent()); } diff --git a/src/main/resources/openapi.yml b/src/main/resources/openapi.yml index 104910136a..9a3ebb76ef 100644 --- a/src/main/resources/openapi.yml +++ b/src/main/resources/openapi.yml @@ -123,30 +123,20 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/Job" + type: string "200": - description: Job was finished successfully and result can be downloaded from the body - "303": - description: Job was finished successfully + description: Job was finished successfully. The body contains the messages from the import. content: application/json: schema: - type: array + type: string description: The messages produced by the background job. - example: - [ - "started import of corpus GUM", - "reading GraphML", - "Error during import of GUM: corpus already exists", - ] - items: - type: string "410": description: Job failed content: application/json: schema: - $ref: "#/components/schemas/Job" + type: string "404": description: Job not found diff --git a/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java b/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java index ddbeb46acc..2455e2f314 100644 --- a/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java +++ b/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java @@ -9,7 +9,6 @@ import java.awt.FontFormatException; import java.io.IOException; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.AnnisUI; import org.corpus_tools.annis.gui.components.ExceptionDialog; @@ -19,6 +18,7 @@ import org.corpus_tools.salt.samples.SampleGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.springframework.web.reactive.function.client.WebClientResponseException; import reactor.core.publisher.Flux; class PDFPanelTest { @@ -39,7 +39,7 @@ void setup() throws FontFormatException, IOException { } @Test - void testBinaryPathOneFile() throws ApiException { + void testBinaryPathOneFile() throws WebClientResponseException { SCorpusGraph corpusGraph = SampleGenerator.createCorpusStructure(); SDocument doc = corpusGraph.getDocuments().get(0); @@ -56,7 +56,7 @@ void testBinaryPathOneFile() throws ApiException { } @Test - void testBinaryPathNoFile() throws ApiException { + void testBinaryPathNoFile() throws WebClientResponseException { SCorpusGraph corpusGraph = SampleGenerator.createCorpusStructure(); SDocument doc = corpusGraph.getDocuments().get(0); @@ -71,7 +71,7 @@ void testBinaryPathNoFile() throws ApiException { } @Test - void testBinaryPathApiExceptionThrown() throws ApiException + void testBinaryPathApiExceptionThrown() throws WebClientResponseException { SCorpusGraph corpusGraph = SampleGenerator.createCorpusStructure(); SDocument doc = corpusGraph.getDocuments().get(0); @@ -84,7 +84,7 @@ void testBinaryPathApiExceptionThrown() throws ApiException // Make sure the document has an assigned PDF file CorporaApi api = mock(CorporaApi.class); when(api.listFiles(anyString(), anyString())) - .thenThrow(new ApiException("Invalid Network Access")); + .thenThrow(new WebClientResponseException(500, "Invalid Network Access", null, null, null)); assertEquals("", fixture.getBinaryPath(api)); verify(ui).addWindow(any(ExceptionDialog.class)); diff --git a/src/test/java/org/corpus_tools/annis/gui/visualizers/htmlvis/HTMLVisTest.java b/src/test/java/org/corpus_tools/annis/gui/visualizers/htmlvis/HTMLVisTest.java index f30f7b16f5..fd730c5860 100644 --- a/src/test/java/org/corpus_tools/annis/gui/visualizers/htmlvis/HTMLVisTest.java +++ b/src/test/java/org/corpus_tools/annis/gui/visualizers/htmlvis/HTMLVisTest.java @@ -23,7 +23,6 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import org.apache.commons.io.FileUtils; -import org.corpus_tools.annis.ApiException; import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.AnnisBaseUI; import org.junit.jupiter.api.BeforeEach; @@ -31,6 +30,8 @@ import org.mockito.Mockito; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import reactor.core.publisher.Mono; class HTMLVisTest { @@ -44,14 +45,14 @@ public void setup() { } @Test - void testWebFontInjection() throws ApiException, IOException { + void testWebFontInjection() throws WebClientResponseException, IOException { AnnisBaseUI ui = mock(AnnisBaseUI.class); CorporaApi api = mock(CorporaApi.class); File jsonFile = File.createTempFile("test", ".fonts.json"); FileUtils.writeStringToFile(jsonFile, "{\"web-fonts\": [" + "{" + "\"name\": \"FancyFont\", " + "\"sources\": {\"format\":\"url\"}}" + "]}", StandardCharsets.UTF_8); - when(api.getFile("rootCorpus", "rootCorpus/test.fonts.json")).thenReturn(jsonFile); + when(api.getFile("rootCorpus", "rootCorpus/test.fonts.json")).thenReturn(Mono.just(jsonFile)); fixture.injectWebFonts("test", "rootCorpus", "rootCorpus", ui, api); @@ -61,7 +62,7 @@ void testWebFontInjection() throws ApiException, IOException { } @Test - void testWebFontInjectionErrorHandling() throws ApiException, IOException { + void testWebFontInjectionErrorHandling() throws WebClientResponseException, IOException { AnnisBaseUI ui = mock(AnnisBaseUI.class); Page page = mock(Page.class); CorporaApi api = mock(CorporaApi.class); @@ -72,14 +73,15 @@ void testWebFontInjectionErrorHandling() throws ApiException, IOException { // Create invalid JSON file File jsonFile = File.createTempFile("test", ".fonts.json"); FileUtils.writeStringToFile(jsonFile, "{\"web-fonts\"}", StandardCharsets.UTF_8); - when(api.getFile("rootCorpus", "rootCorpus/test.fonts.json")).thenReturn(jsonFile); + when(api.getFile("rootCorpus", "rootCorpus/test.fonts.json")).thenReturn(Mono.just(jsonFile)); fixture.injectWebFonts("test", "rootCorpus", "rootCorpus", ui, api); verify(ui, Mockito.never()).injectUniqueCSS(any()); // Don't return a file from the API - when(api.getFile(any(), any())).thenThrow(new ApiException(500, "Server error")); + when(api.getFile(any(), any())) + .thenThrow(new WebClientResponseException(500, "Server error", null, null, null)); fixture.injectWebFonts("test", "rootCorpus", "rootCorpus", ui, api); From 7e10ed09c67bed89e0afcf17adc25db8b7bb56a7 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Fri, 9 Dec 2022 17:33:28 +0100 Subject: [PATCH 10/61] Add a "patched" CorpusApi implementation that allows to get the list of strings as mono. If https://github.com/OpenAPITools/openapi-generator/pull/14125 gets merged, we won't need this workaround anymore --- .../gui/controlpanel/CorpusListPanel.java | 10 +-- .../corpus_tools/api/PatchedCorporaApi.java | 65 +++++++++++++++++++ 2 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/corpus_tools/api/PatchedCorporaApi.java diff --git a/src/main/java/org/corpus_tools/annis/gui/controlpanel/CorpusListPanel.java b/src/main/java/org/corpus_tools/annis/gui/controlpanel/CorpusListPanel.java index d1d717bd38..d5f01ceac6 100644 --- a/src/main/java/org/corpus_tools/annis/gui/controlpanel/CorpusListPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/controlpanel/CorpusListPanel.java @@ -42,7 +42,6 @@ import java.util.List; import java.util.TreeSet; import java.util.stream.Collectors; -import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.AnnisUI; import org.corpus_tools.annis.gui.Background; import org.corpus_tools.annis.gui.CorpusBrowserPanel; @@ -52,6 +51,7 @@ import org.corpus_tools.annis.gui.MetaDataPanel; import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.objects.QueryUIState; +import org.corpus_tools.api.PatchedCorporaApi; import org.slf4j.LoggerFactory; import org.springframework.web.reactive.function.client.WebClientResponseException; import org.vaadin.extension.gridscroll.GridScrollExtension; @@ -78,9 +78,9 @@ public void run() { try { // query in background - CorporaApi api = new CorporaApi(Helper.getClient(ui)); + PatchedCorporaApi api = new PatchedCorporaApi(Helper.getClient(ui)); - List corpora = api.listCorpora().collectList().block(); + List corpora = api.listCorporaAsMono().block(); // update the GUI ui.access(() -> { @@ -296,10 +296,10 @@ public void attach() { // Get the initial corpus list, this must become before the binder is set, // to make sure any selected value is also an item. - CorporaApi api = new CorporaApi(Helper.getClient(ui)); + PatchedCorporaApi api = new PatchedCorporaApi(Helper.getClient(ui)); try { - List corpora = api.listCorpora().collectList().block(); + List corpora = api.listCorporaAsMono().block(); availableCorpora = new ListDataProvider<>(corpora); availableCorpora.setFilter(filter); tblCorpora.setDataProvider(availableCorpora); diff --git a/src/main/java/org/corpus_tools/api/PatchedCorporaApi.java b/src/main/java/org/corpus_tools/api/PatchedCorporaApi.java new file mode 100644 index 0000000000..a254548fa3 --- /dev/null +++ b/src/main/java/org/corpus_tools/api/PatchedCorporaApi.java @@ -0,0 +1,65 @@ +package org.corpus_tools.api; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.corpus_tools.annis.ApiClient; +import org.corpus_tools.annis.api.CorporaApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.client.WebClient.ResponseSpec; +import org.springframework.web.reactive.function.client.WebClientResponseException; +import reactor.core.publisher.Mono; + +public class PatchedCorporaApi extends CorporaApi { + + @Autowired + public PatchedCorporaApi(ApiClient apiClient) { + super(apiClient); + } + + public Mono> listCorporaAsMono() throws WebClientResponseException { + ParameterizedTypeReference> localVarReturnType = + new ParameterizedTypeReference>() {}; + return listCorporaRequestCreation().bodyToMono(localVarReturnType); + } + + /** + * Get a list of all corpora the user is authorized to use. + * + *

+ * 200 - OK + * + * @return List<String> + * @throws WebClientResponseException if an error occurs while attempting to invoke the API + */ + private ResponseSpec listCorporaRequestCreation() throws WebClientResponseException { + Object postBody = null; + // create path and map variables + final Map pathParams = new HashMap(); + + final MultiValueMap queryParams = new LinkedMultiValueMap(); + final HttpHeaders headerParams = new HttpHeaders(); + final MultiValueMap cookieParams = new LinkedMultiValueMap(); + final MultiValueMap formParams = new LinkedMultiValueMap(); + + final String[] localVarAccepts = {"application/json"}; + final List localVarAccept = getApiClient().selectHeaderAccept(localVarAccepts); + final String[] localVarContentTypes = {}; + final MediaType localVarContentType = + getApiClient().selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] {"bearerAuth"}; + + ParameterizedTypeReference localVarReturnType = + new ParameterizedTypeReference() {}; + return getApiClient().invokeAPI("/corpora", HttpMethod.GET, pathParams, queryParams, postBody, + headerParams, cookieParams, formParams, localVarAccept, localVarContentType, + localVarAuthNames, localVarReturnType); + } +} From db60d7a49a3837e0a348d96d500ee2d2527f4437 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Fri, 9 Dec 2022 17:41:20 +0100 Subject: [PATCH 11/61] Use the patched API where the corpus list is fetched --- .../java/org/corpus_tools/annis/gui/SearchView.java | 12 ++++++------ .../annis/gui/admin/model/CorpusManagement.java | 5 +++-- .../annis/gui/admin/reflinks/MigrationPanel.java | 6 +++--- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/SearchView.java b/src/main/java/org/corpus_tools/annis/gui/SearchView.java index 9d7ea24802..1fe7c8b589 100644 --- a/src/main/java/org/corpus_tools/annis/gui/SearchView.java +++ b/src/main/java/org/corpus_tools/annis/gui/SearchView.java @@ -46,7 +46,6 @@ import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.controlpanel.ControlPanel; import org.corpus_tools.annis.gui.docbrowser.DocBrowserController; @@ -61,6 +60,7 @@ import org.corpus_tools.annis.gui.objects.Query; import org.corpus_tools.annis.gui.objects.QueryLanguage; import org.corpus_tools.annis.gui.resultview.ResultViewPanel; +import org.corpus_tools.api.PatchedCorporaApi; import org.slf4j.LoggerFactory; import org.springframework.web.reactive.function.client.WebClientResponseException; @@ -239,11 +239,11 @@ public void evaluateCitation(String relativeUri) { selectedCorpora.addAll(Arrays.asList(cids)); } - // filter by actually avaible user corpora in order not to get any exception + // filter by actually available user corpora in order not to get any exception // later - CorporaApi api = new CorporaApi(Helper.getClient(ui)); + PatchedCorporaApi api = new PatchedCorporaApi(Helper.getClient(ui)); try { - List userCorpora = api.listCorpora().collectList().block(); + List userCorpora = api.listCorporaAsMono().block(); selectedCorpora.retainAll(userCorpora); } catch (WebClientResponseException ex) { log.error("Could not get list of corpora", ex); @@ -290,9 +290,9 @@ private void evaluateFragment(String fragment) { Set corpora = new TreeSet(Arrays.asList(originalCorpusNames)); // Remove all corpora we don't have the access right to try { - CorporaApi api = new CorporaApi(Helper.getClient(ui)); + PatchedCorporaApi api = new PatchedCorporaApi(Helper.getClient(ui)); Set availableCorpora = - new HashSet<>(api.listCorpora().collectList().block()); + new HashSet<>(api.listCorporaAsMono().block()); corpora.removeIf(c -> !availableCorpora.contains(c)); } catch (WebClientResponseException e) { ExceptionDialog.show(e, "Could not get corpus list", ui); diff --git a/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java b/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java index 9a5c809074..b14fe5656c 100644 --- a/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java +++ b/src/main/java/org/corpus_tools/annis/gui/admin/model/CorpusManagement.java @@ -19,6 +19,7 @@ import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.CriticalServiceQueryException; import org.corpus_tools.annis.gui.ServiceQueryException; +import org.corpus_tools.api.PatchedCorporaApi; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; @@ -67,9 +68,9 @@ public void fetchFromService() throws CriticalServiceQueryException, ServiceQuer if (clientProvider != null) { corpora.clear(); - CorporaApi api = new CorporaApi(clientProvider.getClient()); + PatchedCorporaApi api = new PatchedCorporaApi(clientProvider.getClient()); try { - corpora.addAll(api.listCorpora().collectList().block()); + corpora.addAll(api.listCorporaAsMono().block()); } catch (WebClientResponseException ex) { if (ex.getStatusCode() == HttpStatus.UNAUTHORIZED) { throw new CriticalServiceQueryException("You are not authorized to get the corpus list."); diff --git a/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java b/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java index 313390a467..161a82b773 100644 --- a/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/admin/reflinks/MigrationPanel.java @@ -39,13 +39,13 @@ import okhttp3.Request; import okhttp3.Response; import org.corpus_tools.annis.ApiClient; -import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.SearchApi; import org.corpus_tools.annis.gui.AnnisUI; import org.corpus_tools.annis.gui.Background; import org.corpus_tools.annis.gui.Helper; import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.query_references.UrlShortener; +import org.corpus_tools.api.PatchedCorporaApi; import org.springframework.security.oauth2.core.user.OAuth2User; import org.springframework.web.reactive.function.client.WebClientResponseException; import org.springframework.web.util.UriComponentsBuilder; @@ -302,9 +302,9 @@ private int migrateUrlShortener(String serviceURL, String username, String passw .addPathSegment("query").addPathSegment("search").build(); ApiClient apiClient = Helper.getClient(ui); - CorporaApi corporaApi = new CorporaApi(apiClient); + PatchedCorporaApi corporaApi = new PatchedCorporaApi(apiClient); SearchApi searchApi = new SearchApi(apiClient); - Set knownCorpora = new HashSet<>(corporaApi.listCorpora().collectList().block()); + Set knownCorpora = new HashSet<>(corporaApi.listCorporaAsMono().block()); Optional client = createClient(serviceURL, username, password); From 9aee36f31089f5261152d7f11ea035605f2dc0a8 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Mon, 12 Dec 2022 11:06:08 +0100 Subject: [PATCH 12/61] Use the patched API where the file list is fetched --- .../component/AudioVisualizer.java | 7 +-- .../component/VideoVisualizer.java | 7 +-- .../visualizers/component/pdf/PDFPanel.java | 8 +-- .../corpus_tools/api/PatchedCorporaApi.java | 58 +++++++++++++++++++ .../component/pdf/PDFPanelTest.java | 20 ++++--- 5 files changed, 79 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/AudioVisualizer.java b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/AudioVisualizer.java index 78148b76e0..d07e288318 100644 --- a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/AudioVisualizer.java +++ b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/AudioVisualizer.java @@ -21,7 +21,6 @@ import com.vaadin.ui.UI; import java.util.List; import org.apache.tika.Tika; -import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.Helper; import org.corpus_tools.annis.gui.VisualizationToggle; import org.corpus_tools.annis.gui.components.ExceptionDialog; @@ -30,6 +29,7 @@ import org.corpus_tools.annis.gui.media.MediaController; import org.corpus_tools.annis.gui.visualizers.AbstractVisualizer; import org.corpus_tools.annis.gui.visualizers.VisualizerInput; +import org.corpus_tools.api.PatchedCorporaApi; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClientResponseException; @@ -58,11 +58,10 @@ public MediaElementPlayer createComponent(VisualizerInput input, VisualizationTo String corpusName = corpusPath.get(corpusPath.size() - 1); - CorporaApi api = new CorporaApi(Helper.getClient(input.getUI())); + PatchedCorporaApi api = new PatchedCorporaApi(Helper.getClient(input.getUI())); try { List files = - api.listFiles(corpusName, Joiner.on('/').join(Lists.reverse(corpusPath))).collectList() - .block(); + api.listFilesAsMono(corpusName, Joiner.on('/').join(Lists.reverse(corpusPath))).block(); for (String f : files) { String guessedMimeType = tika.detect(f); if (guessedMimeType != null && guessedMimeType.startsWith("audio/")) { diff --git a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/VideoVisualizer.java b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/VideoVisualizer.java index 52f405f610..cc1761dd93 100644 --- a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/VideoVisualizer.java +++ b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/VideoVisualizer.java @@ -21,7 +21,6 @@ import com.vaadin.ui.UI; import java.util.List; import org.apache.tika.Tika; -import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.Helper; import org.corpus_tools.annis.gui.VisualizationToggle; import org.corpus_tools.annis.gui.components.ExceptionDialog; @@ -30,6 +29,7 @@ import org.corpus_tools.annis.gui.media.MediaController; import org.corpus_tools.annis.gui.visualizers.AbstractVisualizer; import org.corpus_tools.annis.gui.visualizers.VisualizerInput; +import org.corpus_tools.api.PatchedCorporaApi; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClientResponseException; @@ -58,11 +58,10 @@ public MediaElementPlayer createComponent(VisualizerInput input, VisualizationTo String corpusName = corpusPath.get(corpusPath.size() - 1); - CorporaApi api = new CorporaApi(Helper.getClient(input.getUI())); + PatchedCorporaApi api = new PatchedCorporaApi(Helper.getClient(input.getUI())); try { List files = - api.listFiles(corpusName, Joiner.on('/').join(Lists.reverse(corpusPath))).collectList() - .block(); + api.listFilesAsMono(corpusName, Joiner.on('/').join(Lists.reverse(corpusPath))).block(); for (String f : files) { String guessedMimeType = tika.detect(f); if (guessedMimeType != null && guessedMimeType.startsWith("video/")) { diff --git a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanel.java b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanel.java index 73e8888d65..0079a10630 100644 --- a/src/main/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanel.java +++ b/src/main/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanel.java @@ -24,10 +24,10 @@ import java.util.Collections; import java.util.List; import java.util.UUID; -import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.gui.Helper; import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.visualizers.VisualizerInput; +import org.corpus_tools.api.PatchedCorporaApi; import org.springframework.web.reactive.function.client.WebClientResponseException; /** @@ -87,13 +87,13 @@ public void attach() { setSizeUndefined(); // set the state - getState().binaryURL = getBinaryPath(new CorporaApi(Helper.getClient(input.getUI()))); + getState().binaryURL = getBinaryPath(new PatchedCorporaApi(Helper.getClient(input.getUI()))); getState().pdfID = getPDF_ID(); getState().firstPage = firstPage; getState().lastPage = lastPage; } - protected String getBinaryPath(CorporaApi api) { + protected String getBinaryPath(PatchedCorporaApi api) { List corpusPath = Helper.getCorpusPath(input.getDocument().getGraph(), input.getDocument()); @@ -101,7 +101,7 @@ protected String getBinaryPath(CorporaApi api) { String corpusName = corpusPath.get(0); try { - for (String f : api.listFiles(corpusName, Joiner.on('/').join(corpusPath)).toIterable()) { + for (String f : api.listFilesAsMono(corpusName, Joiner.on('/').join(corpusPath)).block()) { if (f.endsWith(".pdf")) { // Create an URL how to featch the PDF file return input.getContextPath() + "/Binary?" + "toplevelCorpusName=" diff --git a/src/main/java/org/corpus_tools/api/PatchedCorporaApi.java b/src/main/java/org/corpus_tools/api/PatchedCorporaApi.java index a254548fa3..fed2628943 100644 --- a/src/main/java/org/corpus_tools/api/PatchedCorporaApi.java +++ b/src/main/java/org/corpus_tools/api/PatchedCorporaApi.java @@ -9,6 +9,7 @@ import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -62,4 +63,61 @@ private ResponseSpec listCorporaRequestCreation() throws WebClientResponseExcept headerParams, cookieParams, formParams, localVarAccept, localVarContentType, localVarAuthNames, localVarReturnType); } + + public Mono> listFilesAsMono(String corpus, String node) + throws WebClientResponseException { + ParameterizedTypeReference> localVarReturnType = + new ParameterizedTypeReference>() {}; + return listFilesRequestCreation(corpus, node).bodyToMono(localVarReturnType); + } + + /** + * List the names of all associated file for the corpus. + * + *

+ * 200 - Returns the list of files + * + * @param corpus The name of the corpus to get the configuration for. + * @param node If given, only the files for the (sub-) corpus or document with this ID are + * returned. + * @return List<String> + * @throws WebClientResponseException if an error occurs while attempting to invoke the API + */ + private ResponseSpec listFilesRequestCreation(String corpus, String node) + throws WebClientResponseException { + Object postBody = null; + // verify the required parameter 'corpus' is set + if (corpus == null) { + throw new WebClientResponseException( + "Missing the required parameter 'corpus' when calling listFiles", + HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.getReasonPhrase(), null, null, + null); + } + // create path and map variables + final Map pathParams = new HashMap(); + + pathParams.put("corpus", corpus); + + final MultiValueMap queryParams = new LinkedMultiValueMap(); + final HttpHeaders headerParams = new HttpHeaders(); + final MultiValueMap cookieParams = new LinkedMultiValueMap(); + final MultiValueMap formParams = new LinkedMultiValueMap(); + + queryParams.putAll(getApiClient().parameterToMultiValueMap(null, "node", node)); + + final String[] localVarAccepts = {"default"}; + final List localVarAccept = getApiClient().selectHeaderAccept(localVarAccepts); + final String[] localVarContentTypes = {}; + final MediaType localVarContentType = + getApiClient().selectHeaderContentType(localVarContentTypes); + + String[] localVarAuthNames = new String[] {"bearerAuth"}; + + ParameterizedTypeReference localVarReturnType = + new ParameterizedTypeReference() {}; + return getApiClient().invokeAPI("/corpora/{corpus}/files", HttpMethod.GET, pathParams, + queryParams, + postBody, headerParams, cookieParams, formParams, localVarAccept, localVarContentType, + localVarAuthNames, localVarReturnType); + } } diff --git a/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java b/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java index 2455e2f314..0a784905cc 100644 --- a/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java +++ b/src/test/java/org/corpus_tools/annis/gui/visualizers/component/pdf/PDFPanelTest.java @@ -9,17 +9,19 @@ import java.awt.FontFormatException; import java.io.IOException; -import org.corpus_tools.annis.api.CorporaApi; +import java.util.Arrays; +import java.util.LinkedList; import org.corpus_tools.annis.gui.AnnisUI; import org.corpus_tools.annis.gui.components.ExceptionDialog; import org.corpus_tools.annis.gui.visualizers.VisualizerInput; +import org.corpus_tools.api.PatchedCorporaApi; import org.corpus_tools.salt.common.SCorpusGraph; import org.corpus_tools.salt.common.SDocument; import org.corpus_tools.salt.samples.SampleGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.web.reactive.function.client.WebClientResponseException; -import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; class PDFPanelTest { @@ -47,9 +49,9 @@ void testBinaryPathOneFile() throws WebClientResponseException { when(input.getContextPath()).thenReturn("/context"); // Make sure the document has an assigned PDF file - CorporaApi api = mock(CorporaApi.class); - when(api.listFiles(anyString(), anyString())) - .thenReturn(Flux.just("notapdf.webm", "test.pdf")); + PatchedCorporaApi api = mock(PatchedCorporaApi.class); + when(api.listFilesAsMono(anyString(), anyString())) + .thenReturn(Mono.just(Arrays.asList("notapdf.webm", "test.pdf"))); assertEquals("/context/Binary?toplevelCorpusName=rootCorpus&file=test.pdf", fixture.getBinaryPath(api)); @@ -64,8 +66,8 @@ void testBinaryPathNoFile() throws WebClientResponseException { when(input.getContextPath()).thenReturn("/context"); // Make sure the document has an assigned PDF file - CorporaApi api = mock(CorporaApi.class); - when(api.listFiles(anyString(), anyString())).thenReturn(Flux.just()); + PatchedCorporaApi api = mock(PatchedCorporaApi.class); + when(api.listFilesAsMono(anyString(), anyString())).thenReturn(Mono.just(new LinkedList<>())); assertEquals("", fixture.getBinaryPath(api)); } @@ -82,8 +84,8 @@ void testBinaryPathApiExceptionThrown() throws WebClientResponseException when(input.getUI()).thenReturn(ui); // Make sure the document has an assigned PDF file - CorporaApi api = mock(CorporaApi.class); - when(api.listFiles(anyString(), anyString())) + PatchedCorporaApi api = mock(PatchedCorporaApi.class); + when(api.listFilesAsMono(anyString(), anyString())) .thenThrow(new WebClientResponseException(500, "Invalid Network Access", null, null, null)); assertEquals("", fixture.getBinaryPath(api)); From da4c948465a47ce7d4abf0a82c0bfefce08fd0fc Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Tue, 13 Dec 2022 16:10:16 +0100 Subject: [PATCH 13/61] Attempt to configure a WebClient bean with authentfication --- .../org/corpus_tools/annis/gui/AnnisUI.java | 9 ++++ .../annis/gui/AnnisUiApplication.java | 1 - .../org/corpus_tools/annis/gui/CommonUI.java | 2 - .../annis/gui/resultfetch/ResultFetchJob.java | 16 +++++-- .../gui/security/SecurityConfiguration.java | 46 ++++++++++++++++++- 5 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/AnnisUI.java b/src/main/java/org/corpus_tools/annis/gui/AnnisUI.java index 539e1615fd..0363d70f33 100644 --- a/src/main/java/org/corpus_tools/annis/gui/AnnisUI.java +++ b/src/main/java/org/corpus_tools/annis/gui/AnnisUI.java @@ -53,6 +53,7 @@ import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties; import org.springframework.core.env.Environment; import org.springframework.core.env.Profiles; +import org.springframework.web.reactive.function.client.WebClient; /** * GUI for searching in corpora. @@ -92,6 +93,10 @@ public class AnnisUI extends CommonUI implements ErrorHandler, ViewChangeListene @Autowired private UIConfig config; + @Autowired + private WebClient webClient; + + private final AuthenticationSuccessListener authListener; private AdminView adminView; @@ -264,6 +269,10 @@ public ApiClient getClient() { return new AutoTokenRefreshClient(this, this.getAuthListener()); } + public WebClient getWebClient() { + return webClient; + } + public UIConfig getConfig() { return config; diff --git a/src/main/java/org/corpus_tools/annis/gui/AnnisUiApplication.java b/src/main/java/org/corpus_tools/annis/gui/AnnisUiApplication.java index 0d4368cd9e..e6974aec3a 100644 --- a/src/main/java/org/corpus_tools/annis/gui/AnnisUiApplication.java +++ b/src/main/java/org/corpus_tools/annis/gui/AnnisUiApplication.java @@ -7,7 +7,6 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.ServletComponentScan; import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.PropertySource; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.transaction.annotation.EnableTransactionManagement; diff --git a/src/main/java/org/corpus_tools/annis/gui/CommonUI.java b/src/main/java/org/corpus_tools/annis/gui/CommonUI.java index d5739fb5b2..0d66c0948c 100644 --- a/src/main/java/org/corpus_tools/annis/gui/CommonUI.java +++ b/src/main/java/org/corpus_tools/annis/gui/CommonUI.java @@ -176,8 +176,6 @@ public String getUrlPrefix() { public abstract ApiClient getClient(); - - /** * Handle common errors like database/service connection problems and display a unified error * message. diff --git a/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java b/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java index 408ac7ea54..57cd20e1b4 100644 --- a/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java +++ b/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java @@ -26,7 +26,6 @@ import java.util.stream.Stream; import javax.xml.stream.XMLStreamException; import org.corpus_tools.annis.api.CorporaApi; -import org.corpus_tools.annis.api.SearchApi; import org.corpus_tools.annis.api.model.BadRequestError; import org.corpus_tools.annis.api.model.FindQuery; import org.corpus_tools.annis.api.model.SubgraphWithContext; @@ -48,8 +47,12 @@ import org.eclipse.emf.common.util.URI; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.web.reactive.function.client.WebClientResponseException; +import reactor.core.publisher.Flux; /** * A thread that queries for the matches, fetches the the subgraph for the matches and updates the @@ -76,7 +79,6 @@ public ResultFetchJob(PagedResultQuery query, ResultViewPanel resultPanel, Annis @Override public void run() { - SearchApi search = new SearchApi(Helper.getClient(ui)); CorporaApi corpora = new CorporaApi(Helper.getClient(ui)); // holds the ids of the matches. @@ -99,7 +101,14 @@ public void run() { q.setLimit(query.getLimit()); q.setQueryLanguage(query.getApiQueryLanguage()); q.setOrder(query.getOrder()); - File findResult = search.find(q).block(); + + Flux response = ui.getWebClient().post().uri("/search/find") + .accept(MediaType.TEXT_PLAIN).retrieve() + .bodyToFlux(DataBuffer.class); + + File findResult = File.createTempFile("annis-result", ".txt"); + DataBufferUtils.write(response, findResult.toPath()).block(); + try (Stream findResultLines = Files.lines(findResult.toPath(), StandardCharsets.UTF_8)) { findResultLines.forEachOrdered(line -> { @@ -152,6 +161,7 @@ public void run() { } // end if no results } catch (final WebClientResponseException ex) { + log.error("Could execute find query", ex); ui.access(() -> { if (resultPanel != null && resultPanel.getPaging() != null) { PagingComponent paging = resultPanel.getPaging(); diff --git a/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java b/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java index 94e959b6fa..11b28e2330 100644 --- a/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java +++ b/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java @@ -1,13 +1,24 @@ package org.corpus_tools.annis.gui.security; +import java.util.Optional; +import org.corpus_tools.annis.gui.UIConfig; import org.springframework.boot.autoconfigure.condition.NoneNestedConditions; import org.springframework.boot.autoconfigure.security.oauth2.client.ClientsConfiguredCondition; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder; +import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; +import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; +import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; +import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction; +import org.springframework.web.reactive.function.client.WebClient; @Configuration @@ -51,7 +62,7 @@ protected void configure(HttpSecurity http) throws Exception { public void configure(WebSecurity web) { ignoreVaadinWebSecurity(web); } - + } @EnableWebSecurity @@ -70,6 +81,39 @@ public void configure(WebSecurity web) { } } + @Bean + WebClient webClient(UIConfig config, + Optional authorizedClientManager) { + Optional filter = authorizedClientManager.map(acm -> { + ServletOAuth2AuthorizedClientExchangeFilterFunction filter = + new ServletOAuth2AuthorizedClientExchangeFilterFunction(acm); + + filter.setDefaultClientRegistrationId("annis"); + return filter; + }); + WebClientBuilder builder = WebClient.builder().baseUrl(config.getWebserviceUrl()); + if (filter.isSome()) { + builder = builder.config.getWebserviceUrl(); + } + return builder.build(); + } + + @Bean + @Conditional(ClientsConfiguredCondition.class) + public OAuth2AuthorizedClientManager authorizedClientManager( + ClientRegistrationRepository clientRegistrationRepository, + OAuth2AuthorizedClientRepository authorizedClientRepository) { + + OAuth2AuthorizedClientProvider authorizedClientProvider = + OAuth2AuthorizedClientProviderBuilder.builder().clientCredentials().build(); + + DefaultOAuth2AuthorizedClientManager authorizedClientManager = + new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, + authorizedClientRepository); + authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); + return authorizedClientManager; + } + private static void ignoreVaadinWebSecurity(WebSecurity web) { web.ignoring().antMatchers( // client-side JS code From 1151b2000ee6c1298d7f785728355adc8232ffdb Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Fri, 16 Dec 2022 15:05:32 +0100 Subject: [PATCH 14/61] Fix compilation issues --- .../annis/gui/security/SecurityConfiguration.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java b/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java index 11b28e2330..b3b14c4706 100644 --- a/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java +++ b/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java @@ -85,15 +85,15 @@ public void configure(WebSecurity web) { WebClient webClient(UIConfig config, Optional authorizedClientManager) { Optional filter = authorizedClientManager.map(acm -> { - ServletOAuth2AuthorizedClientExchangeFilterFunction filter = + ServletOAuth2AuthorizedClientExchangeFilterFunction result = new ServletOAuth2AuthorizedClientExchangeFilterFunction(acm); - filter.setDefaultClientRegistrationId("annis"); - return filter; + result.setDefaultClientRegistrationId("annis"); + return result; }); - WebClientBuilder builder = WebClient.builder().baseUrl(config.getWebserviceUrl()); - if (filter.isSome()) { - builder = builder.config.getWebserviceUrl(); + WebClient.Builder builder = WebClient.builder().baseUrl(config.getWebserviceUrl()); + if (filter.isPresent()) { + builder = builder.filter(filter.get()); } return builder.build(); } From b4e1fa00ec32eb333d6350d3ca6c03df0ee3cdb0 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Fri, 16 Dec 2022 15:07:02 +0100 Subject: [PATCH 15/61] Formatting --- .../annis/gui/security/SecurityConfiguration.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java b/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java index b3b14c4706..50ebd0667c 100644 --- a/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java +++ b/src/main/java/org/corpus_tools/annis/gui/security/SecurityConfiguration.java @@ -84,13 +84,14 @@ public void configure(WebSecurity web) { @Bean WebClient webClient(UIConfig config, Optional authorizedClientManager) { - Optional filter = authorizedClientManager.map(acm -> { - ServletOAuth2AuthorizedClientExchangeFilterFunction result = - new ServletOAuth2AuthorizedClientExchangeFilterFunction(acm); - - result.setDefaultClientRegistrationId("annis"); - return result; - }); + Optional filter = + authorizedClientManager.map(acm -> { + ServletOAuth2AuthorizedClientExchangeFilterFunction result = + new ServletOAuth2AuthorizedClientExchangeFilterFunction(acm); + + result.setDefaultClientRegistrationId("annis"); + return result; + }); WebClient.Builder builder = WebClient.builder().baseUrl(config.getWebserviceUrl()); if (filter.isPresent()) { builder = builder.filter(filter.get()); From 651e265716d2bded12492ea8fde7925bada3ccd2 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Mon, 22 May 2023 13:29:14 +0200 Subject: [PATCH 16/61] Excplicitly set the H2 dialect --- src/main/resources/application.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6a0391fc9a..89898a2be5 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -9,6 +9,7 @@ vaadin.servlet.productionMode=true # Path to the persistent database, where e.g. the reference links are stored spring.datasource.url=jdbc:h2:file:${user.home}/.annis/v4/frontend_data.h2 +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect # Automatically create and update the schema spring.jpa.generate-ddl=true From 63550492ccbc9f192812ae3c96c3a06d1d5469ef Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Mon, 22 May 2023 13:35:14 +0200 Subject: [PATCH 17/61] Removed double dependency entry for the salt-api --- pom.xml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/pom.xml b/pom.xml index ad2afbd6f2..a469651514 100644 --- a/pom.xml +++ b/pom.xml @@ -427,20 +427,6 @@ h2 runtime - - - org.corpus-tools - salt-api - 3.4.2 - - - - com.google.guava - guava - - - - io.swagger swagger-annotations From 436171440da67e650ac0f40dd4348e4be2c95911 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Mon, 22 May 2023 14:03:25 +0200 Subject: [PATCH 18/61] Use webclient in ApiClient --- src/main/java/org/corpus_tools/annis/gui/AnnisUI.java | 5 +++-- .../corpus_tools/annis/gui/resultfetch/ResultFetchJob.java | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/AnnisUI.java b/src/main/java/org/corpus_tools/annis/gui/AnnisUI.java index 0363d70f33..d12c99682c 100644 --- a/src/main/java/org/corpus_tools/annis/gui/AnnisUI.java +++ b/src/main/java/org/corpus_tools/annis/gui/AnnisUI.java @@ -45,7 +45,6 @@ import org.corpus_tools.annis.gui.querybuilder.QueryBuilderPlugin; import org.corpus_tools.annis.gui.requesthandler.BinaryRequestHandler; import org.corpus_tools.annis.gui.security.AuthenticationSuccessListener; -import org.corpus_tools.annis.gui.security.AutoTokenRefreshClient; import org.corpus_tools.annis.gui.security.SecurityConfiguration; import org.corpus_tools.annis.gui.visualizers.VisualizerPlugin; import org.slf4j.LoggerFactory; @@ -266,7 +265,9 @@ protected void init(VaadinRequest request) { @Override public ApiClient getClient() { - return new AutoTokenRefreshClient(this, this.getAuthListener()); + ApiClient result = new ApiClient(webClient); + result.setBasePath(getConfig().getWebserviceUrl()); + return result; } public WebClient getWebClient() { diff --git a/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java b/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java index 57cd20e1b4..75c2cbb1d5 100644 --- a/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java +++ b/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java @@ -102,7 +102,8 @@ public void run() { q.setQueryLanguage(query.getApiQueryLanguage()); q.setOrder(query.getOrder()); - Flux response = ui.getWebClient().post().uri("/search/find") + Flux response = + ui.getWebClient().post().uri(ui.getConfig().getWebserviceUrl() + "/search/find") .accept(MediaType.TEXT_PLAIN).retrieve() .bodyToFlux(DataBuffer.class); From aa98f78e0bb2e701c1ca1d2f47fb4dcc8e67a31d Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Mon, 22 May 2023 14:37:09 +0200 Subject: [PATCH 19/61] Send find query as body --- .../annis/gui/resultfetch/ResultFetchJob.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java b/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java index 75c2cbb1d5..2f645a0794 100644 --- a/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java +++ b/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java @@ -102,11 +102,12 @@ public void run() { q.setQueryLanguage(query.getApiQueryLanguage()); q.setOrder(query.getOrder()); + Flux response = ui.getWebClient().post().uri(ui.getConfig().getWebserviceUrl() + "/search/find") - .accept(MediaType.TEXT_PLAIN).retrieve() - .bodyToFlux(DataBuffer.class); - + .contentType(MediaType.APPLICATION_JSON).bodyValue(q).accept(MediaType.TEXT_PLAIN) + .retrieve().bodyToFlux(DataBuffer.class); + File findResult = File.createTempFile("annis-result", ".txt"); DataBufferUtils.write(response, findResult.toPath()).block(); @@ -162,7 +163,7 @@ public void run() { } // end if no results } catch (final WebClientResponseException ex) { - log.error("Could execute find query", ex); + log.error("Could not execute find query", ex); ui.access(() -> { if (resultPanel != null && resultPanel.getPaging() != null) { PagingComponent paging = resultPanel.getPaging(); @@ -192,7 +193,7 @@ public void run() { } }); - } catch(IOException ex) { + } catch (IOException ex) { ui.access(() -> ExceptionDialog.show(ex, ui)); } } From 5f94243cf117bf7a94722cd1ecb5eb13f17243c8 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Tue, 23 May 2023 15:03:04 +0200 Subject: [PATCH 20/61] Update openapi and spring dependencies and use the raw webclient API to get subgraph. --- pom.xml | 6 ++++-- .../annis/gui/resultfetch/ResultFetchJob.java | 19 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index a469651514..b132e6b5b6 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.5 + 2.7.12 @@ -285,7 +285,7 @@ org.openapitools openapi-generator-maven-plugin - 6.0.0 + 6.6.0 @@ -308,6 +308,8 @@ webclient java8 false + true + true serializableModel=true diff --git a/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java b/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java index 2f645a0794..fa47a7455c 100644 --- a/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java +++ b/src/main/java/org/corpus_tools/annis/gui/resultfetch/ResultFetchJob.java @@ -25,7 +25,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import javax.xml.stream.XMLStreamException; -import org.corpus_tools.annis.api.CorporaApi; import org.corpus_tools.annis.api.model.BadRequestError; import org.corpus_tools.annis.api.model.FindQuery; import org.corpus_tools.annis.api.model.SubgraphWithContext; @@ -79,8 +78,6 @@ public ResultFetchJob(PagedResultQuery query, ResultViewPanel resultPanel, Annis @Override public void run() { - CorporaApi corpora = new CorporaApi(Helper.getClient(ui)); - // holds the ids of the matches. MatchGroup result = new MatchGroup(); @@ -150,7 +147,7 @@ public void run() { arg.setSegmentation(query.getSegmentation()); arg.setNodeIds(m.getSaltIDs().stream().collect(Collectors.toList())); - SaltProject p = createSaltFromMatch(m, arg, current, corpora); + SaltProject p = createSaltFromMatch(m, arg, current); ui.access(() -> resultPanel.addQueryResult(query, p, matchList)); @@ -198,14 +195,22 @@ public void run() { } } - private SaltProject createSaltFromMatch(Match m, SubgraphWithContext arg, int currentMatchNumber, - CorporaApi api) throws WebClientResponseException { + private SaltProject createSaltFromMatch(Match m, SubgraphWithContext arg, int currentMatchNumber) throws WebClientResponseException, IOException { List corpusPathRaw = Helper.getCorpusPath(m.getSaltIDs().get(0), false); List corpusPathDecoded = Helper.getCorpusPath(m.getSaltIDs().get(0), true); final SaltProject p = SaltFactory.createSaltProject(); if (!corpusPathRaw.isEmpty()) { - File graphML = api.subgraphForNodes(corpusPathDecoded.get(0), arg).block(); + Flux response = + ui.getWebClient().post() + .uri(ui.getConfig().getWebserviceUrl() + "/corpora/{corpus}/subgraph", + corpusPathDecoded.get(0)) + .contentType(MediaType.APPLICATION_JSON).bodyValue(arg) + .accept(MediaType.APPLICATION_XML) + .retrieve().bodyToFlux(DataBuffer.class); + File graphML = File.createTempFile("annis-subgraph", ".salt"); + DataBufferUtils.write(response, graphML.toPath()).block(); + try { final SCorpusGraph cg = p.createCorpusGraph(); From 6159897f11aa1eef38305b39b412a0c739d74185 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Tue, 23 May 2023 15:50:06 +0200 Subject: [PATCH 21/61] Disable special XML handling --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index b132e6b5b6..12fd8acdfa 100644 --- a/pom.xml +++ b/pom.xml @@ -309,7 +309,6 @@ java8 false true - true serializableModel=true From 90519533caac94dd880c7b12fc0ea1d81dc73585 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Thu, 13 Jul 2023 13:25:02 +0200 Subject: [PATCH 22/61] Use asynchronous webclient functionality to get the count result --- .../annis/gui/QueryController.java | 17 +++++-- .../annis/gui/controller/CountCallback.java | 44 ++----------------- .../annis/gui/objects/QueryUIState.java | 6 +-- 3 files changed, 20 insertions(+), 47 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/QueryController.java b/src/main/java/org/corpus_tools/annis/gui/QueryController.java index be186cb82e..dc44df46b8 100644 --- a/src/main/java/org/corpus_tools/annis/gui/QueryController.java +++ b/src/main/java/org/corpus_tools/annis/gui/QueryController.java @@ -73,6 +73,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.reactive.function.client.WebClientResponseException; +import reactor.core.Disposable; /** * A controller to modifiy the query UI state. s @@ -430,9 +431,19 @@ public void executeSearch(boolean replaceOldTab, boolean freshQuery) { try { CountCallback callback = new CountCallback(newResultView, displayedQuery.getLimit(), annisUI); - api.count(countQuery).single().subscribe(callback); - - state.getExecutedCalls().put(QueryUIState.QueryType.COUNT, callback); + Disposable countDisposable = api.count(countQuery).doOnNext(callback).doOnError(t -> { + annisUI.access(() -> { + annisUI.getQueryState().getExecutedTasks().remove(QueryUIState.QueryType.COUNT); + if (t instanceof WebClientResponseException) { + annisUI.getQueryController().reportServiceException((WebClientResponseException) t, + true); + } else { + log.error("Could not get count result", t); + } + }); + }).single().subscribe(); + + state.getExecutedCalls().put(QueryUIState.QueryType.COUNT, countDisposable); } catch (WebClientResponseException ex) { ExceptionDialog.show(ex, ui); } diff --git a/src/main/java/org/corpus_tools/annis/gui/controller/CountCallback.java b/src/main/java/org/corpus_tools/annis/gui/controller/CountCallback.java index 8d453bd00e..c63f26a2a6 100644 --- a/src/main/java/org/corpus_tools/annis/gui/controller/CountCallback.java +++ b/src/main/java/org/corpus_tools/annis/gui/controller/CountCallback.java @@ -13,22 +13,20 @@ */ package org.corpus_tools.annis.gui.controller; -import org.apache.http.concurrent.Cancellable; +import java.util.function.Consumer; import org.corpus_tools.annis.api.model.CountExtra; import org.corpus_tools.annis.gui.AnnisUI; import org.corpus_tools.annis.gui.objects.QueryUIState; import org.corpus_tools.annis.gui.resultview.ResultViewPanel; -import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.web.reactive.function.client.WebClientResponseException; /** * * @author Thomas Krause {@literal } */ -public class CountCallback implements Subscriber, Cancellable { +public class CountCallback implements Consumer { private static final Logger log = LoggerFactory.getLogger(CountCallback.class); @@ -42,14 +40,8 @@ public CountCallback(ResultViewPanel panel, int pageSize, AnnisUI ui) { this.pageSize = pageSize; this.ui = ui; } - - @Override - public void onSubscribe(Subscription s) { - this.subscription = s; - } - @Override - public void onNext(CountExtra result) { + public void accept(CountExtra result) { ui.access(() -> { ui.getQueryState().getExecutedTasks().remove(QueryUIState.QueryType.COUNT); @@ -63,37 +55,7 @@ public void onNext(CountExtra result) { } ui.getSearchView().getControlPanel().getQueryPanel().setCountIndicatorEnabled(false); }); - } - - @Override - public void onError(Throwable t) { - ui.access(() -> { - ui.getQueryState().getExecutedTasks().remove(QueryUIState.QueryType.COUNT); - if (t instanceof WebClientResponseException) { - ui.getQueryController().reportServiceException((WebClientResponseException) t, true); - } else { - log.error("Could not get count result", t); - } - }); - } - @Override - public void onComplete() { - // nothing to do - } - - public Subscription getSubscription() { - return subscription; - } - - @Override - public boolean cancel() { - if (subscription == null) { - return false; - } else { - subscription.cancel(); - return true; - } } } diff --git a/src/main/java/org/corpus_tools/annis/gui/objects/QueryUIState.java b/src/main/java/org/corpus_tools/annis/gui/objects/QueryUIState.java index ff92aee17e..3fb8f37f08 100644 --- a/src/main/java/org/corpus_tools/annis/gui/objects/QueryUIState.java +++ b/src/main/java/org/corpus_tools/annis/gui/objects/QueryUIState.java @@ -26,7 +26,6 @@ import java.util.Set; import java.util.TreeSet; import java.util.concurrent.Future; -import org.apache.http.concurrent.Cancellable; import org.corpus_tools.annis.api.model.FindQuery.OrderEnum; import org.corpus_tools.annis.api.model.QueryLanguage; import org.corpus_tools.annis.gui.exporter.CSVExporter; @@ -34,6 +33,7 @@ import org.corpus_tools.annis.gui.frequency.UserGeneratedFrequencyEntry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import reactor.core.Disposable; /** * Helper class to bundle all query relevant state information of the UI. @@ -79,7 +79,7 @@ public enum QueryType { private transient Map> executedTasks; - private transient Map executedCalls; + private transient Map executedCalls; private final BeanContainer frequencyTableDefinition = new BeanContainer<>(UserGeneratedFrequencyEntry.class); @@ -110,7 +110,7 @@ public Map> getExecutedTasks() { return executedTasks; } - public Map getExecutedCalls() { + public Map getExecutedCalls() { return executedCalls; } From 965ba8723a6c725a85caa30f2227f5796a888d01 Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Thu, 13 Jul 2023 13:51:33 +0200 Subject: [PATCH 23/61] Use jackson do deserialize parsing error message. --- .../corpus_tools/annis/gui/QueryController.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/corpus_tools/annis/gui/QueryController.java b/src/main/java/org/corpus_tools/annis/gui/QueryController.java index dc44df46b8..7ea642e14d 100644 --- a/src/main/java/org/corpus_tools/annis/gui/QueryController.java +++ b/src/main/java/org/corpus_tools/annis/gui/QueryController.java @@ -13,9 +13,10 @@ */ package org.corpus_tools.annis.gui; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.eventbus.EventBus; import com.google.common.util.concurrent.FutureCallback; -import com.google.gson.Gson; import com.vaadin.data.Binder; import com.vaadin.data.provider.ListDataProvider; import com.vaadin.server.FontAwesome; @@ -513,9 +514,15 @@ public void reportServiceException(WebClientResponseException ex, boolean showNo switch (ex.getStatusCode()) { case BAD_REQUEST: - Gson gson = new Gson(); - BadRequestError error = - gson.fromJson(ex.getResponseBodyAsString(), BadRequestError.class); + ObjectMapper mapper = new ObjectMapper(); + BadRequestError error = new BadRequestError(); + try { + error = mapper.readValue(ex.getResponseBodyAsString(), BadRequestError.class); + } catch (JsonProcessingException parseEx) { + ui.access(() -> { + ExceptionDialog.show(parseEx, "Could not parse response from server", ui); + }); + } caption = "Parsing error"; if (error.getAqLSyntaxError() != null) { From f0bdcfd96d3f2aa6dfc7101bccb90191a022031a Mon Sep 17 00:00:00 2001 From: Thomas Krause Date: Tue, 25 Jul 2023 15:22:46 +0200 Subject: [PATCH 24/61] Recompile online help with mdbook 0.4.32 --- src/main/webapp/VAADIN/help/404.html | 24 ++++++++++++++++++- .../webapp/VAADIN/help/aql/annotations.html | 24 ++++++++++++++++++- .../VAADIN/help/aql/compatibility-mode.html | 24 ++++++++++++++++++- src/main/webapp/VAADIN/help/aql/export.html | 24 ++++++++++++++++++- .../webapp/VAADIN/help/aql/frequency.html | 24 ++++++++++++++++++- src/main/webapp/VAADIN/help/aql/index.html | 24 ++++++++++++++++++- src/main/webapp/VAADIN/help/aql/negation.html | 24 ++++++++++++++++++- .../webapp/VAADIN/help/aql/operators.html | 24 ++++++++++++++++++- src/main/webapp/VAADIN/help/aql/pointing.html | 24 ++++++++++++++++++- src/main/webapp/VAADIN/help/aql/regex.html | 24 ++++++++++++++++++- src/main/webapp/VAADIN/help/aql/trees.html | 24 ++++++++++++++++++- .../webapp/VAADIN/help/aql/word-forms.html | 24 ++++++++++++++++++- src/main/webapp/VAADIN/help/book.js | 18 +++++--------- src/main/webapp/VAADIN/help/index.html | 24 ++++++++++++++++++- .../webapp/VAADIN/help/interface/index.html | 24 ++++++++++++++++++- .../VAADIN/help/interface/query-builder.html | 24 ++++++++++++++++++- .../VAADIN/help/interface/result-window.html | 24 ++++++++++++++++++- .../VAADIN/help/interface/search-form.html | 24 ++++++++++++++++++- src/main/webapp/VAADIN/help/print.html | 24 ++++++++++++++++++- 19 files changed, 420 insertions(+), 30 deletions(-) diff --git a/src/main/webapp/VAADIN/help/404.html b/src/main/webapp/VAADIN/help/404.html index 320e79b311..baaa433fdd 100644 --- a/src/main/webapp/VAADIN/help/404.html +++ b/src/main/webapp/VAADIN/help/404.html @@ -89,11 +89,33 @@

+ + +
-