From 54c11660a13972e259c04c011a707e97153abffe Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 28 May 2018 16:49:35 +0200 Subject: [PATCH 001/176] Upgrade libraries to more recent versions - spring boot to 1.5.13 - spring framework to 4.3.17 - snakeyaml to 1.21 - zmon-actuator to 0.9.8 - postgresql to 42.2.2 - spring-cloud-starter-hystrix to 1.3.6 - httpclient to 4.5.5 - json-schema to 1.8.0 --- build.gradle | 68 +++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/build.gradle b/build.gradle index 0f5d78607f..41c79de694 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,35 @@ import java.util.concurrent.TimeUnit -apply plugin: 'java' -apply plugin: 'groovy' -apply plugin: 'eclipse' -apply plugin: 'application' -apply plugin: 'spring-boot' -apply plugin: "jacoco" -apply plugin: 'findbugs' -apply plugin: 'checkstyle' -apply plugin: 'project-report' +buildscript { + ext { + springBootVersion = '1.5.13.RELEASE' + springFrameworkVersion = '4.3.17.RELEASE' + } + + repositories { + mavenCentral() + maven { + url "https://plugins.gradle.org/m2/" + } + } + + dependencies { + classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion" + classpath 'org.yaml:snakeyaml:1.21' + } +} + +plugins { + id 'java' + id 'groovy' + id 'eclipse' + id 'application' + id 'jacoco' + id 'findbugs' + id 'checkstyle' + id 'project-report' + id 'org.springframework.boot' version "1.5.13.RELEASE" +} group 'org.zalando' sourceCompatibility = 1.8 @@ -64,25 +85,6 @@ sourceSets { } } -buildscript { - ext { - springBootVersion = '1.5.3.RELEASE' - springFrameworkVersion = '4.3.8.RELEASE' - } - - repositories { - mavenCentral() - maven { - url "https://plugins.gradle.org/m2/" - } - } - - dependencies { - classpath "org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE" - classpath 'org.yaml:snakeyaml:1.17' - } -} - jar { baseName = 'nakadi' } @@ -128,16 +130,16 @@ dependencies { // actuator compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion" - compile 'org.zalando.zmon:zmon-actuator:0.9.7' + compile 'org.zalando.zmon:zmon-actuator:0.9.8' // storage compile "org.springframework.boot:spring-boot-starter-jdbc:$springBootVersion" - compile 'org.postgresql:postgresql:42.1.1' + compile 'org.postgresql:postgresql:42.2.2' - compile 'org.springframework.cloud:spring-cloud-starter-hystrix:1.3.0.RELEASE' + compile 'org.springframework.cloud:spring-cloud-starter-hystrix:1.3.6.RELEASE' // misc - compile 'org.apache.httpcomponents:httpclient:4.5.3' + compile 'org.apache.httpcomponents:httpclient:4.5.5' compile('org.zalando.stups:stups-spring-oauth2-server:1.0.19') { exclude module: "httpclient" } @@ -166,7 +168,7 @@ dependencies { compile "org.apache.zookeeper:zookeeper:$zookeeperVersion" // json - compile('com.github.everit-org.json-schema:org.everit.json.schema:6cb8ae440b0bc34030d7bea85ac609d980d741fb') { + compile('com.github.everit-org.json-schema:org.everit.json.schema:1.8.0') { exclude module: "json" } compile('com.fasterxml.jackson.datatype:jackson-datatype-json-org:2.8.8') { From 00f1d89fe9c24b63a18fe702f608b4efd2c26025 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Wed, 30 May 2018 10:09:19 +0200 Subject: [PATCH 002/176] Upgrade more libraries - dropwizard to 3.1.3 - stups-spring-oauth2-server to 1.0.21 - guava to 25.1-jre - commons-lang3 to 3.7 - jackson libraries to 2.8.11 (match spring boot) - org.json to 20180130 - json-path to 2.4.0 - remove rs-api dependency --- build.gradle | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/build.gradle b/build.gradle index 41c79de694..1b391680a1 100644 --- a/build.gradle +++ b/build.gradle @@ -105,7 +105,7 @@ findbugs { dependencies { ext { - dropwizardVersion = '3.1.2' + dropwizardVersion = '3.1.3' curatorVersion = '4.0.1' zookeeperVersion = '3.4.10' } @@ -140,20 +140,19 @@ dependencies { // misc compile 'org.apache.httpcomponents:httpclient:4.5.5' - compile('org.zalando.stups:stups-spring-oauth2-server:1.0.19') { + compile('org.zalando.stups:stups-spring-oauth2-server:1.0.21') { exclude module: "httpclient" } compile 'org.zalando:jackson-datatype-problem:0.5.0' compile 'org.zalando:problem:0.5.0' compile 'org.zalando:problem-spring-web:0.5.0' - compile 'com.google.guava:guava:19.0' - compile 'javax.ws.rs:javax.ws.rs-api:2.0.1' + compile 'com.google.guava:guava:25.1-jre' compile 'org.slf4j:slf4j-log4j12:1.7.25' compile "io.dropwizard.metrics:metrics-core:$dropwizardVersion" compile "com.ryantenney.metrics:metrics-spring:$dropwizardVersion" compile "io.dropwizard.metrics:metrics-servlets:$dropwizardVersion" compile "io.dropwizard.metrics:metrics-jvm:$dropwizardVersion" - compile 'org.apache.commons:commons-lang3:3.5' + compile 'org.apache.commons:commons-lang3:3.7' compile 'org.zalando:nakadi-plugin-api:2.0.0' compile 'org.echocat.jomon:runtime:1.6.3' @@ -171,14 +170,14 @@ dependencies { compile('com.github.everit-org.json-schema:org.everit.json.schema:1.8.0') { exclude module: "json" } - compile('com.fasterxml.jackson.datatype:jackson-datatype-json-org:2.8.8') { + compile('com.fasterxml.jackson.datatype:jackson-datatype-json-org:2.8.11') { exclude module: "json" } - compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.8.8' - compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.8.8' + compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.8.11' + compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.8.11' compile 'org.zalando:twintip-spring-web:1.1.0' compile 'com.grack:nanojson:1.2' - compile 'org.json:json:20171018' + compile 'org.json:json:20180130' // tests testCompile 'org.hamcrest:hamcrest-all:1.3' @@ -195,7 +194,7 @@ dependencies { exclude module: "hamcrest-core" exclude module: "hamcrest-library" } - testCompile 'com.jayway.jsonpath:json-path:2.2.0' + testCompile 'com.jayway.jsonpath:json-path:2.4.0' testRuntime 'org.pegdown:pegdown:1.6.0' } // end::dependencies[] From da745a096d92d6dad32d4efd9d49230fdc1ceb7d Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Thu, 31 May 2018 07:59:06 +0200 Subject: [PATCH 003/176] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0599387d36..8ec84a694e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Fixed +- Upgraded dependencies + ## [2.7.2] - 2018-05-30 ### Changed From 1a346478980c0c0f7bfb98bd949abdab354b9b14 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Fri, 1 Jun 2018 13:11:02 +0200 Subject: [PATCH 004/176] Upgrade gradle --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f9147d507d..2fb4764f65 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Jun 20 11:33:10 CEST 2017 +#Fri Jun 01 13:06:32 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip From 39643bda9532e538494a3fbfebdc6e31a3208002 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Fri, 1 Jun 2018 13:24:15 +0200 Subject: [PATCH 005/176] use gradle distribution with sources --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2fb4764f65..4a4216cc05 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Jun 01 13:06:32 CEST 2018 +#Fri Jun 01 13:23:16 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-all.zip From beb731dc099a8d1e285c5f20b1b4b8b36920f096 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 4 Jun 2018 11:29:36 +0200 Subject: [PATCH 006/176] Same version for all jackson packages --- build.gradle | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 1b391680a1..f6b802dd26 100644 --- a/build.gradle +++ b/build.gradle @@ -4,6 +4,7 @@ buildscript { ext { springBootVersion = '1.5.13.RELEASE' springFrameworkVersion = '4.3.17.RELEASE' + jacksonVersion = '2.8.11' } repositories { @@ -170,11 +171,13 @@ dependencies { compile('com.github.everit-org.json-schema:org.everit.json.schema:1.8.0') { exclude module: "json" } - compile('com.fasterxml.jackson.datatype:jackson-datatype-json-org:2.8.11') { + compile("com.fasterxml.jackson.datatype:jackson-datatype-json-org:$jacksonVersion") { exclude module: "json" } - compile 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.8.11' - compile 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.8.11' + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jacksonVersion" + compile "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion" + compile "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" + compile "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" compile 'org.zalando:twintip-spring-web:1.1.0' compile 'com.grack:nanojson:1.2' compile 'org.json:json:20180130' From 5c9dcd99e332172fa0c39279efc9779ea030932e Mon Sep 17 00:00:00 2001 From: Ricardo de Cillo Date: Tue, 5 Jun 2018 17:50:24 +0200 Subject: [PATCH 007/176] Subscription authorization Since the introduction of Event Type Authorization, it was planned that Subscriptions would also be authorized. Even though data is already protected through Event Type Authorization, users can still accidentally commit offsets to subscriptions owned by other users, eventually causing applications to not process all the data. Subscription could also be accidentally deleted or have it's slots assigned to some other application. With this feature we address all of the problems above. This is just the API definition. --- docs/_data/nakadi-event-bus-api.yaml | 51 +++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/docs/_data/nakadi-event-bus-api.yaml b/docs/_data/nakadi-event-bus-api.yaml index a7d02cdfbb..e937dd4544 100644 --- a/docs/_data/nakadi-event-bus-api.yaml +++ b/docs/_data/nakadi-event-bus-api.yaml @@ -1109,6 +1109,10 @@ paths: $ref: '#/definitions/CursorCommitResult' required: - items + '403': + description: Access forbidden + schema: + $ref: '#/definitions/Problem' '404': description: Subscription not found schema: @@ -1212,6 +1216,10 @@ paths: description: Bad Request schema: $ref: '#/definitions/Problem' + '403': + description: Access forbidden + schema: + $ref: '#/definitions/Problem' '404': description: Subscription not found. schema: @@ -1226,10 +1234,6 @@ paths: - Request to reset subscription cursors is still in progress. schema: $ref: '#/definitions/Problem' - '403': - description: Access is forbidden for the client or event type - schema: - $ref: '#/definitions/Problem' post: tags: @@ -1355,6 +1359,10 @@ paths: description: Bad Request schema: $ref: '#/definitions/Problem' + '403': + description: Access forbidden + schema: + $ref: '#/definitions/Problem' '404': description: Subscription not found. schema: @@ -1371,10 +1379,6 @@ paths: - It is requested to read from a partition that is already assigned to another stream by direct request. schema: $ref: '#/definitions/Problem' - '403': - description: Access is forbidden for the client or event type - schema: - $ref: '#/definitions/Problem' '422': description: At least one of specified partitions doesn't belong to this subscription. schema: @@ -2344,10 +2348,41 @@ definitions: status. items: $ref: '#/definitions/SubscriptionEventTypeStatus' + authorization: + $ref: '#/definitions/SubscriptionAuthorization' required: - owning_application - event_types + SubscriptionAuthorization: + type: object + description: | + Authorization section of a Subscription. This section defines two access control lists: one for consuming + events and committing cursors ('readers'), and one for administering a subscription ('admins'). + Regardless of the values of the authorization properties, administrator accounts will always be authorized. + properties: + admins: + type: array + description: | + An array of subject attributes that are required for updating the subscription. Any one of the attributes + defined in this array is sufficient to be authorized. The wildcard item takes precedence over all others, + i.e. if it is present, all users are authorized. + items: + $ref: '#/definitions/AuthorizationAttribute' + minItems: 1 + readers: + type: array + description: | + An array of subject attributes that are required for reading events and committing cursors to this + subscription. Any one of the attributes defined in this array is sufficient to be authorized. The wildcard + item takes precedence over all others, i.e., if it is present, all users are authorized. + items: + $ref: '#/definitions/AuthorizationAttribute' + minItems: 1 + required: + - admins + - readers + EventType: description: An event type defines the schema and its runtime properties. properties: From c02a8c84ecd2c5e70528c9e6ed204b22e69996ba Mon Sep 17 00:00:00 2001 From: Ricardo de Cillo Date: Thu, 7 Jun 2018 15:04:42 +0200 Subject: [PATCH 008/176] Add subscription update endpoint --- docs/_data/nakadi-event-bus-api.yaml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/_data/nakadi-event-bus-api.yaml b/docs/_data/nakadi-event-bus-api.yaml index e937dd4544..4ed69205b3 100644 --- a/docs/_data/nakadi-event-bus-api.yaml +++ b/docs/_data/nakadi-event-bus-api.yaml @@ -1019,6 +1019,29 @@ paths: responses: '204': description: Subscription was deleted + '403': + description: Access forbidden + schema: + $ref: '#/definitions/Problem' + '404': + description: Subscription not found + schema: + $ref: '#/definitions/Problem' + put: + tags: + - subscription-api + security: + - oauth2: ['nakadi.event_stream.read'] + description: Updates a subscription. + parameters: + - $ref: '#/parameters/SubscriptionId' + responses: + '204': + description: Subscription was updated + '403': + description: Access forbidden + schema: + $ref: '#/definitions/Problem' '404': description: Subscription not found schema: @@ -1158,6 +1181,10 @@ paths: responses: '204': description: Offsets were reset + '403': + description: Access forbidden + schema: + $ref: '#/definitions/Problem' '404': description: Subscription not found schema: From 34a1b6f67b0f2c7dd173dd58a95f6b32974fa3a8 Mon Sep 17 00:00:00 2001 From: Ricardo de Cillo Date: Thu, 7 Jun 2018 16:00:27 +0200 Subject: [PATCH 009/176] Clarify usage of PUT endpoint --- docs/_data/nakadi-event-bus-api.yaml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/_data/nakadi-event-bus-api.yaml b/docs/_data/nakadi-event-bus-api.yaml index 4ed69205b3..7c146e0a35 100644 --- a/docs/_data/nakadi-event-bus-api.yaml +++ b/docs/_data/nakadi-event-bus-api.yaml @@ -1032,9 +1032,21 @@ paths: - subscription-api security: - oauth2: ['nakadi.event_stream.read'] - description: Updates a subscription. + description: | + This endpoint only allows to update the authorization section of a subscription. All other properties are + immutable. This operation is restricted to subjects with administrative role. parameters: - - $ref: '#/parameters/SubscriptionId' + - name: subscription + in: body + description: Subscription with modified authorization section. + schema: + $ref: '#/definitions/Subscription' + required: true + - name: subscription_id + in: path + type: string + description: Id of subscription + required: true responses: '204': description: Subscription was updated From be46623602374417fc87ae9f3bed4b33fb6e00ef Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 11 Jun 2018 14:10:32 +0200 Subject: [PATCH 010/176] set jackson-datatype-jdk8 --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 63fa6f2044..b90cd5b867 100644 --- a/build.gradle +++ b/build.gradle @@ -178,6 +178,7 @@ dependencies { compile "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion" compile "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" compile "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" + compile "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:$jacksonVersion" compile 'org.zalando:twintip-spring-web:1.1.0' compile 'org.json:json:20180130' From bf8880bd8b221203c92c7db0c324bfc43e3aa00c Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Tue, 12 Jun 2018 15:08:06 +0200 Subject: [PATCH 011/176] upgrade spring-cloud-starter-hystrix set versions of jackson-databind and jackson-annotions identical to spring boot dependencies --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index b90cd5b867..fcd508d343 100644 --- a/build.gradle +++ b/build.gradle @@ -137,7 +137,7 @@ dependencies { compile "org.springframework.boot:spring-boot-starter-jdbc:$springBootVersion" compile 'org.postgresql:postgresql:42.2.2' - compile 'org.springframework.cloud:spring-cloud-starter-hystrix:1.3.6.RELEASE' + compile 'org.springframework.cloud:spring-cloud-starter-hystrix:1.4.4.RELEASE' // misc compile 'org.apache.httpcomponents:httpclient:4.5.5' @@ -176,8 +176,8 @@ dependencies { } compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jacksonVersion" compile "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion" - compile "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" - compile "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" + compile "com.fasterxml.jackson.core:jackson-databind:2.8.11.1" + compile "com.fasterxml.jackson.core:jackson-annotations:2.8.0" compile "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:$jacksonVersion" compile 'org.zalando:twintip-spring-web:1.1.0' compile 'org.json:json:20180130' From 71771d2d2d3949c8d4ab2de36d0089df1e55faa0 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Thu, 14 Jun 2018 18:24:36 +0200 Subject: [PATCH 012/176] exclude old jackson dependencies --- build.gradle | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build.gradle b/build.gradle index fcd508d343..070e76ae79 100644 --- a/build.gradle +++ b/build.gradle @@ -97,6 +97,11 @@ configurations { dbMigrationCompile.extendsFrom compile dbMigrationRuntime.extendsFrom runtime pgsql + + implementation { + exclude group: 'org.codehaus.jackson', module: 'jackson-mapper-asl' + exclude group: 'org.codehaus.jackson', module: 'jackson-core-asl' + } } findbugs { From 5bbe9cddf614c5af03713cb34b5d884aaf2227aa Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 18 Jun 2018 14:29:01 +0200 Subject: [PATCH 013/176] Upgrade spring boot and spring framework versions --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 070e76ae79..eb9f165c32 100644 --- a/build.gradle +++ b/build.gradle @@ -2,8 +2,8 @@ import java.util.concurrent.TimeUnit buildscript { ext { - springBootVersion = '1.5.13.RELEASE' - springFrameworkVersion = '4.3.17.RELEASE' + springBootVersion = '1.5.14.RELEASE' + springFrameworkVersion = '4.3.18.RELEASE' jacksonVersion = '2.8.11' } @@ -29,7 +29,7 @@ plugins { id 'findbugs' id 'checkstyle' id 'project-report' - id 'org.springframework.boot' version "1.5.13.RELEASE" + id 'org.springframework.boot' version "1.5.14.RELEASE" } group 'org.zalando' From c20100cd6024f2d56abce75cfcc7e6037c63ac95 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 18 Jun 2018 15:44:48 +0200 Subject: [PATCH 014/176] Upgrade jackson version --- build.gradle | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index eb9f165c32..be30fd5a2c 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ buildscript { ext { springBootVersion = '1.5.14.RELEASE' springFrameworkVersion = '4.3.18.RELEASE' - jacksonVersion = '2.8.11' + jacksonVersion = '2.9.6' } repositories { @@ -179,11 +179,13 @@ dependencies { compile("com.fasterxml.jackson.datatype:jackson-datatype-json-org:$jacksonVersion") { exclude module: "json" } - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jacksonVersion" + compile "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" + compile "com.fasterxml.jackson.core:jackson-core:$jacksonVersion" + compile "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" compile "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion" - compile "com.fasterxml.jackson.core:jackson-databind:2.8.11.1" - compile "com.fasterxml.jackson.core:jackson-annotations:2.8.0" compile "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:$jacksonVersion" + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jacksonVersion" + compile "com.fasterxml.jackson.module:jackson-module-afterburner:$jacksonVersion" compile 'org.zalando:twintip-spring-web:1.1.0' compile 'org.json:json:20180130' From f05f246b6f367496f964607c49f6724add819e23 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 18 Jun 2018 17:56:48 +0200 Subject: [PATCH 015/176] Upgrade spring-security-oauth2 version --- build.gradle | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index be30fd5a2c..02566c7c0d 100644 --- a/build.gradle +++ b/build.gradle @@ -97,11 +97,6 @@ configurations { dbMigrationCompile.extendsFrom compile dbMigrationRuntime.extendsFrom runtime pgsql - - implementation { - exclude group: 'org.codehaus.jackson', module: 'jackson-mapper-asl' - exclude group: 'org.codehaus.jackson', module: 'jackson-core-asl' - } } findbugs { @@ -129,7 +124,7 @@ dependencies { compile "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion" // oauth - compile 'org.springframework.security.oauth:spring-security-oauth2:2.1.0.RELEASE' + compile 'org.springframework.security.oauth:spring-security-oauth2:2.3.3.RELEASE' compile('org.springframework.boot:spring-boot-starter-security') { exclude module: "logback-classic" } From 9aba22a5a5cb0521b425ed130a94ffe4eeb3db3d Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Tue, 19 Jun 2018 15:51:55 +0200 Subject: [PATCH 016/176] Exclude spring dependencies from spring-security-oauth2 --- build.gradle | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 02566c7c0d..1b051caa2c 100644 --- a/build.gradle +++ b/build.gradle @@ -124,7 +124,11 @@ dependencies { compile "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion" // oauth - compile 'org.springframework.security.oauth:spring-security-oauth2:2.3.3.RELEASE' + compile ('org.springframework.security.oauth:spring-security-oauth2:2.3.3.RELEASE') { + exclude module: 'spring-beans' + exclude module: 'spring-core' + exclude module: 'spring-context' + } compile('org.springframework.boot:spring-boot-starter-security') { exclude module: "logback-classic" } From 09c72ceb3d014e6c5290110f19d1c93e12b299c6 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Fri, 22 Jun 2018 12:16:57 +0200 Subject: [PATCH 017/176] Upgrade gradle to 4.8.1 --- gradle/wrapper/gradle-wrapper.jar | Bin 53324 -> 54413 bytes gradle/wrapper/gradle-wrapper.properties | 3 +-- gradlew | 26 +++++++++++++++-------- gradlew.bat | 6 ------ 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 3baa851b28c65f87dd36a6748e1a85cf360c1301..91ca28c8b802289c3a438766657a5e98f20eff03 100644 GIT binary patch delta 38633 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
FthV|n}K8`HchILSWFRVJ(jmE6!=!>lMdWy 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4a4216cc05..debd024022 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Fri Jun 01 13:23:16 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.7-all.zip diff --git a/gradlew b/gradlew index 27309d9231..cccdd3d517 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh ############################################################################## ## @@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS="" # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" -warn ( ) { +warn () { echo "$*" } -die ( ) { +die () { echo echo "$*" echo @@ -154,11 +154,19 @@ if $cygwin ; then esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " } -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" +APP_ARGS=$(save "$@") -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index f6d5974e72..e95643d6a2 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -49,7 +49,6 @@ goto fail @rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args :win9xME_args @rem Slurp the command line arguments. @@ -60,11 +59,6 @@ set _SKIP=2 if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ :execute @rem Setup the command line From 85252fd5d29047a43c7a1a98e63de9da5cf6d919 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Fri, 22 Jun 2018 16:51:33 +0200 Subject: [PATCH 018/176] Use spring dependency management plugin --- build.gradle | 56 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/build.gradle b/build.gradle index 1b051caa2c..47a9b6d2c8 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ buildscript { } dependencies { - classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion" + classpath "org.springframework.boot:spring-boot-gradle-plugin" classpath 'org.yaml:snakeyaml:1.21' } } @@ -32,6 +32,8 @@ plugins { id 'org.springframework.boot' version "1.5.14.RELEASE" } +apply plugin: 'io.spring.dependency-management' + group 'org.zalando' sourceCompatibility = 1.8 targetCompatibility = 1.8 @@ -110,21 +112,27 @@ dependencies { curatorVersion = '4.0.1' zookeeperVersion = '3.4.10' } + // Override spring-boot BOM versions + ext['json.version'] = '20180130' + ext['json-path'] = '2.4.0' + ext['jsonassert'] = '1.5.0' + ext['postgresql.version'] = '42.2.2' + ext['spring-security-oauth2.version'] = '2.3.3.RELEASE' // spring - compile("org.springframework.boot:spring-boot-starter-web:$springBootVersion") { + compile("org.springframework.boot:spring-boot-starter-web") { exclude module: 'logback-classic' exclude module: 'log4j-over-slf4j' exclude module: 'spring-boot-starter-tomcat' } - compile "org.springframework:spring-context:$springFrameworkVersion" - compile "org.springframework:spring-web:$springFrameworkVersion" - compile "org.springframework:spring-webmvc:$springFrameworkVersion" - compile "org.springframework.boot:spring-boot-test:$springBootVersion" - compile "org.springframework.boot:spring-boot-starter-jetty:$springBootVersion" + compile "org.springframework:spring-context" + compile "org.springframework:spring-web" + compile "org.springframework:spring-webmvc" + compile "org.springframework.boot:spring-boot-test" + compile "org.springframework.boot:spring-boot-starter-jetty" // oauth - compile ('org.springframework.security.oauth:spring-security-oauth2:2.3.3.RELEASE') { + compile ('org.springframework.security.oauth:spring-security-oauth2') { exclude module: 'spring-beans' exclude module: 'spring-core' exclude module: 'spring-context' @@ -134,17 +142,17 @@ dependencies { } // actuator - compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion" + compile "org.springframework.boot:spring-boot-starter-actuator" compile 'org.zalando.zmon:zmon-actuator:0.9.8' // storage - compile "org.springframework.boot:spring-boot-starter-jdbc:$springBootVersion" - compile 'org.postgresql:postgresql:42.2.2' + compile "org.springframework.boot:spring-boot-starter-jdbc" + compile 'org.postgresql:postgresql' compile 'org.springframework.cloud:spring-cloud-starter-hystrix:1.4.4.RELEASE' // misc - compile 'org.apache.httpcomponents:httpclient:4.5.5' + compile 'org.apache.httpcomponents:httpclient' compile('org.zalando.stups:stups-spring-oauth2-server:1.0.21') { exclude module: "httpclient" } @@ -152,7 +160,7 @@ dependencies { compile 'org.zalando:problem:0.5.0' compile 'org.zalando:problem-spring-web:0.5.0' compile 'com.google.guava:guava:25.1-jre' - compile 'org.slf4j:slf4j-log4j12:1.7.25' + compile 'org.slf4j:slf4j-log4j12' compile "io.dropwizard.metrics:metrics-core:$dropwizardVersion" compile "com.ryantenney.metrics:metrics-spring:$dropwizardVersion" compile "io.dropwizard.metrics:metrics-servlets:$dropwizardVersion" @@ -175,16 +183,16 @@ dependencies { compile('com.github.everit-org.json-schema:org.everit.json.schema:1.8.0') { exclude module: "json" } - compile("com.fasterxml.jackson.datatype:jackson-datatype-json-org:$jacksonVersion") { + compile("com.fasterxml.jackson.datatype:jackson-datatype-json-org") { exclude module: "json" } - compile "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion" - compile "com.fasterxml.jackson.core:jackson-core:$jacksonVersion" - compile "com.fasterxml.jackson.core:jackson-databind:$jacksonVersion" - compile "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:$jacksonVersion" - compile "com.fasterxml.jackson.datatype:jackson-datatype-jdk8:$jacksonVersion" - compile "com.fasterxml.jackson.datatype:jackson-datatype-joda:$jacksonVersion" - compile "com.fasterxml.jackson.module:jackson-module-afterburner:$jacksonVersion" + compile "com.fasterxml.jackson.core:jackson-annotations" + compile "com.fasterxml.jackson.core:jackson-core" + compile "com.fasterxml.jackson.core:jackson-databind" + compile "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml" + compile "com.fasterxml.jackson.datatype:jackson-datatype-jdk8" + compile "com.fasterxml.jackson.datatype:jackson-datatype-joda" + compile "com.fasterxml.jackson.module:jackson-module-afterburner" compile 'org.zalando:twintip-spring-web:1.1.0' compile 'org.json:json:20180130' @@ -193,17 +201,17 @@ dependencies { testCompile('junit:junit:4.12') { exclude module: "hamcrest-core" } - testCompile "org.springframework:spring-test:$springFrameworkVersion" + testCompile "org.springframework:spring-test" testCompile 'org.springframework.boot:spring-boot-test' testCompile 'org.springframework.boot:spring-boot-starter-test' - testCompile 'org.skyscreamer:jsonassert:1.5.0' + testCompile 'org.skyscreamer:jsonassert' testCompile 'uk.co.datumedge:hamcrest-json:0.2' testCompile 'org.mockito:mockito-all:1.10.19' testCompile('com.jayway.restassured:rest-assured:2.9.0') { exclude module: "hamcrest-core" exclude module: "hamcrest-library" } - testCompile 'com.jayway.jsonpath:json-path:2.4.0' + testCompile 'com.jayway.jsonpath:json-path' testRuntime 'org.pegdown:pegdown:1.6.0' } // end::dependencies[] From 10d55320de6cefa69456be8412c60fb7a7da7497 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Thu, 28 Jun 2018 15:36:04 +0200 Subject: [PATCH 019/176] ARUHA-1681 Base implementation without tests and exceptions mapping --- .../nakadi/webservice/CursorsServiceAT.java | 2 +- .../PostSubscriptionController.java | 30 ++++++- .../zalando/nakadi/domain/AdminResource.java | 17 +--- .../nakadi/domain/AllDataAccessResource.java | 17 +--- .../nakadi/domain/EventTypeResource.java | 11 +-- .../nakadi/domain/ResourceAuthorization.java | 49 ++++++----- .../domain/SubscriptionAuthorization.java | 81 +++++++++++++++++++ .../nakadi/domain/SubscriptionBase.java | 17 ++++ .../nakadi/domain/SubscriptionResource.java | 34 ++++++++ .../domain/ValidatableAuthorization.java | 16 ++++ .../db/SubscriptionDbRepository.java | 17 +++- .../service/AuthorizationValidator.java | 81 ++++++++++++------- .../nakadi/service/CursorsService.java | 8 +- .../nakadi/service/EventTypeService.java | 2 +- .../subscription/SubscriptionService.java | 24 +++++- .../SubscriptionValidationService.java | 30 ++++++- .../SubscriptionControllerTest.java | 2 +- .../service/SubscriptionServiceTest.java | 6 +- .../SubscriptionValidationServiceTest.java | 2 +- 19 files changed, 344 insertions(+), 102 deletions(-) create mode 100644 src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java create mode 100644 src/main/java/org/zalando/nakadi/domain/SubscriptionResource.java create mode 100644 src/main/java/org/zalando/nakadi/domain/ValidatableAuthorization.java diff --git a/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java b/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java index 724a83c79f..e5a5fe791a 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java +++ b/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java @@ -108,7 +108,7 @@ public void before() throws Exception { uuidGenerator = mock(UUIDGenerator.class); when(uuidGenerator.isUUID(any())).thenReturn(true); cursorsService = new CursorsService(subscriptionRepo, null, - mock(NakadiSettings.class), zkSubscriptionFactory, cursorConverter, uuidGenerator, null); + mock(NakadiSettings.class), zkSubscriptionFactory, cursorConverter, uuidGenerator, null, authorizationValidator); // Register cursors in converter registerNakadiCursor(NakadiCursor.of(buildTimeline(etName, topic, CREATED_AT), P1, NEW_OFFSET)); diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index cf9ff44ccb..b544a6ce7c 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -7,6 +7,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.validation.Errors; import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -15,6 +16,7 @@ import org.springframework.web.util.UriComponents; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; +import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.DuplicatedSubscriptionException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; @@ -25,9 +27,8 @@ import org.zalando.nakadi.exceptions.runtime.WrongInitialCursorsException; import org.zalando.nakadi.plugin.api.ApplicationService; import org.zalando.nakadi.problem.ValidationProblem; -import org.zalando.nakadi.security.Client; -import org.zalando.nakadi.service.subscription.SubscriptionService; import org.zalando.nakadi.service.FeatureToggleService; +import org.zalando.nakadi.service.subscription.SubscriptionService; import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; import org.zalando.problem.spring.web.advice.Responses; @@ -63,8 +64,7 @@ public PostSubscriptionController(final FeatureToggleService featureToggleServic @RequestMapping(value = "/subscriptions", method = RequestMethod.POST) public ResponseEntity createOrGetSubscription(@Valid @RequestBody final SubscriptionBase subscriptionBase, final Errors errors, - final NativeWebRequest request, - final Client client) { + final NativeWebRequest request) { if (errors.hasErrors()) { return Responses.create(new ValidationProblem(errors), request); } @@ -91,6 +91,28 @@ public ResponseEntity createOrGetSubscription(@Valid @RequestBody final Subsc } } + @RequestMapping(value = "/subscriptions/{subscription_id}", method = RequestMethod.PUT) + public ResponseEntity updateSubscription( + @PathVariable("subscription_id") final String subscriptionId, + @Valid @RequestBody final SubscriptionBase subscription, + final Errors errors, + final NativeWebRequest request) { + if (errors.hasErrors()) { + return Responses.create(new ValidationProblem(errors), request); + } + if (featureToggleService.isFeatureEnabled(CHECK_OWNING_APPLICATION) + && !applicationService.exists(subscription.getOwningApplication())) { + return Responses.create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, + "owning_application doesn't exist"), request); + } + try { + subscriptionService.updateSubscription(subscriptionId, subscription); + return ResponseEntity.noContent().build(); + } catch (final NoSuchSubscriptionException ex) { + return Responses.create(ex.asProblem(), request); + } + } + private ResponseEntity ok(final Subscription existingSubscription) { final UriComponents location = subscriptionService.getSubscriptionUri(existingSubscription); return ResponseEntity.status(OK).location(location.toUri()).body(existingSubscription); diff --git a/src/main/java/org/zalando/nakadi/domain/AdminResource.java b/src/main/java/org/zalando/nakadi/domain/AdminResource.java index 913defbc56..16dc7a45fa 100644 --- a/src/main/java/org/zalando/nakadi/domain/AdminResource.java +++ b/src/main/java/org/zalando/nakadi/domain/AdminResource.java @@ -32,25 +32,12 @@ public String getType() { @Override public Optional> getAttributesForOperation( final AuthorizationService.Operation operation) { - switch (operation) { - case READ: - return Optional.of(resourceAuthorization.getReaders()); - case WRITE: - return Optional.of(resourceAuthorization.getWriters()); - case ADMIN: - return Optional.of(resourceAuthorization.getAdmins()); - default: - throw new IllegalArgumentException("Operation " + operation + " is not supported"); - } - } - - public List getPermissionsList() { - return resourceAuthorization.toPermissionsList(name); + return resourceAuthorization.getAttributesForOperation(operation); } @Override public String toString() { - return "AuthorizedResource{" + ADMIN_RESOURCE +"='" + name + "'}"; + return "AuthorizedResource{" + ADMIN_RESOURCE + "='" + name + "'}"; } } diff --git a/src/main/java/org/zalando/nakadi/domain/AllDataAccessResource.java b/src/main/java/org/zalando/nakadi/domain/AllDataAccessResource.java index 4c1f2763b4..a76569da65 100644 --- a/src/main/java/org/zalando/nakadi/domain/AllDataAccessResource.java +++ b/src/main/java/org/zalando/nakadi/domain/AllDataAccessResource.java @@ -31,24 +31,11 @@ public String getType() { @Override public Optional> getAttributesForOperation( final AuthorizationService.Operation operation) { - switch (operation) { - case READ: - return Optional.of(resourceAuthorization.getReaders()); - case WRITE: - return Optional.of(resourceAuthorization.getWriters()); - case ADMIN: - return Optional.of(resourceAuthorization.getAdmins()); - default: - throw new IllegalArgumentException("Operation " + operation + " is not supported"); - } - } - - public List getPermissionsList() { - return resourceAuthorization.toPermissionsList(name); + return resourceAuthorization.getAttributesForOperation(operation); } @Override public String toString() { - return "AuthorizedResource{" + ALL_DATA_ACCESS_RESOURCE +"='" + name + "'}"; + return "AuthorizedResource{" + ALL_DATA_ACCESS_RESOURCE + "='" + name + "'}"; } } diff --git a/src/main/java/org/zalando/nakadi/domain/EventTypeResource.java b/src/main/java/org/zalando/nakadi/domain/EventTypeResource.java index e16c095121..c1e4c7a931 100644 --- a/src/main/java/org/zalando/nakadi/domain/EventTypeResource.java +++ b/src/main/java/org/zalando/nakadi/domain/EventTypeResource.java @@ -30,16 +30,7 @@ public String getType() { @Override public Optional> getAttributesForOperation( final AuthorizationService.Operation operation) { - switch (operation) { - case READ: - return Optional.of(etAuthorization.getReaders()); - case WRITE: - return Optional.of(etAuthorization.getWriters()); - case ADMIN: - return Optional.of(etAuthorization.getAdmins()); - default: - throw new IllegalArgumentException("Operation " + operation + " is not supported"); - } + return etAuthorization.getAttributesForOperation(operation); } @Override diff --git a/src/main/java/org/zalando/nakadi/domain/ResourceAuthorization.java b/src/main/java/org/zalando/nakadi/domain/ResourceAuthorization.java index 5db4425f31..7e3c817391 100644 --- a/src/main/java/org/zalando/nakadi/domain/ResourceAuthorization.java +++ b/src/main/java/org/zalando/nakadi/domain/ResourceAuthorization.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import org.zalando.nakadi.exceptions.runtime.UnknownOperationException; +import com.google.common.collect.ImmutableMap; import org.zalando.nakadi.plugin.api.authz.AuthorizationAttribute; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; @@ -12,11 +12,13 @@ import javax.validation.constraints.Size; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; @Immutable -public class ResourceAuthorization { +public class ResourceAuthorization implements ValidatableAuthorization { @NotNull @Valid @@ -58,20 +60,6 @@ public List getWriters() { return writers; } - public List getList(final AuthorizationService.Operation operation) - throws UnknownOperationException { - switch (operation) { - case ADMIN: - return admins; - case READ: - return readers; - case WRITE: - return writers; - default: - throw new UnknownOperationException("Unknown operation: " + operation.toString()); - } - } - public List toPermissionsList(final String resource) { final List permissions = admins.stream() .map(p -> new Permission(resource, AuthorizationService.Operation.ADMIN, p)) @@ -88,20 +76,43 @@ public List toPermissionsList(final String resource) { public static ResourceAuthorization fromPermissionsList(final List permissions) { final List admins = permissions.stream() .filter(p -> p.getOperation().equals(AuthorizationService.Operation.ADMIN)) - .map(p -> p.getAuthorizationAttribute()) + .map(Permission::getAuthorizationAttribute) .collect(Collectors.toList()); final List readers = permissions.stream() .filter(p -> p.getOperation().equals(AuthorizationService.Operation.READ)) - .map(p -> p.getAuthorizationAttribute()) + .map(Permission::getAuthorizationAttribute) .collect(Collectors.toList()); final List writers = permissions.stream() .filter(p -> p.getOperation().equals(AuthorizationService.Operation.WRITE)) - .map(p -> p.getAuthorizationAttribute()) + .map(Permission::getAuthorizationAttribute) .collect(Collectors.toList()); return new ResourceAuthorization(admins, readers, writers); } + public Optional> getAttributesForOperation( + final AuthorizationService.Operation operation) { + switch (operation) { + case READ: + return Optional.of(getReaders()); + case WRITE: + return Optional.of(getWriters()); + case ADMIN: + return Optional.of(getAdmins()); + default: + throw new IllegalArgumentException("Operation " + operation + " is not supported"); + } + } + + + @Override + public Map> asMapValue() { + return ImmutableMap.of( + "admins", getAdmins(), + "readers", getReaders(), + "writers", getWriters()); + } + @Override public boolean equals(final Object o) { if (this == o) { diff --git a/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java b/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java new file mode 100644 index 0000000000..c3a4cf5aab --- /dev/null +++ b/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java @@ -0,0 +1,81 @@ +package org.zalando.nakadi.domain; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.google.common.collect.ImmutableMap; +import org.zalando.nakadi.plugin.api.authz.AuthorizationAttribute; +import org.zalando.nakadi.plugin.api.authz.AuthorizationService; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; + +public class SubscriptionAuthorization implements ValidatableAuthorization { + @NotNull + @Valid + @Size(min = 1, message = "must contain at least one attribute") + @JsonDeserialize(contentAs = ResourceAuthorizationAttribute.class) + private final List admins; + @NotNull + @Valid + @Size(min = 1, message = "must contain at least one attribute") + @JsonDeserialize(contentAs = ResourceAuthorizationAttribute.class) + private final List readers; + + public SubscriptionAuthorization(@JsonProperty("admins") final List admins, + @JsonProperty("readers") final List readers) { + // actually these three properties should never be null but the validation framework first creates an object + // and then uses getters to check if values are null or not, so we need to do this check to avoid exception + this.admins = admins == null ? null : Collections.unmodifiableList(admins); + this.readers = readers == null ? null : Collections.unmodifiableList(readers); + } + + public List getAdmins() { + return admins; + } + + public List getReaders() { + return readers; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SubscriptionAuthorization that = (SubscriptionAuthorization) o; + return Objects.equals(admins, that.admins) && + Objects.equals(readers, that.readers); + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public Map> asMapValue() { + return ImmutableMap.of( + "admins", getAdmins(), + "readers", getReaders() + ); + } + + @Override + public Optional> getAttributesForOperation( + final AuthorizationService.Operation operation) throws IllegalArgumentException { + switch (operation) { + case READ: + return Optional.of(getReaders()); + case ADMIN: + return Optional.of(getAdmins()); + default: + throw new IllegalArgumentException("Operation " + operation + " is not supported"); + } + + } +} diff --git a/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java b/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java index 4a33a2ae42..6f728954b4 100644 --- a/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java +++ b/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java @@ -40,6 +40,9 @@ public enum InitialPosition { @Valid private List initialCursors = ImmutableList.of(); + @Nullable + private SubscriptionAuthorization authorization; + public SubscriptionBase() { } @@ -49,6 +52,15 @@ public SubscriptionBase(final SubscriptionBase subscriptionBase) { this.setConsumerGroup(subscriptionBase.getConsumerGroup()); this.setReadFrom(subscriptionBase.getReadFrom()); this.setInitialCursors(subscriptionBase.getInitialCursors()); + this.setAuthorization(subscriptionBase.getAuthorization()); + } + + public SubscriptionAuthorization getAuthorization() { + return authorization; + } + + public void setAuthorization(SubscriptionAuthorization authorization) { + this.authorization = authorization; } public String getOwningApplication() { @@ -91,6 +103,10 @@ public void setInitialCursors(@Nullable final List> getAttributesForOperation( + final AuthorizationService.Operation operation) { + return subscriptionAuthorization.getAttributesForOperation(operation); + } +} diff --git a/src/main/java/org/zalando/nakadi/domain/ValidatableAuthorization.java b/src/main/java/org/zalando/nakadi/domain/ValidatableAuthorization.java new file mode 100644 index 0000000000..69e694f8b2 --- /dev/null +++ b/src/main/java/org/zalando/nakadi/domain/ValidatableAuthorization.java @@ -0,0 +1,16 @@ +package org.zalando.nakadi.domain; + +import org.zalando.nakadi.plugin.api.authz.AuthorizationAttribute; +import org.zalando.nakadi.plugin.api.authz.AuthorizationService; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface ValidatableAuthorization { + Map> asMapValue(); + + Optional> getAttributesForOperation(final AuthorizationService.Operation operation) + throws IllegalArgumentException; + +} diff --git a/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java b/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java index aa1764f0bf..e93bb0c17f 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java @@ -73,7 +73,7 @@ public Subscription createSubscription(final SubscriptionBase subscriptionBase) return subscription; } catch (final JsonProcessingException e) { - throw new InconsistentStateException("Serialization problem during persistence of event type", e); + throw new InconsistentStateException("Serialization problem during persistence of subscription", e); } catch (final DuplicateKeyException e) { throw new DuplicatedSubscriptionException("Subscription with the same key properties already exists", e); } catch (final DataAccessException e) { @@ -81,6 +81,21 @@ public Subscription createSubscription(final SubscriptionBase subscriptionBase) } } + public void updateSubscription(final Subscription subscription) { + final String keyFieldsHash = hashGenerator.generateSubscriptionKeyFieldsHash(subscription); + try { + jdbcTemplate.update( + "UPDATE zn_data.subscription set s_subscription_object=?::JSONB, s_key_fields_hash=? WHERE s_id=?", + jsonMapper.writer().writeValueAsString(subscription), + keyFieldsHash, + subscription.getId()); + } catch (final JsonProcessingException ex) { + throw new InconsistentStateException("Serialization problem during persistence of subscription", ex); + } catch (final DataAccessException e) { + throw new RepositoryProblemException("Error occurred when running database request", e); + } + } + public Subscription getSubscription(final String id) throws NoSuchSubscriptionException, ServiceTemporarilyUnavailableException { final String sql = "SELECT s_subscription_object FROM zn_data.subscription WHERE s_id = ?"; diff --git a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java index 6a970c755f..3b793a66bb 100644 --- a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java +++ b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java @@ -1,18 +1,17 @@ package org.zalando.nakadi.service; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.zalando.nakadi.domain.EventType; -import org.zalando.nakadi.domain.EventTypeBase; import org.zalando.nakadi.domain.EventTypeResource; -import org.zalando.nakadi.domain.ResourceAuthorization; -import org.zalando.nakadi.domain.SubscriptionBase; +import org.zalando.nakadi.domain.Subscription; +import org.zalando.nakadi.domain.SubscriptionResource; +import org.zalando.nakadi.domain.ValidatableAuthorization; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; +import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.plugin.api.PluginException; import org.zalando.nakadi.plugin.api.authz.AuthorizationAttribute; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; @@ -47,15 +46,12 @@ public AuthorizationValidator( this.adminService = adminService; } - public void validateAuthorization(@Nullable final ResourceAuthorization auth) throws UnableProcessException, + public void validateAuthorization(@Nullable final ValidatableAuthorization auth) throws UnableProcessException, ServiceTemporarilyUnavailableException { if (auth != null) { - final Map> allAttributes = ImmutableMap.of( - "admins", auth.getAdmins(), - "readers", auth.getReaders(), - "writers", auth.getWriters()); - checkAuthAttributesAreValid(allAttributes); - checkAuthAttributesNoDuplicates(allAttributes); + final Map> authorization = auth.asMapValue(); + checkAuthAttributesAreValid(authorization); + checkAuthAttributesNoDuplicates(authorization); } } @@ -129,13 +125,7 @@ public void authorizeEventTypeWrite(final EventType eventType) } } - public void authorizeEventTypeAdmin(final EventType eventType) - throws AccessDeniedException, ServiceTemporarilyUnavailableException { - if (eventType.getAuthorization() == null) { - return; - } - - final Resource resource = new EventTypeResource(eventType.getName(), eventType.getAuthorization()); + private void authorizeResourceAdmin(Resource resource) { try { if (!authorizationService.isAuthorized(AuthorizationService.Operation.ADMIN, resource)) { if (!adminService.isAdmin(AuthorizationService.Operation.WRITE)) { @@ -147,6 +137,14 @@ public void authorizeEventTypeAdmin(final EventType eventType) } } + public void authorizeEventTypeAdmin(final EventType eventType) + throws AccessDeniedException, ServiceTemporarilyUnavailableException { + if (eventType.getAuthorization() == null) { + return; + } + authorizeResourceAdmin(new EventTypeResource(eventType.getName(), eventType.getAuthorization())); + } + public void authorizeStreamRead(final EventType eventType) throws AccessDeniedException { if (eventType.getAuthorization() == null) { return; @@ -163,8 +161,20 @@ public void authorizeStreamRead(final EventType eventType) throws AccessDeniedEx } } - public void authorizeSubscriptionRead(final SubscriptionBase subscriptionBase) throws AccessDeniedException { - subscriptionBase.getEventTypes().forEach( + public void authorizeSubscriptionRead(final Subscription subscription) throws AccessDeniedException { + if (null != subscription.getAuthorization()) { + final Resource resource = new SubscriptionResource(subscription.getId(), subscription.getAuthorization()); + try { + // In this case operation for read will invoke + if (!authorizationService.isAuthorized(AuthorizationService.Operation.READ, resource) + && !adminService.hasAllDataAccess(AuthorizationService.Operation.READ)) { + throw new AccessDeniedException(AuthorizationService.Operation.READ, resource); + } + } catch (final PluginException e) { + throw new ServiceTemporarilyUnavailableException("Error calling authorization plugin", e); + } + } + subscription.getEventTypes().forEach( (eventTypeName) -> { try { eventTypeRepository.findByNameO(eventTypeName).ifPresent(this::authorizeStreamRead); @@ -175,19 +185,36 @@ public void authorizeSubscriptionRead(final SubscriptionBase subscriptionBase) t ); } - public void validateAuthorization(final EventType original, final EventTypeBase newEventType) + public void authorizeSubscriptionCommit(final Subscription subscription) throws AccessDeniedException { + final Resource resource = new SubscriptionResource(subscription.getId(), subscription.getAuthorization()); + try { + if (!authorizationService.isAuthorized(AuthorizationService.Operation.READ, resource) + && !adminService.hasAllDataAccess(AuthorizationService.Operation.READ)) { + throw new AccessDeniedException(AuthorizationService.Operation.READ, resource); + } + } catch (final PluginException e) { + throw new ServiceTemporarilyUnavailableException("Error calling authorization plugin", e); + } + } + + public void authorizeSubscriptionAdmin(final Subscription subscription) { + if (subscription.getAuthorization() == null) { + return; + } + authorizeResourceAdmin(new SubscriptionResource(subscription.getId(), subscription.getAuthorization())); + } + + public void validateAuthorization(final ValidatableAuthorization oldValue, final ValidatableAuthorization newValue) throws UnableProcessException, ServiceTemporarilyUnavailableException { - final ResourceAuthorization originalAuth = original.getAuthorization(); - final ResourceAuthorization newAuth = newEventType.getAuthorization(); - if (originalAuth != null && newAuth == null) { + if (oldValue != null && newValue == null) { throw new UnableProcessException( "Changing authorization object to `null` is not possible due to existing one"); } - if (originalAuth != null && originalAuth.equals(newAuth)) { + if (oldValue != null && oldValue.equals(newValue)) { return; } - validateAuthorization(newAuth); + validateAuthorization(newValue); } } diff --git a/src/main/java/org/zalando/nakadi/service/CursorsService.java b/src/main/java/org/zalando/nakadi/service/CursorsService.java index 2196d1db89..4260cc1108 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorsService.java @@ -50,6 +50,7 @@ public class CursorsService { private final CursorConverter cursorConverter; private final UUIDGenerator uuidGenerator; private final TimelineService timelineService; + private final AuthorizationValidator authorizationValidator; @Autowired public CursorsService(final SubscriptionDbRepository subscriptionRepository, @@ -58,7 +59,8 @@ public CursorsService(final SubscriptionDbRepository subscriptionRepository, final SubscriptionClientFactory zkSubscriptionFactory, final CursorConverter cursorConverter, final UUIDGenerator uuidGenerator, - final TimelineService timelineService) { + final TimelineService timelineService, + final AuthorizationValidator authorizationValidator) { this.subscriptionRepository = subscriptionRepository; this.eventTypeCache = eventTypeCache; this.nakadiSettings = nakadiSettings; @@ -66,6 +68,7 @@ public CursorsService(final SubscriptionDbRepository subscriptionRepository, this.cursorConverter = cursorConverter; this.uuidGenerator = uuidGenerator; this.timelineService = timelineService; + this.authorizationValidator = authorizationValidator; } /** @@ -78,6 +81,9 @@ public List commitCursors(final String streamId, final String subscript TimeLogger.addMeasure("getSubscription"); final Subscription subscription = subscriptionRepository.getSubscription(subscriptionId); + TimeLogger.addMeasure("authorize"); + authorizationValidator.authorizeSubscriptionCommit(subscription); + TimeLogger.addMeasure("validateSubscriptionCursors"); validateSubscriptionCommitCursors(subscription, cursors); diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index f113235929..f8854c7896 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -315,7 +315,7 @@ public void update(final String eventTypeName, eventTypeOptionsValidator.checkRetentionTime(eventTypeBase.getOptions()); authorizationValidator.authorizeEventTypeAdmin(original); } - authorizationValidator.validateAuthorization(original, eventTypeBase); + authorizationValidator.validateAuthorization(original.getAuthorization(), eventTypeBase.getAuthorization()); validateName(eventTypeName, eventTypeBase); validateSchema(eventTypeBase); validateAudience(original, eventTypeBase); diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java index 2ce6518b86..42fbb1cad9 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java @@ -40,6 +40,7 @@ import org.zalando.nakadi.repository.EventTypeRepository; import org.zalando.nakadi.repository.TopicRepository; import org.zalando.nakadi.repository.db.SubscriptionDbRepository; +import org.zalando.nakadi.service.AuthorizationValidator; import org.zalando.nakadi.service.CursorConverter; import org.zalando.nakadi.service.CursorOperationsService; import org.zalando.nakadi.service.FeatureToggleService; @@ -84,6 +85,7 @@ public class SubscriptionService { private final FeatureToggleService featureToggleService; private final String subLogEventType; private final SubscriptionTimeLagService subscriptionTimeLagService; + private final AuthorizationValidator authorizationValidator; public enum StatsMode { LIGHT, @@ -102,7 +104,8 @@ public SubscriptionService(final SubscriptionDbRepository subscriptionRepository final NakadiKpiPublisher nakadiKpiPublisher, final FeatureToggleService featureToggleService, final SubscriptionTimeLagService subscriptionTimeLagService, - @Value("${nakadi.kpi.event-types.nakadiSubscriptionLog}") final String subLogEventType) { + @Value("${nakadi.kpi.event-types.nakadiSubscriptionLog}") final String subLogEventType, + final AuthorizationValidator authorizationValidator) { this.subscriptionRepository = subscriptionRepository; this.subscriptionClientFactory = subscriptionClientFactory; this.timelineService = timelineService; @@ -114,6 +117,7 @@ public SubscriptionService(final SubscriptionDbRepository subscriptionRepository this.featureToggleService = featureToggleService; this.subscriptionTimeLagService = subscriptionTimeLagService; this.subLogEventType = subLogEventType; + this.authorizationValidator = authorizationValidator; } public Subscription createSubscription(final SubscriptionBase subscriptionBase) @@ -135,6 +139,22 @@ public Subscription createSubscription(final SubscriptionBase subscriptionBase) return subscription; } + public Subscription updateSubscription(final String subscriptionId, final SubscriptionBase newValue) + throws NoSuchSubscriptionException { + if (featureToggleService.isFeatureEnabled(FeatureToggleService.Feature.DISABLE_DB_WRITE_OPERATIONS)) { + throw new DbWriteOperationsBlockedException("Cannot create subscription: write operations on DB " + + "are blocked by feature flag."); + } + final Subscription old = subscriptionRepository.getSubscription(subscriptionId); + + authorizationValidator.authorizeSubscriptionAdmin(old); + + subscriptionValidationService.validateSubscriptionChange(old, newValue); + old.mergeFrom(newValue); + subscriptionRepository.updateSubscription(old); + return old; + } + public Subscription getExistingSubscription(final SubscriptionBase subscriptionBase) throws InconsistentStateException, NoSubscriptionException, RepositoryProblemException { return subscriptionRepository.getSubscription( @@ -202,6 +222,8 @@ public Result deleteSubscription(final String subscriptionId) throws DbWri try { final Subscription subscription = subscriptionRepository.getSubscription(subscriptionId); + authorizationValidator.authorizeSubscriptionAdmin(subscription); + subscriptionRepository.deleteSubscription(subscriptionId); final ZkSubscriptionClient zkSubscriptionClient = subscriptionClientFactory.createClient( subscription, "subscription." + subscriptionId + ".delete_subscription"); diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java index 174169acee..3cb1ba4385 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java @@ -8,6 +8,7 @@ import org.zalando.nakadi.domain.EventTypePartition; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Subscription; +import org.zalando.nakadi.domain.SubscriptionAuthorization; import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.InvalidCursorException; @@ -20,6 +21,7 @@ import org.zalando.nakadi.exceptions.runtime.WrongInitialCursorsException; import org.zalando.nakadi.exceptions.runtime.WrongStreamParametersException; import org.zalando.nakadi.repository.EventTypeRepository; +import org.zalando.nakadi.service.AuthorizationValidator; import org.zalando.nakadi.service.CursorConverter; import org.zalando.nakadi.service.timeline.TimelineService; import org.zalando.nakadi.view.SubscriptionCursorWithoutToken; @@ -28,6 +30,7 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; @@ -41,16 +44,19 @@ public class SubscriptionValidationService { private final TimelineService timelineService; private final int maxSubscriptionPartitions; private final CursorConverter cursorConverter; + private final AuthorizationValidator authorizationValidator; @Autowired public SubscriptionValidationService(final TimelineService timelineService, final EventTypeRepository eventTypeRepository, final NakadiSettings nakadiSettings, - final CursorConverter cursorConverter) { + final CursorConverter cursorConverter, + final AuthorizationValidator authorizationValidator) { this.timelineService = timelineService; this.eventTypeRepository = eventTypeRepository; this.maxSubscriptionPartitions = nakadiSettings.getMaxSubscriptionPartitions(); this.cursorConverter = cursorConverter; + this.authorizationValidator = authorizationValidator; } public void validateSubscription(final SubscriptionBase subscription) @@ -74,6 +80,27 @@ public void validateSubscription(final SubscriptionBase subscription) if (subscription.getReadFrom() == SubscriptionBase.InitialPosition.CURSORS) { validateInitialCursors(subscription, allPartitions); } + // Verify that subscription authorization object is valid + authorizationValidator.validateAuthorization(subscription.getAuthorization()); + } + + public void validateSubscriptionChange(final Subscription old, final SubscriptionBase newValue) { + if (!Objects.equals(newValue.getConsumerGroup(), old.getConsumerGroup())) { + throw new IllegalArgumentException("Not allowed to change subscription consumer group"); + } + if (!Objects.equals(newValue.getEventTypes(), old.getEventTypes())) { + throw new IllegalArgumentException("Not allowed to change subscription event types"); + } + if (!Objects.equals(newValue.getOwningApplication(), old.getOwningApplication())) { + throw new IllegalArgumentException("Not allowed to change owning application"); + } + if (!Objects.equals(newValue.getReadFrom(), old.getReadFrom())) { + throw new IllegalArgumentException("Not allowed to change owning application"); + } + if (!Objects.equals(newValue.getInitialCursors(), old.getInitialCursors())) { + throw new IllegalArgumentException("Not allowed to change owning application"); + } + authorizationValidator.validateAuthorization(old.getAuthorization(), newValue.getAuthorization()); } public void validatePartitionsToStream(final Subscription subscription, final List partitions) { @@ -169,5 +196,4 @@ private void checkEventTypesExist(final Map> eventTy StringUtils.join(missingEventTypes, "', '"))); } } - } diff --git a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java index ae6858498c..c9e1cdc91f 100644 --- a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java @@ -123,7 +123,7 @@ public SubscriptionControllerTest() throws Exception { final SubscriptionService subscriptionService = new SubscriptionService(subscriptionRepository, zkSubscriptionClientFactory, timelineService, eventTypeRepository, null, cursorConverter, cursorOperationsService, nakadiKpiPublisher, featureToggleService, null, - "subscription_log_et"); + "subscription_log_et", authorizationValidator); final SubscriptionController controller = new SubscriptionController(featureToggleService, subscriptionService); final ApplicationService applicationService = mock(ApplicationService.class); doReturn(true).when(applicationService).exists(any()); diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java index c3520dfe1c..3ae066f33c 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java @@ -42,11 +42,11 @@ public SubscriptionServiceTest() throws Exception { subscriptionService = new SubscriptionService(subscriptionRepository, zkSubscriptionClientFactory, timelineService, eventTypeRepository, subscriptionValidationService, cursorConverter, - cursorOperationsService, nakadiKpiPublisher, featureToggleService, null, SUBSCRIPTION_LOG_ET); + cursorOperationsService, nakadiKpiPublisher, featureToggleService, null, SUBSCRIPTION_LOG_ET, authorizationValidator); } @Test - public void whenSubscriptionCreatedThenKPIEventSubmitted() throws Exception { + public void whenSubscriptionCreatedThenKPIEventSubmitted() { final SubscriptionBase subscriptionBase = RandomSubscriptionBuilder.builder() .buildSubscriptionBase(); final Subscription subscription = RandomSubscriptionBuilder.builder() @@ -63,7 +63,7 @@ public void whenSubscriptionCreatedThenKPIEventSubmitted() throws Exception { } @Test - public void whenSubscriptionDeletedThenKPIEventSubmitted() throws Exception { + public void whenSubscriptionDeletedThenKPIEventSubmitted() { subscriptionService.deleteSubscription("my_subscription_id1"); checkKPIEventSubmitted(nakadiKpiPublisher, SUBSCRIPTION_LOG_ET, diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java index 2369267714..c1d4c5a187 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java @@ -84,7 +84,7 @@ public void setUp() throws InternalNakadiException { when(timelineService.getTopicRepository((EventType) any())).thenReturn(topicRepository); cursorConverter = mock(CursorConverter.class); subscriptionValidationService = new SubscriptionValidationService(timelineService, etRepo, nakadiSettings, - cursorConverter); + cursorConverter, authorizationValidator); subscriptionBase = new SubscriptionBase(); subscriptionBase.setEventTypes(ImmutableSet.of(ET1, ET2, ET3)); From 311bc0a4070dc5721b827a32e670247c0be5d3b3 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Thu, 28 Jun 2018 16:14:41 +0200 Subject: [PATCH 020/176] ARUHA-1681 Fix tests to pass --- .../nakadi/webservice/CursorsServiceAT.java | 2 +- .../org/zalando/nakadi/domain/EventType.java | 4 ++++ .../zalando/nakadi/domain/Subscription.java | 4 ++++ .../domain/SubscriptionAuthorization.java | 12 +++++++---- .../nakadi/domain/SubscriptionBase.java | 2 +- .../nakadi/domain/SubscriptionResource.java | 3 ++- .../domain/ValidatableAuthorization.java | 2 +- .../service/AuthorizationValidator.java | 16 +++++++-------- .../SubscriptionValidationService.java | 1 - .../service/timeline/TimelineService.java | 20 +++++++++---------- .../EventTypeAuthorizationTest.java | 9 ++++----- .../SubscriptionControllerTest.java | 3 ++- .../service/SubscriptionServiceTest.java | 3 ++- .../SubscriptionValidationServiceTest.java | 2 +- 14 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java b/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java index e5a5fe791a..80bb809f76 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java +++ b/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java @@ -108,7 +108,7 @@ public void before() throws Exception { uuidGenerator = mock(UUIDGenerator.class); when(uuidGenerator.isUUID(any())).thenReturn(true); cursorsService = new CursorsService(subscriptionRepo, null, - mock(NakadiSettings.class), zkSubscriptionFactory, cursorConverter, uuidGenerator, null, authorizationValidator); + mock(NakadiSettings.class), zkSubscriptionFactory, cursorConverter, uuidGenerator, null, null); // Register cursors in converter registerNakadiCursor(NakadiCursor.of(buildTimeline(etName, topic, CREATED_AT), P1, NEW_OFFSET)); diff --git a/src/main/java/org/zalando/nakadi/domain/EventType.java b/src/main/java/org/zalando/nakadi/domain/EventType.java index 36fec0d1b8..e820207790 100644 --- a/src/main/java/org/zalando/nakadi/domain/EventType.java +++ b/src/main/java/org/zalando/nakadi/domain/EventType.java @@ -46,4 +46,8 @@ public void setUpdatedAt(final DateTime updatedAt) { public void setCreatedAt(final DateTime createdAt) { this.createdAt = createdAt; } + + public EventTypeResource asResource() { + return new EventTypeResource(getName(), getAuthorization()); + } } diff --git a/src/main/java/org/zalando/nakadi/domain/Subscription.java b/src/main/java/org/zalando/nakadi/domain/Subscription.java index cc458cf80a..c976ea9854 100644 --- a/src/main/java/org/zalando/nakadi/domain/Subscription.java +++ b/src/main/java/org/zalando/nakadi/domain/Subscription.java @@ -41,6 +41,10 @@ public void setCreatedAt(final DateTime createdAt) { this.createdAt = createdAt; } + public SubscriptionResource asResource() { + return new SubscriptionResource(id, getAuthorization()); + } + @Nullable public List getStatus() { return status; diff --git a/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java b/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java index c3a4cf5aab..4c345b879d 100644 --- a/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java +++ b/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java @@ -44,10 +44,14 @@ public List getReaders() { } @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - SubscriptionAuthorization that = (SubscriptionAuthorization) o; + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final SubscriptionAuthorization that = (SubscriptionAuthorization) o; return Objects.equals(admins, that.admins) && Objects.equals(readers, that.readers); } diff --git a/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java b/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java index 6f728954b4..96afac4e65 100644 --- a/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java +++ b/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java @@ -59,7 +59,7 @@ public SubscriptionAuthorization getAuthorization() { return authorization; } - public void setAuthorization(SubscriptionAuthorization authorization) { + public void setAuthorization(final SubscriptionAuthorization authorization) { this.authorization = authorization; } diff --git a/src/main/java/org/zalando/nakadi/domain/SubscriptionResource.java b/src/main/java/org/zalando/nakadi/domain/SubscriptionResource.java index b4160509ad..54e0185b66 100644 --- a/src/main/java/org/zalando/nakadi/domain/SubscriptionResource.java +++ b/src/main/java/org/zalando/nakadi/domain/SubscriptionResource.java @@ -11,7 +11,8 @@ public class SubscriptionResource implements Resource { private final String subscriptionId; private final SubscriptionAuthorization subscriptionAuthorization; - public SubscriptionResource(String subscriptionId, SubscriptionAuthorization subscriptionAuthorization) { + public SubscriptionResource( + final String subscriptionId, final SubscriptionAuthorization subscriptionAuthorization) { this.subscriptionId = subscriptionId; this.subscriptionAuthorization = subscriptionAuthorization; } diff --git a/src/main/java/org/zalando/nakadi/domain/ValidatableAuthorization.java b/src/main/java/org/zalando/nakadi/domain/ValidatableAuthorization.java index 69e694f8b2..826461ab06 100644 --- a/src/main/java/org/zalando/nakadi/domain/ValidatableAuthorization.java +++ b/src/main/java/org/zalando/nakadi/domain/ValidatableAuthorization.java @@ -10,7 +10,7 @@ public interface ValidatableAuthorization { Map> asMapValue(); - Optional> getAttributesForOperation(final AuthorizationService.Operation operation) + Optional> getAttributesForOperation(AuthorizationService.Operation operation) throws IllegalArgumentException; } diff --git a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java index 3b793a66bb..3e9bc9e9d7 100644 --- a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java +++ b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java @@ -6,7 +6,6 @@ import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeResource; import org.zalando.nakadi.domain.Subscription; -import org.zalando.nakadi.domain.SubscriptionResource; import org.zalando.nakadi.domain.ValidatableAuthorization; import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; @@ -111,8 +110,7 @@ public void authorizeEventTypeWrite(final EventType eventType) if (eventType.getAuthorization() == null) { return; } - final EventTypeResource resource = new EventTypeResource( - eventType.getName(), eventType.getAuthorization()); + final EventTypeResource resource = eventType.asResource(); try { final boolean authorized = authorizationService.isAuthorized( AuthorizationService.Operation.WRITE, @@ -125,7 +123,7 @@ public void authorizeEventTypeWrite(final EventType eventType) } } - private void authorizeResourceAdmin(Resource resource) { + private void authorizeResourceAdmin(final Resource resource) { try { if (!authorizationService.isAuthorized(AuthorizationService.Operation.ADMIN, resource)) { if (!adminService.isAdmin(AuthorizationService.Operation.WRITE)) { @@ -142,7 +140,7 @@ public void authorizeEventTypeAdmin(final EventType eventType) if (eventType.getAuthorization() == null) { return; } - authorizeResourceAdmin(new EventTypeResource(eventType.getName(), eventType.getAuthorization())); + authorizeResourceAdmin(eventType.asResource()); } public void authorizeStreamRead(final EventType eventType) throws AccessDeniedException { @@ -150,7 +148,7 @@ public void authorizeStreamRead(final EventType eventType) throws AccessDeniedEx return; } - final Resource resource = new EventTypeResource(eventType.getName(), eventType.getAuthorization()); + final Resource resource = eventType.asResource(); try { if (!authorizationService.isAuthorized(AuthorizationService.Operation.READ, resource) && !adminService.hasAllDataAccess(AuthorizationService.Operation.READ)) { @@ -163,7 +161,7 @@ public void authorizeStreamRead(final EventType eventType) throws AccessDeniedEx public void authorizeSubscriptionRead(final Subscription subscription) throws AccessDeniedException { if (null != subscription.getAuthorization()) { - final Resource resource = new SubscriptionResource(subscription.getId(), subscription.getAuthorization()); + final Resource resource = subscription.asResource(); try { // In this case operation for read will invoke if (!authorizationService.isAuthorized(AuthorizationService.Operation.READ, resource) @@ -186,7 +184,7 @@ public void authorizeSubscriptionRead(final Subscription subscription) throws Ac } public void authorizeSubscriptionCommit(final Subscription subscription) throws AccessDeniedException { - final Resource resource = new SubscriptionResource(subscription.getId(), subscription.getAuthorization()); + final Resource resource = subscription.asResource(); try { if (!authorizationService.isAuthorized(AuthorizationService.Operation.READ, resource) && !adminService.hasAllDataAccess(AuthorizationService.Operation.READ)) { @@ -201,7 +199,7 @@ public void authorizeSubscriptionAdmin(final Subscription subscription) { if (subscription.getAuthorization() == null) { return; } - authorizeResourceAdmin(new SubscriptionResource(subscription.getId(), subscription.getAuthorization())); + authorizeResourceAdmin(subscription.asResource()); } public void validateAuthorization(final ValidatableAuthorization oldValue, final ValidatableAuthorization newValue) diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java index 3cb1ba4385..b744efa46e 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java @@ -8,7 +8,6 @@ import org.zalando.nakadi.domain.EventTypePartition; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Subscription; -import org.zalando.nakadi.domain.SubscriptionAuthorization; import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.InvalidCursorException; diff --git a/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java b/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java index 67c34b2ab1..3dd54f7013 100644 --- a/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java +++ b/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java @@ -18,25 +18,24 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.runtime.NotFoundException; -import org.zalando.nakadi.exceptions.runtime.TimelineException; -import org.zalando.nakadi.exceptions.runtime.TopicCreationException; -import org.zalando.nakadi.exceptions.runtime.TopicDeletionException; -import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; +import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; import org.zalando.nakadi.exceptions.runtime.DuplicatedTimelineException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; +import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; +import org.zalando.nakadi.exceptions.runtime.TimelineException; +import org.zalando.nakadi.exceptions.runtime.TopicCreationException; +import org.zalando.nakadi.exceptions.runtime.TopicDeletionException; import org.zalando.nakadi.exceptions.runtime.TopicRepositoryException; +import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; -import org.zalando.nakadi.plugin.api.authz.Resource; import org.zalando.nakadi.repository.EventConsumer; import org.zalando.nakadi.repository.MultiTimelineEventConsumer; import org.zalando.nakadi.repository.TopicRepository; @@ -104,8 +103,7 @@ public void createTimeline(final String eventTypeName, final String storageId) final EventType eventType = eventTypeCache.getEventType(eventTypeName); if (!adminService.isAdmin(AuthorizationService.Operation.WRITE)) { - final Resource resource = new EventTypeResource(eventTypeName, eventType.getAuthorization()); - throw new AccessDeniedException(AuthorizationService.Operation.ADMIN, resource); + throw new AccessDeniedException(AuthorizationService.Operation.ADMIN, eventType.asResource()); } final Storage storage = storageDbRepository.getStorage(storageId) @@ -316,8 +314,8 @@ private void finishTimelineUpdate(final String eventTypeName) throws TimelineExc public List getTimelines(final String eventTypeName) throws AccessDeniedException, UnableProcessException, TimelineException, NotFoundException { if (!adminService.isAdmin(AuthorizationService.Operation.READ)) { - final Resource resource = new EventTypeResource(eventTypeName, null); - throw new AccessDeniedException(AuthorizationService.Operation.ADMIN, resource); + throw new AccessDeniedException(AuthorizationService.Operation.ADMIN, + new EventTypeResource(eventTypeName, null)); } try { diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeAuthorizationTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeAuthorizationTest.java index af6ba06e23..00a10cec0b 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeAuthorizationTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeAuthorizationTest.java @@ -3,9 +3,8 @@ import org.junit.Test; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeOptions; -import org.zalando.nakadi.domain.EventTypeResource; -import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; +import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; import org.zalando.nakadi.plugin.api.authz.Resource; import org.zalando.nakadi.utils.EventTypeTestBuilder; @@ -41,7 +40,7 @@ public void whenPUTAuthorized200() throws Exception { @Test public void whenPUTNotAuthorizedThen403() throws Exception { final EventType eventType = EventTypeTestBuilder.builder().build(); - final Resource resource = new EventTypeResource(eventType.getName(), eventType.getAuthorization()); + final Resource resource = eventType.asResource(); doReturn(eventType).when(eventTypeRepository).findByName(any()); doThrow(new AccessDeniedException(AuthorizationService.Operation.ADMIN, resource)) @@ -50,7 +49,7 @@ public void whenPUTNotAuthorizedThen403() throws Exception { putEventType(eventType, eventType.getName()) .andExpect(status().isForbidden()) .andExpect(content().string(matchesProblem(Problem.valueOf(Response.Status.FORBIDDEN, - "Access on ADMIN event-type:"+ eventType.getName() + " denied")))); + "Access on ADMIN event-type:" + eventType.getName() + " denied")))); } @Test @@ -98,7 +97,7 @@ public void whenPUTNullAuthorizationForExistingAuthorization() throws Exception @Test public void whenDELETENotAuthorized200() throws Exception { final EventType eventType = EventTypeTestBuilder.builder().build(); - final Resource resource = new EventTypeResource(eventType.getName(), eventType.getAuthorization()); + final Resource resource = eventType.asResource(); doReturn(Optional.of(eventType)).when(eventTypeRepository).findByNameO(any()); doThrow(new AccessDeniedException(AuthorizationService.Operation.ADMIN, resource)) diff --git a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java index c9e1cdc91f..5ce11c6ca1 100644 --- a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java @@ -31,6 +31,7 @@ import org.zalando.nakadi.repository.db.SubscriptionDbRepository; import org.zalando.nakadi.repository.kafka.KafkaPartitionEndStatistics; import org.zalando.nakadi.security.NakadiClient; +import org.zalando.nakadi.service.AuthorizationValidator; import org.zalando.nakadi.service.CursorConverter; import org.zalando.nakadi.service.CursorOperationsService; import org.zalando.nakadi.service.FeatureToggleService; @@ -123,7 +124,7 @@ public SubscriptionControllerTest() throws Exception { final SubscriptionService subscriptionService = new SubscriptionService(subscriptionRepository, zkSubscriptionClientFactory, timelineService, eventTypeRepository, null, cursorConverter, cursorOperationsService, nakadiKpiPublisher, featureToggleService, null, - "subscription_log_et", authorizationValidator); + "subscription_log_et", mock(AuthorizationValidator.class)); final SubscriptionController controller = new SubscriptionController(featureToggleService, subscriptionService); final ApplicationService applicationService = mock(ApplicationService.class); doReturn(true).when(applicationService).exists(any()); diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java index 3ae066f33c..7376f7db04 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java @@ -42,7 +42,8 @@ public SubscriptionServiceTest() throws Exception { subscriptionService = new SubscriptionService(subscriptionRepository, zkSubscriptionClientFactory, timelineService, eventTypeRepository, subscriptionValidationService, cursorConverter, - cursorOperationsService, nakadiKpiPublisher, featureToggleService, null, SUBSCRIPTION_LOG_ET, authorizationValidator); + cursorOperationsService, nakadiKpiPublisher, featureToggleService, null, SUBSCRIPTION_LOG_ET, + mock(AuthorizationValidator.class)); } @Test diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java index c1d4c5a187..7068bffa35 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java @@ -84,7 +84,7 @@ public void setUp() throws InternalNakadiException { when(timelineService.getTopicRepository((EventType) any())).thenReturn(topicRepository); cursorConverter = mock(CursorConverter.class); subscriptionValidationService = new SubscriptionValidationService(timelineService, etRepo, nakadiSettings, - cursorConverter, authorizationValidator); + cursorConverter, null); subscriptionBase = new SubscriptionBase(); subscriptionBase.setEventTypes(ImmutableSet.of(ET1, ET2, ET3)); From 782609622c9e9e797559e622d3200375684fba30 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Thu, 28 Jun 2018 16:29:59 +0200 Subject: [PATCH 021/176] ARUHA-1681 Validate subscription access while resetting cursors --- .../org/zalando/nakadi/controller/CursorsController.java | 7 +++---- .../java/org/zalando/nakadi/service/CursorsService.java | 7 ++++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/CursorsController.java b/src/main/java/org/zalando/nakadi/controller/CursorsController.java index 2b2ddf9487..a1097c3157 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorsController.java @@ -17,15 +17,15 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.InvalidCursorException; -import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.exceptions.runtime.CursorsAreEmptyException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; +import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; import org.zalando.nakadi.exceptions.runtime.RequestInProgressException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; +import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.problem.ValidationProblem; import org.zalando.nakadi.service.CursorConverter; import org.zalando.nakadi.service.CursorTokenService; @@ -123,8 +123,7 @@ public ResponseEntity commitCursors(@PathVariable("subscriptionId") final Str } catch (final NakadiException e) { LOG.error("Failed to commit cursors", e); return create(e.asProblem(), request); - } - finally { + } finally { LOG.info(TimeLogger.finishMeasure()); } } diff --git a/src/main/java/org/zalando/nakadi/service/CursorsService.java b/src/main/java/org/zalando/nakadi/service/CursorsService.java index 4260cc1108..fd6492314d 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorsService.java @@ -10,6 +10,7 @@ import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; @@ -77,7 +78,8 @@ public CursorsService(final SubscriptionDbRepository subscriptionRepository, public List commitCursors(final String streamId, final String subscriptionId, final List cursors) throws ServiceTemporarilyUnavailableException, InvalidCursorException, InvalidStreamIdException, - NoSuchEventTypeException, InternalNakadiException, NoSuchSubscriptionException, UnableProcessException { + NoSuchEventTypeException, InternalNakadiException, NoSuchSubscriptionException, UnableProcessException, + AccessDeniedException { TimeLogger.addMeasure("getSubscription"); final Subscription subscription = subscriptionRepository.getSubscription(subscriptionId); @@ -158,6 +160,9 @@ public void resetCursors(final String subscriptionId, final List c UnableProcessException, OperationTimeoutException, ZookeeperException, InternalNakadiException, NoSuchEventTypeException, InvalidCursorException { final Subscription subscription = subscriptionRepository.getSubscription(subscriptionId); + + authorizationValidator.authorizeSubscriptionAdmin(subscription); + validateCursorsBelongToSubscription(subscription, cursors); for (final NakadiCursor cursor : cursors) { cursor.checkStorageAvailability(); From 298a6c1a07469ee98b14384da95e98f7b039fb56 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Fri, 29 Jun 2018 09:29:04 +0200 Subject: [PATCH 022/176] ARUHA-1681 Add tests for subscription authorization --- .../service/AuthorizationValidator.java | 4 +- .../subscription/SubscriptionService.java | 1 + .../SubscriptionValidationService.java | 4 +- .../service/AuthorizationValidatorTest.java | 19 +++---- .../nakadi/service/CursorsServiceTest.java | 41 ++++++++++++++ .../service/SubscriptionServiceTest.java | 55 ++++++++++++++++--- 6 files changed, 103 insertions(+), 21 deletions(-) create mode 100644 src/test/java/org/zalando/nakadi/service/CursorsServiceTest.java diff --git a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java index 3e9bc9e9d7..f0820e379d 100644 --- a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java +++ b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java @@ -123,7 +123,7 @@ public void authorizeEventTypeWrite(final EventType eventType) } } - private void authorizeResourceAdmin(final Resource resource) { + private void authorizeResourceAdmin(final Resource resource) throws AccessDeniedException { try { if (!authorizationService.isAuthorized(AuthorizationService.Operation.ADMIN, resource)) { if (!adminService.isAdmin(AuthorizationService.Operation.WRITE)) { @@ -195,7 +195,7 @@ public void authorizeSubscriptionCommit(final Subscription subscription) throws } } - public void authorizeSubscriptionAdmin(final Subscription subscription) { + public void authorizeSubscriptionAdmin(final Subscription subscription) throws AccessDeniedException { if (subscription.getAuthorization() == null) { return; } diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java index 42fbb1cad9..15e963f373 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java @@ -130,6 +130,7 @@ public Subscription createSubscription(final SubscriptionBase subscriptionBase) } subscriptionValidationService.validateSubscription(subscriptionBase); + final Subscription subscription = subscriptionRepository.createSubscription(subscriptionBase); nakadiKpiPublisher.publish(subLogEventType, () -> new JSONObject() diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java index b744efa46e..af017e6c83 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java @@ -94,10 +94,10 @@ public void validateSubscriptionChange(final Subscription old, final Subscriptio throw new IllegalArgumentException("Not allowed to change owning application"); } if (!Objects.equals(newValue.getReadFrom(), old.getReadFrom())) { - throw new IllegalArgumentException("Not allowed to change owning application"); + throw new IllegalArgumentException("Not allowed to change read from"); } if (!Objects.equals(newValue.getInitialCursors(), old.getInitialCursors())) { - throw new IllegalArgumentException("Not allowed to change owning application"); + throw new IllegalArgumentException("Not allowed to change initial cursors"); } authorizationValidator.validateAuthorization(old.getAuthorization(), newValue.getAuthorization()); } diff --git a/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java b/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java index 6022f57086..1f4c2396d2 100644 --- a/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java +++ b/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java @@ -5,9 +5,9 @@ import org.junit.Test; import org.zalando.nakadi.domain.ResourceAuthorization; import org.zalando.nakadi.domain.ResourceAuthorizationAttribute; -import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; +import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.plugin.api.PluginException; import org.zalando.nakadi.plugin.api.authz.AuthorizationAttribute; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; @@ -41,7 +41,7 @@ public AuthorizationValidatorTest() { } @Test - public void whenInvalidAuthAttributesThenInvalidEventTypeException() throws Exception { + public void whenInvalidAuthAttributesThenInvalidEventTypeException() { final ResourceAuthorization auth = new ResourceAuthorization( ImmutableList.of(attr1), ImmutableList.of(attr2), ImmutableList.of(attr3, attr4)); @@ -61,7 +61,7 @@ public void whenInvalidAuthAttributesThenInvalidEventTypeException() throws Exce } @Test - public void whenDuplicatesThenInvalidEventTypeException() throws Exception { + public void whenDuplicatesThenInvalidEventTypeException() { final ResourceAuthorization auth = new ResourceAuthorization( ImmutableList.of(attr1, attr3, attr2, attr1, attr1, attr3), @@ -81,7 +81,7 @@ public void whenDuplicatesThenInvalidEventTypeException() throws Exception { } @Test(expected = ServiceTemporarilyUnavailableException.class) - public void whenPluginExceptionInIsAuthorizationAttributeValidThenServiceUnavailableException() throws Exception { + public void whenPluginExceptionInIsAuthorizationAttributeValidThenServiceUnavailableException() { final ResourceAuthorization auth = new ResourceAuthorization( ImmutableList.of(attr1), @@ -94,19 +94,19 @@ public void whenPluginExceptionInIsAuthorizationAttributeValidThenServiceUnavail } @Test - public void whenAuthorizationIsNullWhileUpdatingETThenOk() throws Exception { + public void whenAuthorizationIsNullWhileUpdatingETThenOk() { validator.authorizeEventTypeAdmin(EventTypeTestBuilder.builder().authorization(null).build()); } @Test(expected = AccessDeniedException.class) - public void whenNotAuthorizedThenForbiddenAccessException() throws Exception { + public void whenNotAuthorizedThenForbiddenAccessException() { when(authorizationService.isAuthorized(any(), any())).thenReturn(false); validator.authorizeEventTypeAdmin(EventTypeTestBuilder.builder() .authorization(new ResourceAuthorization(null, null, null)).build()); } @Test - public void whenETAdminNotAuthorizedButAdminThenOk() throws Exception { + public void whenETAdminNotAuthorizedButAdminThenOk() { when(authorizationService.isAuthorized(any(), any())).thenReturn(false); when(adminService.isAdmin(any())).thenReturn(true); validator.authorizeEventTypeAdmin(EventTypeTestBuilder.builder() @@ -114,15 +114,14 @@ public void whenETAdminNotAuthorizedButAdminThenOk() throws Exception { } @Test - public void whenAuthorizedThenOk() throws Exception { + public void whenAuthorizedThenOk() { when(authorizationService.isAuthorized(any(), any())).thenReturn(true); validator.authorizeEventTypeAdmin(EventTypeTestBuilder.builder() .authorization(new ResourceAuthorization(null, null, null)).build()); } @Test(expected = ServiceTemporarilyUnavailableException.class) - public void whenPluginExceptionInAuthorizeEventTypeUpdateThenServiceTemporarilyUnavailableException() - throws Exception { + public void whenPluginExceptionInAuthorizeEventTypeUpdateThenServiceTemporarilyUnavailableException() { when(authorizationService.isAuthorized(any(), any())).thenThrow(new PluginException("blah")); validator.authorizeEventTypeAdmin(EventTypeTestBuilder.builder() .authorization(new ResourceAuthorization(null, null, null)).build()); diff --git a/src/test/java/org/zalando/nakadi/service/CursorsServiceTest.java b/src/test/java/org/zalando/nakadi/service/CursorsServiceTest.java new file mode 100644 index 0000000000..9457589fbe --- /dev/null +++ b/src/test/java/org/zalando/nakadi/service/CursorsServiceTest.java @@ -0,0 +1,41 @@ +package org.zalando.nakadi.service; + +import org.junit.Before; +import org.junit.Test; +import org.zalando.nakadi.domain.SubscriptionResource; +import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; +import org.zalando.nakadi.plugin.api.authz.AuthorizationService; +import org.zalando.nakadi.repository.db.SubscriptionDbRepository; + +import java.util.Collections; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; + +public class CursorsServiceTest { + + private AuthorizationValidator authorizationValidator; + private CursorsService service; + + @Before + public void setup() { + authorizationValidator = mock(AuthorizationValidator.class); + service = new CursorsService( + mock(SubscriptionDbRepository.class), null, null, null, null, null, null, authorizationValidator); + } + + @Test(expected = AccessDeniedException.class) + public void whenResetCursorsThenAdminAccessChecked() throws Exception { + doThrow(new AccessDeniedException(AuthorizationService.Operation.ADMIN, new SubscriptionResource("", null))) + .when(authorizationValidator).authorizeSubscriptionAdmin(any()); + service.resetCursors("test", Collections.emptyList()); + } + + @Test(expected = AccessDeniedException.class) + public void whenCommitCursorsAccessDenied() throws Exception { + doThrow(new AccessDeniedException(AuthorizationService.Operation.ADMIN, new SubscriptionResource("", null))) + .when(authorizationValidator).authorizeSubscriptionCommit(any()); + service.commitCursors("test", "test", Collections.emptyList()); + } +} \ No newline at end of file diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java index 7376f7db04..0ddd75ac8e 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java @@ -1,9 +1,15 @@ package org.zalando.nakadi.service; import org.json.JSONObject; +import org.junit.Before; import org.junit.Test; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; +import org.zalando.nakadi.domain.SubscriptionResource; +import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; +import org.zalando.nakadi.exceptions.runtime.UnableProcessException; +import org.zalando.nakadi.plugin.api.authz.AuthorizationService; import org.zalando.nakadi.repository.EventTypeRepository; import org.zalando.nakadi.repository.db.SubscriptionDbRepository; import org.zalando.nakadi.service.subscription.SubscriptionService; @@ -14,6 +20,8 @@ import org.zalando.nakadi.utils.RandomSubscriptionBuilder; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.zalando.nakadi.utils.TestUtils.checkKPIEventSubmitted; @@ -22,28 +30,32 @@ public class SubscriptionServiceTest { private static final String SUBSCRIPTION_LOG_ET = "subscription_log_et"; - private final SubscriptionDbRepository subscriptionRepository; - private final NakadiKpiPublisher nakadiKpiPublisher; - private final SubscriptionService subscriptionService; - private final FeatureToggleService featureToggleService; + private SubscriptionDbRepository subscriptionRepository; + private NakadiKpiPublisher nakadiKpiPublisher; + private SubscriptionService subscriptionService; + private FeatureToggleService featureToggleService; + private AuthorizationValidator authorizationValidator; + private SubscriptionValidationService subscriptionValidationService; - public SubscriptionServiceTest() throws Exception { + @Before + public void setUp() throws Exception { final SubscriptionClientFactory zkSubscriptionClientFactory = mock(SubscriptionClientFactory.class); final ZkSubscriptionClient zkSubscriptionClient = mock(ZkSubscriptionClient.class); when(zkSubscriptionClientFactory.createClient(any(), any())).thenReturn(zkSubscriptionClient); final TimelineService timelineService = mock(TimelineService.class); final CursorOperationsService cursorOperationsService = mock(CursorOperationsService.class); final CursorConverter cursorConverter = mock(CursorConverter.class); - final SubscriptionValidationService subscriptionValidationService = mock(SubscriptionValidationService.class); final EventTypeRepository eventTypeRepository = mock(EventTypeRepository.class); + subscriptionValidationService = mock(SubscriptionValidationService.class); nakadiKpiPublisher = mock(NakadiKpiPublisher.class); subscriptionRepository = mock(SubscriptionDbRepository.class); featureToggleService = mock(FeatureToggleService.class); + authorizationValidator = mock(AuthorizationValidator.class); subscriptionService = new SubscriptionService(subscriptionRepository, zkSubscriptionClientFactory, timelineService, eventTypeRepository, subscriptionValidationService, cursorConverter, cursorOperationsService, nakadiKpiPublisher, featureToggleService, null, SUBSCRIPTION_LOG_ET, - mock(AuthorizationValidator.class)); + authorizationValidator); } @Test @@ -73,4 +85,33 @@ public void whenSubscriptionDeletedThenKPIEventSubmitted() { .put("status", "deleted")); } + @Test(expected = UnableProcessException.class) + public void whenSubscriptionCreatedAuthorizationIsValidated() { + final SubscriptionBase subscriptionBase = RandomSubscriptionBuilder.builder() + .buildSubscriptionBase(); + + doThrow(new UnableProcessException("fake")) + .when(subscriptionValidationService).validateSubscription(eq(subscriptionBase)); + + subscriptionService.createSubscription(subscriptionBase); + } + + @Test(expected = AccessDeniedException.class) + public void whenSubscriptionModifiedAuthorizationIsValidated() throws NoSuchSubscriptionException { + doThrow(new AccessDeniedException(AuthorizationService.Operation.ADMIN, new SubscriptionResource("", null))) + .when(authorizationValidator).authorizeSubscriptionAdmin(any()); + + final SubscriptionBase subscriptionBase = RandomSubscriptionBuilder.builder() + .buildSubscriptionBase(); + + subscriptionService.updateSubscription("test", subscriptionBase); + } + + @Test(expected = AccessDeniedException.class) + public void whenSubscriptionDeletedAuthorizationIsValidated() { + doThrow(new AccessDeniedException(AuthorizationService.Operation.ADMIN, new SubscriptionResource("", null))) + .when(authorizationValidator).authorizeSubscriptionAdmin(any()); + + subscriptionService.deleteSubscription("test"); + } } From 9c1e60202c1538f6ce10f64fd4879d240352827b Mon Sep 17 00:00:00 2001 From: dsorokin Date: Fri, 29 Jun 2018 12:26:15 +0200 Subject: [PATCH 023/176] ARUHA-1681 Fix NPE on equals --- .../zalando/nakadi/domain/Subscription.java | 3 ++- .../nakadi/domain/SubscriptionBase.java | 20 ++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/domain/Subscription.java b/src/main/java/org/zalando/nakadi/domain/Subscription.java index c976ea9854..2e1ef62b26 100644 --- a/src/main/java/org/zalando/nakadi/domain/Subscription.java +++ b/src/main/java/org/zalando/nakadi/domain/Subscription.java @@ -5,6 +5,7 @@ import javax.annotation.Nullable; import java.util.List; +import java.util.Objects; public class Subscription extends SubscriptionBase { @@ -63,7 +64,7 @@ public boolean equals(final Object o) { return false; } final Subscription that = (Subscription) o; - return super.equals(that) && id.equals(that.id) && createdAt.equals(that.createdAt); + return super.equals(that) && Objects.equals(id, that.id) && Objects.equals(createdAt, that.createdAt); } @Override diff --git a/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java b/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java index 96afac4e65..a420afb02e 100644 --- a/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java +++ b/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java @@ -9,6 +9,7 @@ import javax.validation.constraints.Size; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -116,21 +117,16 @@ public boolean equals(final Object o) { return false; } final SubscriptionBase that = (SubscriptionBase) o; - return owningApplication.equals(that.owningApplication) - && eventTypes.equals(that.eventTypes) - && consumerGroup.equals(that.consumerGroup) - && readFrom.equals(that.readFrom) - && authorization.equals(that.authorization) - && initialCursors.equals(that.initialCursors); + return Objects.equals(owningApplication, that.owningApplication) + && Objects.equals(eventTypes, that.eventTypes) + && Objects.equals(consumerGroup, that.consumerGroup) + && Objects.equals(readFrom, that.readFrom) + && Objects.equals(authorization, that.authorization) + && Objects.equals(initialCursors, that.initialCursors); } @Override public int hashCode() { - int result = owningApplication != null ? owningApplication.hashCode() : 0; - result = 31 * result + (eventTypes != null ? eventTypes.hashCode() : 0); - result = 31 * result + (consumerGroup != null ? consumerGroup.hashCode() : 0); - result = 31 * result + (readFrom != null ? readFrom.hashCode() : 0); - result = 31 * result + (initialCursors != null ? initialCursors.hashCode() : 0); - return result; + return Objects.hash(owningApplication, eventTypes, consumerGroup, readFrom, initialCursors); } } From 37a86aae58cbcc6960f215b6a0c2a5259367af19 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Mon, 2 Jul 2018 11:33:51 +0200 Subject: [PATCH 024/176] ARUHA-1681 Fix npe in acceptance test --- .../java/org/zalando/nakadi/webservice/CursorsServiceAT.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java b/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java index 80bb809f76..5ce6b9716b 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java +++ b/src/acceptance-test/java/org/zalando/nakadi/webservice/CursorsServiceAT.java @@ -15,6 +15,7 @@ import org.zalando.nakadi.repository.TopicRepository; import org.zalando.nakadi.repository.db.SubscriptionDbRepository; import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; +import org.zalando.nakadi.service.AuthorizationValidator; import org.zalando.nakadi.service.CursorConverter; import org.zalando.nakadi.service.CursorsService; import org.zalando.nakadi.service.subscription.model.Partition; @@ -108,7 +109,8 @@ public void before() throws Exception { uuidGenerator = mock(UUIDGenerator.class); when(uuidGenerator.isUUID(any())).thenReturn(true); cursorsService = new CursorsService(subscriptionRepo, null, - mock(NakadiSettings.class), zkSubscriptionFactory, cursorConverter, uuidGenerator, null, null); + mock(NakadiSettings.class), zkSubscriptionFactory, cursorConverter, uuidGenerator, null, + mock(AuthorizationValidator.class)); // Register cursors in converter registerNakadiCursor(NakadiCursor.of(buildTimeline(etName, topic, CREATED_AT), P1, NEW_OFFSET)); From f4b028ac864b23d87ff7a419541f76e0c1b22473 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Fri, 13 Jul 2018 13:21:21 +0200 Subject: [PATCH 025/176] ARUHA-1681 Fix 500 for subscription modification --- .../controller/PostSubscriptionController.java | 3 +++ .../SubscriptionUpdateConflictException.java | 7 +++++++ .../service/subscription/SubscriptionService.java | 3 ++- .../SubscriptionValidationService.java | 14 ++++++++------ 4 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index b544a6ce7c..443885ecd1 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -23,6 +23,7 @@ import org.zalando.nakadi.exceptions.runtime.MyNakadiRuntimeException1; import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.SubscriptionUpdateConflictException; import org.zalando.nakadi.exceptions.runtime.TooManyPartitionsException; import org.zalando.nakadi.exceptions.runtime.WrongInitialCursorsException; import org.zalando.nakadi.plugin.api.ApplicationService; @@ -108,6 +109,8 @@ public ResponseEntity updateSubscription( try { subscriptionService.updateSubscription(subscriptionId, subscription); return ResponseEntity.noContent().build(); + } catch (final SubscriptionUpdateConflictException ex) { + return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, ex.getMessage(), request); } catch (final NoSuchSubscriptionException ex) { return Responses.create(ex.asProblem(), request); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java new file mode 100644 index 0000000000..ebe50acf0c --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java @@ -0,0 +1,7 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class SubscriptionUpdateConflictException extends MyNakadiRuntimeException1 { + public SubscriptionUpdateConflictException(final String message) { + super(message); + } +} diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java index 15e963f373..b91d105d2f 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java @@ -35,6 +35,7 @@ import org.zalando.nakadi.exceptions.runtime.NoSubscriptionException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; +import org.zalando.nakadi.exceptions.runtime.SubscriptionUpdateConflictException; import org.zalando.nakadi.exceptions.runtime.TooManyPartitionsException; import org.zalando.nakadi.exceptions.runtime.WrongInitialCursorsException; import org.zalando.nakadi.repository.EventTypeRepository; @@ -141,7 +142,7 @@ public Subscription createSubscription(final SubscriptionBase subscriptionBase) } public Subscription updateSubscription(final String subscriptionId, final SubscriptionBase newValue) - throws NoSuchSubscriptionException { + throws NoSuchSubscriptionException, SubscriptionUpdateConflictException { if (featureToggleService.isFeatureEnabled(FeatureToggleService.Feature.DISABLE_DB_WRITE_OPERATIONS)) { throw new DbWriteOperationsBlockedException("Cannot create subscription: write operations on DB " + "are blocked by feature flag."); diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java index af017e6c83..b36c160f2a 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java @@ -16,6 +16,7 @@ import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; +import org.zalando.nakadi.exceptions.runtime.SubscriptionUpdateConflictException; import org.zalando.nakadi.exceptions.runtime.TooManyPartitionsException; import org.zalando.nakadi.exceptions.runtime.WrongInitialCursorsException; import org.zalando.nakadi.exceptions.runtime.WrongStreamParametersException; @@ -83,21 +84,22 @@ public void validateSubscription(final SubscriptionBase subscription) authorizationValidator.validateAuthorization(subscription.getAuthorization()); } - public void validateSubscriptionChange(final Subscription old, final SubscriptionBase newValue) { + public void validateSubscriptionChange(final Subscription old, final SubscriptionBase newValue) + throws SubscriptionUpdateConflictException { if (!Objects.equals(newValue.getConsumerGroup(), old.getConsumerGroup())) { - throw new IllegalArgumentException("Not allowed to change subscription consumer group"); + throw new SubscriptionUpdateConflictException("Not allowed to change subscription consumer group"); } if (!Objects.equals(newValue.getEventTypes(), old.getEventTypes())) { - throw new IllegalArgumentException("Not allowed to change subscription event types"); + throw new SubscriptionUpdateConflictException("Not allowed to change subscription event types"); } if (!Objects.equals(newValue.getOwningApplication(), old.getOwningApplication())) { - throw new IllegalArgumentException("Not allowed to change owning application"); + throw new SubscriptionUpdateConflictException("Not allowed to change owning application"); } if (!Objects.equals(newValue.getReadFrom(), old.getReadFrom())) { - throw new IllegalArgumentException("Not allowed to change read from"); + throw new SubscriptionUpdateConflictException("Not allowed to change read from"); } if (!Objects.equals(newValue.getInitialCursors(), old.getInitialCursors())) { - throw new IllegalArgumentException("Not allowed to change initial cursors"); + throw new SubscriptionUpdateConflictException("Not allowed to change initial cursors"); } authorizationValidator.validateAuthorization(old.getAuthorization(), newValue.getAuthorization()); } From 3d8067339b90e4fabf658aaa21867dc1576cf8e2 Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Fri, 20 Jul 2018 06:07:23 +0200 Subject: [PATCH 026/176] Remove legacy feature toggles Remove legacy feature toggles to control the tech debit in order to not slowdown the development process. --- docker-compose.yml | 4 ---- .../nakadi/controller/EventStreamController.java | 13 +++++-------- .../nakadi/controller/EventTypeController.java | 7 ------- .../controller/PostSubscriptionController.java | 7 ------- .../nakadi/service/EventStreamWriterProvider.java | 11 ++--------- .../zalando/nakadi/service/EventTypeService.java | 6 +----- .../nakadi/service/FeatureToggleService.java | 4 ---- src/main/resources/application.yml | 8 -------- .../controller/EventTypeControllerTestCase.java | 2 -- 9 files changed, 8 insertions(+), 54 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index e9bc82d7c6..d5bfc3d793 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,10 +16,6 @@ services: - NAKADI_FEATURES_DEFAULT_FEATURES_DISABLE_EVENT_TYPE_CREATION - NAKADI_FEATURES_DEFAULT_FEATURES_DISABLE_EVENT_TYPE_DELETION - NAKADI_FEATURES_DEFAULT_FEATURES_DISABLE_SUBSCRIPTION_CREATION - - NAKADI_FEATURES_DEFAULT_FEATURES_CHECK_PARTITIONS_KEYS - - NAKADI_FEATURES_DEFAULT_FEATURES_CHECK_OWNING_APPLICATION - - NAKADI_FEATURES_DEFAULT_FEATURES_LIMIT_CONSUMERS_NUMBER - - NAKADI_FEATURES_DEFAULT_FEATURES_SEND_BATCH_VIA_OUTPUT_STREAM - NAKADI_FEATURES_DEFAULT_FEATURES_REMOTE_TOKENINFO - NAKADI_FEATURES_DEFAULT_FEATURES_KPI_COLLECTION - NAKADI_FEATURES_DEFAULT_FEATURES_DISABLE_DB_WRITE_OPERATIONS diff --git a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java index c6e15b47a1..25c994abd1 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java @@ -78,7 +78,6 @@ import static javax.ws.rs.core.Response.Status.PRECONDITION_FAILED; import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.zalando.nakadi.metrics.MetricUtils.metricNameFor; -import static org.zalando.nakadi.service.FeatureToggleService.Feature.LIMIT_CONSUMERS_NUMBER; @RestController public class EventStreamController { @@ -244,13 +243,11 @@ public StreamingResponseBody streamEvents( .build(); // acquire connection slots to limit the number of simultaneous connections from one client - if (featureToggleService.isFeatureEnabled(LIMIT_CONSUMERS_NUMBER)) { - final List partitions = streamConfig.getCursors().stream() - .map(NakadiCursor::getPartition) - .collect(Collectors.toList()); - connectionSlots = consumerLimitingService.acquireConnectionSlots( - client.getClientId(), eventTypeName, partitions); - } + final List partitions = streamConfig.getCursors().stream() + .map(NakadiCursor::getPartition) + .collect(Collectors.toList()); + connectionSlots = consumerLimitingService.acquireConnectionSlots( + client.getClientId(), eventTypeName, partitions); consumerCounter = metricRegistry.counter(metricNameFor(eventTypeName, CONSUMERS_COUNT_METRIC_NAME)); consumerCounter.inc(); diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index 7768e808f9..e0b825fa60 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -50,7 +50,6 @@ import java.util.List; import static org.springframework.http.ResponseEntity.status; -import static org.zalando.nakadi.service.FeatureToggleService.Feature.CHECK_OWNING_APPLICATION; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DISABLE_EVENT_TYPE_CREATION; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DISABLE_EVENT_TYPE_DELETION; @@ -96,12 +95,6 @@ public ResponseEntity create(@Valid @RequestBody final EventTypeBase eventTyp return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } - if (featureToggleService.isFeatureEnabled(CHECK_OWNING_APPLICATION) - && !applicationService.exists(eventType.getOwningApplication())) { - return Responses.create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, - "owning_application doesn't exist"), request); - } - if (errors.hasErrors()) { return Responses.create(new ValidationProblem(errors), request); } diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index c106062948..b1e9ceff1d 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -36,7 +36,6 @@ import javax.ws.rs.core.Response; import static org.springframework.http.HttpStatus.OK; -import static org.zalando.nakadi.service.FeatureToggleService.Feature.CHECK_OWNING_APPLICATION; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DISABLE_SUBSCRIPTION_CREATION; @@ -67,12 +66,6 @@ public ResponseEntity createOrGetSubscription(@Valid @RequestBody final Subsc return Responses.create(new ValidationProblem(errors), request); } - if (featureToggleService.isFeatureEnabled(CHECK_OWNING_APPLICATION) - && !applicationService.exists(subscriptionBase.getOwningApplication())) { - return Responses.create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, - "owning_application doesn't exist"), request); - } - try { return ok(subscriptionService.getExistingSubscription(subscriptionBase)); } catch (final NoSubscriptionException e) { diff --git a/src/main/java/org/zalando/nakadi/service/EventStreamWriterProvider.java b/src/main/java/org/zalando/nakadi/service/EventStreamWriterProvider.java index c18df9f966..6021766512 100644 --- a/src/main/java/org/zalando/nakadi/service/EventStreamWriterProvider.java +++ b/src/main/java/org/zalando/nakadi/service/EventStreamWriterProvider.java @@ -8,23 +8,16 @@ public class EventStreamWriterProvider { private final FeatureToggleService featureToggleService; private final EventStreamWriter binaryWriter; - private final EventStreamWriter stringWriter; @Autowired public EventStreamWriterProvider( final FeatureToggleService featureToggleService, - @Qualifier("binary") final EventStreamWriter binaryWriter, - @Qualifier("string") final EventStreamWriter stringWriter) { + @Qualifier("binary") final EventStreamWriter binaryWriter) { this.featureToggleService = featureToggleService; this.binaryWriter = binaryWriter; - this.stringWriter = stringWriter; } public EventStreamWriter getWriter() { - if (featureToggleService.isFeatureEnabled(FeatureToggleService.Feature.SEND_BATCH_VIA_OUTPUT_STREAM)) { - return binaryWriter; - } else { - return stringWriter; - } + return binaryWriter; } } diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index dda30c2c48..0b3ab246d1 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -71,7 +71,6 @@ import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; -import static org.zalando.nakadi.service.FeatureToggleService.Feature.CHECK_PARTITIONS_KEYS; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DELETE_EVENT_TYPE_WITH_SUBSCRIPTIONS; @Component @@ -506,10 +505,7 @@ private void validateSchema(final EventTypeBase eventType) throws InvalidEventTy throw new InvalidEventTypeException("\"metadata\" property is reserved"); } - if (featureToggleService.isFeatureEnabled(CHECK_PARTITIONS_KEYS)) { - validatePartitionKeys(schema, eventType); - } - + validatePartitionKeys(schema, eventType); validateOrderingKeys(schema, eventType); if (eventType.getCompatibilityMode() == CompatibilityMode.COMPATIBLE) { diff --git a/src/main/java/org/zalando/nakadi/service/FeatureToggleService.java b/src/main/java/org/zalando/nakadi/service/FeatureToggleService.java index 22a85d2a08..dd124c1e43 100644 --- a/src/main/java/org/zalando/nakadi/service/FeatureToggleService.java +++ b/src/main/java/org/zalando/nakadi/service/FeatureToggleService.java @@ -33,10 +33,6 @@ enum Feature { DISABLE_EVENT_TYPE_DELETION("disable_event_type_deletion"), DELETE_EVENT_TYPE_WITH_SUBSCRIPTIONS("delete_event_type_with_subscriptions"), DISABLE_SUBSCRIPTION_CREATION("disable_subscription_creation"), - CHECK_PARTITIONS_KEYS("check_partitions_keys"), - CHECK_OWNING_APPLICATION("check_owning_application"), - LIMIT_CONSUMERS_NUMBER("limit_consumers_number"), - SEND_BATCH_VIA_OUTPUT_STREAM("send_batch_via_output_stream"), REMOTE_TOKENINFO("remote_tokeninfo"), KPI_COLLECTION("kpi_collection"), DISABLE_DB_WRITE_OPERATIONS("disable_db_write_operations"), diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3ad5cb4d00..ec2a97ced3 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -144,10 +144,6 @@ nakadi: DISABLE_EVENT_TYPE_CREATION: false DISABLE_EVENT_TYPE_DELETION: false DISABLE_SUBSCRIPTION_CREATION: false - CHECK_PARTITIONS_KEYS: true - CHECK_OWNING_APPLICATION: false - LIMIT_CONSUMERS_NUMBER: true - SEND_BATCH_VIA_OUTPUT_STREAM: true REMOTE_TOKENINFO: true KPI_COLLECTION: false DISABLE_DB_WRITE_OPERATIONS: false @@ -172,10 +168,6 @@ nakadi.features.defaultFeatures: DISABLE_EVENT_TYPE_CREATION: false DISABLE_EVENT_TYPE_DELETION: false DISABLE_SUBSCRIPTION_CREATION: false - CHECK_PARTITIONS_KEYS: true - CHECK_OWNING_APPLICATION: true - LIMIT_CONSUMERS_NUMBER: true - SEND_BATCH_VIA_OUTPUT_STREAM: true REMOTE_TOKENINFO: true KPI_COLLECTION: false DISABLE_DB_WRITE_OPERATIONS: false diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java index cc09983bba..91ead44928 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java @@ -50,7 +50,6 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; -import static org.zalando.nakadi.service.FeatureToggleService.Feature.CHECK_PARTITIONS_KEYS; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DISABLE_EVENT_TYPE_DELETION; import static org.zalando.nakadi.util.PrincipalMockFactory.mockPrincipal; import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; @@ -114,7 +113,6 @@ public void init() throws Exception { doReturn(randomUUID).when(uuid).randomUUID(); doReturn(true).when(applicationService).exists(any()); - doReturn(true).when(featureToggleService).isFeatureEnabled(CHECK_PARTITIONS_KEYS); mockMvc = standaloneSetup(controller) .setMessageConverters(new StringHttpMessageConverter(), TestUtils.JACKSON_2_HTTP_MESSAGE_CONVERTER) From a1021fa4ef3ee19a3296f9625409010991864efc Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Sun, 22 Jul 2018 18:20:10 +0200 Subject: [PATCH 027/176] Remove as toggles set at staging & add changelog --- CHANGELOG.md | 3 ++ .../controller/EventStreamController.java | 9 +--- .../controller/EventTypeController.java | 5 ++ .../PostSubscriptionController.java | 5 ++ .../nakadi/service/EventTypeService.java | 11 ---- .../controller/EventTypeControllerTest.java | 51 ------------------- 6 files changed, 14 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae9fe13809..fdc248dad0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [2.8.1] +### Removed +- Removed Legacy Feature Toggles + ### Added - Log Compaction Feature Toggle diff --git a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java index 25c994abd1..5b66bef6a3 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java @@ -218,7 +218,7 @@ public StreamingResponseBody streamEvents( final AtomicBoolean connectionReady = closedConnectionsCrutch.listenForConnectionClose(request); Counter consumerCounter = null; EventStream eventStream = null; - List connectionSlots = ImmutableList.of(); + final List connectionSlots = ImmutableList.of(); final AtomicBoolean needCheckAuthorization = new AtomicBoolean(false); LOG.info("[X-NAKADI-CURSORS] \"{}\" {}", eventTypeName, Optional.ofNullable(cursorsStr).orElse("-")); @@ -242,13 +242,6 @@ public StreamingResponseBody streamEvents( .withMaxMemoryUsageBytes(maxMemoryUsageBytes) .build(); - // acquire connection slots to limit the number of simultaneous connections from one client - final List partitions = streamConfig.getCursors().stream() - .map(NakadiCursor::getPartition) - .collect(Collectors.toList()); - connectionSlots = consumerLimitingService.acquireConnectionSlots( - client.getClientId(), eventTypeName, partitions); - consumerCounter = metricRegistry.counter(metricNameFor(eventTypeName, CONSUMERS_COUNT_METRIC_NAME)); consumerCounter.inc(); diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index e0b825fa60..2cfbac3172 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -95,6 +95,11 @@ public ResponseEntity create(@Valid @RequestBody final EventTypeBase eventTyp return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } + if (!applicationService.exists(eventType.getOwningApplication())) { + return Responses.create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, + "owning_application doesn't exist"), request); + } + if (errors.hasErrors()) { return Responses.create(new ValidationProblem(errors), request); } diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index b1e9ceff1d..670044336a 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -66,6 +66,11 @@ public ResponseEntity createOrGetSubscription(@Valid @RequestBody final Subsc return Responses.create(new ValidationProblem(errors), request); } + if (!applicationService.exists(subscriptionBase.getOwningApplication())) { + return Responses.create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, + "owning_application doesn't exist"), request); + } + try { return ok(subscriptionService.getExistingSubscription(subscriptionBase)); } catch (final NoSubscriptionException e) { diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 0b3ab246d1..96b794e915 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -505,7 +505,6 @@ private void validateSchema(final EventTypeBase eventType) throws InvalidEventTy throw new InvalidEventTypeException("\"metadata\" property is reserved"); } - validatePartitionKeys(schema, eventType); validateOrderingKeys(schema, eventType); if (eventType.getCompatibilityMode() == CompatibilityMode.COMPATIBLE) { @@ -528,16 +527,6 @@ private void validateJsonSchemaConstraints(final JSONObject schema) throws Inval } } - private void validatePartitionKeys(final Schema schema, final EventTypeBase eventType) - throws InvalidEventTypeException, JSONException, SchemaException { - final List absentFields = eventType.getPartitionKeyFields().stream() - .filter(field -> !schema.definesProperty(convertToJSONPointer(field))) - .collect(Collectors.toList()); - if (!absentFields.isEmpty()) { - throw new InvalidEventTypeException("partition_key_fields " + absentFields + " absent in schema"); - } - } - private void validateOrderingKeys(final Schema schema, final EventTypeBase eventType) throws InvalidEventTypeException, JSONException, SchemaException { final List absentFields = eventType.getOrderingKeyFields().stream() diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java index 7888ec792f..80d5dd07ce 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java @@ -187,19 +187,6 @@ public void whenPOSTWithInvalidPartitionStrategyThen422() throws Exception { .andExpect(content().contentType("application/problem+json")); } - @Test - public void whenPUTWithInvalidPartitionStrategyThen422() throws Exception { - - final EventType eventType = EventTypeTestBuilder.builder() - .partitionKeyFields(Lists.newArrayList("invalid_key")).build(); - - doReturn(eventType).when(eventTypeRepository).findByName(any()); - - putEventType(eventType, eventType.getName()) - .andExpect(status().isUnprocessableEntity()) - .andExpect(content().contentType("application/problem+json")); - } - @Test public void whenPUTwithPartitionStrategyChangeFromRandomToUserDefinedThenOK() throws Exception { final EventType eventType = EventTypeTestBuilder.builder() @@ -571,18 +558,6 @@ public void whenDeleteEventTypeThatHasSubscriptionsThenConflict() throws Excepti .andExpect(content().string(matchesProblem(expectedProblem))); } - @Test - public void whenCreateEventTypeWithWrongPartitionKeyFieldsThen422() throws Exception { - - final EventType eventType = EventTypeTestBuilder.builder() - .partitionKeyFields(Collections.singletonList("blabla")).build(); - - doReturn(eventType).when(eventTypeRepository).findByName(eventType.getName()); - - postEventType(eventType).andExpect(status().isUnprocessableEntity()) - .andExpect(content().contentType("application/problem+json")); - } - @Test public void whenCreateEventTypeWithUnknownApplicationThen422() throws Exception { @@ -597,32 +572,6 @@ public void whenCreateEventTypeWithUnknownApplicationThen422() throws Exception .andExpect(content().contentType("application/problem+json")); } - @Test - public void whenPUTEventTypeWithWrongPartitionKeyFieldsThen422() throws Exception { - - final EventType eventType = EventTypeTestBuilder.builder() - .partitionKeyFields(Collections.singletonList("blabla")).build(); - - doReturn(eventType).when(eventTypeRepository).findByName(eventType.getName()); - - putEventType(eventType, eventType.getName()).andExpect(status().isUnprocessableEntity()) - .andExpect(content().contentType("application/problem+json")); - } - - @Test - public void whenPUTEventTypeWithWrongPartitionKeyToBusinessCategoryFieldsThen422() throws Exception { - - final EventType eventType = EventTypeTestBuilder.builder() - .partitionKeyFields(Collections.singletonList("blabla")) - .category(BUSINESS) - .build(); - - doReturn(eventType).when(eventTypeRepository).findByName(eventType.getName()); - - putEventType(eventType, eventType.getName()).andExpect(status().isUnprocessableEntity()) - .andExpect(content().contentType("application/problem+json")); - } - @Test public void whenDeleteEventTypeAndNakadiExceptionThen500() throws Exception { From a76b82d8fef7e9b9ba1022b34e96b448ef319153 Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Sun, 22 Jul 2018 19:34:43 +0200 Subject: [PATCH 028/176] Remove tests for toggle to check owning app --- .../nakadi/controller/EventTypeController.java | 5 ----- .../controller/PostSubscriptionController.java | 5 ----- .../nakadi/controller/EventTypeControllerTest.java | 14 -------------- .../controller/PostSubscriptionControllerTest.java | 10 ---------- 4 files changed, 34 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index 2cfbac3172..e0b825fa60 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -95,11 +95,6 @@ public ResponseEntity create(@Valid @RequestBody final EventTypeBase eventTyp return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED); } - if (!applicationService.exists(eventType.getOwningApplication())) { - return Responses.create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, - "owning_application doesn't exist"), request); - } - if (errors.hasErrors()) { return Responses.create(new ValidationProblem(errors), request); } diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index 670044336a..b1e9ceff1d 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -66,11 +66,6 @@ public ResponseEntity createOrGetSubscription(@Valid @RequestBody final Subsc return Responses.create(new ValidationProblem(errors), request); } - if (!applicationService.exists(subscriptionBase.getOwningApplication())) { - return Responses.create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, - "owning_application doesn't exist"), request); - } - try { return ok(subscriptionService.getExistingSubscription(subscriptionBase)); } catch (final NoSubscriptionException e) { diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java index 80d5dd07ce..64fd0bf310 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java @@ -558,20 +558,6 @@ public void whenDeleteEventTypeThatHasSubscriptionsThenConflict() throws Excepti .andExpect(content().string(matchesProblem(expectedProblem))); } - @Test - public void whenCreateEventTypeWithUnknownApplicationThen422() throws Exception { - - doReturn(false).when(applicationService).exists(any()); - - final EventType eventType = EventTypeTestBuilder.builder() - .partitionKeyFields(Collections.singletonList("blabla")).build(); - - doReturn(eventType).when(eventTypeRepository).findByName(eventType.getName()); - - postEventType(eventType).andExpect(status().isUnprocessableEntity()) - .andExpect(content().contentType("application/problem+json")); - } - @Test public void whenDeleteEventTypeAndNakadiExceptionThen500() throws Exception { diff --git a/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java b/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java index 3c91da81d0..14a6ee80a9 100644 --- a/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java @@ -114,16 +114,6 @@ public void whenPostValidSubscriptionThenOk() throws Exception { .andExpect(header().string("Content-Location", "/subscriptions/123")); } - @Test - public void whenCreateSubscriptionWithUnknownApplicationThenUnprocessableEntity() throws Exception { - final SubscriptionBase subscriptionBase = builder().buildSubscriptionBase(); - when(applicationService.exists(any())).thenReturn(false); - - postSubscription(subscriptionBase) - .andExpect(status().isUnprocessableEntity()) - .andExpect(content().contentTypeCompatibleWith("application/problem+json")); - } - @Test public void whenCreateSubscriptionWithEmptyConsumerGroupThenUnprocessableEntity() throws Exception { final SubscriptionBase subscriptionBase = builder() From 6ec43afa66e7aa8484a56e1ec0432e56ad115f90 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 23 Jul 2018 09:52:25 +0200 Subject: [PATCH 029/176] Upgrade Kafka client to 1.1.1 --- CHANGELOG.md | 2 +- build.gradle | 4 ++-- docker-compose.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae9fe13809..d35a25dde8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Log Compaction Feature Toggle ### Changed -- Upgraded Kafka client to 1.1.0 +- Upgraded Kafka client to 1.1.1 ## [2.8.0] diff --git a/build.gradle b/build.gradle index 38089b0379..d03dc91c84 100644 --- a/build.gradle +++ b/build.gradle @@ -137,8 +137,8 @@ dependencies { compile 'org.echocat.jomon:runtime:1.6.3' // kafka & zookeeper - compile 'org.apache.kafka:kafka-clients:1.1.0' - compile('org.apache.kafka:kafka_2.12:1.1.0') { + compile 'org.apache.kafka:kafka-clients:1.1.1' + compile('org.apache.kafka:kafka_2.12:1.1.1') { exclude module: "zookeeper" } compile("org.apache.curator:curator-recipes:$curatorVersion") { diff --git a/docker-compose.yml b/docker-compose.yml index e9bc82d7c6..99b69c48e7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -49,7 +49,7 @@ services: - "2181:2181" kafka: - image: wurstmeister/kafka:1.1.0 + image: wurstmeister/kafka:1.1.1 network_mode: "host" ports: - "9092:9092" From 56c8d5ac987c062697af86a7e9cdcedf71b05671 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 23 Jul 2018 10:11:57 +0200 Subject: [PATCH 030/176] wurstmeister haven't published a docker image for kafka 1.1.1 yet --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 99b69c48e7..e9bc82d7c6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -49,7 +49,7 @@ services: - "2181:2181" kafka: - image: wurstmeister/kafka:1.1.1 + image: wurstmeister/kafka:1.1.0 network_mode: "host" ports: - "9092:9092" From d69f065b23b736d49e061f849718733d63a6c6e8 Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Mon, 23 Jul 2018 13:34:39 +0200 Subject: [PATCH 031/176] Check partition keys and remove toggle --- .../nakadi/service/EventTypeService.java | 11 ++++ .../controller/EventTypeControllerTest.java | 51 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 96b794e915..0b3ab246d1 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -505,6 +505,7 @@ private void validateSchema(final EventTypeBase eventType) throws InvalidEventTy throw new InvalidEventTypeException("\"metadata\" property is reserved"); } + validatePartitionKeys(schema, eventType); validateOrderingKeys(schema, eventType); if (eventType.getCompatibilityMode() == CompatibilityMode.COMPATIBLE) { @@ -527,6 +528,16 @@ private void validateJsonSchemaConstraints(final JSONObject schema) throws Inval } } + private void validatePartitionKeys(final Schema schema, final EventTypeBase eventType) + throws InvalidEventTypeException, JSONException, SchemaException { + final List absentFields = eventType.getPartitionKeyFields().stream() + .filter(field -> !schema.definesProperty(convertToJSONPointer(field))) + .collect(Collectors.toList()); + if (!absentFields.isEmpty()) { + throw new InvalidEventTypeException("partition_key_fields " + absentFields + " absent in schema"); + } + } + private void validateOrderingKeys(final Schema schema, final EventTypeBase eventType) throws InvalidEventTypeException, JSONException, SchemaException { final List absentFields = eventType.getOrderingKeyFields().stream() diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java index 64fd0bf310..8d78acb26c 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java @@ -187,6 +187,19 @@ public void whenPOSTWithInvalidPartitionStrategyThen422() throws Exception { .andExpect(content().contentType("application/problem+json")); } + @Test + public void whenPUTWithInvalidPartitionStrategyThen422() throws Exception { + + final EventType eventType = EventTypeTestBuilder.builder() + .partitionKeyFields(Lists.newArrayList("invalid_key")).build(); + + doReturn(eventType).when(eventTypeRepository).findByName(any()); + + putEventType(eventType, eventType.getName()) + .andExpect(status().isUnprocessableEntity()) + .andExpect(content().contentType("application/problem+json")); + } + @Test public void whenPUTwithPartitionStrategyChangeFromRandomToUserDefinedThenOK() throws Exception { final EventType eventType = EventTypeTestBuilder.builder() @@ -558,6 +571,44 @@ public void whenDeleteEventTypeThatHasSubscriptionsThenConflict() throws Excepti .andExpect(content().string(matchesProblem(expectedProblem))); } + @Test + public void whenCreateEventTypeWithWrongPartitionKeyFieldsThen422() throws Exception { + + final EventType eventType = EventTypeTestBuilder.builder() + .partitionKeyFields(Collections.singletonList("blabla")).build(); + + doReturn(eventType).when(eventTypeRepository).findByName(eventType.getName()); + + postEventType(eventType).andExpect(status().isUnprocessableEntity()) + .andExpect(content().contentType("application/problem+json")); + } + + @Test + public void whenPUTEventTypeWithWrongPartitionKeyFieldsThen422() throws Exception { + + final EventType eventType = EventTypeTestBuilder.builder() + .partitionKeyFields(Collections.singletonList("blabla")).build(); + + doReturn(eventType).when(eventTypeRepository).findByName(eventType.getName()); + + putEventType(eventType, eventType.getName()).andExpect(status().isUnprocessableEntity()) + .andExpect(content().contentType("application/problem+json")); + } + + @Test + public void whenPUTEventTypeWithWrongPartitionKeyToBusinessCategoryFieldsThen422() throws Exception { + + final EventType eventType = EventTypeTestBuilder.builder() + .partitionKeyFields(Collections.singletonList("blabla")) + .category(BUSINESS) + .build(); + + doReturn(eventType).when(eventTypeRepository).findByName(eventType.getName()); + + putEventType(eventType, eventType.getName()).andExpect(status().isUnprocessableEntity()) + .andExpect(content().contentType("application/problem+json")); + } + @Test public void whenDeleteEventTypeAndNakadiExceptionThen500() throws Exception { From d68ea7961d3b2886ba5c944032c93316c62d164b Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Mon, 23 Jul 2018 13:59:27 +0200 Subject: [PATCH 032/176] Remove EventStreamWriterProvider, EventStreamWriterString classes Remove the EventStreamWriterProvider class and use binary writer --- .../zalando/nakadi/service/EventStream.java | 9 +-- .../nakadi/service/EventStreamFactory.java | 9 +-- .../service/EventStreamWriterProvider.java | 23 ------ .../service/EventStreamWriterString.java | 70 ------------------- .../SubscriptionStreamerFactory.java | 10 +-- .../nakadi/service/EventStreamTest.java | 39 ++++------- 6 files changed, 29 insertions(+), 131 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/service/EventStreamWriterProvider.java delete mode 100644 src/main/java/org/zalando/nakadi/service/EventStreamWriterString.java diff --git a/src/main/java/org/zalando/nakadi/service/EventStream.java b/src/main/java/org/zalando/nakadi/service/EventStream.java index b3edc30164..120d1c9f1f 100644 --- a/src/main/java/org/zalando/nakadi/service/EventStream.java +++ b/src/main/java/org/zalando/nakadi/service/EventStream.java @@ -6,6 +6,7 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Qualifier; import org.zalando.nakadi.domain.ConsumedEvent; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.metrics.StreamKpiData; @@ -36,7 +37,7 @@ public class EventStream { private final BlacklistService blacklistService; private final CursorConverter cursorConverter; private final Meter bytesFlushedMeter; - private final EventStreamWriterProvider writer; + private final EventStreamWriter eventStreamWriter; private final StreamKpiData kpiData; private final String kpiDataStreamedEventType; private final long kpiFrequencyMs; @@ -47,7 +48,7 @@ public EventStream(final EventConsumer eventConsumer, final EventStreamConfig config, final BlacklistService blacklistService, final CursorConverter cursorConverter, final Meter bytesFlushedMeter, - final EventStreamWriterProvider writer, + @Qualifier("binary") final EventStreamWriter eventStreamWriter, final NakadiKpiPublisher kpiPublisher, final String kpiDataStreamedEventType, final long kpiFrequencyMs) { this.eventConsumer = eventConsumer; @@ -56,7 +57,7 @@ public EventStream(final EventConsumer eventConsumer, this.blacklistService = blacklistService; this.cursorConverter = cursorConverter; this.bytesFlushedMeter = bytesFlushedMeter; - this.writer = writer; + this.eventStreamWriter = eventStreamWriter; this.kpiPublisher = kpiPublisher; this.kpiData = new StreamKpiData(); this.kpiDataStreamedEventType = kpiDataStreamedEventType; @@ -224,7 +225,7 @@ private Map createMapWithPartitionKeys(final Function private void sendBatch(final NakadiCursor topicPosition, final List currentBatch) throws IOException { - final int bytesWritten = writer.getWriter() + final int bytesWritten = eventStreamWriter .writeBatch(outputStream, cursorConverter.convert(topicPosition), currentBatch); bytesFlushedMeter.mark(bytesWritten); kpiData.addBytesSent(bytesWritten); diff --git a/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java b/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java index aa65ea0190..58c92071c4 100644 --- a/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java +++ b/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java @@ -2,6 +2,7 @@ import com.codahale.metrics.Meter; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.zalando.nakadi.exceptions.InvalidCursorException; @@ -14,7 +15,7 @@ public class EventStreamFactory { private final CursorConverter cursorConverter; - private final EventStreamWriterProvider writerProvider; + private final EventStreamWriter eventStreamWriter; private final BlacklistService blacklistService; private final NakadiKpiPublisher nakadiKpiPublisher; private final String kpiDataStreamedEventType; @@ -23,13 +24,13 @@ public class EventStreamFactory { @Autowired public EventStreamFactory( final CursorConverter cursorConverter, - final EventStreamWriterProvider writerProvider, + @Qualifier("binary") final EventStreamWriter eventStreamWriter, final BlacklistService blacklistService, final NakadiKpiPublisher nakadiKpiPublisher, @Value("${nakadi.kpi.event-types.nakadiDataStreamed}") final String kpiDataStreamedEventType, @Value("${nakadi.kpi.config.stream-data-collection-frequency-ms}") final long kpiFrequencyMs) { this.cursorConverter = cursorConverter; - this.writerProvider = writerProvider; + this.eventStreamWriter = eventStreamWriter; this.blacklistService = blacklistService; this.nakadiKpiPublisher = nakadiKpiPublisher; this.kpiDataStreamedEventType = kpiDataStreamedEventType; @@ -46,7 +47,7 @@ public EventStream createEventStream(final OutputStream outputStream, final Even blacklistService, cursorConverter, bytesFlushedMeter, - writerProvider, + eventStreamWriter, nakadiKpiPublisher, kpiDataStreamedEventType, kpiFrequencyMs); diff --git a/src/main/java/org/zalando/nakadi/service/EventStreamWriterProvider.java b/src/main/java/org/zalando/nakadi/service/EventStreamWriterProvider.java deleted file mode 100644 index 6021766512..0000000000 --- a/src/main/java/org/zalando/nakadi/service/EventStreamWriterProvider.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.zalando.nakadi.service; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; - -@Component -public class EventStreamWriterProvider { - private final FeatureToggleService featureToggleService; - private final EventStreamWriter binaryWriter; - - @Autowired - public EventStreamWriterProvider( - final FeatureToggleService featureToggleService, - @Qualifier("binary") final EventStreamWriter binaryWriter) { - this.featureToggleService = featureToggleService; - this.binaryWriter = binaryWriter; - } - - public EventStreamWriter getWriter() { - return binaryWriter; - } -} diff --git a/src/main/java/org/zalando/nakadi/service/EventStreamWriterString.java b/src/main/java/org/zalando/nakadi/service/EventStreamWriterString.java deleted file mode 100644 index 87e710f859..0000000000 --- a/src/main/java/org/zalando/nakadi/service/EventStreamWriterString.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.zalando.nakadi.service; - -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.stereotype.Component; -import org.zalando.nakadi.domain.ConsumedEvent; -import org.zalando.nakadi.view.Cursor; -import org.zalando.nakadi.view.SubscriptionCursor; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.List; -import java.util.Optional; - -import static com.google.common.base.Charsets.UTF_8; - -@Component -@Qualifier("string") -public class EventStreamWriterString implements EventStreamWriter { - - @Override - public int writeSubscriptionBatch(final OutputStream os, final SubscriptionCursor cursor, - final List events, - final Optional metadata) throws IOException { - final StringBuilder builder = new StringBuilder() - .append("{\"cursor\":{\"partition\":\"").append(cursor.getPartition()) - .append("\",\"offset\":\"").append(cursor.getOffset()) - .append("\",\"event_type\":\"").append(cursor.getEventType()) - .append("\",\"cursor_token\":\"").append(cursor.getCursorToken()) - .append("\"}"); - if (!events.isEmpty()) { - builder.append(",\"events\":["); - events.forEach(event -> builder.append(new String(event.getEvent())).append(",")); - builder.deleteCharAt(builder.length() - 1).append("]"); - } - metadata.ifPresent(s -> builder.append(",\"info\":{\"debug\":\"").append(s).append("\"}")); - builder.append("}").append(BATCH_SEPARATOR); - - final String eventsString = builder.toString(); - - final byte[] batchBytes = eventsString.getBytes(UTF_8); - os.write(batchBytes); - - os.flush(); - - return batchBytes.length; - } - - @Override - public int writeBatch(final OutputStream os, final Cursor cursor, final List events) throws IOException { - final StringBuilder builder = new StringBuilder() - .append("{\"cursor\":{\"partition\":\"").append(cursor.getPartition()) - .append("\",\"offset\":\"").append(cursor.getOffset()).append("\"}"); - if (!events.isEmpty()) { - builder.append(",\"events\":["); - events.forEach(event -> builder.append(new String(event)).append(",")); - builder.deleteCharAt(builder.length() - 1).append("]"); - } - - builder.append("}").append(BATCH_SEPARATOR); - - final String eventsString = builder.toString(); - - final byte[] batchBytes = eventsString.getBytes(UTF_8); - os.write(batchBytes); - - os.flush(); - - return batchBytes.length; - } -} diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java index e6249fcea3..3437b429a4 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java @@ -14,7 +14,7 @@ import org.zalando.nakadi.service.BlacklistService; import org.zalando.nakadi.service.CursorConverter; import org.zalando.nakadi.service.CursorTokenService; -import org.zalando.nakadi.service.EventStreamWriterProvider; +import org.zalando.nakadi.service.EventStreamWriter; import org.zalando.nakadi.service.EventTypeChangeListener; import org.zalando.nakadi.service.NakadiCursorComparator; import org.zalando.nakadi.service.NakadiKpiPublisher; @@ -37,7 +37,7 @@ public class SubscriptionStreamerFactory { private final CursorConverter cursorConverter; private final MetricRegistry metricRegistry; private final SubscriptionClientFactory zkClientFactory; - private final EventStreamWriterProvider eventStreamWriterProvider; + private final EventStreamWriter eventStreamWriter; private final AuthorizationValidator authorizationValidator; private final EventTypeChangeListener eventTypeChangeListener; private final EventTypeCache eventTypeCache; @@ -54,7 +54,7 @@ public SubscriptionStreamerFactory( final CursorConverter cursorConverter, @Qualifier("streamMetricsRegistry") final MetricRegistry metricRegistry, final SubscriptionClientFactory zkClientFactory, - final EventStreamWriterProvider eventStreamWriterProvider, + @Qualifier("binary") final EventStreamWriter eventStreamWriter, final AuthorizationValidator authorizationValidator, final EventTypeChangeListener eventTypeChangeListener, final EventTypeCache eventTypeCache, @@ -68,7 +68,7 @@ public SubscriptionStreamerFactory( this.cursorConverter = cursorConverter; this.metricRegistry = metricRegistry; this.zkClientFactory = zkClientFactory; - this.eventStreamWriterProvider = eventStreamWriterProvider; + this.eventStreamWriter = eventStreamWriter; this.authorizationValidator = authorizationValidator; this.eventTypeChangeListener = eventTypeChangeListener; this.eventTypeCache = eventTypeCache; @@ -106,7 +106,7 @@ public SubscriptionStreamer build( .setSubscription(subscription) .setMetricRegistry(metricRegistry) .setTimelineService(timelineService) - .setWriter(eventStreamWriterProvider.getWriter()) + .setWriter(eventStreamWriter) .setAuthorizationValidator(authorizationValidator) .setEventTypeChangeListener(eventTypeChangeListener) .setCursorComparator(new NakadiCursorComparator(eventTypeCache)) diff --git a/src/test/java/org/zalando/nakadi/service/EventStreamTest.java b/src/test/java/org/zalando/nakadi/service/EventStreamTest.java index 3cb06e8390..d269c5fe3e 100644 --- a/src/test/java/org/zalando/nakadi/service/EventStreamTest.java +++ b/src/test/java/org/zalando/nakadi/service/EventStreamTest.java @@ -8,7 +8,6 @@ import org.json.JSONArray; import org.json.JSONObject; import org.junit.Assert; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.zalando.nakadi.domain.ConsumedEvent; @@ -69,7 +68,7 @@ public class EventStreamTest { private static final Timeline TIMELINE = buildTimelineWithTopic(TOPIC); private static CursorConverter cursorConverter; - private static EventStreamWriterProvider writerProvider; + private static EventStreamWriter eventStreamWriter = new EventStreamWriterBinary(); private final NakadiKpiPublisher kpiPublisher = mock(NakadiKpiPublisher.class); private final String kpiEventType = "nakadi.data.streamed"; @@ -80,16 +79,6 @@ public static void setupMocks() { final TimelineService timelineService = mock(TimelineService.class); final EventTypeCache eventTypeCache = mock(EventTypeCache.class); cursorConverter = new CursorConverterImpl(eventTypeCache, timelineService); - writerProvider = mock(EventStreamWriterProvider.class); - } - - @Before - public void setupWriter() { - when(writerProvider.getWriter()).thenReturn(createWriter()); - } - - protected EventStreamWriter createWriter() { - return new EventStreamWriterBinary(); } @Test(timeout = 15000) @@ -104,7 +93,7 @@ public void whenIOExceptionThenStreamIsClosed() throws NakadiException, Interrup final OutputStream outputStreamMock = mock(OutputStream.class); final EventStream eventStream = new EventStream( emptyConsumer(), outputStreamMock, config, mock(BlacklistService.class), cursorConverter, - BYTES_FLUSHED_METER, writerProvider, kpiPublisher, kpiEventType, kpiFrequencyMs); + BYTES_FLUSHED_METER, eventStreamWriter, kpiPublisher, kpiEventType, kpiFrequencyMs); final Thread thread = new Thread(() -> eventStream.streamEvents(new AtomicBoolean(true), () -> { })); @@ -132,7 +121,7 @@ public void whenCrutchWorkedThenStreamIsClosed() throws NakadiException, Interru .build(); final EventStream eventStream = new EventStream( emptyConsumer(), mock(OutputStream.class), config, mock(BlacklistService.class), cursorConverter, - BYTES_FLUSHED_METER, writerProvider, kpiPublisher, kpiEventType, kpiFrequencyMs); + BYTES_FLUSHED_METER, eventStreamWriter, kpiPublisher, kpiEventType, kpiFrequencyMs); final AtomicBoolean streamOpen = new AtomicBoolean(true); final Thread thread = new Thread(() -> eventStream.streamEvents(streamOpen, () -> { })); @@ -160,7 +149,7 @@ public void whenAuthorizationChangedStreamClosed() throws NakadiException, Inter .build(); final EventStream eventStream = new EventStream( emptyConsumer(), mock(OutputStream.class), config, mock(BlacklistService.class), cursorConverter, - BYTES_FLUSHED_METER, writerProvider, kpiPublisher, kpiEventType, kpiFrequencyMs); + BYTES_FLUSHED_METER, eventStreamWriter, kpiPublisher, kpiEventType, kpiFrequencyMs); final AtomicBoolean triggerAuthChange = new AtomicBoolean(false); final AtomicBoolean accessDeniedTriggered = new AtomicBoolean(false); final Thread thread = new Thread(() -> { @@ -203,7 +192,7 @@ public void whenStreamTimeoutIsSetThenStreamIsClosed() throws NakadiException, I .build(); final EventStream eventStream = new EventStream( emptyConsumer(), mock(OutputStream.class), config, mock(BlacklistService.class), cursorConverter, - BYTES_FLUSHED_METER, writerProvider, kpiPublisher, kpiEventType, kpiFrequencyMs); + BYTES_FLUSHED_METER, eventStreamWriter, kpiPublisher, kpiEventType, kpiFrequencyMs); eventStream.streamEvents(new AtomicBoolean(true), () -> { }); // if something goes wrong - the test should fail with a timeout @@ -219,7 +208,7 @@ public void whenStreamLimitIsSetThenStreamIsClosed() throws NakadiException, IOE .withConsumingClient(mock(Client.class)) .build(); final EventStream eventStream = new EventStream(endlessDummyConsumer(), mock(OutputStream.class), config, - mock(BlacklistService.class), cursorConverter, BYTES_FLUSHED_METER, writerProvider, kpiPublisher, + mock(BlacklistService.class), cursorConverter, BYTES_FLUSHED_METER, eventStreamWriter, kpiPublisher, kpiEventType, kpiFrequencyMs); eventStream.streamEvents(new AtomicBoolean(true), () -> { }); @@ -238,7 +227,7 @@ public void whenKeepAliveLimitIsSetThenStreamIsClosed() throws NakadiException, .build(); final EventStream eventStream = new EventStream( emptyConsumer(), mock(OutputStream.class), config, mock(BlacklistService.class), cursorConverter, - BYTES_FLUSHED_METER, writerProvider, kpiPublisher, kpiEventType, kpiFrequencyMs); + BYTES_FLUSHED_METER, eventStreamWriter, kpiPublisher, kpiEventType, kpiFrequencyMs); eventStream.streamEvents(new AtomicBoolean(true), () -> { }); // if something goes wrong - the test should fail with a timeout @@ -259,7 +248,7 @@ public void whenNoEventsToReadThenKeepAliveIsSent() throws NakadiException, IOEx final EventStream eventStream = new EventStream( emptyConsumer(), out, config, mock(BlacklistService.class), cursorConverter, BYTES_FLUSHED_METER, - writerProvider, kpiPublisher, kpiEventType, kpiFrequencyMs); + eventStreamWriter, kpiPublisher, kpiEventType, kpiFrequencyMs); eventStream.streamEvents(new AtomicBoolean(true), () -> { }); @@ -286,7 +275,7 @@ public void whenBatchSizeIsSetThenGetEventsInBatches() throws NakadiException, I final EventStream eventStream = new EventStream( nCountDummyConsumerForPartition(12, "0"), out, config, mock(BlacklistService.class), - cursorConverter, BYTES_FLUSHED_METER, writerProvider, kpiPublisher, kpiEventType, kpiFrequencyMs); + cursorConverter, BYTES_FLUSHED_METER, eventStreamWriter, kpiPublisher, kpiEventType, kpiFrequencyMs); eventStream.streamEvents(new AtomicBoolean(true), () -> { }); @@ -324,7 +313,7 @@ public void whenReadingEventsTheOrderIsCorrect() throws NakadiException, IOExcep final EventStream eventStream = new EventStream(predefinedConsumer(events), out, config, mock(BlacklistService.class), cursorConverter, - BYTES_FLUSHED_METER, writerProvider, kpiPublisher, kpiEventType, kpiFrequencyMs); + BYTES_FLUSHED_METER, eventStreamWriter, kpiPublisher, kpiEventType, kpiFrequencyMs); eventStream.streamEvents(new AtomicBoolean(true), () -> { }); @@ -369,7 +358,7 @@ public void whenReadFromMultiplePartitionsThenGroupedInBatchesAccordingToPartiti final EventStream eventStream = new EventStream(predefinedConsumer(events), out, config, mock(BlacklistService.class), cursorConverter, - BYTES_FLUSHED_METER, writerProvider, kpiPublisher, kpiEventType, kpiFrequencyMs); + BYTES_FLUSHED_METER, eventStreamWriter, kpiPublisher, kpiEventType, kpiFrequencyMs); eventStream.streamEvents(new AtomicBoolean(true), () -> { }); @@ -466,7 +455,7 @@ public void testWriteStreamEvent() { "{\"e\":\"f\"}".getBytes()); try { - writerProvider.getWriter().writeBatch(baos, cursor, events); + eventStreamWriter.writeBatch(baos, cursor, events); final Map batch = TestUtils.OBJECT_MAPPER.readValue(baos.toString(), new TypeReference>() { }); @@ -497,7 +486,7 @@ public void testWriteStreamEventEmptyBatchProducesNoEventArray() { final ArrayList events = Lists.newArrayList(); try { - writerProvider.getWriter().writeBatch(baos, cursor, events); + eventStreamWriter.writeBatch(baos, cursor, events); final String json = baos.toString(); assertEquals("{\"cursor\":{\"partition\":\"11\",\"offset\":\"000000000000000012\"}}\n", json); @@ -527,7 +516,7 @@ public void testWriteStreamInfoWhenPresent() { new ConsumedEvent("{\"a\":\"b\"}".getBytes(), mock(NakadiCursor.class), 0)); try { - writerProvider.getWriter().writeSubscriptionBatch(baos, cursor, events, Optional.of("something")); + eventStreamWriter.writeSubscriptionBatch(baos, cursor, events, Optional.of("something")); final JSONObject batch = new JSONObject(baos.toString()); final JSONObject cursorM = batch.getJSONObject("cursor"); From 244f73d3cb68444076f9933c2b4e935358f84135 Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Mon, 23 Jul 2018 15:53:55 +0200 Subject: [PATCH 033/176] Remove ConsumerLimitingService and related code --- .../job/ConsumerLimitingCleaningJobAT.java | 73 ------ .../webservice/ConsumerLimitingServiceAT.java | 112 ---------- .../controller/EventStreamController.java | 8 - .../service/ConsumerLimitingService.java | 209 ------------------ .../job/ConsumerLimitingCleaningJob.java | 58 ----- .../controller/EventStreamControllerTest.java | 6 +- 6 files changed, 1 insertion(+), 465 deletions(-) delete mode 100644 src/acceptance-test/java/org/zalando/nakadi/service/job/ConsumerLimitingCleaningJobAT.java delete mode 100644 src/acceptance-test/java/org/zalando/nakadi/webservice/ConsumerLimitingServiceAT.java delete mode 100644 src/main/java/org/zalando/nakadi/service/ConsumerLimitingService.java delete mode 100644 src/main/java/org/zalando/nakadi/service/job/ConsumerLimitingCleaningJob.java diff --git a/src/acceptance-test/java/org/zalando/nakadi/service/job/ConsumerLimitingCleaningJobAT.java b/src/acceptance-test/java/org/zalando/nakadi/service/job/ConsumerLimitingCleaningJobAT.java deleted file mode 100644 index 2adf8f1398..0000000000 --- a/src/acceptance-test/java/org/zalando/nakadi/service/job/ConsumerLimitingCleaningJobAT.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.zalando.nakadi.service.job; - -import org.apache.curator.framework.CuratorFramework; -import org.apache.zookeeper.KeeperException; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; -import org.zalando.nakadi.repository.zookeeper.ZooKeeperLockFactory; -import org.zalando.nakadi.service.ConsumerLimitingService; -import org.zalando.nakadi.webservice.BaseAT; -import org.zalando.nakadi.webservice.utils.ZookeeperTestUtils; - -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class ConsumerLimitingCleaningJobAT extends BaseAT { - - private static final CuratorFramework CURATOR = ZookeeperTestUtils.createCurator(ZOOKEEPER_URL); - - private ConsumerLimitingCleaningJob cleaningService; - - public ConsumerLimitingCleaningJobAT() { - final ZooKeeperHolder zkHolder = mock(ZooKeeperHolder.class); - when(zkHolder.get()).thenReturn(CURATOR); - final ZooKeeperLockFactory zkLockFactory = new ZooKeeperLockFactory(zkHolder); - final ConsumerLimitingService limitingService = new ConsumerLimitingService(zkHolder, zkLockFactory, 5); - - final JobWrapperFactory jobWrapperFactory = mock(JobWrapperFactory.class); - final ExclusiveJobWrapper jobWrapper = DummyJobWrapper.create(); - when(jobWrapperFactory.createExclusiveJobWrapper(any(), anyLong())).thenReturn(jobWrapper); - - cleaningService = new ConsumerLimitingCleaningJob(zkHolder, jobWrapperFactory, limitingService, 0); - } - - @Before - public void before() throws Exception { - deleteConsumersData(); - - // "hanging" node - CURATOR.create().creatingParentsIfNeeded().forPath("/nakadi/consumers/connections/hanging"); - - // "normal" node with child - CURATOR.create().creatingParentsIfNeeded().forPath("/nakadi/consumers/connections/normal/some_child"); - } - - @After - public void deleteConsumersData() throws Exception { - try { - CURATOR.delete().deletingChildrenIfNeeded().forPath("/nakadi/consumers"); - } catch (final KeeperException.NoNodeException e) { - // this is fine - } - } - - @Test - public void whenCleanThenOk() throws Exception { - cleaningService.cleanHangingNodes(); - - assertThat("the 'hanging' node should be deleted", - CURATOR.checkExists().forPath("/nakadi/consumers/connections/hanging"), - nullValue()); - assertThat("node with children nodes should not be deleted", - CURATOR.checkExists().forPath("/nakadi/consumers/connections/normal"), - not(nullValue())); - } - -} diff --git a/src/acceptance-test/java/org/zalando/nakadi/webservice/ConsumerLimitingServiceAT.java b/src/acceptance-test/java/org/zalando/nakadi/webservice/ConsumerLimitingServiceAT.java deleted file mode 100644 index 57f18fdb84..0000000000 --- a/src/acceptance-test/java/org/zalando/nakadi/webservice/ConsumerLimitingServiceAT.java +++ /dev/null @@ -1,112 +0,0 @@ -package org.zalando.nakadi.webservice; - -import com.google.common.collect.ImmutableList; -import org.apache.curator.framework.CuratorFramework; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; -import org.zalando.nakadi.exceptions.runtime.NoConnectionSlotsException; -import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; -import org.zalando.nakadi.repository.zookeeper.ZooKeeperLockFactory; -import org.zalando.nakadi.service.ConnectionSlot; -import org.zalando.nakadi.service.ConsumerLimitingService; -import org.zalando.nakadi.utils.TestUtils; -import org.zalando.nakadi.webservice.utils.ZookeeperTestUtils; - -import java.util.List; - -import static java.text.MessageFormat.format; -import static java.util.stream.IntStream.range; -import static org.hamcrest.CoreMatchers.hasItem; -import static org.hamcrest.CoreMatchers.not; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasSize; -import static org.mockito.Mockito.when; -import static org.zalando.nakadi.utils.TestUtils.randomUUID; - -public class ConsumerLimitingServiceAT extends BaseAT { - - private static final CuratorFramework CURATOR = ZookeeperTestUtils.createCurator(ZOOKEEPER_URL); - - private ConsumerLimitingService limitingService; - private String eventType; - private String client; - - @Before - public void before() { - eventType = TestUtils.randomValidEventTypeName(); - client = TestUtils.randomTextString(); - - final ZooKeeperHolder zkHolder = Mockito.mock(ZooKeeperHolder.class); - when(zkHolder.get()).thenReturn(CURATOR); - final ZooKeeperLockFactory zkLockFactory = new ZooKeeperLockFactory(zkHolder); - limitingService = new ConsumerLimitingService(zkHolder, zkLockFactory, 5); - } - - @Test - public void whenAcquireConnectionSlotsThenDataInZk() throws Exception { - final ImmutableList partitions = ImmutableList.of("0", "1", "2", "3"); - - final List connectionSlots = limitingService.acquireConnectionSlots(client, eventType, - partitions); - - assertThat("4 connection slots were created in ZK", connectionSlots, hasSize(4)); - - for (final String partition : partitions) { - final String path = zkPathForConsumer(partition); - - assertThat("Node for partition should be created", - CURATOR.checkExists().forPath(path), - not(nullValue())); - - final List children = CURATOR.getChildren().forPath(path); - assertThat("Node for connection should be created", - children, - hasSize(1)); - - final ConnectionSlot expectedSlot = new ConnectionSlot(client, eventType, partition, children.get(0)); - assertThat(connectionSlots, hasItem(expectedSlot)); - } - } - - @Test(expected = NoConnectionSlotsException.class) - public void whenNoFreeSlotsThenException() throws Exception { - final String partition = "0"; - - range(0, 5).forEach(x -> { - try { - final String path = zkPathForConsumer(partition) + "/" + randomUUID(); - CURATOR.create().creatingParentsIfNeeded().forPath(path); - } catch (Exception e) { - throw new AssertionError("Error occurred when accessing Zookeeper"); - } - }); - - limitingService.acquireConnectionSlots(client, eventType, ImmutableList.of(partition)); - } - - @Test - public void whenReleaseSlotThatNodeDeletedInZk() throws Exception { - final String connectionId = randomUUID(); - final String partition = "0"; - - final String partitionPath = zkPathForConsumer(partition); - final String connectionPath = partitionPath + "/" + connectionId; - CURATOR.create().creatingParentsIfNeeded().forPath(connectionPath); - - final ImmutableList connectionSlots = - ImmutableList.of(new ConnectionSlot(client, eventType, partition, connectionId)); - - limitingService.releaseConnectionSlots(connectionSlots); - - assertThat("partition and connection Zk nodes should be deleted", - CURATOR.checkExists().forPath(partitionPath), - nullValue()); - } - - private String zkPathForConsumer(final String partition) { - return format("/nakadi/consumers/connections/{0}|{1}|{2}", client, eventType, partition); - } - -} diff --git a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java index 5b66bef6a3..31ffdab0ba 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java @@ -6,7 +6,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -42,8 +41,6 @@ import org.zalando.nakadi.service.AuthorizationValidator; import org.zalando.nakadi.service.BlacklistService; import org.zalando.nakadi.service.ClosedConnectionsCrutch; -import org.zalando.nakadi.service.ConnectionSlot; -import org.zalando.nakadi.service.ConsumerLimitingService; import org.zalando.nakadi.service.CursorConverter; import org.zalando.nakadi.service.EventStream; import org.zalando.nakadi.service.EventStreamConfig; @@ -92,7 +89,6 @@ public class EventStreamController { private final MetricRegistry metricRegistry; private final ClosedConnectionsCrutch closedConnectionsCrutch; private final BlacklistService blacklistService; - private final ConsumerLimitingService consumerLimitingService; private final FeatureToggleService featureToggleService; private final CursorConverter cursorConverter; private final MetricRegistry streamMetrics; @@ -109,7 +105,6 @@ public EventStreamController(final EventTypeRepository eventTypeRepository, @Qualifier("streamMetricsRegistry") final MetricRegistry streamMetrics, final ClosedConnectionsCrutch closedConnectionsCrutch, final BlacklistService blacklistService, - final ConsumerLimitingService consumerLimitingService, final FeatureToggleService featureToggleService, final CursorConverter cursorConverter, final AuthorizationValidator authorizationValidator, @@ -123,7 +118,6 @@ public EventStreamController(final EventTypeRepository eventTypeRepository, this.streamMetrics = streamMetrics; this.closedConnectionsCrutch = closedConnectionsCrutch; this.blacklistService = blacklistService; - this.consumerLimitingService = consumerLimitingService; this.featureToggleService = featureToggleService; this.cursorConverter = cursorConverter; this.authorizationValidator = authorizationValidator; @@ -218,7 +212,6 @@ public StreamingResponseBody streamEvents( final AtomicBoolean connectionReady = closedConnectionsCrutch.listenForConnectionClose(request); Counter consumerCounter = null; EventStream eventStream = null; - final List connectionSlots = ImmutableList.of(); final AtomicBoolean needCheckAuthorization = new AtomicBoolean(false); LOG.info("[X-NAKADI-CURSORS] \"{}\" {}", eventTypeName, Optional.ofNullable(cursorsStr).orElse("-")); @@ -295,7 +288,6 @@ public StreamingResponseBody streamEvents( writeProblemResponse(response, outputStream, INTERNAL_SERVER_ERROR, e.getMessage()); } finally { connectionReady.set(false); - consumerLimitingService.releaseConnectionSlots(connectionSlots); if (consumerCounter != null) { consumerCounter.dec(); } diff --git a/src/main/java/org/zalando/nakadi/service/ConsumerLimitingService.java b/src/main/java/org/zalando/nakadi/service/ConsumerLimitingService.java deleted file mode 100644 index 0cdfd56be2..0000000000 --- a/src/main/java/org/zalando/nakadi/service/ConsumerLimitingService.java +++ /dev/null @@ -1,209 +0,0 @@ -package org.zalando.nakadi.service; - -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.commons.lang3.StringUtils; -import org.apache.curator.framework.recipes.cache.PathChildrenCache; -import org.apache.curator.utils.ZKPaths; -import org.apache.zookeeper.CreateMode; -import org.apache.zookeeper.KeeperException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.runtime.NoConnectionSlotsException; -import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; -import org.zalando.nakadi.repository.zookeeper.ZkChildrenCache; -import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; -import org.zalando.nakadi.repository.zookeeper.ZooKeeperLockFactory; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.ConcurrentMap; - -import static java.text.MessageFormat.format; -import static java.util.stream.Collectors.toList; -import static org.zalando.nakadi.repository.zookeeper.ZookeeperUtils.runLocked; - -@Component -public class ConsumerLimitingService { - - public static final String CONNECTIONS_ZK_PATH = "/nakadi/consumers/connections"; - public static final String LOCKS_ZK_PATH = "/nakadi/consumers/locks"; - - private static final Logger LOG = LoggerFactory.getLogger(ConsumerLimitingService.class); - - private static final String ERROR_MSG = "You exceeded the maximum number of simultaneous connections to a single " + - "partition for event type: {0}, partition(s): {1}; max limit is {2} connections per client"; - - private final ZooKeeperHolder zkHolder; - private final ZooKeeperLockFactory zkLockFactory; - private final int maxConnections; - - private static final ConcurrentMap SLOTS_CACHES = Maps.newConcurrentMap(); - private static final List ACQUIRED_SLOTS = Collections.synchronizedList(Lists.newArrayList()); - - @Autowired - public ConsumerLimitingService(final ZooKeeperHolder zkHolder, - final ZooKeeperLockFactory zkLockFactory, - @Value("${nakadi.stream.maxConnections}") final int maxConnections) { - this.zkHolder = zkHolder; - this.zkLockFactory = zkLockFactory; - this.maxConnections = maxConnections; - } - - @SuppressWarnings("unchecked") - public List acquireConnectionSlots(final String client, final String eventType, - final List partitions) - throws NoConnectionSlotsException, ServiceTemporarilyUnavailableException { - - final List partitionsWithNoFreeSlots = getPartitionsWithNoFreeSlots(client, eventType, partitions); - if (partitionsWithNoFreeSlots.size() == 0) { - - final List slots = new ArrayList<>(); - final String lockZkPath = ZKPaths.makePath(LOCKS_ZK_PATH, client + "|" + eventType); - try { - return runLocked(() -> { - // we need to check it again when we are under lock - final List occupiedPartitions = getPartitionsWithNoFreeSlots(client, eventType, partitions); - if (occupiedPartitions.size() > 0) { - throw generateNoConnectionSlotsException(eventType, occupiedPartitions, client); - } - - for (final String partition : partitions) { - final ConnectionSlot connectionSlot = acquireConnectionSlot(client, eventType, partition); - slots.add(connectionSlot); - } - return slots; - }, zkLockFactory.createLock(lockZkPath)); - } catch (final NoConnectionSlotsException e) { - throw e; - } catch (final Exception e) { - // in a case of failure release slots for partitions that already acquired slots - slots.forEach(this::releaseConnectionSlot); - throw new ServiceTemporarilyUnavailableException("Error communicating with zookeeper", e); - } - } else { - throw generateNoConnectionSlotsException(eventType, partitionsWithNoFreeSlots, client); - } - } - - private List getPartitionsWithNoFreeSlots(final String client, final String eventType, - final List partitions) { - return partitions.stream() - .filter(partition -> { - final String zkPath = zkPathForConsumer(client, eventType, partition); - final List slotsOccupied = getChildrenCached(zkPath); - return slotsOccupied.size() >= maxConnections; - }) - .collect(toList()); - } - - private NoConnectionSlotsException generateNoConnectionSlotsException(final String eventType, - final List overBookedPartitions, - final String client) { - final String partitionsStr = StringUtils.join(overBookedPartitions, ","); - final String msg = format(ERROR_MSG, eventType, partitionsStr, maxConnections); - LOG.debug("Limit exceeded for connection count for client: {}, event type: {}, partition(s): {}", - client, eventType, partitionsStr); - return new NoConnectionSlotsException(msg); - } - - public void releaseConnectionSlots(final List connectionSlots) { - connectionSlots.forEach(this::releaseConnectionSlot); - } - - private void releaseConnectionSlot(final ConnectionSlot slot) { - final String consumerNode = zkNodeNameForConsumer(slot.getClient(), slot.getEventType(), slot.getPartition()); - final String connectionNodePath = ZKPaths.makePath(CONNECTIONS_ZK_PATH, consumerNode, slot.getConnectionId()); - try { - zkHolder.get() - .delete() - .guaranteed() - .forPath(connectionNodePath); - deletePartitionNodeIfPossible(consumerNode); - } catch (final Exception e) { - LOG.error("Zookeeper error when deleting consumer connection node", e); - } - - ACQUIRED_SLOTS.remove(slot); - try { - deleteCacheIfPossible(slot); - } catch (final Exception e) { - LOG.error("Zookeeper error when deleting consumer connections cache", e); - } - } - - private void deleteCacheIfPossible(final ConnectionSlot slot) throws IOException { - final boolean hasMoreConnectionsToPartition = ACQUIRED_SLOTS.stream() - .anyMatch(s -> s.getPartition().equals(slot.getPartition()) - && s.getClient().equals(slot.getClient()) - && s.getEventType().equals(slot.getEventType())); - if (!hasMoreConnectionsToPartition) { - final String consumerPath = zkPathForConsumer(slot.getClient(), slot.getEventType(), slot.getPartition()); - final PathChildrenCache cache = SLOTS_CACHES.remove(consumerPath); - if (cache != null) { - cache.close(); - } - } - } - - public void deletePartitionNodeIfPossible(final String nodeName) { - try { - zkHolder.get() - .delete() - .forPath(ZKPaths.makePath(CONNECTIONS_ZK_PATH, nodeName)); - } catch (final KeeperException.NotEmptyException | KeeperException.NoNodeException e) { - // if the node has children - we should not delete it - // if the node doesn't exist - good, other thread/instance already deleted it - } catch (final Exception e) { - LOG.error("Zookeeper error when trying delete consumer node", e); - } - } - - private ConnectionSlot acquireConnectionSlot(final String client, final String eventType, - final String partition) { - - final String parent = zkPathForConsumer(client, eventType, partition); - final String slotId = UUID.randomUUID().toString(); - final String zkPath = ZKPaths.makePath(parent, slotId); - try { - zkHolder.get() - .create() - .creatingParentsIfNeeded() - .withMode(CreateMode.EPHEMERAL) - .forPath(zkPath); - } catch (Exception e) { - LOG.error("Zookeeper error when creating consumer node", e); - throw new NakadiRuntimeException(e); - } - final ConnectionSlot acquiredSlot = new ConnectionSlot(client, eventType, partition, slotId); - ACQUIRED_SLOTS.add(acquiredSlot); - return acquiredSlot; - } - - private List getChildrenCached(final String zkPath) { - final PathChildrenCache cache = SLOTS_CACHES.computeIfAbsent(zkPath, - key -> ZkChildrenCache.createCache(zkHolder.get(), key)); - return cache.getCurrentData().stream() - .map(childData -> { - final String[] pathParts = childData.getPath().split("/"); - return pathParts[pathParts.length - 1]; - }) - .collect(toList()); - } - - private String zkPathForConsumer(final String client, final String eventType, final String partition) { - return ZKPaths.makePath(CONNECTIONS_ZK_PATH, zkNodeNameForConsumer(client, eventType, partition)); - } - - private String zkNodeNameForConsumer(final String client, final String eventType, final String partition) { - return format("{0}|{1}|{2}", client, eventType, partition); - } - -} diff --git a/src/main/java/org/zalando/nakadi/service/job/ConsumerLimitingCleaningJob.java b/src/main/java/org/zalando/nakadi/service/job/ConsumerLimitingCleaningJob.java deleted file mode 100644 index 2fbe837b08..0000000000 --- a/src/main/java/org/zalando/nakadi/service/job/ConsumerLimitingCleaningJob.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.zalando.nakadi.service.job; - -import org.apache.zookeeper.KeeperException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; -import org.zalando.nakadi.service.ConsumerLimitingService; - -import static org.zalando.nakadi.service.ConsumerLimitingService.CONNECTIONS_ZK_PATH; - -@Service -public class ConsumerLimitingCleaningJob { - - public static final String JOB_NAME = "consumer-nodes-cleanup"; - - private static final Logger LOG = LoggerFactory.getLogger(ConsumerLimitingCleaningJob.class); - - private final ZooKeeperHolder zkHolder; - private final ConsumerLimitingService limitingService; - private final ExclusiveJobWrapper jobWrapper; - - @Autowired - public ConsumerLimitingCleaningJob(final ZooKeeperHolder zkHolder, - final JobWrapperFactory jobWrapperFactory, - final ConsumerLimitingService limitingService, - @Value("${nakadi.jobs.consumerNodesCleanup.runPeriodMs}") final int periodMs) { - this.zkHolder = zkHolder; - this.limitingService = limitingService; - jobWrapper = jobWrapperFactory.createExclusiveJobWrapper(JOB_NAME, periodMs); - } - - @Scheduled( - fixedDelayString = "${nakadi.jobs.checkRunMs}", - initialDelayString = "${random.int(${nakadi.jobs.checkRunMs})}") - public void cleanHangingNodes() { - jobWrapper.runJobLocked(this::cleanHangingConsumersNodes); - } - - private void cleanHangingConsumersNodes() { - // try to remove every consumer node; - // the nodes that have children will fail to be removed - try { - zkHolder.get() - .getChildren() - .forPath(CONNECTIONS_ZK_PATH) - .forEach(limitingService::deletePartitionNodeIfPossible); - } catch (final KeeperException.NoNodeException e) { - LOG.debug("ZK node for connections doesn't exist"); - } catch (final Exception e) { - LOG.error("ZK error when cleaning consumer nodes"); - } - } - -} diff --git a/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java index 0130d22eaa..7ff058f298 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java @@ -39,7 +39,6 @@ import org.zalando.nakadi.service.AuthorizationValidator; import org.zalando.nakadi.service.BlacklistService; import org.zalando.nakadi.service.ClosedConnectionsCrutch; -import org.zalando.nakadi.service.ConsumerLimitingService; import org.zalando.nakadi.service.EventStream; import org.zalando.nakadi.service.EventStreamConfig; import org.zalando.nakadi.service.EventStreamFactory; @@ -151,9 +150,6 @@ public void setup() throws NakadiException, UnknownHostException, InvalidCursorE blacklistService = Mockito.mock(BlacklistService.class); Mockito.when(blacklistService.isConsumptionBlocked(any(), any())).thenReturn(false); - final ConsumerLimitingService consumerLimitingService = Mockito.mock(ConsumerLimitingService.class); - when(consumerLimitingService.acquireConnectionSlots(any(), any(), any())).thenReturn(ImmutableList.of()); - featureToggleService = mock(FeatureToggleService.class); timelineService = mock(TimelineService.class); when(timelineService.getTopicRepository((Timeline) any())).thenReturn(topicRepositoryMock); @@ -167,7 +163,7 @@ public void setup() throws NakadiException, UnknownHostException, InvalidCursorE when(eventTypeChangeListener.registerListener(any(), any())).thenReturn(mock(Closeable.class)); controller = new EventStreamController( eventTypeRepository, timelineService, TestUtils.OBJECT_MAPPER, eventStreamFactoryMock, metricRegistry, - streamMetrics, crutch, blacklistService, consumerLimitingService, featureToggleService, + streamMetrics, crutch, blacklistService, featureToggleService, new CursorConverterImpl(eventTypeCache, timelineService), authorizationValidator, eventTypeChangeListener, null); From 03f1dd3f7166bba27fe6703afbc2b53a40f8f20e Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Mon, 23 Jul 2018 16:40:21 +0200 Subject: [PATCH 034/176] Remove Qualifier for binarywriter and unused featureToggleService import --- .../org/zalando/nakadi/controller/EventStreamController.java | 4 ---- src/main/java/org/zalando/nakadi/service/EventStream.java | 3 +-- .../java/org/zalando/nakadi/service/EventStreamFactory.java | 3 +-- .../org/zalando/nakadi/service/EventStreamWriterBinary.java | 2 -- .../service/subscription/SubscriptionStreamerFactory.java | 2 +- .../zalando/nakadi/controller/EventStreamControllerTest.java | 2 +- 6 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java index 31ffdab0ba..159b13cb09 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java @@ -46,7 +46,6 @@ import org.zalando.nakadi.service.EventStreamConfig; import org.zalando.nakadi.service.EventStreamFactory; import org.zalando.nakadi.service.EventTypeChangeListener; -import org.zalando.nakadi.service.FeatureToggleService; import org.zalando.nakadi.service.timeline.TimelineService; import org.zalando.nakadi.util.FlowIdUtils; import org.zalando.nakadi.view.Cursor; @@ -89,7 +88,6 @@ public class EventStreamController { private final MetricRegistry metricRegistry; private final ClosedConnectionsCrutch closedConnectionsCrutch; private final BlacklistService blacklistService; - private final FeatureToggleService featureToggleService; private final CursorConverter cursorConverter; private final MetricRegistry streamMetrics; private final AuthorizationValidator authorizationValidator; @@ -105,7 +103,6 @@ public EventStreamController(final EventTypeRepository eventTypeRepository, @Qualifier("streamMetricsRegistry") final MetricRegistry streamMetrics, final ClosedConnectionsCrutch closedConnectionsCrutch, final BlacklistService blacklistService, - final FeatureToggleService featureToggleService, final CursorConverter cursorConverter, final AuthorizationValidator authorizationValidator, final EventTypeChangeListener eventTypeChangeListener, @@ -118,7 +115,6 @@ public EventStreamController(final EventTypeRepository eventTypeRepository, this.streamMetrics = streamMetrics; this.closedConnectionsCrutch = closedConnectionsCrutch; this.blacklistService = blacklistService; - this.featureToggleService = featureToggleService; this.cursorConverter = cursorConverter; this.authorizationValidator = authorizationValidator; this.eventTypeChangeListener = eventTypeChangeListener; diff --git a/src/main/java/org/zalando/nakadi/service/EventStream.java b/src/main/java/org/zalando/nakadi/service/EventStream.java index 120d1c9f1f..5819c11603 100644 --- a/src/main/java/org/zalando/nakadi/service/EventStream.java +++ b/src/main/java/org/zalando/nakadi/service/EventStream.java @@ -6,7 +6,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Qualifier; import org.zalando.nakadi.domain.ConsumedEvent; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.metrics.StreamKpiData; @@ -48,7 +47,7 @@ public EventStream(final EventConsumer eventConsumer, final EventStreamConfig config, final BlacklistService blacklistService, final CursorConverter cursorConverter, final Meter bytesFlushedMeter, - @Qualifier("binary") final EventStreamWriter eventStreamWriter, + final EventStreamWriter eventStreamWriter, final NakadiKpiPublisher kpiPublisher, final String kpiDataStreamedEventType, final long kpiFrequencyMs) { this.eventConsumer = eventConsumer; diff --git a/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java b/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java index 58c92071c4..9dee599d65 100644 --- a/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java +++ b/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java @@ -2,7 +2,6 @@ import com.codahale.metrics.Meter; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.zalando.nakadi.exceptions.InvalidCursorException; @@ -24,7 +23,7 @@ public class EventStreamFactory { @Autowired public EventStreamFactory( final CursorConverter cursorConverter, - @Qualifier("binary") final EventStreamWriter eventStreamWriter, + final EventStreamWriter eventStreamWriter, final BlacklistService blacklistService, final NakadiKpiPublisher nakadiKpiPublisher, @Value("${nakadi.kpi.event-types.nakadiDataStreamed}") final String kpiDataStreamedEventType, diff --git a/src/main/java/org/zalando/nakadi/service/EventStreamWriterBinary.java b/src/main/java/org/zalando/nakadi/service/EventStreamWriterBinary.java index adce181e9e..1046a2c3e9 100644 --- a/src/main/java/org/zalando/nakadi/service/EventStreamWriterBinary.java +++ b/src/main/java/org/zalando/nakadi/service/EventStreamWriterBinary.java @@ -1,6 +1,5 @@ package org.zalando.nakadi.service; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.zalando.nakadi.domain.ConsumedEvent; import org.zalando.nakadi.view.Cursor; @@ -14,7 +13,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; @Component -@Qualifier("binary") class EventStreamWriterBinary implements EventStreamWriter { private static final byte[] B_BATCH_SEPARATOR = BATCH_SEPARATOR.getBytes(UTF_8); diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java index 3437b429a4..cafd3d2790 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java @@ -54,7 +54,7 @@ public SubscriptionStreamerFactory( final CursorConverter cursorConverter, @Qualifier("streamMetricsRegistry") final MetricRegistry metricRegistry, final SubscriptionClientFactory zkClientFactory, - @Qualifier("binary") final EventStreamWriter eventStreamWriter, + final EventStreamWriter eventStreamWriter, final AuthorizationValidator authorizationValidator, final EventTypeChangeListener eventTypeChangeListener, final EventTypeCache eventTypeCache, diff --git a/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java index 7ff058f298..58eed109ee 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java @@ -163,7 +163,7 @@ public void setup() throws NakadiException, UnknownHostException, InvalidCursorE when(eventTypeChangeListener.registerListener(any(), any())).thenReturn(mock(Closeable.class)); controller = new EventStreamController( eventTypeRepository, timelineService, TestUtils.OBJECT_MAPPER, eventStreamFactoryMock, metricRegistry, - streamMetrics, crutch, blacklistService, featureToggleService, + streamMetrics, crutch, blacklistService, new CursorConverterImpl(eventTypeCache, timelineService), authorizationValidator, eventTypeChangeListener, null); From 24891695188bb5db48fca89a57b593f3c83d6f5f Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Mon, 23 Jul 2018 17:09:09 +0200 Subject: [PATCH 035/176] Fix changes in CHANGELOG.md --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdc248dad0..48ae883d5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -## [2.8.1] - ### Removed - Removed Legacy Feature Toggles +## [2.8.1] + ### Added - Log Compaction Feature Toggle From dfcfa48478e7f9e63bb29a5799a58956cac66f10 Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Thu, 26 Jul 2018 11:17:36 +0200 Subject: [PATCH 036/176] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48ae883d5d..5d8feab9ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [2.8.2] - 2018-07-26 + ### Removed - Removed Legacy Feature Toggles From 05415a1aedba1cb8e64b5f3f2499a453663d4338 Mon Sep 17 00:00:00 2001 From: Dmitry Goryunov Date: Thu, 26 Jul 2018 15:29:53 +0200 Subject: [PATCH 037/176] Add `pyNakadi` client --- docs/_documentation/using_clients.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/_documentation/using_clients.md b/docs/_documentation/using_clients.md index 010cad83b9..91307ccb43 100644 --- a/docs/_documentation/using_clients.md +++ b/docs/_documentation/using_clients.md @@ -16,6 +16,7 @@ Nakadi does not ship with a client, but there are some open source clients avail | nakadi-client | Haskell | | | go-nakadi | Go | | | nakacli | CLI | | +| pyNakadi | Python | | More Nakadi related projects can be found here [https://github.com/zalando-nakadi](https://github.com/zalando-nakadi) From 845b91ee76bd8c01064405e84abe5562f5e7f8cd Mon Sep 17 00:00:00 2001 From: Ricardo de Cillo Date: Mon, 30 Jul 2018 14:15:45 +0200 Subject: [PATCH 038/176] Warn users about log compaction usage gotchas Some organizations have strict guidelines on what type of data can or cannot be stored permanently (log compacted means some data can be potentially permanently stored). This config opens space for configuring a message for users of the API. --- .../repository/kafka/KafkaRepositoryAT.java | 4 ++- .../zalando/nakadi/config/NakadiSettings.java | 9 ++++- .../controller/EventTypeController.java | 34 +++++++++++++------ src/main/resources/application.yml | 1 + .../controller/EventTypeControllerTest.java | 10 ++++++ .../EventTypeControllerTestCase.java | 3 +- .../nakadi/service/EventPublisherTest.java | 2 +- 7 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/acceptance-test/java/org/zalando/nakadi/repository/kafka/KafkaRepositoryAT.java b/src/acceptance-test/java/org/zalando/nakadi/repository/kafka/KafkaRepositoryAT.java index c6973161a0..b1f7cb74a3 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/repository/kafka/KafkaRepositoryAT.java +++ b/src/acceptance-test/java/org/zalando/nakadi/repository/kafka/KafkaRepositoryAT.java @@ -66,6 +66,7 @@ public class KafkaRepositoryAT extends BaseAT { private static final String DEFAULT_ADMIN_DATA_TYPE = "service"; private static final String DEFAULT_ADMIN_VALUE = "nakadi"; private static final String DEFAULT_WARN_ALL_DATA_ACCESS_MESSAGE = ""; + private static final String DEFAULT_WARN_LOG_COMPACTION_MESSAGE = ""; private NakadiSettings nakadiSettings; private KafkaSettings kafkaSettings; @@ -91,7 +92,8 @@ public void setup() { NAKADI_SUBSCRIPTION_MAX_PARTITIONS, DEFAULT_ADMIN_DATA_TYPE, DEFAULT_ADMIN_VALUE, - DEFAULT_WARN_ALL_DATA_ACCESS_MESSAGE); + DEFAULT_WARN_ALL_DATA_ACCESS_MESSAGE, + DEFAULT_WARN_LOG_COMPACTION_MESSAGE); kafkaSettings = new KafkaSettings(KAFKA_REQUEST_TIMEOUT, KAFKA_BATCH_SIZE, KAFKA_LINGER_MS, KAFKA_ENABLE_AUTO_COMMIT, KAFKA_MAX_REQUEST_SIZE); zookeeperSettings = new ZookeeperSettings(ZK_SESSION_TIMEOUT, ZK_CONNECTION_TIMEOUT); diff --git a/src/main/java/org/zalando/nakadi/config/NakadiSettings.java b/src/main/java/org/zalando/nakadi/config/NakadiSettings.java index 72bbf9d1dc..4704e396a5 100644 --- a/src/main/java/org/zalando/nakadi/config/NakadiSettings.java +++ b/src/main/java/org/zalando/nakadi/config/NakadiSettings.java @@ -22,6 +22,7 @@ public class NakadiSettings { private final int maxSubscriptionPartitions; private final AuthorizationAttribute defaultAdmin; private final String warnAllDataAccessMessage; + private final String logCompactionWarnMessage; @Autowired public NakadiSettings(@Value("${nakadi.topic.max.partitionNum}") final int maxTopicPartitionCount, @@ -37,7 +38,8 @@ public NakadiSettings(@Value("${nakadi.topic.max.partitionNum}") final int maxTo @Value("${nakadi.subscription.maxPartitions}") final int maxSubscriptionPartitions, @Value("${nakadi.admin.default.dataType}") final String defaultAdminDataType, @Value("${nakadi.admin.default.value}") final String defaultAdminValue, - @Value("${nakadi.authz.warnAllDataAccessMessage}") final String warnAllDataAccessMessage) { + @Value("${nakadi.authz.warnAllDataAccessMessage}") final String warnAllDataAccessMessage, + @Value("${nakadi.topic.compacted.warnMessage}") final String logCompactionWarnMessage) { this.maxTopicPartitionCount = maxTopicPartitionCount; this.defaultTopicPartitionCount = defaultTopicPartitionCount; this.defaultTopicReplicaFactor = defaultTopicReplicaFactor; @@ -51,6 +53,7 @@ public NakadiSettings(@Value("${nakadi.topic.max.partitionNum}") final int maxTo this.maxSubscriptionPartitions = maxSubscriptionPartitions; this.defaultAdmin = new ResourceAuthorizationAttribute(defaultAdminDataType, defaultAdminValue); this.warnAllDataAccessMessage = warnAllDataAccessMessage; + this.logCompactionWarnMessage = logCompactionWarnMessage; } public int getDefaultTopicPartitionCount() { @@ -104,4 +107,8 @@ public AuthorizationAttribute getDefaultAdmin() { public String getWarnAllDataAccessMessage() { return warnAllDataAccessMessage; } + + public String getLogCompactionWarnMessage() { + return logCompactionWarnMessage; + } } diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index 7768e808f9..b2ff7c94d3 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -1,5 +1,6 @@ package org.zalando.nakadi.controller; +import com.google.common.collect.Lists; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -15,25 +16,26 @@ import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.config.NakadiSettings; +import org.zalando.nakadi.domain.CleanupPolicy; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; -import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.NoSuchPartitionStrategyException; -import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; -import org.zalando.nakadi.exceptions.runtime.TopicCreationException; -import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; +import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; import org.zalando.nakadi.exceptions.runtime.EventTypeDeletionException; +import org.zalando.nakadi.exceptions.runtime.EventTypeOptionsValidationException; import org.zalando.nakadi.exceptions.runtime.EventTypeUnavailableException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; +import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TopicConfigException; -import org.zalando.nakadi.exceptions.runtime.EventTypeOptionsValidationException; +import org.zalando.nakadi.exceptions.runtime.TopicCreationException; +import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.plugin.api.ApplicationService; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; import org.zalando.nakadi.problem.ValidationProblem; @@ -48,6 +50,7 @@ import javax.validation.Valid; import javax.ws.rs.core.Response; import java.util.List; +import java.util.stream.Collectors; import static org.springframework.http.ResponseEntity.status; import static org.zalando.nakadi.service.FeatureToggleService.Feature.CHECK_OWNING_APPLICATION; @@ -108,7 +111,7 @@ public ResponseEntity create(@Valid @RequestBody final EventTypeBase eventTyp eventTypeService.create(eventType); - return ResponseEntity.status(HttpStatus.CREATED).headers(generateWarningHeaders()).build(); + return ResponseEntity.status(HttpStatus.CREATED).headers(generateWarningHeaders(eventType)).build(); } @RequestMapping(value = "/{name:.+}", method = RequestMethod.DELETE) @@ -145,7 +148,7 @@ public ResponseEntity update( eventTypeService.update(name, eventType); - return status(HttpStatus.OK).headers(generateWarningHeaders()).build(); + return status(HttpStatus.OK).headers(generateWarningHeaders(eventType)).build(); } @RequestMapping(value = "/{name:.+}", method = RequestMethod.GET) @@ -157,12 +160,23 @@ public ResponseEntity get(@PathVariable final String name, final NativeWebReq return status(HttpStatus.OK).body(result.getValue()); } - private HttpHeaders generateWarningHeaders() { + private HttpHeaders generateWarningHeaders(final EventTypeBase eventType) { final HttpHeaders headers = new HttpHeaders(); - if (!nakadiSettings.getWarnAllDataAccessMessage().isEmpty()) { + + final List warnings = Lists.newArrayList(nakadiSettings.getWarnAllDataAccessMessage()); + + if (eventType.getCleanupPolicy().equals(CleanupPolicy.COMPACT)) { + warnings.add(nakadiSettings.getLogCompactionWarnMessage()); + } + + final String warningMessage = warnings.stream() + .filter(s -> !s.isEmpty()).collect(Collectors.joining("\n")); + + if (!warnings.isEmpty()) { headers.add(HttpHeaders.WARNING, - String.format("299 nakadi \"%s\"", nakadiSettings.getWarnAllDataAccessMessage())); + String.format("299 nakadi \"%s\"", warningMessage)); } + return headers; } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3ad5cb4d00..7b8706c406 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -52,6 +52,7 @@ nakadi: rotationMs: 10800000 # 3 hours segmentBytes: 1073741824 # 1 GB compactionLagMs: 10800000 # 3 hours + warnMessage: "" stream: timeoutMs: 31536000000 # 1 year :-P default.commitTimeout: 60 # 1 minute diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java index 7888ec792f..9191ba83d1 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java @@ -127,6 +127,16 @@ public void whenPostEventTypeThenWarning() throws Exception { header().string("Warning", "299 nakadi \"I am warning you\"")); } + @Test + public void whenPostLogCompactedEventTypeThenWarning() throws Exception { + final EventType eventType = buildDefaultEventType(); + eventType.setCategory(BUSINESS); + eventType.setCleanupPolicy(CleanupPolicy.COMPACT); + eventType.getSchema().setSchema("{}"); + postEventType(eventType).andExpect(status().isCreated()).andExpect( + header().string("Warning", "299 nakadi \"I am warning you\nI am warning you, even more\"")); + } + @Test public void whenPostEventTypeWithTooLongNameThen422() throws Exception { final EventType invalidEventType = buildDefaultEventType(); diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java index cc09983bba..bc4b39d5db 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java @@ -93,7 +93,8 @@ public void init() throws Exception { final NakadiSettings nakadiSettings = new NakadiSettings(0, 0, 0, TOPIC_RETENTION_TIME_MS, 0, 60, NAKADI_POLL_TIMEOUT, NAKADI_SEND_TIMEOUT, 0, NAKADI_EVENT_MAX_BYTES, - NAKADI_SUBSCRIPTION_MAX_PARTITIONS, "service", "nakadi", "I am warning you"); + NAKADI_SUBSCRIPTION_MAX_PARTITIONS, "service", "nakadi", "I am warning you", + "I am warning you, even more"); final PartitionsCalculator partitionsCalculator = new KafkaConfig().createPartitionsCalculator( "t2.large", TestUtils.OBJECT_MAPPER, nakadiSettings); when(timelineService.getTopicRepository((Timeline) any())).thenReturn(topicRepository); diff --git a/src/test/java/org/zalando/nakadi/service/EventPublisherTest.java b/src/test/java/org/zalando/nakadi/service/EventPublisherTest.java index 404a7c3113..f0fd92b644 100644 --- a/src/test/java/org/zalando/nakadi/service/EventPublisherTest.java +++ b/src/test/java/org/zalando/nakadi/service/EventPublisherTest.java @@ -71,7 +71,7 @@ public class EventPublisherTest { private final AuthorizationValidator authzValidator = mock(AuthorizationValidator.class); private final NakadiSettings nakadiSettings = new NakadiSettings(0, 0, 0, TOPIC_RETENTION_TIME_MS, 0, 60, NAKADI_POLL_TIMEOUT, NAKADI_SEND_TIMEOUT, TIMELINE_WAIT_TIMEOUT_MS, NAKADI_EVENT_MAX_BYTES, - NAKADI_SUBSCRIPTION_MAX_PARTITIONS, "service", "nakadi", ""); + NAKADI_SUBSCRIPTION_MAX_PARTITIONS, "service", "nakadi", "", ""); private final EventPublisher publisher; public EventPublisherTest() { From 8a321c8913adb8e5e26ab1507014af29f26f5dcd Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Tue, 31 Jul 2018 15:47:41 +0200 Subject: [PATCH 039/176] Fix date in CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b757100797..57c351f599 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -## [2.8.2] - 2018-07-26 +## [2.8.2] - 2018-07-31 ### Removed - Removed Legacy Feature Toggles From 53724a9d793cc986305b5d585e67340754684528 Mon Sep 17 00:00:00 2001 From: Ricardo de Cillo Date: Wed, 1 Aug 2018 14:49:48 +0200 Subject: [PATCH 040/176] Remove partition key fields check This feature was believed to be enabled for a long time now. It happens that it was never enabled, since it breaks existen use cases. More specifically event log, which has not predefined schema. Since this feature was never there and now it was accidentally enabled, this is a hotfix to completely remove. --- CHANGELOG.md | 5 +++++ .../org/zalando/nakadi/service/EventTypeService.java | 11 ----------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 57c351f599..a25758e138 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +## [2.8.3] - 2018-08-01 + +### Fixed +- Removed partition key fields check + ## [2.8.2] - 2018-07-31 ### Removed diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 0b3ab246d1..96b794e915 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -505,7 +505,6 @@ private void validateSchema(final EventTypeBase eventType) throws InvalidEventTy throw new InvalidEventTypeException("\"metadata\" property is reserved"); } - validatePartitionKeys(schema, eventType); validateOrderingKeys(schema, eventType); if (eventType.getCompatibilityMode() == CompatibilityMode.COMPATIBLE) { @@ -528,16 +527,6 @@ private void validateJsonSchemaConstraints(final JSONObject schema) throws Inval } } - private void validatePartitionKeys(final Schema schema, final EventTypeBase eventType) - throws InvalidEventTypeException, JSONException, SchemaException { - final List absentFields = eventType.getPartitionKeyFields().stream() - .filter(field -> !schema.definesProperty(convertToJSONPointer(field))) - .collect(Collectors.toList()); - if (!absentFields.isEmpty()) { - throw new InvalidEventTypeException("partition_key_fields " + absentFields + " absent in schema"); - } - } - private void validateOrderingKeys(final Schema schema, final EventTypeBase eventType) throws InvalidEventTypeException, JSONException, SchemaException { final List absentFields = eventType.getOrderingKeyFields().stream() From cfd7be3bb891e73b6597747811ef178b5d25b361 Mon Sep 17 00:00:00 2001 From: Ricardo de Cillo Date: Wed, 1 Aug 2018 14:58:31 +0200 Subject: [PATCH 041/176] Remove tests for partition key fields feature --- .../controller/EventTypeControllerTest.java | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java index 8d78acb26c..64fd0bf310 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java @@ -187,19 +187,6 @@ public void whenPOSTWithInvalidPartitionStrategyThen422() throws Exception { .andExpect(content().contentType("application/problem+json")); } - @Test - public void whenPUTWithInvalidPartitionStrategyThen422() throws Exception { - - final EventType eventType = EventTypeTestBuilder.builder() - .partitionKeyFields(Lists.newArrayList("invalid_key")).build(); - - doReturn(eventType).when(eventTypeRepository).findByName(any()); - - putEventType(eventType, eventType.getName()) - .andExpect(status().isUnprocessableEntity()) - .andExpect(content().contentType("application/problem+json")); - } - @Test public void whenPUTwithPartitionStrategyChangeFromRandomToUserDefinedThenOK() throws Exception { final EventType eventType = EventTypeTestBuilder.builder() @@ -571,44 +558,6 @@ public void whenDeleteEventTypeThatHasSubscriptionsThenConflict() throws Excepti .andExpect(content().string(matchesProblem(expectedProblem))); } - @Test - public void whenCreateEventTypeWithWrongPartitionKeyFieldsThen422() throws Exception { - - final EventType eventType = EventTypeTestBuilder.builder() - .partitionKeyFields(Collections.singletonList("blabla")).build(); - - doReturn(eventType).when(eventTypeRepository).findByName(eventType.getName()); - - postEventType(eventType).andExpect(status().isUnprocessableEntity()) - .andExpect(content().contentType("application/problem+json")); - } - - @Test - public void whenPUTEventTypeWithWrongPartitionKeyFieldsThen422() throws Exception { - - final EventType eventType = EventTypeTestBuilder.builder() - .partitionKeyFields(Collections.singletonList("blabla")).build(); - - doReturn(eventType).when(eventTypeRepository).findByName(eventType.getName()); - - putEventType(eventType, eventType.getName()).andExpect(status().isUnprocessableEntity()) - .andExpect(content().contentType("application/problem+json")); - } - - @Test - public void whenPUTEventTypeWithWrongPartitionKeyToBusinessCategoryFieldsThen422() throws Exception { - - final EventType eventType = EventTypeTestBuilder.builder() - .partitionKeyFields(Collections.singletonList("blabla")) - .category(BUSINESS) - .build(); - - doReturn(eventType).when(eventTypeRepository).findByName(eventType.getName()); - - putEventType(eventType, eventType.getName()).andExpect(status().isUnprocessableEntity()) - .andExpect(content().contentType("application/problem+json")); - } - @Test public void whenDeleteEventTypeAndNakadiExceptionThen500() throws Exception { From 3260e1708ea5295467bb7e9a799045da7af5547b Mon Sep 17 00:00:00 2001 From: dsorokin Date: Thu, 2 Aug 2018 11:57:47 +0200 Subject: [PATCH 042/176] ARUHA-1681 Fix after merge --- .../nakadi/controller/PostSubscriptionController.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index 51c0b771aa..4a4a56d368 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -92,11 +92,6 @@ public ResponseEntity updateSubscription( if (errors.hasErrors()) { return Responses.create(new ValidationProblem(errors), request); } - if (featureToggleService.isFeatureEnabled(CHECK_OWNING_APPLICATION) - && !applicationService.exists(subscription.getOwningApplication())) { - return Responses.create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, - "owning_application doesn't exist"), request); - } try { subscriptionService.updateSubscription(subscriptionId, subscription); return ResponseEntity.noContent().build(); From e584a472990b75ab82e1c4e57fd8411e495a875f Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Thu, 26 Jul 2018 09:52:12 +0200 Subject: [PATCH 043/176] Don't allow schema root object type to be array Don't allow the root object type in schema for business and data category to be of type array --- CHANGELOG.md | 3 +++ .../org/zalando/nakadi/service/EventTypeService.java | 5 +++++ .../nakadi/controller/EventTypeControllerTest.java | 11 +++++++++++ 3 files changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a25758e138..857b0c99b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Removed partition key fields check +### Removed +- Removed the ability to specify schema root object type to be of type array. + ## [2.8.2] - 2018-07-31 ### Removed diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 0f53d63463..867daad206 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -501,6 +501,11 @@ private void validateSchema(final EventTypeBase eventType) throws InvalidEventTy final JSONObject schemaAsJson = new JSONObject(eventTypeSchema); final Schema schema = SchemaLoader.load(schemaAsJson); + if (schemaAsJson.has("type") && schemaAsJson.getString("type").equals("array") + && eventType.getCategory() != EventCategory.UNDEFINED) { + throw new InvalidEventTypeException("\"type\" of root element in schema cannot be \"array\""); + } + if (eventType.getCategory() == EventCategory.BUSINESS && schema.definesProperty("#/metadata")) { throw new InvalidEventTypeException("\"metadata\" property is reserved"); } diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java index 64fd0bf310..076a848195 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java @@ -174,6 +174,17 @@ public void whenPostWithNoSchemaSchemaThenReturn422() throws Exception { postETAndExpect422WithProblem(eventType, expectedProblem); } + @Test + public void whenPostWithRootElementOfTypeArrayThenReturn422() throws Exception { + final Problem expectedProblem = createInvalidEventTypeExceptionProblem("\"type\" of root element in" + + " schema cannot be \"array\""); + + final String eventType = "{\"category\": \"data\", \"owning_application\": \"blah-app\", \n" + + " \"name\": \"blah-event-type\",\n" + + " \"schema\": {\"type\": \"json_schema\", \"schema\": \"{\\\"type\\\":\\\"array\\\" }\"}}"; + postETAndExpect422WithProblem(eventType, expectedProblem); + } + @Test public void whenPOSTWithInvalidPartitionStrategyThen422() throws Exception { final EventType eventType = buildDefaultEventType(); From 0c7c4b51f8499e4f9d0a3b999ff2d10eb5d72f29 Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Thu, 26 Jul 2018 10:57:23 +0200 Subject: [PATCH 044/176] Fix changelog & check for type to be of only object. --- CHANGELOG.md | 4 ++-- .../java/org/zalando/nakadi/service/EventTypeService.java | 5 ++--- .../zalando/nakadi/controller/EventTypeControllerTest.java | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 857b0c99b2..41273848b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Removed partition key fields check -### Removed -- Removed the ability to specify schema root object type to be of type array. +### Fixed +- Fixed and added check for schema root object type to be only of type object. ## [2.8.2] - 2018-07-31 diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 867daad206..0af66c6d2d 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -501,9 +501,8 @@ private void validateSchema(final EventTypeBase eventType) throws InvalidEventTy final JSONObject schemaAsJson = new JSONObject(eventTypeSchema); final Schema schema = SchemaLoader.load(schemaAsJson); - if (schemaAsJson.has("type") && schemaAsJson.getString("type").equals("array") - && eventType.getCategory() != EventCategory.UNDEFINED) { - throw new InvalidEventTypeException("\"type\" of root element in schema cannot be \"array\""); + if (schemaAsJson.has("type") && !schemaAsJson.getString("type").equals("object")) { + throw new InvalidEventTypeException("\"type\" of root element in schema can only be \"object\""); } if (eventType.getCategory() == EventCategory.BUSINESS && schema.definesProperty("#/metadata")) { diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java index 076a848195..64ac30d367 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java @@ -177,7 +177,7 @@ public void whenPostWithNoSchemaSchemaThenReturn422() throws Exception { @Test public void whenPostWithRootElementOfTypeArrayThenReturn422() throws Exception { final Problem expectedProblem = createInvalidEventTypeExceptionProblem("\"type\" of root element in" - + " schema cannot be \"array\""); + + " schema can only be \"object\""); final String eventType = "{\"category\": \"data\", \"owning_application\": \"blah-app\", \n" + " \"name\": \"blah-event-type\",\n" + From 9d0be46700d7fab1b7a71cb2f2a7e46e1e505435 Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Tue, 31 Jul 2018 16:32:30 +0200 Subject: [PATCH 045/176] Fix comparision and move call to schemaloader down --- .../java/org/zalando/nakadi/service/EventTypeService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 0af66c6d2d..1fba1e7585 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -499,12 +499,12 @@ private void validateSchema(final EventTypeBase eventType) throws InvalidEventTy JsonUtils.checkEventTypeSchemaValid(eventTypeSchema); final JSONObject schemaAsJson = new JSONObject(eventTypeSchema); - final Schema schema = SchemaLoader.load(schemaAsJson); - if (schemaAsJson.has("type") && !schemaAsJson.getString("type").equals("object")) { + if (schemaAsJson.has("type") && !Objects.equals("object", schemaAsJson.getString("type"))) { throw new InvalidEventTypeException("\"type\" of root element in schema can only be \"object\""); } + final Schema schema = SchemaLoader.load(schemaAsJson); if (eventType.getCategory() == EventCategory.BUSINESS && schema.definesProperty("#/metadata")) { throw new InvalidEventTypeException("\"metadata\" property is reserved"); } From 8d98579fad449ccdccf609e95658bd4685cbb544 Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Mon, 30 Jul 2018 09:45:57 +0200 Subject: [PATCH 046/176] Fix ISE when parsing number larger than max long Nakadi replies with status code 500 when the number being parsed is greater than max long. --- CHANGELOG.md | 3 +++ .../java/org/zalando/nakadi/domain/StrictJsonParser.java | 6 +++--- .../java/org/zalando/nakadi/domain/BatchFactoryTest.java | 9 +++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41273848b9..b210c2a568 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Fixed and added check for schema root object type to be only of type object. +### Fixed +- Fixed ISE when parsing number larger than max long + ## [2.8.2] - 2018-07-31 ### Removed diff --git a/src/main/java/org/zalando/nakadi/domain/StrictJsonParser.java b/src/main/java/org/zalando/nakadi/domain/StrictJsonParser.java index eafd046a13..4a5f6405d7 100644 --- a/src/main/java/org/zalando/nakadi/domain/StrictJsonParser.java +++ b/src/main/java/org/zalando/nakadi/domain/StrictJsonParser.java @@ -157,13 +157,13 @@ private static Object readNumberTillTheEnd(final char value, final StringTokeniz throw syntaxError(stringNumber + " can not be used", tokenizer); } } else { - final long longValue = Long.parseLong(stringNumber); - if (stringNumber.equals(String.valueOf(longValue))) { + try { + final long longValue = Long.parseLong(stringNumber); if (longValue <= Integer.MAX_VALUE && longValue >= Integer.MIN_VALUE) { return (int) longValue; } return longValue; - } else { + } catch (NumberFormatException e) { throw syntaxError("Can not use long value '" + stringNumber + "' cause it is too big", tokenizer); } } diff --git a/src/test/java/org/zalando/nakadi/domain/BatchFactoryTest.java b/src/test/java/org/zalando/nakadi/domain/BatchFactoryTest.java index 679504aa63..b76786a658 100644 --- a/src/test/java/org/zalando/nakadi/domain/BatchFactoryTest.java +++ b/src/test/java/org/zalando/nakadi/domain/BatchFactoryTest.java @@ -132,4 +132,13 @@ public void testGarbageBetweenEvents() { fail(); } catch (JSONException e) {} } + + @Test + public void testNumberLargerThanMaxLongInEvents() { + final String events = "[{\"number\": 9223372036854775808 }]"; + try { + BatchFactory.from(events); + fail(); + } catch (JSONException e) {} + } } From 0de99b16e61730996c1681203d72ff6958aa67e0 Mon Sep 17 00:00:00 2001 From: Suyash Garg Date: Tue, 31 Jul 2018 16:41:53 +0200 Subject: [PATCH 047/176] Modify annotation instead of call fail() and catch exception --- .../java/org/zalando/nakadi/domain/BatchFactoryTest.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/test/java/org/zalando/nakadi/domain/BatchFactoryTest.java b/src/test/java/org/zalando/nakadi/domain/BatchFactoryTest.java index b76786a658..b48e50ab99 100644 --- a/src/test/java/org/zalando/nakadi/domain/BatchFactoryTest.java +++ b/src/test/java/org/zalando/nakadi/domain/BatchFactoryTest.java @@ -133,12 +133,9 @@ public void testGarbageBetweenEvents() { } catch (JSONException e) {} } - @Test + @Test(expected = JSONException.class) public void testNumberLargerThanMaxLongInEvents() { final String events = "[{\"number\": 9223372036854775808 }]"; - try { - BatchFactory.from(events); - fail(); - } catch (JSONException e) {} + BatchFactory.from(events); } } From a6f6e3e4722d9f85d52a58c56d2eafd878670fcd Mon Sep 17 00:00:00 2001 From: Ricardo de Cillo Date: Thu, 2 Aug 2018 13:25:33 +0200 Subject: [PATCH 048/176] Changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41273848b9..e35e94ae2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Removed partition key fields check - -### Fixed - Fixed and added check for schema root object type to be only of type object. +### Added +- Warn message when creation log compacted event types + ## [2.8.2] - 2018-07-31 ### Removed From fa00c6a88f14367beba0c28bfadcddc6808f3a94 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Thu, 2 Aug 2018 15:51:38 +0200 Subject: [PATCH 049/176] ARUHA-1681 Fix npe while committing cursors --- .../org/zalando/nakadi/service/AuthorizationValidator.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java index f0820e379d..381ce29098 100644 --- a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java +++ b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java @@ -184,6 +184,9 @@ public void authorizeSubscriptionRead(final Subscription subscription) throws Ac } public void authorizeSubscriptionCommit(final Subscription subscription) throws AccessDeniedException { + if (null == subscription.getAuthorization()) { + return; + } final Resource resource = subscription.asResource(); try { if (!authorizationService.isAuthorized(AuthorizationService.Operation.READ, resource) From afcbdf35ab56d7702d0960f1016540f2eb05482c Mon Sep 17 00:00:00 2001 From: dsorokin Date: Wed, 1 Aug 2018 14:49:57 +0200 Subject: [PATCH 050/176] ARUHA-1828 Remove logger name from access log --- src/main/java/org/zalando/nakadi/filters/LoggingFilter.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/filters/LoggingFilter.java b/src/main/java/org/zalando/nakadi/filters/LoggingFilter.java index 5084c08996..c5f9d9a221 100644 --- a/src/main/java/org/zalando/nakadi/filters/LoggingFilter.java +++ b/src/main/java/org/zalando/nakadi/filters/LoggingFilter.java @@ -21,7 +21,8 @@ @Component public class LoggingFilter extends OncePerRequestFilter { - private static final Logger LOG = LoggerFactory.getLogger(LoggingFilter.class); + // We are using empty log name, cause it is used only for access log and we do not care about class name + private static final Logger ACCESS_LOGGER = LoggerFactory.getLogger(""); private final NakadiKpiPublisher nakadiKpiPublisher; private final String accessLogEventType; @@ -55,7 +56,7 @@ protected void doFilterInternal(final HttpServletRequest request, .orElse("-"); final Long contentLength = request.getContentLengthLong() == -1 ? 0 : request.getContentLengthLong(); - LOG.info("[ACCESS_LOG] {} \"{}{}\" \"{}\" \"{}\" statusCode: {} {} ms \"{}\" \"{}\" {} bytes", + ACCESS_LOGGER.info("[ACCESS_LOG] {} \"{}{}\" \"{}\" \"{}\" statusCode: {} {} ms \"{}\" \"{}\" {} bytes", method, path, query, From 64a3802e7d932d67a57e83e78881f521a6b30ae4 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Wed, 1 Aug 2018 14:55:06 +0200 Subject: [PATCH 051/176] ARUHA-1828 Reduce log size for cursor commits --- .../subscription/zk/AbstractZkSubscriptionClient.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java index 4c8fa532c8..4b9d9aa2cd 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java @@ -432,7 +432,11 @@ public List commitOffsets( } } if (!currentMaxCursor.getOffset().equals(currentMaxOffset)) { - getLog().info("Committing {} to {}", currentMaxCursor.getOffset(), offsetPath); + getLog().info("Committing {} to {}/{}", + currentMaxCursor.getOffset(), + entry.getKey().getEventType(), + entry.getKey().getPartition()); + getCurator() .setData() .withVersion(stat.getVersion()) From 3914b5d9f6216adf65fe0a5286c1d738d6f40a43 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Wed, 1 Aug 2018 15:01:10 +0200 Subject: [PATCH 052/176] ARUHA-1828 Move switching from/to to one log line --- src/main/java/org/zalando/nakadi/service/EventStream.java | 2 +- .../nakadi/service/subscription/StreamingContext.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/service/EventStream.java b/src/main/java/org/zalando/nakadi/service/EventStream.java index 5819c11603..faa1003ad4 100644 --- a/src/main/java/org/zalando/nakadi/service/EventStream.java +++ b/src/main/java/org/zalando/nakadi/service/EventStream.java @@ -136,7 +136,7 @@ public void streamEvents(final AtomicBoolean connectionReady, final Runnable che .get(); sendBatch(latestOffsets.get(heaviestPartition.getKey()), heaviestPartition.getValue()); final long freed = heaviestPartition.getValue().stream().mapToLong(v -> v.length).sum(); - LOG.warn("Memory limit reached for event type {}: {} bytes. Freed: {} bytes, {} messages", + LOG.info("Memory limit reached for event type {}: {} bytes. Freed: {} bytes, {} messages", config.getEtName(), bytesInMemory, freed, heaviestPartition.getValue().size()); bytesInMemory -= freed; // Init new batch for subscription diff --git a/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java b/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java index 1acc0e1025..145b09c923 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java @@ -198,7 +198,9 @@ void streamInternal(final State firstState) throws InterruptedException { public void switchState(final State newState) { this.addTask(() -> { - log.info("Switching state from " + currentState.getClass().getSimpleName()); + log.info("Switching state from {} to {}", + currentState.getClass().getSimpleName(), + newState.getClass().getSimpleName()); // There is a problem with onExit call - it can not throw exceptions, otherwise it won't be possible // to finish state correctly. In order to avoid it in future state will be switched even in case of // exception. @@ -207,7 +209,6 @@ public void switchState(final State newState) { } finally { currentState = newState; - log.info("Switching state to " + currentState.getClass().getSimpleName()); currentState.setContext(this, loggingPath); currentState.onEnter(); } From 5b9690d5453b336b22e24377ffedfbb20dc5044a Mon Sep 17 00:00:00 2001 From: dsorokin Date: Wed, 1 Aug 2018 15:03:19 +0200 Subject: [PATCH 053/176] ARUHA-1828 Remove commit cursors additional logging --- .../java/org/zalando/nakadi/controller/CursorsController.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/CursorsController.java b/src/main/java/org/zalando/nakadi/controller/CursorsController.java index a1097c3157..904d8b3ef3 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorsController.java @@ -93,9 +93,6 @@ public ResponseEntity commitCursors(@PathVariable("subscriptionId") final Str @NotNull @RequestHeader("X-Nakadi-StreamId") final String streamId, final NativeWebRequest request) { - TimeLogger.startMeasure( - "COMMIT_CURSORS sid:" + subscriptionId + ", size=" + cursorsIn.getItems().size(), - "isFeatureEnabled"); try { TimeLogger.addMeasure("convertToNakadiCursors"); final List cursors = convertToNakadiCursors(cursorsIn); From 5ff4281b33e02aee94457c59971d8aa51048e760 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Thu, 2 Aug 2018 09:15:34 +0200 Subject: [PATCH 054/176] ARUHA-1828 Reduce access log size, remove usage of TimeLogger completely. --- .../zalando/nakadi/controller/CursorsController.java | 6 ------ .../java/org/zalando/nakadi/filters/LoggingFilter.java | 4 ++-- .../org/zalando/nakadi/service/CursorsService.java | 10 ++-------- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/CursorsController.java b/src/main/java/org/zalando/nakadi/controller/CursorsController.java index 904d8b3ef3..c6cfa26b49 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorsController.java @@ -31,7 +31,6 @@ import org.zalando.nakadi.service.CursorTokenService; import org.zalando.nakadi.service.CursorsService; import org.zalando.nakadi.service.FeatureToggleService; -import org.zalando.nakadi.util.TimeLogger; import org.zalando.nakadi.view.CursorCommitResult; import org.zalando.nakadi.view.SubscriptionCursor; import org.zalando.nakadi.view.SubscriptionCursorWithoutToken; @@ -94,15 +93,12 @@ public ResponseEntity commitCursors(@PathVariable("subscriptionId") final Str final NativeWebRequest request) { try { - TimeLogger.addMeasure("convertToNakadiCursors"); final List cursors = convertToNakadiCursors(cursorsIn); if (cursors.isEmpty()) { throw new CursorsAreEmptyException(); } - TimeLogger.addMeasure("callService"); final List items = cursorsService.commitCursors(streamId, subscriptionId, cursors); - TimeLogger.addMeasure("prepareResponse"); final boolean allCommited = items.stream().allMatch(item -> item); if (allCommited) { return noContent().build(); @@ -120,8 +116,6 @@ public ResponseEntity commitCursors(@PathVariable("subscriptionId") final Str } catch (final NakadiException e) { LOG.error("Failed to commit cursors", e); return create(e.asProblem(), request); - } finally { - LOG.info(TimeLogger.finishMeasure()); } } diff --git a/src/main/java/org/zalando/nakadi/filters/LoggingFilter.java b/src/main/java/org/zalando/nakadi/filters/LoggingFilter.java index c5f9d9a221..5cc5955e84 100644 --- a/src/main/java/org/zalando/nakadi/filters/LoggingFilter.java +++ b/src/main/java/org/zalando/nakadi/filters/LoggingFilter.java @@ -22,7 +22,7 @@ public class LoggingFilter extends OncePerRequestFilter { // We are using empty log name, cause it is used only for access log and we do not care about class name - private static final Logger ACCESS_LOGGER = LoggerFactory.getLogger(""); + private static final Logger ACCESS_LOGGER = LoggerFactory.getLogger("ACCESS_LOG"); private final NakadiKpiPublisher nakadiKpiPublisher; private final String accessLogEventType; @@ -56,7 +56,7 @@ protected void doFilterInternal(final HttpServletRequest request, .orElse("-"); final Long contentLength = request.getContentLengthLong() == -1 ? 0 : request.getContentLengthLong(); - ACCESS_LOGGER.info("[ACCESS_LOG] {} \"{}{}\" \"{}\" \"{}\" statusCode: {} {} ms \"{}\" \"{}\" {} bytes", + ACCESS_LOGGER.info("{} \"{}{}\" \"{}\" \"{}\" {} {}ms \"{}\" \"{}\" {}B", method, path, query, diff --git a/src/main/java/org/zalando/nakadi/service/CursorsService.java b/src/main/java/org/zalando/nakadi/service/CursorsService.java index fd6492314d..17a97ca544 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorsService.java @@ -16,9 +16,10 @@ import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; -import org.zalando.nakadi.exceptions.runtime.UnableProcessException; +import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; import org.zalando.nakadi.exceptions.runtime.OperationTimeoutException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; +import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.exceptions.runtime.ZookeeperException; import org.zalando.nakadi.repository.TopicRepository; import org.zalando.nakadi.repository.db.EventTypeCache; @@ -29,7 +30,6 @@ import org.zalando.nakadi.service.subscription.zk.SubscriptionNotInitializedException; import org.zalando.nakadi.service.subscription.zk.ZkSubscriptionClient; import org.zalando.nakadi.service.timeline.TimelineService; -import org.zalando.nakadi.util.TimeLogger; import org.zalando.nakadi.util.UUIDGenerator; import org.zalando.nakadi.view.SubscriptionCursorWithoutToken; @@ -80,23 +80,17 @@ public List commitCursors(final String streamId, final String subscript throws ServiceTemporarilyUnavailableException, InvalidCursorException, InvalidStreamIdException, NoSuchEventTypeException, InternalNakadiException, NoSuchSubscriptionException, UnableProcessException, AccessDeniedException { - TimeLogger.addMeasure("getSubscription"); final Subscription subscription = subscriptionRepository.getSubscription(subscriptionId); - TimeLogger.addMeasure("authorize"); authorizationValidator.authorizeSubscriptionCommit(subscription); - TimeLogger.addMeasure("validateSubscriptionCursors"); validateSubscriptionCommitCursors(subscription, cursors); - TimeLogger.addMeasure("createSubscriptionClient"); final ZkSubscriptionClient zkClient = zkSubscriptionFactory.createClient( subscription, "subscription." + subscriptionId + "." + streamId + ".offsets"); - TimeLogger.addMeasure("validateStreamId"); validateStreamId(cursors, streamId, zkClient); - TimeLogger.addMeasure("writeToZK"); return zkClient.commitOffsets( cursors.stream().map(cursorConverter::convertToNoToken).collect(Collectors.toList()), new SubscriptionCursorComparator(new NakadiCursorComparator(eventTypeCache))); From 49d7775beb76519fdd90742af2399ab0ab677aeb Mon Sep 17 00:00:00 2001 From: dsorokin Date: Thu, 2 Aug 2018 09:20:09 +0200 Subject: [PATCH 055/176] ARUHA-1828 Remove newline separator from message --- .../java/org/zalando/nakadi/service/EventPublisher.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/service/EventPublisher.java b/src/main/java/org/zalando/nakadi/service/EventPublisher.java index cdd7e931ab..877f5743bf 100644 --- a/src/main/java/org/zalando/nakadi/service/EventPublisher.java +++ b/src/main/java/org/zalando/nakadi/service/EventPublisher.java @@ -104,7 +104,10 @@ EventPublishResult publishInternal(final String events, return ok(batch); } catch (final EventValidationException e) { - LOG.debug("Event validation error: {}", e.getMessage()); + LOG.debug( + "Event validation error: {}", + Optional.ofNullable(e.getMessage()).map(s -> s.replaceAll("\n", "; ")).orElse(null) + ); return aborted(EventPublishingStep.VALIDATING, batch); } catch (final PartitioningException e) { LOG.debug("Event partition error: {}", e.getMessage()); @@ -167,7 +170,7 @@ private void partition(final List batch, final EventType eventType) t } } - private void compact(final List batch, final EventType eventType) throws CompactionException { + private void compact(final List batch, final EventType eventType) { if (eventType.getCleanupPolicy() == CleanupPolicy.COMPACT) { for (final BatchItem item : batch) { final String compactionKey = item.getEvent() From aa23387a917b489726064a9906f44a1dbd527c3a Mon Sep 17 00:00:00 2001 From: dsorokin Date: Thu, 2 Aug 2018 10:03:31 +0200 Subject: [PATCH 056/176] ARUHA-1828 Reduce logging for closed connection crutch --- .../org/zalando/nakadi/service/ClosedConnectionsCrutch.java | 4 ++-- src/main/resources/log4j.properties | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/service/ClosedConnectionsCrutch.java b/src/main/java/org/zalando/nakadi/service/ClosedConnectionsCrutch.java index f8313d4c4a..3a236f7b73 100644 --- a/src/main/java/org/zalando/nakadi/service/ClosedConnectionsCrutch.java +++ b/src/main/java/org/zalando/nakadi/service/ClosedConnectionsCrutch.java @@ -146,7 +146,7 @@ public void listenForConnectionClose( if (!featureToggleService.isFeatureEnabled(FeatureToggleService.Feature.CONNECTION_CLOSE_CRUTCH)) { return; } - LOG.debug("Listening for connection to close using crutch (" + address + ":" + port + ")"); + LOG.debug("Listening for connection to close using crutch ({}:{})", address, port); synchronized (toAdd) { toAdd.computeIfAbsent(new ConnectionInfo(address, port), tmp -> new ArrayList<>()).add(onCloseListener); } @@ -169,7 +169,7 @@ public void refresh() throws IOException { .filter(key -> CLOSED_STATES.contains(currentConnections.getOrDefault(key, ConnectionState.TCP_CLOSE))) .mapToLong(key -> { - LOG.info("Notifying about connection close via crutch: " + key); + LOG.debug("Notifying about connection close via crutch: {}", key); return listeners.remove(key).stream().filter(BooleanSupplier::getAsBoolean).count(); }).sum(); if (closedCount > 0) { diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties index 6c1d5f18b4..54f54fc38f 100644 --- a/src/main/resources/log4j.properties +++ b/src/main/resources/log4j.properties @@ -21,3 +21,4 @@ log4j.category.org.thymeleaf=WARN log4j.category.org.zalando.nakadi=DEBUG log4j.category.org.zalando.nakadi.config=INFO log4j.category.org.apache.kafka=WARN +lgo4j.category.org.zalando.nakadi.service.ClosedConnectionsCrutch=INFO From 82741a643d7d774672bff0d74ad93d5561f41992 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Thu, 2 Aug 2018 11:23:53 +0200 Subject: [PATCH 057/176] ARUHA-1828 Reduce logging on subscription side --- .../org/zalando/nakadi/service/CursorsService.java | 8 ++++---- .../org/zalando/nakadi/service/EventPublisher.java | 2 +- .../service/subscription/LogPathBuilder.java | 11 +++++++++++ .../service/subscription/StreamingContext.java | 12 ++---------- .../service/subscription/SubscriptionService.java | 4 ++-- .../subscription/SubscriptionStreamerFactory.java | 5 ++--- .../nakadi/service/subscription/state/State.java | 8 ++++++-- .../service/subscription/state/StreamingState.java | 6 ++++-- .../service/subscription/StreamingContextTest.java | 14 +++++++------- .../subscription/state/StreamingStateTest.java | 2 +- 10 files changed, 40 insertions(+), 32 deletions(-) create mode 100644 src/main/java/org/zalando/nakadi/service/subscription/LogPathBuilder.java diff --git a/src/main/java/org/zalando/nakadi/service/CursorsService.java b/src/main/java/org/zalando/nakadi/service/CursorsService.java index 17a97ca544..d64b4f443d 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorsService.java @@ -16,7 +16,6 @@ import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; -import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; import org.zalando.nakadi.exceptions.runtime.OperationTimeoutException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.UnableProcessException; @@ -24,6 +23,7 @@ import org.zalando.nakadi.repository.TopicRepository; import org.zalando.nakadi.repository.db.EventTypeCache; import org.zalando.nakadi.repository.db.SubscriptionDbRepository; +import org.zalando.nakadi.service.subscription.LogPathBuilder; import org.zalando.nakadi.service.subscription.model.Partition; import org.zalando.nakadi.service.subscription.state.StartingState; import org.zalando.nakadi.service.subscription.zk.SubscriptionClientFactory; @@ -87,7 +87,7 @@ public List commitCursors(final String streamId, final String subscript validateSubscriptionCommitCursors(subscription, cursors); final ZkSubscriptionClient zkClient = zkSubscriptionFactory.createClient( - subscription, "subscription." + subscriptionId + "." + streamId + ".offsets"); + subscription, LogPathBuilder.build(subscriptionId, streamId, "offsets")); validateStreamId(cursors, streamId, zkClient); @@ -131,7 +131,7 @@ public List getSubscriptionCursors(final String throws NakadiException, ServiceTemporarilyUnavailableException { final Subscription subscription = subscriptionRepository.getSubscription(subscriptionId); final ZkSubscriptionClient zkSubscriptionClient = zkSubscriptionFactory.createClient( - subscription, "subscription." + subscriptionId + ".get_cursors"); + subscription, LogPathBuilder.build(subscriptionId, "get_cursors")); final ImmutableList.Builder cursorsListBuilder = ImmutableList.builder(); Partition[] partitions; @@ -170,7 +170,7 @@ public void resetCursors(final String subscriptionId, final List c } final ZkSubscriptionClient zkClient = zkSubscriptionFactory.createClient( - subscription, "subscription." + subscriptionId + ".reset_cursors"); + subscription, LogPathBuilder.build(subscriptionId, "reset_cursors")); // In case if subscription was never initialized - initialize it zkClient.runLocked(() -> StartingState.initializeSubscriptionLocked( diff --git a/src/main/java/org/zalando/nakadi/service/EventPublisher.java b/src/main/java/org/zalando/nakadi/service/EventPublisher.java index 877f5743bf..9738fe9949 100644 --- a/src/main/java/org/zalando/nakadi/service/EventPublisher.java +++ b/src/main/java/org/zalando/nakadi/service/EventPublisher.java @@ -170,7 +170,7 @@ private void partition(final List batch, final EventType eventType) t } } - private void compact(final List batch, final EventType eventType) { + private void compact(final List batch, final EventType eventType) throws CompactionException { if (eventType.getCleanupPolicy() == CleanupPolicy.COMPACT) { for (final BatchItem item : batch) { final String compactionKey = item.getEvent() diff --git a/src/main/java/org/zalando/nakadi/service/subscription/LogPathBuilder.java b/src/main/java/org/zalando/nakadi/service/subscription/LogPathBuilder.java new file mode 100644 index 0000000000..a6abedb7ab --- /dev/null +++ b/src/main/java/org/zalando/nakadi/service/subscription/LogPathBuilder.java @@ -0,0 +1,11 @@ +package org.zalando.nakadi.service.subscription; + +public class LogPathBuilder { + public static String build(final String subscriptionId, final String addition) { + return "s." + subscriptionId + "." + addition; + } + + public static String build(final String subscriptionId, final String streamId, final String addition) { + return build(subscriptionId, streamId + "." + addition); + } +} diff --git a/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java b/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java index 145b09c923..e78c586ff2 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java @@ -57,7 +57,6 @@ public class StreamingContext implements SubscriptionStreamer { private final ScheduledExecutorService timer; private final BlockingQueue taskQueue = new LinkedBlockingQueue<>(); private final BiFunction, Partition[], Partition[]> rebalancer; - private final String loggingPath; private final CursorConverter cursorConverter; private final Subscription subscription; private final MetricRegistry metricRegistry; @@ -86,8 +85,7 @@ private StreamingContext(final Builder builder) { this.timer = builder.timer; this.zkClient = builder.zkClient; this.kafkaPollTimeout = builder.kafkaPollTimeout; - this.loggingPath = builder.loggingPath + ".stream"; - this.log = LoggerFactory.getLogger(builder.loggingPath); + this.log = LoggerFactory.getLogger(LogPathBuilder.build(builder.subscription.getId(), builder.session.getId())); this.connectionReady = builder.connectionReady; this.timelineService = builder.timelineService; this.cursorTokenService = builder.cursorTokenService; @@ -209,7 +207,7 @@ public void switchState(final State newState) { } finally { currentState = newState; - currentState.setContext(this, loggingPath); + currentState.setContext(this); currentState.onEnter(); } }); @@ -332,7 +330,6 @@ public static final class Builder { private ZkSubscriptionClient zkClient; private BiFunction, Partition[], Partition[]> rebalancer; private long kafkaPollTimeout; - private String loggingPath; private AtomicBoolean connectionReady; private CursorTokenService cursorTokenService; private ObjectMapper objectMapper; @@ -395,11 +392,6 @@ public Builder setKafkaPollTimeout(final long kafkaPollTimeout) { return this; } - public Builder setLoggingPath(final String loggingPath) { - this.loggingPath = loggingPath; - return this; - } - public Builder setConnectionReady(final AtomicBoolean connectionReady) { this.connectionReady = connectionReady; return this; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java index b91d105d2f..ab5593e092 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java @@ -228,7 +228,7 @@ public Result deleteSubscription(final String subscriptionId) throws DbWri subscriptionRepository.deleteSubscription(subscriptionId); final ZkSubscriptionClient zkSubscriptionClient = subscriptionClientFactory.createClient( - subscription, "subscription." + subscriptionId + ".delete_subscription"); + subscription, LogPathBuilder.build(subscriptionId, "delete_subscription")); zkSubscriptionClient.deleteSubscription(); nakadiKpiPublisher.publish(subLogEventType, () -> new JSONObject() @@ -279,7 +279,7 @@ private ZkSubscriptionClient createZkSubscriptionClient(final Subscription subsc throws ServiceTemporarilyUnavailableException { try { return subscriptionClientFactory.createClient(subscription, - "subscription." + subscription.getId() + ".stats"); + LogPathBuilder.build(subscription.getId(), "stats")); } catch (final InternalNakadiException | NoSuchEventTypeException e) { throw new ServiceTemporarilyUnavailableException(e); } diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java index cafd3d2790..fa4d8d4343 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java @@ -86,7 +86,6 @@ public SubscriptionStreamer build( final BlacklistService blacklistService) throws InternalNakadiException, NoSuchEventTypeException { final Session session = Session.generate(1, streamParameters.getPartitions()); - final String loggingPath = "subscription." + subscription.getId() + "." + session.getId(); // Create streaming context return new StreamingContext.Builder() .setOut(output) @@ -94,10 +93,10 @@ public SubscriptionStreamer build( .setParameters(streamParameters) .setSession(session) .setTimer(executorService) - .setZkClient(zkClientFactory.createClient(subscription, loggingPath)) + .setZkClient(zkClientFactory.createClient( + subscription, LogPathBuilder.build(subscription.getId(), session.getId()))) .setRebalancer(new SubscriptionRebalancer()) .setKafkaPollTimeout(kafkaPollTimeout) - .setLoggingPath(loggingPath) .setConnectionReady(connectionReady) .setCursorTokenService(cursorTokenService) .setObjectMapper(objectMapper) diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/State.java b/src/main/java/org/zalando/nakadi/service/subscription/state/State.java index 30aaed2253..6d0ffde7d8 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/State.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/State.java @@ -3,6 +3,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zalando.nakadi.domain.NakadiCursor; +import org.zalando.nakadi.service.subscription.LogPathBuilder; import org.zalando.nakadi.service.subscription.StreamParameters; import org.zalando.nakadi.service.subscription.StreamingContext; import org.zalando.nakadi.service.subscription.SubscriptionOutput; @@ -15,9 +16,12 @@ public abstract class State { private StreamingContext context; private Logger log; - public void setContext(final StreamingContext context, final String loggingPath) { + public void setContext(final StreamingContext context) { this.context = context; - this.log = LoggerFactory.getLogger(loggingPath + "." + this.getClass().getSimpleName()); + this.log = LoggerFactory.getLogger(LogPathBuilder.build( + context.getSubscription().getId(), + context.getSessionId(), + "state." + this.getClass().getSimpleName())); } public Logger getLog() { diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java index 66f7090160..0f0e8fc64d 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java @@ -19,6 +19,7 @@ import org.zalando.nakadi.security.Client; import org.zalando.nakadi.service.NakadiKpiPublisher; import org.zalando.nakadi.service.subscription.IdleStreamWatcher; +import org.zalando.nakadi.service.subscription.LogPathBuilder; import org.zalando.nakadi.service.subscription.model.Partition; import org.zalando.nakadi.service.subscription.zk.ZkSubscription; import org.zalando.nakadi.service.subscription.zk.ZkSubscriptionClient; @@ -359,7 +360,7 @@ public void logExtendedCommitInformation() { final SubscriptionCursorWithoutToken remembered = getContext().getCursorConverter().convertToNoToken(v.getValue().getCommitOffset()); final SubscriptionCursorWithoutToken real = realCommitted.get(v.getKey()); - return real.getOffset().compareTo(remembered.getOffset())> 0; + return real.getOffset().compareTo(remembered.getOffset()) > 0; }) .map(Map.Entry::getKey) .collect(Collectors.toList()); @@ -627,7 +628,8 @@ private void addToStreaming(final Partition partition, getComparator(), subscription, cursor, - LoggerFactory.getLogger("subscription." + getSessionId() + "." + partition.getKey()), + LoggerFactory.getLogger(LogPathBuilder.build( + getContext().getSubscription().getId(), getSessionId(), String.valueOf(partition.getKey()))), System.currentTimeMillis()); offsets.put(partition.getKey(), pd); diff --git a/src/test/java/org/zalando/nakadi/service/subscription/StreamingContextTest.java b/src/test/java/org/zalando/nakadi/service/subscription/StreamingContextTest.java index e6076265e6..770d6de7ee 100644 --- a/src/test/java/org/zalando/nakadi/service/subscription/StreamingContextTest.java +++ b/src/test/java/org/zalando/nakadi/service/subscription/StreamingContextTest.java @@ -5,12 +5,12 @@ import org.junit.Ignore; import org.junit.Test; import org.mockito.Mockito; +import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.service.subscription.model.Session; import org.zalando.nakadi.service.subscription.state.CleanupState; import org.zalando.nakadi.service.subscription.state.DummyState; import org.zalando.nakadi.service.subscription.state.State; -import java.io.IOException; import java.io.OutputStream; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -20,7 +20,7 @@ public class StreamingContextTest { private static StreamingContext createTestContext(final Consumer onException) { final SubscriptionOutput output = new SubscriptionOutput() { @Override - public void onInitialized(final String ignore) throws IOException { + public void onInitialized(final String ignore) { } @Override @@ -39,11 +39,11 @@ public OutputStream getOutputStream() { .setOut(output) .setParameters(null) .setSession(Session.generate(1, ImmutableList.of())) + .setSubscription(new Subscription()) .setTimer(null) .setZkClient(null) .setRebalancer(null) .setKafkaPollTimeout(0) - .setLoggingPath("stream") .setConnectionReady(new AtomicBoolean(true)) .setCursorTokenService(null) .setObjectMapper(null) @@ -87,8 +87,8 @@ public void stateBaseMethodsMustBeCalledOnSwitching() throws InterruptedExceptio final boolean[] contextsSet = new boolean[]{false, false}; final State state1 = new State() { @Override - public void setContext(final StreamingContext context, final String tmp) { - super.setContext(context, tmp); + public void setContext(final StreamingContext context) { + super.setContext(context); contextsSet[0] = null != context; } @@ -106,8 +106,8 @@ public void onExit() { }; final State state2 = new State() { @Override - public void setContext(final StreamingContext context, final String tmp) { - super.setContext(context, tmp); + public void setContext(final StreamingContext context) { + super.setContext(context); contextsSet[1] = true; } diff --git a/src/test/java/org/zalando/nakadi/service/subscription/state/StreamingStateTest.java b/src/test/java/org/zalando/nakadi/service/subscription/state/StreamingStateTest.java index ff760b79f7..c6d42ad2dc 100644 --- a/src/test/java/org/zalando/nakadi/service/subscription/state/StreamingStateTest.java +++ b/src/test/java/org/zalando/nakadi/service/subscription/state/StreamingStateTest.java @@ -86,7 +86,7 @@ public void prepareMocks() throws Exception { ); when(contextMock.getParameters()).thenReturn(spMock); - state.setContext(contextMock, "test"); + state.setContext(contextMock); } @Test From 357555969168740c0fd0fd225144ac4ddc2aa50b Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Wed, 8 Aug 2018 17:31:12 +0200 Subject: [PATCH 058/176] Add CODEOWNERS file --- .github/CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..0888a31a7b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @zalando/team-nakadi \ No newline at end of file From c203eab9fa3df194905c3875525a9e241a8057b6 Mon Sep 17 00:00:00 2001 From: Matthew de Detrich Date: Tue, 14 Aug 2018 16:07:54 +0200 Subject: [PATCH 059/176] Add Kanadi client to documentation --- docs/_documentation/using_clients.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/_documentation/using_clients.md b/docs/_documentation/using_clients.md index 010cad83b9..dc6710e538 100644 --- a/docs/_documentation/using_clients.md +++ b/docs/_documentation/using_clients.md @@ -12,6 +12,7 @@ Nakadi does not ship with a client, but there are some open source clients avail | Nakadi Java | Java | | | Fahrschein | Java | | | Riptide: Stream | Java/Spring | | +| Kanadi | Scala | | | Nakadion | Rust | | | nakadi-client | Haskell | | | go-nakadi | Go | | From 86ff082bd84aadf424a0cee067cc6b20716ad89b Mon Sep 17 00:00:00 2001 From: Andrey Dyachkov Date: Wed, 15 Aug 2018 15:57:02 +0200 Subject: [PATCH 060/176] bump deps versions --- build.gradle | 15 ++++----------- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 0f73570bbb..0a1535516a 100644 --- a/build.gradle +++ b/build.gradle @@ -2,9 +2,7 @@ import java.util.concurrent.TimeUnit buildscript { ext { - springBootVersion = '1.5.14.RELEASE' - springFrameworkVersion = '4.3.18.RELEASE' - jacksonVersion = '2.9.6' + springBootVersion = '1.5.15.RELEASE' } repositories { @@ -29,7 +27,7 @@ plugins { id 'findbugs' id 'checkstyle' id 'project-report' - id 'org.springframework.boot' version "1.5.14.RELEASE" + id 'org.springframework.boot' } apply plugin: 'io.spring.dependency-management' @@ -43,9 +41,6 @@ springBoot { layout = "ZIP" } -def dockerGroup = "aruha" -def dockerApplicationName = "nakadi" - repositories { mavenCentral() maven { url 'https://jitpack.io' } @@ -98,7 +93,6 @@ dependencies { ext['json-path'] = '2.4.0' ext['jsonassert'] = '1.5.0' ext['postgresql.version'] = '42.2.2' - ext['spring-security-oauth2.version'] = '2.3.3.RELEASE' // spring compile("org.springframework.boot:spring-boot-starter-web") { @@ -109,7 +103,6 @@ dependencies { compile "org.springframework:spring-context" compile "org.springframework:spring-web" compile "org.springframework:spring-webmvc" - compile "org.springframework.boot:spring-boot-test" compile "org.springframework.boot:spring-boot-starter-jetty" // oauth @@ -130,11 +123,11 @@ dependencies { compile "org.springframework.boot:spring-boot-starter-jdbc" compile 'org.postgresql:postgresql' - compile 'org.springframework.cloud:spring-cloud-starter-hystrix:1.4.4.RELEASE' + compile 'org.springframework.cloud:spring-cloud-starter-hystrix:1.4.5.RELEASE' // misc compile 'org.apache.httpcomponents:httpclient' - compile('org.zalando.stups:stups-spring-oauth2-server:1.0.21') { + compile('org.zalando.stups:stups-spring-oauth2-server:1.0.22') { exclude module: "httpclient" } compile 'org.zalando:jackson-datatype-problem:0.5.0' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index debd024022..7dc503f149 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From a1abea91ace92a348c6132cb335730bd74bcbf7e Mon Sep 17 00:00:00 2001 From: Andrey Dyachkov Date: Wed, 15 Aug 2018 16:24:07 +0200 Subject: [PATCH 061/176] apply plugins --- build.gradle | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/build.gradle b/build.gradle index 0a1535516a..0be33a08e8 100644 --- a/build.gradle +++ b/build.gradle @@ -13,23 +13,20 @@ buildscript { } dependencies { - classpath "org.springframework.boot:spring-boot-gradle-plugin" + classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" classpath 'org.yaml:snakeyaml:1.21' } } -plugins { - id 'java' - id 'groovy' - id 'eclipse' - id 'application' - id 'jacoco' - id 'findbugs' - id 'checkstyle' - id 'project-report' - id 'org.springframework.boot' -} - +apply plugin: 'java' +apply plugin: 'groovy' +apply plugin: 'eclipse' +apply plugin: 'application' +apply plugin: 'jacoco' +apply plugin: 'findbugs' +apply plugin: 'checkstyle' +apply plugin: 'project-report' +apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' group 'org.zalando' @@ -106,7 +103,7 @@ dependencies { compile "org.springframework.boot:spring-boot-starter-jetty" // oauth - compile ('org.springframework.security.oauth:spring-security-oauth2') { + compile('org.springframework.security.oauth:spring-security-oauth2') { exclude module: 'spring-beans' exclude module: 'spring-core' exclude module: 'spring-context' From e38708a5ba60f9c8cb4e4554a16e5daab9890000 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Wed, 15 Aug 2018 17:08:04 +0200 Subject: [PATCH 062/176] Remane MyNakadiRuntimeException1 to NakadiRuntimeBaseException --- .../nakadi/controller/CursorOperationsController.java | 6 +++--- .../org/zalando/nakadi/controller/ExceptionHandling.java | 6 +++--- .../zalando/nakadi/controller/PartitionsController.java | 4 ++-- .../nakadi/controller/PostSubscriptionController.java | 4 ++-- src/main/java/org/zalando/nakadi/domain/NakadiCursor.java | 4 ++-- .../exceptions/ErrorGettingCursorTimeLagException.java | 4 ++-- .../nakadi/exceptions/runtime/AccessDeniedException.java | 2 +- .../nakadi/exceptions/runtime/ConflictException.java | 2 +- .../runtime/ConnectionSlotOccupiedException.java | 2 +- .../exceptions/runtime/CursorConversionException.java | 2 +- .../exceptions/runtime/CursorsAreEmptyException.java | 2 +- .../runtime/DbWriteOperationsBlockedException.java | 2 +- .../runtime/DuplicatedEventTypeNameException.java | 2 +- .../exceptions/runtime/DuplicatedStorageException.java | 2 +- .../runtime/DuplicatedSubscriptionException.java | 2 +- .../exceptions/runtime/DuplicatedTimelineException.java | 2 +- .../exceptions/runtime/EventPublishingException.java | 2 +- .../exceptions/runtime/EventTypeDeletionException.java | 2 +- .../runtime/EventTypeOptionsValidationException.java | 2 +- .../exceptions/runtime/EventTypeTimeoutException.java | 2 +- .../exceptions/runtime/EventTypeUnavailableException.java | 2 +- .../exceptions/runtime/EventValidationException.java | 2 +- .../exceptions/runtime/FeatureNotAvailableException.java | 2 +- .../exceptions/runtime/IllegalClientIdException.java | 2 +- .../exceptions/runtime/InconsistentStateException.java | 2 +- .../nakadi/exceptions/runtime/InvalidCursorOperation.java | 2 +- .../exceptions/runtime/InvalidEventTypeException.java | 2 +- .../exceptions/runtime/InvalidStreamIdException.java | 2 +- .../nakadi/exceptions/runtime/LimitReachedException.java | 2 +- ...imeException1.java => NakadiRuntimeBaseException.java} | 8 ++++---- .../exceptions/runtime/NoConnectionSlotsException.java | 2 +- .../nakadi/exceptions/runtime/NoEventTypeException.java | 2 +- .../nakadi/exceptions/runtime/NoStorageException.java | 2 +- .../exceptions/runtime/NoSubscriptionException.java | 2 +- .../nakadi/exceptions/runtime/NotFoundException.java | 2 +- .../exceptions/runtime/OperationInterruptedException.java | 2 +- .../exceptions/runtime/OperationTimeoutException.java | 2 +- .../exceptions/runtime/RebalanceConflictException.java | 2 +- .../exceptions/runtime/RepositoryProblemException.java | 2 +- .../exceptions/runtime/RequestInProgressException.java | 2 +- .../runtime/ServiceTemporarilyUnavailableException.java | 2 +- .../nakadi/exceptions/runtime/StorageIsUsedException.java | 2 +- .../runtime/SubscriptionPartitionConflictException.java | 2 +- .../runtime/SubscriptionUpdateConflictException.java | 2 +- .../exceptions/runtime/TimeLagStatsTimeoutException.java | 2 +- .../nakadi/exceptions/runtime/TimelineException.java | 2 +- .../runtime/TimelinesNotSupportedException.java | 2 +- .../exceptions/runtime/TooManyPartitionsException.java | 2 +- .../nakadi/exceptions/runtime/TopicConfigException.java | 2 +- .../nakadi/exceptions/runtime/TopicCreationException.java | 2 +- .../nakadi/exceptions/runtime/TopicDeletionException.java | 2 +- .../exceptions/runtime/TopicRepositoryException.java | 2 +- .../nakadi/exceptions/runtime/UnableProcessException.java | 2 +- .../exceptions/runtime/UnknownOperationException.java | 2 +- .../exceptions/runtime/UnknownStorageTypeException.java | 2 +- .../exceptions/runtime/UnparseableCursorException.java | 2 +- .../exceptions/runtime/WrongInitialCursorsException.java | 2 +- .../runtime/WrongStreamParametersException.java | 2 +- .../nakadi/exceptions/runtime/ZookeeperException.java | 2 +- .../zalando/nakadi/service/CursorOperationsService.java | 4 ++-- .../service/subscription/SubscriptionTimeLagService.java | 6 +++--- .../nakadi/service/subscription/state/ClosingState.java | 4 ++-- .../subscription/zk/AbstractZkSubscriptionClient.java | 4 ++-- .../zk/SubscriptionNotInitializedException.java | 4 ++-- .../service/subscription/zk/ZkSubscriptionClient.java | 4 ++-- 65 files changed, 83 insertions(+), 83 deletions(-) rename src/main/java/org/zalando/nakadi/exceptions/runtime/{MyNakadiRuntimeException1.java => NakadiRuntimeBaseException.java} (53%) diff --git a/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java b/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java index 3a10cdb7ee..606b71f954 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java @@ -22,7 +22,7 @@ import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.CursorConversionException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; -import org.zalando.nakadi.exceptions.runtime.MyNakadiRuntimeException1; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.repository.EventTypeRepository; import org.zalando.nakadi.service.AuthorizationValidator; @@ -83,7 +83,7 @@ public ResponseEntity getDistance(@PathVariable("eventTypeName") final String final Long distance = cursorOperationsService.calculateDistance(initialCursor, finalCursor); query.setDistance(distance); } catch (InternalNakadiException | ServiceTemporarilyUnavailableException e) { - throw new MyNakadiRuntimeException1("problem calculating cursors distance", e); + throw new NakadiRuntimeBaseException("problem calculating cursors distance", e); } catch (final NoSuchEventTypeException e) { throw new NotFoundException("event type not found", e); } catch (final InvalidCursorException e) { @@ -151,7 +151,7 @@ private String clientErrorMessage(final InvalidCursorOperation.Reason reason) { "have matching partitions."; default: LOG.error("Unexpected invalid cursor operation reason " + reason); - throw new MyNakadiRuntimeException1(); + throw new NakadiRuntimeBaseException(); } } diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 2ada606512..033d3eeb46 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -20,7 +20,7 @@ import org.zalando.nakadi.exceptions.runtime.CursorsAreEmptyException; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; import org.zalando.nakadi.exceptions.runtime.LimitReachedException; -import org.zalando.nakadi.exceptions.runtime.MyNakadiRuntimeException1; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; @@ -120,8 +120,8 @@ public ResponseEntity handleRepositoryProblem(final RepositoryProblemEx return Responses.create(Response.Status.SERVICE_UNAVAILABLE, exception.getMessage(), request); } - @ExceptionHandler(MyNakadiRuntimeException1.class) - public ResponseEntity handleInternalError(final MyNakadiRuntimeException1 exception, + @ExceptionHandler(NakadiRuntimeBaseException.class) + public ResponseEntity handleInternalError(final NakadiRuntimeBaseException exception, final NativeWebRequest request) { LOG.error("Unexpected problem occurred", exception); return Responses.create(Response.Status.INTERNAL_SERVER_ERROR, exception.getMessage(), request); diff --git a/src/main/java/org/zalando/nakadi/controller/PartitionsController.java b/src/main/java/org/zalando/nakadi/controller/PartitionsController.java index 55233a438a..3203bd2256 100644 --- a/src/main/java/org/zalando/nakadi/controller/PartitionsController.java +++ b/src/main/java/org/zalando/nakadi/controller/PartitionsController.java @@ -23,7 +23,7 @@ import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; -import org.zalando.nakadi.exceptions.runtime.MyNakadiRuntimeException1; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.repository.EventTypeRepository; @@ -163,7 +163,7 @@ private CursorLag getCursorLag(final String eventTypeName, final String partitio .stream() .findFirst() .map(this::toCursorLag) - .orElseThrow(MyNakadiRuntimeException1::new); + .orElseThrow(NakadiRuntimeBaseException::new); } private EventTypePartitionView getTopicPartition(final String eventTypeName, final String partition) diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index 4a4a56d368..d71baa88ec 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -19,7 +19,7 @@ import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.DuplicatedSubscriptionException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; -import org.zalando.nakadi.exceptions.runtime.MyNakadiRuntimeException1; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSubscriptionException; import org.zalando.nakadi.exceptions.runtime.SubscriptionUpdateConflictException; @@ -119,7 +119,7 @@ private ResponseEntity prepareLocationResponse(final Subscription subscriptio NoEventTypeException.class, WrongInitialCursorsException.class, TooManyPartitionsException.class}) - public ResponseEntity handleUnprocessableSubscription(final MyNakadiRuntimeException1 exception, + public ResponseEntity handleUnprocessableSubscription(final NakadiRuntimeBaseException exception, final NativeWebRequest request) { LOG.debug("Error occurred when working with subscriptions", exception); return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, exception.getMessage(), request); diff --git a/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java b/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java index 2541bcd32b..aada4785fa 100644 --- a/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java +++ b/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java @@ -2,7 +2,7 @@ import com.google.common.base.Preconditions; import org.zalando.nakadi.exceptions.InvalidCursorException; -import org.zalando.nakadi.exceptions.runtime.MyNakadiRuntimeException1; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.repository.kafka.KafkaCursor; import java.util.Objects; @@ -118,7 +118,7 @@ public static NakadiCursor of(final Timeline timeline, final String partition, f case KAFKA: return new NakadiKafkaCursor(timeline, partition, offset); default: - throw new MyNakadiRuntimeException1( + throw new NakadiRuntimeBaseException( "Cursor storage type " + timeline.getStorage().getType() + " not supported"); } } diff --git a/src/main/java/org/zalando/nakadi/exceptions/ErrorGettingCursorTimeLagException.java b/src/main/java/org/zalando/nakadi/exceptions/ErrorGettingCursorTimeLagException.java index fe442242a0..0ea8a6424b 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/ErrorGettingCursorTimeLagException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/ErrorGettingCursorTimeLagException.java @@ -1,9 +1,9 @@ package org.zalando.nakadi.exceptions; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.runtime.MyNakadiRuntimeException1; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; -public class ErrorGettingCursorTimeLagException extends MyNakadiRuntimeException1 { +public class ErrorGettingCursorTimeLagException extends NakadiRuntimeBaseException { private final NakadiCursor failedCursor; diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/AccessDeniedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/AccessDeniedException.java index f7771bacc4..ce1c6211fe 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/AccessDeniedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/AccessDeniedException.java @@ -3,7 +3,7 @@ import org.zalando.nakadi.plugin.api.authz.AuthorizationService; import org.zalando.nakadi.plugin.api.authz.Resource; -public class AccessDeniedException extends MyNakadiRuntimeException1 { +public class AccessDeniedException extends NakadiRuntimeBaseException { private final Resource resource; private final AuthorizationService.Operation operation; diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/ConflictException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/ConflictException.java index fda674780e..00ef12008e 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/ConflictException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/ConflictException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class ConflictException extends MyNakadiRuntimeException1 { +public class ConflictException extends NakadiRuntimeBaseException { public ConflictException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/ConnectionSlotOccupiedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/ConnectionSlotOccupiedException.java index a832ffe4cf..3b92672363 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/ConnectionSlotOccupiedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/ConnectionSlotOccupiedException.java @@ -1,4 +1,4 @@ package org.zalando.nakadi.exceptions.runtime; -public class ConnectionSlotOccupiedException extends MyNakadiRuntimeException1 { +public class ConnectionSlotOccupiedException extends NakadiRuntimeBaseException { } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorConversionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorConversionException.java index 1e8564c883..430893252c 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorConversionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorConversionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class CursorConversionException extends MyNakadiRuntimeException1 { +public class CursorConversionException extends NakadiRuntimeBaseException { public CursorConversionException(final String message, final Exception e) { super(message, e); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorsAreEmptyException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorsAreEmptyException.java index f51fcc795a..a47d48deb4 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorsAreEmptyException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorsAreEmptyException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class CursorsAreEmptyException extends MyNakadiRuntimeException1 { +public class CursorsAreEmptyException extends NakadiRuntimeBaseException { public CursorsAreEmptyException() { super("Cursors are empty"); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/DbWriteOperationsBlockedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/DbWriteOperationsBlockedException.java index eb4fbebf4b..470810556f 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/DbWriteOperationsBlockedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/DbWriteOperationsBlockedException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class DbWriteOperationsBlockedException extends MyNakadiRuntimeException1 { +public class DbWriteOperationsBlockedException extends NakadiRuntimeBaseException { public DbWriteOperationsBlockedException(final String message) { super(message); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedEventTypeNameException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedEventTypeNameException.java index 5675698358..77d25022e6 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedEventTypeNameException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedEventTypeNameException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class DuplicatedEventTypeNameException extends MyNakadiRuntimeException1 { +public class DuplicatedEventTypeNameException extends NakadiRuntimeBaseException { public DuplicatedEventTypeNameException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedStorageException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedStorageException.java index 6ec7a94f80..3523046baf 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedStorageException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedStorageException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class DuplicatedStorageException extends MyNakadiRuntimeException1 { +public class DuplicatedStorageException extends NakadiRuntimeBaseException { public DuplicatedStorageException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedSubscriptionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedSubscriptionException.java index b8dfbedc55..2851397946 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedSubscriptionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedSubscriptionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class DuplicatedSubscriptionException extends MyNakadiRuntimeException1 { +public class DuplicatedSubscriptionException extends NakadiRuntimeBaseException { public DuplicatedSubscriptionException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedTimelineException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedTimelineException.java index 3d53a093e1..06613132a0 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedTimelineException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedTimelineException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class DuplicatedTimelineException extends MyNakadiRuntimeException1 { +public class DuplicatedTimelineException extends NakadiRuntimeBaseException { public DuplicatedTimelineException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventPublishingException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventPublishingException.java index 4798068041..a079a8b6a4 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventPublishingException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventPublishingException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventPublishingException extends MyNakadiRuntimeException1 { +public class EventPublishingException extends NakadiRuntimeBaseException { public EventPublishingException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeDeletionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeDeletionException.java index 1e8ace53ad..040b72e1df 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeDeletionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeDeletionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventTypeDeletionException extends MyNakadiRuntimeException1 { +public class EventTypeDeletionException extends NakadiRuntimeBaseException { public EventTypeDeletionException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeOptionsValidationException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeOptionsValidationException.java index 47288f648a..c58f7fab04 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeOptionsValidationException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeOptionsValidationException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventTypeOptionsValidationException extends MyNakadiRuntimeException1 { +public class EventTypeOptionsValidationException extends NakadiRuntimeBaseException { public EventTypeOptionsValidationException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeTimeoutException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeTimeoutException.java index 6047766269..4e5a24bfa3 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeTimeoutException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeTimeoutException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventTypeTimeoutException extends MyNakadiRuntimeException1 { +public class EventTypeTimeoutException extends NakadiRuntimeBaseException { public EventTypeTimeoutException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeUnavailableException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeUnavailableException.java index 7cf3e0aa07..263d3c8c04 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeUnavailableException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeUnavailableException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventTypeUnavailableException extends MyNakadiRuntimeException1 { +public class EventTypeUnavailableException extends NakadiRuntimeBaseException { public EventTypeUnavailableException(final String message) { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventValidationException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventValidationException.java index 43dd4c46e2..a67a4b79e5 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventValidationException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventValidationException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventValidationException extends MyNakadiRuntimeException1 { +public class EventValidationException extends NakadiRuntimeBaseException { public EventValidationException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/FeatureNotAvailableException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/FeatureNotAvailableException.java index 2a34e66d28..0d50d39bc6 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/FeatureNotAvailableException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/FeatureNotAvailableException.java @@ -2,7 +2,7 @@ import org.zalando.nakadi.service.FeatureToggleService; -public class FeatureNotAvailableException extends MyNakadiRuntimeException1 { +public class FeatureNotAvailableException extends NakadiRuntimeBaseException { private final FeatureToggleService.Feature feature; public FeatureNotAvailableException(final String message, final FeatureToggleService.Feature feature) { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/IllegalClientIdException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/IllegalClientIdException.java index bc56ecbb46..9ddd952efd 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/IllegalClientIdException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/IllegalClientIdException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class IllegalClientIdException extends MyNakadiRuntimeException1 { +public class IllegalClientIdException extends NakadiRuntimeBaseException { public IllegalClientIdException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InconsistentStateException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InconsistentStateException.java index ba3bc8d709..138b1c3e74 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/InconsistentStateException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InconsistentStateException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class InconsistentStateException extends MyNakadiRuntimeException1 { +public class InconsistentStateException extends NakadiRuntimeBaseException { public InconsistentStateException(final String msg, final Throwable cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorOperation.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorOperation.java index b9244e543d..c7b653891c 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorOperation.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorOperation.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class InvalidCursorOperation extends MyNakadiRuntimeException1 { +public class InvalidCursorOperation extends NakadiRuntimeBaseException { private final Reason reason; public enum Reason { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidEventTypeException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidEventTypeException.java index 7f713053bb..ae18bbd44e 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidEventTypeException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidEventTypeException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class InvalidEventTypeException extends MyNakadiRuntimeException1 { +public class InvalidEventTypeException extends NakadiRuntimeBaseException { public InvalidEventTypeException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidStreamIdException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidStreamIdException.java index fec377a6a8..795f8338c7 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidStreamIdException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidStreamIdException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class InvalidStreamIdException extends MyNakadiRuntimeException1 { +public class InvalidStreamIdException extends NakadiRuntimeBaseException { private final String streamId; diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/LimitReachedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/LimitReachedException.java index 176632da4a..af2c96cb33 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/LimitReachedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/LimitReachedException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class LimitReachedException extends MyNakadiRuntimeException1 { +public class LimitReachedException extends NakadiRuntimeBaseException { public LimitReachedException(final String msg, final Throwable cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/MyNakadiRuntimeException1.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiRuntimeBaseException.java similarity index 53% rename from src/main/java/org/zalando/nakadi/exceptions/runtime/MyNakadiRuntimeException1.java rename to src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiRuntimeBaseException.java index 568bce1346..163df2d624 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/MyNakadiRuntimeException1.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiRuntimeBaseException.java @@ -4,16 +4,16 @@ * Parent class for Nakadi runtime exceptions * Name NakadiRuntimeException was already taken for some kind of wrapper. This name is a nice alternative ;) */ -public class MyNakadiRuntimeException1 extends RuntimeException { +public class NakadiRuntimeBaseException extends RuntimeException { - public MyNakadiRuntimeException1() { + public NakadiRuntimeBaseException() { } - public MyNakadiRuntimeException1(final String message) { + public NakadiRuntimeBaseException(final String message) { super(message); } - public MyNakadiRuntimeException1(final String message, final Throwable cause) { + public NakadiRuntimeBaseException(final String message, final Throwable cause) { super(message, cause); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoConnectionSlotsException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoConnectionSlotsException.java index f8934968cd..5f4b849452 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoConnectionSlotsException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoConnectionSlotsException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NoConnectionSlotsException extends MyNakadiRuntimeException1 { +public class NoConnectionSlotsException extends NakadiRuntimeBaseException { public NoConnectionSlotsException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java index 438433dd7c..3eb699ebce 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java @@ -2,7 +2,7 @@ import org.zalando.nakadi.exceptions.NoSuchEventTypeException; -public class NoEventTypeException extends MyNakadiRuntimeException1 { +public class NoEventTypeException extends NakadiRuntimeBaseException { public NoEventTypeException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStorageException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStorageException.java index c32d4262c8..87ea1dd21a 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStorageException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStorageException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NoStorageException extends MyNakadiRuntimeException1 { +public class NoStorageException extends NakadiRuntimeBaseException { public NoStorageException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSubscriptionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSubscriptionException.java index 32a7900f1f..664b8b65ee 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSubscriptionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSubscriptionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NoSubscriptionException extends MyNakadiRuntimeException1 { +public class NoSubscriptionException extends NakadiRuntimeBaseException { public NoSubscriptionException(final String message, final Throwable cause) { super(message, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NotFoundException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NotFoundException.java index deac2c52ac..b6ba3f2a18 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NotFoundException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NotFoundException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NotFoundException extends MyNakadiRuntimeException1 { +public class NotFoundException extends NakadiRuntimeBaseException { public NotFoundException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationInterruptedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationInterruptedException.java index 9b860a1be5..19a47d4274 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationInterruptedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationInterruptedException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class OperationInterruptedException extends MyNakadiRuntimeException1 { +public class OperationInterruptedException extends NakadiRuntimeBaseException { public OperationInterruptedException(final String message, final Throwable cause) { super(message, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationTimeoutException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationTimeoutException.java index e8e598346c..17b469573b 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationTimeoutException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationTimeoutException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class OperationTimeoutException extends MyNakadiRuntimeException1 { +public class OperationTimeoutException extends NakadiRuntimeBaseException { public OperationTimeoutException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/RebalanceConflictException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/RebalanceConflictException.java index 60d29c255b..46147b8dcd 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/RebalanceConflictException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/RebalanceConflictException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class RebalanceConflictException extends MyNakadiRuntimeException1 { +public class RebalanceConflictException extends NakadiRuntimeBaseException { public RebalanceConflictException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/RepositoryProblemException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/RepositoryProblemException.java index 6b268e5347..df029689ba 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/RepositoryProblemException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/RepositoryProblemException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class RepositoryProblemException extends MyNakadiRuntimeException1 { +public class RepositoryProblemException extends NakadiRuntimeBaseException { public RepositoryProblemException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/RequestInProgressException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/RequestInProgressException.java index 540915b887..0ed8671099 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/RequestInProgressException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/RequestInProgressException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class RequestInProgressException extends MyNakadiRuntimeException1 { +public class RequestInProgressException extends NakadiRuntimeBaseException { public RequestInProgressException(final String message, final Throwable cause) { super(message, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/ServiceTemporarilyUnavailableException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/ServiceTemporarilyUnavailableException.java index a543c9a41e..5e4106191f 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/ServiceTemporarilyUnavailableException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/ServiceTemporarilyUnavailableException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class ServiceTemporarilyUnavailableException extends MyNakadiRuntimeException1 { +public class ServiceTemporarilyUnavailableException extends NakadiRuntimeBaseException { public ServiceTemporarilyUnavailableException(final Exception cause) { super(cause.getMessage(), cause); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/StorageIsUsedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/StorageIsUsedException.java index 1992c1efee..1a757ad266 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/StorageIsUsedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/StorageIsUsedException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class StorageIsUsedException extends MyNakadiRuntimeException1 { +public class StorageIsUsedException extends NakadiRuntimeBaseException { public StorageIsUsedException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionPartitionConflictException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionPartitionConflictException.java index 1eca7c8571..d20fb3dff8 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionPartitionConflictException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionPartitionConflictException.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.stream.Collectors; -public class SubscriptionPartitionConflictException extends MyNakadiRuntimeException1 { +public class SubscriptionPartitionConflictException extends NakadiRuntimeBaseException { private SubscriptionPartitionConflictException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java index ebe50acf0c..018b58ccf3 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class SubscriptionUpdateConflictException extends MyNakadiRuntimeException1 { +public class SubscriptionUpdateConflictException extends NakadiRuntimeBaseException { public SubscriptionUpdateConflictException(final String message) { super(message); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimeLagStatsTimeoutException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimeLagStatsTimeoutException.java index 9eec9d7a5e..c59bbf759b 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimeLagStatsTimeoutException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimeLagStatsTimeoutException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TimeLagStatsTimeoutException extends MyNakadiRuntimeException1 { +public class TimeLagStatsTimeoutException extends NakadiRuntimeBaseException { public TimeLagStatsTimeoutException(final String msg, final Throwable cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelineException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelineException.java index 6830f97ba0..2852de605d 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelineException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelineException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TimelineException extends MyNakadiRuntimeException1 { +public class TimelineException extends NakadiRuntimeBaseException { public TimelineException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelinesNotSupportedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelinesNotSupportedException.java index 5b4a8d08ff..d3ef47034f 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelinesNotSupportedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelinesNotSupportedException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TimelinesNotSupportedException extends MyNakadiRuntimeException1 { +public class TimelinesNotSupportedException extends NakadiRuntimeBaseException { public TimelinesNotSupportedException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TooManyPartitionsException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TooManyPartitionsException.java index ee3faaf953..08a597f18b 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TooManyPartitionsException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TooManyPartitionsException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TooManyPartitionsException extends MyNakadiRuntimeException1 { +public class TooManyPartitionsException extends NakadiRuntimeBaseException { public TooManyPartitionsException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicConfigException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicConfigException.java index a0379ed1d8..6a9c970f47 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicConfigException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicConfigException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TopicConfigException extends MyNakadiRuntimeException1 { +public class TopicConfigException extends NakadiRuntimeBaseException { public TopicConfigException(final String message, final Exception e) { super(message, e); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicCreationException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicCreationException.java index 5913aa4e21..a4eaa41df2 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicCreationException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicCreationException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TopicCreationException extends MyNakadiRuntimeException1 { +public class TopicCreationException extends NakadiRuntimeBaseException { public TopicCreationException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicDeletionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicDeletionException.java index fb56e71dd4..f247c672f5 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicDeletionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicDeletionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TopicDeletionException extends MyNakadiRuntimeException1 { +public class TopicDeletionException extends NakadiRuntimeBaseException { public TopicDeletionException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicRepositoryException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicRepositoryException.java index cce6f570dc..09798fa6c5 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicRepositoryException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicRepositoryException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TopicRepositoryException extends MyNakadiRuntimeException1 { +public class TopicRepositoryException extends NakadiRuntimeBaseException { public TopicRepositoryException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnableProcessException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnableProcessException.java index 5e6af521a4..bd6e6f0d5c 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnableProcessException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnableProcessException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class UnableProcessException extends MyNakadiRuntimeException1 { +public class UnableProcessException extends NakadiRuntimeBaseException { public UnableProcessException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownOperationException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownOperationException.java index 15abf9a159..8c3ae410cc 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownOperationException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownOperationException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class UnknownOperationException extends MyNakadiRuntimeException1 { +public class UnknownOperationException extends NakadiRuntimeBaseException { public UnknownOperationException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownStorageTypeException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownStorageTypeException.java index 603db17a1b..cc9860bbd0 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownStorageTypeException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownStorageTypeException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class UnknownStorageTypeException extends MyNakadiRuntimeException1 { +public class UnknownStorageTypeException extends NakadiRuntimeBaseException { public UnknownStorageTypeException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnparseableCursorException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnparseableCursorException.java index d257e0e7e0..361f16a46d 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnparseableCursorException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnparseableCursorException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class UnparseableCursorException extends MyNakadiRuntimeException1 { +public class UnparseableCursorException extends NakadiRuntimeBaseException { private final String cursors; public UnparseableCursorException(final String msg, final Exception cause, final String cursors) { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongInitialCursorsException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongInitialCursorsException.java index 977524a9e4..8155f8a8c0 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongInitialCursorsException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongInitialCursorsException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class WrongInitialCursorsException extends MyNakadiRuntimeException1 { +public class WrongInitialCursorsException extends NakadiRuntimeBaseException { public WrongInitialCursorsException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongStreamParametersException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongStreamParametersException.java index b95549c8c7..cd99b213d8 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongStreamParametersException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongStreamParametersException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class WrongStreamParametersException extends MyNakadiRuntimeException1 { +public class WrongStreamParametersException extends NakadiRuntimeBaseException { public WrongStreamParametersException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/ZookeeperException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/ZookeeperException.java index eb656c8948..a57ee45af4 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/ZookeeperException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/ZookeeperException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class ZookeeperException extends MyNakadiRuntimeException1 { +public class ZookeeperException extends NakadiRuntimeBaseException { public ZookeeperException(final String message, final Throwable cause) { super(message, cause); diff --git a/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java b/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java index 098f862e4f..ec6f6074d6 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java @@ -13,7 +13,7 @@ import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; -import org.zalando.nakadi.exceptions.runtime.MyNakadiRuntimeException1; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.UnknownStorageTypeException; import org.zalando.nakadi.repository.kafka.KafkaCursor; @@ -108,7 +108,7 @@ public List cursorsLag(final String eventTypeName, final List getTimeLags(final Collection(listeners.keySet())); - } catch (final NakadiRuntimeException | MyNakadiRuntimeException1 ex) { + } catch (final NakadiRuntimeException | NakadiRuntimeBaseException ex) { // In order not to stuck here one will just log this exception, without rethrowing getLog().error("Failed to transfer partitions when leaving ClosingState", ex); } finally { diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java index 4b9d9aa2cd..ae6600d600 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java @@ -14,7 +14,7 @@ import org.zalando.nakadi.domain.EventTypePartition; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.UnableProcessException; -import org.zalando.nakadi.exceptions.runtime.MyNakadiRuntimeException1; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.OperationInterruptedException; import org.zalando.nakadi.exceptions.runtime.OperationTimeoutException; import org.zalando.nakadi.exceptions.runtime.RequestInProgressException; @@ -112,7 +112,7 @@ public final T runLocked(final Callable function) { throw releaseException; } return result; - } catch (final NakadiRuntimeException | MyNakadiRuntimeException1 e) { + } catch (final NakadiRuntimeException | NakadiRuntimeBaseException e) { throw e; } catch (final Exception e) { throw new NakadiRuntimeException(e); diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionNotInitializedException.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionNotInitializedException.java index e462991ea4..5cf82a40b2 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionNotInitializedException.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionNotInitializedException.java @@ -1,8 +1,8 @@ package org.zalando.nakadi.service.subscription.zk; -import org.zalando.nakadi.exceptions.runtime.MyNakadiRuntimeException1; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; -public class SubscriptionNotInitializedException extends MyNakadiRuntimeException1 { +public class SubscriptionNotInitializedException extends NakadiRuntimeBaseException { public SubscriptionNotInitializedException(final String subscriptionId) { super("Subscription " + subscriptionId + " is not initialized"); diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java index 64bdcca3e2..1c4cedbf67 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java @@ -4,7 +4,7 @@ import org.apache.commons.codec.binary.Hex; import org.zalando.nakadi.domain.EventTypePartition; import org.zalando.nakadi.exceptions.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.runtime.MyNakadiRuntimeException1; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.OperationTimeoutException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.ZookeeperException; @@ -214,7 +214,7 @@ public Topology withUpdatedPartitions(final String newHash, final Partition[] pa } } if (selectedIdx < 0) { - throw new MyNakadiRuntimeException1( + throw new NakadiRuntimeBaseException( "Failed to find partition " + newValue.getKey() + " in " + this); } resultPartitions[selectedIdx] = newValue; From acb21663ffc8bef58dc25be3175d82af614c5aac Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Wed, 15 Aug 2018 18:18:13 +0200 Subject: [PATCH 063/176] Remove UnprocessableEntityException --- .../controller/EventStreamController.java | 4 ++ .../controller/EventTypeController.java | 2 +- .../nakadi/controller/ExceptionHandling.java | 41 +++++++++++++++++++ .../controller/SubscriptionController.java | 2 +- .../zalando/nakadi/enrichment/Enrichment.java | 2 +- .../nakadi/enrichment/EnrichmentStrategy.java | 2 +- .../MetadataEnrichmentStrategy.java | 2 +- .../exceptions/CompactionException.java | 9 ---- .../NoSuchPartitionStrategyException.java | 9 ---- .../exceptions/PartitioningException.java | 15 ------- .../UnprocessableEntityException.java | 24 ----------- .../runtime/CompactionException.java | 9 ++++ .../{ => runtime}/EnrichmentException.java | 4 +- .../ErrorGettingCursorTimeLagException.java | 3 +- .../runtime/InvalidLimitException.java | 8 ++++ .../InvalidPartitionKeyFieldsException.java | 5 +-- .../NoSuchPartitionStrategyException.java | 9 ++++ .../runtime/PartitioningException.java | 11 +++++ .../partitioning/HashPartitionStrategy.java | 2 +- .../partitioning/PartitionResolver.java | 4 +- .../partitioning/PartitionStrategy.java | 2 +- .../UserDefinedPartitionStrategy.java | 2 +- .../nakadi/service/EventPublisher.java | 6 +-- .../nakadi/service/EventStreamConfig.java | 10 ++--- .../nakadi/service/EventTypeService.java | 2 +- .../SubscriptionTimeLagService.java | 2 +- .../zalando/nakadi/util/JsonPathAccess.java | 2 +- .../controller/EventTypeControllerTest.java | 14 ------- .../MetadataEnrichmentStrategyTest.java | 2 +- .../partitioning/PartitionResolverTest.java | 4 +- .../UserDefinedPartitionStrategyTest.java | 2 +- .../nakadi/service/EventPublisherTest.java | 4 +- .../service/EventStreamConfigBuilderTest.java | 20 ++++----- .../SubscriptionTimeLagServiceTest.java | 2 +- .../subscription/StreamParametersTest.java | 3 +- .../nakadi/util/JsonPathAccessTest.java | 2 +- 36 files changed, 126 insertions(+), 120 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/CompactionException.java delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/NoSuchPartitionStrategyException.java delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/PartitioningException.java delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/UnprocessableEntityException.java create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/CompactionException.java rename src/main/java/org/zalando/nakadi/exceptions/{ => runtime}/EnrichmentException.java (61%) rename src/main/java/org/zalando/nakadi/exceptions/{ => runtime}/ErrorGettingCursorTimeLagException.java (84%) create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidLimitException.java rename src/main/java/org/zalando/nakadi/exceptions/{ => runtime}/InvalidPartitionKeyFieldsException.java (59%) create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchPartitionStrategyException.java create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/PartitioningException.java diff --git a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java index 159b13cb09..90a71462f4 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java @@ -30,6 +30,7 @@ import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; +import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; import org.zalando.nakadi.exceptions.runtime.NoConnectionSlotsException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.UnparseableCursorException; @@ -74,6 +75,7 @@ import static javax.ws.rs.core.Response.Status.PRECONDITION_FAILED; import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.zalando.nakadi.metrics.MetricUtils.metricNameFor; +import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; @RestController public class EventStreamController { @@ -272,6 +274,8 @@ public StreamingResponseBody streamEvents( } catch (final ServiceTemporarilyUnavailableException e) { LOG.error("Error while trying to stream events.", e); writeProblemResponse(response, outputStream, SERVICE_UNAVAILABLE, e.getMessage()); + } catch (final InvalidLimitException e) { + writeProblemResponse(response, outputStream, UNPROCESSABLE_ENTITY, e.getMessage()); } catch (final NakadiException e) { LOG.error("Error while trying to stream events.", e); writeProblemResponse(response, outputStream, e.asProblem()); diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index a49baef82a..08c96b4564 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -22,7 +22,7 @@ import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.NoSuchPartitionStrategyException; +import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 033d3eeb46..300e75b1ff 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -10,6 +10,11 @@ import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.NativeWebRequest; +import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; +import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; +import org.zalando.nakadi.exceptions.runtime.PartitioningException; +import org.zalando.nakadi.exceptions.runtime.CompactionException; +import org.zalando.nakadi.exceptions.runtime.EnrichmentException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.IllegalClientIdException; import org.zalando.nakadi.exceptions.NakadiException; @@ -181,7 +186,43 @@ public ResponseEntity handleFeatureNotAvailable( final NativeWebRequest request) { LOG.debug(ex.getMessage(), ex); return Responses.create(Problem.valueOf(NOT_IMPLEMENTED, ex.getMessage()), request); + } + + @ExceptionHandler(CompactionException.class) + public ResponseEntity handleCompactionException(final CompactionException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); + } + + @ExceptionHandler(EnrichmentException.class) + public ResponseEntity handleEnrichmentException(final EnrichmentException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); + } + + @ExceptionHandler(NoSuchPartitionStrategyException.class) + public ResponseEntity handleNoSuchPartitionStrategyException( + final NoSuchPartitionStrategyException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); + } + + @ExceptionHandler(PartitioningException.class) + public ResponseEntity handlePartitioningException(final PartitioningException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); + } + @ExceptionHandler(InvalidPartitionKeyFieldsException.class) + public ResponseEntity handleInvalidPartitionKeyFieldsException( + final InvalidPartitionKeyFieldsException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } } diff --git a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java index 3116a2029a..c15bf61244 100644 --- a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java @@ -14,7 +14,7 @@ import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.domain.ItemsWrapper; import org.zalando.nakadi.domain.SubscriptionEventTypeStats; -import org.zalando.nakadi.exceptions.ErrorGettingCursorTimeLagException; +import org.zalando.nakadi.exceptions.runtime.ErrorGettingCursorTimeLagException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; diff --git a/src/main/java/org/zalando/nakadi/enrichment/Enrichment.java b/src/main/java/org/zalando/nakadi/enrichment/Enrichment.java index cfca6edc91..aa576f154d 100644 --- a/src/main/java/org/zalando/nakadi/enrichment/Enrichment.java +++ b/src/main/java/org/zalando/nakadi/enrichment/Enrichment.java @@ -7,7 +7,7 @@ import org.zalando.nakadi.domain.EventCategory; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; -import org.zalando.nakadi.exceptions.EnrichmentException; +import org.zalando.nakadi.exceptions.runtime.EnrichmentException; import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; import java.util.HashSet; diff --git a/src/main/java/org/zalando/nakadi/enrichment/EnrichmentStrategy.java b/src/main/java/org/zalando/nakadi/enrichment/EnrichmentStrategy.java index 17283dea6d..c46f270856 100644 --- a/src/main/java/org/zalando/nakadi/enrichment/EnrichmentStrategy.java +++ b/src/main/java/org/zalando/nakadi/enrichment/EnrichmentStrategy.java @@ -2,7 +2,7 @@ import org.zalando.nakadi.domain.BatchItem; import org.zalando.nakadi.domain.EventType; -import org.zalando.nakadi.exceptions.EnrichmentException; +import org.zalando.nakadi.exceptions.runtime.EnrichmentException; public interface EnrichmentStrategy { void enrich(BatchItem batchItem, EventType eventType) throws EnrichmentException; diff --git a/src/main/java/org/zalando/nakadi/enrichment/MetadataEnrichmentStrategy.java b/src/main/java/org/zalando/nakadi/enrichment/MetadataEnrichmentStrategy.java index 189fde06fc..9bb82a94cc 100644 --- a/src/main/java/org/zalando/nakadi/enrichment/MetadataEnrichmentStrategy.java +++ b/src/main/java/org/zalando/nakadi/enrichment/MetadataEnrichmentStrategy.java @@ -6,7 +6,7 @@ import org.json.JSONObject; import org.zalando.nakadi.domain.BatchItem; import org.zalando.nakadi.domain.EventType; -import org.zalando.nakadi.exceptions.EnrichmentException; +import org.zalando.nakadi.exceptions.runtime.EnrichmentException; import org.zalando.nakadi.util.FlowIdUtils; public class MetadataEnrichmentStrategy implements EnrichmentStrategy { diff --git a/src/main/java/org/zalando/nakadi/exceptions/CompactionException.java b/src/main/java/org/zalando/nakadi/exceptions/CompactionException.java deleted file mode 100644 index ae87942474..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/CompactionException.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.zalando.nakadi.exceptions; - -public class CompactionException extends UnprocessableEntityException { - - public CompactionException(final String message) { - super(message); - } - -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/NoSuchPartitionStrategyException.java b/src/main/java/org/zalando/nakadi/exceptions/NoSuchPartitionStrategyException.java deleted file mode 100644 index adbf3a139c..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/NoSuchPartitionStrategyException.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.zalando.nakadi.exceptions; - -public class NoSuchPartitionStrategyException extends UnprocessableEntityException { - - public NoSuchPartitionStrategyException(final String message) { - super(message); - } - -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/PartitioningException.java b/src/main/java/org/zalando/nakadi/exceptions/PartitioningException.java deleted file mode 100644 index 63d1ada554..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/PartitioningException.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.zalando.nakadi.exceptions; - -public class PartitioningException extends UnprocessableEntityException { - public PartitioningException(final String message) { - super(message); - } - - public PartitioningException(final String msg, final Exception cause) { - super(msg, cause); - } - - public PartitioningException(final String msg, final String problemMessage, final Exception cause) { - super(msg, problemMessage, cause); - } -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/UnprocessableEntityException.java b/src/main/java/org/zalando/nakadi/exceptions/UnprocessableEntityException.java deleted file mode 100644 index 9b817ecdf8..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/UnprocessableEntityException.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.zalando.nakadi.exceptions; - -import org.zalando.problem.MoreStatus; - -import javax.ws.rs.core.Response; - -public class UnprocessableEntityException extends NakadiException { - public UnprocessableEntityException(final String message) { - super(message); - } - - public UnprocessableEntityException(final String msg, final Exception cause) { - super(msg, cause); - } - - public UnprocessableEntityException(final String msg, final String problemMessage, final Exception cause) { - super(msg, problemMessage, cause); - } - - @Override - protected Response.StatusType getStatus() { - return MoreStatus.UNPROCESSABLE_ENTITY; - } -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/CompactionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/CompactionException.java new file mode 100644 index 0000000000..e8bc1c0191 --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/CompactionException.java @@ -0,0 +1,9 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class CompactionException extends NakadiRuntimeBaseException { + + public CompactionException(final String message) { + super(message); + } + +} diff --git a/src/main/java/org/zalando/nakadi/exceptions/EnrichmentException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EnrichmentException.java similarity index 61% rename from src/main/java/org/zalando/nakadi/exceptions/EnrichmentException.java rename to src/main/java/org/zalando/nakadi/exceptions/runtime/EnrichmentException.java index 293fbab358..efeaba01fa 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/EnrichmentException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EnrichmentException.java @@ -1,6 +1,6 @@ -package org.zalando.nakadi.exceptions; +package org.zalando.nakadi.exceptions.runtime; -public class EnrichmentException extends UnprocessableEntityException { +public class EnrichmentException extends NakadiRuntimeBaseException { public EnrichmentException(final String msg, final Exception cause) { super(msg, cause); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/ErrorGettingCursorTimeLagException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/ErrorGettingCursorTimeLagException.java similarity index 84% rename from src/main/java/org/zalando/nakadi/exceptions/ErrorGettingCursorTimeLagException.java rename to src/main/java/org/zalando/nakadi/exceptions/runtime/ErrorGettingCursorTimeLagException.java index 0ea8a6424b..36b8ffc3c9 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/ErrorGettingCursorTimeLagException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/ErrorGettingCursorTimeLagException.java @@ -1,7 +1,6 @@ -package org.zalando.nakadi.exceptions; +package org.zalando.nakadi.exceptions.runtime; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; public class ErrorGettingCursorTimeLagException extends NakadiRuntimeBaseException { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidLimitException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidLimitException.java new file mode 100644 index 0000000000..6b36ed013c --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidLimitException.java @@ -0,0 +1,8 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class InvalidLimitException extends NakadiRuntimeBaseException { + + public InvalidLimitException(final String message) { + super(message); + } +} diff --git a/src/main/java/org/zalando/nakadi/exceptions/InvalidPartitionKeyFieldsException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidPartitionKeyFieldsException.java similarity index 59% rename from src/main/java/org/zalando/nakadi/exceptions/InvalidPartitionKeyFieldsException.java rename to src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidPartitionKeyFieldsException.java index 016380b6e1..640c5226ba 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/InvalidPartitionKeyFieldsException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidPartitionKeyFieldsException.java @@ -1,4 +1,4 @@ -package org.zalando.nakadi.exceptions; +package org.zalando.nakadi.exceptions.runtime; public class InvalidPartitionKeyFieldsException extends PartitioningException { public InvalidPartitionKeyFieldsException(final String message) { @@ -9,7 +9,4 @@ public InvalidPartitionKeyFieldsException(final String msg, final Exception caus super(msg, cause); } - public InvalidPartitionKeyFieldsException(final String msg, final String problemMessage, final Exception cause) { - super(msg, problemMessage, cause); - } } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchPartitionStrategyException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchPartitionStrategyException.java new file mode 100644 index 0000000000..6e56dfbfb9 --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchPartitionStrategyException.java @@ -0,0 +1,9 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class NoSuchPartitionStrategyException extends NakadiRuntimeBaseException { + + public NoSuchPartitionStrategyException(final String message) { + super(message); + } + +} diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/PartitioningException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/PartitioningException.java new file mode 100644 index 0000000000..e433b6017e --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/PartitioningException.java @@ -0,0 +1,11 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class PartitioningException extends NakadiRuntimeBaseException { + public PartitioningException(final String message) { + super(message); + } + + public PartitioningException(final String msg, final Exception cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/zalando/nakadi/partitioning/HashPartitionStrategy.java b/src/main/java/org/zalando/nakadi/partitioning/HashPartitionStrategy.java index 3e6f782514..c32e255878 100644 --- a/src/main/java/org/zalando/nakadi/partitioning/HashPartitionStrategy.java +++ b/src/main/java/org/zalando/nakadi/partitioning/HashPartitionStrategy.java @@ -5,7 +5,7 @@ import org.springframework.stereotype.Component; import org.zalando.nakadi.domain.EventCategory; import org.zalando.nakadi.domain.EventType; -import org.zalando.nakadi.exceptions.InvalidPartitionKeyFieldsException; +import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.Try; import org.zalando.nakadi.util.JsonPathAccess; diff --git a/src/main/java/org/zalando/nakadi/partitioning/PartitionResolver.java b/src/main/java/org/zalando/nakadi/partitioning/PartitionResolver.java index 3411a67c80..c55e31a09c 100644 --- a/src/main/java/org/zalando/nakadi/partitioning/PartitionResolver.java +++ b/src/main/java/org/zalando/nakadi/partitioning/PartitionResolver.java @@ -7,8 +7,8 @@ import org.springframework.stereotype.Component; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; -import org.zalando.nakadi.exceptions.NoSuchPartitionStrategyException; -import org.zalando.nakadi.exceptions.PartitioningException; +import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; +import org.zalando.nakadi.exceptions.runtime.PartitioningException; import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; import org.zalando.nakadi.service.timeline.TimelineService; diff --git a/src/main/java/org/zalando/nakadi/partitioning/PartitionStrategy.java b/src/main/java/org/zalando/nakadi/partitioning/PartitionStrategy.java index 681ccd8b5f..f43cabd64f 100644 --- a/src/main/java/org/zalando/nakadi/partitioning/PartitionStrategy.java +++ b/src/main/java/org/zalando/nakadi/partitioning/PartitionStrategy.java @@ -2,7 +2,7 @@ import org.json.JSONObject; import org.zalando.nakadi.domain.EventType; -import org.zalando.nakadi.exceptions.PartitioningException; +import org.zalando.nakadi.exceptions.runtime.PartitioningException; import java.util.List; diff --git a/src/main/java/org/zalando/nakadi/partitioning/UserDefinedPartitionStrategy.java b/src/main/java/org/zalando/nakadi/partitioning/UserDefinedPartitionStrategy.java index 265d104e57..0a9e36f051 100644 --- a/src/main/java/org/zalando/nakadi/partitioning/UserDefinedPartitionStrategy.java +++ b/src/main/java/org/zalando/nakadi/partitioning/UserDefinedPartitionStrategy.java @@ -3,7 +3,7 @@ import org.json.JSONException; import org.json.JSONObject; import org.zalando.nakadi.domain.EventType; -import org.zalando.nakadi.exceptions.PartitioningException; +import org.zalando.nakadi.exceptions.runtime.PartitioningException; import java.util.List; diff --git a/src/main/java/org/zalando/nakadi/service/EventPublisher.java b/src/main/java/org/zalando/nakadi/service/EventPublisher.java index 9738fe9949..efef3b1c92 100644 --- a/src/main/java/org/zalando/nakadi/service/EventPublisher.java +++ b/src/main/java/org/zalando/nakadi/service/EventPublisher.java @@ -16,11 +16,11 @@ import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.enrichment.Enrichment; -import org.zalando.nakadi.exceptions.CompactionException; -import org.zalando.nakadi.exceptions.EnrichmentException; +import org.zalando.nakadi.exceptions.runtime.CompactionException; +import org.zalando.nakadi.exceptions.runtime.EnrichmentException; import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.PartitioningException; +import org.zalando.nakadi.exceptions.runtime.PartitioningException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.EventPublishingException; import org.zalando.nakadi.exceptions.runtime.EventTypeTimeoutException; diff --git a/src/main/java/org/zalando/nakadi/service/EventStreamConfig.java b/src/main/java/org/zalando/nakadi/service/EventStreamConfig.java index cdfc900449..0cfc5f059a 100644 --- a/src/main/java/org/zalando/nakadi/service/EventStreamConfig.java +++ b/src/main/java/org/zalando/nakadi/service/EventStreamConfig.java @@ -1,7 +1,7 @@ package org.zalando.nakadi.service; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.UnprocessableEntityException; +import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; import org.zalando.nakadi.security.Client; import javax.annotation.Nullable; @@ -198,13 +198,13 @@ public Builder withConsumingClient(final Client consumingClient) { } - public EventStreamConfig build() throws UnprocessableEntityException { + public EventStreamConfig build() throws InvalidLimitException { if (streamLimit != 0 && streamLimit < batchLimit) { - throw new UnprocessableEntityException("stream_limit can't be lower than batch_limit"); + throw new InvalidLimitException("stream_limit can't be lower than batch_limit"); } else if (streamTimeout != 0 && streamTimeout < batchTimeout) { - throw new UnprocessableEntityException("stream_timeout can't be lower than batch_flush_timeout"); + throw new InvalidLimitException("stream_timeout can't be lower than batch_flush_timeout"); } else if (batchLimit < 1) { - throw new UnprocessableEntityException("batch_limit can't be lower than 1"); + throw new InvalidLimitException("batch_limit can't be lower than 1"); } return new EventStreamConfig(cursors, batchLimit, streamLimit, batchTimeout, streamTimeout, streamKeepAliveLimit, etName, consumingClient, maxMemoryUsageBytes); diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 1fba1e7585..2e2d6ea5e3 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -29,7 +29,7 @@ import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.NoSuchPartitionStrategyException; +import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java index 140ef549a1..cd2da6048b 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java @@ -8,7 +8,7 @@ import org.zalando.nakadi.domain.EventTypePartition; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.PartitionEndStatistics; -import org.zalando.nakadi.exceptions.ErrorGettingCursorTimeLagException; +import org.zalando.nakadi.exceptions.runtime.ErrorGettingCursorTimeLagException; import org.zalando.nakadi.exceptions.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; diff --git a/src/main/java/org/zalando/nakadi/util/JsonPathAccess.java b/src/main/java/org/zalando/nakadi/util/JsonPathAccess.java index fed583415c..2511eab4f6 100644 --- a/src/main/java/org/zalando/nakadi/util/JsonPathAccess.java +++ b/src/main/java/org/zalando/nakadi/util/JsonPathAccess.java @@ -2,7 +2,7 @@ import org.json.JSONException; import org.json.JSONObject; -import org.zalando.nakadi.exceptions.InvalidPartitionKeyFieldsException; +import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; /* One could use JsonPath Lib instead: https://github.com/jayway/JsonPath diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java index 7387ed3aee..a843c93723 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java @@ -27,7 +27,6 @@ import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.UnprocessableEntityException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; import org.zalando.nakadi.exceptions.runtime.TopicConfigException; @@ -681,19 +680,6 @@ public void whenPUTNotExistingEventTypeThen404() throws Exception { .andExpect(content().string(matchesProblem(expectedProblem))); } - @Test - public void whenPUTRepoNakadiExceptionThen422() throws Exception { - final EventType eventType = buildDefaultEventType(); - - final Problem expectedProblem = Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY); - - doThrow(UnprocessableEntityException.class).when(eventTypeRepository).findByName(eventType.getName()); - - putEventType(eventType, eventType.getName()).andExpect(status().isUnprocessableEntity()) - .andExpect(content().contentType("application/problem+json")) - .andExpect(content().string(matchesProblem(expectedProblem))); - } - @Test public void canExposeASingleEventType() throws Exception { final EventType expectedEventType = buildDefaultEventType(); diff --git a/src/test/java/org/zalando/nakadi/enrichment/MetadataEnrichmentStrategyTest.java b/src/test/java/org/zalando/nakadi/enrichment/MetadataEnrichmentStrategyTest.java index add6dadf41..a4973962a6 100644 --- a/src/test/java/org/zalando/nakadi/enrichment/MetadataEnrichmentStrategyTest.java +++ b/src/test/java/org/zalando/nakadi/enrichment/MetadataEnrichmentStrategyTest.java @@ -5,7 +5,7 @@ import org.junit.Test; import org.zalando.nakadi.domain.BatchItem; import org.zalando.nakadi.domain.EventType; -import org.zalando.nakadi.exceptions.EnrichmentException; +import org.zalando.nakadi.exceptions.runtime.EnrichmentException; import org.zalando.nakadi.util.FlowIdUtils; import org.zalando.nakadi.utils.TestUtils; diff --git a/src/test/java/org/zalando/nakadi/partitioning/PartitionResolverTest.java b/src/test/java/org/zalando/nakadi/partitioning/PartitionResolverTest.java index 0ff78a612d..e7c0032e05 100644 --- a/src/test/java/org/zalando/nakadi/partitioning/PartitionResolverTest.java +++ b/src/test/java/org/zalando/nakadi/partitioning/PartitionResolverTest.java @@ -8,8 +8,8 @@ import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.NoSuchPartitionStrategyException; -import org.zalando.nakadi.exceptions.PartitioningException; +import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; +import org.zalando.nakadi.exceptions.runtime.PartitioningException; import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; import org.zalando.nakadi.repository.TopicRepository; import org.zalando.nakadi.service.timeline.TimelineService; diff --git a/src/test/java/org/zalando/nakadi/partitioning/UserDefinedPartitionStrategyTest.java b/src/test/java/org/zalando/nakadi/partitioning/UserDefinedPartitionStrategyTest.java index 43e917fb89..7a80b01699 100644 --- a/src/test/java/org/zalando/nakadi/partitioning/UserDefinedPartitionStrategyTest.java +++ b/src/test/java/org/zalando/nakadi/partitioning/UserDefinedPartitionStrategyTest.java @@ -3,7 +3,7 @@ import com.google.common.collect.ImmutableList; import org.json.JSONObject; import org.junit.Test; -import org.zalando.nakadi.exceptions.PartitioningException; +import org.zalando.nakadi.exceptions.runtime.PartitioningException; import java.util.List; diff --git a/src/test/java/org/zalando/nakadi/service/EventPublisherTest.java b/src/test/java/org/zalando/nakadi/service/EventPublisherTest.java index f0fd92b644..b3703584ad 100644 --- a/src/test/java/org/zalando/nakadi/service/EventPublisherTest.java +++ b/src/test/java/org/zalando/nakadi/service/EventPublisherTest.java @@ -15,8 +15,8 @@ import org.zalando.nakadi.domain.EventTypeBase; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.enrichment.Enrichment; -import org.zalando.nakadi.exceptions.EnrichmentException; -import org.zalando.nakadi.exceptions.PartitioningException; +import org.zalando.nakadi.exceptions.runtime.EnrichmentException; +import org.zalando.nakadi.exceptions.runtime.PartitioningException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.EventPublishingException; import org.zalando.nakadi.exceptions.runtime.EventTypeTimeoutException; diff --git a/src/test/java/org/zalando/nakadi/service/EventStreamConfigBuilderTest.java b/src/test/java/org/zalando/nakadi/service/EventStreamConfigBuilderTest.java index 27fabd59f3..972ee89d59 100644 --- a/src/test/java/org/zalando/nakadi/service/EventStreamConfigBuilderTest.java +++ b/src/test/java/org/zalando/nakadi/service/EventStreamConfigBuilderTest.java @@ -1,7 +1,7 @@ package org.zalando.nakadi.service; import org.junit.Test; -import org.zalando.nakadi.exceptions.UnprocessableEntityException; +import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.lessThanOrEqualTo; @@ -12,7 +12,7 @@ public class EventStreamConfigBuilderTest { @Test - public void batchLimitZeroValueTest() throws UnprocessableEntityException { + public void batchLimitZeroValueTest() throws InvalidLimitException { final EventStreamConfig config = EventStreamConfig .builder() .withBatchLimit(1) @@ -23,7 +23,7 @@ public void batchLimitZeroValueTest() throws UnprocessableEntityException { } @Test - public void batchLimitDefaultValueTest() throws UnprocessableEntityException { + public void batchLimitDefaultValueTest() throws InvalidLimitException { final EventStreamConfig config = EventStreamConfig .builder() .withBatchLimit(1) @@ -33,7 +33,7 @@ public void batchLimitDefaultValueTest() throws UnprocessableEntityException { } @Test - public void batchLimitSpecifiedValueTest() throws UnprocessableEntityException { + public void batchLimitSpecifiedValueTest() throws InvalidLimitException { final EventStreamConfig config = EventStreamConfig .builder() .withBatchLimit(1) @@ -43,8 +43,8 @@ public void batchLimitSpecifiedValueTest() throws UnprocessableEntityException { assertThat(config.getBatchTimeout(), is(29)); } - @Test(expected = UnprocessableEntityException.class) - public void streamLimitLessThenBatchLimit() throws UnprocessableEntityException { + @Test(expected = InvalidLimitException.class) + public void streamLimitLessThenBatchLimit() throws InvalidLimitException { EventStreamConfig .builder() .withBatchLimit(10) @@ -52,8 +52,8 @@ public void streamLimitLessThenBatchLimit() throws UnprocessableEntityException .build(); } - @Test(expected = UnprocessableEntityException.class) - public void streamTimeoutLessThenBatchTimeout() throws UnprocessableEntityException { + @Test(expected = InvalidLimitException.class) + public void streamTimeoutLessThenBatchTimeout() throws InvalidLimitException { EventStreamConfig .builder() .withBatchTimeout(10) @@ -62,7 +62,7 @@ public void streamTimeoutLessThenBatchTimeout() throws UnprocessableEntityExcept } @Test - public void streamTimeoutHigherThanMax() throws UnprocessableEntityException { + public void streamTimeoutHigherThanMax() throws InvalidLimitException { final EventStreamConfig config = EventStreamConfig .builder() .withStreamTimeout(MAX_STREAM_TIMEOUT + 100) @@ -72,7 +72,7 @@ public void streamTimeoutHigherThanMax() throws UnprocessableEntityException { } @Test - public void unlimitedStreamTimeout() throws UnprocessableEntityException { + public void unlimitedStreamTimeout() throws InvalidLimitException { final EventStreamConfig config = EventStreamConfig .builder() .withStreamTimeout(0) diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java index 6c444166c9..5c5ed83edc 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java @@ -9,7 +9,7 @@ import org.zalando.nakadi.domain.PartitionEndStatistics; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.ErrorGettingCursorTimeLagException; +import org.zalando.nakadi.exceptions.runtime.ErrorGettingCursorTimeLagException; import org.zalando.nakadi.exceptions.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; diff --git a/src/test/java/org/zalando/nakadi/service/subscription/StreamParametersTest.java b/src/test/java/org/zalando/nakadi/service/subscription/StreamParametersTest.java index 1a1bc932d8..538bf75942 100644 --- a/src/test/java/org/zalando/nakadi/service/subscription/StreamParametersTest.java +++ b/src/test/java/org/zalando/nakadi/service/subscription/StreamParametersTest.java @@ -2,7 +2,6 @@ import com.google.common.collect.ImmutableList; import org.junit.Test; -import org.zalando.nakadi.exceptions.UnprocessableEntityException; import org.zalando.nakadi.exceptions.runtime.WrongStreamParametersException; import org.zalando.nakadi.security.Client; import org.zalando.nakadi.service.EventStreamConfig; @@ -94,7 +93,7 @@ public static StreamParameters createStreamParameters(final int batchLimitEvents final Integer batchKeepAliveIterations, final int maxUncommittedMessages, final long commitTimeoutSeconds, - final Client client) throws UnprocessableEntityException { + final Client client) throws WrongStreamParametersException { final UserStreamParameters userParams = new UserStreamParameters(batchLimitEvents, streamLimitEvents, batchTimeoutSeconds, streamTimeoutSeconds, batchKeepAliveIterations, maxUncommittedMessages, ImmutableList.of()); diff --git a/src/test/java/org/zalando/nakadi/util/JsonPathAccessTest.java b/src/test/java/org/zalando/nakadi/util/JsonPathAccessTest.java index 28d847ec5a..28b83ec187 100644 --- a/src/test/java/org/zalando/nakadi/util/JsonPathAccessTest.java +++ b/src/test/java/org/zalando/nakadi/util/JsonPathAccessTest.java @@ -2,7 +2,7 @@ import org.json.JSONObject; import org.junit.Test; -import org.zalando.nakadi.exceptions.InvalidPartitionKeyFieldsException; +import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; import org.zalando.nakadi.utils.TestUtils; import java.io.IOException; From 4de99c5ed3f71cdc857d487662eda45202ae88b5 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Wed, 15 Aug 2018 20:49:37 +0200 Subject: [PATCH 064/176] Handle NoSuchPartitionStrategyException correctly --- .../nakadi/controller/EventTypeController.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index 08c96b4564..abd17cb4e5 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -22,7 +22,6 @@ import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; @@ -32,6 +31,7 @@ import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TopicConfigException; import org.zalando.nakadi.exceptions.runtime.TopicCreationException; @@ -43,7 +43,6 @@ import org.zalando.nakadi.service.EventTypeService; import org.zalando.nakadi.service.FeatureToggleService; import org.zalando.nakadi.service.Result; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; import org.zalando.problem.spring.web.advice.Responses; @@ -55,6 +54,7 @@ import static org.springframework.http.ResponseEntity.status; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DISABLE_EVENT_TYPE_CREATION; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DISABLE_EVENT_TYPE_DELETION; +import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; @RestController @RequestMapping(value = "/event-types") @@ -134,7 +134,8 @@ public ResponseEntity update( InconsistentStateException, NakadiRuntimeException, ServiceTemporarilyUnavailableException, - UnableProcessException { + UnableProcessException, + NoSuchPartitionStrategyException{ if (errors.hasErrors()) { return Responses.create(new ValidationProblem(errors), request); } @@ -184,7 +185,7 @@ public ResponseEntity deletion(final EventTypeDeletionException excepti public ResponseEntity unableProcess(final UnableProcessException exception, final NativeWebRequest request) { LOG.debug(exception.getMessage(), exception); - return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, exception.getMessage(), request); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } @ExceptionHandler(ConflictException.class) @@ -215,10 +216,10 @@ public ResponseEntity nakadiException(final NakadiException exception, } @ExceptionHandler(NoSuchPartitionStrategyException.class) - public ResponseEntity noSuchPartitionStrategyException(final NakadiException exception, + public ResponseEntity noSuchPartitionStrategyException(final NoSuchPartitionStrategyException exception, final NativeWebRequest request) { LOG.debug(exception.getMessage(), exception); - return Responses.create(exception.asProblem(), request); + return Responses.create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); } @ExceptionHandler(DuplicatedEventTypeNameException.class) @@ -232,13 +233,13 @@ public ResponseEntity duplicatedEventTypeNameException(final Duplicated public ResponseEntity invalidEventTypeException(final InvalidEventTypeException exception, final NativeWebRequest request) { LOG.debug(exception.getMessage(), exception); - return Responses.create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, exception.getMessage()), request); + return Responses.create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); } @ExceptionHandler(EventTypeOptionsValidationException.class) public ResponseEntity unableProcess(final EventTypeOptionsValidationException exception, final NativeWebRequest request) { LOG.debug(exception.getMessage(), exception); - return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, exception.getMessage(), request); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } } From 322e8379d6c1bd206d8866457db533d6162e8dd1 Mon Sep 17 00:00:00 2001 From: Ricardo de Cillo Date: Thu, 16 Aug 2018 11:47:10 +0200 Subject: [PATCH 065/176] Support OpenTracing span context In order to trace distributed systems, open tracing span context can be transported in the metadata of events. This way, publishers and consumer can share a span even when asynchronously communicating through Nakadi. --- docs/_data/nakadi-event-bus-api.yaml | 7 +++++++ .../validation/JsonSchemaEnrichment.java | 2 ++ .../validation/JSONSchemaValidationTest.java | 21 +++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/docs/_data/nakadi-event-bus-api.yaml b/docs/_data/nakadi-event-bus-api.yaml index c2487091fe..705f59da45 100644 --- a/docs/_data/nakadi-event-bus-api.yaml +++ b/docs/_data/nakadi-event-bus-api.yaml @@ -2053,6 +2053,13 @@ definitions: same partition and therefore compacted in a proper way (as compaction is performed per partition). type: string example: '329ed3d2-8366-11e8-adc0-fa7ae01bbebc' + span_ctx: + description: | + Object containing an OpenTracing http://opentracing.io span context. In case the producer of this event type + uses OpenTracing for tracing transcations accross distributed services, this field is be populated with an + object that allows consumers to resume the context of a span. The details of the payload are vendor + specific and consumers are expected to contact the producer in order to obtain further details. + type: object required: - eid - occurred_at diff --git a/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java b/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java index 33487c92d5..f1f89c6c75 100644 --- a/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java +++ b/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java @@ -162,6 +162,7 @@ private static JSONObject addMetadata(final JSONObject schema, final EventType e .put("type", "string") .put("enum", Arrays.asList(new String[]{eventType.getName()})); final JSONObject string = new JSONObject().put("type", "string"); + final JSONObject object = new JSONObject().put("type", "object"); final JSONObject dateTime = new JSONObject() .put("type", "string"); @@ -171,6 +172,7 @@ private static JSONObject addMetadata(final JSONObject schema, final EventType e metadataProperties.put("parent_eids", arrayOfUUIDs); metadataProperties.put("flow_id", string); metadataProperties.put("partition", string); + metadataProperties.put("span_ctx", object); final ArrayList requiredFields = newArrayList("eid", "occurred_at"); if (eventType.getCleanupPolicy() == CleanupPolicy.COMPACT) { diff --git a/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java b/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java index 6e56d54e9b..c655e8be6d 100644 --- a/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java +++ b/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java @@ -37,6 +37,27 @@ public void validationOfBusinessEventShouldRequiredMetadata() { assertThat(error.get().getMessage(), equalTo("#: required key [metadata] not found")); } + @Test + public void validationOfBusinessEventShouldAllowSpanCtxtInMetadata() { + final EventType et = EventTypeTestBuilder.builder().name("some-event-type") + .schema(basicSchema()).build(); + et.setCategory(EventCategory.BUSINESS); + + final JSONObject event = new JSONObject("{\"metadata\":{" + + "\"occurred_at\":\"1992-08-03T10:00:00Z\"," + + "\"eid\":\"329ed3d2-8366-11e8-adc0-fa7ae01bbebc\"," + + "\"span_ctx\": {" + + " \"ot-tracer-spanid\": \"b268f901d5f2b865\"," + + " \"ot-tracer-traceid\": \"e9435c17dabe8238\"," + + " \"ot-baggage-foo\": \"bar\"" + + "}}," + + "\"foo\": \"bar\"}"); + + final Optional error = EventValidation.forType(et).validate(event); + + assertThat(error, isAbsent()); + } + @Test public void validationOfDataChangeEventRequiresExtraFields() { final EventType et = EventTypeTestBuilder.builder().name("some-event-type") From 51753d3d4dbdc980c1e9d27759abf4499a301feb Mon Sep 17 00:00:00 2001 From: Ricardo de Cillo Date: Thu, 16 Aug 2018 14:24:30 +0200 Subject: [PATCH 066/176] Fixed typos and clarified recommendations on how to use the field --- docs/_data/nakadi-event-bus-api.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/_data/nakadi-event-bus-api.yaml b/docs/_data/nakadi-event-bus-api.yaml index 705f59da45..fd8f312825 100644 --- a/docs/_data/nakadi-event-bus-api.yaml +++ b/docs/_data/nakadi-event-bus-api.yaml @@ -2056,9 +2056,11 @@ definitions: span_ctx: description: | Object containing an OpenTracing http://opentracing.io span context. In case the producer of this event type - uses OpenTracing for tracing transcations accross distributed services, this field is be populated with an + uses OpenTracing for tracing transactions accross distributed services, this field is populated with an object that allows consumers to resume the context of a span. The details of the payload are vendor - specific and consumers are expected to contact the producer in order to obtain further details. + specific and consumers are expected to contact the producer in order to obtain further details. Any attempt + to inspect or effectively use the payload, apart from the tracer implementation, can lead to vendor lock-in + which should be avoided. type: object required: - eid From d74d2c64de26811ffe230809df289b4dd6acb30f Mon Sep 17 00:00:00 2001 From: Andrey Dyachkov Date: Fri, 17 Aug 2018 14:32:41 +0200 Subject: [PATCH 067/176] changed http firewall --- .../nakadi/config/SecurityConfiguration.java | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java index b57de03e68..5a568549b9 100644 --- a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java +++ b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java @@ -4,6 +4,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpOutputMessage; import org.springframework.http.converter.HttpMessageConverter; @@ -19,13 +20,22 @@ import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; +import org.springframework.security.web.firewall.FirewalledRequest; +import org.springframework.security.web.firewall.HttpFirewall; +import org.springframework.security.web.firewall.RequestRejectedException; +import org.springframework.security.web.firewall.StrictHttpFirewall; import org.zalando.stups.oauth2.spring.security.expression.ExtendedOAuth2WebSecurityExpressionHandler; +import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Response; import java.io.IOException; import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import static org.springframework.http.HttpMethod.DELETE; import static org.springframework.http.HttpMethod.GET; @@ -189,5 +199,94 @@ public String getDetail() { } } + // TODO: REMOVE IT AFTER EVERYONE HAS NORMALIZED THEIR URLS + @Bean + public HttpFirewall allowUrlEncodedSlashHttpFirewall() { + return new AllowForwardSlashesStrictHttpFirewall(); + } + + // TODO: REMOVE IT AFTER EVERYONE HAS NORMALIZED THEIR URLS + private static class AllowForwardSlashesStrictHttpFirewall extends StrictHttpFirewall { + + private static final String ENCODED_PERCENT = "%25"; + private static final String PERCENT = "%"; + private static final List FORBIDDEN_ENCODED_PERIOD = Collections.unmodifiableList(Arrays.asList("%2e", "%2E")); + private Set encodedUrlBlacklist = new HashSet<>(); + private Set decodedUrlBlacklist = new HashSet<>(); + + public AllowForwardSlashesStrictHttpFirewall() { + super(); + this.encodedUrlBlacklist.add(ENCODED_PERCENT); + this.encodedUrlBlacklist.addAll(FORBIDDEN_ENCODED_PERIOD); + this.decodedUrlBlacklist.add(PERCENT); + } + + private static boolean containsOnlyPrintableAsciiCharacters(String uri) { + int length = uri.length(); + for (int i = 0; i < length; i++) { + char c = uri.charAt(i); + if (c < '\u0020' || c > '\u007e') { + return false; + } + } + + return true; + } + + private static boolean encodedUrlContains(HttpServletRequest request, String value) { + if (valueContains(request.getContextPath(), value)) { + return true; + } + return valueContains(request.getRequestURI(), value); + } + + private static boolean decodedUrlContains(HttpServletRequest request, String value) { + if (valueContains(request.getServletPath(), value)) { + return true; + } + if (valueContains(request.getPathInfo(), value)) { + return true; + } + return false; + } + + private static boolean valueContains(String value, String contains) { + return value != null && value.contains(contains); + } + + @Override + public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException { + rejectedBlacklistedUrls(request); + + // ONLY THIS PART IS REMOVED, ALL OTHER CODE IS THE SAME AS IN StrictHttpFirewall + //if (!isNormalized(request)) { + // throw new RequestRejectedException("The request was rejected because the URL was not normalized."); + //} + + String requestUri = request.getRequestURI(); + if (!containsOnlyPrintableAsciiCharacters(requestUri)) { + throw new RequestRejectedException("The requestURI was rejected because it can only contain printable ASCII characters."); + } + return new FirewalledRequest(request) { + @Override + public void reset() { + } + }; + } + + private void rejectedBlacklistedUrls(HttpServletRequest request) { + for (String forbidden : this.encodedUrlBlacklist) { + if (encodedUrlContains(request, forbidden)) { + throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\""); + } + } + for (String forbidden : this.decodedUrlBlacklist) { + if (decodedUrlContains(request, forbidden)) { + throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\""); + } + } + } + + } } From 96fc62218ecfd0ef8b2948b116713cef32f26499 Mon Sep 17 00:00:00 2001 From: Andrey Dyachkov Date: Fri, 17 Aug 2018 14:44:25 +0200 Subject: [PATCH 068/176] removed only forward slashes check --- .../nakadi/config/SecurityConfiguration.java | 50 +++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java index 5a568549b9..6ce380c535 100644 --- a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java +++ b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java @@ -258,10 +258,9 @@ private static boolean valueContains(String value, String contains) { public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException { rejectedBlacklistedUrls(request); - // ONLY THIS PART IS REMOVED, ALL OTHER CODE IS THE SAME AS IN StrictHttpFirewall - //if (!isNormalized(request)) { - // throw new RequestRejectedException("The request was rejected because the URL was not normalized."); - //} + if (!isNormalized(request)) { + throw new RequestRejectedException("The request was rejected because the URL was not normalized."); + } String requestUri = request.getRequestURI(); if (!containsOnlyPrintableAsciiCharacters(requestUri)) { @@ -274,6 +273,49 @@ public void reset() { }; } + private static boolean isNormalized(HttpServletRequest request) { + if (!isNormalized(request.getRequestURI())) { + return false; + } + if (!isNormalized(request.getContextPath())) { + return false; + } + if (!isNormalized(request.getServletPath())) { + return false; + } + if (!isNormalized(request.getPathInfo())) { + return false; + } + return true; + } + + private static boolean isNormalized(String path) { + if (path == null) { + return true; + } + + // ONLY THIS PART IS REMOVED, ALL OTHER CODE IS THE SAME AS IN StrictHttpFirewall + // if (path.indexOf("//") > -1) { + // return false; + // } + + for (int j = path.length(); j > 0;) { + int i = path.lastIndexOf('/', j - 1); + int gap = j - i; + + if (gap == 2 && path.charAt(i + 1) == '.') { + // ".", "/./" or "/." + return false; + } else if (gap == 3 && path.charAt(i + 1) == '.' && path.charAt(i + 2) == '.') { + return false; + } + + j = i; + } + + return true; + } + private void rejectedBlacklistedUrls(HttpServletRequest request) { for (String forbidden : this.encodedUrlBlacklist) { if (encodedUrlContains(request, forbidden)) { From 7a1e85c79d3adf42bcd62af061b2dca222f14e74 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 09:28:14 +0200 Subject: [PATCH 069/176] fix --- .../db/EventTypeDbRepositoryTest.java | 2 +- .../zalando/nakadi/webservice/EventTypeAT.java | 2 +- .../webservice/PartitionsControllerAT.java | 2 +- .../controller/CursorOperationsController.java | 4 ++-- .../nakadi/controller/CursorsController.java | 4 ++-- .../controller/EventPublishingController.java | 5 +++-- .../controller/EventStreamController.java | 4 ++-- .../nakadi/controller/ExceptionHandling.java | 10 +++++++++- .../controller/PartitionsController.java | 4 ++-- .../controller/SubscriptionController.java | 4 +++- .../zalando/nakadi/domain/NakadiCursor.java | 2 +- .../exceptions/NoSuchEventTypeException.java | 18 ------------------ .../org/zalando/nakadi/exceptions/Try.java | 4 ++++ .../{ => runtime}/InvalidCursorException.java | 4 ++-- .../runtime/NoEventTypeException.java | 2 -- .../runtime/NoSuchEventTypeException.java | 11 +++++++++++ .../nakadi/repository/EventConsumer.java | 2 +- .../nakadi/repository/EventTypeRepository.java | 2 +- .../repository/MultiTimelineEventConsumer.java | 2 +- .../nakadi/repository/TopicRepository.java | 2 +- .../db/CachingEventTypeRepository.java | 2 +- .../nakadi/repository/db/EventTypeCache.java | 2 +- .../repository/db/EventTypeDbRepository.java | 2 +- .../nakadi/repository/kafka/KafkaCursor.java | 2 +- .../repository/kafka/KafkaTopicRepository.java | 2 +- .../nakadi/service/CursorConverter.java | 4 ++-- .../zalando/nakadi/service/CursorsService.java | 4 ++-- .../zalando/nakadi/service/EventPublisher.java | 2 +- .../nakadi/service/EventStreamFactory.java | 2 +- .../nakadi/service/EventTypeService.java | 6 ++++-- .../nakadi/service/NakadiCursorComparator.java | 2 +- .../service/converter/CursorConverterImpl.java | 4 ++-- .../service/converter/VersionOneConverter.java | 4 ++-- .../converter/VersionZeroConverter.java | 4 ++-- .../service/converter/VersionedConverter.java | 4 ++-- .../subscription/SubscriptionService.java | 16 ++++++++++------ .../SubscriptionStreamerFactory.java | 2 +- .../SubscriptionTimeLagService.java | 2 +- .../SubscriptionValidationService.java | 2 +- .../subscription/state/StreamingState.java | 2 +- .../zk/SubscriptionClientFactory.java | 2 +- .../service/timeline/TimelineService.java | 4 ++-- .../controller/CursorsControllerTest.java | 4 ++-- .../EventPublishingControllerTest.java | 2 +- .../controller/EventStreamControllerTest.java | 4 ++-- .../controller/EventTypeControllerTest.java | 2 +- .../controller/PartitionsControllerTest.java | 2 +- .../controller/SubscriptionControllerTest.java | 2 +- .../nakadi/domain/NakadiCursorTest.java | 2 +- .../repository/kafka/KafkaCursorTest.java | 2 +- .../kafka/KafkaTopicRepositoryTest.java | 2 +- .../service/NakadiCursorComparatorTest.java | 2 +- .../SubscriptionTimeLagServiceTest.java | 2 +- .../SubscriptionValidationServiceTest.java | 2 +- .../converter/VersionOneConverterTest.java | 2 +- .../converter/VersionZeroConverterTest.java | 4 ++-- .../subscription/state/StreamingStateTest.java | 4 ++-- .../service/timeline/TimelineServiceTest.java | 2 +- 58 files changed, 109 insertions(+), 97 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/NoSuchEventTypeException.java rename src/main/java/org/zalando/nakadi/exceptions/{ => runtime}/InvalidCursorException.java (95%) create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchEventTypeException.java diff --git a/src/acceptance-test/java/org/zalando/nakadi/repository/db/EventTypeDbRepositoryTest.java b/src/acceptance-test/java/org/zalando/nakadi/repository/db/EventTypeDbRepositoryTest.java index 7fd3d13bae..76204879e6 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/repository/db/EventTypeDbRepositoryTest.java +++ b/src/acceptance-test/java/org/zalando/nakadi/repository/db/EventTypeDbRepositoryTest.java @@ -10,7 +10,7 @@ import org.zalando.nakadi.domain.EventTypeSchema; import org.zalando.nakadi.domain.Version; import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; import org.zalando.nakadi.repository.EventTypeRepository; import org.zalando.nakadi.utils.TestUtils; diff --git a/src/acceptance-test/java/org/zalando/nakadi/webservice/EventTypeAT.java b/src/acceptance-test/java/org/zalando/nakadi/webservice/EventTypeAT.java index c5f9a0a449..0ba764fb80 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/webservice/EventTypeAT.java +++ b/src/acceptance-test/java/org/zalando/nakadi/webservice/EventTypeAT.java @@ -18,7 +18,7 @@ import org.zalando.nakadi.domain.ResourceAuthorization; import org.zalando.nakadi.domain.ResourceAuthorizationAttribute; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.partitioning.PartitionStrategy; import org.zalando.nakadi.repository.kafka.KafkaTestHelper; import org.zalando.nakadi.utils.EventTypeTestBuilder; diff --git a/src/acceptance-test/java/org/zalando/nakadi/webservice/PartitionsControllerAT.java b/src/acceptance-test/java/org/zalando/nakadi/webservice/PartitionsControllerAT.java index e68abd8ffa..44522e7bc1 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/webservice/PartitionsControllerAT.java +++ b/src/acceptance-test/java/org/zalando/nakadi/webservice/PartitionsControllerAT.java @@ -11,7 +11,7 @@ import org.junit.Test; import org.springframework.http.HttpStatus; import org.zalando.nakadi.domain.EventType; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.kafka.KafkaTestHelper; import org.zalando.nakadi.utils.EventTypeTestBuilder; import org.zalando.nakadi.view.Cursor; diff --git a/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java b/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java index 606b71f954..8716756147 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java @@ -16,9 +16,9 @@ import org.zalando.nakadi.domain.NakadiCursorLag; import org.zalando.nakadi.domain.ShiftedNakadiCursor; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.CursorConversionException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; diff --git a/src/main/java/org/zalando/nakadi/controller/CursorsController.java b/src/main/java/org/zalando/nakadi/controller/CursorsController.java index c6cfa26b49..ddf62cf8c0 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorsController.java @@ -16,10 +16,10 @@ import org.zalando.nakadi.domain.ItemsWrapper; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.CursorsAreEmptyException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; diff --git a/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java b/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java index 24571576b6..924b8c1229 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java @@ -17,7 +17,7 @@ import org.zalando.nakadi.domain.EventPublishResult; import org.zalando.nakadi.domain.EventPublishingStatus; import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.EventTypeTimeoutException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; @@ -35,6 +35,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static org.springframework.http.ResponseEntity.status; import static org.springframework.web.bind.annotation.RequestMethod.POST; import static org.zalando.problem.spring.web.advice.Responses.create; @@ -110,7 +111,7 @@ private ResponseEntity postEventInternal(final String eventTypeName, return processJSONException(e, nativeWebRequest); } catch (final NoSuchEventTypeException e) { LOG.debug("Event type not found.", e.getMessage()); - return create(e.asProblem(), nativeWebRequest); + return create(Problem.valueOf(NOT_FOUND, e.getMessage()), nativeWebRequest); } catch (final EventTypeTimeoutException e) { LOG.debug("Failed to publish batch", e); return create(Problem.valueOf(Response.Status.SERVICE_UNAVAILABLE, e.getMessage()), nativeWebRequest); diff --git a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java index 90a71462f4..d31a4e87ca 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java @@ -26,9 +26,9 @@ import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; import org.zalando.nakadi.exceptions.runtime.NoConnectionSlotsException; diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 300e75b1ff..0938e94196 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; import org.zalando.nakadi.exceptions.runtime.PartitioningException; import org.zalando.nakadi.exceptions.runtime.CompactionException; @@ -37,6 +38,7 @@ import javax.ws.rs.core.Response; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.NOT_IMPLEMENTED; import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; @@ -85,7 +87,7 @@ class and stacktrace like information. @ExceptionHandler(NoEventTypeException.class) public ResponseEntity noEventTypeException(final NoEventTypeException exception, final NativeWebRequest request) { - return Responses.create(Response.Status.NOT_FOUND, exception.getMessage(), request); + return Responses.create(NOT_FOUND, exception.getMessage(), request); } @ExceptionHandler(AccessDeniedException.class) @@ -225,4 +227,10 @@ public ResponseEntity handleInvalidPartitionKeyFieldsException( return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } + @ExceptionHandler(NoSuchEventTypeException.class) + public ResponseEntity handleNoSuchEventTypeException(final NoSuchEventTypeException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return Responses.create(NOT_FOUND, exception.getMessage(), request); + } } diff --git a/src/main/java/org/zalando/nakadi/controller/PartitionsController.java b/src/main/java/org/zalando/nakadi/controller/PartitionsController.java index 3203bd2256..3a44572bf8 100644 --- a/src/main/java/org/zalando/nakadi/controller/PartitionsController.java +++ b/src/main/java/org/zalando/nakadi/controller/PartitionsController.java @@ -19,9 +19,9 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.NotFoundException; diff --git a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java index c15bf61244..6eaf0bb5df 100644 --- a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java @@ -18,6 +18,7 @@ import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TimeLagStatsTimeoutException; import org.zalando.nakadi.service.FeatureToggleService; @@ -83,7 +84,8 @@ public ResponseEntity deleteSubscription(@PathVariable("id") final String sub public ItemsWrapper getSubscriptionStats( @PathVariable("id") final String subscriptionId, @RequestParam(value = "show_time_lag", required = false, defaultValue = "false") final boolean showTimeLag) - throws NakadiException, InconsistentStateException, ServiceTemporarilyUnavailableException { + throws NakadiException, InconsistentStateException, + NoSuchEventTypeException, ServiceTemporarilyUnavailableException { final StatsMode statsMode = showTimeLag ? StatsMode.TIMELAG : StatsMode.NORMAL; return subscriptionService.getSubscriptionStat(subscriptionId, statsMode); } diff --git a/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java b/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java index aada4785fa..a216f31243 100644 --- a/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java +++ b/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java @@ -1,7 +1,7 @@ package org.zalando.nakadi.domain; import com.google.common.base.Preconditions; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.repository.kafka.KafkaCursor; diff --git a/src/main/java/org/zalando/nakadi/exceptions/NoSuchEventTypeException.java b/src/main/java/org/zalando/nakadi/exceptions/NoSuchEventTypeException.java deleted file mode 100644 index f22d722baa..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/NoSuchEventTypeException.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.zalando.nakadi.exceptions; - -import javax.ws.rs.core.Response; - -public class NoSuchEventTypeException extends NakadiException { - public NoSuchEventTypeException(final String message) { - super(message); - } - - public NoSuchEventTypeException(final String msg, final Exception cause) { - super(msg, cause); - } - - @Override - protected Response.StatusType getStatus() { - return Response.Status.NOT_FOUND; - } -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/Try.java b/src/main/java/org/zalando/nakadi/exceptions/Try.java index fb87f1ef65..b40295c720 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/Try.java +++ b/src/main/java/org/zalando/nakadi/exceptions/Try.java @@ -1,5 +1,7 @@ package org.zalando.nakadi.exceptions; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; + import java.util.Optional; import java.util.concurrent.Callable; import java.util.function.Function; @@ -95,6 +97,8 @@ public boolean isSuccess() { public T getOrThrow() { if (exception instanceof NakadiRuntimeException) { throw (NakadiRuntimeException) exception; + } else if (exception instanceof NakadiRuntimeBaseException) { + throw (NakadiRuntimeBaseException) exception; } throw new NakadiRuntimeException(exception); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/InvalidCursorException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorException.java similarity index 95% rename from src/main/java/org/zalando/nakadi/exceptions/InvalidCursorException.java rename to src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorException.java index 88c12022ec..1e53656644 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/InvalidCursorException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorException.java @@ -1,10 +1,10 @@ -package org.zalando.nakadi.exceptions; +package org.zalando.nakadi.exceptions.runtime; import org.zalando.nakadi.domain.CursorError; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.view.Cursor; -public class InvalidCursorException extends Exception { +public class InvalidCursorException extends NakadiRuntimeBaseException { private final CursorError error; private final Cursor cursor; diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java index 3eb699ebce..c7542644ae 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java @@ -1,7 +1,5 @@ package org.zalando.nakadi.exceptions.runtime; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; - public class NoEventTypeException extends NakadiRuntimeBaseException { public NoEventTypeException(final String msg) { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchEventTypeException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchEventTypeException.java new file mode 100644 index 0000000000..e4966d213d --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchEventTypeException.java @@ -0,0 +1,11 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class NoSuchEventTypeException extends NakadiRuntimeBaseException { + public NoSuchEventTypeException(final String message) { + super(message); + } + + public NoSuchEventTypeException(final String msg, final Exception cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/zalando/nakadi/repository/EventConsumer.java b/src/main/java/org/zalando/nakadi/repository/EventConsumer.java index 4b27f7bdb0..4c1bda3569 100644 --- a/src/main/java/org/zalando/nakadi/repository/EventConsumer.java +++ b/src/main/java/org/zalando/nakadi/repository/EventConsumer.java @@ -4,7 +4,7 @@ import org.zalando.nakadi.domain.EventTypePartition; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.TopicPartition; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import java.io.Closeable; diff --git a/src/main/java/org/zalando/nakadi/repository/EventTypeRepository.java b/src/main/java/org/zalando/nakadi/repository/EventTypeRepository.java index e7cbdd139e..8f109f70ee 100644 --- a/src/main/java/org/zalando/nakadi/repository/EventTypeRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/EventTypeRepository.java @@ -3,7 +3,7 @@ import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; import java.util.List; diff --git a/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java b/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java index 716af70a96..ce96b93b7e 100644 --- a/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java +++ b/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java @@ -8,7 +8,7 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.domain.TopicPartition; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; diff --git a/src/main/java/org/zalando/nakadi/repository/TopicRepository.java b/src/main/java/org/zalando/nakadi/repository/TopicRepository.java index cb0c55a78a..8c3322d8c0 100644 --- a/src/main/java/org/zalando/nakadi/repository/TopicRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/TopicRepository.java @@ -5,7 +5,7 @@ import org.zalando.nakadi.domain.PartitionEndStatistics; import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.EventPublishingException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; diff --git a/src/main/java/org/zalando/nakadi/repository/db/CachingEventTypeRepository.java b/src/main/java/org/zalando/nakadi/repository/db/CachingEventTypeRepository.java index 401b6eb5a8..7c362044be 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/CachingEventTypeRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/db/CachingEventTypeRepository.java @@ -9,7 +9,7 @@ import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; import org.zalando.nakadi.repository.EventTypeRepository; diff --git a/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java b/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java index bc11bb847d..91d29ffbb2 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java +++ b/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java @@ -16,7 +16,7 @@ import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.EventTypeRepository; import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; import org.zalando.nakadi.service.timeline.TimelineSync; diff --git a/src/main/java/org/zalando/nakadi/repository/db/EventTypeDbRepository.java b/src/main/java/org/zalando/nakadi/repository/db/EventTypeDbRepository.java index 219055038c..99f8e09077 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/EventTypeDbRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/db/EventTypeDbRepository.java @@ -16,7 +16,7 @@ import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; import org.zalando.nakadi.repository.EventTypeRepository; diff --git a/src/main/java/org/zalando/nakadi/repository/kafka/KafkaCursor.java b/src/main/java/org/zalando/nakadi/repository/kafka/KafkaCursor.java index 7f0375d96f..f57bb7743c 100644 --- a/src/main/java/org/zalando/nakadi/repository/kafka/KafkaCursor.java +++ b/src/main/java/org/zalando/nakadi/repository/kafka/KafkaCursor.java @@ -2,7 +2,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import java.util.Objects; diff --git a/src/main/java/org/zalando/nakadi/repository/kafka/KafkaTopicRepository.java b/src/main/java/org/zalando/nakadi/repository/kafka/KafkaTopicRepository.java index 90023698f9..e3a0d44142 100644 --- a/src/main/java/org/zalando/nakadi/repository/kafka/KafkaTopicRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/kafka/KafkaTopicRepository.java @@ -27,7 +27,7 @@ import org.zalando.nakadi.domain.PartitionEndStatistics; import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.EventPublishingException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TopicConfigException; diff --git a/src/main/java/org/zalando/nakadi/service/CursorConverter.java b/src/main/java/org/zalando/nakadi/service/CursorConverter.java index 1d4f311782..c173fb75ed 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorConverter.java +++ b/src/main/java/org/zalando/nakadi/service/CursorConverter.java @@ -3,8 +3,8 @@ import com.google.common.base.Preconditions; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.view.Cursor; import org.zalando.nakadi.view.SubscriptionCursor; diff --git a/src/main/java/org/zalando/nakadi/service/CursorsService.java b/src/main/java/org/zalando/nakadi/service/CursorsService.java index d64b4f443d..40c45f1f81 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorsService.java @@ -9,12 +9,12 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.OperationTimeoutException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; diff --git a/src/main/java/org/zalando/nakadi/service/EventPublisher.java b/src/main/java/org/zalando/nakadi/service/EventPublisher.java index efef3b1c92..9cdb3ed239 100644 --- a/src/main/java/org/zalando/nakadi/service/EventPublisher.java +++ b/src/main/java/org/zalando/nakadi/service/EventPublisher.java @@ -19,7 +19,7 @@ import org.zalando.nakadi.exceptions.runtime.CompactionException; import org.zalando.nakadi.exceptions.runtime.EnrichmentException; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.PartitioningException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.EventPublishingException; diff --git a/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java b/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java index 9dee599d65..272a2bede0 100644 --- a/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java +++ b/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java @@ -4,7 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.repository.EventConsumer; diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 2e2d6ea5e3..fa712933bd 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -28,7 +28,7 @@ import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; @@ -61,6 +61,7 @@ import org.zalando.nakadi.util.JsonUtils; import org.zalando.nakadi.validation.SchemaEvolutionService; import org.zalando.nakadi.validation.SchemaIncompatibility; +import org.zalando.problem.Problem; import java.io.Closeable; import java.io.IOException; @@ -71,6 +72,7 @@ import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DELETE_EVENT_TYPE_WITH_SUBSCRIPTIONS; @Component @@ -444,7 +446,7 @@ public Result get(final String eventTypeName) { return Result.ok(eventType); } catch (final NoSuchEventTypeException e) { LOG.debug("Could not find EventType: {}", eventTypeName); - return Result.problem(e.asProblem()); + return Result.problem(Problem.valueOf(NOT_FOUND, e.getMessage())); } catch (final InternalNakadiException e) { LOG.error("Problem loading event type " + eventTypeName, e); return Result.problem(e.asProblem()); diff --git a/src/main/java/org/zalando/nakadi/service/NakadiCursorComparator.java b/src/main/java/org/zalando/nakadi/service/NakadiCursorComparator.java index 8f7e94e0cd..c861bb02f0 100644 --- a/src/main/java/org/zalando/nakadi/service/NakadiCursorComparator.java +++ b/src/main/java/org/zalando/nakadi/service/NakadiCursorComparator.java @@ -5,7 +5,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.db.EventTypeCache; import java.util.Comparator; diff --git a/src/main/java/org/zalando/nakadi/service/converter/CursorConverterImpl.java b/src/main/java/org/zalando/nakadi/service/converter/CursorConverterImpl.java index 2e48b8548b..daa7732ffd 100644 --- a/src/main/java/org/zalando/nakadi/service/converter/CursorConverterImpl.java +++ b/src/main/java/org/zalando/nakadi/service/converter/CursorConverterImpl.java @@ -5,8 +5,8 @@ import org.springframework.stereotype.Service; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.repository.db.EventTypeCache; import org.zalando.nakadi.service.CursorConverter; diff --git a/src/main/java/org/zalando/nakadi/service/converter/VersionOneConverter.java b/src/main/java/org/zalando/nakadi/service/converter/VersionOneConverter.java index 880bfa4a86..9c6cd4c3ef 100644 --- a/src/main/java/org/zalando/nakadi/service/converter/VersionOneConverter.java +++ b/src/main/java/org/zalando/nakadi/service/converter/VersionOneConverter.java @@ -4,8 +4,8 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.db.EventTypeCache; import org.zalando.nakadi.service.CursorConverter; import org.zalando.nakadi.service.StaticStorageWorkerFactory; diff --git a/src/main/java/org/zalando/nakadi/service/converter/VersionZeroConverter.java b/src/main/java/org/zalando/nakadi/service/converter/VersionZeroConverter.java index 110b3ab012..80acfe0a03 100644 --- a/src/main/java/org/zalando/nakadi/service/converter/VersionZeroConverter.java +++ b/src/main/java/org/zalando/nakadi/service/converter/VersionZeroConverter.java @@ -6,8 +6,8 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.repository.TopicRepository; import org.zalando.nakadi.service.CursorConverter; diff --git a/src/main/java/org/zalando/nakadi/service/converter/VersionedConverter.java b/src/main/java/org/zalando/nakadi/service/converter/VersionedConverter.java index 30a5296d60..7a6b596dc6 100644 --- a/src/main/java/org/zalando/nakadi/service/converter/VersionedConverter.java +++ b/src/main/java/org/zalando/nakadi/service/converter/VersionedConverter.java @@ -2,8 +2,8 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.service.CursorConverter; import org.zalando.nakadi.view.Cursor; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java index ab5593e092..b800ed4b18 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java @@ -23,8 +23,8 @@ import org.zalando.nakadi.domain.SubscriptionEventTypeStats; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.Try; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; @@ -69,6 +69,8 @@ import java.util.Set; import java.util.stream.Collectors; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; + @Component public class SubscriptionService { @@ -244,13 +246,14 @@ public Result deleteSubscription(final String subscriptionId) throws DbWri return Result.problem(Problem.valueOf(Response.Status.SERVICE_UNAVAILABLE, e.getMessage())); } catch (final NoSuchEventTypeException | InternalNakadiException e) { LOG.error("Exception can not occur", e); - return Result.problem(e.asProblem()); + return Result.problem(Problem.valueOf(NOT_FOUND, e.getMessage())); } } public ItemsWrapper getSubscriptionStat(final String subscriptionId, final StatsMode statsMode) - throws InconsistentStateException, NoSuchSubscriptionException, ServiceTemporarilyUnavailableException { + throws InconsistentStateException, NoSuchEventTypeException, + NoSuchSubscriptionException, ServiceTemporarilyUnavailableException { final Subscription subscription; try { subscription = subscriptionRepository.getSubscription(subscriptionId); @@ -263,7 +266,7 @@ public ItemsWrapper getSubscriptionStat(final String private List createSubscriptionStat(final Subscription subscription, final StatsMode statsMode) - throws InconsistentStateException, ServiceTemporarilyUnavailableException { + throws InconsistentStateException, NoSuchEventTypeException, ServiceTemporarilyUnavailableException { final List eventTypes = getEventTypesForSubscription(subscription); final ZkSubscriptionClient subscriptionClient = createZkSubscriptionClient(subscription); final Optional zkSubscriptionNode = subscriptionClient.getZkSubscriptionNode(); @@ -285,7 +288,8 @@ private ZkSubscriptionClient createZkSubscriptionClient(final Subscription subsc } } - private List getEventTypesForSubscription(final Subscription subscription) { + private List getEventTypesForSubscription(final Subscription subscription) + throws NoSuchEventTypeException { return subscription.getEventTypes().stream() .map(Try.wrap(eventTypeRepository::findByName)) .map(Try::getOrThrow) diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java index fa4d8d4343..2102537748 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java @@ -8,7 +8,7 @@ import org.springframework.stereotype.Service; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.db.EventTypeCache; import org.zalando.nakadi.service.AuthorizationValidator; import org.zalando.nakadi.service.BlacklistService; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java index cd2da6048b..fb5c68b42a 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java @@ -9,7 +9,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.PartitionEndStatistics; import org.zalando.nakadi.exceptions.runtime.ErrorGettingCursorTimeLagException; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.LimitReachedException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java index b36c160f2a..d23d91a5ed 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java @@ -10,7 +10,7 @@ import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java index 0f0e8fc64d..d38c5eb387 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java @@ -9,7 +9,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionClientFactory.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionClientFactory.java index 59abfe2065..f736524b5a 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionClientFactory.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionClientFactory.java @@ -6,7 +6,7 @@ import org.springframework.stereotype.Service; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; @Service diff --git a/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java b/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java index 4a3cbfb8b4..1e941fb11d 100644 --- a/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java +++ b/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java @@ -21,9 +21,9 @@ import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; diff --git a/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java b/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java index b489d245e9..91e0284003 100644 --- a/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java @@ -12,8 +12,8 @@ import org.zalando.nakadi.domain.ItemsWrapper; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InvalidCursorException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.repository.EventTypeRepository; diff --git a/src/test/java/org/zalando/nakadi/controller/EventPublishingControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventPublishingControllerTest.java index a46d4142f4..f144e78c12 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventPublishingControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventPublishingControllerTest.java @@ -17,7 +17,7 @@ import org.zalando.nakadi.domain.EventPublishingStatus; import org.zalando.nakadi.domain.EventPublishingStep; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.EventTypeTimeoutException; import org.zalando.nakadi.metrics.EventTypeMetricRegistry; import org.zalando.nakadi.metrics.EventTypeMetrics; diff --git a/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java index 58eed109ee..db50090942 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java @@ -20,9 +20,9 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java index a843c93723..749615580c 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java @@ -26,7 +26,7 @@ import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; import org.zalando.nakadi.exceptions.runtime.TopicConfigException; diff --git a/src/test/java/org/zalando/nakadi/controller/PartitionsControllerTest.java b/src/test/java/org/zalando/nakadi/controller/PartitionsControllerTest.java index bde6e42a15..e26d6621e7 100644 --- a/src/test/java/org/zalando/nakadi/controller/PartitionsControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/PartitionsControllerTest.java @@ -15,7 +15,7 @@ import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.repository.EventTypeRepository; import org.zalando.nakadi.repository.TopicRepository; diff --git a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java index 5ce11c6ca1..61dac0bba5 100644 --- a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java @@ -22,7 +22,7 @@ import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionEventTypeStats; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.plugin.api.ApplicationService; diff --git a/src/test/java/org/zalando/nakadi/domain/NakadiCursorTest.java b/src/test/java/org/zalando/nakadi/domain/NakadiCursorTest.java index 5d1057dc60..e08eeaef20 100644 --- a/src/test/java/org/zalando/nakadi/domain/NakadiCursorTest.java +++ b/src/test/java/org/zalando/nakadi/domain/NakadiCursorTest.java @@ -2,7 +2,7 @@ import com.google.common.collect.ImmutableMap; import org.junit.Test; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; diff --git a/src/test/java/org/zalando/nakadi/repository/kafka/KafkaCursorTest.java b/src/test/java/org/zalando/nakadi/repository/kafka/KafkaCursorTest.java index 2b653ba9dc..cfabf2ebd7 100644 --- a/src/test/java/org/zalando/nakadi/repository/kafka/KafkaCursorTest.java +++ b/src/test/java/org/zalando/nakadi/repository/kafka/KafkaCursorTest.java @@ -4,7 +4,7 @@ import org.junit.Test; import org.zalando.nakadi.domain.CursorError; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.utils.TestUtils; public class KafkaCursorTest { diff --git a/src/test/java/org/zalando/nakadi/repository/kafka/KafkaTopicRepositoryTest.java b/src/test/java/org/zalando/nakadi/repository/kafka/KafkaTopicRepositoryTest.java index 205ce97def..d87efec091 100644 --- a/src/test/java/org/zalando/nakadi/repository/kafka/KafkaTopicRepositoryTest.java +++ b/src/test/java/org/zalando/nakadi/repository/kafka/KafkaTopicRepositoryTest.java @@ -23,7 +23,7 @@ import org.zalando.nakadi.domain.PartitionEndStatistics; import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.EventPublishingException; import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; import org.zalando.nakadi.repository.zookeeper.ZookeeperSettings; diff --git a/src/test/java/org/zalando/nakadi/service/NakadiCursorComparatorTest.java b/src/test/java/org/zalando/nakadi/service/NakadiCursorComparatorTest.java index f7f6de0d83..ea19eeb86d 100644 --- a/src/test/java/org/zalando/nakadi/service/NakadiCursorComparatorTest.java +++ b/src/test/java/org/zalando/nakadi/service/NakadiCursorComparatorTest.java @@ -7,7 +7,7 @@ import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.db.EventTypeCache; import org.zalando.nakadi.repository.kafka.KafkaCursor; diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java index 5c5ed83edc..0ab31f1d64 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java @@ -10,7 +10,7 @@ import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.runtime.ErrorGettingCursorTimeLagException; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.repository.EventConsumer; diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java index 7068bffa35..e99a4c896d 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java @@ -11,7 +11,7 @@ import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; diff --git a/src/test/java/org/zalando/nakadi/service/converter/VersionOneConverterTest.java b/src/test/java/org/zalando/nakadi/service/converter/VersionOneConverterTest.java index 85a649c4b2..f0de627811 100644 --- a/src/test/java/org/zalando/nakadi/service/converter/VersionOneConverterTest.java +++ b/src/test/java/org/zalando/nakadi/service/converter/VersionOneConverterTest.java @@ -8,7 +8,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.repository.db.EventTypeCache; import org.zalando.nakadi.view.Cursor; diff --git a/src/test/java/org/zalando/nakadi/service/converter/VersionZeroConverterTest.java b/src/test/java/org/zalando/nakadi/service/converter/VersionZeroConverterTest.java index 20fa8c66ca..144e733a0e 100644 --- a/src/test/java/org/zalando/nakadi/service/converter/VersionZeroConverterTest.java +++ b/src/test/java/org/zalando/nakadi/service/converter/VersionZeroConverterTest.java @@ -3,8 +3,8 @@ import org.junit.Before; import org.junit.Test; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.service.timeline.TimelineService; import org.zalando.nakadi.view.Cursor; diff --git a/src/test/java/org/zalando/nakadi/service/subscription/state/StreamingStateTest.java b/src/test/java/org/zalando/nakadi/service/subscription/state/StreamingStateTest.java index c6d42ad2dc..3a9abe6637 100644 --- a/src/test/java/org/zalando/nakadi/service/subscription/state/StreamingStateTest.java +++ b/src/test/java/org/zalando/nakadi/service/subscription/state/StreamingStateTest.java @@ -12,8 +12,8 @@ import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.InvalidCursorException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.repository.EventConsumer; import org.zalando.nakadi.repository.TopicRepository; diff --git a/src/test/java/org/zalando/nakadi/service/timeline/TimelineServiceTest.java b/src/test/java/org/zalando/nakadi/service/timeline/TimelineServiceTest.java index 27153642cc..1a2a265155 100644 --- a/src/test/java/org/zalando/nakadi/service/timeline/TimelineServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/timeline/TimelineServiceTest.java @@ -13,7 +13,7 @@ import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.TimelineException; From 5b6ea5e8e5325a2ff08d355338d1cf00c3d43eb9 Mon Sep 17 00:00:00 2001 From: Andrey Dyachkov Date: Mon, 20 Aug 2018 11:58:34 +0200 Subject: [PATCH 070/176] fixed checkstyle --- .../nakadi/config/SecurityConfiguration.java | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java index 6ce380c535..81b10df382 100644 --- a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java +++ b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java @@ -210,21 +210,22 @@ private static class AllowForwardSlashesStrictHttpFirewall extends StrictHttpFir private static final String ENCODED_PERCENT = "%25"; private static final String PERCENT = "%"; - private static final List FORBIDDEN_ENCODED_PERIOD = Collections.unmodifiableList(Arrays.asList("%2e", "%2E")); + private static final List FORBIDDEN_ENCODED_PERIOD = + Collections.unmodifiableList(Arrays.asList("%2e", "%2E")); private Set encodedUrlBlacklist = new HashSet<>(); private Set decodedUrlBlacklist = new HashSet<>(); - public AllowForwardSlashesStrictHttpFirewall() { + AllowForwardSlashesStrictHttpFirewall() { super(); this.encodedUrlBlacklist.add(ENCODED_PERCENT); this.encodedUrlBlacklist.addAll(FORBIDDEN_ENCODED_PERIOD); this.decodedUrlBlacklist.add(PERCENT); } - private static boolean containsOnlyPrintableAsciiCharacters(String uri) { - int length = uri.length(); + private static boolean containsOnlyPrintableAsciiCharacters(final String uri) { + final int length = uri.length(); for (int i = 0; i < length; i++) { - char c = uri.charAt(i); + final char c = uri.charAt(i); if (c < '\u0020' || c > '\u007e') { return false; } @@ -233,14 +234,14 @@ private static boolean containsOnlyPrintableAsciiCharacters(String uri) { return true; } - private static boolean encodedUrlContains(HttpServletRequest request, String value) { + private static boolean encodedUrlContains(final HttpServletRequest request, final String value) { if (valueContains(request.getContextPath(), value)) { return true; } return valueContains(request.getRequestURI(), value); } - private static boolean decodedUrlContains(HttpServletRequest request, String value) { + private static boolean decodedUrlContains(final HttpServletRequest request, final String value) { if (valueContains(request.getServletPath(), value)) { return true; } @@ -250,21 +251,23 @@ private static boolean decodedUrlContains(HttpServletRequest request, String val return false; } - private static boolean valueContains(String value, String contains) { + private static boolean valueContains(final String value, final String contains) { return value != null && value.contains(contains); } @Override - public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException { + public FirewalledRequest getFirewalledRequest(final HttpServletRequest request) + throws RequestRejectedException { rejectedBlacklistedUrls(request); if (!isNormalized(request)) { throw new RequestRejectedException("The request was rejected because the URL was not normalized."); } - String requestUri = request.getRequestURI(); + final String requestUri = request.getRequestURI(); if (!containsOnlyPrintableAsciiCharacters(requestUri)) { - throw new RequestRejectedException("The requestURI was rejected because it can only contain printable ASCII characters."); + throw new RequestRejectedException("The requestURI was rejected because it can only " + + "contain printable ASCII characters."); } return new FirewalledRequest(request) { @Override @@ -273,7 +276,7 @@ public void reset() { }; } - private static boolean isNormalized(HttpServletRequest request) { + private static boolean isNormalized(final HttpServletRequest request) { if (!isNormalized(request.getRequestURI())) { return false; } @@ -289,7 +292,7 @@ private static boolean isNormalized(HttpServletRequest request) { return true; } - private static boolean isNormalized(String path) { + private static boolean isNormalized(final String path) { if (path == null) { return true; } @@ -300,8 +303,8 @@ private static boolean isNormalized(String path) { // } for (int j = path.length(); j > 0;) { - int i = path.lastIndexOf('/', j - 1); - int gap = j - i; + final int i = path.lastIndexOf('/', j - 1); + final int gap = j - i; if (gap == 2 && path.charAt(i + 1) == '.') { // ".", "/./" or "/." @@ -316,15 +319,17 @@ private static boolean isNormalized(String path) { return true; } - private void rejectedBlacklistedUrls(HttpServletRequest request) { - for (String forbidden : this.encodedUrlBlacklist) { + private void rejectedBlacklistedUrls(final HttpServletRequest request) { + for (final String forbidden : this.encodedUrlBlacklist) { if (encodedUrlContains(request, forbidden)) { - throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\""); + throw new RequestRejectedException("The request was rejected because the URL contained " + + "a potentially malicious String \"" + forbidden + "\""); } } - for (String forbidden : this.decodedUrlBlacklist) { + for (final String forbidden : this.decodedUrlBlacklist) { if (decodedUrlContains(request, forbidden)) { - throw new RequestRejectedException("The request was rejected because the URL contained a potentially malicious String \"" + forbidden + "\""); + throw new RequestRejectedException("The request was rejected because the URL contained " + + "a potentially malicious String \"" + forbidden + "\""); } } } From 3677664a2d7ebd8b3c1704bc5173ccba4816559b Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 12:29:23 +0200 Subject: [PATCH 071/176] fix --- .../org/zalando/nakadi/webservice/EventStreamReadingAT.java | 2 +- .../java/org/zalando/nakadi/repository/db/EventTypeCache.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/acceptance-test/java/org/zalando/nakadi/webservice/EventStreamReadingAT.java b/src/acceptance-test/java/org/zalando/nakadi/webservice/EventStreamReadingAT.java index 499fe06bc3..aaa04db1d4 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/webservice/EventStreamReadingAT.java +++ b/src/acceptance-test/java/org/zalando/nakadi/webservice/EventStreamReadingAT.java @@ -262,7 +262,7 @@ public void whenReachKeepAliveLimitThenStreamIsClosed() { } @Test(timeout = 5000) - public void whenGetEventsWithUknownTopicThenTopicNotFound() { + public void whenGetEventsWithUnknownTopicThenTopicNotFound() { given() .when() .get(createStreamEndpointUrl("blah-topic")) diff --git a/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java b/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java index 91d29ffbb2..cd4ca37021 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java +++ b/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java @@ -5,6 +5,7 @@ import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.common.collect.ImmutableList; +import com.google.common.util.concurrent.UncheckedExecutionException; import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.recipes.cache.PathChildrenCache; import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; @@ -161,7 +162,7 @@ private Optional getCached(final String name) throws NoSuchEventTypeException, InternalNakadiException { try { return Optional.ofNullable(eventTypeCache.get(name)); - } catch (final ExecutionException e) { + } catch (final UncheckedExecutionException | ExecutionException e) { if (e.getCause() instanceof NoSuchEventTypeException) { throw (NoSuchEventTypeException) e.getCause(); } else { From c1d8843ef749a3913de52c43f70dd4fb093eb472 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 12:52:42 +0200 Subject: [PATCH 072/176] Refactor NoSuchSchemaException --- .../nakadi/controller/ExceptionHandling.java | 8 ++++++++ .../exceptions/NoSuchSchemaException.java | 19 ------------------- .../runtime/NoSuchSchemaException.java | 13 +++++++++++++ .../repository/db/SchemaRepository.java | 2 +- .../zalando/nakadi/service/SchemaService.java | 4 ++-- .../nakadi/service/SchemaServiceTest.java | 2 +- 6 files changed, 25 insertions(+), 23 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/NoSuchSchemaException.java create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSchemaException.java diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 0938e94196..3ddcc13751 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.NativeWebRequest; +import org.zalando.nakadi.exceptions.runtime.NoSuchSchemaException; import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; @@ -233,4 +234,11 @@ public ResponseEntity handleNoSuchEventTypeException(final NoSuchEventT LOG.debug(exception.getMessage(), exception); return Responses.create(NOT_FOUND, exception.getMessage(), request); } + + @ExceptionHandler(NoSuchSchemaException.class) + public ResponseEntity handleNoSuchEventTypeException(final NoSuchSchemaException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return Responses.create(NOT_FOUND, exception.getMessage(), request); + } } diff --git a/src/main/java/org/zalando/nakadi/exceptions/NoSuchSchemaException.java b/src/main/java/org/zalando/nakadi/exceptions/NoSuchSchemaException.java deleted file mode 100644 index 631898000e..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/NoSuchSchemaException.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.zalando.nakadi.exceptions; - -import javax.ws.rs.core.Response; - -public class NoSuchSchemaException extends NakadiException { - - public NoSuchSchemaException(final String message) { - super(message); - } - - public NoSuchSchemaException(final String msg, final Exception cause) { - super(msg, cause); - } - - @Override - protected Response.StatusType getStatus() { - return Response.Status.NOT_FOUND; - } -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSchemaException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSchemaException.java new file mode 100644 index 0000000000..a8824d12d1 --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSchemaException.java @@ -0,0 +1,13 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class NoSuchSchemaException extends NakadiRuntimeBaseException { + + public NoSuchSchemaException(final String message) { + super(message); + } + + public NoSuchSchemaException(final String msg, final Exception cause) { + super(msg, cause); + } + +} diff --git a/src/main/java/org/zalando/nakadi/repository/db/SchemaRepository.java b/src/main/java/org/zalando/nakadi/repository/db/SchemaRepository.java index 958a0e70f2..e776f84bc2 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/SchemaRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/db/SchemaRepository.java @@ -7,7 +7,7 @@ import org.springframework.jdbc.core.RowMapper; import org.springframework.stereotype.Component; import org.zalando.nakadi.domain.EventTypeSchema; -import org.zalando.nakadi.exceptions.NoSuchSchemaException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSchemaException; import java.io.IOException; import java.sql.ResultSet; diff --git a/src/main/java/org/zalando/nakadi/service/SchemaService.java b/src/main/java/org/zalando/nakadi/service/SchemaService.java index 9eb9e0b71c..544159e1e4 100644 --- a/src/main/java/org/zalando/nakadi/service/SchemaService.java +++ b/src/main/java/org/zalando/nakadi/service/SchemaService.java @@ -5,7 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.zalando.nakadi.domain.EventTypeSchema; -import org.zalando.nakadi.exceptions.NoSuchSchemaException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSchemaException; import org.zalando.nakadi.repository.db.SchemaRepository; import org.zalando.problem.Problem; @@ -57,7 +57,7 @@ public Result getSchemaVersion(final String name, final String return Result.ok(schema); } catch (final NoSuchSchemaException e) { LOG.debug("Could not find EventTypeSchema version: {} for EventType: {}", version, name); - return Result.problem(e.asProblem()); + return Result.problem(Problem.valueOf(Response.Status.NOT_FOUND, e.getMessage())); } } } diff --git a/src/test/java/org/zalando/nakadi/service/SchemaServiceTest.java b/src/test/java/org/zalando/nakadi/service/SchemaServiceTest.java index 685d04e8d4..5d7fd724fb 100644 --- a/src/test/java/org/zalando/nakadi/service/SchemaServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SchemaServiceTest.java @@ -8,7 +8,7 @@ import org.zalando.nakadi.domain.EventTypeSchema; import org.zalando.nakadi.domain.PaginationWrapper; import org.zalando.nakadi.domain.Version; -import org.zalando.nakadi.exceptions.NoSuchSchemaException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSchemaException; import org.zalando.nakadi.repository.db.SchemaRepository; import javax.ws.rs.core.Response; From 1ea81f73a1dbc38c979ab88bc4b40bfbc55c2701 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 13:48:35 +0200 Subject: [PATCH 073/176] Refactor NoSuchSubscriptionException --- .../db/SubscriptionDbRepositoryTest.java | 2 +- .../nakadi/controller/CursorsController.java | 5 +++++ .../nakadi/controller/ExceptionHandling.java | 12 ++++++++++-- .../PostSubscriptionController.java | 5 +++-- .../SubscriptionStreamController.java | 2 +- .../NoSuchSubscriptionException.java | 19 ------------------- .../runtime/NoSuchSubscriptionException.java | 12 ++++++++++++ .../db/SubscriptionDbRepository.java | 2 +- .../nakadi/service/BlacklistService.java | 2 +- .../nakadi/service/CursorsService.java | 2 +- .../nakadi/service/EventTypeService.java | 2 +- .../subscription/SubscriptionService.java | 6 +++--- .../controller/CursorsControllerTest.java | 2 +- .../SubscriptionControllerTest.java | 2 +- .../service/SubscriptionServiceTest.java | 2 +- 15 files changed, 42 insertions(+), 35 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/NoSuchSubscriptionException.java create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSubscriptionException.java diff --git a/src/acceptance-test/java/org/zalando/nakadi/repository/db/SubscriptionDbRepositoryTest.java b/src/acceptance-test/java/org/zalando/nakadi/repository/db/SubscriptionDbRepositoryTest.java index bae9b0dec1..130fdb124b 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/repository/db/SubscriptionDbRepositoryTest.java +++ b/src/acceptance-test/java/org/zalando/nakadi/repository/db/SubscriptionDbRepositoryTest.java @@ -8,7 +8,7 @@ import org.zalando.nakadi.config.JsonConfig; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; -import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.DuplicatedSubscriptionException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.util.HashGenerator; diff --git a/src/main/java/org/zalando/nakadi/controller/CursorsController.java b/src/main/java/org/zalando/nakadi/controller/CursorsController.java index ddf62cf8c0..ce00a42b6b 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorsController.java @@ -23,6 +23,7 @@ import org.zalando.nakadi.exceptions.runtime.CursorsAreEmptyException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.RequestInProgressException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.UnableProcessException; @@ -46,6 +47,7 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.springframework.http.ResponseEntity.noContent; import static org.springframework.http.ResponseEntity.ok; @@ -110,6 +112,9 @@ public ResponseEntity commitCursors(@PathVariable("subscriptionId") final Str } } catch (final NoSuchEventTypeException | InvalidCursorException e) { return create(Problem.valueOf(UNPROCESSABLE_ENTITY, e.getMessage()), request); + } catch (final NoSuchSubscriptionException e) { + LOG.error("Subscription not found", e); + return create(Problem.valueOf(NOT_FOUND, e.getMessage()), request); } catch (final ServiceTemporarilyUnavailableException e) { LOG.error("Failed to commit cursors", e); return create(Problem.valueOf(SERVICE_UNAVAILABLE, e.getMessage()), request); diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 3ddcc13751..f207e101d6 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -14,6 +14,7 @@ import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.PartitioningException; import org.zalando.nakadi.exceptions.runtime.CompactionException; import org.zalando.nakadi.exceptions.runtime.EnrichmentException; @@ -236,8 +237,15 @@ public ResponseEntity handleNoSuchEventTypeException(final NoSuchEventT } @ExceptionHandler(NoSuchSchemaException.class) - public ResponseEntity handleNoSuchEventTypeException(final NoSuchSchemaException exception, - final NativeWebRequest request) { + public ResponseEntity handleNoSuchSchemaException(final NoSuchSchemaException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return Responses.create(NOT_FOUND, exception.getMessage(), request); + } + + @ExceptionHandler(NoSuchSubscriptionException.class) + public ResponseEntity handleNoSuchSubscriptionException(final NoSuchSubscriptionException exception, + final NativeWebRequest request) { LOG.debug(exception.getMessage(), exception); return Responses.create(NOT_FOUND, exception.getMessage(), request); } diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index d71baa88ec..885262a9bc 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -16,7 +16,7 @@ import org.springframework.web.util.UriComponents; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; -import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.DuplicatedSubscriptionException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; @@ -37,6 +37,7 @@ import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static org.springframework.http.HttpStatus.OK; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DISABLE_SUBSCRIPTION_CREATION; @@ -98,7 +99,7 @@ public ResponseEntity updateSubscription( } catch (final SubscriptionUpdateConflictException ex) { return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, ex.getMessage(), request); } catch (final NoSuchSubscriptionException ex) { - return Responses.create(ex.asProblem(), request); + return Responses.create(Problem.valueOf(NOT_FOUND, ex.getMessage()), request); } } diff --git a/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java b/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java index 7abe9f8c62..c6676e87df 100644 --- a/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java @@ -22,7 +22,7 @@ import org.zalando.nakadi.config.NakadiSettings; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.SubscriptionPartitionConflictException; import org.zalando.nakadi.exceptions.runtime.WrongStreamParametersException; diff --git a/src/main/java/org/zalando/nakadi/exceptions/NoSuchSubscriptionException.java b/src/main/java/org/zalando/nakadi/exceptions/NoSuchSubscriptionException.java deleted file mode 100644 index cd788fdce9..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/NoSuchSubscriptionException.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.zalando.nakadi.exceptions; - -import javax.ws.rs.core.Response; - -public class NoSuchSubscriptionException extends NakadiException { - - public NoSuchSubscriptionException(final String message) { - super(message); - } - - public NoSuchSubscriptionException(final String msg, final Exception cause) { - super(msg, cause); - } - - @Override - protected Response.StatusType getStatus() { - return Response.Status.NOT_FOUND; - } -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSubscriptionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSubscriptionException.java new file mode 100644 index 0000000000..235f111b03 --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSubscriptionException.java @@ -0,0 +1,12 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class NoSuchSubscriptionException extends NakadiRuntimeBaseException { + + public NoSuchSubscriptionException(final String message) { + super(message); + } + + public NoSuchSubscriptionException(final String msg, final Exception cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java b/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java index e93bb0c17f..66e8c8010b 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java @@ -18,7 +18,7 @@ import org.springframework.stereotype.Component; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; -import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.DuplicatedSubscriptionException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.NoSubscriptionException; diff --git a/src/main/java/org/zalando/nakadi/service/BlacklistService.java b/src/main/java/org/zalando/nakadi/service/BlacklistService.java index 9130ea58ba..c19f8966aa 100644 --- a/src/main/java/org/zalando/nakadi/service/BlacklistService.java +++ b/src/main/java/org/zalando/nakadi/service/BlacklistService.java @@ -8,7 +8,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.repository.db.SubscriptionDbRepository; import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; diff --git a/src/main/java/org/zalando/nakadi/service/CursorsService.java b/src/main/java/org/zalando/nakadi/service/CursorsService.java index 40c45f1f81..38963b96e5 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorsService.java @@ -15,7 +15,7 @@ import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.OperationTimeoutException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.UnableProcessException; diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index fa712933bd..2790916fa3 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -30,7 +30,7 @@ import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; -import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java index b800ed4b18..44e5f0fdc3 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java @@ -25,7 +25,7 @@ import org.zalando.nakadi.exceptions.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.Try; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; import org.zalando.nakadi.exceptions.runtime.DuplicatedSubscriptionException; @@ -211,7 +211,7 @@ public Result getSubscription(final String subscriptionId) { return Result.ok(subscription); } catch (final NoSuchSubscriptionException e) { LOG.debug("Failed to find subscription: {}", subscriptionId); - return Result.problem(e.asProblem()); + return Result.problem(Problem.valueOf(NOT_FOUND, e.getMessage())); } catch (final ServiceTemporarilyUnavailableException e) { LOG.error("Error occurred when trying to get subscription: {}", subscriptionId, e); return Result.problem(Problem.valueOf(Response.Status.SERVICE_UNAVAILABLE, e.getMessage())); @@ -240,7 +240,7 @@ public Result deleteSubscription(final String subscriptionId) throws DbWri return Result.ok(); } catch (final NoSuchSubscriptionException e) { LOG.debug("Failed to find subscription: {}", subscriptionId, e); - return Result.problem(e.asProblem()); + return Result.problem(Problem.valueOf(NOT_FOUND, e.getMessage())); } catch (final ServiceTemporarilyUnavailableException e) { LOG.error("Error occurred when trying to delete subscription: {}", subscriptionId, e); return Result.problem(Problem.valueOf(Response.Status.SERVICE_UNAVAILABLE, e.getMessage())); diff --git a/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java b/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java index 91e0284003..810f287dd3 100644 --- a/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java @@ -14,7 +14,7 @@ import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.repository.EventTypeRepository; import org.zalando.nakadi.repository.db.SubscriptionDbRepository; diff --git a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java index 61dac0bba5..df95d26a89 100644 --- a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java @@ -23,7 +23,7 @@ import org.zalando.nakadi.domain.SubscriptionEventTypeStats; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.plugin.api.ApplicationService; import org.zalando.nakadi.repository.EventTypeRepository; diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java index 0ddd75ac8e..70bebfa13e 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionServiceTest.java @@ -6,7 +6,7 @@ import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.domain.SubscriptionResource; -import org.zalando.nakadi.exceptions.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; From b14339933ae5d31b0214beee45f7beba51caa6d2 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 14:00:39 +0200 Subject: [PATCH 074/176] Refactor NoStreamingSlotsAvailable --- .../nakadi/controller/ExceptionHandling.java | 31 ++++++++++++------- .../exceptions/NoStreamingSlotsAvailable.java | 14 --------- .../runtime/NoStreamingSlotsAvailable.java | 7 +++++ .../subscription/state/StartingState.java | 2 +- 4 files changed, 28 insertions(+), 26 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/NoStreamingSlotsAvailable.java create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/NoStreamingSlotsAvailable.java diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index f207e101d6..84d13876f0 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -10,28 +10,29 @@ import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.NativeWebRequest; -import org.zalando.nakadi.exceptions.runtime.NoSuchSchemaException; -import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; -import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; -import org.zalando.nakadi.exceptions.runtime.PartitioningException; -import org.zalando.nakadi.exceptions.runtime.CompactionException; -import org.zalando.nakadi.exceptions.runtime.EnrichmentException; -import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; -import org.zalando.nakadi.exceptions.runtime.IllegalClientIdException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.runtime.TimelineException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; +import org.zalando.nakadi.exceptions.runtime.CompactionException; import org.zalando.nakadi.exceptions.runtime.CursorConversionException; import org.zalando.nakadi.exceptions.runtime.CursorsAreEmptyException; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; +import org.zalando.nakadi.exceptions.runtime.EnrichmentException; +import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; +import org.zalando.nakadi.exceptions.runtime.IllegalClientIdException; +import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; import org.zalando.nakadi.exceptions.runtime.LimitReachedException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoStreamingSlotsAvailable; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSchemaException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.PartitioningException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; +import org.zalando.nakadi.exceptions.runtime.TimelineException; import org.zalando.nakadi.exceptions.runtime.TopicCreationException; import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; @@ -40,6 +41,7 @@ import javax.ws.rs.core.Response; +import static javax.ws.rs.core.Response.Status.CONFLICT; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.NOT_IMPLEMENTED; import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; @@ -249,4 +251,11 @@ public ResponseEntity handleNoSuchSubscriptionException(final NoSuchSub LOG.debug(exception.getMessage(), exception); return Responses.create(NOT_FOUND, exception.getMessage(), request); } + + @ExceptionHandler(NoStreamingSlotsAvailable.class) + public ResponseEntity handleNoStreamingSlotsAvailable(final NoStreamingSlotsAvailable exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return Responses.create(CONFLICT, exception.getMessage(), request); + } } diff --git a/src/main/java/org/zalando/nakadi/exceptions/NoStreamingSlotsAvailable.java b/src/main/java/org/zalando/nakadi/exceptions/NoStreamingSlotsAvailable.java deleted file mode 100644 index 9ebe84fdb1..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/NoStreamingSlotsAvailable.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.zalando.nakadi.exceptions; - -import javax.ws.rs.core.Response; - -public class NoStreamingSlotsAvailable extends NakadiException { - public NoStreamingSlotsAvailable(final int totalSlots) { - super("No free slots for streaming available. Total slots: " + totalSlots); - } - - @Override - protected Response.StatusType getStatus() { - return Response.Status.CONFLICT; - } -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStreamingSlotsAvailable.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStreamingSlotsAvailable.java new file mode 100644 index 0000000000..16d71735fe --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStreamingSlotsAvailable.java @@ -0,0 +1,7 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class NoStreamingSlotsAvailable extends NakadiRuntimeBaseException { + public NoStreamingSlotsAvailable(final int totalSlots) { + super("No free slots for streaming available. Total slots: " + totalSlots); + } +} diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java b/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java index e2bbbbb47f..62e8d1de89 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java @@ -8,7 +8,7 @@ import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.NoStreamingSlotsAvailable; +import org.zalando.nakadi.exceptions.runtime.NoStreamingSlotsAvailable; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.SubscriptionPartitionConflictException; From 55d5302cdd84e38d0363d463ea6f9b814064fc18 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 14:38:43 +0200 Subject: [PATCH 075/176] fix test --- .../SubscriptionStreamController.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java b/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java index c6676e87df..126fe9fe0b 100644 --- a/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java @@ -22,8 +22,9 @@ import org.zalando.nakadi.config.NakadiSettings; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; +import org.zalando.nakadi.exceptions.runtime.NoStreamingSlotsAvailable; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.SubscriptionPartitionConflictException; import org.zalando.nakadi.exceptions.runtime.WrongStreamParametersException; import org.zalando.nakadi.repository.db.SubscriptionDbRepository; @@ -38,7 +39,6 @@ import org.zalando.nakadi.service.subscription.SubscriptionValidationService; import org.zalando.nakadi.util.FlowIdUtils; import org.zalando.nakadi.view.UserStreamParameters; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; import org.zalando.problem.spring.web.advice.Responses; @@ -46,12 +46,16 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; -import javax.ws.rs.core.Response; import java.io.IOException; import java.io.OutputStream; import java.util.concurrent.atomic.AtomicBoolean; +import static javax.ws.rs.core.Response.Status.CONFLICT; +import static javax.ws.rs.core.Response.Status.FORBIDDEN; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.zalando.nakadi.metrics.MetricUtils.metricNameForSubscription; +import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; @RestController public class SubscriptionStreamController { @@ -118,21 +122,23 @@ public void onException(final Exception ex) { headersSent = true; try { if (ex instanceof AccessDeniedException) { - writeProblemResponse(response, out, Problem.valueOf(Response.Status.FORBIDDEN, + writeProblemResponse(response, out, Problem.valueOf(FORBIDDEN, ((AccessDeniedException) ex).explain())); } else if (ex instanceof SubscriptionPartitionConflictException) { - writeProblemResponse(response, out, Problem.valueOf(Response.Status.CONFLICT, + writeProblemResponse(response, out, Problem.valueOf(CONFLICT, ex.getMessage())); } else if (ex instanceof WrongStreamParametersException) { - writeProblemResponse(response, out, Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, + writeProblemResponse(response, out, Problem.valueOf(UNPROCESSABLE_ENTITY, ex.getMessage())); } else if (ex instanceof NoSuchSubscriptionException) { - writeProblemResponse(response, out, Problem.valueOf(Response.Status.NOT_FOUND, + writeProblemResponse(response, out, Problem.valueOf(NOT_FOUND, ex.getMessage())); } else if (ex instanceof NakadiException) { writeProblemResponse(response, out, ((NakadiException) ex).asProblem()); + } else if (ex instanceof NoStreamingSlotsAvailable) { + writeProblemResponse(response, out, Problem.valueOf(CONFLICT, ex.getMessage())); } else { - writeProblemResponse(response, out, Problem.valueOf(Response.Status.SERVICE_UNAVAILABLE, + writeProblemResponse(response, out, Problem.valueOf(SERVICE_UNAVAILABLE, "Failed to continue streaming")); } out.flush(); @@ -207,7 +213,7 @@ private StreamingResponseBody stream(final String subscriptionId, try { if (blacklistService.isSubscriptionConsumptionBlocked(subscriptionId, client.getClientId())) { writeProblemResponse(response, outputStream, - Problem.valueOf(Response.Status.FORBIDDEN, "Application or event type is blocked")); + Problem.valueOf(FORBIDDEN, "Application or event type is blocked")); return; } @@ -243,7 +249,7 @@ private void writeProblemResponse(final HttpServletResponse response, public ResponseEntity invalidEventTypeException(final WrongStreamParametersException exception, final NativeWebRequest request) { LOG.debug(exception.getMessage(), exception); - return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, exception.getMessage(), request); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } } From 3648944958278514c5b809ca63089dcf220e50ff Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 15:06:13 +0200 Subject: [PATCH 076/176] Refactor InternalNakadiException --- .../zalando/nakadi/config/NakadiConfig.java | 2 +- .../CursorOperationsController.java | 13 +++++------ .../nakadi/controller/CursorsController.java | 11 +++++----- .../controller/EventPublishingController.java | 12 +++++----- .../controller/EventStreamController.java | 2 +- .../controller/EventTypeController.java | 2 +- .../controller/PartitionsController.java | 14 ++++++------ .../exceptions/InternalNakadiException.java | 22 ------------------- .../runtime/InternalNakadiException.java | 11 ++++++++++ .../repository/EventTypeRepository.java | 2 +- .../db/CachingEventTypeRepository.java | 2 +- .../nakadi/repository/db/EventTypeCache.java | 2 +- .../repository/db/EventTypeDbRepository.java | 2 +- .../service/AuthorizationValidator.java | 2 +- .../nakadi/service/CursorConverter.java | 2 +- .../service/CursorOperationsService.java | 6 ++--- .../nakadi/service/CursorsService.java | 2 +- .../nakadi/service/EventPublisher.java | 2 +- .../nakadi/service/EventTypeService.java | 15 +++++++------ .../service/NakadiCursorComparator.java | 2 +- .../converter/CursorConverterImpl.java | 2 +- .../converter/VersionOneConverter.java | 2 +- .../converter/VersionZeroConverter.java | 2 +- .../service/converter/VersionedConverter.java | 2 +- .../subscription/SubscriptionService.java | 2 +- .../SubscriptionStreamerFactory.java | 2 +- .../SubscriptionValidationService.java | 7 +++--- .../subscription/state/StartingState.java | 5 +++-- .../subscription/state/StreamingState.java | 3 ++- .../zk/SubscriptionClientFactory.java | 2 +- .../service/timeline/TimelineService.java | 4 ++-- .../EventPublishingControllerTest.java | 2 +- .../controller/EventTypeControllerTest.java | 2 +- .../controller/PartitionsControllerTest.java | 2 +- .../db/CachingEventTypeRepositoryTest.java | 2 +- .../nakadi/service/EventTypeServiceTest.java | 2 +- .../service/NakadiCursorComparatorTest.java | 2 +- .../SubscriptionValidationServiceTest.java | 2 +- .../converter/VersionZeroConverterTest.java | 2 +- .../state/StreamingStateTest.java | 2 +- .../service/timeline/TimelineServiceTest.java | 2 +- 41 files changed, 87 insertions(+), 94 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/InternalNakadiException.java create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/InternalNakadiException.java diff --git a/src/main/java/org/zalando/nakadi/config/NakadiConfig.java b/src/main/java/org/zalando/nakadi/config/NakadiConfig.java index 85fa3d489e..f1cf7f4fb6 100644 --- a/src/main/java/org/zalando/nakadi/config/NakadiConfig.java +++ b/src/main/java/org/zalando/nakadi/config/NakadiConfig.java @@ -14,7 +14,7 @@ import org.springframework.scheduling.annotation.EnableScheduling; import org.zalando.nakadi.domain.DefaultStorage; import org.zalando.nakadi.domain.Storage; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.DuplicatedStorageException; import org.zalando.nakadi.repository.db.StorageDbRepository; import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; diff --git a/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java b/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java index 8716756147..1ae88ace5e 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java @@ -15,14 +15,13 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.NakadiCursorLag; import org.zalando.nakadi.domain.ShiftedNakadiCursor; -import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.CursorConversionException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.repository.EventTypeRepository; import org.zalando.nakadi.service.AuthorizationValidator; @@ -168,7 +167,7 @@ private Function toNakadiCursor(final String eventTypeName return cursor -> { try { return cursorConverter.convert(eventTypeName, cursor); - } catch (final NakadiException | InvalidCursorException e) { + } catch (final InternalNakadiException | InvalidCursorException e) { throw new CursorConversionException("problem converting cursors", e); } }; @@ -180,7 +179,7 @@ private Function toShiftedNakadiCursor(final final NakadiCursor nakadiCursor = cursorConverter.convert(eventTypeName, cursor); return new ShiftedNakadiCursor(nakadiCursor.getTimeline(), nakadiCursor.getPartition(), nakadiCursor.getOffset(), cursor.getShift()); - } catch (final NakadiException | InvalidCursorException e) { + } catch (final InternalNakadiException | InvalidCursorException e) { throw new CursorConversionException("problem converting cursors", e); } }; diff --git a/src/main/java/org/zalando/nakadi/controller/CursorsController.java b/src/main/java/org/zalando/nakadi/controller/CursorsController.java index ce00a42b6b..7515b81f11 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorsController.java @@ -15,7 +15,7 @@ import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.domain.ItemsWrapper; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; @@ -47,6 +47,7 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; +import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.springframework.http.ResponseEntity.noContent; @@ -118,9 +119,9 @@ public ResponseEntity commitCursors(@PathVariable("subscriptionId") final Str } catch (final ServiceTemporarilyUnavailableException e) { LOG.error("Failed to commit cursors", e); return create(Problem.valueOf(SERVICE_UNAVAILABLE, e.getMessage()), request); - } catch (final NakadiException e) { + } catch (final InternalNakadiException e) { LOG.error("Failed to commit cursors", e); - return create(e.asProblem(), request); + return create(Problem.valueOf(INTERNAL_SERVER_ERROR, e.getMessage()), request); } } @@ -136,8 +137,8 @@ public ResponseEntity resetCursors( throw new UnableProcessException(e.getMessage()); } catch (final InvalidCursorException e) { return create(Problem.valueOf(UNPROCESSABLE_ENTITY, e.getMessage()), request); - } catch (final NakadiException e) { - return create(e.asProblem(), request); + } catch (final InternalNakadiException e) { + return create(Problem.valueOf(INTERNAL_SERVER_ERROR, e.getMessage()), request); } } diff --git a/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java b/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java index 924b8c1229..f74b47c35d 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java @@ -16,10 +16,10 @@ import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.domain.EventPublishResult; import org.zalando.nakadi.domain.EventPublishingStatus; -import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.EventTypeTimeoutException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.metrics.EventTypeMetricRegistry; import org.zalando.nakadi.metrics.EventTypeMetrics; @@ -35,7 +35,9 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.springframework.http.ResponseEntity.status; import static org.springframework.web.bind.annotation.RequestMethod.POST; import static org.zalando.problem.spring.web.advice.Responses.create; @@ -114,10 +116,10 @@ private ResponseEntity postEventInternal(final String eventTypeName, return create(Problem.valueOf(NOT_FOUND, e.getMessage()), nativeWebRequest); } catch (final EventTypeTimeoutException e) { LOG.debug("Failed to publish batch", e); - return create(Problem.valueOf(Response.Status.SERVICE_UNAVAILABLE, e.getMessage()), nativeWebRequest); - } catch (final NakadiException e) { + return create(Problem.valueOf(SERVICE_UNAVAILABLE, e.getMessage()), nativeWebRequest); + } catch (final InternalNakadiException e) { LOG.debug("Failed to publish batch", e); - return create(e.asProblem(), nativeWebRequest); + return create(Problem.valueOf(INTERNAL_SERVER_ERROR, e.getMessage()), nativeWebRequest); } finally { eventTypeMetrics.updateTiming(startingNanos, System.nanoTime()); } diff --git a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java index d31a4e87ca..6d02a2d33c 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java @@ -25,7 +25,7 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index abd17cb4e5..28aec3821f 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -19,7 +19,7 @@ import org.zalando.nakadi.domain.CleanupPolicy; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; diff --git a/src/main/java/org/zalando/nakadi/controller/PartitionsController.java b/src/main/java/org/zalando/nakadi/controller/PartitionsController.java index 3a44572bf8..0ad3c3c899 100644 --- a/src/main/java/org/zalando/nakadi/controller/PartitionsController.java +++ b/src/main/java/org/zalando/nakadi/controller/PartitionsController.java @@ -18,12 +18,11 @@ import org.zalando.nakadi.domain.PartitionEndStatistics; import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.repository.EventTypeRepository; @@ -46,6 +45,7 @@ import java.util.stream.Collectors; import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.springframework.http.ResponseEntity.ok; import static org.zalando.problem.spring.web.advice.Responses.create; @@ -105,9 +105,9 @@ public ResponseEntity listPartitions(@PathVariable("name") final String event return ok().body(result); } catch (final NoSuchEventTypeException e) { return create(Problem.valueOf(NOT_FOUND, "topic not found"), request); - } catch (final NakadiException e) { + } catch (final InternalNakadiException e) { LOG.error("Could not list partitions. Respond with SERVICE_UNAVAILABLE.", e); - return create(e.asProblem(), request); + return create(Problem.valueOf(SERVICE_UNAVAILABLE, e.getMessage()), request); } } @@ -132,9 +132,9 @@ public ResponseEntity getPartition( } } catch (final NoSuchEventTypeException e) { return create(Problem.valueOf(NOT_FOUND, "topic not found"), request); - } catch (final NakadiException e) { + } catch (final InternalNakadiException e) { LOG.error("Could not get partition. Respond with SERVICE_UNAVAILABLE.", e); - return create(e.asProblem(), request); + return create(Problem.valueOf(SERVICE_UNAVAILABLE, e.getMessage()), request); } catch (final InvalidCursorException e) { return create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, INVALID_CURSOR_MESSAGE), request); diff --git a/src/main/java/org/zalando/nakadi/exceptions/InternalNakadiException.java b/src/main/java/org/zalando/nakadi/exceptions/InternalNakadiException.java deleted file mode 100644 index 90415303ac..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/InternalNakadiException.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.zalando.nakadi.exceptions; - -import javax.ws.rs.core.Response; - -public class InternalNakadiException extends NakadiException { - public InternalNakadiException(final String message) { - super(message); - } - - public InternalNakadiException(final String msg, final Exception cause) { - super(msg, cause); - } - - public InternalNakadiException(final String msg, final String problemMessage, final Exception cause) { - super(msg, problemMessage, cause); - } - - @Override - protected Response.StatusType getStatus() { - return Response.Status.INTERNAL_SERVER_ERROR; - } -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InternalNakadiException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InternalNakadiException.java new file mode 100644 index 0000000000..ccc73816a7 --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InternalNakadiException.java @@ -0,0 +1,11 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class InternalNakadiException extends NakadiRuntimeBaseException { + public InternalNakadiException(final String message) { + super(message); + } + + public InternalNakadiException(final String msg, final Exception cause) { + super(msg, cause); + } +} diff --git a/src/main/java/org/zalando/nakadi/repository/EventTypeRepository.java b/src/main/java/org/zalando/nakadi/repository/EventTypeRepository.java index 8f109f70ee..c1a35d8580 100644 --- a/src/main/java/org/zalando/nakadi/repository/EventTypeRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/EventTypeRepository.java @@ -2,7 +2,7 @@ import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; diff --git a/src/main/java/org/zalando/nakadi/repository/db/CachingEventTypeRepository.java b/src/main/java/org/zalando/nakadi/repository/db/CachingEventTypeRepository.java index 7c362044be..06bd41bfa5 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/CachingEventTypeRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/db/CachingEventTypeRepository.java @@ -8,7 +8,7 @@ import org.zalando.nakadi.annotations.DB; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; import org.zalando.nakadi.repository.EventTypeRepository; diff --git a/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java b/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java index cd4ca37021..8d7b77cc72 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java +++ b/src/main/java/org/zalando/nakadi/repository/db/EventTypeCache.java @@ -16,7 +16,7 @@ import org.slf4j.LoggerFactory; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.EventTypeRepository; import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; diff --git a/src/main/java/org/zalando/nakadi/repository/db/EventTypeDbRepository.java b/src/main/java/org/zalando/nakadi/repository/db/EventTypeDbRepository.java index 99f8e09077..3a0edafdf1 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/EventTypeDbRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/db/EventTypeDbRepository.java @@ -15,7 +15,7 @@ import org.zalando.nakadi.annotations.DB; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; import org.zalando.nakadi.repository.EventTypeRepository; diff --git a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java index 381ce29098..1336f59f62 100644 --- a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java +++ b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java @@ -7,7 +7,7 @@ import org.zalando.nakadi.domain.EventTypeResource; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.ValidatableAuthorization; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.UnableProcessException; diff --git a/src/main/java/org/zalando/nakadi/service/CursorConverter.java b/src/main/java/org/zalando/nakadi/service/CursorConverter.java index c173fb75ed..dc58deef42 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorConverter.java +++ b/src/main/java/org/zalando/nakadi/service/CursorConverter.java @@ -2,7 +2,7 @@ import com.google.common.base.Preconditions; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; diff --git a/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java b/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java index ec6f6074d6..6c144f6280 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java @@ -11,7 +11,7 @@ import org.zalando.nakadi.domain.ShiftedNakadiCursor; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; @@ -107,7 +107,7 @@ public List cursorsLag(final String eventTypeName, final List timelines; try { timelines = timelineService.getAllTimelinesOrdered(eventTypeName); - } catch (final NakadiException e) { + } catch (final InternalNakadiException e) { throw new RuntimeException(e); } return timelines.stream() diff --git a/src/main/java/org/zalando/nakadi/service/CursorsService.java b/src/main/java/org/zalando/nakadi/service/CursorsService.java index 38963b96e5..6b8db62b8a 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorsService.java @@ -8,7 +8,7 @@ import org.zalando.nakadi.domain.EventTypePartition; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Subscription; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; diff --git a/src/main/java/org/zalando/nakadi/service/EventPublisher.java b/src/main/java/org/zalando/nakadi/service/EventPublisher.java index 9cdb3ed239..6a7a87f5ae 100644 --- a/src/main/java/org/zalando/nakadi/service/EventPublisher.java +++ b/src/main/java/org/zalando/nakadi/service/EventPublisher.java @@ -18,7 +18,7 @@ import org.zalando.nakadi.enrichment.Enrichment; import org.zalando.nakadi.exceptions.runtime.CompactionException; import org.zalando.nakadi.exceptions.runtime.EnrichmentException; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.PartitioningException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 2790916fa3..51745e550c 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -25,7 +25,7 @@ import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.enrichment.Enrichment; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; @@ -72,6 +72,7 @@ import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; +import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DELETE_EVENT_TYPE_WITH_SUBSCRIPTIONS; @@ -251,7 +252,7 @@ public void delete(final String eventTypeName) throws EventTypeDeletionException LOG.error("Failed to wait for timeline switch", e); throw new EventTypeUnavailableException("Event type " + eventTypeName + " is currently in maintenance, please repeat request"); - } catch (final NakadiException | ServiceTemporarilyUnavailableException e) { + } catch (final InternalNakadiException | ServiceTemporarilyUnavailableException e) { LOG.error("Error deleting event type " + eventTypeName, e); throw new EventTypeDeletionException("Failed to delete event type " + eventTypeName); } finally { @@ -401,13 +402,13 @@ private void updateRetentionTime(final EventType original, final EventType event } private void updateEventTypeInDB(final EventType eventType, final Long newRetentionTime, - final Long oldRetentionTime) throws NakadiException { - final NakadiException exception = transactionTemplate.execute(action -> { + final Long oldRetentionTime) throws InternalNakadiException { + final InternalNakadiException exception = transactionTemplate.execute(action -> { try { updateTimelinesCleanup(eventType.getName(), newRetentionTime, oldRetentionTime); eventTypeRepository.update(eventType); return null; - } catch (final NakadiException e) { + } catch (final InternalNakadiException e) { return e; } }); @@ -449,7 +450,7 @@ public Result get(final String eventTypeName) { return Result.problem(Problem.valueOf(NOT_FOUND, e.getMessage())); } catch (final InternalNakadiException e) { LOG.error("Problem loading event type " + eventTypeName, e); - return Result.problem(e.asProblem()); + return Result.problem(Problem.valueOf(INTERNAL_SERVER_ERROR, e.getMessage())); } } @@ -463,7 +464,7 @@ private Multimap deleteEventType(final String eventType } catch (TimelineException | NotFoundException e) { LOG.error("Problem deleting timeline for event type " + eventTypeName, e); throw new EventTypeDeletionException("Failed to delete timelines for event type " + eventTypeName); - } catch (NakadiException e) { + } catch (InternalNakadiException e) { LOG.error("Error deleting event type " + eventTypeName, e); throw new EventTypeDeletionException("Failed to delete event type " + eventTypeName); } diff --git a/src/main/java/org/zalando/nakadi/service/NakadiCursorComparator.java b/src/main/java/org/zalando/nakadi/service/NakadiCursorComparator.java index c861bb02f0..8f5d7596f1 100644 --- a/src/main/java/org/zalando/nakadi/service/NakadiCursorComparator.java +++ b/src/main/java/org/zalando/nakadi/service/NakadiCursorComparator.java @@ -4,7 +4,7 @@ import org.springframework.stereotype.Component; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.db.EventTypeCache; diff --git a/src/main/java/org/zalando/nakadi/service/converter/CursorConverterImpl.java b/src/main/java/org/zalando/nakadi/service/converter/CursorConverterImpl.java index daa7732ffd..d3e824d73b 100644 --- a/src/main/java/org/zalando/nakadi/service/converter/CursorConverterImpl.java +++ b/src/main/java/org/zalando/nakadi/service/converter/CursorConverterImpl.java @@ -4,7 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; diff --git a/src/main/java/org/zalando/nakadi/service/converter/VersionOneConverter.java b/src/main/java/org/zalando/nakadi/service/converter/VersionOneConverter.java index 9c6cd4c3ef..df2fa4e126 100644 --- a/src/main/java/org/zalando/nakadi/service/converter/VersionOneConverter.java +++ b/src/main/java/org/zalando/nakadi/service/converter/VersionOneConverter.java @@ -3,7 +3,7 @@ import org.zalando.nakadi.domain.CursorError; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.db.EventTypeCache; diff --git a/src/main/java/org/zalando/nakadi/service/converter/VersionZeroConverter.java b/src/main/java/org/zalando/nakadi/service/converter/VersionZeroConverter.java index 80acfe0a03..453eb545c9 100644 --- a/src/main/java/org/zalando/nakadi/service/converter/VersionZeroConverter.java +++ b/src/main/java/org/zalando/nakadi/service/converter/VersionZeroConverter.java @@ -5,7 +5,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; diff --git a/src/main/java/org/zalando/nakadi/service/converter/VersionedConverter.java b/src/main/java/org/zalando/nakadi/service/converter/VersionedConverter.java index 7a6b596dc6..c64d695d7b 100644 --- a/src/main/java/org/zalando/nakadi/service/converter/VersionedConverter.java +++ b/src/main/java/org/zalando/nakadi/service/converter/VersionedConverter.java @@ -1,7 +1,7 @@ package org.zalando.nakadi.service.converter; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java index 44e5f0fdc3..55d82eb0df 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java @@ -22,7 +22,7 @@ import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.domain.SubscriptionEventTypeStats; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java index 2102537748..343a3e9bc2 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionStreamerFactory.java @@ -7,7 +7,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.zalando.nakadi.domain.Subscription; -import org.zalando.nakadi.exceptions.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.db.EventTypeCache; import org.zalando.nakadi.service.AuthorizationValidator; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java index d23d91a5ed..aeb757e484 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java @@ -9,10 +9,9 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; -import org.zalando.nakadi.exceptions.InternalNakadiException; -import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; @@ -158,7 +157,7 @@ private void validateInitialCursors(final SubscriptionBase subscription, } } catch (final InvalidCursorException ex) { throw new WrongInitialCursorsException(ex.getMessage(), ex); - } catch (final NakadiException | ServiceTemporarilyUnavailableException ex) { + } catch (final InternalNakadiException | ServiceTemporarilyUnavailableException ex) { throw new RepositoryProblemException("Topic repository problem occurred when validating cursors", ex); } } diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java b/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java index 62e8d1de89..89598d59f2 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java @@ -8,6 +8,7 @@ import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.NoStreamingSlotsAvailable; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; @@ -158,7 +159,7 @@ public List calculate( try { // get oldest active timeline return timelineService.getActiveTimelinesOrdered(et).get(0); - } catch (final NakadiException e) { + } catch (final InternalNakadiException e) { throw new NakadiRuntimeException(e); } }) @@ -197,7 +198,7 @@ public List calculate( // get newest active timeline final List activeTimelines = timelineService.getActiveTimelinesOrdered(et); return activeTimelines.get(activeTimelines.size() - 1); - } catch (final NakadiException e) { + } catch (final InternalNakadiException e) { throw new NakadiRuntimeException(e); } }) diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java index d38c5eb387..513a2c5693 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java @@ -9,6 +9,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; @@ -590,7 +591,7 @@ private Map getBeforeFirstCursors(final Set Date: Mon, 20 Aug 2018 15:12:04 +0200 Subject: [PATCH 077/176] Use kakfa 1.1.1 in docker-compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index d5bfc3d793..509198f665 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -45,7 +45,7 @@ services: - "2181:2181" kafka: - image: wurstmeister/kafka:1.1.0 + image: wurstmeister/kafka:2.11-1.1.1 network_mode: "host" ports: - "9092:9092" From e9b621c27b7e709d672578325d4b6597897d3e48 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Mon, 20 Aug 2018 15:29:25 +0200 Subject: [PATCH 078/176] ARUHA-1885 Hide unnecessary errors and stack traces while flushing subscription data to consumers --- .../nakadi/service/subscription/state/StreamingState.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java index 0f0e8fc64d..8a02f203e5 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java @@ -337,7 +337,7 @@ private void flushData(final EventTypePartition pk, final List da batchesSent++; } catch (final IOException e) { - getLog().error("Failed to write data to output.", e); + getLog().warn("Failed to write data to output: {}", e.getMessage()); shutdownGracefully("Failed to write data to output"); } } From f1f97903b796128c064b528916e1b1803ce8c971 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 15:41:03 +0200 Subject: [PATCH 079/176] Do not throw NakadiException --- .../controller/EventTypeController.java | 10 +--------- .../controller/SubscriptionController.java | 13 +++--------- .../subscription/state/StartingState.java | 20 ++++--------------- 3 files changed, 8 insertions(+), 35 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index 28aec3821f..594bd185c1 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -19,8 +19,6 @@ import org.zalando.nakadi.domain.CleanupPolicy; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; -import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; @@ -29,6 +27,7 @@ import org.zalando.nakadi.exceptions.runtime.EventTypeOptionsValidationException; import org.zalando.nakadi.exceptions.runtime.EventTypeUnavailableException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; @@ -208,13 +207,6 @@ public ResponseEntity eventTypeUnavailable(final EventTypeUnavailableEx return Responses.create(Response.Status.SERVICE_UNAVAILABLE, exception.getMessage(), request); } - @ExceptionHandler(NakadiException.class) - public ResponseEntity nakadiException(final NakadiException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); - return Responses.create(exception.asProblem(), request); - } - @ExceptionHandler(NoSuchPartitionStrategyException.class) public ResponseEntity noSuchPartitionStrategyException(final NoSuchPartitionStrategyException exception, final NativeWebRequest request) { diff --git a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java index 6eaf0bb5df..c23d7a5bad 100644 --- a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java @@ -15,10 +15,10 @@ import org.zalando.nakadi.domain.ItemsWrapper; import org.zalando.nakadi.domain.SubscriptionEventTypeStats; import org.zalando.nakadi.exceptions.runtime.ErrorGettingCursorTimeLagException; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TimeLagStatsTimeoutException; import org.zalando.nakadi.service.FeatureToggleService; @@ -84,19 +84,12 @@ public ResponseEntity deleteSubscription(@PathVariable("id") final String sub public ItemsWrapper getSubscriptionStats( @PathVariable("id") final String subscriptionId, @RequestParam(value = "show_time_lag", required = false, defaultValue = "false") final boolean showTimeLag) - throws NakadiException, InconsistentStateException, - NoSuchEventTypeException, ServiceTemporarilyUnavailableException { + throws InconsistentStateException, + NoSuchEventTypeException, NoSuchSubscriptionException, ServiceTemporarilyUnavailableException { final StatsMode statsMode = showTimeLag ? StatsMode.TIMELAG : StatsMode.NORMAL; return subscriptionService.getSubscriptionStat(subscriptionId, statsMode); } - @ExceptionHandler(NakadiException.class) - public ResponseEntity handleNakadiException(final NakadiException ex, - final NativeWebRequest request) { - LOG.debug(ex.getMessage(), ex); - return Responses.create(ex.asProblem(), request); - } - @ExceptionHandler(FeatureNotAvailableException.class) public ResponseEntity handleFeatureTurnedOff(final FeatureNotAvailableException ex, final NativeWebRequest request) { diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java b/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java index 89598d59f2..dbb1d22d1f 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java @@ -6,11 +6,11 @@ import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; +import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.NoStreamingSlotsAvailable; -import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.SubscriptionPartitionConflictException; import org.zalando.nakadi.service.CursorConverter; @@ -20,7 +20,6 @@ import org.zalando.nakadi.service.timeline.TimelineService; import org.zalando.nakadi.view.SubscriptionCursorWithoutToken; -import javax.ws.rs.core.Response; import java.io.IOException; import java.util.Collection; import java.util.EnumMap; @@ -38,13 +37,7 @@ public void onEnter() { try { getContext().checkAccessAuthorized(); } catch (final AccessDeniedException e) { - switchState(new CleanupState( - new NakadiException(e.explain()) { - @Override - protected Response.StatusType getStatus() { - return Response.Status.FORBIDDEN; - } - })); + switchState(new CleanupState(e)); return; } getZk().runLocked(this::initializeStream); @@ -95,12 +88,7 @@ private void initializeStream() { if (getZk().isCursorResetInProgress()) { switchState(new CleanupState( - new NakadiException("Resetting subscription cursors request is still in progress") { - @Override - protected Response.StatusType getStatus() { - return Response.Status.CONFLICT; - } - })); + new ConflictException("Resetting subscription cursors request is still in progress"))); return; } From 6d2d014569326faeb5afa2266c84eb166acd9b48 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 16:25:46 +0200 Subject: [PATCH 080/176] Remove NakadiException --- .../db/EventTypeDbRepositoryTest.java | 11 +++-- .../nakadi/controller/CursorsController.java | 9 ++-- .../controller/EventStreamController.java | 9 ++-- .../nakadi/controller/ExceptionHandling.java | 13 +++--- .../SubscriptionStreamController.java | 7 ++-- .../nakadi/exceptions/NakadiException.java | 41 ------------------- .../nakadi/repository/EventConsumer.java | 3 +- .../MultiTimelineEventConsumer.java | 13 +++--- .../nakadi/repository/TopicRepository.java | 5 +-- .../nakadi/service/CursorsService.java | 8 ++-- .../nakadi/service/EventStreamFactory.java | 3 +- .../nakadi/service/EventTypeService.java | 13 +++--- .../SubscriptionTimeLagService.java | 5 +-- .../subscription/state/StreamingState.java | 7 ++-- .../service/timeline/TimelineService.java | 9 ++-- .../controller/EventStreamControllerTest.java | 23 +++++------ .../partitioning/PartitionResolverTest.java | 9 ++-- .../kafka/NakadiKafkaConsumerTest.java | 9 ++-- .../nakadi/service/EventStreamTest.java | 33 +++++++-------- .../SubscriptionTimeLagServiceTest.java | 14 +++---- 20 files changed, 94 insertions(+), 150 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/NakadiException.java diff --git a/src/acceptance-test/java/org/zalando/nakadi/repository/db/EventTypeDbRepositoryTest.java b/src/acceptance-test/java/org/zalando/nakadi/repository/db/EventTypeDbRepositoryTest.java index 76204879e6..e52b989843 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/repository/db/EventTypeDbRepositoryTest.java +++ b/src/acceptance-test/java/org/zalando/nakadi/repository/db/EventTypeDbRepositoryTest.java @@ -9,9 +9,8 @@ import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeSchema; import org.zalando.nakadi.domain.Version; -import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.repository.EventTypeRepository; import org.zalando.nakadi.utils.TestUtils; @@ -100,12 +99,12 @@ public void whenEventExistsFindByNameReturnsSomething() throws Exception { } @Test(expected = NoSuchEventTypeException.class) - public void whenEventDoesntExistsFindByNameReturnsNothing() throws NakadiException { + public void whenEventDoesntExistsFindByNameReturnsNothing() { repository.findByName("inexisting-name"); } @Test - public void whenUpdateExistingEventTypeItUpdates() throws NakadiException, IOException { + public void whenUpdateExistingEventTypeItUpdates() throws IOException { final EventType eventType = buildDefaultEventType(); repository.saveEventType(eventType); @@ -135,7 +134,7 @@ public void whenUpdateExistingEventTypeItUpdates() throws NakadiException, IOExc } @Test - public void whenUpdateDifferentSchemaVersionThenInsertIt() throws NakadiException, IOException { + public void whenUpdateDifferentSchemaVersionThenInsertIt() throws IOException { final EventType eventType = buildDefaultEventType(); repository.saveEventType(eventType); @@ -151,7 +150,7 @@ public void whenUpdateDifferentSchemaVersionThenInsertIt() throws NakadiExceptio } @Test - public void whenListExistingEventTypesAreListed() throws NakadiException { + public void whenListExistingEventTypesAreListed() { final EventType eventType1 = buildDefaultEventType(); final EventType eventType2 = buildDefaultEventType(); diff --git a/src/main/java/org/zalando/nakadi/controller/CursorsController.java b/src/main/java/org/zalando/nakadi/controller/CursorsController.java index 7515b81f11..c5df428f83 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorsController.java @@ -15,14 +15,13 @@ import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.domain.ItemsWrapper; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; -import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.CursorsAreEmptyException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.RequestInProgressException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; @@ -84,7 +83,7 @@ public ItemsWrapper getCursors(@PathVariable("subscriptionId .map(cursor -> cursor.withToken(cursorTokenService.generateToken())) .collect(Collectors.toList()); return new ItemsWrapper<>(cursors); - } catch (final NakadiException e) { + } catch (final InternalNakadiException e) { throw new NakadiRuntimeException(e); } } diff --git a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java index 6d02a2d33c..d6a441d35a 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java @@ -25,13 +25,12 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; +import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; import org.zalando.nakadi.exceptions.runtime.NoConnectionSlotsException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.UnparseableCursorException; import org.zalando.nakadi.metrics.MetricUtils; @@ -276,9 +275,9 @@ public StreamingResponseBody streamEvents( writeProblemResponse(response, outputStream, SERVICE_UNAVAILABLE, e.getMessage()); } catch (final InvalidLimitException e) { writeProblemResponse(response, outputStream, UNPROCESSABLE_ENTITY, e.getMessage()); - } catch (final NakadiException e) { + } catch (final InternalNakadiException e) { LOG.error("Error while trying to stream events.", e); - writeProblemResponse(response, outputStream, e.asProblem()); + writeProblemResponse(response, outputStream, INTERNAL_SERVER_ERROR, e.getMessage()); } catch (final InvalidCursorException e) { writeProblemResponse(response, outputStream, PRECONDITION_FAILED, e.getMessage()); } catch (final AccessDeniedException e) { diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 84d13876f0..1b170f2e51 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -10,7 +10,6 @@ import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.NativeWebRequest; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.CompactionException; @@ -20,6 +19,7 @@ import org.zalando.nakadi.exceptions.runtime.EnrichmentException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.IllegalClientIdException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; import org.zalando.nakadi.exceptions.runtime.LimitReachedException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; @@ -42,6 +42,7 @@ import javax.ws.rs.core.Response; import static javax.ws.rs.core.Response.Status.CONFLICT; +import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.NOT_IMPLEMENTED; import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; @@ -117,9 +118,8 @@ public ResponseEntity handleCursorsUnavailableException(final RuntimeEx public ResponseEntity handleExceptionWrapper(final NakadiRuntimeException exception, final NativeWebRequest request) throws Exception { final Throwable cause = exception.getCause(); - if (cause instanceof NakadiException) { - final NakadiException ne = (NakadiException) cause; - return Responses.create(ne.asProblem(), request); + if (cause instanceof InternalNakadiException) { + return Responses.create(INTERNAL_SERVER_ERROR, exception.getMessage(), request); } throw exception.getException(); } @@ -143,9 +143,8 @@ public ResponseEntity handleTimelineException(final TimelineException e final NativeWebRequest request) { LOG.error(exception.getMessage(), exception); final Throwable cause = exception.getCause(); - if (cause instanceof NakadiException) { - final NakadiException ne = (NakadiException) cause; - return Responses.create(ne.asProblem(), request); + if (cause instanceof InternalNakadiException) { + return Responses.create(Problem.valueOf(INTERNAL_SERVER_ERROR, exception.getMessage()), request); } return Responses.create(Response.Status.SERVICE_UNAVAILABLE, exception.getMessage(), request); } diff --git a/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java b/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java index 126fe9fe0b..5d9b261677 100644 --- a/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java @@ -21,8 +21,8 @@ import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import org.zalando.nakadi.config.NakadiSettings; import org.zalando.nakadi.domain.Subscription; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.NoStreamingSlotsAvailable; import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.SubscriptionPartitionConflictException; @@ -52,6 +52,7 @@ import static javax.ws.rs.core.Response.Status.CONFLICT; import static javax.ws.rs.core.Response.Status.FORBIDDEN; +import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.zalando.nakadi.metrics.MetricUtils.metricNameForSubscription; @@ -133,8 +134,8 @@ public void onException(final Exception ex) { } else if (ex instanceof NoSuchSubscriptionException) { writeProblemResponse(response, out, Problem.valueOf(NOT_FOUND, ex.getMessage())); - } else if (ex instanceof NakadiException) { - writeProblemResponse(response, out, ((NakadiException) ex).asProblem()); + } else if (ex instanceof InternalNakadiException) { + writeProblemResponse(response, out, Problem.valueOf(INTERNAL_SERVER_ERROR, ex.getMessage())); } else if (ex instanceof NoStreamingSlotsAvailable) { writeProblemResponse(response, out, Problem.valueOf(CONFLICT, ex.getMessage())); } else { diff --git a/src/main/java/org/zalando/nakadi/exceptions/NakadiException.java b/src/main/java/org/zalando/nakadi/exceptions/NakadiException.java deleted file mode 100644 index 00a83c2ed9..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/NakadiException.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.zalando.nakadi.exceptions; - - -import org.apache.commons.lang3.StringUtils; -import org.zalando.problem.Problem; - -import javax.ws.rs.core.Response; - -public abstract class NakadiException extends Exception { - - private String problemMessage; - - public NakadiException(final String message) { - super(message); - } - - public NakadiException(final String msg, final Exception cause) { - super(msg, cause); - } - - public NakadiException(final String msg, final String problemMessage, final Exception cause) { - this(msg, cause); - setProblemMessage(problemMessage); - } - - public String getProblemMessage() { - return problemMessage; - } - - public void setProblemMessage(final String problemMessage) { - this.problemMessage = problemMessage; - } - - public Problem asProblem() { - final String detail = StringUtils.isNotBlank(problemMessage) ? problemMessage : getMessage(); - return Problem.valueOf(getStatus(), detail); - } - - protected abstract Response.StatusType getStatus(); - -} diff --git a/src/main/java/org/zalando/nakadi/repository/EventConsumer.java b/src/main/java/org/zalando/nakadi/repository/EventConsumer.java index 4c1bda3569..119fbcc027 100644 --- a/src/main/java/org/zalando/nakadi/repository/EventConsumer.java +++ b/src/main/java/org/zalando/nakadi/repository/EventConsumer.java @@ -5,7 +5,6 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.TopicPartition; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; import java.io.Closeable; import java.util.Collection; @@ -23,6 +22,6 @@ interface LowLevelConsumer extends EventConsumer { interface ReassignableEventConsumer extends EventConsumer { Set getAssignment(); - void reassign(Collection newValues) throws NakadiException, InvalidCursorException; + void reassign(Collection newValues) throws InvalidCursorException; } } diff --git a/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java b/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java index ce96b93b7e..80636b7172 100644 --- a/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java +++ b/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java @@ -8,9 +8,8 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.domain.TopicPartition; -import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.service.timeline.TimelineService; import org.zalando.nakadi.service.timeline.TimelineSync; @@ -85,7 +84,7 @@ public List readEvents() { if (timelinesChanged.compareAndSet(true, false)) { try { onTimelinesChanged(); - } catch (final NakadiException | InvalidCursorException ex) { + } catch (final InvalidCursorException ex) { throw new NakadiRuntimeException(ex); } } @@ -177,7 +176,7 @@ private NakadiCursor getBeforeFirstCursor( " and partition " + partition + ", but it wasn't found")).getBeforeFirst(); } - private void electTopicRepositories() throws NakadiException, InvalidCursorException { + private void electTopicRepositories() throws InvalidCursorException { final Map> newAssignment = new HashMap<>(); borderOffsets.clear(); // Purpose of this collection is to hold tr that definitely changed their positions and should be recreated. @@ -244,7 +243,7 @@ private void stopAndRemoveConsumer(final TopicRepository toRemove) { } - private void onTimelinesChanged() throws NakadiException, InvalidCursorException { + private void onTimelinesChanged() throws InvalidCursorException { final Set eventTypes = latestOffsets.values().stream() .map(NakadiCursor::getEventType) .collect(Collectors.toSet()); @@ -265,7 +264,7 @@ private void onTimelinesChanged() throws NakadiException, InvalidCursorException } @Override - public void reassign(final Collection newValues) throws NakadiException, InvalidCursorException { + public void reassign(final Collection newValues) throws InvalidCursorException { final Map newCursorMap = newValues.stream() .collect(Collectors.toMap(NakadiCursor::getEventTypePartition, Function.identity())); @@ -308,7 +307,7 @@ void onTimelineChange(final String eventType) { public void close() throws IOException { try { reassign(Collections.emptySet()); - } catch (final NakadiException | InvalidCursorException e) { + } catch (final InvalidCursorException e) { throw new IOException(e); } } diff --git a/src/main/java/org/zalando/nakadi/repository/TopicRepository.java b/src/main/java/org/zalando/nakadi/repository/TopicRepository.java index 8c3322d8c0..02033448ee 100644 --- a/src/main/java/org/zalando/nakadi/repository/TopicRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/TopicRepository.java @@ -5,9 +5,8 @@ import org.zalando.nakadi.domain.PartitionEndStatistics; import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.EventPublishingException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TopicConfigException; import org.zalando.nakadi.exceptions.runtime.TopicCreationException; @@ -69,7 +68,7 @@ List loadTopicEndStatistics(Collection topics) List listPartitionNames(String topicId); EventConsumer.LowLevelConsumer createEventConsumer(String clientId, List positions) - throws NakadiException, InvalidCursorException; + throws InvalidCursorException; void validateReadCursors(List cursors) throws InvalidCursorException, ServiceTemporarilyUnavailableException; diff --git a/src/main/java/org/zalando/nakadi/service/CursorsService.java b/src/main/java/org/zalando/nakadi/service/CursorsService.java index 6b8db62b8a..05ae0c0172 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorsService.java @@ -8,12 +8,11 @@ import org.zalando.nakadi.domain.EventTypePartition; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Subscription; +import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; -import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.OperationTimeoutException; @@ -128,7 +127,8 @@ private void validateStreamId(final List cursors, final String str } public List getSubscriptionCursors(final String subscriptionId) - throws NakadiException, ServiceTemporarilyUnavailableException { + throws InternalNakadiException, NoSuchEventTypeException, + NoSuchSubscriptionException, ServiceTemporarilyUnavailableException { final Subscription subscription = subscriptionRepository.getSubscription(subscriptionId); final ZkSubscriptionClient zkSubscriptionClient = zkSubscriptionFactory.createClient( subscription, LogPathBuilder.build(subscriptionId, "get_cursors")); diff --git a/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java b/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java index 272a2bede0..a83bfbad2c 100644 --- a/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java +++ b/src/main/java/org/zalando/nakadi/service/EventStreamFactory.java @@ -5,7 +5,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.repository.EventConsumer; import java.io.OutputStream; @@ -38,7 +37,7 @@ public EventStreamFactory( public EventStream createEventStream(final OutputStream outputStream, final EventConsumer eventConsumer, final EventStreamConfig config, final Meter bytesFlushedMeter) - throws NakadiException, InvalidCursorException { + throws InvalidCursorException { return new EventStream( eventConsumer, outputStream, diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 51745e550c..84b9dccbfc 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -25,12 +25,7 @@ import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.enrichment.Enrichment; -import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; -import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; @@ -40,8 +35,12 @@ import org.zalando.nakadi.exceptions.runtime.EventTypeUnavailableException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TimelineException; @@ -358,7 +357,7 @@ public void update(final String eventTypeName, LOG.error("Failed to wait for timeline switch", e); throw new ServiceTemporarilyUnavailableException( "Event type is currently in maintenance, please repeat request", e); - } catch (final NakadiException e) { + } catch (final InternalNakadiException e) { LOG.error("Unable to update event type", e); throw new NakadiRuntimeException(e); } finally { @@ -378,7 +377,7 @@ public void update(final String eventTypeName, .put("compatibility_mode", eventTypeBase.getCompatibilityMode())); } - private void updateRetentionTime(final EventType original, final EventType eventType) throws NakadiException { + private void updateRetentionTime(final EventType original, final EventType eventType) { final Long newRetentionTime = eventType.getOptions().getRetentionTime(); final Long oldRetentionTime = original.getOptions().getRetentionTime(); if (oldRetentionTime == null) { diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java index fb5c68b42a..e81e82001b 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionTimeLagService.java @@ -9,9 +9,8 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.PartitionEndStatistics; import org.zalando.nakadi.exceptions.runtime.ErrorGettingCursorTimeLagException; -import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.LimitReachedException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.TimeLagStatsTimeoutException; @@ -172,7 +171,7 @@ private Duration getNextEventTimeLag(final NakadiCursor cursor) throws ErrorGett } else { return Duration.ofMillis(new Date().getTime() - nextEvent.getTimestamp()); } - } catch (final NakadiException | IOException e) { + } catch (final IOException e) { throw new InconsistentStateException("Unexpected error happened when getting consumer time lag", e); } catch (final InvalidCursorException e) { throw new ErrorGettingCursorTimeLagException(cursor, e); diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java index 513a2c5693..696115d7b7 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java @@ -9,10 +9,9 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; +import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.metrics.MetricUtils; import org.zalando.nakadi.metrics.StreamKpiData; @@ -554,7 +553,7 @@ private void reconfigureKafkaConsumer(final boolean forceSeek) { // removing all the current assignments for real consumer. try { eventConsumer.reassign(Collections.emptyList()); - } catch (final NakadiException | InvalidCursorException ex) { + } catch (final InvalidCursorException ex) { throw new NakadiRuntimeException(ex); } } @@ -578,7 +577,7 @@ private void reconfigureKafkaConsumer(final boolean forceSeek) { .collect(Collectors.toList()); eventConsumer.reassign(cursors); - } catch (NakadiException | InvalidCursorException ex) { + } catch (InvalidCursorException ex) { throw new NakadiRuntimeException(ex); } } diff --git a/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java b/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java index d46f761e79..d9253084be 100644 --- a/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java +++ b/src/main/java/org/zalando/nakadi/service/timeline/TimelineService.java @@ -20,15 +20,14 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; -import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; import org.zalando.nakadi.exceptions.runtime.DuplicatedTimelineException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; @@ -251,7 +250,7 @@ public TopicRepository getTopicRepository(final Timeline timeline) } public EventConsumer createEventConsumer(@Nullable final String clientId, final List positions) - throws NakadiException, InvalidCursorException { + throws InvalidCursorException { final MultiTimelineEventConsumer result = new MultiTimelineEventConsumer( clientId, this, timelineSync, new NakadiCursorComparator(eventTypeCache)); result.reassign(positions); diff --git a/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java index db50090942..7166c4f9ef 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java @@ -20,10 +20,9 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; +import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; import org.zalando.nakadi.repository.EventConsumer; @@ -121,7 +120,7 @@ public class EventStreamControllerTest { private AuthorizationService authorizationService; @Before - public void setup() throws NakadiException, UnknownHostException, InvalidCursorException { + public void setup() throws UnknownHostException, InvalidCursorException { EVENT_TYPE.setName(TEST_EVENT_TYPE_NAME); timeline = buildTimelineWithTopic(TEST_TOPIC); @@ -229,7 +228,7 @@ public void whenNoParamsThenDefaultsAreUsed() throws Exception { } @Test - public void whenTopicNotExistsThenTopicNotFound() throws IOException, NakadiException { + public void whenTopicNotExistsThenTopicNotFound() throws IOException { when(eventTypeRepository.findByName(TEST_EVENT_TYPE_NAME)).thenThrow(NoSuchEventTypeException.class); final StreamingResponseBody responseBody = createStreamingResponseBody(); @@ -239,7 +238,7 @@ public void whenTopicNotExistsThenTopicNotFound() throws IOException, NakadiExce } @Test - public void whenStreamLimitLowerThanBatchLimitThenUnprocessableEntity() throws NakadiException, IOException { + public void whenStreamLimitLowerThanBatchLimitThenUnprocessableEntity() throws IOException { when(eventTypeRepository.findByName(TEST_EVENT_TYPE_NAME)).thenReturn(EVENT_TYPE); final StreamingResponseBody responseBody = createStreamingResponseBody(20, 10, 0, 0, 0, null); @@ -250,7 +249,7 @@ public void whenStreamLimitLowerThanBatchLimitThenUnprocessableEntity() throws N } @Test - public void whenStreamTimeoutLowerThanBatchTimeoutThenUnprocessableEntity() throws NakadiException, IOException { + public void whenStreamTimeoutLowerThanBatchTimeoutThenUnprocessableEntity() throws IOException { when(eventTypeRepository.findByName(TEST_EVENT_TYPE_NAME)).thenReturn(EVENT_TYPE); final StreamingResponseBody responseBody = createStreamingResponseBody(0, 0, 20, 10, 0, null); @@ -261,7 +260,7 @@ public void whenStreamTimeoutLowerThanBatchTimeoutThenUnprocessableEntity() thro } @Test - public void whenBatchLimitLowerThan1ThenUnprocessableEntity() throws NakadiException, IOException { + public void whenBatchLimitLowerThan1ThenUnprocessableEntity() throws IOException { when(eventTypeRepository.findByName(TEST_EVENT_TYPE_NAME)).thenReturn(EVENT_TYPE); final StreamingResponseBody responseBody = createStreamingResponseBody(0, 0, 0, 0, 0, null); @@ -271,7 +270,7 @@ public void whenBatchLimitLowerThan1ThenUnprocessableEntity() throws NakadiExcep } @Test - public void whenWrongCursorsFormatThenBadRequest() throws NakadiException, IOException { + public void whenWrongCursorsFormatThenBadRequest() throws IOException { when(eventTypeRepository.findByName(TEST_EVENT_TYPE_NAME)).thenReturn(EVENT_TYPE); final StreamingResponseBody responseBody = createStreamingResponseBody(0, 0, 0, 0, 0, @@ -297,7 +296,7 @@ public void whenInvalidCursorsThenPreconditionFailed() throws Exception { } @Test - public void whenNoCursorsThenLatestOffsetsAreUsed() throws NakadiException, IOException, InvalidCursorException { + public void whenNoCursorsThenLatestOffsetsAreUsed() throws IOException, InvalidCursorException { when(eventTypeRepository.findByName(TEST_EVENT_TYPE_NAME)).thenReturn(EVENT_TYPE); final List tps2 = ImmutableList.of( new KafkaPartitionStatistics(timeline, 0, 0, 87), @@ -370,7 +369,7 @@ public void whenNormalCaseThenParametersArePassedToConfigAndStreamStarted() thro } @Test - public void whenNakadiExceptionIsThrownThenServiceUnavailable() throws NakadiException, IOException { + public void whenNakadiExceptionIsThrownThenServiceUnavailable() throws IOException { when(eventTypeRepository.findByName(TEST_EVENT_TYPE_NAME)) .thenThrow(ServiceTemporarilyUnavailableException.class); @@ -381,7 +380,7 @@ public void whenNakadiExceptionIsThrownThenServiceUnavailable() throws NakadiExc } @Test - public void whenExceptionIsThrownThenInternalServerError() throws NakadiException, IOException { + public void whenExceptionIsThrownThenInternalServerError() throws IOException { when(eventTypeRepository.findByName(TEST_EVENT_TYPE_NAME)).thenThrow(NullPointerException.class); final StreamingResponseBody responseBody = createStreamingResponseBody(); @@ -505,7 +504,7 @@ private ArgumentCaptor getStatusCaptor() { return statusCaptor; } - private void prepareScopeRead() throws NakadiException, InvalidCursorException { + private void prepareScopeRead() throws InvalidCursorException { final EventConsumer.LowLevelConsumer eventConsumerMock = mock(EventConsumer.LowLevelConsumer.class); when(eventTypeRepository.findByName(TEST_EVENT_TYPE_NAME)).thenReturn(EVENT_TYPE); when(topicRepositoryMock.createEventConsumer( diff --git a/src/test/java/org/zalando/nakadi/partitioning/PartitionResolverTest.java b/src/test/java/org/zalando/nakadi/partitioning/PartitionResolverTest.java index e7c0032e05..ded230526f 100644 --- a/src/test/java/org/zalando/nakadi/partitioning/PartitionResolverTest.java +++ b/src/test/java/org/zalando/nakadi/partitioning/PartitionResolverTest.java @@ -7,10 +7,9 @@ import org.mockito.Mockito; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NakadiException; +import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; import org.zalando.nakadi.exceptions.runtime.PartitioningException; -import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; import org.zalando.nakadi.repository.TopicRepository; import org.zalando.nakadi.service.timeline.TimelineService; @@ -32,7 +31,7 @@ public class PartitionResolverTest { private TimelineService timelineService; @Before - public void before() throws NakadiException { + public void before() { final TopicRepository topicRepository = Mockito.mock(TopicRepository.class); when(topicRepository.listPartitionNames(any(String.class))).thenReturn(ImmutableList.of("0")); timelineService = Mockito.mock(TimelineService.class); @@ -42,7 +41,7 @@ public void before() throws NakadiException { } @Test - public void whenResolvePartitionWithKnownStrategyThenOk() throws NakadiException { + public void whenResolvePartitionWithKnownStrategyThenOk() { final EventType eventType = new EventType(); eventType.setPartitionStrategy(RANDOM_STRATEGY); @@ -57,7 +56,7 @@ public void whenResolvePartitionWithKnownStrategyThenOk() throws NakadiException } @Test(expected = PartitioningException.class) - public void whenResolvePartitionWithUnknownStrategyThenPartitioningException() throws NakadiException { + public void whenResolvePartitionWithUnknownStrategyThenPartitioningException() { final EventType eventType = new EventType(); eventType.setPartitionStrategy("blah_strategy"); diff --git a/src/test/java/org/zalando/nakadi/repository/kafka/NakadiKafkaConsumerTest.java b/src/test/java/org/zalando/nakadi/repository/kafka/NakadiKafkaConsumerTest.java index 4e87c05de2..c72ee907d6 100644 --- a/src/test/java/org/zalando/nakadi/repository/kafka/NakadiKafkaConsumerTest.java +++ b/src/test/java/org/zalando/nakadi/repository/kafka/NakadiKafkaConsumerTest.java @@ -152,13 +152,13 @@ public void whenReadEventsThenGetRightEvents() { @Test @SuppressWarnings("unchecked") - public void whenReadEventsThenNakadiException() { + public void whenReadEventsThenNakadiRuntimeBaseException() { // ARRANGE // final ImmutableList exceptions = ImmutableList.of(new NoOffsetForPartitionException( new TopicPartition("", 0)), new KafkaException()); - int numberOfNakadiExceptions = 0; + int numberOfNakadiRuntimeBaseExceptions = 0; for (final Exception exception : exceptions) { final KafkaConsumer kafkaConsumerMock = mock(KafkaConsumer.class); when(kafkaConsumerMock.poll(POLL_TIMEOUT)).thenThrow(exception); @@ -173,11 +173,12 @@ public void whenReadEventsThenNakadiException() { // ASSERT // fail("An Exception was expected to be be thrown"); } catch (final Exception e) { - numberOfNakadiExceptions++; + numberOfNakadiRuntimeBaseExceptions++; } } - assertThat("We should get a NakadiException for every call", numberOfNakadiExceptions, + assertThat("We should get a NakadiRuntimeBaseException for every call", + numberOfNakadiRuntimeBaseExceptions, equalTo(exceptions.size())); } diff --git a/src/test/java/org/zalando/nakadi/service/EventStreamTest.java b/src/test/java/org/zalando/nakadi/service/EventStreamTest.java index d269c5fe3e..5fa6f654c3 100644 --- a/src/test/java/org/zalando/nakadi/service/EventStreamTest.java +++ b/src/test/java/org/zalando/nakadi/service/EventStreamTest.java @@ -13,7 +13,6 @@ import org.zalando.nakadi.domain.ConsumedEvent; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.repository.db.EventTypeCache; import org.zalando.nakadi.repository.kafka.KafkaCursor; @@ -82,7 +81,7 @@ public static void setupMocks() { } @Test(timeout = 15000) - public void whenIOExceptionThenStreamIsClosed() throws NakadiException, InterruptedException, IOException { + public void whenIOExceptionThenStreamIsClosed() throws InterruptedException, IOException { final EventStreamConfig config = EventStreamConfig .builder() .withCursors(ImmutableList.of(NakadiCursor.of(TIMELINE, "0", "0"))) @@ -111,7 +110,7 @@ public void whenIOExceptionThenStreamIsClosed() throws NakadiException, Interrup } @Test(timeout = 10000) - public void whenCrutchWorkedThenStreamIsClosed() throws NakadiException, InterruptedException, IOException { + public void whenCrutchWorkedThenStreamIsClosed() throws InterruptedException, IOException { final EventStreamConfig config = EventStreamConfig .builder() .withCursors(ImmutableList.of(NakadiCursor.of(TIMELINE, "0", "0"))) @@ -139,7 +138,7 @@ public void whenCrutchWorkedThenStreamIsClosed() throws NakadiException, Interru } @Test(timeout = 10000) - public void whenAuthorizationChangedStreamClosed() throws NakadiException, InterruptedException, IOException { + public void whenAuthorizationChangedStreamClosed() throws InterruptedException, IOException { final EventStreamConfig config = EventStreamConfig .builder() .withCursors(ImmutableList.of(NakadiCursor.of(TIMELINE, "0", "0"))) @@ -181,7 +180,7 @@ public void whenAuthorizationChangedStreamClosed() throws NakadiException, Inter } @Test(timeout = 5000) - public void whenStreamTimeoutIsSetThenStreamIsClosed() throws NakadiException, IOException, InterruptedException { + public void whenStreamTimeoutIsSetThenStreamIsClosed() throws IOException, InterruptedException { final EventStreamConfig config = EventStreamConfig .builder() .withBatchLimit(1) @@ -199,7 +198,7 @@ public void whenStreamTimeoutIsSetThenStreamIsClosed() throws NakadiException, I } @Test(timeout = 3000) - public void whenStreamLimitIsSetThenStreamIsClosed() throws NakadiException, IOException, InterruptedException { + public void whenStreamLimitIsSetThenStreamIsClosed() throws IOException, InterruptedException { final EventStreamConfig config = EventStreamConfig .builder() .withCursors(ImmutableList.of(NakadiCursor.of(TIMELINE, "0", "0"))) @@ -216,7 +215,7 @@ public void whenStreamLimitIsSetThenStreamIsClosed() throws NakadiException, IOE } @Test(timeout = 5000) - public void whenKeepAliveLimitIsSetThenStreamIsClosed() throws NakadiException, IOException, InterruptedException { + public void whenKeepAliveLimitIsSetThenStreamIsClosed() throws IOException, InterruptedException { final EventStreamConfig config = EventStreamConfig .builder() .withCursors(ImmutableList.of(NakadiCursor.of(TIMELINE, "0", "0"))) @@ -234,7 +233,7 @@ public void whenKeepAliveLimitIsSetThenStreamIsClosed() throws NakadiException, } @Test(timeout = 15000) - public void whenNoEventsToReadThenKeepAliveIsSent() throws NakadiException, IOException, InterruptedException { + public void whenNoEventsToReadThenKeepAliveIsSent() throws IOException, InterruptedException { final EventStreamConfig config = EventStreamConfig .builder() .withCursors(ImmutableList.of(NakadiCursor.of(TIMELINE, "0", "000000000000000000"))) @@ -261,7 +260,7 @@ public void whenNoEventsToReadThenKeepAliveIsSent() throws NakadiException, IOEx } @Test(timeout = 10000) - public void whenBatchSizeIsSetThenGetEventsInBatches() throws NakadiException, IOException, InterruptedException { + public void whenBatchSizeIsSetThenGetEventsInBatches() throws IOException, InterruptedException { final EventStreamConfig config = EventStreamConfig .builder() .withCursors(ImmutableList.of(NakadiCursor.of(TIMELINE, "0", String.format("%18d", 0)))) @@ -291,7 +290,7 @@ public void whenBatchSizeIsSetThenGetEventsInBatches() throws NakadiException, I } @Test(timeout = 10000) - public void whenReadingEventsTheOrderIsCorrect() throws NakadiException, IOException, InterruptedException { + public void whenReadingEventsTheOrderIsCorrect() throws IOException, InterruptedException { final EventStreamConfig config = EventStreamConfig .builder() .withCursors(ImmutableList.of(NakadiCursor.of(TIMELINE, "0", "0"))) @@ -332,7 +331,7 @@ public void whenReadingEventsTheOrderIsCorrect() throws NakadiException, IOExcep @Test(timeout = 10000) public void whenReadFromMultiplePartitionsThenGroupedInBatchesAccordingToPartition() - throws NakadiException, IOException, InterruptedException { + throws IOException, InterruptedException { final EventStreamConfig config = EventStreamConfig .builder() @@ -373,13 +372,13 @@ public void whenReadFromMultiplePartitionsThenGroupedInBatchesAccordingToPartiti Optional.of(nCopies(2, new String(DUMMY)))))); } - private static NakadiKafkaConsumer emptyConsumer() throws NakadiException { + private static NakadiKafkaConsumer emptyConsumer() { final NakadiKafkaConsumer nakadiKafkaConsumer = mock(NakadiKafkaConsumer.class); when(nakadiKafkaConsumer.readEvents()).thenReturn(Collections.emptyList()); return nakadiKafkaConsumer; } - private static NakadiKafkaConsumer endlessDummyConsumerForPartition(final String partition) throws NakadiException { + private static NakadiKafkaConsumer endlessDummyConsumerForPartition(final String partition) { final NakadiKafkaConsumer nakadiKafkaConsumer = mock(NakadiKafkaConsumer.class); when(nakadiKafkaConsumer.readEvents()) .thenReturn(Collections.singletonList( @@ -387,8 +386,7 @@ private static NakadiKafkaConsumer endlessDummyConsumerForPartition(final String return nakadiKafkaConsumer; } - private static NakadiKafkaConsumer nCountDummyConsumerForPartition(final int eventNum, final String partition) - throws NakadiException { + private static NakadiKafkaConsumer nCountDummyConsumerForPartition(final int eventNum, final String partition) { final NakadiKafkaConsumer nakadiKafkaConsumer = mock(NakadiKafkaConsumer.class); final AtomicInteger eventsToCreate = new AtomicInteger(eventNum); when(nakadiKafkaConsumer.readEvents()).thenAnswer(invocation -> { @@ -403,8 +401,7 @@ private static NakadiKafkaConsumer nCountDummyConsumerForPartition(final int eve return nakadiKafkaConsumer; } - private static NakadiKafkaConsumer predefinedConsumer(final List events) - throws NakadiException { + private static NakadiKafkaConsumer predefinedConsumer(final List events) { final NakadiKafkaConsumer nakadiKafkaConsumer = mock(NakadiKafkaConsumer.class); final AtomicBoolean sent = new AtomicBoolean(false); when(nakadiKafkaConsumer.readEvents()).thenAnswer(invocation -> { @@ -418,7 +415,7 @@ private static NakadiKafkaConsumer predefinedConsumer(final List return nakadiKafkaConsumer; } - private static NakadiKafkaConsumer endlessDummyConsumer() throws NakadiException { + private static NakadiKafkaConsumer endlessDummyConsumer() { return endlessDummyConsumerForPartition("0"); } diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java index 0ab31f1d64..425ddc5b46 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java @@ -9,10 +9,10 @@ import org.zalando.nakadi.domain.PartitionEndStatistics; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; +import org.zalando.nakadi.exceptions.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.ErrorGettingCursorTimeLagException; -import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.NakadiException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.repository.EventConsumer; import org.zalando.nakadi.service.subscription.SubscriptionTimeLagService; import org.zalando.nakadi.service.timeline.TimelineService; @@ -45,7 +45,7 @@ public void setUp() throws Exception { } @Test - public void testTimeLagsForTailAndNotTailPositions() throws NakadiException, InvalidCursorException { + public void testTimeLagsForTailAndNotTailPositions() throws InvalidCursorException { final EventConsumer eventConsumer = mock(EventConsumer.class); final Timeline timeline = mock(Timeline.class); @@ -81,9 +81,9 @@ public void testTimeLagsForTailAndNotTailPositions() throws NakadiException, Inv @Test(expected = InconsistentStateException.class) @SuppressWarnings("unchecked") - public void whenNakadiExceptionThenInconsistentStateExceptionIsThrown() - throws NakadiException, InvalidCursorException { - when(timelineService.createEventConsumer(any(), any())).thenThrow(NakadiException.class); + public void whenNakadiRuntimeExceptionThenInconsistentStateExceptionIsThrown() + throws InvalidCursorException { + when(timelineService.createEventConsumer(any(), any())).thenThrow(NakadiRuntimeException.class); final Timeline et1Timeline = new Timeline("et1", 0, new Storage("", Storage.Type.KAFKA), "t1", null); final NakadiCursor committedCursor1 = NakadiCursor.of(et1Timeline, "p1", "o1"); @@ -94,7 +94,7 @@ public void whenNakadiExceptionThenInconsistentStateExceptionIsThrown() @Test(expected = ErrorGettingCursorTimeLagException.class) @SuppressWarnings("unchecked") public void whenInvalidCursorThenErrorGettingCursorTimeLagExceptionIsThrown() - throws NakadiException, InvalidCursorException { + throws InvalidCursorException { when(timelineService.createEventConsumer(any(), any())).thenThrow(InvalidCursorException.class); final Timeline et1Timeline = new Timeline("et1", 0, new Storage("", Storage.Type.KAFKA), "t1", null); From 65dbab9a98b2d6ae03e4137e5b21267a8443cce2 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 16:34:14 +0200 Subject: [PATCH 081/176] move NakadiRuntimeException with the others --- .../java/org/zalando/nakadi/controller/CursorsController.java | 2 +- .../java/org/zalando/nakadi/controller/EventTypeController.java | 2 +- .../java/org/zalando/nakadi/controller/ExceptionHandling.java | 2 +- src/main/java/org/zalando/nakadi/exceptions/Try.java | 1 + .../nakadi/exceptions/{ => runtime}/NakadiRuntimeException.java | 2 +- .../org/zalando/nakadi/partitioning/HashPartitionStrategy.java | 2 +- .../org/zalando/nakadi/repository/KafkaRepositoryCreator.java | 2 +- .../zalando/nakadi/repository/MultiTimelineEventConsumer.java | 2 +- .../org/zalando/nakadi/repository/TopicRepositoryCreator.java | 2 +- .../org/zalando/nakadi/repository/TopicRepositoryHolder.java | 2 +- .../zalando/nakadi/repository/zookeeper/ZkChildrenCache.java | 2 +- src/main/java/org/zalando/nakadi/service/CursorsService.java | 2 +- src/main/java/org/zalando/nakadi/service/EventTypeService.java | 2 +- .../zalando/nakadi/service/subscription/StreamingContext.java | 2 +- .../zalando/nakadi/service/subscription/state/ClosingState.java | 2 +- .../nakadi/service/subscription/state/StartingState.java | 2 +- .../nakadi/service/subscription/state/StreamingState.java | 2 +- .../service/subscription/zk/AbstractZkSubscriptionClient.java | 2 +- .../nakadi/service/subscription/zk/NewZkSubscriptionClient.java | 2 +- .../zalando/nakadi/service/subscription/zk/ZkSubscription.java | 2 +- .../nakadi/service/subscription/zk/ZkSubscriptionClient.java | 2 +- .../nakadi/service/subscription/zk/ZkSubscriptionImpl.java | 2 +- .../zalando/nakadi/repository/TopicRepositoryHolderTest.java | 2 +- .../zalando/nakadi/service/SubscriptionTimeLagServiceTest.java | 2 +- 24 files changed, 24 insertions(+), 23 deletions(-) rename src/main/java/org/zalando/nakadi/exceptions/{ => runtime}/NakadiRuntimeException.java (89%) diff --git a/src/main/java/org/zalando/nakadi/controller/CursorsController.java b/src/main/java/org/zalando/nakadi/controller/CursorsController.java index c5df428f83..941f5ab5de 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorsController.java @@ -15,7 +15,7 @@ import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.domain.ItemsWrapper; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.CursorsAreEmptyException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index 594bd185c1..7018786a52 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -19,7 +19,7 @@ import org.zalando.nakadi.domain.CleanupPolicy; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 1b170f2e51..0c34de5e1e 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.NativeWebRequest; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.CompactionException; import org.zalando.nakadi.exceptions.runtime.CursorConversionException; diff --git a/src/main/java/org/zalando/nakadi/exceptions/Try.java b/src/main/java/org/zalando/nakadi/exceptions/Try.java index b40295c720..0a4865e580 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/Try.java +++ b/src/main/java/org/zalando/nakadi/exceptions/Try.java @@ -1,6 +1,7 @@ package org.zalando.nakadi.exceptions; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import java.util.Optional; import java.util.concurrent.Callable; diff --git a/src/main/java/org/zalando/nakadi/exceptions/NakadiRuntimeException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiRuntimeException.java similarity index 89% rename from src/main/java/org/zalando/nakadi/exceptions/NakadiRuntimeException.java rename to src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiRuntimeException.java index dcf88383d8..20313b178e 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/NakadiRuntimeException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiRuntimeException.java @@ -1,4 +1,4 @@ -package org.zalando.nakadi.exceptions; +package org.zalando.nakadi.exceptions.runtime; /* This exception is meant to be caught and unwrap the real excpetion */ public class NakadiRuntimeException extends RuntimeException { diff --git a/src/main/java/org/zalando/nakadi/partitioning/HashPartitionStrategy.java b/src/main/java/org/zalando/nakadi/partitioning/HashPartitionStrategy.java index c32e255878..e4db3da7cf 100644 --- a/src/main/java/org/zalando/nakadi/partitioning/HashPartitionStrategy.java +++ b/src/main/java/org/zalando/nakadi/partitioning/HashPartitionStrategy.java @@ -6,7 +6,7 @@ import org.zalando.nakadi.domain.EventCategory; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.Try; import org.zalando.nakadi.util.JsonPathAccess; import org.zalando.nakadi.validation.JsonSchemaEnrichment; diff --git a/src/main/java/org/zalando/nakadi/repository/KafkaRepositoryCreator.java b/src/main/java/org/zalando/nakadi/repository/KafkaRepositoryCreator.java index 731bba8ef1..e047754e9c 100644 --- a/src/main/java/org/zalando/nakadi/repository/KafkaRepositoryCreator.java +++ b/src/main/java/org/zalando/nakadi/repository/KafkaRepositoryCreator.java @@ -7,7 +7,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.TopicRepositoryException; import org.zalando.nakadi.repository.kafka.KafkaFactory; import org.zalando.nakadi.repository.kafka.KafkaLocationManager; diff --git a/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java b/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java index 80636b7172..d0deb8fe4a 100644 --- a/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java +++ b/src/main/java/org/zalando/nakadi/repository/MultiTimelineEventConsumer.java @@ -8,7 +8,7 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.domain.TopicPartition; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.service.timeline.TimelineService; diff --git a/src/main/java/org/zalando/nakadi/repository/TopicRepositoryCreator.java b/src/main/java/org/zalando/nakadi/repository/TopicRepositoryCreator.java index acae318b10..fd6472b8bd 100644 --- a/src/main/java/org/zalando/nakadi/repository/TopicRepositoryCreator.java +++ b/src/main/java/org/zalando/nakadi/repository/TopicRepositoryCreator.java @@ -3,7 +3,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.TopicRepositoryException; import java.util.List; diff --git a/src/main/java/org/zalando/nakadi/repository/TopicRepositoryHolder.java b/src/main/java/org/zalando/nakadi/repository/TopicRepositoryHolder.java index f7c9d708d5..00c60a7e03 100644 --- a/src/main/java/org/zalando/nakadi/repository/TopicRepositoryHolder.java +++ b/src/main/java/org/zalando/nakadi/repository/TopicRepositoryHolder.java @@ -9,7 +9,7 @@ import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TopicRepositoryException; diff --git a/src/main/java/org/zalando/nakadi/repository/zookeeper/ZkChildrenCache.java b/src/main/java/org/zalando/nakadi/repository/zookeeper/ZkChildrenCache.java index 852cf55d98..377c3db501 100644 --- a/src/main/java/org/zalando/nakadi/repository/zookeeper/ZkChildrenCache.java +++ b/src/main/java/org/zalando/nakadi/repository/zookeeper/ZkChildrenCache.java @@ -7,7 +7,7 @@ import org.echocat.jomon.runtime.concurrent.RetryForSpecifiedCountStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import static org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode.BUILD_INITIAL_CACHE; import static org.echocat.jomon.runtime.concurrent.Retryer.executeWithRetry; diff --git a/src/main/java/org/zalando/nakadi/service/CursorsService.java b/src/main/java/org/zalando/nakadi/service/CursorsService.java index 05ae0c0172..7c5481588e 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorsService.java @@ -8,7 +8,7 @@ import org.zalando.nakadi.domain.EventTypePartition; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Subscription; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 84b9dccbfc..9f4a17eabd 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -25,7 +25,7 @@ import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.enrichment.Enrichment; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java b/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java index e78c586ff2..8b0a85266c 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/StreamingContext.java @@ -8,7 +8,7 @@ import org.zalando.nakadi.ShutdownHooks; import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Subscription; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.service.AuthorizationValidator; import org.zalando.nakadi.service.BlacklistService; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/ClosingState.java b/src/main/java/org/zalando/nakadi/service/subscription/state/ClosingState.java index 3ad6f41f18..6470e5de99 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/ClosingState.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/ClosingState.java @@ -2,7 +2,7 @@ import org.zalando.nakadi.domain.EventTypePartition; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.service.subscription.model.Partition; import org.zalando.nakadi.service.subscription.zk.ZkSubscription; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java b/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java index dbb1d22d1f..fee67591b7 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/StartingState.java @@ -6,7 +6,7 @@ import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java index 696115d7b7..5ba63ab7b9 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/state/StreamingState.java @@ -9,7 +9,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.PartitionStatistics; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java index ae6600d600..f1160cf276 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java @@ -12,7 +12,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zalando.nakadi.domain.EventTypePartition; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.OperationInterruptedException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/NewZkSubscriptionClient.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/NewZkSubscriptionClient.java index d68882c3ed..27d430889f 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/NewZkSubscriptionClient.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/NewZkSubscriptionClient.java @@ -6,7 +6,7 @@ import org.apache.curator.framework.CuratorFramework; import org.apache.zookeeper.KeeperException; import org.zalando.nakadi.domain.EventTypePartition; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.service.subscription.model.Partition; import org.zalando.nakadi.service.subscription.model.Session; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscription.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscription.java index 6fdd761592..9dff6183cb 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscription.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscription.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.service.subscription.zk; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import java.io.Closeable; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java index 1c4cedbf67..170268ec24 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java @@ -3,7 +3,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.commons.codec.binary.Hex; import org.zalando.nakadi.domain.EventTypePartition; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.OperationTimeoutException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionImpl.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionImpl.java index 529919eadb..1d0dd05f83 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionImpl.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionImpl.java @@ -5,7 +5,7 @@ import org.apache.curator.framework.api.GetDataBuilder; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import java.util.List; import java.util.function.Function; diff --git a/src/test/java/org/zalando/nakadi/repository/TopicRepositoryHolderTest.java b/src/test/java/org/zalando/nakadi/repository/TopicRepositoryHolderTest.java index becec77404..5f3ac8039d 100644 --- a/src/test/java/org/zalando/nakadi/repository/TopicRepositoryHolderTest.java +++ b/src/test/java/org/zalando/nakadi/repository/TopicRepositoryHolderTest.java @@ -5,7 +5,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.TopicRepositoryException; import java.util.List; diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java index 425ddc5b46..df885b643d 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionTimeLagServiceTest.java @@ -9,7 +9,7 @@ import org.zalando.nakadi.domain.PartitionEndStatistics; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.ErrorGettingCursorTimeLagException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; From e75bb71ccc2b2cb09aae3efe331d3e173f59b391 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 16:52:57 +0200 Subject: [PATCH 082/176] Refactor exceptions and logs - merge NoEventTypeException and NoSuchEventTypeException - merge NoSubscriptionException and NoSuchSubscriptionException - rename NoStorageException to NoSuchStorageException (consistency) - create UnprocessableSubscriptionException - don't log whole stack trace when error is in user input (still log message) --- .../db/StorageDbRepositoryTest.java | 4 +- .../controller/EventTypeController.java | 13 ++----- .../nakadi/controller/ExceptionHandling.java | 38 ++++++++++--------- .../PostSubscriptionController.java | 11 +++--- .../runtime/NoEventTypeException.java | 12 ------ .../runtime/NoStorageException.java | 9 ----- .../runtime/NoSubscriptionException.java | 8 ---- .../runtime/NoSuchStorageException.java | 9 +++++ .../UnprocessableSubscriptionException.java | 7 ++++ .../repository/db/StorageDbRepository.java | 6 +-- .../db/SubscriptionDbRepository.java | 7 ++-- .../nakadi/service/EventTypeService.java | 7 ++-- .../nakadi/service/StorageService.java | 4 +- .../subscription/SubscriptionService.java | 14 +++---- .../SubscriptionValidationService.java | 10 ++--- .../PostSubscriptionControllerTest.java | 18 ++++----- .../nakadi/service/StorageServiceTest.java | 4 +- .../SubscriptionValidationServiceTest.java | 8 ++-- 18 files changed, 84 insertions(+), 105 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/NoStorageException.java delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/NoSubscriptionException.java create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchStorageException.java create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java diff --git a/src/acceptance-test/java/org/zalando/nakadi/repository/db/StorageDbRepositoryTest.java b/src/acceptance-test/java/org/zalando/nakadi/repository/db/StorageDbRepositoryTest.java index ba6fd27726..e5fabc6eae 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/repository/db/StorageDbRepositoryTest.java +++ b/src/acceptance-test/java/org/zalando/nakadi/repository/db/StorageDbRepositoryTest.java @@ -5,7 +5,7 @@ import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.runtime.NoStorageException; +import org.zalando.nakadi.exceptions.runtime.NoSuchStorageException; import org.zalando.nakadi.exceptions.runtime.StorageIsUsedException; import org.zalando.nakadi.utils.TestUtils; @@ -94,7 +94,7 @@ public void testStorageDeleted() throws Exception { assertFalse(repository.getStorage(storage.getId()).isPresent()); } - @Test(expected = NoStorageException.class) + @Test(expected = NoSuchStorageException.class) public void testDeleteNoneExistingStorage() throws Exception { repository.deleteStorage(randomUUID()); } diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index 7018786a52..321229d212 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -19,7 +19,6 @@ import org.zalando.nakadi.domain.CleanupPolicy; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeBase; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; @@ -29,7 +28,8 @@ import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; -import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TopicConfigException; @@ -110,7 +110,7 @@ public ResponseEntity create(@Valid @RequestBody final EventTypeBase eventTyp public ResponseEntity delete(@PathVariable("name") final String eventTypeName) throws EventTypeDeletionException, AccessDeniedException, - NoEventTypeException, + NoSuchEventTypeException, ConflictException, ServiceTemporarilyUnavailableException { if (featureToggleService.isFeatureEnabled(DISABLE_EVENT_TYPE_DELETION) @@ -193,13 +193,6 @@ public ResponseEntity conflict(final ConflictException exception, final return Responses.create(Response.Status.CONFLICT, exception.getMessage(), request); } - @ExceptionHandler(NoEventTypeException.class) - public ResponseEntity noEventType(final NoEventTypeException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); - return Responses.create(Response.Status.NOT_FOUND, exception.getMessage(), request); - } - @ExceptionHandler(EventTypeUnavailableException.class) public ResponseEntity eventTypeUnavailable(final EventTypeUnavailableException exception, final NativeWebRequest request) { diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 0c34de5e1e..7632cafcb6 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -10,7 +10,6 @@ import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.NativeWebRequest; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; import org.zalando.nakadi.exceptions.runtime.CompactionException; import org.zalando.nakadi.exceptions.runtime.CursorConversionException; @@ -23,7 +22,7 @@ import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; import org.zalando.nakadi.exceptions.runtime.LimitReachedException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; -import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.NoStreamingSlotsAvailable; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; @@ -34,6 +33,7 @@ import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TimelineException; import org.zalando.nakadi.exceptions.runtime.TopicCreationException; +import org.zalando.nakadi.exceptions.runtime.UnprocessableSubscriptionException; import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; import org.zalando.problem.spring.web.advice.ProblemHandling; @@ -89,12 +89,6 @@ class and stacktrace like information. return Responses.create(Response.Status.BAD_REQUEST, message, request); } - @ExceptionHandler(NoEventTypeException.class) - public ResponseEntity noEventTypeException(final NoEventTypeException exception, - final NativeWebRequest request) { - return Responses.create(NOT_FOUND, exception.getMessage(), request); - } - @ExceptionHandler(AccessDeniedException.class) public ResponseEntity accessDeniedException(final AccessDeniedException exception, final NativeWebRequest request) { @@ -189,21 +183,21 @@ public ResponseEntity handleDbWriteOperationsBlockedException( public ResponseEntity handleFeatureNotAvailable( final FeatureNotAvailableException ex, final NativeWebRequest request) { - LOG.debug(ex.getMessage(), ex); + LOG.debug(ex.getMessage()); return Responses.create(Problem.valueOf(NOT_IMPLEMENTED, ex.getMessage()), request); } @ExceptionHandler(CompactionException.class) public ResponseEntity handleCompactionException(final CompactionException exception, final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); + LOG.debug(exception.getMessage()); return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } @ExceptionHandler(EnrichmentException.class) public ResponseEntity handleEnrichmentException(final EnrichmentException exception, final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); + LOG.debug(exception.getMessage()); return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } @@ -211,14 +205,14 @@ public ResponseEntity handleEnrichmentException(final EnrichmentExcepti public ResponseEntity handleNoSuchPartitionStrategyException( final NoSuchPartitionStrategyException exception, final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); + LOG.debug(exception.getMessage()); return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } @ExceptionHandler(PartitioningException.class) public ResponseEntity handlePartitioningException(final PartitioningException exception, final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); + LOG.debug(exception.getMessage()); return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } @@ -226,35 +220,43 @@ public ResponseEntity handlePartitioningException(final PartitioningExc public ResponseEntity handleInvalidPartitionKeyFieldsException( final InvalidPartitionKeyFieldsException exception, final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); + LOG.debug(exception.getMessage()); return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } @ExceptionHandler(NoSuchEventTypeException.class) public ResponseEntity handleNoSuchEventTypeException(final NoSuchEventTypeException exception, final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); + LOG.debug(exception.getMessage()); return Responses.create(NOT_FOUND, exception.getMessage(), request); } @ExceptionHandler(NoSuchSchemaException.class) public ResponseEntity handleNoSuchSchemaException(final NoSuchSchemaException exception, final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); + LOG.debug(exception.getMessage()); return Responses.create(NOT_FOUND, exception.getMessage(), request); } @ExceptionHandler(NoSuchSubscriptionException.class) public ResponseEntity handleNoSuchSubscriptionException(final NoSuchSubscriptionException exception, final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); + LOG.debug(exception.getMessage()); return Responses.create(NOT_FOUND, exception.getMessage(), request); } @ExceptionHandler(NoStreamingSlotsAvailable.class) public ResponseEntity handleNoStreamingSlotsAvailable(final NoStreamingSlotsAvailable exception, final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); + LOG.debug(exception.getMessage()); return Responses.create(CONFLICT, exception.getMessage(), request); } + + @ExceptionHandler(UnprocessableSubscriptionException.class) + public ResponseEntity handleUnprocessableSubscriptionException( + final UnprocessableSubscriptionException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); + } } diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index 885262a9bc..0c844ce23c 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -16,14 +16,14 @@ import org.springframework.web.util.UriComponents; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; -import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.DuplicatedSubscriptionException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; -import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; -import org.zalando.nakadi.exceptions.runtime.NoSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.SubscriptionUpdateConflictException; import org.zalando.nakadi.exceptions.runtime.TooManyPartitionsException; +import org.zalando.nakadi.exceptions.runtime.UnprocessableSubscriptionException; import org.zalando.nakadi.exceptions.runtime.WrongInitialCursorsException; import org.zalando.nakadi.plugin.api.ApplicationService; import org.zalando.nakadi.problem.ValidationProblem; @@ -70,7 +70,7 @@ public ResponseEntity createOrGetSubscription(@Valid @RequestBody final Subsc try { return ok(subscriptionService.getExistingSubscription(subscriptionBase)); - } catch (final NoSubscriptionException e) { + } catch (final NoSuchSubscriptionException e) { if (featureToggleService.isFeatureEnabled(DISABLE_SUBSCRIPTION_CREATION)) { return Responses.create(Response.Status.SERVICE_UNAVAILABLE, "Subscription creation is temporarily unavailable", request); @@ -80,6 +80,8 @@ public ResponseEntity createOrGetSubscription(@Valid @RequestBody final Subsc return prepareLocationResponse(subscription); } catch (final DuplicatedSubscriptionException ex) { throw new InconsistentStateException("Unexpected problem occurred when creating subscription", ex); + } catch (final NoSuchEventTypeException ex) { + throw new UnprocessableSubscriptionException(ex.getMessage()); } } } @@ -117,7 +119,6 @@ private ResponseEntity prepareLocationResponse(final Subscription subscriptio } @ExceptionHandler({ - NoEventTypeException.class, WrongInitialCursorsException.class, TooManyPartitionsException.class}) public ResponseEntity handleUnprocessableSubscription(final NakadiRuntimeBaseException exception, diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java deleted file mode 100644 index c7542644ae..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoEventTypeException.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.zalando.nakadi.exceptions.runtime; - -public class NoEventTypeException extends NakadiRuntimeBaseException { - - public NoEventTypeException(final String msg) { - super(msg); - } - - public NoEventTypeException(final String message, final NoSuchEventTypeException e) { - super(message, e); - } -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStorageException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStorageException.java deleted file mode 100644 index 87ea1dd21a..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStorageException.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.zalando.nakadi.exceptions.runtime; - -public class NoStorageException extends NakadiRuntimeBaseException { - - public NoStorageException(final String msg) { - super(msg); - } - -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSubscriptionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSubscriptionException.java deleted file mode 100644 index 664b8b65ee..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSubscriptionException.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.zalando.nakadi.exceptions.runtime; - -public class NoSubscriptionException extends NakadiRuntimeBaseException { - - public NoSubscriptionException(final String message, final Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchStorageException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchStorageException.java new file mode 100644 index 0000000000..0cf65f11c9 --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchStorageException.java @@ -0,0 +1,9 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class NoSuchStorageException extends NakadiRuntimeBaseException { + + public NoSuchStorageException(final String msg) { + super(msg); + } + +} diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java new file mode 100644 index 0000000000..8218cacdf6 --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java @@ -0,0 +1,7 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class UnprocessableSubscriptionException extends NakadiRuntimeBaseException { + public UnprocessableSubscriptionException(String message) { + super(message); + } +} diff --git a/src/main/java/org/zalando/nakadi/repository/db/StorageDbRepository.java b/src/main/java/org/zalando/nakadi/repository/db/StorageDbRepository.java index e79e6343ff..9611453cf5 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/StorageDbRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/db/StorageDbRepository.java @@ -12,7 +12,7 @@ import org.zalando.nakadi.annotations.DB; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.exceptions.runtime.DuplicatedStorageException; -import org.zalando.nakadi.exceptions.runtime.NoStorageException; +import org.zalando.nakadi.exceptions.runtime.NoSuchStorageException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.StorageIsUsedException; @@ -73,11 +73,11 @@ public Storage createStorage(final Storage storage) throws DuplicatedStorageExce } public void deleteStorage(final String id) - throws NoStorageException, StorageIsUsedException, RepositoryProblemException { + throws NoSuchStorageException, StorageIsUsedException, RepositoryProblemException { try { final int rowDeleted = jdbcTemplate.update("DELETE FROM zn_data.storage WHERE st_id=?", id); if (rowDeleted == 0) { - throw new NoStorageException("Tried to remove storage that doesn't exist, id: " + id); + throw new NoSuchStorageException("Tried to remove storage that doesn't exist, id: " + id); } } catch (final DataIntegrityViolationException e) { throw new StorageIsUsedException("Can't delete storage as it is still used, id: " + id, e); diff --git a/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java b/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java index 66e8c8010b..ec8e7d5fdc 100644 --- a/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java +++ b/src/main/java/org/zalando/nakadi/repository/db/SubscriptionDbRepository.java @@ -18,10 +18,9 @@ import org.springframework.stereotype.Component; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; -import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.DuplicatedSubscriptionException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; -import org.zalando.nakadi.exceptions.runtime.NoSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.util.HashGenerator; @@ -161,7 +160,7 @@ public List listSubscriptions(final Set eventTypes, final public Subscription getSubscription(final String owningApplication, final Set eventTypes, final String consumerGroup) - throws InconsistentStateException, NoSubscriptionException, RepositoryProblemException { + throws InconsistentStateException, NoSuchSubscriptionException, RepositoryProblemException { final String sql = "SELECT s_subscription_object FROM zn_data.subscription " + "WHERE s_subscription_object->>'owning_application' = ? " + @@ -174,7 +173,7 @@ public Subscription getSubscription(final String owningApplication, final Set eventTypeOpt = eventTypeRepository.findByNameO(eventTypeName); if (!eventTypeOpt.isPresent()) { - throw new NoEventTypeException("EventType \"" + eventTypeName + "\" does not exist."); + throw new NoSuchEventTypeException("EventType \"" + eventTypeName + "\" does not exist."); } eventType = eventTypeOpt.get(); diff --git a/src/main/java/org/zalando/nakadi/service/StorageService.java b/src/main/java/org/zalando/nakadi/service/StorageService.java index fd1c7eedfb..df3dd48cc7 100644 --- a/src/main/java/org/zalando/nakadi/service/StorageService.java +++ b/src/main/java/org/zalando/nakadi/service/StorageService.java @@ -16,7 +16,7 @@ import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; import org.zalando.nakadi.exceptions.runtime.DuplicatedStorageException; -import org.zalando.nakadi.exceptions.runtime.NoStorageException; +import org.zalando.nakadi.exceptions.runtime.NoSuchStorageException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.StorageIsUsedException; import org.zalando.nakadi.repository.db.StorageDbRepository; @@ -152,7 +152,7 @@ public Result deleteStorage(final String id) throws DbWriteOperationsBlock } try { storageDbRepository.deleteStorage(id); - } catch (final NoStorageException e) { + } catch (final NoSuchStorageException e) { return Result.notFound("No storage with ID " + id); } catch (final StorageIsUsedException e) { return Result.forbidden("Storage " + id + " is in use"); diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java index 55d82eb0df..dcae6188d8 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java @@ -22,17 +22,15 @@ import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.domain.SubscriptionEventTypeStats; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; -import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.Try; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; import org.zalando.nakadi.exceptions.runtime.DuplicatedSubscriptionException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; -import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; -import org.zalando.nakadi.exceptions.runtime.NoSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.SubscriptionUpdateConflictException; @@ -125,7 +123,7 @@ public SubscriptionService(final SubscriptionDbRepository subscriptionRepository public Subscription createSubscription(final SubscriptionBase subscriptionBase) throws TooManyPartitionsException, RepositoryProblemException, DuplicatedSubscriptionException, - NoEventTypeException, InconsistentStateException, WrongInitialCursorsException, + NoSuchEventTypeException, InconsistentStateException, WrongInitialCursorsException, DbWriteOperationsBlockedException { if (featureToggleService.isFeatureEnabled(FeatureToggleService.Feature.DISABLE_DB_WRITE_OPERATIONS)) { throw new DbWriteOperationsBlockedException("Cannot create subscription: write operations on DB " + @@ -160,7 +158,7 @@ public Subscription updateSubscription(final String subscriptionId, final Subscr } public Subscription getExistingSubscription(final SubscriptionBase subscriptionBase) - throws InconsistentStateException, NoSubscriptionException, RepositoryProblemException { + throws InconsistentStateException, NoSuchSubscriptionException, RepositoryProblemException { return subscriptionRepository.getSubscription( subscriptionBase.getOwningApplication(), subscriptionBase.getEventTypes(), diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java index aeb757e484..8adb08444d 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionValidationService.java @@ -12,7 +12,7 @@ import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.SubscriptionUpdateConflictException; @@ -59,7 +59,7 @@ public SubscriptionValidationService(final TimelineService timelineService, } public void validateSubscription(final SubscriptionBase subscription) - throws TooManyPartitionsException, RepositoryProblemException, NoEventTypeException, + throws TooManyPartitionsException, RepositoryProblemException, NoSuchEventTypeException, InconsistentStateException, WrongInitialCursorsException { // check that all event-types exist @@ -186,14 +186,14 @@ private Map> getSubscriptionEventTypesOrNone(final S } private void checkEventTypesExist(final Map> eventTypesOrNone) - throws NoEventTypeException { + throws NoSuchEventTypeException { final List missingEventTypes = eventTypesOrNone.entrySet().stream() .filter(entry -> !entry.getValue().isPresent()) .map(Map.Entry::getKey) .collect(Collectors.toList()); if (!missingEventTypes.isEmpty()) { - throw new NoEventTypeException(String.format("Failed to create subscription, event type(s) not found: '%s'", - StringUtils.join(missingEventTypes, "', '"))); + throw new NoSuchEventTypeException(String.format("Failed to create subscription, event type(s) not " + + "found: '%s'", StringUtils.join(missingEventTypes, "', '"))); } } } diff --git a/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java b/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java index 14a6ee80a9..2e94ce20f5 100644 --- a/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java @@ -16,13 +16,13 @@ import org.springframework.web.method.support.ModelAndViewContainer; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.SubscriptionBase; -import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; -import org.zalando.nakadi.exceptions.runtime.NoSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.TooManyPartitionsException; import org.zalando.nakadi.plugin.api.ApplicationService; import org.zalando.nakadi.security.NakadiClient; -import org.zalando.nakadi.service.subscription.SubscriptionService; import org.zalando.nakadi.service.FeatureToggleService; +import org.zalando.nakadi.service.subscription.SubscriptionService; import org.zalando.nakadi.utils.TestUtils; import org.zalando.problem.Problem; @@ -74,7 +74,7 @@ public PostSubscriptionControllerTest() throws Exception { @Test public void whenSubscriptionCreationIsDisabledThenCreationFails() throws Exception { final SubscriptionBase subscriptionBase = builder().buildSubscriptionBase(); - when(subscriptionService.getExistingSubscription(any())).thenThrow(new NoSubscriptionException("", null)); + when(subscriptionService.getExistingSubscription(any())).thenThrow(new NoSuchSubscriptionException("", null)); when(featureToggleService.isFeatureEnabled(DISABLE_SUBSCRIPTION_CREATION)).thenReturn(true); postSubscription(subscriptionBase).andExpect(status().isServiceUnavailable()); @@ -103,7 +103,7 @@ public void whenPostValidSubscriptionThenOk() throws Exception { final SubscriptionBase subscriptionBase = builder().buildSubscriptionBase(); final Subscription subscription = new Subscription("123", new DateTime(DateTimeZone.UTC), subscriptionBase); - when(subscriptionService.getExistingSubscription(any())).thenThrow(new NoSubscriptionException("", null)); + when(subscriptionService.getExistingSubscription(any())).thenThrow(new NoSuchSubscriptionException("", null)); when(subscriptionService.createSubscription(any())).thenReturn(subscription); postSubscription(subscriptionBase) @@ -152,7 +152,7 @@ public void whenEventTypesIsEmptyThenUnprocessableEntity() throws Exception { @Test public void whenMoreThanAllowedEventTypeThenUnprocessableEntity() throws Exception { - when(subscriptionService.getExistingSubscription(any())).thenThrow(new NoSubscriptionException("", null)); + when(subscriptionService.getExistingSubscription(any())).thenThrow(new NoSuchSubscriptionException("", null)); when(subscriptionService.createSubscription(any())).thenThrow(new TooManyPartitionsException("msg")); final SubscriptionBase subscriptionBase = builder().buildSubscriptionBase(); @@ -178,8 +178,8 @@ public void whenWrongStartFromThenBadRequest() throws Exception { @Test public void whenEventTypeDoesNotExistThenUnprocessableEntity() throws Exception { final SubscriptionBase subscriptionBase = builder().buildSubscriptionBase(); - when(subscriptionService.getExistingSubscription(any())).thenThrow(new NoSubscriptionException("", null)); - when(subscriptionService.createSubscription(any())).thenThrow(new NoEventTypeException("msg")); + when(subscriptionService.getExistingSubscription(any())).thenThrow(new NoSuchSubscriptionException("", null)); + when(subscriptionService.createSubscription(any())).thenThrow(new NoSuchEventTypeException("msg")); final Problem expectedProblem = Problem.valueOf(UNPROCESSABLE_ENTITY, "msg"); checkForProblem(postSubscription(subscriptionBase), expectedProblem); @@ -192,7 +192,7 @@ public void whenSubscriptionExistsThenReturnIt() throws Exception { subscriptionBase); when(subscriptionService.getExistingSubscription(any())).thenReturn(existingSubscription); - when(subscriptionService.createSubscription(any())).thenThrow(new NoEventTypeException("msg")); + when(subscriptionService.createSubscription(any())).thenThrow(new NoSuchEventTypeException("msg")); postSubscription(subscriptionBase) .andExpect(status().isOk()) diff --git a/src/test/java/org/zalando/nakadi/service/StorageServiceTest.java b/src/test/java/org/zalando/nakadi/service/StorageServiceTest.java index 8351ca69e0..0e10138dfc 100644 --- a/src/test/java/org/zalando/nakadi/service/StorageServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/StorageServiceTest.java @@ -5,7 +5,7 @@ import org.junit.Test; import org.zalando.nakadi.domain.DefaultStorage; import org.zalando.nakadi.domain.Storage; -import org.zalando.nakadi.exceptions.runtime.NoStorageException; +import org.zalando.nakadi.exceptions.runtime.NoSuchStorageException; import org.zalando.nakadi.exceptions.runtime.StorageIsUsedException; import org.zalando.nakadi.repository.db.StorageDbRepository; import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; @@ -64,7 +64,7 @@ public void testDeleteStorageInUse() throws Exception { @Test public void testDeleteNonExistingStorage() throws Exception { - doThrow(new NoStorageException("")).when(storageDbRepository).deleteStorage("s"); + doThrow(new NoSuchStorageException("")).when(storageDbRepository).deleteStorage("s"); final Result result = storageService.deleteStorage("s"); diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java index d8d3a9c010..b02b376fe4 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java @@ -10,10 +10,10 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.domain.Timeline; +import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; -import org.zalando.nakadi.exceptions.runtime.NoEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TooManyPartitionsException; @@ -104,8 +104,8 @@ public void whenNoEventTypeThenException() throws Exception { try { subscriptionValidationService.validateSubscription(subscriptionBase); - fail("NoEventTypeException expected"); - } catch (final NoEventTypeException e) { + fail("NoSuchEventTypeException expected"); + } catch (final NoSuchEventTypeException e) { final String expectedMessage = String.format("Failed to create subscription, event type(s) not found: '%s', '%s'", ET1, ET3); assertThat(e.getMessage(), equalTo(expectedMessage)); From 3b56bc7901aab414c88cc2f7d3d38e63ae423b67 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 16:59:17 +0200 Subject: [PATCH 083/176] Rename NakadiRuntimeBaseException to NakadiBaseException --- .../nakadi/controller/CursorOperationsController.java | 6 +++--- .../org/zalando/nakadi/controller/ExceptionHandling.java | 6 +++--- .../zalando/nakadi/controller/PartitionsController.java | 4 ++-- .../nakadi/controller/PostSubscriptionController.java | 4 ++-- src/main/java/org/zalando/nakadi/domain/NakadiCursor.java | 4 ++-- src/main/java/org/zalando/nakadi/exceptions/Try.java | 6 +++--- .../nakadi/exceptions/runtime/AccessDeniedException.java | 2 +- .../nakadi/exceptions/runtime/CompactionException.java | 2 +- .../nakadi/exceptions/runtime/ConflictException.java | 2 +- .../runtime/ConnectionSlotOccupiedException.java | 2 +- .../exceptions/runtime/CursorConversionException.java | 2 +- .../exceptions/runtime/CursorsAreEmptyException.java | 2 +- .../runtime/DbWriteOperationsBlockedException.java | 2 +- .../runtime/DuplicatedEventTypeNameException.java | 2 +- .../exceptions/runtime/DuplicatedStorageException.java | 2 +- .../runtime/DuplicatedSubscriptionException.java | 2 +- .../exceptions/runtime/DuplicatedTimelineException.java | 2 +- .../nakadi/exceptions/runtime/EnrichmentException.java | 2 +- .../runtime/ErrorGettingCursorTimeLagException.java | 2 +- .../exceptions/runtime/EventPublishingException.java | 2 +- .../exceptions/runtime/EventTypeDeletionException.java | 2 +- .../runtime/EventTypeOptionsValidationException.java | 2 +- .../exceptions/runtime/EventTypeTimeoutException.java | 2 +- .../exceptions/runtime/EventTypeUnavailableException.java | 2 +- .../exceptions/runtime/EventValidationException.java | 2 +- .../exceptions/runtime/FeatureNotAvailableException.java | 2 +- .../exceptions/runtime/IllegalClientIdException.java | 2 +- .../exceptions/runtime/InconsistentStateException.java | 2 +- .../exceptions/runtime/InternalNakadiException.java | 2 +- .../nakadi/exceptions/runtime/InvalidCursorException.java | 2 +- .../nakadi/exceptions/runtime/InvalidCursorOperation.java | 2 +- .../exceptions/runtime/InvalidEventTypeException.java | 2 +- .../nakadi/exceptions/runtime/InvalidLimitException.java | 2 +- .../exceptions/runtime/InvalidStreamIdException.java | 2 +- .../nakadi/exceptions/runtime/LimitReachedException.java | 2 +- ...RuntimeBaseException.java => NakadiBaseException.java} | 8 ++++---- .../exceptions/runtime/NoConnectionSlotsException.java | 2 +- .../exceptions/runtime/NoStreamingSlotsAvailable.java | 2 +- .../exceptions/runtime/NoSuchEventTypeException.java | 2 +- .../runtime/NoSuchPartitionStrategyException.java | 2 +- .../nakadi/exceptions/runtime/NoSuchSchemaException.java | 2 +- .../nakadi/exceptions/runtime/NoSuchStorageException.java | 2 +- .../exceptions/runtime/NoSuchSubscriptionException.java | 2 +- .../nakadi/exceptions/runtime/NotFoundException.java | 2 +- .../exceptions/runtime/OperationInterruptedException.java | 2 +- .../exceptions/runtime/OperationTimeoutException.java | 2 +- .../nakadi/exceptions/runtime/PartitioningException.java | 2 +- .../exceptions/runtime/RebalanceConflictException.java | 2 +- .../exceptions/runtime/RepositoryProblemException.java | 2 +- .../exceptions/runtime/RequestInProgressException.java | 2 +- .../runtime/ServiceTemporarilyUnavailableException.java | 2 +- .../nakadi/exceptions/runtime/StorageIsUsedException.java | 2 +- .../runtime/SubscriptionPartitionConflictException.java | 2 +- .../runtime/SubscriptionUpdateConflictException.java | 2 +- .../exceptions/runtime/TimeLagStatsTimeoutException.java | 2 +- .../nakadi/exceptions/runtime/TimelineException.java | 2 +- .../runtime/TimelinesNotSupportedException.java | 2 +- .../exceptions/runtime/TooManyPartitionsException.java | 2 +- .../nakadi/exceptions/runtime/TopicConfigException.java | 2 +- .../nakadi/exceptions/runtime/TopicCreationException.java | 2 +- .../nakadi/exceptions/runtime/TopicDeletionException.java | 2 +- .../exceptions/runtime/TopicRepositoryException.java | 2 +- .../nakadi/exceptions/runtime/UnableProcessException.java | 2 +- .../exceptions/runtime/UnknownOperationException.java | 2 +- .../exceptions/runtime/UnknownStorageTypeException.java | 2 +- .../exceptions/runtime/UnparseableCursorException.java | 2 +- .../runtime/UnprocessableSubscriptionException.java | 2 +- .../exceptions/runtime/WrongInitialCursorsException.java | 2 +- .../runtime/WrongStreamParametersException.java | 2 +- .../nakadi/exceptions/runtime/ZookeeperException.java | 2 +- .../zalando/nakadi/service/CursorOperationsService.java | 4 ++-- .../service/subscription/SubscriptionTimeLagService.java | 6 +++--- .../nakadi/service/subscription/state/ClosingState.java | 4 ++-- .../subscription/zk/AbstractZkSubscriptionClient.java | 4 ++-- .../zk/SubscriptionNotInitializedException.java | 4 ++-- .../service/subscription/zk/ZkSubscriptionClient.java | 4 ++-- .../nakadi/repository/kafka/NakadiKafkaConsumerTest.java | 2 +- 77 files changed, 96 insertions(+), 96 deletions(-) rename src/main/java/org/zalando/nakadi/exceptions/runtime/{NakadiRuntimeBaseException.java => NakadiBaseException.java} (53%) diff --git a/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java b/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java index 1ae88ace5e..ab640408df 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java @@ -19,7 +19,7 @@ import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; @@ -82,7 +82,7 @@ public ResponseEntity getDistance(@PathVariable("eventTypeName") final String final Long distance = cursorOperationsService.calculateDistance(initialCursor, finalCursor); query.setDistance(distance); } catch (InternalNakadiException | ServiceTemporarilyUnavailableException e) { - throw new NakadiRuntimeBaseException("problem calculating cursors distance", e); + throw new NakadiBaseException("problem calculating cursors distance", e); } catch (final NoSuchEventTypeException e) { throw new NotFoundException("event type not found", e); } catch (final InvalidCursorException e) { @@ -150,7 +150,7 @@ private String clientErrorMessage(final InvalidCursorOperation.Reason reason) { "have matching partitions."; default: LOG.error("Unexpected invalid cursor operation reason " + reason); - throw new NakadiRuntimeBaseException(); + throw new NakadiBaseException(); } } diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 7632cafcb6..604042b162 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -21,7 +21,7 @@ import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; import org.zalando.nakadi.exceptions.runtime.LimitReachedException; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.NoStreamingSlotsAvailable; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; @@ -125,8 +125,8 @@ public ResponseEntity handleRepositoryProblem(final RepositoryProblemEx return Responses.create(Response.Status.SERVICE_UNAVAILABLE, exception.getMessage(), request); } - @ExceptionHandler(NakadiRuntimeBaseException.class) - public ResponseEntity handleInternalError(final NakadiRuntimeBaseException exception, + @ExceptionHandler(NakadiBaseException.class) + public ResponseEntity handleInternalError(final NakadiBaseException exception, final NativeWebRequest request) { LOG.error("Unexpected problem occurred", exception); return Responses.create(Response.Status.INTERNAL_SERVER_ERROR, exception.getMessage(), request); diff --git a/src/main/java/org/zalando/nakadi/controller/PartitionsController.java b/src/main/java/org/zalando/nakadi/controller/PartitionsController.java index 0ad3c3c899..19e37ac713 100644 --- a/src/main/java/org/zalando/nakadi/controller/PartitionsController.java +++ b/src/main/java/org/zalando/nakadi/controller/PartitionsController.java @@ -21,7 +21,7 @@ import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; @@ -163,7 +163,7 @@ private CursorLag getCursorLag(final String eventTypeName, final String partitio .stream() .findFirst() .map(this::toCursorLag) - .orElseThrow(NakadiRuntimeBaseException::new); + .orElseThrow(NakadiBaseException::new); } private EventTypePartitionView getTopicPartition(final String eventTypeName, final String partition) diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index 0c844ce23c..b8d0faa9b8 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -18,7 +18,7 @@ import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.exceptions.runtime.DuplicatedSubscriptionException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.SubscriptionUpdateConflictException; @@ -121,7 +121,7 @@ private ResponseEntity prepareLocationResponse(final Subscription subscriptio @ExceptionHandler({ WrongInitialCursorsException.class, TooManyPartitionsException.class}) - public ResponseEntity handleUnprocessableSubscription(final NakadiRuntimeBaseException exception, + public ResponseEntity handleUnprocessableSubscription(final NakadiBaseException exception, final NativeWebRequest request) { LOG.debug("Error occurred when working with subscriptions", exception); return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, exception.getMessage(), request); diff --git a/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java b/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java index a216f31243..a3881b87f9 100644 --- a/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java +++ b/src/main/java/org/zalando/nakadi/domain/NakadiCursor.java @@ -2,7 +2,7 @@ import com.google.common.base.Preconditions; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.repository.kafka.KafkaCursor; import java.util.Objects; @@ -118,7 +118,7 @@ public static NakadiCursor of(final Timeline timeline, final String partition, f case KAFKA: return new NakadiKafkaCursor(timeline, partition, offset); default: - throw new NakadiRuntimeBaseException( + throw new NakadiBaseException( "Cursor storage type " + timeline.getStorage().getType() + " not supported"); } } diff --git a/src/main/java/org/zalando/nakadi/exceptions/Try.java b/src/main/java/org/zalando/nakadi/exceptions/Try.java index 0a4865e580..9b0cac27c4 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/Try.java +++ b/src/main/java/org/zalando/nakadi/exceptions/Try.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import java.util.Optional; @@ -98,8 +98,8 @@ public boolean isSuccess() { public T getOrThrow() { if (exception instanceof NakadiRuntimeException) { throw (NakadiRuntimeException) exception; - } else if (exception instanceof NakadiRuntimeBaseException) { - throw (NakadiRuntimeBaseException) exception; + } else if (exception instanceof NakadiBaseException) { + throw (NakadiBaseException) exception; } throw new NakadiRuntimeException(exception); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/AccessDeniedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/AccessDeniedException.java index ce1c6211fe..c494b381f0 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/AccessDeniedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/AccessDeniedException.java @@ -3,7 +3,7 @@ import org.zalando.nakadi.plugin.api.authz.AuthorizationService; import org.zalando.nakadi.plugin.api.authz.Resource; -public class AccessDeniedException extends NakadiRuntimeBaseException { +public class AccessDeniedException extends NakadiBaseException { private final Resource resource; private final AuthorizationService.Operation operation; diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/CompactionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/CompactionException.java index e8bc1c0191..0555c78036 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/CompactionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/CompactionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class CompactionException extends NakadiRuntimeBaseException { +public class CompactionException extends NakadiBaseException { public CompactionException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/ConflictException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/ConflictException.java index 00ef12008e..97f12b1928 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/ConflictException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/ConflictException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class ConflictException extends NakadiRuntimeBaseException { +public class ConflictException extends NakadiBaseException { public ConflictException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/ConnectionSlotOccupiedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/ConnectionSlotOccupiedException.java index 3b92672363..fbbc93c47e 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/ConnectionSlotOccupiedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/ConnectionSlotOccupiedException.java @@ -1,4 +1,4 @@ package org.zalando.nakadi.exceptions.runtime; -public class ConnectionSlotOccupiedException extends NakadiRuntimeBaseException { +public class ConnectionSlotOccupiedException extends NakadiBaseException { } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorConversionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorConversionException.java index 430893252c..cf9bf7ed0b 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorConversionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorConversionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class CursorConversionException extends NakadiRuntimeBaseException { +public class CursorConversionException extends NakadiBaseException { public CursorConversionException(final String message, final Exception e) { super(message, e); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorsAreEmptyException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorsAreEmptyException.java index a47d48deb4..58dd633a7a 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorsAreEmptyException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/CursorsAreEmptyException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class CursorsAreEmptyException extends NakadiRuntimeBaseException { +public class CursorsAreEmptyException extends NakadiBaseException { public CursorsAreEmptyException() { super("Cursors are empty"); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/DbWriteOperationsBlockedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/DbWriteOperationsBlockedException.java index 470810556f..9352601c13 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/DbWriteOperationsBlockedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/DbWriteOperationsBlockedException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class DbWriteOperationsBlockedException extends NakadiRuntimeBaseException { +public class DbWriteOperationsBlockedException extends NakadiBaseException { public DbWriteOperationsBlockedException(final String message) { super(message); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedEventTypeNameException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedEventTypeNameException.java index 77d25022e6..10be80f2aa 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedEventTypeNameException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedEventTypeNameException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class DuplicatedEventTypeNameException extends NakadiRuntimeBaseException { +public class DuplicatedEventTypeNameException extends NakadiBaseException { public DuplicatedEventTypeNameException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedStorageException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedStorageException.java index 3523046baf..ca2464b93e 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedStorageException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedStorageException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class DuplicatedStorageException extends NakadiRuntimeBaseException { +public class DuplicatedStorageException extends NakadiBaseException { public DuplicatedStorageException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedSubscriptionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedSubscriptionException.java index 2851397946..4f1e7b03dc 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedSubscriptionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedSubscriptionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class DuplicatedSubscriptionException extends NakadiRuntimeBaseException { +public class DuplicatedSubscriptionException extends NakadiBaseException { public DuplicatedSubscriptionException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedTimelineException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedTimelineException.java index 06613132a0..848ce0641a 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedTimelineException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/DuplicatedTimelineException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class DuplicatedTimelineException extends NakadiRuntimeBaseException { +public class DuplicatedTimelineException extends NakadiBaseException { public DuplicatedTimelineException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EnrichmentException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EnrichmentException.java index efeaba01fa..990902975f 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EnrichmentException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EnrichmentException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EnrichmentException extends NakadiRuntimeBaseException { +public class EnrichmentException extends NakadiBaseException { public EnrichmentException(final String msg, final Exception cause) { super(msg, cause); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/ErrorGettingCursorTimeLagException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/ErrorGettingCursorTimeLagException.java index 36b8ffc3c9..0af37e820c 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/ErrorGettingCursorTimeLagException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/ErrorGettingCursorTimeLagException.java @@ -2,7 +2,7 @@ import org.zalando.nakadi.domain.NakadiCursor; -public class ErrorGettingCursorTimeLagException extends NakadiRuntimeBaseException { +public class ErrorGettingCursorTimeLagException extends NakadiBaseException { private final NakadiCursor failedCursor; diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventPublishingException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventPublishingException.java index a079a8b6a4..e0bc7d82b0 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventPublishingException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventPublishingException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventPublishingException extends NakadiRuntimeBaseException { +public class EventPublishingException extends NakadiBaseException { public EventPublishingException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeDeletionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeDeletionException.java index 040b72e1df..a9ff52d056 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeDeletionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeDeletionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventTypeDeletionException extends NakadiRuntimeBaseException { +public class EventTypeDeletionException extends NakadiBaseException { public EventTypeDeletionException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeOptionsValidationException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeOptionsValidationException.java index c58f7fab04..c26a5a92ce 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeOptionsValidationException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeOptionsValidationException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventTypeOptionsValidationException extends NakadiRuntimeBaseException { +public class EventTypeOptionsValidationException extends NakadiBaseException { public EventTypeOptionsValidationException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeTimeoutException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeTimeoutException.java index 4e5a24bfa3..3cabc9d821 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeTimeoutException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeTimeoutException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventTypeTimeoutException extends NakadiRuntimeBaseException { +public class EventTypeTimeoutException extends NakadiBaseException { public EventTypeTimeoutException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeUnavailableException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeUnavailableException.java index 263d3c8c04..f6e06c4699 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeUnavailableException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventTypeUnavailableException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventTypeUnavailableException extends NakadiRuntimeBaseException { +public class EventTypeUnavailableException extends NakadiBaseException { public EventTypeUnavailableException(final String message) { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventValidationException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventValidationException.java index a67a4b79e5..4ff1ad7093 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/EventValidationException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/EventValidationException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class EventValidationException extends NakadiRuntimeBaseException { +public class EventValidationException extends NakadiBaseException { public EventValidationException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/FeatureNotAvailableException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/FeatureNotAvailableException.java index 0d50d39bc6..fa968c1c73 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/FeatureNotAvailableException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/FeatureNotAvailableException.java @@ -2,7 +2,7 @@ import org.zalando.nakadi.service.FeatureToggleService; -public class FeatureNotAvailableException extends NakadiRuntimeBaseException { +public class FeatureNotAvailableException extends NakadiBaseException { private final FeatureToggleService.Feature feature; public FeatureNotAvailableException(final String message, final FeatureToggleService.Feature feature) { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/IllegalClientIdException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/IllegalClientIdException.java index 9ddd952efd..8c3c0bc518 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/IllegalClientIdException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/IllegalClientIdException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class IllegalClientIdException extends NakadiRuntimeBaseException { +public class IllegalClientIdException extends NakadiBaseException { public IllegalClientIdException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InconsistentStateException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InconsistentStateException.java index 138b1c3e74..98b4b62edc 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/InconsistentStateException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InconsistentStateException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class InconsistentStateException extends NakadiRuntimeBaseException { +public class InconsistentStateException extends NakadiBaseException { public InconsistentStateException(final String msg, final Throwable cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InternalNakadiException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InternalNakadiException.java index ccc73816a7..66c5ae64f5 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/InternalNakadiException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InternalNakadiException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class InternalNakadiException extends NakadiRuntimeBaseException { +public class InternalNakadiException extends NakadiBaseException { public InternalNakadiException(final String message) { super(message); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorException.java index 1e53656644..19db439a9e 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorException.java @@ -4,7 +4,7 @@ import org.zalando.nakadi.domain.NakadiCursor; import org.zalando.nakadi.view.Cursor; -public class InvalidCursorException extends NakadiRuntimeBaseException { +public class InvalidCursorException extends NakadiBaseException { private final CursorError error; private final Cursor cursor; diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorOperation.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorOperation.java index c7b653891c..e997909a16 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorOperation.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidCursorOperation.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class InvalidCursorOperation extends NakadiRuntimeBaseException { +public class InvalidCursorOperation extends NakadiBaseException { private final Reason reason; public enum Reason { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidEventTypeException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidEventTypeException.java index ae18bbd44e..d3780de91f 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidEventTypeException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidEventTypeException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class InvalidEventTypeException extends NakadiRuntimeBaseException { +public class InvalidEventTypeException extends NakadiBaseException { public InvalidEventTypeException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidLimitException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidLimitException.java index 6b36ed013c..707345cc15 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidLimitException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidLimitException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class InvalidLimitException extends NakadiRuntimeBaseException { +public class InvalidLimitException extends NakadiBaseException { public InvalidLimitException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidStreamIdException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidStreamIdException.java index 795f8338c7..f7316272b7 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidStreamIdException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidStreamIdException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class InvalidStreamIdException extends NakadiRuntimeBaseException { +public class InvalidStreamIdException extends NakadiBaseException { private final String streamId; diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/LimitReachedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/LimitReachedException.java index af2c96cb33..9c1f02b129 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/LimitReachedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/LimitReachedException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class LimitReachedException extends NakadiRuntimeBaseException { +public class LimitReachedException extends NakadiBaseException { public LimitReachedException(final String msg, final Throwable cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiRuntimeBaseException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiBaseException.java similarity index 53% rename from src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiRuntimeBaseException.java rename to src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiBaseException.java index 163df2d624..a3ca3a8ab1 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiRuntimeBaseException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NakadiBaseException.java @@ -4,16 +4,16 @@ * Parent class for Nakadi runtime exceptions * Name NakadiRuntimeException was already taken for some kind of wrapper. This name is a nice alternative ;) */ -public class NakadiRuntimeBaseException extends RuntimeException { +public class NakadiBaseException extends RuntimeException { - public NakadiRuntimeBaseException() { + public NakadiBaseException() { } - public NakadiRuntimeBaseException(final String message) { + public NakadiBaseException(final String message) { super(message); } - public NakadiRuntimeBaseException(final String message, final Throwable cause) { + public NakadiBaseException(final String message, final Throwable cause) { super(message, cause); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoConnectionSlotsException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoConnectionSlotsException.java index 5f4b849452..deb22eef1c 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoConnectionSlotsException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoConnectionSlotsException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NoConnectionSlotsException extends NakadiRuntimeBaseException { +public class NoConnectionSlotsException extends NakadiBaseException { public NoConnectionSlotsException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStreamingSlotsAvailable.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStreamingSlotsAvailable.java index 16d71735fe..9d99abccb1 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStreamingSlotsAvailable.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoStreamingSlotsAvailable.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NoStreamingSlotsAvailable extends NakadiRuntimeBaseException { +public class NoStreamingSlotsAvailable extends NakadiBaseException { public NoStreamingSlotsAvailable(final int totalSlots) { super("No free slots for streaming available. Total slots: " + totalSlots); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchEventTypeException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchEventTypeException.java index e4966d213d..cd7e33a8ee 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchEventTypeException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchEventTypeException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NoSuchEventTypeException extends NakadiRuntimeBaseException { +public class NoSuchEventTypeException extends NakadiBaseException { public NoSuchEventTypeException(final String message) { super(message); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchPartitionStrategyException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchPartitionStrategyException.java index 6e56dfbfb9..5325918097 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchPartitionStrategyException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchPartitionStrategyException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NoSuchPartitionStrategyException extends NakadiRuntimeBaseException { +public class NoSuchPartitionStrategyException extends NakadiBaseException { public NoSuchPartitionStrategyException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSchemaException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSchemaException.java index a8824d12d1..970878344f 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSchemaException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSchemaException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NoSuchSchemaException extends NakadiRuntimeBaseException { +public class NoSuchSchemaException extends NakadiBaseException { public NoSuchSchemaException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchStorageException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchStorageException.java index 0cf65f11c9..9a23e92c53 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchStorageException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchStorageException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NoSuchStorageException extends NakadiRuntimeBaseException { +public class NoSuchStorageException extends NakadiBaseException { public NoSuchStorageException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSubscriptionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSubscriptionException.java index 235f111b03..a57c48923a 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSubscriptionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NoSuchSubscriptionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NoSuchSubscriptionException extends NakadiRuntimeBaseException { +public class NoSuchSubscriptionException extends NakadiBaseException { public NoSuchSubscriptionException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/NotFoundException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/NotFoundException.java index b6ba3f2a18..b82bc85156 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/NotFoundException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/NotFoundException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class NotFoundException extends NakadiRuntimeBaseException { +public class NotFoundException extends NakadiBaseException { public NotFoundException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationInterruptedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationInterruptedException.java index 19a47d4274..4f864604cb 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationInterruptedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationInterruptedException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class OperationInterruptedException extends NakadiRuntimeBaseException { +public class OperationInterruptedException extends NakadiBaseException { public OperationInterruptedException(final String message, final Throwable cause) { super(message, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationTimeoutException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationTimeoutException.java index 17b469573b..af27d03f5b 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationTimeoutException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/OperationTimeoutException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class OperationTimeoutException extends NakadiRuntimeBaseException { +public class OperationTimeoutException extends NakadiBaseException { public OperationTimeoutException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/PartitioningException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/PartitioningException.java index e433b6017e..a786f729e1 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/PartitioningException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/PartitioningException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class PartitioningException extends NakadiRuntimeBaseException { +public class PartitioningException extends NakadiBaseException { public PartitioningException(final String message) { super(message); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/RebalanceConflictException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/RebalanceConflictException.java index 46147b8dcd..0b476eebc7 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/RebalanceConflictException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/RebalanceConflictException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class RebalanceConflictException extends NakadiRuntimeBaseException { +public class RebalanceConflictException extends NakadiBaseException { public RebalanceConflictException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/RepositoryProblemException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/RepositoryProblemException.java index df029689ba..71856f93ce 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/RepositoryProblemException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/RepositoryProblemException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class RepositoryProblemException extends NakadiRuntimeBaseException { +public class RepositoryProblemException extends NakadiBaseException { public RepositoryProblemException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/RequestInProgressException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/RequestInProgressException.java index 0ed8671099..ad1fb4a960 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/RequestInProgressException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/RequestInProgressException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class RequestInProgressException extends NakadiRuntimeBaseException { +public class RequestInProgressException extends NakadiBaseException { public RequestInProgressException(final String message, final Throwable cause) { super(message, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/ServiceTemporarilyUnavailableException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/ServiceTemporarilyUnavailableException.java index 5e4106191f..80f187f1ae 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/ServiceTemporarilyUnavailableException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/ServiceTemporarilyUnavailableException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class ServiceTemporarilyUnavailableException extends NakadiRuntimeBaseException { +public class ServiceTemporarilyUnavailableException extends NakadiBaseException { public ServiceTemporarilyUnavailableException(final Exception cause) { super(cause.getMessage(), cause); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/StorageIsUsedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/StorageIsUsedException.java index 1a757ad266..11bfb92cc6 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/StorageIsUsedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/StorageIsUsedException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class StorageIsUsedException extends NakadiRuntimeBaseException { +public class StorageIsUsedException extends NakadiBaseException { public StorageIsUsedException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionPartitionConflictException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionPartitionConflictException.java index d20fb3dff8..c30b842657 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionPartitionConflictException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionPartitionConflictException.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.stream.Collectors; -public class SubscriptionPartitionConflictException extends NakadiRuntimeBaseException { +public class SubscriptionPartitionConflictException extends NakadiBaseException { private SubscriptionPartitionConflictException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java index 018b58ccf3..2a54ab8c27 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionUpdateConflictException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class SubscriptionUpdateConflictException extends NakadiRuntimeBaseException { +public class SubscriptionUpdateConflictException extends NakadiBaseException { public SubscriptionUpdateConflictException(final String message) { super(message); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimeLagStatsTimeoutException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimeLagStatsTimeoutException.java index c59bbf759b..2da65922dd 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimeLagStatsTimeoutException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimeLagStatsTimeoutException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TimeLagStatsTimeoutException extends NakadiRuntimeBaseException { +public class TimeLagStatsTimeoutException extends NakadiBaseException { public TimeLagStatsTimeoutException(final String msg, final Throwable cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelineException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelineException.java index 2852de605d..914c857872 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelineException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelineException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TimelineException extends NakadiRuntimeBaseException { +public class TimelineException extends NakadiBaseException { public TimelineException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelinesNotSupportedException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelinesNotSupportedException.java index d3ef47034f..4f7b71d74b 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelinesNotSupportedException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TimelinesNotSupportedException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TimelinesNotSupportedException extends NakadiRuntimeBaseException { +public class TimelinesNotSupportedException extends NakadiBaseException { public TimelinesNotSupportedException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TooManyPartitionsException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TooManyPartitionsException.java index 08a597f18b..fe0083491c 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TooManyPartitionsException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TooManyPartitionsException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TooManyPartitionsException extends NakadiRuntimeBaseException { +public class TooManyPartitionsException extends NakadiBaseException { public TooManyPartitionsException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicConfigException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicConfigException.java index 6a9c970f47..b9bcf80ae0 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicConfigException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicConfigException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TopicConfigException extends NakadiRuntimeBaseException { +public class TopicConfigException extends NakadiBaseException { public TopicConfigException(final String message, final Exception e) { super(message, e); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicCreationException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicCreationException.java index a4eaa41df2..87efdeb37e 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicCreationException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicCreationException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TopicCreationException extends NakadiRuntimeBaseException { +public class TopicCreationException extends NakadiBaseException { public TopicCreationException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicDeletionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicDeletionException.java index f247c672f5..e98c6f6362 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicDeletionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicDeletionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TopicDeletionException extends NakadiRuntimeBaseException { +public class TopicDeletionException extends NakadiBaseException { public TopicDeletionException(final String msg, final Exception cause) { super(msg, cause); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicRepositoryException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicRepositoryException.java index 09798fa6c5..afdfa62464 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicRepositoryException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/TopicRepositoryException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class TopicRepositoryException extends NakadiRuntimeBaseException { +public class TopicRepositoryException extends NakadiBaseException { public TopicRepositoryException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnableProcessException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnableProcessException.java index bd6e6f0d5c..93d9abda84 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnableProcessException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnableProcessException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class UnableProcessException extends NakadiRuntimeBaseException { +public class UnableProcessException extends NakadiBaseException { public UnableProcessException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownOperationException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownOperationException.java index 8c3ae410cc..1b30365196 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownOperationException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownOperationException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class UnknownOperationException extends NakadiRuntimeBaseException { +public class UnknownOperationException extends NakadiBaseException { public UnknownOperationException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownStorageTypeException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownStorageTypeException.java index cc9860bbd0..e292c6ec54 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownStorageTypeException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnknownStorageTypeException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class UnknownStorageTypeException extends NakadiRuntimeBaseException { +public class UnknownStorageTypeException extends NakadiBaseException { public UnknownStorageTypeException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnparseableCursorException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnparseableCursorException.java index 361f16a46d..62cef7f182 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnparseableCursorException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnparseableCursorException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class UnparseableCursorException extends NakadiRuntimeBaseException { +public class UnparseableCursorException extends NakadiBaseException { private final String cursors; public UnparseableCursorException(final String msg, final Exception cause, final String cursors) { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java index 8218cacdf6..3ec1f5cd01 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class UnprocessableSubscriptionException extends NakadiRuntimeBaseException { +public class UnprocessableSubscriptionException extends NakadiBaseException { public UnprocessableSubscriptionException(String message) { super(message); } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongInitialCursorsException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongInitialCursorsException.java index 8155f8a8c0..2684c20ca8 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongInitialCursorsException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongInitialCursorsException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class WrongInitialCursorsException extends NakadiRuntimeBaseException { +public class WrongInitialCursorsException extends NakadiBaseException { public WrongInitialCursorsException(final String msg) { super(msg); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongStreamParametersException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongStreamParametersException.java index cd99b213d8..13f390f222 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongStreamParametersException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/WrongStreamParametersException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class WrongStreamParametersException extends NakadiRuntimeBaseException { +public class WrongStreamParametersException extends NakadiBaseException { public WrongStreamParametersException(final String message) { super(message); diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/ZookeeperException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/ZookeeperException.java index a57ee45af4..6592bd6bb1 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/ZookeeperException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/ZookeeperException.java @@ -1,6 +1,6 @@ package org.zalando.nakadi.exceptions.runtime; -public class ZookeeperException extends NakadiRuntimeBaseException { +public class ZookeeperException extends NakadiBaseException { public ZookeeperException(final String message, final Throwable cause) { super(message, cause); diff --git a/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java b/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java index 6c144f6280..c58f81f1c1 100644 --- a/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java +++ b/src/main/java/org/zalando/nakadi/service/CursorOperationsService.java @@ -13,7 +13,7 @@ import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.UnknownStorageTypeException; import org.zalando.nakadi.repository.kafka.KafkaCursor; @@ -108,7 +108,7 @@ public List cursorsLag(final String eventTypeName, final List getTimeLags(final Collection(listeners.keySet())); - } catch (final NakadiRuntimeException | NakadiRuntimeBaseException ex) { + } catch (final NakadiRuntimeException | NakadiBaseException ex) { // In order not to stuck here one will just log this exception, without rethrowing getLog().error("Failed to transfer partitions when leaving ClosingState", ex); } finally { diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java index f1160cf276..dcb559b451 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/AbstractZkSubscriptionClient.java @@ -12,9 +12,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.zalando.nakadi.domain.EventTypePartition; +import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.UnableProcessException; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; import org.zalando.nakadi.exceptions.runtime.OperationInterruptedException; import org.zalando.nakadi.exceptions.runtime.OperationTimeoutException; import org.zalando.nakadi.exceptions.runtime.RequestInProgressException; @@ -112,7 +112,7 @@ public final T runLocked(final Callable function) { throw releaseException; } return result; - } catch (final NakadiRuntimeException | NakadiRuntimeBaseException e) { + } catch (final NakadiRuntimeException | NakadiBaseException e) { throw e; } catch (final Exception e) { throw new NakadiRuntimeException(e); diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionNotInitializedException.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionNotInitializedException.java index 5cf82a40b2..8e4fdd384f 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionNotInitializedException.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/SubscriptionNotInitializedException.java @@ -1,8 +1,8 @@ package org.zalando.nakadi.service.subscription.zk; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; -public class SubscriptionNotInitializedException extends NakadiRuntimeBaseException { +public class SubscriptionNotInitializedException extends NakadiBaseException { public SubscriptionNotInitializedException(final String subscriptionId) { super("Subscription " + subscriptionId + " is not initialized"); diff --git a/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java b/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java index 170268ec24..13dfc3f223 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/zk/ZkSubscriptionClient.java @@ -4,7 +4,7 @@ import org.apache.commons.codec.binary.Hex; import org.zalando.nakadi.domain.EventTypePartition; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeBaseException; +import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.exceptions.runtime.OperationTimeoutException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.ZookeeperException; @@ -214,7 +214,7 @@ public Topology withUpdatedPartitions(final String newHash, final Partition[] pa } } if (selectedIdx < 0) { - throw new NakadiRuntimeBaseException( + throw new NakadiBaseException( "Failed to find partition " + newValue.getKey() + " in " + this); } resultPartitions[selectedIdx] = newValue; diff --git a/src/test/java/org/zalando/nakadi/repository/kafka/NakadiKafkaConsumerTest.java b/src/test/java/org/zalando/nakadi/repository/kafka/NakadiKafkaConsumerTest.java index c72ee907d6..aa300d797b 100644 --- a/src/test/java/org/zalando/nakadi/repository/kafka/NakadiKafkaConsumerTest.java +++ b/src/test/java/org/zalando/nakadi/repository/kafka/NakadiKafkaConsumerTest.java @@ -177,7 +177,7 @@ public void whenReadEventsThenNakadiRuntimeBaseException() { } } - assertThat("We should get a NakadiRuntimeBaseException for every call", + assertThat("We should get a NakadiBaseException for every call", numberOfNakadiRuntimeBaseExceptions, equalTo(exceptions.size())); } From 465e53f6b9fbc9cad6ec14b69ea1ade3c8066c55 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 17:00:04 +0200 Subject: [PATCH 084/176] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a59bc351ca..ffffc21087 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Upgraded dependencies +- Refactored exceptions ## [2.8.3] - 2018-08-01 From ade79f3e41327daa948ecef5b7412917cbf779fe Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Mon, 20 Aug 2018 17:06:49 +0200 Subject: [PATCH 085/176] checkstyle --- .../exceptions/runtime/UnprocessableSubscriptionException.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java index 3ec1f5cd01..73df3e051e 100644 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableSubscriptionException.java @@ -1,7 +1,7 @@ package org.zalando.nakadi.exceptions.runtime; public class UnprocessableSubscriptionException extends NakadiBaseException { - public UnprocessableSubscriptionException(String message) { + public UnprocessableSubscriptionException(final String message) { super(message); } } From 43be24ba64d52360601d1c9dae4fa1701b0b8cd1 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Tue, 21 Aug 2018 10:30:55 +0200 Subject: [PATCH 086/176] newline --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0888a31a7b..dc1e19759e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @zalando/team-nakadi \ No newline at end of file +* @zalando/team-nakadi From 51d2e1eaf767024a1192aa9552d3fb072c4d1b5e Mon Sep 17 00:00:00 2001 From: Andrey Dyachkov Date: Mon, 27 Aug 2018 12:01:46 +0200 Subject: [PATCH 087/176] removed newline from warning message --- .../org/zalando/nakadi/controller/EventTypeController.java | 2 +- src/main/resources/application.yml | 4 ++-- .../zalando/nakadi/controller/EventTypeControllerTest.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index a49baef82a..49a1929482 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -163,7 +163,7 @@ private HttpHeaders generateWarningHeaders(final EventTypeBase eventType) { } final String warningMessage = warnings.stream() - .filter(s -> !s.isEmpty()).collect(Collectors.joining("\n")); + .filter(s -> !s.isEmpty()).collect(Collectors.joining(". ")); if (!warnings.isEmpty()) { headers.add(HttpHeaders.WARNING, diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index a2a303caff..f924b588a6 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -36,7 +36,7 @@ nakadi: admin.default: dataType: service value: stups_nakadi - authz.warnAllDataAccessMessage: "" + authz.warnAllDataAccessMessage: "Data access warning" topic: min: retentionMs: 86400000 # 1 days @@ -52,7 +52,7 @@ nakadi: rotationMs: 10800000 # 3 hours segmentBytes: 1073741824 # 1 GB compactionLagMs: 10800000 # 3 hours - warnMessage: "" + warnMessage: "Compaction warning" stream: timeoutMs: 31536000000 # 1 year :-P default.commitTimeout: 60 # 1 minute diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java index 7387ed3aee..33c08540c3 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java @@ -134,7 +134,7 @@ public void whenPostLogCompactedEventTypeThenWarning() throws Exception { eventType.setCleanupPolicy(CleanupPolicy.COMPACT); eventType.getSchema().setSchema("{}"); postEventType(eventType).andExpect(status().isCreated()).andExpect( - header().string("Warning", "299 nakadi \"I am warning you\nI am warning you, even more\"")); + header().string("Warning", "299 nakadi \"I am warning you. I am warning you, even more\"")); } @Test From 513a43781259df45f58ed70b11184eccec8f66f4 Mon Sep 17 00:00:00 2001 From: Andrey Dyachkov Date: Tue, 28 Aug 2018 12:11:25 +0200 Subject: [PATCH 088/176] enable multiple forward slashes reject --- .../nakadi/config/SecurityConfiguration.java | 137 ------------------ 1 file changed, 137 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java index 81b10df382..e2ec571431 100644 --- a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java +++ b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java @@ -199,141 +199,4 @@ public String getDetail() { } } - // TODO: REMOVE IT AFTER EVERYONE HAS NORMALIZED THEIR URLS - @Bean - public HttpFirewall allowUrlEncodedSlashHttpFirewall() { - return new AllowForwardSlashesStrictHttpFirewall(); - } - - // TODO: REMOVE IT AFTER EVERYONE HAS NORMALIZED THEIR URLS - private static class AllowForwardSlashesStrictHttpFirewall extends StrictHttpFirewall { - - private static final String ENCODED_PERCENT = "%25"; - private static final String PERCENT = "%"; - private static final List FORBIDDEN_ENCODED_PERIOD = - Collections.unmodifiableList(Arrays.asList("%2e", "%2E")); - private Set encodedUrlBlacklist = new HashSet<>(); - private Set decodedUrlBlacklist = new HashSet<>(); - - AllowForwardSlashesStrictHttpFirewall() { - super(); - this.encodedUrlBlacklist.add(ENCODED_PERCENT); - this.encodedUrlBlacklist.addAll(FORBIDDEN_ENCODED_PERIOD); - this.decodedUrlBlacklist.add(PERCENT); - } - - private static boolean containsOnlyPrintableAsciiCharacters(final String uri) { - final int length = uri.length(); - for (int i = 0; i < length; i++) { - final char c = uri.charAt(i); - if (c < '\u0020' || c > '\u007e') { - return false; - } - } - - return true; - } - - private static boolean encodedUrlContains(final HttpServletRequest request, final String value) { - if (valueContains(request.getContextPath(), value)) { - return true; - } - return valueContains(request.getRequestURI(), value); - } - - private static boolean decodedUrlContains(final HttpServletRequest request, final String value) { - if (valueContains(request.getServletPath(), value)) { - return true; - } - if (valueContains(request.getPathInfo(), value)) { - return true; - } - return false; - } - - private static boolean valueContains(final String value, final String contains) { - return value != null && value.contains(contains); - } - - @Override - public FirewalledRequest getFirewalledRequest(final HttpServletRequest request) - throws RequestRejectedException { - rejectedBlacklistedUrls(request); - - if (!isNormalized(request)) { - throw new RequestRejectedException("The request was rejected because the URL was not normalized."); - } - - final String requestUri = request.getRequestURI(); - if (!containsOnlyPrintableAsciiCharacters(requestUri)) { - throw new RequestRejectedException("The requestURI was rejected because it can only " + - "contain printable ASCII characters."); - } - return new FirewalledRequest(request) { - @Override - public void reset() { - } - }; - } - - private static boolean isNormalized(final HttpServletRequest request) { - if (!isNormalized(request.getRequestURI())) { - return false; - } - if (!isNormalized(request.getContextPath())) { - return false; - } - if (!isNormalized(request.getServletPath())) { - return false; - } - if (!isNormalized(request.getPathInfo())) { - return false; - } - return true; - } - - private static boolean isNormalized(final String path) { - if (path == null) { - return true; - } - - // ONLY THIS PART IS REMOVED, ALL OTHER CODE IS THE SAME AS IN StrictHttpFirewall - // if (path.indexOf("//") > -1) { - // return false; - // } - - for (int j = path.length(); j > 0;) { - final int i = path.lastIndexOf('/', j - 1); - final int gap = j - i; - - if (gap == 2 && path.charAt(i + 1) == '.') { - // ".", "/./" or "/." - return false; - } else if (gap == 3 && path.charAt(i + 1) == '.' && path.charAt(i + 2) == '.') { - return false; - } - - j = i; - } - - return true; - } - - private void rejectedBlacklistedUrls(final HttpServletRequest request) { - for (final String forbidden : this.encodedUrlBlacklist) { - if (encodedUrlContains(request, forbidden)) { - throw new RequestRejectedException("The request was rejected because the URL contained " + - "a potentially malicious String \"" + forbidden + "\""); - } - } - for (final String forbidden : this.decodedUrlBlacklist) { - if (decodedUrlContains(request, forbidden)) { - throw new RequestRejectedException("The request was rejected because the URL contained " + - "a potentially malicious String \"" + forbidden + "\""); - } - } - } - - } - } From 36db745fae4c84e7d0f0e5316242726eeb9fe87a Mon Sep 17 00:00:00 2001 From: Andrey Dyachkov Date: Tue, 28 Aug 2018 12:52:38 +0200 Subject: [PATCH 089/176] removed unused imports --- .../zalando/nakadi/config/SecurityConfiguration.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java index e2ec571431..012995bd59 100644 --- a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java +++ b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java @@ -4,7 +4,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpOutputMessage; import org.springframework.http.converter.HttpMessageConverter; @@ -20,22 +19,13 @@ import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; -import org.springframework.security.web.firewall.FirewalledRequest; -import org.springframework.security.web.firewall.HttpFirewall; -import org.springframework.security.web.firewall.RequestRejectedException; -import org.springframework.security.web.firewall.StrictHttpFirewall; import org.zalando.stups.oauth2.spring.security.expression.ExtendedOAuth2WebSecurityExpressionHandler; -import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.Response; import java.io.IOException; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; import java.util.List; -import java.util.Set; import static org.springframework.http.HttpMethod.DELETE; import static org.springframework.http.HttpMethod.GET; From a641102fb6a7251967f788d487003852451c92c8 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Wed, 29 Aug 2018 10:59:09 +0200 Subject: [PATCH 090/176] ARUHA-1854 Introduce ordering_instance_ids. --- docs/_data/nakadi-event-bus-api.yaml | 16 ++++++++++++++++ .../zalando/nakadi/domain/EventTypeBase.java | 18 ++++++++++++++++-- .../nakadi/service/EventTypeService.java | 11 ++++++----- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/docs/_data/nakadi-event-bus-api.yaml b/docs/_data/nakadi-event-bus-api.yaml index c2487091fe..49d93dd6a2 100644 --- a/docs/_data/nakadi-event-bus-api.yaml +++ b/docs/_data/nakadi-event-bus-api.yaml @@ -2635,6 +2635,22 @@ definitions: expected to notify consumer in advance about the change. example: "data.incremental_counter" + ordering_instance_ids: + type: array + description: | + This is only an informational field. + + Specifies array of fields that are used to be event identifier. + + This field can be modified at any moment, but event type owners are expected to notify consumer in advance + about the change. + items: + type: string + description: | + Indicates a single instance id field. This is a dot separated string, which is applied onto the whole event + object, including the contained metadata and data (in case of data change event). + + The field must be present in the schema. audience: type: string x-extensible-enum: diff --git a/src/main/java/org/zalando/nakadi/domain/EventTypeBase.java b/src/main/java/org/zalando/nakadi/domain/EventTypeBase.java index 029f9d6822..e552ee548e 100644 --- a/src/main/java/org/zalando/nakadi/domain/EventTypeBase.java +++ b/src/main/java/org/zalando/nakadi/domain/EventTypeBase.java @@ -48,6 +48,9 @@ public class EventTypeBase { @Nullable private List orderingKeyFields; + @Nullable + private List orderingInstanceIds; + @Valid @NotNull private EventTypeSchemaBase schema; @@ -78,12 +81,14 @@ public EventTypeBase() { this.cleanupPolicy = CleanupPolicy.DELETE; } - public EventTypeBase(final String name, final String owningApplication, + public EventTypeBase(final String name, + final String owningApplication, final EventCategory category, final List validationStrategies, final List enrichmentStrategies, final String partitionStrategy, - final List partitionKeyFields, final EventTypeSchemaBase schema, + final List partitionKeyFields, + final EventTypeSchemaBase schema, final EventTypeStatistics defaultStatistic, final EventTypeOptions options, final CompatibilityMode compatibilityMode, @@ -117,6 +122,7 @@ public EventTypeBase(final EventTypeBase eventType) { this.setAuthorization(eventType.getAuthorization()); this.setAudience(eventType.getAudience()); this.setOrderingKeyFields(eventType.getOrderingKeyFields()); + this.setOrderingInstanceIds(eventType.getOrderingInstanceIds()); this.setCleanupPolicy(eventType.getCleanupPolicy()); } @@ -196,6 +202,14 @@ public void setOrderingKeyFields(@Nullable final List orderingKeyFields) this.orderingKeyFields = orderingKeyFields; } + public List getOrderingInstanceIds() { + return unmodifiableList(orderingInstanceIds != null ? orderingInstanceIds : EMPTY_ORDERING_KEY_FIELDS); + } + + public void setOrderingInstanceIds(@Nullable final List orderingInstanceIds) { + this.orderingInstanceIds = orderingInstanceIds; + } + public List getEnrichmentStrategies() { return enrichmentStrategies; } diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 1fba1e7585..9d7d48cb80 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -509,7 +509,8 @@ private void validateSchema(final EventTypeBase eventType) throws InvalidEventTy throw new InvalidEventTypeException("\"metadata\" property is reserved"); } - validateOrderingKeys(schema, eventType); + validateFieldsInSchema("ordering_key_fields", eventType.getOrderingKeyFields(), schema); + validateFieldsInSchema("ordering_instance_ids", eventType.getOrderingInstanceIds(), schema); if (eventType.getCompatibilityMode() == CompatibilityMode.COMPATIBLE) { validateJsonSchemaConstraints(schemaAsJson); @@ -531,16 +532,16 @@ private void validateJsonSchemaConstraints(final JSONObject schema) throws Inval } } - private void validateOrderingKeys(final Schema schema, final EventTypeBase eventType) - throws InvalidEventTypeException, JSONException, SchemaException { - final List absentFields = eventType.getOrderingKeyFields().stream() + private void validateFieldsInSchema(final String fieldName, final List fields, final Schema schema) { + final List absentFields = fields.stream() .filter(field -> !schema.definesProperty(convertToJSONPointer(field))) .collect(Collectors.toList()); if (!absentFields.isEmpty()) { - throw new InvalidEventTypeException("ordering_key_fields " + absentFields + " absent in schema"); + throw new InvalidEventTypeException(fieldName + " " + absentFields + " absent in schema"); } } + private String convertToJSONPointer(final String value) { return value.replaceAll("\\.", "/"); } From 4e3c454dc3308c255fa8a1ae2b3089b394b8b341 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Wed, 29 Aug 2018 15:54:54 +0200 Subject: [PATCH 091/176] Remove Problem from EventTypeService --- .../nakadi/controller/EventTypeController.java | 8 ++------ .../nakadi/controller/SchemaController.java | 12 +++--------- .../nakadi/service/EventTypeService.java | 17 +++-------------- .../nakadi/controller/SchemaControllerTest.java | 14 +++++++------- 4 files changed, 15 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index 321229d212..fdba2a6176 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -41,7 +41,6 @@ import org.zalando.nakadi.service.AdminService; import org.zalando.nakadi.service.EventTypeService; import org.zalando.nakadi.service.FeatureToggleService; -import org.zalando.nakadi.service.Result; import org.zalando.problem.Problem; import org.zalando.problem.spring.web.advice.Responses; @@ -146,11 +145,8 @@ public ResponseEntity update( @RequestMapping(value = "/{name:.+}", method = RequestMethod.GET) public ResponseEntity get(@PathVariable final String name, final NativeWebRequest request) { - final Result result = eventTypeService.get(name); - if (!result.isSuccessful()) { - return Responses.create(result.getProblem(), request); - } - return status(HttpStatus.OK).body(result.getValue()); + final EventType eventType = eventTypeService.get(name); + return status(HttpStatus.OK).body(eventType); } private HttpHeaders generateWarningHeaders(final EventTypeBase eventType) { diff --git a/src/main/java/org/zalando/nakadi/controller/SchemaController.java b/src/main/java/org/zalando/nakadi/controller/SchemaController.java index 32caa2c95f..e5c208d83d 100644 --- a/src/main/java/org/zalando/nakadi/controller/SchemaController.java +++ b/src/main/java/org/zalando/nakadi/controller/SchemaController.java @@ -33,10 +33,7 @@ public ResponseEntity getSchemas( @RequestParam(value = "offset", required = false, defaultValue = "0") final int offset, @RequestParam(value = "limit", required = false, defaultValue = "20") final int limit, final NativeWebRequest request) { - final Result eventTypeResult = eventTypeService.get(name); - if (!eventTypeResult.isSuccessful()) { - return Responses.create(eventTypeResult.getProblem(), request); - } + final EventType eventType = eventTypeService.get(name); final Result result = schemaService.getSchemas(name, offset, limit); if (result.isSuccessful()) { @@ -50,12 +47,9 @@ public ResponseEntity getSchemaVersion(@PathVariable("name") final String nam @PathVariable("version") final String version, final NativeWebRequest request) { if (version.equals("latest")) { // latest schema might be cached with the event type - final Result eventTypeResult = eventTypeService.get(name); - if (!eventTypeResult.isSuccessful()) { - return Responses.create(eventTypeResult.getProblem(), request); - } + final EventType eventType = eventTypeService.get(name); - return ResponseEntity.status(HttpStatus.OK).body(eventTypeResult.getValue().getSchema()); + return ResponseEntity.status(HttpStatus.OK).body(eventType.getSchema()); } final Result result = schemaService.getSchemaVersion(name, version); diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 8da0f8c2af..99670f0f1d 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -59,7 +59,6 @@ import org.zalando.nakadi.util.JsonUtils; import org.zalando.nakadi.validation.SchemaEvolutionService; import org.zalando.nakadi.validation.SchemaIncompatibility; -import org.zalando.problem.Problem; import java.io.Closeable; import java.io.IOException; @@ -70,8 +69,6 @@ import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DELETE_EVENT_TYPE_WITH_SUBSCRIPTIONS; @Component @@ -439,17 +436,9 @@ private void updateTopicRetentionTime(final String eventTypeName, final Long ret .setRetentionTime(timeline.getTopic(), retentionTime)); } - public Result get(final String eventTypeName) { - try { - final EventType eventType = eventTypeRepository.findByName(eventTypeName); - return Result.ok(eventType); - } catch (final NoSuchEventTypeException e) { - LOG.debug("Could not find EventType: {}", eventTypeName); - return Result.problem(Problem.valueOf(NOT_FOUND, e.getMessage())); - } catch (final InternalNakadiException e) { - LOG.error("Problem loading event type " + eventTypeName, e); - return Result.problem(Problem.valueOf(INTERNAL_SERVER_ERROR, e.getMessage())); - } + public EventType get(final String eventTypeName) throws NoSuchEventTypeException, InternalNakadiException { + final EventType eventType = eventTypeRepository.findByName(eventTypeName); + return eventType; } private Multimap deleteEventType(final String eventTypeName) diff --git a/src/test/java/org/zalando/nakadi/controller/SchemaControllerTest.java b/src/test/java/org/zalando/nakadi/controller/SchemaControllerTest.java index 3054348f45..73752f1448 100644 --- a/src/test/java/org/zalando/nakadi/controller/SchemaControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/SchemaControllerTest.java @@ -8,6 +8,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.domain.EventType; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.service.EventTypeService; import org.zalando.nakadi.service.Result; import org.zalando.nakadi.service.SchemaService; @@ -34,7 +35,7 @@ public void setUp() { @Test public void testSuccess() { Mockito.when(schemaService.getSchemas("et_test", 0, 1)).thenReturn(Result.ok(null)); - Mockito.when(eventTypeService.get("et_test")).thenReturn(Result.ok(EventTypeTestBuilder.builder().build())); + Mockito.when(eventTypeService.get("et_test")).thenReturn(EventTypeTestBuilder.builder().build()); final ResponseEntity result = new SchemaController(schemaService, eventTypeService) .getSchemas("et_test", 0, 1, nativeWebRequest); @@ -43,7 +44,7 @@ public void testSuccess() { @Test public void testFailure503() { - Mockito.when(eventTypeService.get("et_test")).thenReturn(Result.ok(EventTypeTestBuilder.builder().build())); + Mockito.when(eventTypeService.get("et_test")).thenReturn(EventTypeTestBuilder.builder().build()); Mockito.when(schemaService.getSchemas("et_test", 0, 1)) .thenReturn(Result.problem(Problem.valueOf(Response.Status.SERVICE_UNAVAILABLE))); final ResponseEntity result = @@ -55,7 +56,7 @@ public void testFailure503() { @Test public void testGetLatestSchemaVersionThen200() { final EventType eventType = buildDefaultEventType(); - Mockito.when(eventTypeService.get(eventType.getName())).thenReturn(Result.ok(eventType)); + Mockito.when(eventTypeService.get(eventType.getName())).thenReturn(eventType); final ResponseEntity result = new SchemaController(schemaService, eventTypeService) .getSchemaVersion(eventType.getName(), "latest", nativeWebRequest); @@ -63,15 +64,14 @@ public void testGetLatestSchemaVersionThen200() { Assert.assertEquals(eventType.getSchema().toString(), result.getBody().toString()); } - @Test + @Test(expected = NoSuchEventTypeException.class) public void testGetLatestSchemaVersionWrongEventTypeThen404() { Mockito.when(eventTypeService.get("et_wrong_event")) - .thenReturn(Result.problem(Problem.valueOf(Response.Status.NOT_FOUND))); + .thenThrow(new NoSuchEventTypeException("no event type")); final ResponseEntity result = new SchemaController(schemaService, eventTypeService) .getSchemaVersion("et_wrong_event", "latest", nativeWebRequest); - Assert.assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode()); } @Test @@ -97,7 +97,7 @@ public void testGetIllegalSchemaVersionThen404() { } public void testFailure404() { Mockito.when(eventTypeService.get("et_test")) - .thenReturn(Result.problem(Problem.valueOf(Response.Status.NOT_FOUND))); + .thenThrow(new NoSuchEventTypeException("no event type")); final ResponseEntity result = new SchemaController(schemaService, eventTypeService) .getSchemas("et_test", 0, 1, nativeWebRequest); From 9fa55a72acb6349770d086cadf9ebda9dab0504f Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Wed, 29 Aug 2018 16:56:44 +0200 Subject: [PATCH 092/176] Remove Result from SchemaService --- .../nakadi/controller/ExceptionHandling.java | 19 ++++++++ .../nakadi/controller/SchemaController.java | 21 +++------ .../InvalidVersionNumberException.java | 8 ++++ .../zalando/nakadi/service/SchemaService.java | 33 ++++++------- .../controller/SchemaControllerTest.java | 37 +-------------- .../nakadi/service/SchemaServiceTest.java | 46 ++++++------------- 6 files changed, 65 insertions(+), 99 deletions(-) create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidVersionNumberException.java diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 604042b162..2a3aeaed14 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -19,7 +19,9 @@ import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.IllegalClientIdException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; +import org.zalando.nakadi.exceptions.runtime.InvalidVersionNumberException; import org.zalando.nakadi.exceptions.runtime.LimitReachedException; import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; @@ -41,6 +43,7 @@ import javax.ws.rs.core.Response; +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static javax.ws.rs.core.Response.Status.CONFLICT; import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static javax.ws.rs.core.Response.Status.NOT_FOUND; @@ -259,4 +262,20 @@ public ResponseEntity handleUnprocessableSubscriptionException( LOG.debug(exception.getMessage()); return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } + + @ExceptionHandler(InvalidLimitException.class) + public ResponseEntity handleInvalidLimitException( + final InvalidLimitException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return Responses.create(BAD_REQUEST, exception.getMessage(), request); + } + + @ExceptionHandler(InvalidVersionNumberException.class) + public ResponseEntity handleInvalidVersionNumberException( + final InvalidVersionNumberException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return Responses.create(BAD_REQUEST, exception.getMessage(), request); + } } diff --git a/src/main/java/org/zalando/nakadi/controller/SchemaController.java b/src/main/java/org/zalando/nakadi/controller/SchemaController.java index e5c208d83d..cad9c36d32 100644 --- a/src/main/java/org/zalando/nakadi/controller/SchemaController.java +++ b/src/main/java/org/zalando/nakadi/controller/SchemaController.java @@ -10,10 +10,10 @@ import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.domain.EventTypeSchema; +import org.zalando.nakadi.domain.PaginationWrapper; +import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; import org.zalando.nakadi.service.EventTypeService; -import org.zalando.nakadi.service.Result; import org.zalando.nakadi.service.SchemaService; -import org.zalando.problem.spring.web.advice.Responses; @RestController public class SchemaController { @@ -32,14 +32,11 @@ public ResponseEntity getSchemas( @PathVariable("name") final String name, @RequestParam(value = "offset", required = false, defaultValue = "0") final int offset, @RequestParam(value = "limit", required = false, defaultValue = "20") final int limit, - final NativeWebRequest request) { + final NativeWebRequest request) throws InvalidLimitException { final EventType eventType = eventTypeService.get(name); - final Result result = schemaService.getSchemas(name, offset, limit); - if (result.isSuccessful()) { - return ResponseEntity.status(HttpStatus.OK).body(result.getValue()); - } - return Responses.create(result.getProblem(), request); + final PaginationWrapper schemas = schemaService.getSchemas(name, offset, limit); + return ResponseEntity.status(HttpStatus.OK).body(schemas); } @RequestMapping("/event-types/{name}/schemas/{version}") @@ -52,11 +49,7 @@ public ResponseEntity getSchemaVersion(@PathVariable("name") final String nam return ResponseEntity.status(HttpStatus.OK).body(eventType.getSchema()); } - final Result result = schemaService.getSchemaVersion(name, version); - if (!result.isSuccessful()) { - return Responses.create(result.getProblem(), request); - } - - return ResponseEntity.status(HttpStatus.OK).body(result.getValue()); + final EventTypeSchema result = schemaService.getSchemaVersion(name, version); + return ResponseEntity.status(HttpStatus.OK).body(result); } } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidVersionNumberException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidVersionNumberException.java new file mode 100644 index 0000000000..142938fdfe --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/InvalidVersionNumberException.java @@ -0,0 +1,8 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class InvalidVersionNumberException extends NakadiBaseException { + + public InvalidVersionNumberException(final String message) { + super(message); + } +} diff --git a/src/main/java/org/zalando/nakadi/service/SchemaService.java b/src/main/java/org/zalando/nakadi/service/SchemaService.java index 544159e1e4..7c86d97af3 100644 --- a/src/main/java/org/zalando/nakadi/service/SchemaService.java +++ b/src/main/java/org/zalando/nakadi/service/SchemaService.java @@ -5,11 +5,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.zalando.nakadi.domain.EventTypeSchema; +import org.zalando.nakadi.domain.PaginationWrapper; +import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; +import org.zalando.nakadi.exceptions.runtime.InvalidVersionNumberException; import org.zalando.nakadi.exceptions.runtime.NoSuchSchemaException; import org.zalando.nakadi.repository.db.SchemaRepository; -import org.zalando.problem.Problem; -import javax.ws.rs.core.Response; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -29,35 +30,29 @@ public SchemaService(final SchemaRepository schemaRepository, this.paginationService = paginationService; } - public Result getSchemas(final String name, final int offset, final int limit) { + public PaginationWrapper getSchemas(final String name, final int offset, final int limit) + throws InvalidLimitException { if (limit < 1 || limit > 1000) { - return Result.problem(Problem.valueOf(Response.Status.BAD_REQUEST, - "'limit' parameter should have value from 1 to 1000")); + throw new InvalidLimitException("'limit' parameter sholud have value between 1 and 1000"); } if (offset < 0) { - return Result.problem(Problem.valueOf(Response.Status.BAD_REQUEST, - "'offset' parameter can't be lower than 0")); + throw new InvalidLimitException("'offset' parameter can't be lower than 0"); } - return Result.ok(paginationService + return paginationService .paginate(offset, limit, String.format("/event-types/%s/schemas", name), (o, l) -> schemaRepository.getSchemas(name, o, l), - () -> schemaRepository.getSchemasCount(name))); + () -> schemaRepository.getSchemasCount(name)); } - public Result getSchemaVersion(final String name, final String version) { + public EventTypeSchema getSchemaVersion(final String name, final String version) + throws NoSuchSchemaException, InvalidVersionNumberException { final Matcher versionMatcher = VERSION_PATTERN.matcher(version); if (!versionMatcher.matches()) { - return Result.problem(Problem.valueOf(Response.Status.BAD_REQUEST, "Invalid version number")); - } - - try { - final EventTypeSchema schema = schemaRepository.getSchemaVersion(name, version); - return Result.ok(schema); - } catch (final NoSuchSchemaException e) { - LOG.debug("Could not find EventTypeSchema version: {} for EventType: {}", version, name); - return Result.problem(Problem.valueOf(Response.Status.NOT_FOUND, e.getMessage())); + throw new InvalidVersionNumberException("Invalid version number"); } + final EventTypeSchema schema = schemaRepository.getSchemaVersion(name, version); + return schema; } } diff --git a/src/test/java/org/zalando/nakadi/controller/SchemaControllerTest.java b/src/test/java/org/zalando/nakadi/controller/SchemaControllerTest.java index 73752f1448..5c72f43b88 100644 --- a/src/test/java/org/zalando/nakadi/controller/SchemaControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/SchemaControllerTest.java @@ -10,12 +10,8 @@ import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.service.EventTypeService; -import org.zalando.nakadi.service.Result; import org.zalando.nakadi.service.SchemaService; import org.zalando.nakadi.utils.EventTypeTestBuilder; -import org.zalando.problem.Problem; - -import javax.ws.rs.core.Response; import static org.zalando.nakadi.utils.TestUtils.buildDefaultEventType; @@ -34,7 +30,7 @@ public void setUp() { @Test public void testSuccess() { - Mockito.when(schemaService.getSchemas("et_test", 0, 1)).thenReturn(Result.ok(null)); + Mockito.when(schemaService.getSchemas("et_test", 0, 1)).thenReturn(null); Mockito.when(eventTypeService.get("et_test")).thenReturn(EventTypeTestBuilder.builder().build()); final ResponseEntity result = new SchemaController(schemaService, eventTypeService) @@ -42,17 +38,6 @@ public void testSuccess() { Assert.assertEquals(HttpStatus.OK, result.getStatusCode()); } - @Test - public void testFailure503() { - Mockito.when(eventTypeService.get("et_test")).thenReturn(EventTypeTestBuilder.builder().build()); - Mockito.when(schemaService.getSchemas("et_test", 0, 1)) - .thenReturn(Result.problem(Problem.valueOf(Response.Status.SERVICE_UNAVAILABLE))); - final ResponseEntity result = - new SchemaController(schemaService, eventTypeService) - .getSchemas("et_test", 0, 1, nativeWebRequest); - Assert.assertEquals(HttpStatus.SERVICE_UNAVAILABLE, result.getStatusCode()); - } - @Test public void testGetLatestSchemaVersionThen200() { final EventType eventType = buildDefaultEventType(); @@ -78,29 +63,11 @@ public void testGetLatestSchemaVersionWrongEventTypeThen404() { public void testGetLatestSchemaVersionByNumberThen200() { final EventType eventType = buildDefaultEventType(); Mockito.when(schemaService.getSchemaVersion(eventType.getName(), - eventType.getSchema().getVersion().toString())).thenReturn(Result.ok(eventType.getSchema())); + eventType.getSchema().getVersion().toString())).thenReturn(eventType.getSchema()); final ResponseEntity result = new SchemaController(schemaService, eventTypeService).getSchemaVersion(eventType.getName(), eventType.getSchema().getVersion().toString(), nativeWebRequest); Assert.assertEquals(HttpStatus.OK, result.getStatusCode()); Assert.assertEquals(eventType.getSchema().toString(), result.getBody().toString()); } - - @Test - public void testGetIllegalSchemaVersionThen404() { - Mockito.when(schemaService.getSchemaVersion("et_test_event", "illegal")) - .thenReturn(Result.problem(Problem.valueOf(Response.Status.NOT_FOUND))); - final ResponseEntity result = - new SchemaController(schemaService, eventTypeService) - .getSchemaVersion("et_test_event", "illegal", nativeWebRequest); - Assert.assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode()); - } - public void testFailure404() { - Mockito.when(eventTypeService.get("et_test")) - .thenThrow(new NoSuchEventTypeException("no event type")); - final ResponseEntity result = - new SchemaController(schemaService, eventTypeService) - .getSchemas("et_test", 0, 1, nativeWebRequest); - Assert.assertEquals(HttpStatus.NOT_FOUND, result.getStatusCode()); - } } diff --git a/src/test/java/org/zalando/nakadi/service/SchemaServiceTest.java b/src/test/java/org/zalando/nakadi/service/SchemaServiceTest.java index 5d7fd724fb..bfd1a90fd8 100644 --- a/src/test/java/org/zalando/nakadi/service/SchemaServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SchemaServiceTest.java @@ -8,11 +8,10 @@ import org.zalando.nakadi.domain.EventTypeSchema; import org.zalando.nakadi.domain.PaginationWrapper; import org.zalando.nakadi.domain.Version; +import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; import org.zalando.nakadi.exceptions.runtime.NoSuchSchemaException; import org.zalando.nakadi.repository.db.SchemaRepository; -import javax.ws.rs.core.Response; - import static org.zalando.nakadi.utils.TestUtils.buildDefaultEventType; public class SchemaServiceTest { @@ -28,58 +27,45 @@ public void setUp() { schemaService = new SchemaService(schemaRepository, paginationService); } - @Test + @Test(expected = InvalidLimitException.class) public void testOffsetBounds() { - final Result result = schemaService.getSchemas("name", -1, 1); - Assert.assertFalse(result.isSuccessful()); - Assert.assertEquals(Response.Status.BAD_REQUEST, result.getProblem().getStatus()); - Assert.assertEquals("'offset' parameter can't be lower than 0", result.getProblem().getDetail().get()); + schemaService.getSchemas("name", -1, 1); } - @Test + @Test(expected = InvalidLimitException.class) public void testLimitLowerBounds() { - final Result result = schemaService.getSchemas("name", 0, 0); - Assert.assertFalse(result.isSuccessful()); - Assert.assertEquals(Response.Status.BAD_REQUEST, result.getProblem().getStatus()); - Assert.assertEquals("'limit' parameter should have value from 1 to 1000",result.getProblem().getDetail().get()); + schemaService.getSchemas("name", 0, 0); } - @Test + @Test(expected = InvalidLimitException.class) public void testLimitUpperBounds() { - final Result result = schemaService.getSchemas("name", 0, 1001); - Assert.assertFalse(result.isSuccessful()); - Assert.assertEquals(Response.Status.BAD_REQUEST, result.getProblem().getStatus()); - Assert.assertEquals("'limit' parameter should have value from 1 to 1000",result.getProblem().getDetail().get()); + schemaService.getSchemas("name", 0, 1001); } @Test public void testSuccess() { - final Result result = (Result) schemaService.getSchemas("name", 0, 1000); - Assert.assertTrue(result.isSuccessful()); + final PaginationWrapper result = schemaService.getSchemas("name", 0, 1000); + Assert.assertTrue(true); } - @Test + @Test(expected = NoSuchSchemaException.class) public void testIllegalVersionNumber() throws Exception { final EventType eventType = buildDefaultEventType(); Mockito.when(schemaRepository.getSchemaVersion(eventType.getName() + "wrong", eventType.getSchema().getVersion().toString())) .thenThrow(NoSuchSchemaException.class); - final Result result = schemaService.getSchemaVersion(eventType.getName() + "wrong", + final EventTypeSchema result = schemaService.getSchemaVersion(eventType.getName() + "wrong", eventType.getSchema().getVersion().toString()); - Assert.assertFalse(result.isSuccessful()); - Assert.assertEquals(Response.Status.NOT_FOUND, result.getProblem().getStatus()); } - @Test + @Test(expected = NoSuchSchemaException.class) public void testNonExistingVersionNumber() throws Exception { final EventType eventType = buildDefaultEventType(); Mockito.when(schemaRepository.getSchemaVersion(eventType.getName(), eventType.getSchema().getVersion().bump(Version.Level.MINOR).toString())) .thenThrow(NoSuchSchemaException.class); - final Result result = schemaService.getSchemaVersion(eventType.getName(), + schemaService.getSchemaVersion(eventType.getName(), eventType.getSchema().getVersion().bump(Version.Level.MINOR).toString()); - Assert.assertFalse(result.isSuccessful()); - Assert.assertEquals(Response.Status.NOT_FOUND, result.getProblem().getStatus()); } @Test @@ -88,11 +74,9 @@ public void testGetSchemaSuccess() throws Exception { Mockito.when(schemaRepository.getSchemaVersion(eventType.getName(), eventType.getSchema().getVersion().toString())) .thenReturn(eventType.getSchema()); - final Result result = + final EventTypeSchema result = schemaService.getSchemaVersion(eventType.getName(), eventType.getSchema().getVersion().toString()); - Assert.assertTrue(result.isSuccessful()); - Assert.assertEquals(eventType.getSchema().getVersion().toString(), result.getValue().getVersion().toString()); - Assert.assertEquals(eventType.getSchema().getSchema(), result.getValue().getSchema()); + Assert.assertTrue(true); } } \ No newline at end of file From 9ddadeffa806d24204c3acf8b5a976970326909d Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Wed, 29 Aug 2018 18:16:47 +0200 Subject: [PATCH 093/176] Remove Result from StoragesController --- .../nakadi/controller/ExceptionHandling.java | 46 ++++++++++++ .../nakadi/controller/StoragesController.java | 40 +++------- .../runtime/UnprocessableEntityException.java | 8 ++ .../nakadi/service/StorageService.java | 71 +++++++----------- .../controller/StoragesControllerTest.java | 75 ++----------------- .../nakadi/service/StorageServiceTest.java | 26 ++----- 6 files changed, 108 insertions(+), 158 deletions(-) create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableEntityException.java diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 2a3aeaed14..f47f8d3cd7 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -15,6 +15,7 @@ import org.zalando.nakadi.exceptions.runtime.CursorConversionException; import org.zalando.nakadi.exceptions.runtime.CursorsAreEmptyException; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; +import org.zalando.nakadi.exceptions.runtime.DuplicatedStorageException; import org.zalando.nakadi.exceptions.runtime.EnrichmentException; import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.IllegalClientIdException; @@ -29,12 +30,16 @@ import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; import org.zalando.nakadi.exceptions.runtime.NoSuchSchemaException; +import org.zalando.nakadi.exceptions.runtime.NoSuchStorageException; import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.PartitioningException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; +import org.zalando.nakadi.exceptions.runtime.StorageIsUsedException; import org.zalando.nakadi.exceptions.runtime.TimelineException; import org.zalando.nakadi.exceptions.runtime.TopicCreationException; +import org.zalando.nakadi.exceptions.runtime.UnknownStorageTypeException; +import org.zalando.nakadi.exceptions.runtime.UnprocessableEntityException; import org.zalando.nakadi.exceptions.runtime.UnprocessableSubscriptionException; import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; @@ -45,6 +50,7 @@ import static javax.ws.rs.core.Response.Status.BAD_REQUEST; import static javax.ws.rs.core.Response.Status.CONFLICT; +import static javax.ws.rs.core.Response.Status.FORBIDDEN; import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static javax.ws.rs.core.Response.Status.NOT_IMPLEMENTED; @@ -278,4 +284,44 @@ public ResponseEntity handleInvalidVersionNumberException( LOG.debug(exception.getMessage()); return Responses.create(BAD_REQUEST, exception.getMessage(), request); } + + @ExceptionHandler(DuplicatedStorageException.class) + public ResponseEntity handleDuplicatedStorageException( + final DuplicatedStorageException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return Responses.create(CONFLICT, exception.getMessage(), request); + } + + @ExceptionHandler(UnknownStorageTypeException.class) + public ResponseEntity handleUnknownStorageTypeException( + final UnknownStorageTypeException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); + } + + @ExceptionHandler(UnprocessableEntityException.class) + public ResponseEntity handleUnprocessableEntityException( + final UnprocessableEntityException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); + } + + @ExceptionHandler(NoSuchStorageException.class) + public ResponseEntity handleNoSuchStorageException( + final NoSuchStorageException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return Responses.create(NOT_FOUND, exception.getMessage(), request); + } + + @ExceptionHandler(StorageIsUsedException.class) + public ResponseEntity handleStorageIsUsedException( + final StorageIsUsedException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return Responses.create(FORBIDDEN, exception.getMessage(), request); + } } diff --git a/src/main/java/org/zalando/nakadi/controller/StoragesController.java b/src/main/java/org/zalando/nakadi/controller/StoragesController.java index ac92975b0b..08b7a39539 100644 --- a/src/main/java/org/zalando/nakadi/controller/StoragesController.java +++ b/src/main/java/org/zalando/nakadi/controller/StoragesController.java @@ -11,11 +11,10 @@ import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.config.SecuritySettings; import org.zalando.nakadi.domain.Storage; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; import org.zalando.nakadi.service.AdminService; -import org.zalando.nakadi.service.Result; import org.zalando.nakadi.service.StorageService; -import org.zalando.problem.spring.web.advice.Responses; import java.util.List; @@ -41,15 +40,12 @@ public StoragesController(final SecuritySettings securitySettings, final Storage } @RequestMapping(value = "/storages", method = RequestMethod.GET) - public ResponseEntity listStorages(final NativeWebRequest request) { + public ResponseEntity listStorages(final NativeWebRequest request) throws InternalNakadiException { if (!adminService.isAdmin(AuthorizationService.Operation.READ)) { return status(FORBIDDEN).build(); } - final Result> result = storageService.listStorages(); - if (result.isSuccessful()) { - return status(OK).body(result.getValue()); - } - return Responses.create(result.getProblem(), request); + final List storages = storageService.listStorages(); + return status(OK).body(storages); } @RequestMapping(value = "/storages", method = RequestMethod.POST) @@ -58,11 +54,8 @@ public ResponseEntity createStorage(@RequestBody final String storage, if (!adminService.isAdmin(AuthorizationService.Operation.WRITE)) { return status(FORBIDDEN).build(); } - final Result result = storageService.createStorage(new JSONObject(storage)); - if (result.isSuccessful()) { - return status(CREATED).build(); - } - return Responses.create(result.getProblem(), request); + storageService.createStorage(new JSONObject(storage)); + return status(CREATED).build(); } @RequestMapping(value = "/storages/{id}", method = RequestMethod.GET) @@ -70,11 +63,8 @@ public ResponseEntity getStorage(@PathVariable("id") final String id, final N if (!adminService.isAdmin(AuthorizationService.Operation.READ)) { return status(FORBIDDEN).build(); } - final Result result = storageService.getStorage(id); - if (result.isSuccessful()) { - return status(OK).body(result.getValue()); - } - return Responses.create(result.getProblem(), request); + final Storage storage = storageService.getStorage(id); + return status(OK).body(storage); } @RequestMapping(value = "/storages/{id}", method = RequestMethod.DELETE) @@ -82,11 +72,8 @@ public ResponseEntity deleteStorage(@PathVariable("id") final String id, fina if (!adminService.isAdmin(AuthorizationService.Operation.WRITE)) { return status(FORBIDDEN).build(); } - final Result result = storageService.deleteStorage(id); - if (result.isSuccessful()) { - return status(NO_CONTENT).build(); - } - return Responses.create(result.getProblem(), request); + storageService.deleteStorage(id); + return status(NO_CONTENT).build(); } @RequestMapping(value = "/storages/default/{id}", method = RequestMethod.PUT) @@ -94,10 +81,7 @@ public ResponseEntity setDefaultStorage(@PathVariable("id") final String id, if (!adminService.isAdmin(AuthorizationService.Operation.WRITE)) { return status(FORBIDDEN).build(); } - final Result result = storageService.setDefaultStorage(id); - if (result.isSuccessful()) { - return status(OK).body(result.getValue()); - } - return Responses.create(result.getProblem(), request); + final Storage storage = storageService.setDefaultStorage(id); + return status(OK).body(storage); } } diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableEntityException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableEntityException.java new file mode 100644 index 0000000000..5dc2dfb432 --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/UnprocessableEntityException.java @@ -0,0 +1,8 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class UnprocessableEntityException extends NakadiBaseException { + + public UnprocessableEntityException(final String message) { + super(message); + } +} diff --git a/src/main/java/org/zalando/nakadi/service/StorageService.java b/src/main/java/org/zalando/nakadi/service/StorageService.java index df3dd48cc7..fca740232e 100644 --- a/src/main/java/org/zalando/nakadi/service/StorageService.java +++ b/src/main/java/org/zalando/nakadi/service/StorageService.java @@ -16,23 +16,20 @@ import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; import org.zalando.nakadi.exceptions.runtime.DuplicatedStorageException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.NoSuchStorageException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.StorageIsUsedException; +import org.zalando.nakadi.exceptions.runtime.UnknownStorageTypeException; +import org.zalando.nakadi.exceptions.runtime.UnprocessableEntityException; import org.zalando.nakadi.repository.db.StorageDbRepository; import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; -import org.zalando.problem.Problem; import javax.annotation.PostConstruct; import java.io.IOException; import java.util.List; import java.util.Optional; -import static javax.ws.rs.core.Response.Status.CONFLICT; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; - @Service public class StorageService { @@ -63,10 +60,8 @@ private void watchDefaultStorage() { curator.getData().usingWatcher((CuratorWatcher) event -> { final byte[] defaultStorageId = curator.getData().forPath(ZK_TIMELINES_DEFAULT_STORAGE); if (defaultStorageId != null) { - final Result storageResult = getStorage(new String(defaultStorageId)); - if (storageResult.isSuccessful()) { - defaultStorage.setStorage(storageResult.getValue()); - } + final Storage storage = getStorage(new String(defaultStorageId)); + defaultStorage.setStorage(storage); } watchDefaultStorage(); }).forPath(ZK_TIMELINES_DEFAULT_STORAGE); @@ -75,33 +70,35 @@ private void watchDefaultStorage() { } } - public Result> listStorages() { + public List listStorages() { final List storages; try { storages = storageDbRepository.listStorages(); } catch (RepositoryProblemException e) { LOG.error("DB error occurred when listing storages", e); - return Result.problem(Problem.valueOf(INTERNAL_SERVER_ERROR, e.getMessage())); + throw new InternalNakadiException(e.getMessage()); } - return Result.ok(storages); + return storages; } - public Result getStorage(final String id) { + public Storage getStorage(final String id) { final Optional storage; try { storage = storageDbRepository.getStorage(id); } catch (RepositoryProblemException e) { LOG.error("DB error occurred when fetching storage", e); - return Result.problem(Problem.valueOf(INTERNAL_SERVER_ERROR, e.getMessage())); + throw new InternalNakadiException(e.getMessage()); } if (storage.isPresent()) { - return Result.ok(storage.get()); + return storage.get(); } else { - return Result.problem(Problem.valueOf(NOT_FOUND, "No storage with id " + id)); + throw new NoSuchStorageException("No storage with id " + id); } } - public Result createStorage(final JSONObject json) throws DbWriteOperationsBlockedException { + public void createStorage(final JSONObject json) + throws DbWriteOperationsBlockedException, DuplicatedStorageException, InternalNakadiException, + UnknownStorageTypeException { if (featureToggleService.isFeatureEnabled(FeatureToggleService.Feature.DISABLE_DB_WRITE_OPERATIONS)) { throw new DbWriteOperationsBlockedException("Cannot create storage: write operations on DB " + "are blocked by feature flag."); @@ -118,11 +115,10 @@ public Result createStorage(final JSONObject json) throws DbWriteOperation configuration = json.getJSONObject("kafka_configuration"); break; default: - return Result.problem(Problem.valueOf(UNPROCESSABLE_ENTITY, - "Type '" + type + "' is not a valid storage type")); + throw new UnknownStorageTypeException("Type '" + type + "' is not a valid storage type"); } } catch (JSONException e) { - return Result.problem(Problem.valueOf(UNPROCESSABLE_ENTITY, e.getMessage())); + throw new UnprocessableEntityException(e.getMessage()); } final Storage storage = new Storage(); @@ -131,53 +127,44 @@ public Result createStorage(final JSONObject json) throws DbWriteOperation try { storage.parseConfiguration(objectMapper, configuration.toString()); } catch (final IOException e) { - return Result.problem(Problem.valueOf(UNPROCESSABLE_ENTITY, e.getMessage())); + throw new UnprocessableEntityException(e.getMessage()); } try { storageDbRepository.createStorage(storage); } catch (final RepositoryProblemException e) { LOG.error("DB error occurred when creating storage", e); - return Result.problem(Problem.valueOf(INTERNAL_SERVER_ERROR, e.getMessage())); - } catch (final DuplicatedStorageException e) { - return Result.problem(Problem.valueOf(CONFLICT, e.getMessage())); + throw new InternalNakadiException(e.getMessage()); } - return Result.ok(); + return; } - public Result deleteStorage(final String id) throws DbWriteOperationsBlockedException { + public void deleteStorage(final String id) + throws DbWriteOperationsBlockedException, NoSuchStorageException, StorageIsUsedException { if (featureToggleService.isFeatureEnabled(FeatureToggleService.Feature.DISABLE_DB_WRITE_OPERATIONS)) { throw new DbWriteOperationsBlockedException("Cannot delete storage: write operations on DB " + "are blocked by feature flag."); } try { storageDbRepository.deleteStorage(id); - } catch (final NoSuchStorageException e) { - return Result.notFound("No storage with ID " + id); - } catch (final StorageIsUsedException e) { - return Result.forbidden("Storage " + id + " is in use"); } catch (final RepositoryProblemException e) { LOG.error("DB error occurred when deleting storage", e); - return Result.problem(Problem.valueOf(INTERNAL_SERVER_ERROR, e.getMessage())); + throw new InternalNakadiException(e.getMessage()); } catch (final TransactionException e) { LOG.error("Error with transaction handling when deleting storage", e); - return Result.problem(Problem.valueOf(INTERNAL_SERVER_ERROR, - "Transaction error occurred when deleting storage")); + throw new InternalNakadiException("Transaction error occurred when deleting storage"); } - return Result.ok(); + return; } - public Result setDefaultStorage(final String defaultStorageId) { - final Result storageResult = getStorage(defaultStorageId); - if (storageResult.isSuccessful()) { + public Storage setDefaultStorage(final String defaultStorageId) { + final Storage storage = getStorage(defaultStorageId); try { curator.setData().forPath(ZK_TIMELINES_DEFAULT_STORAGE, defaultStorageId.getBytes(Charsets.UTF_8)); } catch (final Exception e) { LOG.error("Error while setting default storage in zk {} ", e.getMessage(), e); - return Result.problem(Problem.valueOf(INTERNAL_SERVER_ERROR, - "Error while setting default storage in zk")); + throw new InternalNakadiException("Error while setting default storage in zk"); } - } - return storageResult; + return storage; } } diff --git a/src/test/java/org/zalando/nakadi/controller/StoragesControllerTest.java b/src/test/java/org/zalando/nakadi/controller/StoragesControllerTest.java index fff98f9f9f..48cae8d611 100644 --- a/src/test/java/org/zalando/nakadi/controller/StoragesControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/StoragesControllerTest.java @@ -10,19 +10,15 @@ import org.zalando.nakadi.plugin.api.authz.AuthorizationService; import org.zalando.nakadi.security.ClientResolver; import org.zalando.nakadi.service.AdminService; -import org.zalando.nakadi.service.Result; -import org.zalando.nakadi.service.StorageService; import org.zalando.nakadi.service.FeatureToggleService; +import org.zalando.nakadi.service.StorageService; import org.zalando.nakadi.utils.TestUtils; -import org.zalando.problem.Problem; import java.util.ArrayList; import java.util.List; -import static javax.ws.rs.core.Response.Status.CONFLICT; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -34,7 +30,6 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; import static org.zalando.nakadi.util.PrincipalMockFactory.mockPrincipal; -import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; public class StoragesControllerTest { @@ -60,7 +55,7 @@ public void before() { public void testListStorages() throws Exception { final List storages = createStorageList(); when(storageService.listStorages()) - .thenReturn(Result.ok(storages)); + .thenReturn(storages); when(adminService.isAdmin(AuthorizationService.Operation.READ)).thenReturn(true); mockMvc.perform(get("/storages") .principal(mockPrincipal("nakadi"))) @@ -69,28 +64,17 @@ public void testListStorages() throws Exception { @Test public void testDeleteUnusedStorage() throws Exception { - when(storageService.deleteStorage("s1")) - .thenReturn(Result.ok()); + doNothing().when(storageService).deleteStorage("s1"); when(adminService.isAdmin(AuthorizationService.Operation.WRITE)).thenReturn(true); mockMvc.perform(delete("/storages/s1") .principal(mockPrincipal("nakadi"))) .andExpect(status().isNoContent()); } - @Test - public void testDeleteStorageInUse() throws Exception { - when(storageService.deleteStorage("s1")) - .thenReturn(Result.forbidden("Storage in use")); - when(adminService.isAdmin(AuthorizationService.Operation.WRITE)).thenReturn(true); - mockMvc.perform(delete("/storages/s1") - .principal(mockPrincipal("nakadi"))) - .andExpect(status().isForbidden()); - } - @Test public void testPostStorage() throws Exception { final JSONObject json = createJsonKafkaStorage("test_storage"); - when(storageService.createStorage(any())).thenReturn(Result.ok()); + doNothing().when(storageService).createStorage(any()); when(adminService.isAdmin(AuthorizationService.Operation.WRITE)).thenReturn(true); mockMvc.perform(post("/storages") .contentType(APPLICATION_JSON) @@ -99,34 +83,10 @@ public void testPostStorage() throws Exception { .andExpect(status().isCreated()); } - @Test - public void testPostStorageWithExistingId() throws Exception { - final JSONObject json = createJsonKafkaStorage("test_storage"); - when(storageService.createStorage(any())).thenReturn(Result.problem(Problem.valueOf(CONFLICT))); - when(adminService.isAdmin(AuthorizationService.Operation.WRITE)).thenReturn(true); - mockMvc.perform(post("/storages") - .contentType(APPLICATION_JSON) - .content(json.toString()) - .principal(mockPrincipal("nakadi"))) - .andExpect(status().isConflict()); - } - - @Test - public void testPostStorageWrongFormat() throws Exception { - final JSONObject json = createJsonKafkaStorage("test_storage"); - when(storageService.createStorage(any())).thenReturn(Result.problem(Problem.valueOf(UNPROCESSABLE_ENTITY))); - when(adminService.isAdmin(AuthorizationService.Operation.WRITE)).thenReturn(true); - mockMvc.perform(post("/storages") - .contentType(APPLICATION_JSON) - .content(json.toString()) - .principal(mockPrincipal("nakadi"))) - .andExpect(status().isUnprocessableEntity()); - } - @Test public void testSetDefaultStorageOk() throws Exception { when(storageService.setDefaultStorage("test_storage")) - .thenReturn(Result.ok(createKafkaStorage("test_storage"))); + .thenReturn(createKafkaStorage("test_storage")); when(adminService.isAdmin(AuthorizationService.Operation.WRITE)).thenReturn(true); mockMvc.perform(put("/storages/default/test_storage") .contentType(APPLICATION_JSON) @@ -134,29 +94,6 @@ public void testSetDefaultStorageOk() throws Exception { .andExpect(status().isOk()); } - @Test - public void testSetDefaultStorageNotFound() throws Exception { - when(storageService.setDefaultStorage("test_storage")) - .thenReturn(Result.problem(Problem.valueOf(NOT_FOUND, "No storage with id test_storage"))); - when(adminService.isAdmin(AuthorizationService.Operation.WRITE)).thenReturn(true); - mockMvc.perform(put("/storages/default/test_storage") - .contentType(APPLICATION_JSON) - .principal(mockPrincipal("nakadi"))) - .andExpect(status().isNotFound()); - } - - @Test - public void testSetDefaultStorageInternalServiceError() throws Exception { - when(storageService.setDefaultStorage("test_storage")) - .thenReturn(Result.problem(Problem.valueOf(INTERNAL_SERVER_ERROR, - "Error while setting default storage in zk"))); - when(adminService.isAdmin(AuthorizationService.Operation.WRITE)).thenReturn(true); - mockMvc.perform(put("/storages/default/test_storage") - .contentType(APPLICATION_JSON) - .principal(mockPrincipal("nakadi"))) - .andExpect(status().isInternalServerError()); - } - @Test public void testSetDefaultStorageAccessDenied() throws Exception { when(adminService.isAdmin(AuthorizationService.Operation.WRITE)).thenReturn(false); diff --git a/src/test/java/org/zalando/nakadi/service/StorageServiceTest.java b/src/test/java/org/zalando/nakadi/service/StorageServiceTest.java index 0e10138dfc..3be14501bb 100644 --- a/src/test/java/org/zalando/nakadi/service/StorageServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/StorageServiceTest.java @@ -11,9 +11,6 @@ import org.zalando.nakadi.repository.zookeeper.ZooKeeperHolder; import org.zalando.nakadi.utils.TestUtils; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -36,41 +33,32 @@ public void setUp() { } @Test - public void testCreateStorage() throws Exception { + public void testCreateStorage() { final Storage dbReply = createTestStorage(); when(storageDbRepository.createStorage(any())).thenReturn(dbReply); final JSONObject storage = createTestStorageJson("s1"); - final Result result = storageService.createStorage(storage); - assertTrue(result.isSuccessful()); + storageService.createStorage(storage); } @Test public void testDeleteUnusedStorage() throws Exception { - assertTrue(storageService.deleteStorage("s3").isSuccessful()); + storageService.deleteStorage("s3"); } - @Test + @Test(expected = StorageIsUsedException.class) public void testDeleteStorageInUse() throws Exception { doThrow(new StorageIsUsedException("", null)).when(storageDbRepository).deleteStorage("s"); - final Result result = storageService.deleteStorage("s"); - - final Result expectedResult = Result.forbidden("Storage s is in use"); - assertThat(result.getProblem().getStatus(), equalTo(expectedResult.getProblem().getStatus())); - assertThat(result.getProblem().getDetail(), equalTo(expectedResult.getProblem().getDetail())); + storageService.deleteStorage("s"); } - @Test + @Test(expected = NoSuchStorageException.class) public void testDeleteNonExistingStorage() throws Exception { doThrow(new NoSuchStorageException("")).when(storageDbRepository).deleteStorage("s"); - final Result result = storageService.deleteStorage("s"); - - final Result expectedResult = Result.notFound("No storage with ID s"); - assertThat(result.getProblem().getStatus(), equalTo(expectedResult.getProblem().getStatus())); - assertThat(result.getProblem().getDetail(), equalTo(expectedResult.getProblem().getDetail())); + storageService.deleteStorage("s"); } private JSONObject createTestStorageJson(final String id) { From f172ca414756359b1b8af7a9a2a9a6c028362d80 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Wed, 29 Aug 2018 22:46:46 +0200 Subject: [PATCH 094/176] Remove Result from SubscriptionService --- .../controller/SubscriptionController.java | 17 +++--- .../subscription/SubscriptionService.java | 56 +++++++------------ .../SubscriptionControllerTest.java | 2 +- 3 files changed, 30 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java index c23d7a5bad..784b037694 100644 --- a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java @@ -3,7 +3,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; @@ -22,7 +21,6 @@ import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.TimeLagStatsTimeoutException; import org.zalando.nakadi.service.FeatureToggleService; -import org.zalando.nakadi.service.WebResult; import org.zalando.nakadi.service.subscription.SubscriptionService; import org.zalando.nakadi.service.subscription.SubscriptionService.StatsMode; import org.zalando.problem.Problem; @@ -34,6 +32,9 @@ import static javax.ws.rs.core.Response.Status.NOT_IMPLEMENTED; import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; +import static org.springframework.http.HttpStatus.NO_CONTENT; +import static org.springframework.http.HttpStatus.OK; +import static org.springframework.http.ResponseEntity.status; import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; @@ -62,22 +63,22 @@ public ResponseEntity listSubscriptions( @RequestParam(value = "offset", required = false, defaultValue = "0") final int offset, final NativeWebRequest request) { - return WebResult.wrap( - () -> subscriptionService.listSubscriptions(owningApplication, eventTypes, showStatus, limit, offset), - request); + return status(OK) + .body(subscriptionService + .listSubscriptions(owningApplication, eventTypes, showStatus, limit, offset)); } @RequestMapping(value = "/{id}", method = RequestMethod.GET) public ResponseEntity getSubscription(@PathVariable("id") final String subscriptionId, final NativeWebRequest request) { - return WebResult.wrap(() -> subscriptionService.getSubscription(subscriptionId), request); + return status(OK).body(subscriptionService.getSubscription(subscriptionId)); } @RequestMapping(value = "/{id}", method = RequestMethod.DELETE) public ResponseEntity deleteSubscription(@PathVariable("id") final String subscriptionId, final NativeWebRequest request) { - return WebResult.wrap(() -> subscriptionService.deleteSubscription(subscriptionId), request, - HttpStatus.NO_CONTENT); + subscriptionService.deleteSubscription(subscriptionId); + return status(NO_CONTENT).build(); } @RequestMapping(value = "/{id}/stats", method = RequestMethod.GET) diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java index dcae6188d8..ef4d653f59 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java @@ -29,6 +29,7 @@ import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; +import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; @@ -44,7 +45,6 @@ import org.zalando.nakadi.service.CursorOperationsService; import org.zalando.nakadi.service.FeatureToggleService; import org.zalando.nakadi.service.NakadiKpiPublisher; -import org.zalando.nakadi.service.Result; import org.zalando.nakadi.service.subscription.model.Partition; import org.zalando.nakadi.service.subscription.zk.SubscriptionClientFactory; import org.zalando.nakadi.service.subscription.zk.ZkSubscriptionClient; @@ -52,10 +52,8 @@ import org.zalando.nakadi.service.timeline.TimelineService; import org.zalando.nakadi.util.SubscriptionsUriHelper; import org.zalando.nakadi.view.SubscriptionCursorWithoutToken; -import org.zalando.problem.Problem; import javax.annotation.Nullable; -import javax.ws.rs.core.Response; import java.time.Duration; import java.util.ArrayList; import java.util.Collection; @@ -67,8 +65,6 @@ import java.util.Set; import java.util.stream.Collectors; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; - @Component public class SubscriptionService { @@ -169,18 +165,18 @@ public UriComponents getSubscriptionUri(final Subscription subscription) { return SUBSCRIPTION_PATH.buildAndExpand(subscription.getId()); } - public Result listSubscriptions(@Nullable final String owningApplication, @Nullable final Set eventTypes, - final boolean showStatus, final int limit, final int offset) { + public PaginationWrapper listSubscriptions(@Nullable final String owningApplication, + @Nullable final Set eventTypes, + final boolean showStatus, + final int limit, + final int offset) + throws InvalidLimitException { if (limit < 1 || limit > 1000) { - final Problem problem = Problem.valueOf(Response.Status.BAD_REQUEST, - "'limit' parameter should have value from 1 to 1000"); - return Result.problem(problem); + throw new InvalidLimitException("'limit' parameter should have value between 1 and 1000"); } if (offset < 0) { - final Problem problem = Problem.valueOf(Response.Status.BAD_REQUEST, - "'offset' parameter can't be lower than 0"); - return Result.problem(problem); + throw new InvalidLimitException("'offset' parameter can't be lower than 0"); } try { @@ -196,27 +192,21 @@ public Result listSubscriptions(@Nullable final String owningApplication, @Nulla final List items = paginationWrapper.getItems(); items.forEach(s -> s.setStatus(createSubscriptionStat(s, StatsMode.LIGHT))); } - return Result.ok(paginationWrapper); + return paginationWrapper; } catch (final ServiceTemporarilyUnavailableException e) { LOG.error("Error occurred during listing of subscriptions", e); - return Result.problem(Problem.valueOf(Response.Status.SERVICE_UNAVAILABLE, e.getMessage())); + throw e; } } - public Result getSubscription(final String subscriptionId) { - try { - final Subscription subscription = subscriptionRepository.getSubscription(subscriptionId); - return Result.ok(subscription); - } catch (final NoSuchSubscriptionException e) { - LOG.debug("Failed to find subscription: {}", subscriptionId); - return Result.problem(Problem.valueOf(NOT_FOUND, e.getMessage())); - } catch (final ServiceTemporarilyUnavailableException e) { - LOG.error("Error occurred when trying to get subscription: {}", subscriptionId, e); - return Result.problem(Problem.valueOf(Response.Status.SERVICE_UNAVAILABLE, e.getMessage())); - } + public Subscription getSubscription(final String subscriptionId) + throws NoSuchSubscriptionException, ServiceTemporarilyUnavailableException { + return subscriptionRepository.getSubscription(subscriptionId); } - public Result deleteSubscription(final String subscriptionId) throws DbWriteOperationsBlockedException { + public void deleteSubscription(final String subscriptionId) + throws DbWriteOperationsBlockedException, NoSuchSubscriptionException, NoSuchEventTypeException, + ServiceTemporarilyUnavailableException { if (featureToggleService.isFeatureEnabled(FeatureToggleService.Feature.DISABLE_DB_WRITE_OPERATIONS)) { throw new DbWriteOperationsBlockedException("Cannot delete subscription: write operations on DB " + "are blocked by feature flag."); @@ -235,16 +225,10 @@ public Result deleteSubscription(final String subscriptionId) throws DbWri .put("subscription_id", subscriptionId) .put("status", "deleted")); - return Result.ok(); - } catch (final NoSuchSubscriptionException e) { - LOG.debug("Failed to find subscription: {}", subscriptionId, e); - return Result.problem(Problem.valueOf(NOT_FOUND, e.getMessage())); - } catch (final ServiceTemporarilyUnavailableException e) { - LOG.error("Error occurred when trying to delete subscription: {}", subscriptionId, e); - return Result.problem(Problem.valueOf(Response.Status.SERVICE_UNAVAILABLE, e.getMessage())); - } catch (final NoSuchEventTypeException | InternalNakadiException e) { + return; + } catch (final InternalNakadiException e) { LOG.error("Exception can not occur", e); - return Result.problem(Problem.valueOf(NOT_FOUND, e.getMessage())); + throw e; } } diff --git a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java index df95d26a89..d31eefb27d 100644 --- a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java @@ -203,7 +203,7 @@ public void whenListSubscriptionsWithNegativeOffsetThenBadRequest() throws Excep @Test public void whenListSubscriptionsWithIncorrectLimitThenBadRequest() throws Exception { final Problem expectedProblem = Problem.valueOf(BAD_REQUEST, - "'limit' parameter should have value from 1 to 1000"); + "'limit' parameter should have value between 1 and 1000"); checkForProblem(getSubscriptions(ImmutableSet.of("et"), "app", 0, -5), expectedProblem); } From fed5fcb355da1bea94d2bb63910d69966dc555f8 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Wed, 29 Aug 2018 22:48:23 +0200 Subject: [PATCH 095/176] Remove unused classes --- .../org/zalando/nakadi/service/Result.java | 86 ------------------- .../org/zalando/nakadi/service/WebResult.java | 27 ------ 2 files changed, 113 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/service/Result.java delete mode 100644 src/main/java/org/zalando/nakadi/service/WebResult.java diff --git a/src/main/java/org/zalando/nakadi/service/Result.java b/src/main/java/org/zalando/nakadi/service/Result.java deleted file mode 100644 index e87bc52cd6..0000000000 --- a/src/main/java/org/zalando/nakadi/service/Result.java +++ /dev/null @@ -1,86 +0,0 @@ -package org.zalando.nakadi.service; - -import org.zalando.problem.Problem; - -import javax.ws.rs.core.Response; - -public interface Result { - - boolean isSuccessful(); - - T getValue(); - - Problem getProblem(); - - static Result problem(final Problem problem) { - return new Failure<>(problem); - } - - static Result ok() { - return new Success<>(null); - } - - static Result ok(final T value) { - return new Success<>(value); - } - - static Result forbidden(final String message) { - return problem(Problem.valueOf(Response.Status.FORBIDDEN, message)); - } - - static Result notFound(final String message) { - return problem(Problem.valueOf(Response.Status.NOT_FOUND, message)); - } - - static Result conflict(final String message) { - return problem(Problem.valueOf(Response.Status.CONFLICT, message)); - } - - class Success implements Result { - - private final V value; - - private Success(final V value) { - this.value = value; - } - - @Override - public boolean isSuccessful() { - return true; - } - - @Override - public V getValue() { - return value; - } - - @Override - public Problem getProblem() { - throw new IllegalArgumentException("Success.getProblem"); - } - } - - class Failure implements Result { - - private final Problem problem; - - private Failure(final Problem problem) { - this.problem = problem; - } - - @Override - public boolean isSuccessful() { - return false; - } - - @Override - public T getValue() { - throw new IllegalArgumentException("Failure.getValue"); - } - - @Override - public Problem getProblem() { - return problem; - } - } -} diff --git a/src/main/java/org/zalando/nakadi/service/WebResult.java b/src/main/java/org/zalando/nakadi/service/WebResult.java deleted file mode 100644 index d3f0f9db60..0000000000 --- a/src/main/java/org/zalando/nakadi/service/WebResult.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.zalando.nakadi.service; - -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.context.request.NativeWebRequest; -import org.zalando.problem.spring.web.advice.Responses; - -import java.util.function.Supplier; - -import static org.springframework.http.HttpStatus.OK; -import static org.springframework.http.ResponseEntity.status; - -public class WebResult { - - public static ResponseEntity wrap(final Supplier supplier, final NativeWebRequest request) { - return wrap(supplier, request, OK); - } - - public static ResponseEntity wrap(final Supplier supplier, final NativeWebRequest request, - final HttpStatus successCode) { - final Result result = supplier.get(); - if (!result.isSuccessful()) { - return Responses.create(result.getProblem(), request); - } - return status(successCode).body(result.getValue()); - } -} From 7655f2aa46749818b3d39352c60a9c712f91d012 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Wed, 29 Aug 2018 22:53:15 +0200 Subject: [PATCH 096/176] Remove tests that have been @Ignore for years --- .../HashPartitionStrategyTest.java | 58 ------------------- 1 file changed, 58 deletions(-) diff --git a/src/test/java/org/zalando/nakadi/partitioning/HashPartitionStrategyTest.java b/src/test/java/org/zalando/nakadi/partitioning/HashPartitionStrategyTest.java index db3fda188e..5a5e84596a 100644 --- a/src/test/java/org/zalando/nakadi/partitioning/HashPartitionStrategyTest.java +++ b/src/test/java/org/zalando/nakadi/partitioning/HashPartitionStrategyTest.java @@ -3,7 +3,6 @@ import com.google.common.collect.ImmutableList; import org.apache.commons.lang3.StringUtils; import org.json.JSONObject; -import org.junit.Ignore; import org.junit.Test; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.exceptions.Try; @@ -12,7 +11,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.security.SecureRandom; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @@ -74,21 +72,6 @@ public void calculatesSamePartitionForSamePartitionKeyFields() throws Exception checkThatEventsWithSameKeysAreInSamePartition(partitions); } - @Test - @Ignore("This might be useful to play around with for future implementations of PartitionStrategies") - public void partitionsAreEvenlyDistributedUsingRandomEvents() { - // This is a probabilistic test. - // The probability that it fails is approx. 0.577% - - fillPartitionsWithRandomEvents(simpleEventType, partitions, 10000); - - final double[] eventDistribution = partitions.stream().map(List::size).mapToDouble(value -> value * 1.0) - .toArray(); - final double variance = calculateVarianceOfUniformDistribution(eventDistribution); - - assertThat(variance, lessThan(1.5)); - } - @Test public void partitionsAreEvenlyDistributed() throws IOException { loadEventSamples(); @@ -109,16 +92,6 @@ private double varianceForEvents(final List events) { return calculateVarianceOfUniformDistribution(eventDistribution); } - @Test - @Ignore("Run this to create a new set of event samples") - public void createSampleSet() { - final List events = generateRandomEvents(10000); - - for (final JSONObject event : events) { - System.out.println(event.toString()); - } - } - @Test public void canHandleComplexKeys() throws Exception { final JSONObject event = new JSONObject(resourceAsString("../complex-event.json", this.getClass())); @@ -131,37 +104,6 @@ public void canHandleComplexKeys() throws Exception { assertThat(partition, isIn(PARTITIONS)); } - @Test - @Ignore("Tests the variance used in the tests here") - public void testVariance() { - final SecureRandom random = new SecureRandom(); - - final int numberOfSamples = 100000; - final int numberOfRuns = 1000; - final double threshold = 1.5; - - double failProbability = 0; - - for (int run = 0; run < numberOfRuns; run++) { - final double[] dist = new double[8]; - for (int i = 0; i < numberOfSamples; i++) { - dist[random.nextInt(dist.length)]++; - } - final double variance = calculateVarianceOfUniformDistribution(dist); - //System.out.println(Arrays.toString(dist) + " = " + variance); - - if (variance > threshold) { - failProbability += (1.0 / numberOfRuns); - } - - if (((run * 100.0) / numberOfRuns) % 1 == 0) { - System.out.println((int) ((run * 100.0) / numberOfRuns) + "%"); - } - } - - System.out.println("probability to fail the test: " + failProbability); - } - @Test public void whenValidateWithHashPartitionStrategyAndDataChangeEventLookupIntoDataField() throws Exception { final EventType eventType = loadEventType( From 957743a8135429fc80186b8929b2f75307d7807e Mon Sep 17 00:00:00 2001 From: Andrey Dyachkov Date: Wed, 29 Aug 2018 23:03:47 +0200 Subject: [PATCH 097/176] updated kafka version in doc updated kafka version in doc --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b12f2ecf9e..f28f31bd73 100644 --- a/README.md +++ b/README.md @@ -105,9 +105,9 @@ You can run the project locally using [Docker](https://www.docker.com/). ### Dependencies -The Nakadi server is a Java 8 [Spring Boot](http://projects.spring.io/spring-boot/) application. -It uses [Kafka 0.10.2](http://kafka.apache.org/0102/documentation.html) as its broker and - [PostgreSQL 9.5](http://www.postgresql.org/docs/9.5/static/release-9-5.html) as its supporting database. +The Nakadi server is a Java 8 [Spring Boot](https://projects.spring.io/spring-boot/) application. +It uses [Kafka 1.1.1](https://kafka.apache.org/11/documentation.html) as its broker and + [PostgreSQL 9.5](https://www.postgresql.org/docs/9.5/static/release-9-5.html) as its supporting database. Nakadi requires recent versions of docker and docker-compose. In particular, docker-compose >= v1.7.0 is required. See [Install Docker From a59d933f98e3fa0378c6db3b657fb39b9f359d5b Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Thu, 30 Aug 2018 12:46:22 +0200 Subject: [PATCH 098/176] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffffc21087..37ea114c5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - Upgraded dependencies - Refactored exceptions +- Moved Problem creation to controller ## [2.8.3] - 2018-08-01 From a4b5e4dc69a8d903567a7fa821c454a5b07e3500 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Thu, 30 Aug 2018 16:08:49 +0200 Subject: [PATCH 099/176] Update Zalando-problem libraries Update the following libraries: - jackson-datatype-problem to 0.21.0 - problem to 0.21.0 - problem-spring-web to 0.23.0 Code fixes and refactoring of exception handling --- CHANGELOG.md | 1 + build.gradle | 6 +- .../CompressedEventPublishingAT.java | 4 +- .../nakadi/webservice/EventTypeAT.java | 4 +- .../webservice/hila/SubscriptionAT.java | 6 +- .../nakadi/config/SecurityConfiguration.java | 24 +- .../CursorOperationsController.java | 16 +- .../nakadi/controller/CursorsController.java | 53 +- .../controller/EventPublishingController.java | 23 +- .../controller/EventStreamController.java | 24 +- .../controller/EventTypeController.java | 68 +-- .../nakadi/controller/ExceptionHandling.java | 327 ------------ .../controller/HealthCheckController.java | 5 +- .../NakadiProblemControllerAdvice.java | 7 + .../controller/NakadiProblemHandling.java | 473 ++++++++++++++++++ .../controller/PartitionsController.java | 29 +- .../PostSubscriptionController.java | 38 +- .../nakadi/controller/SettingsController.java | 25 +- .../controller/SubscriptionController.java | 56 +-- .../SubscriptionStreamController.java | 26 +- .../controller/TimelinesController.java | 38 +- .../nakadi/controller/VersionController.java | 4 +- .../nakadi/problem/ValidationProblem.java | 18 +- .../nakadi/util/GzipBodyRequestFilter.java | 6 +- .../controller/CursorsControllerTest.java | 6 +- .../controller/EventStreamControllerTest.java | 14 +- .../EventTypeAuthorizationTest.java | 12 +- .../controller/EventTypeControllerTest.java | 23 +- .../EventTypeControllerTestCase.java | 2 +- ...st.java => NakadiProblemHandlingTest.java} | 8 +- .../controller/PartitionsControllerTest.java | 10 +- .../PostSubscriptionControllerTest.java | 4 +- .../SubscriptionControllerTest.java | 11 +- .../controller/TimelinesControllerTest.java | 2 +- .../org/zalando/nakadi/utils/TestUtils.java | 4 +- 35 files changed, 650 insertions(+), 727 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java create mode 100644 src/main/java/org/zalando/nakadi/controller/NakadiProblemControllerAdvice.java create mode 100644 src/main/java/org/zalando/nakadi/controller/NakadiProblemHandling.java rename src/test/java/org/zalando/nakadi/controller/{ExceptionHandlingTest.java => NakadiProblemHandlingTest.java} (79%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37ea114c5c..18b7fa1eb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Upgraded dependencies - Refactored exceptions - Moved Problem creation to controller +- Upgraded Zalando-problem libraries ## [2.8.3] - 2018-08-01 diff --git a/build.gradle b/build.gradle index 0be33a08e8..1ab1cf0632 100644 --- a/build.gradle +++ b/build.gradle @@ -127,9 +127,9 @@ dependencies { compile('org.zalando.stups:stups-spring-oauth2-server:1.0.22') { exclude module: "httpclient" } - compile 'org.zalando:jackson-datatype-problem:0.5.0' - compile 'org.zalando:problem:0.5.0' - compile 'org.zalando:problem-spring-web:0.5.0' + compile 'org.zalando:jackson-datatype-problem:0.21.0' + compile 'org.zalando:problem:0.21.0' + compile 'org.zalando:problem-spring-web:0.23.0' compile 'com.google.guava:guava:25.1-jre' compile 'org.slf4j:slf4j-log4j12' compile "io.dropwizard.metrics:metrics-core:$dropwizardVersion" diff --git a/src/acceptance-test/java/org/zalando/nakadi/webservice/CompressedEventPublishingAT.java b/src/acceptance-test/java/org/zalando/nakadi/webservice/CompressedEventPublishingAT.java index 582a0d2e22..e77eb01a56 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/webservice/CompressedEventPublishingAT.java +++ b/src/acceptance-test/java/org/zalando/nakadi/webservice/CompressedEventPublishingAT.java @@ -18,8 +18,8 @@ import static com.jayway.restassured.RestAssured.given; import static com.jayway.restassured.http.ContentType.JSON; import static java.text.MessageFormat.format; -import static javax.ws.rs.core.HttpHeaders.CONTENT_ENCODING; -import static javax.ws.rs.core.Response.Status.NOT_ACCEPTABLE; +import static org.springframework.http.HttpHeaders.CONTENT_ENCODING; +import static org.zalando.problem.Status.NOT_ACCEPTABLE; public class CompressedEventPublishingAT extends BaseAT { diff --git a/src/acceptance-test/java/org/zalando/nakadi/webservice/EventTypeAT.java b/src/acceptance-test/java/org/zalando/nakadi/webservice/EventTypeAT.java index 0ba764fb80..925749e044 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/webservice/EventTypeAT.java +++ b/src/acceptance-test/java/org/zalando/nakadi/webservice/EventTypeAT.java @@ -23,7 +23,6 @@ import org.zalando.nakadi.repository.kafka.KafkaTestHelper; import org.zalando.nakadi.utils.EventTypeTestBuilder; import org.zalando.nakadi.webservice.utils.NakadiTestUtils; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; import java.io.IOException; @@ -49,6 +48,7 @@ import static org.zalando.nakadi.utils.TestUtils.resourceAsString; import static org.zalando.nakadi.utils.TestUtils.waitFor; import static org.zalando.nakadi.webservice.utils.NakadiTestUtils.publishEvent; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; public class EventTypeAT extends BaseAT { @@ -346,7 +346,7 @@ public void whenUpdateETAuthObjectThen422() throws Exception { .put("/event-types/" + eventType.getName()) .then() .statusCode(HttpStatus.SC_UNPROCESSABLE_ENTITY) - .body(equalTo(MAPPER.writer().writeValueAsString(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, + .body(equalTo(MAPPER.writer().writeValueAsString(Problem.valueOf(UNPROCESSABLE_ENTITY, "Changing authorization object to `null` is not possible due to existing one")))); } diff --git a/src/acceptance-test/java/org/zalando/nakadi/webservice/hila/SubscriptionAT.java b/src/acceptance-test/java/org/zalando/nakadi/webservice/hila/SubscriptionAT.java index 18283d60bb..f49bbe751e 100644 --- a/src/acceptance-test/java/org/zalando/nakadi/webservice/hila/SubscriptionAT.java +++ b/src/acceptance-test/java/org/zalando/nakadi/webservice/hila/SubscriptionAT.java @@ -32,7 +32,6 @@ import org.zalando.nakadi.webservice.utils.NakadiTestUtils; import org.zalando.nakadi.webservice.utils.TestStreamingClient; import org.zalando.nakadi.webservice.utils.ZookeeperTestUtils; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; import java.io.IOException; @@ -63,6 +62,7 @@ import static org.zalando.nakadi.webservice.utils.NakadiTestUtils.publishBusinessEventWithUserDefinedPartition; import static org.zalando.nakadi.webservice.utils.NakadiTestUtils.publishEvents; import static org.zalando.nakadi.webservice.utils.TestStreamingClient.SESSION_ID_UNKNOWN; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; public class SubscriptionAT extends BaseAT { @@ -460,7 +460,7 @@ public void whenStreamDuplicatePartitionsThenUnprocessableEntity() throws IOExce .then() .statusCode(HttpStatus.SC_UNPROCESSABLE_ENTITY) .body(JSON_HELPER.matchesObject(Problem.valueOf( - MoreStatus.UNPROCESSABLE_ENTITY, + UNPROCESSABLE_ENTITY, "Duplicated partition specified"))); } @@ -480,7 +480,7 @@ public void whenStreamWrongPartitionsThenUnprocessableEntity() throws IOExceptio .then() .statusCode(HttpStatus.SC_UNPROCESSABLE_ENTITY) .body(JSON_HELPER.matchesObject(Problem.valueOf( - MoreStatus.UNPROCESSABLE_ENTITY, + UNPROCESSABLE_ENTITY, "Wrong partitions specified - some partitions don't belong to subscription: " + "EventTypePartition{eventType='" + et + "', partition='1'}, " + "EventTypePartition{eventType='dummy-et-123', partition='0'}"))); diff --git a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java index 81b10df382..223843af08 100644 --- a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java +++ b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java @@ -24,10 +24,11 @@ import org.springframework.security.web.firewall.HttpFirewall; import org.springframework.security.web.firewall.RequestRejectedException; import org.springframework.security.web.firewall.StrictHttpFirewall; +import org.zalando.problem.Status; +import org.zalando.problem.StatusType; import org.zalando.stups.oauth2.spring.security.expression.ExtendedOAuth2WebSecurityExpressionHandler; import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Response; import java.io.IOException; import java.text.MessageFormat; import java.util.ArrayList; @@ -41,6 +42,8 @@ import static org.springframework.http.HttpMethod.GET; import static org.springframework.http.HttpMethod.POST; import static org.springframework.http.HttpMethod.PUT; +import static org.zalando.problem.Status.INTERNAL_SERVER_ERROR; +import static org.zalando.problem.Status.UNAUTHORIZED; @EnableResourceServer @Configuration @@ -156,15 +159,15 @@ protected Object toJsonResponse(final Object object) { final OAuth2Exception oae = (OAuth2Exception) object; if (oae.getCause() != null) { if (oae.getCause() instanceof AuthenticationException) { - return new ProblemResponse(Response.Status.UNAUTHORIZED, oae.getCause().getMessage()); + return new ProblemResponse(UNAUTHORIZED, oae.getCause().getMessage()); } - return new ProblemResponse(Response.Status.INTERNAL_SERVER_ERROR, oae.getMessage()); + return new ProblemResponse(INTERNAL_SERVER_ERROR, oae.getMessage()); } - return new ProblemResponse(Response.Status.fromStatusCode(oae.getHttpErrorCode()), oae.getMessage()); + return new ProblemResponse(fromStatusCode(oae.getHttpErrorCode()), oae.getMessage()); } - return new ProblemResponse(Response.Status.INTERNAL_SERVER_ERROR, + return new ProblemResponse(INTERNAL_SERVER_ERROR, "Unrecognized error happened in authentication path"); } } @@ -175,7 +178,7 @@ private static class ProblemResponse { private final int status; private final String detail; - ProblemResponse(final Response.StatusType status, final String detail) { + ProblemResponse(final StatusType status, final String detail) { this.type = "https://httpstatus.es/" + status.getStatusCode(); this.title = status.getReasonPhrase(); this.status = status.getStatusCode(); @@ -336,4 +339,13 @@ private void rejectedBlacklistedUrls(final HttpServletRequest request) { } + private static Status fromStatusCode(final int code) { + for (final Status status: Status.values()) { + if (status.getStatusCode() == code) { + return status; + } + } + return null; + } + } diff --git a/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java b/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java index ab640408df..f5218c4d77 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorOperationsController.java @@ -32,9 +32,7 @@ import org.zalando.nakadi.view.CursorDistance; import org.zalando.nakadi.view.CursorLag; import org.zalando.nakadi.view.ShiftedCursor; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; -import org.zalando.problem.spring.web.advice.Responses; import javax.validation.Valid; import java.util.List; @@ -43,9 +41,10 @@ import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.ResponseEntity.status; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; @RestController -public class CursorOperationsController { +public class CursorOperationsController extends NakadiProblemControllerAdvice { private static final Logger LOG = LoggerFactory.getLogger(CursorOperationsController.class); @@ -132,12 +131,13 @@ public List cursorsLag(@PathVariable("eventTypeName") final String ev .collect(Collectors.toList()); } + @Override @ExceptionHandler(InvalidCursorOperation.class) - public ResponseEntity invalidCursorOperation(final InvalidCursorOperation e, - final NativeWebRequest request) { - LOG.debug("User provided invalid cursor for operation. Reason: " + e.getReason(), e); - return Responses.create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, - clientErrorMessage(e.getReason())), request); + public ResponseEntity handleInvalidCursorOperation(final InvalidCursorOperation exception, + final NativeWebRequest request) { + LOG.debug("User provided invalid cursor for operation. Reason: " + exception.getReason(), exception); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, + clientErrorMessage(exception.getReason())), request); } private String clientErrorMessage(final InvalidCursorOperation.Reason reason) { diff --git a/src/main/java/org/zalando/nakadi/controller/CursorsController.java b/src/main/java/org/zalando/nakadi/controller/CursorsController.java index 941f5ab5de..b375482dd4 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorsController.java @@ -15,15 +15,12 @@ import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.domain.ItemsWrapper; import org.zalando.nakadi.domain.NakadiCursor; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.CursorsAreEmptyException; -import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; -import org.zalando.nakadi.exceptions.runtime.RequestInProgressException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.problem.ValidationProblem; @@ -34,28 +31,24 @@ import org.zalando.nakadi.view.CursorCommitResult; import org.zalando.nakadi.view.SubscriptionCursor; import org.zalando.nakadi.view.SubscriptionCursorWithoutToken; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; -import org.zalando.problem.spring.web.advice.Responses; import javax.validation.Valid; import javax.validation.constraints.NotNull; -import javax.ws.rs.core.Response; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.springframework.http.ResponseEntity.noContent; import static org.springframework.http.ResponseEntity.ok; -import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; -import static org.zalando.problem.spring.web.advice.Responses.create; +import static org.zalando.problem.Status.INTERNAL_SERVER_ERROR; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; @RestController -public class CursorsController { +public class CursorsController extends NakadiProblemControllerAdvice { private static final Logger LOG = LoggerFactory.getLogger(CursorsController.class); @@ -152,39 +145,19 @@ private List convertToNakadiCursors( return nakadiCursors; } - @ExceptionHandler(InvalidStreamIdException.class) - public ResponseEntity handleInvalidStreamId(final InvalidStreamIdException ex, - final NativeWebRequest request) { - LOG.warn("Stream id {} is not found: {}", ex.getStreamId(), ex.getMessage()); - return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, ex.getMessage(), request); - } - + @Override @ExceptionHandler(UnableProcessException.class) - public ResponseEntity handleUnableProcessException(final RuntimeException ex, + public ResponseEntity handleUnableProcessException(final UnableProcessException ex, final NativeWebRequest request) { LOG.debug(ex.getMessage(), ex); - return Responses.create(SERVICE_UNAVAILABLE, ex.getMessage(), request); - } - - @ExceptionHandler(RequestInProgressException.class) - public ResponseEntity handleRequestInProgressException(final RequestInProgressException ex, - final NativeWebRequest request) { - LOG.debug(ex.getMessage(), ex); - return Responses.create(Response.Status.CONFLICT, ex.getMessage(), request); + return create(Problem.valueOf(SERVICE_UNAVAILABLE, ex.getMessage()), request); } + @Override @ExceptionHandler(MethodArgumentNotValidException.class) - public ResponseEntity handleMethodArgumentNotValidException(final MethodArgumentNotValidException ex, - final NativeWebRequest request) { - LOG.debug(ex.getMessage(), ex); - return Responses.create(new ValidationProblem(ex.getBindingResult()), request); - } - - @ExceptionHandler(FeatureNotAvailableException.class) - public ResponseEntity handleFeatureNotAllowed(final FeatureNotAvailableException ex, - final NativeWebRequest request) { + public ResponseEntity handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, + final NativeWebRequest request) { LOG.debug(ex.getMessage(), ex); - return Responses.create(Problem.valueOf(Response.Status.NOT_IMPLEMENTED, "Feature is disabled"), request); + return create(new ValidationProblem(ex.getBindingResult()), request); } - } diff --git a/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java b/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java index f74b47c35d..160585864c 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventPublishingController.java @@ -29,21 +29,20 @@ import org.zalando.nakadi.service.NakadiKpiPublisher; import org.zalando.problem.Problem; import org.zalando.problem.ThrowableProblem; -import org.zalando.problem.spring.web.advice.Responses; -import javax.ws.rs.core.Response; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.springframework.http.ResponseEntity.status; import static org.springframework.web.bind.annotation.RequestMethod.POST; -import static org.zalando.problem.spring.web.advice.Responses.create; +import static org.zalando.problem.Status.BAD_REQUEST; +import static org.zalando.problem.Status.FORBIDDEN; +import static org.zalando.problem.Status.INTERNAL_SERVER_ERROR; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; @RestController -public class EventPublishingController { +public class EventPublishingController extends NakadiProblemControllerAdvice { private static final Logger LOG = LoggerFactory.getLogger(EventPublishingController.class); @@ -77,8 +76,8 @@ public ResponseEntity postEvent(@PathVariable final String eventTypeName, try { if (blacklistService.isProductionBlocked(eventTypeName, client.getClientId())) { - return Responses.create( - Problem.valueOf(Response.Status.FORBIDDEN, "Application or event type is blocked"), request); + return create( + Problem.valueOf(FORBIDDEN, "Application or event type is blocked"), request); } final ResponseEntity response = postEventInternal( @@ -86,7 +85,7 @@ public ResponseEntity postEvent(@PathVariable final String eventTypeName, eventTypeMetrics.incrementResponseCount(response.getStatusCode().value()); return response; } catch (final RuntimeException ex) { - eventTypeMetrics.incrementResponseCount(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); + eventTypeMetrics.incrementResponseCount(INTERNAL_SERVER_ERROR.getStatusCode()); throw ex; } } @@ -162,11 +161,11 @@ private ResponseEntity processJSONException(final JSONException e, final NativeW if (e.getCause() == null) { return create(createProblem(e), nativeWebRequest); } - return create(Problem.valueOf(Response.Status.BAD_REQUEST), nativeWebRequest); + return create(Problem.valueOf(BAD_REQUEST), nativeWebRequest); } private ThrowableProblem createProblem(final JSONException e) { - return Problem.valueOf(Response.Status.BAD_REQUEST, "Error occurred when parsing event(s). " + e.getMessage()); + return Problem.valueOf(BAD_REQUEST, "Error occurred when parsing event(s). " + e.getMessage()); } private ResponseEntity response(final EventPublishResult result) { diff --git a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java index d6a441d35a..97d5ecd479 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventStreamController.java @@ -49,13 +49,12 @@ import org.zalando.nakadi.service.timeline.TimelineService; import org.zalando.nakadi.util.FlowIdUtils; import org.zalando.nakadi.view.Cursor; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; +import org.zalando.problem.StatusType; import javax.annotation.Nullable; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.core.Response; import java.io.Closeable; import java.io.IOException; import java.io.OutputStream; @@ -67,14 +66,15 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; -import static javax.ws.rs.core.Response.Status.BAD_REQUEST; -import static javax.ws.rs.core.Response.Status.FORBIDDEN; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.PRECONDITION_FAILED; -import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.zalando.nakadi.metrics.MetricUtils.metricNameFor; -import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; +import static org.zalando.problem.Status.BAD_REQUEST; +import static org.zalando.problem.Status.FORBIDDEN; +import static org.zalando.problem.Status.INTERNAL_SERVER_ERROR; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.PRECONDITION_FAILED; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; +import static org.zalando.problem.Status.TOO_MANY_REQUESTS; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; @RestController public class EventStreamController { @@ -202,7 +202,7 @@ public StreamingResponseBody streamEvents( if (blacklistService.isConsumptionBlocked(eventTypeName, client.getClientId())) { writeProblemResponse(response, outputStream, - Problem.valueOf(Response.Status.FORBIDDEN, "Application or event type is blocked")); + Problem.valueOf(FORBIDDEN, "Application or event type is blocked")); return; } @@ -269,7 +269,7 @@ public StreamingResponseBody streamEvents( } catch (final NoConnectionSlotsException e) { LOG.debug("Connection creation failed due to exceeding max connection count"); writeProblemResponse(response, outputStream, - Problem.valueOf(MoreStatus.TOO_MANY_REQUESTS, e.getMessage())); + Problem.valueOf(TOO_MANY_REQUESTS, e.getMessage())); } catch (final ServiceTemporarilyUnavailableException e) { LOG.error("Error while trying to stream events.", e); writeProblemResponse(response, outputStream, SERVICE_UNAVAILABLE, e.getMessage()); @@ -314,7 +314,7 @@ private String getKafkaQuotaClientId(final String eventTypeName, final Client cl } private void writeProblemResponse(final HttpServletResponse response, final OutputStream outputStream, - final Response.StatusType statusCode, final String message) throws IOException { + final StatusType statusCode, final String message) throws IOException { writeProblemResponse(response, outputStream, Problem.valueOf(statusCode, message)); } diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index 306513274e..304541254c 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -8,7 +8,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.Errors; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -23,8 +22,6 @@ import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; import org.zalando.nakadi.exceptions.runtime.EventTypeDeletionException; -import org.zalando.nakadi.exceptions.runtime.EventTypeOptionsValidationException; -import org.zalando.nakadi.exceptions.runtime.EventTypeUnavailableException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; @@ -41,22 +38,18 @@ import org.zalando.nakadi.service.AdminService; import org.zalando.nakadi.service.EventTypeService; import org.zalando.nakadi.service.FeatureToggleService; -import org.zalando.problem.Problem; -import org.zalando.problem.spring.web.advice.Responses; import javax.validation.Valid; -import javax.ws.rs.core.Response; import java.util.List; import java.util.stream.Collectors; import static org.springframework.http.ResponseEntity.status; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DISABLE_EVENT_TYPE_CREATION; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DISABLE_EVENT_TYPE_DELETION; -import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; @RestController @RequestMapping(value = "/event-types") -public class EventTypeController { +public class EventTypeController extends NakadiProblemControllerAdvice { private static final Logger LOG = LoggerFactory.getLogger(TimelinesController.class); @@ -97,7 +90,7 @@ public ResponseEntity create(@Valid @RequestBody final EventTypeBase eventTyp } if (errors.hasErrors()) { - return Responses.create(new ValidationProblem(errors), request); + return create(new ValidationProblem(errors), request); } eventTypeService.create(eventType); @@ -135,7 +128,7 @@ public ResponseEntity update( UnableProcessException, NoSuchPartitionStrategyException{ if (errors.hasErrors()) { - return Responses.create(new ValidationProblem(errors), request); + return create(new ValidationProblem(errors), request); } eventTypeService.update(name, eventType); @@ -168,59 +161,4 @@ private HttpHeaders generateWarningHeaders(final EventTypeBase eventType) { return headers; } - - @ExceptionHandler(EventTypeDeletionException.class) - public ResponseEntity deletion(final EventTypeDeletionException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); - return Responses.create(Response.Status.INTERNAL_SERVER_ERROR, exception.getMessage(), request); - } - - @ExceptionHandler(UnableProcessException.class) - public ResponseEntity unableProcess(final UnableProcessException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } - - @ExceptionHandler(ConflictException.class) - public ResponseEntity conflict(final ConflictException exception, final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); - return Responses.create(Response.Status.CONFLICT, exception.getMessage(), request); - } - - @ExceptionHandler(EventTypeUnavailableException.class) - public ResponseEntity eventTypeUnavailable(final EventTypeUnavailableException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); - return Responses.create(Response.Status.SERVICE_UNAVAILABLE, exception.getMessage(), request); - } - - @ExceptionHandler(NoSuchPartitionStrategyException.class) - public ResponseEntity noSuchPartitionStrategyException(final NoSuchPartitionStrategyException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); - return Responses.create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); - } - - @ExceptionHandler(DuplicatedEventTypeNameException.class) - public ResponseEntity duplicatedEventTypeNameException(final DuplicatedEventTypeNameException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); - return Responses.create(Problem.valueOf(Response.Status.CONFLICT, exception.getMessage()), request); - } - - @ExceptionHandler(InvalidEventTypeException.class) - public ResponseEntity invalidEventTypeException(final InvalidEventTypeException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); - return Responses.create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); - } - - @ExceptionHandler(EventTypeOptionsValidationException.class) - public ResponseEntity unableProcess(final EventTypeOptionsValidationException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } } diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java deleted file mode 100644 index f47f8d3cd7..0000000000 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ /dev/null @@ -1,327 +0,0 @@ -package org.zalando.nakadi.controller; - -import com.fasterxml.jackson.databind.JsonMappingException; -import com.google.common.base.CaseFormat; -import org.apache.commons.lang3.RandomStringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.ResponseEntity; -import org.springframework.http.converter.HttpMessageNotReadableException; -import org.springframework.web.bind.annotation.ControllerAdvice; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.context.request.NativeWebRequest; -import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; -import org.zalando.nakadi.exceptions.runtime.CompactionException; -import org.zalando.nakadi.exceptions.runtime.CursorConversionException; -import org.zalando.nakadi.exceptions.runtime.CursorsAreEmptyException; -import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; -import org.zalando.nakadi.exceptions.runtime.DuplicatedStorageException; -import org.zalando.nakadi.exceptions.runtime.EnrichmentException; -import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; -import org.zalando.nakadi.exceptions.runtime.IllegalClientIdException; -import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; -import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; -import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; -import org.zalando.nakadi.exceptions.runtime.InvalidVersionNumberException; -import org.zalando.nakadi.exceptions.runtime.LimitReachedException; -import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; -import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; -import org.zalando.nakadi.exceptions.runtime.NoStreamingSlotsAvailable; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; -import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; -import org.zalando.nakadi.exceptions.runtime.NoSuchSchemaException; -import org.zalando.nakadi.exceptions.runtime.NoSuchStorageException; -import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; -import org.zalando.nakadi.exceptions.runtime.PartitioningException; -import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; -import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; -import org.zalando.nakadi.exceptions.runtime.StorageIsUsedException; -import org.zalando.nakadi.exceptions.runtime.TimelineException; -import org.zalando.nakadi.exceptions.runtime.TopicCreationException; -import org.zalando.nakadi.exceptions.runtime.UnknownStorageTypeException; -import org.zalando.nakadi.exceptions.runtime.UnprocessableEntityException; -import org.zalando.nakadi.exceptions.runtime.UnprocessableSubscriptionException; -import org.zalando.problem.MoreStatus; -import org.zalando.problem.Problem; -import org.zalando.problem.spring.web.advice.ProblemHandling; -import org.zalando.problem.spring.web.advice.Responses; - -import javax.ws.rs.core.Response; - -import static javax.ws.rs.core.Response.Status.BAD_REQUEST; -import static javax.ws.rs.core.Response.Status.CONFLICT; -import static javax.ws.rs.core.Response.Status.FORBIDDEN; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.NOT_IMPLEMENTED; -import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; - - -@ControllerAdvice -public final class ExceptionHandling implements ProblemHandling { - - private static final Logger LOG = LoggerFactory.getLogger(ExceptionHandling.class); - - @Override - public String formatFieldName(final String fieldName) { - return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fieldName); - } - - @Override - @ExceptionHandler - public ResponseEntity handleThrowable(final Throwable throwable, final NativeWebRequest request) { - final String errorTraceId = generateErrorTraceId(); - LOG.error("InternalServerError (" + errorTraceId + "):", throwable); - return Responses.create(Response.Status.INTERNAL_SERVER_ERROR, "An internal error happened. Please report it. (" - + errorTraceId + ")", request); - } - - private String generateErrorTraceId() { - return "ETI" + RandomStringUtils.randomAlphanumeric(24); - } - - @Override - @ExceptionHandler - public ResponseEntity handleMessageNotReadableException(final HttpMessageNotReadableException exception, - final NativeWebRequest request) { - /* - Unwrap nested JsonMappingException because the enclosing HttpMessageNotReadableException adds some ugly, Java - class and stacktrace like information. - */ - final Throwable mostSpecificCause = exception.getMostSpecificCause(); - final String message; - if (mostSpecificCause instanceof JsonMappingException) { - message = mostSpecificCause.getMessage(); - } else { - message = exception.getMessage(); - } - return Responses.create(Response.Status.BAD_REQUEST, message, request); - } - - @ExceptionHandler(AccessDeniedException.class) - public ResponseEntity accessDeniedException(final AccessDeniedException exception, - final NativeWebRequest request) { - return Responses.create(Response.Status.FORBIDDEN, exception.explain(), request); - } - - @ExceptionHandler(IllegalClientIdException.class) - public ResponseEntity handleIllegalClientIdException(final IllegalClientIdException exception, - final NativeWebRequest request) { - return Responses.create(Response.Status.FORBIDDEN, exception.getMessage(), request); - } - - @ExceptionHandler(CursorsAreEmptyException.class) - public ResponseEntity handleCursorsUnavailableException(final RuntimeException ex, - final NativeWebRequest request) { - LOG.debug(ex.getMessage(), ex); - return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, ex.getMessage(), request); - } - - @ExceptionHandler - public ResponseEntity handleExceptionWrapper(final NakadiRuntimeException exception, - final NativeWebRequest request) throws Exception { - final Throwable cause = exception.getCause(); - if (cause instanceof InternalNakadiException) { - return Responses.create(INTERNAL_SERVER_ERROR, exception.getMessage(), request); - } - throw exception.getException(); - } - - @ExceptionHandler(RepositoryProblemException.class) - public ResponseEntity handleRepositoryProblem(final RepositoryProblemException exception, - final NativeWebRequest request) { - LOG.error("Repository problem occurred", exception); - return Responses.create(Response.Status.SERVICE_UNAVAILABLE, exception.getMessage(), request); - } - - @ExceptionHandler(NakadiBaseException.class) - public ResponseEntity handleInternalError(final NakadiBaseException exception, - final NativeWebRequest request) { - LOG.error("Unexpected problem occurred", exception); - return Responses.create(Response.Status.INTERNAL_SERVER_ERROR, exception.getMessage(), request); - } - - @ExceptionHandler(TimelineException.class) - public ResponseEntity handleTimelineException(final TimelineException exception, - final NativeWebRequest request) { - LOG.error(exception.getMessage(), exception); - final Throwable cause = exception.getCause(); - if (cause instanceof InternalNakadiException) { - return Responses.create(Problem.valueOf(INTERNAL_SERVER_ERROR, exception.getMessage()), request); - } - return Responses.create(Response.Status.SERVICE_UNAVAILABLE, exception.getMessage(), request); - } - - @ExceptionHandler(TopicCreationException.class) - public ResponseEntity handleTopicCreationException(final TopicCreationException exception, - final NativeWebRequest request) { - LOG.error(exception.getMessage(), exception); - return Responses.create(Response.Status.SERVICE_UNAVAILABLE, exception.getMessage(), request); - } - - @ExceptionHandler(CursorConversionException.class) - public ResponseEntity handleCursorConversionException(final CursorConversionException exception, - final NativeWebRequest request) { - LOG.error(exception.getMessage(), exception); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } - - @ExceptionHandler(ServiceTemporarilyUnavailableException.class) - public ResponseEntity handleServiceTemporarilyUnavailableException( - final ServiceTemporarilyUnavailableException exception, final NativeWebRequest request) { - LOG.error(exception.getMessage(), exception); - return Responses.create(Response.Status.SERVICE_UNAVAILABLE, exception.getMessage(), request); - } - - @ExceptionHandler(LimitReachedException.class) - public ResponseEntity handleLimitReachedException( - final ServiceTemporarilyUnavailableException exception, final NativeWebRequest request) { - LOG.warn(exception.getMessage()); - return Responses.create(MoreStatus.TOO_MANY_REQUESTS, exception.getMessage(), request); - } - - @ExceptionHandler(DbWriteOperationsBlockedException.class) - public ResponseEntity handleDbWriteOperationsBlockedException( - final DbWriteOperationsBlockedException exception, final NativeWebRequest request) { - LOG.warn(exception.getMessage()); - return Responses.create(Response.Status.SERVICE_UNAVAILABLE, - "Database is currently in read-only mode", request); - } - - @ExceptionHandler(FeatureNotAvailableException.class) - public ResponseEntity handleFeatureNotAvailable( - final FeatureNotAvailableException ex, - final NativeWebRequest request) { - LOG.debug(ex.getMessage()); - return Responses.create(Problem.valueOf(NOT_IMPLEMENTED, ex.getMessage()), request); - } - - @ExceptionHandler(CompactionException.class) - public ResponseEntity handleCompactionException(final CompactionException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } - - @ExceptionHandler(EnrichmentException.class) - public ResponseEntity handleEnrichmentException(final EnrichmentException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } - - @ExceptionHandler(NoSuchPartitionStrategyException.class) - public ResponseEntity handleNoSuchPartitionStrategyException( - final NoSuchPartitionStrategyException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } - - @ExceptionHandler(PartitioningException.class) - public ResponseEntity handlePartitioningException(final PartitioningException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } - - @ExceptionHandler(InvalidPartitionKeyFieldsException.class) - public ResponseEntity handleInvalidPartitionKeyFieldsException( - final InvalidPartitionKeyFieldsException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } - - @ExceptionHandler(NoSuchEventTypeException.class) - public ResponseEntity handleNoSuchEventTypeException(final NoSuchEventTypeException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(NOT_FOUND, exception.getMessage(), request); - } - - @ExceptionHandler(NoSuchSchemaException.class) - public ResponseEntity handleNoSuchSchemaException(final NoSuchSchemaException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(NOT_FOUND, exception.getMessage(), request); - } - - @ExceptionHandler(NoSuchSubscriptionException.class) - public ResponseEntity handleNoSuchSubscriptionException(final NoSuchSubscriptionException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(NOT_FOUND, exception.getMessage(), request); - } - - @ExceptionHandler(NoStreamingSlotsAvailable.class) - public ResponseEntity handleNoStreamingSlotsAvailable(final NoStreamingSlotsAvailable exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(CONFLICT, exception.getMessage(), request); - } - - @ExceptionHandler(UnprocessableSubscriptionException.class) - public ResponseEntity handleUnprocessableSubscriptionException( - final UnprocessableSubscriptionException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } - - @ExceptionHandler(InvalidLimitException.class) - public ResponseEntity handleInvalidLimitException( - final InvalidLimitException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(BAD_REQUEST, exception.getMessage(), request); - } - - @ExceptionHandler(InvalidVersionNumberException.class) - public ResponseEntity handleInvalidVersionNumberException( - final InvalidVersionNumberException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(BAD_REQUEST, exception.getMessage(), request); - } - - @ExceptionHandler(DuplicatedStorageException.class) - public ResponseEntity handleDuplicatedStorageException( - final DuplicatedStorageException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(CONFLICT, exception.getMessage(), request); - } - - @ExceptionHandler(UnknownStorageTypeException.class) - public ResponseEntity handleUnknownStorageTypeException( - final UnknownStorageTypeException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } - - @ExceptionHandler(UnprocessableEntityException.class) - public ResponseEntity handleUnprocessableEntityException( - final UnprocessableEntityException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } - - @ExceptionHandler(NoSuchStorageException.class) - public ResponseEntity handleNoSuchStorageException( - final NoSuchStorageException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(NOT_FOUND, exception.getMessage(), request); - } - - @ExceptionHandler(StorageIsUsedException.class) - public ResponseEntity handleStorageIsUsedException( - final StorageIsUsedException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(FORBIDDEN, exception.getMessage(), request); - } -} diff --git a/src/main/java/org/zalando/nakadi/controller/HealthCheckController.java b/src/main/java/org/zalando/nakadi/controller/HealthCheckController.java index 0daaa19bb0..d181a904c9 100644 --- a/src/main/java/org/zalando/nakadi/controller/HealthCheckController.java +++ b/src/main/java/org/zalando/nakadi/controller/HealthCheckController.java @@ -4,13 +4,12 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import javax.ws.rs.core.MediaType; - +import static org.springframework.http.MediaType.TEXT_PLAIN_VALUE; import static org.springframework.http.ResponseEntity.ok; import static org.springframework.web.bind.annotation.RequestMethod.GET; @RestController -@RequestMapping(value = "/health", produces = MediaType.TEXT_PLAIN) +@RequestMapping(value = "/health", produces = TEXT_PLAIN_VALUE) public class HealthCheckController { @RequestMapping(method = GET) diff --git a/src/main/java/org/zalando/nakadi/controller/NakadiProblemControllerAdvice.java b/src/main/java/org/zalando/nakadi/controller/NakadiProblemControllerAdvice.java new file mode 100644 index 0000000000..0d83c8288b --- /dev/null +++ b/src/main/java/org/zalando/nakadi/controller/NakadiProblemControllerAdvice.java @@ -0,0 +1,7 @@ +package org.zalando.nakadi.controller; + +import org.springframework.web.bind.annotation.ControllerAdvice; + +@ControllerAdvice +public class NakadiProblemControllerAdvice implements NakadiProblemHandling { +} diff --git a/src/main/java/org/zalando/nakadi/controller/NakadiProblemHandling.java b/src/main/java/org/zalando/nakadi/controller/NakadiProblemHandling.java new file mode 100644 index 0000000000..db9c8c012d --- /dev/null +++ b/src/main/java/org/zalando/nakadi/controller/NakadiProblemHandling.java @@ -0,0 +1,473 @@ +package org.zalando.nakadi.controller; + +import com.fasterxml.jackson.databind.JsonMappingException; +import com.google.common.base.CaseFormat; +import org.apache.commons.lang3.RandomStringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.NativeWebRequest; +import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; +import org.zalando.nakadi.exceptions.runtime.CompactionException; +import org.zalando.nakadi.exceptions.runtime.ConflictException; +import org.zalando.nakadi.exceptions.runtime.CursorConversionException; +import org.zalando.nakadi.exceptions.runtime.CursorsAreEmptyException; +import org.zalando.nakadi.exceptions.runtime.DbWriteOperationsBlockedException; +import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; +import org.zalando.nakadi.exceptions.runtime.DuplicatedStorageException; +import org.zalando.nakadi.exceptions.runtime.EnrichmentException; +import org.zalando.nakadi.exceptions.runtime.ErrorGettingCursorTimeLagException; +import org.zalando.nakadi.exceptions.runtime.EventTypeDeletionException; +import org.zalando.nakadi.exceptions.runtime.EventTypeOptionsValidationException; +import org.zalando.nakadi.exceptions.runtime.EventTypeUnavailableException; +import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; +import org.zalando.nakadi.exceptions.runtime.IllegalClientIdException; +import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; +import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; +import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; +import org.zalando.nakadi.exceptions.runtime.InvalidLimitException; +import org.zalando.nakadi.exceptions.runtime.InvalidPartitionKeyFieldsException; +import org.zalando.nakadi.exceptions.runtime.InvalidStreamIdException; +import org.zalando.nakadi.exceptions.runtime.InvalidVersionNumberException; +import org.zalando.nakadi.exceptions.runtime.LimitReachedException; +import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; +import org.zalando.nakadi.exceptions.runtime.NakadiRuntimeException; +import org.zalando.nakadi.exceptions.runtime.NoStreamingSlotsAvailable; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchPartitionStrategyException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSchemaException; +import org.zalando.nakadi.exceptions.runtime.NoSuchStorageException; +import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.NotFoundException; +import org.zalando.nakadi.exceptions.runtime.PartitioningException; +import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; +import org.zalando.nakadi.exceptions.runtime.RequestInProgressException; +import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; +import org.zalando.nakadi.exceptions.runtime.StorageIsUsedException; +import org.zalando.nakadi.exceptions.runtime.TimeLagStatsTimeoutException; +import org.zalando.nakadi.exceptions.runtime.TimelineException; +import org.zalando.nakadi.exceptions.runtime.TooManyPartitionsException; +import org.zalando.nakadi.exceptions.runtime.TopicCreationException; +import org.zalando.nakadi.exceptions.runtime.UnableProcessException; +import org.zalando.nakadi.exceptions.runtime.UnknownOperationException; +import org.zalando.nakadi.exceptions.runtime.UnknownStorageTypeException; +import org.zalando.nakadi.exceptions.runtime.UnprocessableEntityException; +import org.zalando.nakadi.exceptions.runtime.UnprocessableSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.WrongInitialCursorsException; +import org.zalando.nakadi.exceptions.runtime.WrongStreamParametersException; +import org.zalando.problem.Problem; +import org.zalando.problem.spring.web.advice.ProblemHandling; + +import static org.zalando.problem.Status.BAD_REQUEST; +import static org.zalando.problem.Status.CONFLICT; +import static org.zalando.problem.Status.FORBIDDEN; +import static org.zalando.problem.Status.INTERNAL_SERVER_ERROR; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.NOT_IMPLEMENTED; +import static org.zalando.problem.Status.REQUEST_TIMEOUT; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; +import static org.zalando.problem.Status.TOO_MANY_REQUESTS; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; + + +public interface NakadiProblemHandling extends ProblemHandling { + + Logger LOG = LoggerFactory.getLogger(NakadiProblemHandling.class); + + String INVALID_CURSOR_MESSAGE = "invalid consumed_offset or partition"; + + @Override + default String formatFieldName(final String fieldName) { + return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fieldName); + } + + @Override + @ExceptionHandler + default ResponseEntity handleThrowable(final Throwable throwable, final NativeWebRequest request) { + final String errorTraceId = generateErrorTraceId(); + LOG.error("InternalServerError (" + errorTraceId + "):", throwable); + return create(Problem.valueOf(INTERNAL_SERVER_ERROR, "An internal error happened. Please report it. (" + + errorTraceId + ")"), request); + } + + default String generateErrorTraceId() { + return "ETI" + RandomStringUtils.randomAlphanumeric(24); + } + + @Override + @ExceptionHandler + default ResponseEntity handleMessageNotReadableException(final HttpMessageNotReadableException exception, + final NativeWebRequest request) { + /* + Unwrap nested JsonMappingException because the enclosing HttpMessageNotReadableException adds some ugly, Java + class and stacktrace like information. + */ + final Throwable mostSpecificCause = exception.getMostSpecificCause(); + final String message; + if (mostSpecificCause instanceof JsonMappingException) { + message = mostSpecificCause.getMessage(); + } else { + message = exception.getMessage(); + } + return create(Problem.valueOf(BAD_REQUEST, message), request); + } + + @ExceptionHandler(AccessDeniedException.class) + default ResponseEntity handleAccessDeniedException(final AccessDeniedException exception, + final NativeWebRequest request) { + return create(Problem.valueOf(FORBIDDEN, exception.explain()), request); + } + + @ExceptionHandler(CompactionException.class) + default ResponseEntity handleCompactionException(final CompactionException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(ConflictException.class) + default ResponseEntity handleConflictException(final ConflictException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(CONFLICT, exception.getMessage()), request); + } + + @ExceptionHandler(CursorsAreEmptyException.class) + default ResponseEntity handleCursorsAreEmptyException(final RuntimeException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(CursorConversionException.class) + default ResponseEntity handleCursorConversionException(final CursorConversionException exception, + final NativeWebRequest request) { + LOG.error(exception.getMessage(), exception); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(DbWriteOperationsBlockedException.class) + default ResponseEntity handleDbWriteOperationsBlockedException( + final DbWriteOperationsBlockedException exception, final NativeWebRequest request) { + LOG.warn(exception.getMessage()); + return create(Problem.valueOf(SERVICE_UNAVAILABLE, + "Database is currently in read-only mode"), request); + } + + @ExceptionHandler(DuplicatedEventTypeNameException.class) + default ResponseEntity handleDuplicatedEventTypeNameException( + final DuplicatedEventTypeNameException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(CONFLICT, exception.getMessage()), request); + } + + @ExceptionHandler(DuplicatedStorageException.class) + default ResponseEntity handleDuplicatedStorageException( + final DuplicatedStorageException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(CONFLICT, exception.getMessage()), request); + } + + @ExceptionHandler(EnrichmentException.class) + default ResponseEntity handleEnrichmentException(final EnrichmentException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(ErrorGettingCursorTimeLagException.class) + default ResponseEntity handleErrorGettingCursorTimeLagException( + final ErrorGettingCursorTimeLagException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(EventTypeDeletionException.class) + default ResponseEntity handleEventTypeDeletionException(final EventTypeDeletionException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(INTERNAL_SERVER_ERROR, exception.getMessage()), request); + } + + @ExceptionHandler(EventTypeOptionsValidationException.class) + default ResponseEntity handleEventTypeOptionsValidationException( + final EventTypeOptionsValidationException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(EventTypeUnavailableException.class) + default ResponseEntity handleEventTypeUnavailableException(final EventTypeUnavailableException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(SERVICE_UNAVAILABLE, exception.getMessage()), request); + } + + @ExceptionHandler(FeatureNotAvailableException.class) + default ResponseEntity handleFeatureNotAvailableException( + final FeatureNotAvailableException ex, + final NativeWebRequest request) { + LOG.debug(ex.getMessage()); + return create(Problem.valueOf(NOT_IMPLEMENTED, ex.getMessage()), request); + } + + @ExceptionHandler(IllegalClientIdException.class) + default ResponseEntity handleIllegalClientIdException(final IllegalClientIdException exception, + final NativeWebRequest request) { + return create(Problem.valueOf(FORBIDDEN, exception.getMessage()), request); + } + + @ExceptionHandler(InconsistentStateException.class) + default ResponseEntity handleInconsistentStateExcetpion(final InconsistentStateException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(SERVICE_UNAVAILABLE, exception.getMessage()), request); + } + + @ExceptionHandler(InvalidCursorOperation.class) + default ResponseEntity handleInvalidCursorOperation(final InvalidCursorOperation exception, + final NativeWebRequest request) { + LOG.debug("User provided invalid cursor for operation. Reason: " + exception.getReason(), exception); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, INVALID_CURSOR_MESSAGE), request); + } + + @ExceptionHandler(InvalidEventTypeException.class) + default ResponseEntity handleInvalidEventTypeException(final InvalidEventTypeException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(InvalidLimitException.class) + default ResponseEntity handleInvalidLimitException( + final InvalidLimitException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(BAD_REQUEST, exception.getMessage()), request); + } + + @ExceptionHandler(InvalidPartitionKeyFieldsException.class) + default ResponseEntity handleInvalidPartitionKeyFieldsException( + final InvalidPartitionKeyFieldsException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(InvalidStreamIdException.class) + default ResponseEntity handleInvalidStreamIdException(final InvalidStreamIdException exception, + final NativeWebRequest request) { + LOG.warn("Stream id {} is not found: {}", exception.getStreamId(), exception.getMessage()); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(InvalidVersionNumberException.class) + default ResponseEntity handleInvalidVersionNumberException( + final InvalidVersionNumberException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(BAD_REQUEST, exception.getMessage()), request); + } + + @ExceptionHandler(LimitReachedException.class) + default ResponseEntity handleLimitReachedException( + final ServiceTemporarilyUnavailableException exception, final NativeWebRequest request) { + LOG.warn(exception.getMessage()); + return create(Problem.valueOf(TOO_MANY_REQUESTS, exception.getMessage()), request); + } + + @ExceptionHandler(NakadiBaseException.class) + default ResponseEntity handleNakadiBaseException(final NakadiBaseException exception, + final NativeWebRequest request) { + LOG.error("Unexpected problem occurred", exception); + return create(Problem.valueOf(INTERNAL_SERVER_ERROR, exception.getMessage()), request); + } + + @ExceptionHandler + default ResponseEntity handleNakadiRuntimeException(final NakadiRuntimeException exception, + final NativeWebRequest request) throws Exception { + final Throwable cause = exception.getCause(); + if (cause instanceof InternalNakadiException) { + return create(Problem.valueOf(INTERNAL_SERVER_ERROR, exception.getMessage()), request); + } + throw exception.getException(); + } + + @ExceptionHandler(NotFoundException.class) + default ResponseEntity handleNotFoundException(final NotFoundException exception, + final NativeWebRequest request) { + LOG.error(exception.getMessage(), exception); + return create(Problem.valueOf(NOT_FOUND, exception.getMessage()), request); + } + + @ExceptionHandler(NoStreamingSlotsAvailable.class) + default ResponseEntity handleNoStreamingSlotsAvailable(final NoStreamingSlotsAvailable exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(CONFLICT, exception.getMessage()), request); + } + + @ExceptionHandler(NoSuchEventTypeException.class) + default ResponseEntity handleNoSuchEventTypeException(final NoSuchEventTypeException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(NOT_FOUND, exception.getMessage()), request); + } + + @ExceptionHandler(NoSuchPartitionStrategyException.class) + default ResponseEntity handleNoSuchPartitionStrategyException( + final NoSuchPartitionStrategyException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(NoSuchSchemaException.class) + default ResponseEntity handleNoSuchSchemaException(final NoSuchSchemaException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(NOT_FOUND, exception.getMessage()), request); + } + + @ExceptionHandler(NoSuchStorageException.class) + default ResponseEntity handleNoSuchStorageException( + final NoSuchStorageException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(NOT_FOUND, exception.getMessage()), request); + } + + @ExceptionHandler(NoSuchSubscriptionException.class) + default ResponseEntity handleNoSuchSubscriptionException(final NoSuchSubscriptionException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(NOT_FOUND, exception.getMessage()), request); + } + + @ExceptionHandler(PartitioningException.class) + default ResponseEntity handlePartitioningException(final PartitioningException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(RepositoryProblemException.class) + default ResponseEntity handleRepositoryProblemException(final RepositoryProblemException exception, + final NativeWebRequest request) { + LOG.error("Repository problem occurred", exception); + return create(Problem.valueOf(SERVICE_UNAVAILABLE, exception.getMessage()), request); + } + + @ExceptionHandler(RequestInProgressException.class) + default ResponseEntity handleRequestInProgressException(final RequestInProgressException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(CONFLICT, exception.getMessage()), request); + } + + @ExceptionHandler(ServiceTemporarilyUnavailableException.class) + default ResponseEntity handleServiceTemporarilyUnavailableException( + final ServiceTemporarilyUnavailableException exception, final NativeWebRequest request) { + LOG.error(exception.getMessage(), exception); + return create(Problem.valueOf(SERVICE_UNAVAILABLE, exception.getMessage()), request); + } + + @ExceptionHandler(StorageIsUsedException.class) + default ResponseEntity handleStorageIsUsedException( + final StorageIsUsedException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(FORBIDDEN, exception.getMessage()), request); + } + + @ExceptionHandler(TimeLagStatsTimeoutException.class) + default ResponseEntity handleTimeLagStatsTimeoutException(final TimeLagStatsTimeoutException exception, + final NativeWebRequest request) { + LOG.warn(exception.getMessage()); + return create(Problem.valueOf(REQUEST_TIMEOUT, exception.getMessage()), request); + } + + @ExceptionHandler(TimelineException.class) + default ResponseEntity handleTimelineException(final TimelineException exception, + final NativeWebRequest request) { + LOG.error(exception.getMessage(), exception); + final Throwable cause = exception.getCause(); + if (cause instanceof InternalNakadiException) { + return create(Problem.valueOf(INTERNAL_SERVER_ERROR, exception.getMessage()), request); + } + return create(Problem.valueOf(SERVICE_UNAVAILABLE, exception.getMessage()), request); + } + + @ExceptionHandler(TooManyPartitionsException.class) + default ResponseEntity handleTooManyPartitionsException(final TooManyPartitionsException exception, + final NativeWebRequest request) { + LOG.debug("Error occurred when working with subscriptions", exception); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(TopicCreationException.class) + default ResponseEntity handleTopicCreationException(final TopicCreationException exception, + final NativeWebRequest request) { + LOG.error(exception.getMessage(), exception); + return create(Problem.valueOf(SERVICE_UNAVAILABLE, exception.getMessage()), request); + } + + @ExceptionHandler(UnableProcessException.class) + default ResponseEntity handleUnableProcessException(final UnableProcessException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(UnknownOperationException.class) + default ResponseEntity handleUnknownOperationException(final RuntimeException exception, + final NativeWebRequest request) { + LOG.error(exception.getMessage(), exception); + return create(Problem.valueOf(SERVICE_UNAVAILABLE, "There was a problem processing your request."), request); + } + + @ExceptionHandler(UnknownStorageTypeException.class) + default ResponseEntity handleUnknownStorageTypeException( + final UnknownStorageTypeException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(UnprocessableEntityException.class) + default ResponseEntity handleUnprocessableEntityException( + final UnprocessableEntityException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(UnprocessableSubscriptionException.class) + default ResponseEntity handleUnprocessableSubscriptionException( + final UnprocessableSubscriptionException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(WrongInitialCursorsException.class) + default ResponseEntity handleWrongInitialCursorsException(final WrongInitialCursorsException exception, + final NativeWebRequest request) { + LOG.debug("Error occurred when working with subscriptions", exception); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } + + @ExceptionHandler(WrongStreamParametersException.class) + default ResponseEntity handleWrongStreamParametersException(final WrongStreamParametersException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage(), exception); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, exception.getMessage()), request); + } +} diff --git a/src/main/java/org/zalando/nakadi/controller/PartitionsController.java b/src/main/java/org/zalando/nakadi/controller/PartitionsController.java index 19e37ac713..53aebac950 100644 --- a/src/main/java/org/zalando/nakadi/controller/PartitionsController.java +++ b/src/main/java/org/zalando/nakadi/controller/PartitionsController.java @@ -5,7 +5,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -20,7 +19,6 @@ import org.zalando.nakadi.domain.Timeline; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidCursorException; -import org.zalando.nakadi.exceptions.runtime.InvalidCursorOperation; import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NotFoundException; @@ -33,31 +31,27 @@ import org.zalando.nakadi.view.Cursor; import org.zalando.nakadi.view.CursorLag; import org.zalando.nakadi.view.EventTypePartitionView; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; -import org.zalando.problem.spring.web.advice.Responses; import javax.annotation.Nullable; -import javax.ws.rs.core.Response; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.springframework.http.ResponseEntity.ok; -import static org.zalando.problem.spring.web.advice.Responses.create; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; @RestController -public class PartitionsController { +public class PartitionsController extends NakadiProblemControllerAdvice { private static final Logger LOG = LoggerFactory.getLogger(PartitionsController.class); private final TimelineService timelineService; private final CursorConverter cursorConverter; private final CursorOperationsService cursorOperationsService; - private static final String INVALID_CURSOR_MESSAGE = "invalid consumed_offset or partition"; private final EventTypeRepository eventTypeRepository; private final AuthorizationValidator authorizationValidator; @@ -136,24 +130,11 @@ public ResponseEntity getPartition( LOG.error("Could not get partition. Respond with SERVICE_UNAVAILABLE.", e); return create(Problem.valueOf(SERVICE_UNAVAILABLE, e.getMessage()), request); } catch (final InvalidCursorException e) { - return create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, INVALID_CURSOR_MESSAGE), + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, INVALID_CURSOR_MESSAGE), request); } } - @ExceptionHandler(InvalidCursorOperation.class) - public ResponseEntity invalidCursorOperation(final InvalidCursorOperation e, - final NativeWebRequest request) { - LOG.debug("User provided invalid cursor for operation. Reason: " + e.getReason(), e); - return Responses.create(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, INVALID_CURSOR_MESSAGE), request); - } - - @ExceptionHandler(NotFoundException.class) - public ResponseEntity notFound(final NotFoundException ex, final NativeWebRequest request) { - LOG.error(ex.getMessage(), ex); - return Responses.create(Response.Status.NOT_FOUND, ex.getMessage(), request); - } - private CursorLag getCursorLag(final String eventTypeName, final String partition, final String consumedOffset) throws InternalNakadiException, NoSuchEventTypeException, InvalidCursorException, ServiceTemporarilyUnavailableException { diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index b8d0faa9b8..e91e202fe6 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -6,7 +6,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.Errors; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -18,32 +17,28 @@ import org.zalando.nakadi.domain.SubscriptionBase; import org.zalando.nakadi.exceptions.runtime.DuplicatedSubscriptionException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; -import org.zalando.nakadi.exceptions.runtime.NakadiBaseException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.SubscriptionUpdateConflictException; -import org.zalando.nakadi.exceptions.runtime.TooManyPartitionsException; import org.zalando.nakadi.exceptions.runtime.UnprocessableSubscriptionException; -import org.zalando.nakadi.exceptions.runtime.WrongInitialCursorsException; import org.zalando.nakadi.plugin.api.ApplicationService; import org.zalando.nakadi.problem.ValidationProblem; import org.zalando.nakadi.service.FeatureToggleService; import org.zalando.nakadi.service.subscription.SubscriptionService; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; -import org.zalando.problem.spring.web.advice.Responses; import javax.validation.Valid; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.Response; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static org.apache.http.HttpHeaders.CONTENT_LOCATION; import static org.springframework.http.HttpStatus.OK; import static org.zalando.nakadi.service.FeatureToggleService.Feature.DISABLE_SUBSCRIPTION_CREATION; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; @RestController -public class PostSubscriptionController { +public class PostSubscriptionController extends NakadiProblemControllerAdvice { private static final Logger LOG = LoggerFactory.getLogger(PostSubscriptionController.class); @@ -65,15 +60,15 @@ public ResponseEntity createOrGetSubscription(@Valid @RequestBody final Subsc final Errors errors, final NativeWebRequest request) { if (errors.hasErrors()) { - return Responses.create(new ValidationProblem(errors), request); + return create(new ValidationProblem(errors), request); } try { return ok(subscriptionService.getExistingSubscription(subscriptionBase)); } catch (final NoSuchSubscriptionException e) { if (featureToggleService.isFeatureEnabled(DISABLE_SUBSCRIPTION_CREATION)) { - return Responses.create(Response.Status.SERVICE_UNAVAILABLE, - "Subscription creation is temporarily unavailable", request); + return create(Problem.valueOf(SERVICE_UNAVAILABLE, + "Subscription creation is temporarily unavailable"), request); } try { final Subscription subscription = subscriptionService.createSubscription(subscriptionBase); @@ -93,15 +88,15 @@ public ResponseEntity updateSubscription( final Errors errors, final NativeWebRequest request) { if (errors.hasErrors()) { - return Responses.create(new ValidationProblem(errors), request); + return create(new ValidationProblem(errors), request); } try { subscriptionService.updateSubscription(subscriptionId, subscription); return ResponseEntity.noContent().build(); } catch (final SubscriptionUpdateConflictException ex) { - return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, ex.getMessage(), request); + return create(Problem.valueOf(UNPROCESSABLE_ENTITY, ex.getMessage()), request); } catch (final NoSuchSubscriptionException ex) { - return Responses.create(Problem.valueOf(NOT_FOUND, ex.getMessage()), request); + return create(Problem.valueOf(NOT_FOUND, ex.getMessage()), request); } } @@ -114,16 +109,7 @@ private ResponseEntity prepareLocationResponse(final Subscription subscriptio final UriComponents location = subscriptionService.getSubscriptionUri(subscription); return ResponseEntity.status(HttpStatus.CREATED) .location(location.toUri()) - .header(HttpHeaders.CONTENT_LOCATION, location.toString()) + .header(CONTENT_LOCATION, location.toString()) .body(subscription); } - - @ExceptionHandler({ - WrongInitialCursorsException.class, - TooManyPartitionsException.class}) - public ResponseEntity handleUnprocessableSubscription(final NakadiBaseException exception, - final NativeWebRequest request) { - LOG.debug("Error occurred when working with subscriptions", exception); - return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } } diff --git a/src/main/java/org/zalando/nakadi/controller/SettingsController.java b/src/main/java/org/zalando/nakadi/controller/SettingsController.java index 6b0db0317b..2d4923005e 100644 --- a/src/main/java/org/zalando/nakadi/controller/SettingsController.java +++ b/src/main/java/org/zalando/nakadi/controller/SettingsController.java @@ -5,35 +5,27 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.config.SecuritySettings; import org.zalando.nakadi.domain.ItemsWrapper; import org.zalando.nakadi.domain.ResourceAuthorization; -import org.zalando.nakadi.exceptions.runtime.UnableProcessException; -import org.zalando.nakadi.exceptions.runtime.UnknownOperationException; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; import org.zalando.nakadi.security.Client; import org.zalando.nakadi.service.AdminService; import org.zalando.nakadi.service.BlacklistService; import org.zalando.nakadi.service.FeatureToggleService; -import org.zalando.problem.MoreStatus; -import org.zalando.problem.Problem; -import org.zalando.problem.spring.web.advice.Responses; import javax.validation.Valid; -import javax.ws.rs.core.Response; import static org.zalando.nakadi.domain.AdminResource.ADMIN_RESOURCE; @RestController @RequestMapping(value = "/settings") -public class SettingsController { +public class SettingsController extends NakadiProblemControllerAdvice { private static final Logger LOG = LoggerFactory.getLogger(SettingsController.class); private final BlacklistService blacklistService; @@ -116,21 +108,6 @@ public ResponseEntity updateAdmins(@Valid @RequestBody final ResourceAuthoriz return ResponseEntity.ok().build(); } - @ExceptionHandler(UnknownOperationException.class) - public ResponseEntity handleUnknownOperationException(final RuntimeException ex, - final NativeWebRequest request) { - LOG.error(ex.getMessage(), ex); - return Responses.create(Response.Status.SERVICE_UNAVAILABLE, - "There was a problem processing your request.", request); - } - - @ExceptionHandler(UnableProcessException.class) - public ResponseEntity handleUnableProcessException(final RuntimeException ex, - final NativeWebRequest request) { - LOG.error(ex.getMessage(), ex); - return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, ex.getMessage(), request); - } - private boolean isNotAdmin(final Client client) { return !client.getClientId().equals(securitySettings.getAdminClientId()); } diff --git a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java index 784b037694..ec50774f87 100644 --- a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java @@ -4,7 +4,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -13,34 +12,25 @@ import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.domain.ItemsWrapper; import org.zalando.nakadi.domain.SubscriptionEventTypeStats; -import org.zalando.nakadi.exceptions.runtime.ErrorGettingCursorTimeLagException; -import org.zalando.nakadi.exceptions.runtime.FeatureNotAvailableException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; -import org.zalando.nakadi.exceptions.runtime.TimeLagStatsTimeoutException; import org.zalando.nakadi.service.FeatureToggleService; import org.zalando.nakadi.service.subscription.SubscriptionService; import org.zalando.nakadi.service.subscription.SubscriptionService.StatsMode; -import org.zalando.problem.Problem; -import org.zalando.problem.spring.web.advice.Responses; import javax.annotation.Nullable; -import javax.ws.rs.core.Response; import java.util.Set; -import static javax.ws.rs.core.Response.Status.NOT_IMPLEMENTED; -import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.springframework.http.HttpStatus.NO_CONTENT; import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.ResponseEntity.status; -import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; @RestController @RequestMapping(value = "/subscriptions") -public class SubscriptionController { +public class SubscriptionController extends NakadiProblemControllerAdvice { private static final Logger LOG = LoggerFactory.getLogger(SubscriptionController.class); @@ -90,48 +80,4 @@ public ItemsWrapper getSubscriptionStats( final StatsMode statsMode = showTimeLag ? StatsMode.TIMELAG : StatsMode.NORMAL; return subscriptionService.getSubscriptionStat(subscriptionId, statsMode); } - - @ExceptionHandler(FeatureNotAvailableException.class) - public ResponseEntity handleFeatureTurnedOff(final FeatureNotAvailableException ex, - final NativeWebRequest request) { - LOG.debug(ex.getMessage(), ex); - return Responses.create(Problem.valueOf(NOT_IMPLEMENTED, ex.getMessage()), request); - } - - @ExceptionHandler(ErrorGettingCursorTimeLagException.class) - public ResponseEntity handleTimeLagException(final ErrorGettingCursorTimeLagException ex, - final NativeWebRequest request) { - LOG.debug(ex.getMessage(), ex); - return Responses.create(Problem.valueOf(UNPROCESSABLE_ENTITY, ex.getMessage()), request); - } - - @ExceptionHandler(InconsistentStateException.class) - public ResponseEntity handleInconsistentState(final InconsistentStateException ex, - final NativeWebRequest request) { - LOG.debug(ex.getMessage(), ex); - return Responses.create( - Problem.valueOf( - SERVICE_UNAVAILABLE, - ex.getMessage()), - request); - } - - @ExceptionHandler(ServiceTemporarilyUnavailableException.class) - public ResponseEntity handleServiceTemporarilyUnavailable(final ServiceTemporarilyUnavailableException ex, - final NativeWebRequest request) { - LOG.debug(ex.getMessage(), ex); - return Responses.create( - Problem.valueOf( - SERVICE_UNAVAILABLE, - ex.getMessage()), - request); - } - - @ExceptionHandler(TimeLagStatsTimeoutException.class) - public ResponseEntity handleTimeLagStatsTimeoutException(final TimeLagStatsTimeoutException e, - final NativeWebRequest request) { - LOG.warn(e.getMessage()); - return Responses.create(Response.Status.REQUEST_TIMEOUT, e.getMessage(), request); - } - } diff --git a/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java b/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java index 5d9b261677..20969a7940 100644 --- a/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java @@ -9,15 +9,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import org.zalando.nakadi.config.NakadiSettings; import org.zalando.nakadi.domain.Subscription; @@ -40,7 +37,6 @@ import org.zalando.nakadi.util.FlowIdUtils; import org.zalando.nakadi.view.UserStreamParameters; import org.zalando.problem.Problem; -import org.zalando.problem.spring.web.advice.Responses; import javax.annotation.Nullable; import javax.servlet.http.HttpServletRequest; @@ -50,16 +46,16 @@ import java.io.OutputStream; import java.util.concurrent.atomic.AtomicBoolean; -import static javax.ws.rs.core.Response.Status.CONFLICT; -import static javax.ws.rs.core.Response.Status.FORBIDDEN; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.zalando.nakadi.metrics.MetricUtils.metricNameForSubscription; -import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; +import static org.zalando.problem.Status.CONFLICT; +import static org.zalando.problem.Status.FORBIDDEN; +import static org.zalando.problem.Status.INTERNAL_SERVER_ERROR; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; @RestController -public class SubscriptionStreamController { +public class SubscriptionStreamController extends NakadiProblemControllerAdvice { public static final String CONSUMERS_COUNT_METRIC_NAME = "consumers"; private static final Logger LOG = LoggerFactory.getLogger(SubscriptionStreamController.class); @@ -245,12 +241,4 @@ private void writeProblemResponse(final HttpServletResponse response, response.setContentType("application/problem+json"); jsonMapper.writer().writeValue(outputStream, problem); } - - @ExceptionHandler(WrongStreamParametersException.class) - public ResponseEntity invalidEventTypeException(final WrongStreamParametersException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage(), exception); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } - } diff --git a/src/main/java/org/zalando/nakadi/controller/TimelinesController.java b/src/main/java/org/zalando/nakadi/controller/TimelinesController.java index c58c3d329f..28a62e3af9 100644 --- a/src/main/java/org/zalando/nakadi/controller/TimelinesController.java +++ b/src/main/java/org/zalando/nakadi/controller/TimelinesController.java @@ -5,36 +5,27 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.exceptions.runtime.AccessDeniedException; -import org.zalando.nakadi.exceptions.runtime.ConflictException; import org.zalando.nakadi.exceptions.runtime.InconsistentStateException; -import org.zalando.nakadi.exceptions.runtime.NotFoundException; import org.zalando.nakadi.exceptions.runtime.RepositoryProblemException; import org.zalando.nakadi.exceptions.runtime.TimelineException; -import org.zalando.nakadi.exceptions.runtime.TimelinesNotSupportedException; import org.zalando.nakadi.exceptions.runtime.TopicRepositoryException; -import org.zalando.nakadi.exceptions.runtime.UnableProcessException; import org.zalando.nakadi.service.timeline.TimelineService; import org.zalando.nakadi.view.TimelineRequest; import org.zalando.nakadi.view.TimelineView; -import org.zalando.problem.MoreStatus; -import org.zalando.problem.Problem; -import org.zalando.problem.spring.web.advice.Responses; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; import java.util.stream.Collectors; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + @RestController -@RequestMapping(value = "/event-types/{name}/timelines", produces = MediaType.APPLICATION_JSON) -public class TimelinesController { +@RequestMapping(value = "/event-types/{name}/timelines", produces = APPLICATION_JSON_VALUE) +public class TimelinesController extends NakadiProblemControllerAdvice { private static final Logger LOG = LoggerFactory.getLogger(TimelinesController.class); @@ -60,25 +51,4 @@ public ResponseEntity getTimelines(@PathVariable("name") final String eventTy .map(TimelineView::new) .collect(Collectors.toList())); } - - @ExceptionHandler({ - UnableProcessException.class, - TimelinesNotSupportedException.class}) - public ResponseEntity unprocessable(final UnableProcessException ex, final NativeWebRequest request) { - LOG.error(ex.getMessage(), ex); - return Responses.create(MoreStatus.UNPROCESSABLE_ENTITY, ex.getMessage(), request); - } - - @ExceptionHandler(NotFoundException.class) - public ResponseEntity notFound(final NotFoundException ex, final NativeWebRequest request) { - LOG.error(ex.getMessage(), ex); - return Responses.create(Response.Status.NOT_FOUND, ex.getMessage(), request); - } - - @ExceptionHandler(ConflictException.class) - public ResponseEntity conflict(final ConflictException ex, final NativeWebRequest request) { - LOG.debug(ex.getMessage(), ex); - return Responses.create(Response.Status.CONFLICT, ex.getMessage(), request); - } - } diff --git a/src/main/java/org/zalando/nakadi/controller/VersionController.java b/src/main/java/org/zalando/nakadi/controller/VersionController.java index 6a6417fcd0..8c7473cb1a 100644 --- a/src/main/java/org/zalando/nakadi/controller/VersionController.java +++ b/src/main/java/org/zalando/nakadi/controller/VersionController.java @@ -8,15 +8,15 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import javax.ws.rs.core.MediaType; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; import static org.springframework.web.bind.annotation.RequestMethod.GET; @RestController -@RequestMapping(value = "/version", produces = MediaType.APPLICATION_JSON) +@RequestMapping(value = "/version", produces = APPLICATION_JSON_VALUE) @Profile("!test") public class VersionController { diff --git a/src/main/java/org/zalando/nakadi/problem/ValidationProblem.java b/src/main/java/org/zalando/nakadi/problem/ValidationProblem.java index b504e9e9e0..803c5f136f 100644 --- a/src/main/java/org/zalando/nakadi/problem/ValidationProblem.java +++ b/src/main/java/org/zalando/nakadi/problem/ValidationProblem.java @@ -4,14 +4,14 @@ import org.springframework.validation.Errors; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; -import org.zalando.problem.MoreStatus; -import org.zalando.problem.Problem; +import org.zalando.problem.StatusType; +import org.zalando.problem.ThrowableProblem; -import javax.ws.rs.core.Response; import java.net.URI; -import java.util.Optional; -public class ValidationProblem implements Problem { +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; + +public class ValidationProblem extends ThrowableProblem { private final Errors errors; private static final String TYPE_VALUE = "http://httpstatus.es/422"; @@ -33,13 +33,13 @@ public String getTitle() { } @Override - public Response.StatusType getStatus() { - return MoreStatus.UNPROCESSABLE_ENTITY; + public StatusType getStatus() { + return UNPROCESSABLE_ENTITY; } @Override - public Optional getDetail() { - return Optional.of(buildErrorMessage()); + public String getDetail() { + return buildErrorMessage(); } private String buildErrorMessage() { diff --git a/src/main/java/org/zalando/nakadi/util/GzipBodyRequestFilter.java b/src/main/java/org/zalando/nakadi/util/GzipBodyRequestFilter.java index 769d6d44cc..28b83a8783 100644 --- a/src/main/java/org/zalando/nakadi/util/GzipBodyRequestFilter.java +++ b/src/main/java/org/zalando/nakadi/util/GzipBodyRequestFilter.java @@ -24,9 +24,9 @@ import java.util.Optional; import java.util.zip.GZIPInputStream; -import static javax.ws.rs.HttpMethod.POST; -import static javax.ws.rs.core.HttpHeaders.CONTENT_ENCODING; -import static javax.ws.rs.core.Response.Status.NOT_ACCEPTABLE; +import static org.springframework.http.HttpHeaders.CONTENT_ENCODING; +import static org.springframework.http.HttpMethod.POST; +import static org.zalando.problem.Status.NOT_ACCEPTABLE; public class GzipBodyRequestFilter implements Filter { diff --git a/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java b/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java index 810f287dd3..6db7fc6a2d 100644 --- a/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java @@ -33,8 +33,6 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doReturn; @@ -49,7 +47,9 @@ import static org.zalando.nakadi.utils.TestUtils.buildDefaultEventType; import static org.zalando.nakadi.utils.TestUtils.buildTimelineWithTopic; import static org.zalando.nakadi.utils.TestUtils.invalidProblem; -import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; public class CursorsControllerTest { diff --git a/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java index 7166c4f9ef..cae5f57815 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventStreamControllerTest.java @@ -63,12 +63,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; -import static javax.ws.rs.core.Response.Status.BAD_REQUEST; -import static javax.ws.rs.core.Response.Status.FORBIDDEN; -import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.PRECONDITION_FAILED; -import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThanOrEqualTo; @@ -87,7 +81,13 @@ import static org.zalando.nakadi.metrics.MetricUtils.metricNameFor; import static org.zalando.nakadi.utils.TestUtils.buildTimelineWithTopic; import static org.zalando.nakadi.utils.TestUtils.mockAccessDeniedException; -import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; +import static org.zalando.problem.Status.BAD_REQUEST; +import static org.zalando.problem.Status.FORBIDDEN; +import static org.zalando.problem.Status.INTERNAL_SERVER_ERROR; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.PRECONDITION_FAILED; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; public class EventStreamControllerTest { diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeAuthorizationTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeAuthorizationTest.java index 00a10cec0b..60f932e2ea 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeAuthorizationTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeAuthorizationTest.java @@ -8,10 +8,8 @@ import org.zalando.nakadi.plugin.api.authz.AuthorizationService; import org.zalando.nakadi.plugin.api.authz.Resource; import org.zalando.nakadi.utils.EventTypeTestBuilder; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; -import javax.ws.rs.core.Response; import java.io.IOException; import java.util.Optional; @@ -21,6 +19,8 @@ import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.zalando.problem.Status.FORBIDDEN; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; public class EventTypeAuthorizationTest extends EventTypeControllerTestCase { @@ -48,7 +48,7 @@ public void whenPUTNotAuthorizedThen403() throws Exception { putEventType(eventType, eventType.getName()) .andExpect(status().isForbidden()) - .andExpect(content().string(matchesProblem(Problem.valueOf(Response.Status.FORBIDDEN, + .andExpect(content().string(matchesProblem(Problem.valueOf(FORBIDDEN, "Access on ADMIN event-type:" + eventType.getName() + " denied")))); } @@ -76,7 +76,7 @@ public void whenPUTUnlimitedRetentionTimeByUserThen422() throws Exception { putEventType(eventType, eventType.getName()) .andExpect(status().isUnprocessableEntity()) - .andExpect(content().string(matchesProblem(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, + .andExpect(content().string(matchesProblem(Problem.valueOf(UNPROCESSABLE_ENTITY, "Field \"options.retention_time\" can not be more than 345600000")))); } @@ -90,7 +90,7 @@ public void whenPUTNullAuthorizationForExistingAuthorization() throws Exception putEventType(newEventType, newEventType.getName()) .andExpect(status().isUnprocessableEntity()) - .andExpect(content().string(matchesProblem(Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, + .andExpect(content().string(matchesProblem(Problem.valueOf(UNPROCESSABLE_ENTITY, "Changing authorization object to `null` is not possible due to existing one")))); } @@ -105,7 +105,7 @@ public void whenDELETENotAuthorized200() throws Exception { deleteEventType(eventType.getName()) .andExpect(status().isForbidden()) - .andExpect(content().string(matchesProblem(Problem.valueOf(Response.Status.FORBIDDEN, + .andExpect(content().string(matchesProblem(Problem.valueOf(FORBIDDEN, "Access on ADMIN event-type:" + eventType.getName() + " denied")))); } diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java index 8b669eb103..56c10cb678 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTest.java @@ -25,10 +25,10 @@ import org.zalando.nakadi.domain.ResourceAuthorizationAttribute; import org.zalando.nakadi.domain.Subscription; import org.zalando.nakadi.domain.Timeline; -import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; -import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.DuplicatedEventTypeNameException; +import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.exceptions.runtime.InvalidEventTypeException; +import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.TopicConfigException; import org.zalando.nakadi.exceptions.runtime.TopicCreationException; import org.zalando.nakadi.exceptions.runtime.UnableProcessException; @@ -36,11 +36,9 @@ import org.zalando.nakadi.repository.TopicRepository; import org.zalando.nakadi.utils.EventTypeTestBuilder; import org.zalando.nakadi.utils.TestUtils; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; import org.zalando.problem.ThrowableProblem; -import javax.ws.rs.core.Response; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -49,8 +47,6 @@ import java.util.Optional; import java.util.concurrent.TimeoutException; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.hamcrest.Matchers.containsString; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; @@ -76,6 +72,11 @@ import static org.zalando.nakadi.utils.TestUtils.createInvalidEventTypeExceptionProblem; import static org.zalando.nakadi.utils.TestUtils.invalidProblem; import static org.zalando.nakadi.utils.TestUtils.randomValidEventTypeName; +import static org.zalando.problem.Status.CONFLICT; +import static org.zalando.problem.Status.INTERNAL_SERVER_ERROR; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; public class EventTypeControllerTest extends EventTypeControllerTestCase { @@ -424,7 +425,7 @@ public void whenPostAndAuthorizationInvalidThen422() throws Exception { doThrow(new UnableProcessException("dummy")).when(authorizationValidator).validateAuthorization(any()); - postETAndExpect422WithProblem(eventType, Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, "dummy")); + postETAndExpect422WithProblem(eventType, Problem.valueOf(UNPROCESSABLE_ENTITY, "dummy")); } @Test @@ -499,7 +500,7 @@ public void whenPOSTInvalidSchemaThen422() throws Exception { @Test public void whenPostDuplicatedEventTypeReturn409() throws Exception { - final Problem expectedProblem = Problem.valueOf(Response.Status.CONFLICT, "some-name"); + final Problem expectedProblem = Problem.valueOf(CONFLICT, "some-name"); doThrow(new DuplicatedEventTypeNameException("some-name")).when(eventTypeRepository).saveEventType(any( EventTypeBase.class)); @@ -569,7 +570,7 @@ public void whenDeleteEventTypeThatHasSubscriptionsThenConflict() throws Excepti .listSubscriptions(eq(ImmutableSet.of(eventType.getName())), eq(Optional.empty()), anyInt(), anyInt())) .thenReturn(ImmutableList.of(mock(Subscription.class))); - final Problem expectedProblem = Problem.valueOf(Response.Status.CONFLICT, + final Problem expectedProblem = Problem.valueOf(CONFLICT, "Can't remove event type " + eventType.getName() + ", as it has subscriptions"); deleteEventType(eventType.getName()) @@ -582,7 +583,7 @@ public void whenDeleteEventTypeThatHasSubscriptionsThenConflict() throws Excepti public void whenDeleteEventTypeAndNakadiExceptionThen500() throws Exception { final String eventTypeName = randomValidEventTypeName(); - final Problem expectedProblem = Problem.valueOf(Response.Status.INTERNAL_SERVER_ERROR, + final Problem expectedProblem = Problem.valueOf(INTERNAL_SERVER_ERROR, "Failed to delete event type " + eventTypeName); doThrow(new InternalNakadiException("dummy message")) @@ -597,7 +598,7 @@ public void whenDeleteEventTypeAndNakadiExceptionThen500() throws Exception { @Test public void whenPersistencyErrorThen500() throws Exception { - final Problem expectedProblem = Problem.valueOf(Response.Status.INTERNAL_SERVER_ERROR); + final Problem expectedProblem = Problem.valueOf(INTERNAL_SERVER_ERROR); doThrow(InternalNakadiException.class).when(eventTypeRepository).saveEventType(any(EventType.class)); diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java index 11b80985ba..8187ee959d 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java @@ -118,7 +118,7 @@ public void init() throws Exception { mockMvc = standaloneSetup(controller) .setMessageConverters(new StringHttpMessageConverter(), TestUtils.JACKSON_2_HTTP_MESSAGE_CONVERTER) .setCustomArgumentResolvers(new ClientResolver(settings, featureToggleService)) - .setControllerAdvice(new ExceptionHandling()) + .setControllerAdvice(new NakadiProblemControllerAdvice()) .build(); } diff --git a/src/test/java/org/zalando/nakadi/controller/ExceptionHandlingTest.java b/src/test/java/org/zalando/nakadi/controller/NakadiProblemHandlingTest.java similarity index 79% rename from src/test/java/org/zalando/nakadi/controller/ExceptionHandlingTest.java rename to src/test/java/org/zalando/nakadi/controller/NakadiProblemHandlingTest.java index bcc9c9169f..acb108364a 100644 --- a/src/test/java/org/zalando/nakadi/controller/ExceptionHandlingTest.java +++ b/src/test/java/org/zalando/nakadi/controller/NakadiProblemHandlingTest.java @@ -10,21 +10,21 @@ import org.zalando.nakadi.exceptions.runtime.IllegalClientIdException; import org.zalando.problem.Problem; -public class ExceptionHandlingTest { +public class NakadiProblemHandlingTest { private static final String OAUTH2_SCOPE_WRITE = "oauth2.scope.write"; @Test public void testIllegalClientIdException() { - final ExceptionHandling exceptionHandling = new ExceptionHandling(); + final NakadiProblemHandling nakadiProblemHandling = new NakadiProblemControllerAdvice(); final NativeWebRequest mockedRequest = Mockito.mock(NativeWebRequest.class); Mockito.when(mockedRequest.getHeader(Matchers.any())).thenReturn(""); - final ResponseEntity problemResponseEntity = exceptionHandling.handleIllegalClientIdException( + final ResponseEntity problemResponseEntity = nakadiProblemHandling.handleIllegalClientIdException( new IllegalClientIdException("You don't have access to this event type"), mockedRequest); Assert.assertEquals(problemResponseEntity.getStatusCode(), HttpStatus.FORBIDDEN); - Assert.assertEquals(problemResponseEntity.getBody().getDetail().get(), + Assert.assertEquals(problemResponseEntity.getBody().getDetail(), "You don't have access to this event type"); } } \ No newline at end of file diff --git a/src/test/java/org/zalando/nakadi/controller/PartitionsControllerTest.java b/src/test/java/org/zalando/nakadi/controller/PartitionsControllerTest.java index f7edc3ca70..08e39befde 100644 --- a/src/test/java/org/zalando/nakadi/controller/PartitionsControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/PartitionsControllerTest.java @@ -38,8 +38,6 @@ import java.util.List; import java.util.Optional; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.doNothing; @@ -51,6 +49,8 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; import static org.zalando.nakadi.utils.TestUtils.buildTimeline; import static org.zalando.nakadi.utils.TestUtils.mockAccessDeniedException; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; public class PartitionsControllerTest { @@ -111,7 +111,7 @@ public void before() throws InternalNakadiException, NoSuchEventTypeException { mockMvc = standaloneSetup(controller) .setMessageConverters(new StringHttpMessageConverter(), TestUtils.JACKSON_2_HTTP_MESSAGE_CONVERTER) .setCustomArgumentResolvers(new ClientResolver(settings, featureToggleService)) - .setControllerAdvice(new ExceptionHandling()) + .setControllerAdvice(new NakadiProblemControllerAdvice()) .build(); } @@ -144,7 +144,7 @@ public void whenListPartitionsAndNakadiExceptionThenServiceUnavaiable() throws E when(timelineService.getActiveTimelinesOrdered(eq(TEST_EVENT_TYPE))) .thenThrow(ServiceTemporarilyUnavailableException.class); - final ThrowableProblem expectedProblem = Problem.valueOf(SERVICE_UNAVAILABLE, null); + final ThrowableProblem expectedProblem = Problem.valueOf(SERVICE_UNAVAILABLE, ""); mockMvc.perform( get(String.format("/event-types/%s/partitions", TEST_EVENT_TYPE))) .andExpect(status().isServiceUnavailable()) @@ -262,7 +262,7 @@ public void whenGetPartitionAndNakadiExceptionThenServiceUnavaiable() throws Exc when(timelineService.getActiveTimelinesOrdered(eq(TEST_EVENT_TYPE))) .thenThrow(ServiceTemporarilyUnavailableException.class); - final ThrowableProblem expectedProblem = Problem.valueOf(SERVICE_UNAVAILABLE, null); + final ThrowableProblem expectedProblem = Problem.valueOf(SERVICE_UNAVAILABLE, ""); mockMvc.perform( get(String.format("/event-types/%s/partitions/%s", TEST_EVENT_TYPE, TEST_PARTITION))) .andExpect(status().isServiceUnavailable()) diff --git a/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java b/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java index 2e94ce20f5..b315432b94 100644 --- a/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java @@ -38,7 +38,7 @@ import static org.zalando.nakadi.service.FeatureToggleService.Feature.DISABLE_SUBSCRIPTION_CREATION; import static org.zalando.nakadi.utils.RandomSubscriptionBuilder.builder; import static org.zalando.nakadi.utils.TestUtils.invalidProblem; -import static org.zalando.problem.MoreStatus.UNPROCESSABLE_ENTITY; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; public class PostSubscriptionControllerTest { @@ -67,7 +67,7 @@ public PostSubscriptionControllerTest() throws Exception { mockMvcBuilder = standaloneSetup(controller) .setMessageConverters(new StringHttpMessageConverter(), TestUtils.JACKSON_2_HTTP_MESSAGE_CONVERTER) - .setControllerAdvice(new ExceptionHandling()) + .setControllerAdvice(new NakadiProblemControllerAdvice()) .setCustomArgumentResolvers(new TestHandlerMethodArgumentResolver()); } diff --git a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java index d31eefb27d..ac06ae8544 100644 --- a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java @@ -50,7 +50,6 @@ import org.zalando.problem.Problem; import org.zalando.problem.ThrowableProblem; -import javax.ws.rs.core.Response; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -61,9 +60,6 @@ import java.util.Set; import static java.text.MessageFormat.format; -import static javax.ws.rs.core.Response.Status.BAD_REQUEST; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; -import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; @@ -83,6 +79,9 @@ import static org.zalando.nakadi.utils.RandomSubscriptionBuilder.builder; import static org.zalando.nakadi.utils.TestUtils.buildTimelineWithTopic; import static org.zalando.nakadi.utils.TestUtils.createRandomSubscriptions; +import static org.zalando.problem.Status.BAD_REQUEST; +import static org.zalando.problem.Status.NOT_FOUND; +import static org.zalando.problem.Status.SERVICE_UNAVAILABLE; import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; public class SubscriptionControllerTest { @@ -131,7 +130,7 @@ public SubscriptionControllerTest() throws Exception { mockMvcBuilder = standaloneSetup(controller) .setMessageConverters(new StringHttpMessageConverter(), TestUtils.JACKSON_2_HTTP_MESSAGE_CONVERTER) - .setControllerAdvice(new ExceptionHandling()) + .setControllerAdvice(new NakadiProblemControllerAdvice()) .setCustomArgumentResolvers(new TestHandlerMethodArgumentResolver()); } @@ -150,7 +149,7 @@ public void whenGetNoneExistingSubscriptionThenNotFound() throws Exception { final Subscription subscription = builder().build(); when(subscriptionRepository.getSubscription(subscription.getId())) .thenThrow(new NoSuchSubscriptionException("dummy-message")); - final ThrowableProblem expectedProblem = Problem.valueOf(Response.Status.NOT_FOUND, "dummy-message"); + final ThrowableProblem expectedProblem = Problem.valueOf(NOT_FOUND, "dummy-message"); getSubscription(subscription.getId()) .andExpect(status().isNotFound()) diff --git a/src/test/java/org/zalando/nakadi/controller/TimelinesControllerTest.java b/src/test/java/org/zalando/nakadi/controller/TimelinesControllerTest.java index 7c3f9e20cc..22ab92a9ed 100644 --- a/src/test/java/org/zalando/nakadi/controller/TimelinesControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/TimelinesControllerTest.java @@ -42,7 +42,7 @@ public TimelinesControllerTest() { mockMvc = MockMvcBuilders.standaloneSetup(controller) .setMessageConverters(new StringHttpMessageConverter(), TestUtils.JACKSON_2_HTTP_MESSAGE_CONVERTER) .setCustomArgumentResolvers(new ClientResolver(securitySettings, featureToggleService)) - .setControllerAdvice(new ExceptionHandling()) + .setControllerAdvice(new NakadiProblemControllerAdvice()) .build(); } diff --git a/src/test/java/org/zalando/nakadi/utils/TestUtils.java b/src/test/java/org/zalando/nakadi/utils/TestUtils.java index f4b7f2c32e..a72da43b16 100644 --- a/src/test/java/org/zalando/nakadi/utils/TestUtils.java +++ b/src/test/java/org/zalando/nakadi/utils/TestUtils.java @@ -27,7 +27,6 @@ import org.zalando.nakadi.plugin.api.authz.Resource; import org.zalando.nakadi.problem.ValidationProblem; import org.zalando.nakadi.service.NakadiKpiPublisher; -import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; import java.io.IOException; @@ -51,6 +50,7 @@ import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; import static org.zalando.nakadi.utils.RandomSubscriptionBuilder.builder; +import static org.zalando.problem.Status.UNPROCESSABLE_ENTITY; public class TestUtils { @@ -177,7 +177,7 @@ public static Problem invalidProblem(final String field, final String descriptio } public static Problem createInvalidEventTypeExceptionProblem(final String message) { - return Problem.valueOf(MoreStatus.UNPROCESSABLE_ENTITY, message); + return Problem.valueOf(UNPROCESSABLE_ENTITY, message); } public static void waitFor(final Runnable runnable) { From 6a76edaabbf7fb9e1127588d564fa81f8e5c7fa0 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Thu, 30 Aug 2018 16:28:48 +0200 Subject: [PATCH 100/176] Clean up controllers --- .../zalando/nakadi/controller/CursorsController.java | 4 ---- .../zalando/nakadi/controller/EventTypeController.java | 8 -------- .../nakadi/controller/PostSubscriptionController.java | 8 -------- .../zalando/nakadi/controller/SettingsController.java | 3 --- .../zalando/nakadi/controller/StoragesController.java | 6 +----- .../nakadi/controller/SubscriptionController.java | 10 +--------- .../controller/SubscriptionStreamController.java | 4 ---- .../zalando/nakadi/controller/TimelinesController.java | 4 ---- .../nakadi/controller/CursorsControllerTest.java | 3 +-- .../nakadi/controller/EventTypeControllerTestCase.java | 2 +- .../controller/PostSubscriptionControllerTest.java | 2 +- .../nakadi/controller/StoragesControllerTest.java | 2 +- .../nakadi/controller/SubscriptionControllerTest.java | 2 +- 13 files changed, 7 insertions(+), 51 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/CursorsController.java b/src/main/java/org/zalando/nakadi/controller/CursorsController.java index b375482dd4..a40e61d796 100644 --- a/src/main/java/org/zalando/nakadi/controller/CursorsController.java +++ b/src/main/java/org/zalando/nakadi/controller/CursorsController.java @@ -27,7 +27,6 @@ import org.zalando.nakadi.service.CursorConverter; import org.zalando.nakadi.service.CursorTokenService; import org.zalando.nakadi.service.CursorsService; -import org.zalando.nakadi.service.FeatureToggleService; import org.zalando.nakadi.view.CursorCommitResult; import org.zalando.nakadi.view.SubscriptionCursor; import org.zalando.nakadi.view.SubscriptionCursorWithoutToken; @@ -53,17 +52,14 @@ public class CursorsController extends NakadiProblemControllerAdvice { private static final Logger LOG = LoggerFactory.getLogger(CursorsController.class); private final CursorsService cursorsService; - private final FeatureToggleService featureToggleService; private final CursorConverter cursorConverter; private final CursorTokenService cursorTokenService; @Autowired public CursorsController(final CursorsService cursorsService, - final FeatureToggleService featureToggleService, final CursorConverter cursorConverter, final CursorTokenService cursorTokenService) { this.cursorsService = cursorsService; - this.featureToggleService = featureToggleService; this.cursorConverter = cursorConverter; this.cursorTokenService = cursorTokenService; } diff --git a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java index 304541254c..bc1462a14e 100644 --- a/src/main/java/org/zalando/nakadi/controller/EventTypeController.java +++ b/src/main/java/org/zalando/nakadi/controller/EventTypeController.java @@ -1,8 +1,6 @@ package org.zalando.nakadi.controller; import com.google.common.collect.Lists; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -32,7 +30,6 @@ import org.zalando.nakadi.exceptions.runtime.TopicConfigException; import org.zalando.nakadi.exceptions.runtime.TopicCreationException; import org.zalando.nakadi.exceptions.runtime.UnableProcessException; -import org.zalando.nakadi.plugin.api.ApplicationService; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; import org.zalando.nakadi.problem.ValidationProblem; import org.zalando.nakadi.service.AdminService; @@ -51,23 +48,18 @@ @RequestMapping(value = "/event-types") public class EventTypeController extends NakadiProblemControllerAdvice { - private static final Logger LOG = LoggerFactory.getLogger(TimelinesController.class); - private final EventTypeService eventTypeService; private final FeatureToggleService featureToggleService; - private final ApplicationService applicationService; private final AdminService adminService; private final NakadiSettings nakadiSettings; @Autowired public EventTypeController(final EventTypeService eventTypeService, final FeatureToggleService featureToggleService, - final ApplicationService applicationService, final AdminService adminService, final NakadiSettings nakadiSettings) { this.eventTypeService = eventTypeService; this.featureToggleService = featureToggleService; - this.applicationService = applicationService; this.adminService = adminService; this.nakadiSettings = nakadiSettings; } diff --git a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java index e91e202fe6..51df4938ab 100644 --- a/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/PostSubscriptionController.java @@ -1,7 +1,5 @@ package org.zalando.nakadi.controller; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -21,7 +19,6 @@ import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.SubscriptionUpdateConflictException; import org.zalando.nakadi.exceptions.runtime.UnprocessableSubscriptionException; -import org.zalando.nakadi.plugin.api.ApplicationService; import org.zalando.nakadi.problem.ValidationProblem; import org.zalando.nakadi.service.FeatureToggleService; import org.zalando.nakadi.service.subscription.SubscriptionService; @@ -40,18 +37,13 @@ @RestController public class PostSubscriptionController extends NakadiProblemControllerAdvice { - private static final Logger LOG = LoggerFactory.getLogger(PostSubscriptionController.class); - private final FeatureToggleService featureToggleService; - private final ApplicationService applicationService; private final SubscriptionService subscriptionService; @Autowired public PostSubscriptionController(final FeatureToggleService featureToggleService, - final ApplicationService applicationService, final SubscriptionService subscriptionService) { this.featureToggleService = featureToggleService; - this.applicationService = applicationService; this.subscriptionService = subscriptionService; } diff --git a/src/main/java/org/zalando/nakadi/controller/SettingsController.java b/src/main/java/org/zalando/nakadi/controller/SettingsController.java index 2d4923005e..87e24cc265 100644 --- a/src/main/java/org/zalando/nakadi/controller/SettingsController.java +++ b/src/main/java/org/zalando/nakadi/controller/SettingsController.java @@ -1,7 +1,5 @@ package org.zalando.nakadi.controller; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -27,7 +25,6 @@ @RequestMapping(value = "/settings") public class SettingsController extends NakadiProblemControllerAdvice { - private static final Logger LOG = LoggerFactory.getLogger(SettingsController.class); private final BlacklistService blacklistService; private final FeatureToggleService featureToggleService; private final SecuritySettings securitySettings; diff --git a/src/main/java/org/zalando/nakadi/controller/StoragesController.java b/src/main/java/org/zalando/nakadi/controller/StoragesController.java index 08b7a39539..a90aadd39f 100644 --- a/src/main/java/org/zalando/nakadi/controller/StoragesController.java +++ b/src/main/java/org/zalando/nakadi/controller/StoragesController.java @@ -9,7 +9,6 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.NativeWebRequest; -import org.zalando.nakadi.config.SecuritySettings; import org.zalando.nakadi.domain.Storage; import org.zalando.nakadi.exceptions.runtime.InternalNakadiException; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; @@ -27,14 +26,11 @@ @RestController public class StoragesController { - private final SecuritySettings securitySettings; private final StorageService storageService; private final AdminService adminService; @Autowired - public StoragesController(final SecuritySettings securitySettings, final StorageService storageService, - final AdminService adminService) { - this.securitySettings = securitySettings; + public StoragesController(final StorageService storageService, final AdminService adminService) { this.storageService = storageService; this.adminService = adminService; } diff --git a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java index ec50774f87..23ea534681 100644 --- a/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java +++ b/src/main/java/org/zalando/nakadi/controller/SubscriptionController.java @@ -1,7 +1,5 @@ package org.zalando.nakadi.controller; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PathVariable; @@ -16,7 +14,6 @@ import org.zalando.nakadi.exceptions.runtime.NoSuchEventTypeException; import org.zalando.nakadi.exceptions.runtime.NoSuchSubscriptionException; import org.zalando.nakadi.exceptions.runtime.ServiceTemporarilyUnavailableException; -import org.zalando.nakadi.service.FeatureToggleService; import org.zalando.nakadi.service.subscription.SubscriptionService; import org.zalando.nakadi.service.subscription.SubscriptionService.StatsMode; @@ -32,15 +29,10 @@ @RequestMapping(value = "/subscriptions") public class SubscriptionController extends NakadiProblemControllerAdvice { - private static final Logger LOG = LoggerFactory.getLogger(SubscriptionController.class); - - private final FeatureToggleService featureToggleService; private final SubscriptionService subscriptionService; @Autowired - public SubscriptionController(final FeatureToggleService featureToggleService, - final SubscriptionService subscriptionService) { - this.featureToggleService = featureToggleService; + public SubscriptionController(final SubscriptionService subscriptionService) { this.subscriptionService = subscriptionService; } diff --git a/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java b/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java index 20969a7940..890ecc2887 100644 --- a/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java +++ b/src/main/java/org/zalando/nakadi/controller/SubscriptionStreamController.java @@ -28,7 +28,6 @@ import org.zalando.nakadi.security.Client; import org.zalando.nakadi.service.BlacklistService; import org.zalando.nakadi.service.ClosedConnectionsCrutch; -import org.zalando.nakadi.service.FeatureToggleService; import org.zalando.nakadi.service.subscription.StreamParameters; import org.zalando.nakadi.service.subscription.SubscriptionOutput; import org.zalando.nakadi.service.subscription.SubscriptionStreamer; @@ -60,7 +59,6 @@ public class SubscriptionStreamController extends NakadiProblemControllerAdvice private static final Logger LOG = LoggerFactory.getLogger(SubscriptionStreamController.class); private final SubscriptionStreamerFactory subscriptionStreamerFactory; - private final FeatureToggleService featureToggleService; private final ObjectMapper jsonMapper; private final ClosedConnectionsCrutch closedConnectionsCrutch; private final NakadiSettings nakadiSettings; @@ -71,7 +69,6 @@ public class SubscriptionStreamController extends NakadiProblemControllerAdvice @Autowired public SubscriptionStreamController(final SubscriptionStreamerFactory subscriptionStreamerFactory, - final FeatureToggleService featureToggleService, final ObjectMapper objectMapper, final ClosedConnectionsCrutch closedConnectionsCrutch, final NakadiSettings nakadiSettings, @@ -80,7 +77,6 @@ public SubscriptionStreamController(final SubscriptionStreamerFactory subscripti final SubscriptionDbRepository subscriptionDbRepository, final SubscriptionValidationService subscriptionValidationService) { this.subscriptionStreamerFactory = subscriptionStreamerFactory; - this.featureToggleService = featureToggleService; this.jsonMapper = objectMapper; this.closedConnectionsCrutch = closedConnectionsCrutch; this.nakadiSettings = nakadiSettings; diff --git a/src/main/java/org/zalando/nakadi/controller/TimelinesController.java b/src/main/java/org/zalando/nakadi/controller/TimelinesController.java index 28a62e3af9..546352a60d 100644 --- a/src/main/java/org/zalando/nakadi/controller/TimelinesController.java +++ b/src/main/java/org/zalando/nakadi/controller/TimelinesController.java @@ -1,7 +1,5 @@ package org.zalando.nakadi.controller; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -27,8 +25,6 @@ @RequestMapping(value = "/event-types/{name}/timelines", produces = APPLICATION_JSON_VALUE) public class TimelinesController extends NakadiProblemControllerAdvice { - private static final Logger LOG = LoggerFactory.getLogger(TimelinesController.class); - private final TimelineService timelineService; @Autowired diff --git a/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java b/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java index 6db7fc6a2d..520a8ec8b0 100644 --- a/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/CursorsControllerTest.java @@ -94,8 +94,7 @@ public CursorsControllerTest() throws Exception { final CursorTokenService tokenService = mock(CursorTokenService.class); when(tokenService.generateToken()).thenReturn(TOKEN); - final CursorsController controller = new CursorsController(cursorsService, featureToggleService, - cursorConverter, tokenService); + final CursorsController controller = new CursorsController(cursorsService, cursorConverter, tokenService); final SecuritySettings settings = mock(SecuritySettings.class); doReturn(SecuritySettings.AuthMode.OFF).when(settings).getAuthMode(); diff --git a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java index 8187ee959d..53b274184d 100644 --- a/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java +++ b/src/test/java/org/zalando/nakadi/controller/EventTypeControllerTestCase.java @@ -110,7 +110,7 @@ public void init() throws Exception { featureToggleService, authorizationValidator, timelineSync, transactionTemplate, nakadiSettings, nakadiKpiPublisher, "et-log-event-type", eventTypeOptionsValidator, adminService); final EventTypeController controller = new EventTypeController(eventTypeService,featureToggleService, - applicationService, adminService, nakadiSettings); + adminService, nakadiSettings); doReturn(randomUUID).when(uuid).randomUUID(); doReturn(true).when(applicationService).exists(any()); diff --git a/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java b/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java index b315432b94..9cbda1590b 100644 --- a/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/PostSubscriptionControllerTest.java @@ -63,7 +63,7 @@ public PostSubscriptionControllerTest() throws Exception { when(subscriptionService.getSubscriptionUri(any())).thenCallRealMethod(); final PostSubscriptionController controller = new PostSubscriptionController(featureToggleService, - applicationService, subscriptionService); + subscriptionService); mockMvcBuilder = standaloneSetup(controller) .setMessageConverters(new StringHttpMessageConverter(), TestUtils.JACKSON_2_HTTP_MESSAGE_CONVERTER) diff --git a/src/test/java/org/zalando/nakadi/controller/StoragesControllerTest.java b/src/test/java/org/zalando/nakadi/controller/StoragesControllerTest.java index 48cae8d611..2c6a1cfb40 100644 --- a/src/test/java/org/zalando/nakadi/controller/StoragesControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/StoragesControllerTest.java @@ -41,7 +41,7 @@ public class StoragesControllerTest { @Before public void before() { - final StoragesController controller = new StoragesController(securitySettings, storageService, adminService); + final StoragesController controller = new StoragesController(storageService, adminService); final FeatureToggleService featureToggleService = mock(FeatureToggleService.class); doReturn("nakadi").when(securitySettings).getAdminClientId(); diff --git a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java index ac06ae8544..2381b42983 100644 --- a/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java +++ b/src/test/java/org/zalando/nakadi/controller/SubscriptionControllerTest.java @@ -124,7 +124,7 @@ public SubscriptionControllerTest() throws Exception { zkSubscriptionClientFactory, timelineService, eventTypeRepository, null, cursorConverter, cursorOperationsService, nakadiKpiPublisher, featureToggleService, null, "subscription_log_et", mock(AuthorizationValidator.class)); - final SubscriptionController controller = new SubscriptionController(featureToggleService, subscriptionService); + final SubscriptionController controller = new SubscriptionController(subscriptionService); final ApplicationService applicationService = mock(ApplicationService.class); doReturn(true).when(applicationService).exists(any()); From e0991d08bc9582d7b31f1d2f0d1113c257e659cf Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Thu, 30 Aug 2018 16:38:29 +0200 Subject: [PATCH 101/176] gradle 4.10 --- gradle/wrapper/gradle-wrapper.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7dc503f149..786e104107 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Thu Aug 30 16:32:45 CEST 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip From 746642612308f619a1af672b19a61f2e28ca2b22 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Thu, 30 Aug 2018 16:47:59 +0200 Subject: [PATCH 102/176] Build file ready for Gradle 5.0 --- build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index 1ab1cf0632..a03ae8f200 100644 --- a/build.gradle +++ b/build.gradle @@ -188,8 +188,8 @@ dependencies { // end::dependencies[] // tag::wrapper[] -task wrapper(type: Wrapper) { - gradleVersion = '2.3' +wrapper { + gradleVersion = '4.10' } tasks.withType(FindBugs) { @@ -265,7 +265,7 @@ task fullAcceptanceTest(type: GradleBuild) { } task acceptanceTest(type: Test) { - testClassesDir = sourceSets.acceptanceTest.output.classesDir + testClassesDirs = sourceSets.acceptanceTest.output classpath = sourceSets.acceptanceTest.runtimeClasspath maxParallelForks = Runtime.runtime.availableProcessors() } From 48d3919827547fd517096300d8739520a60f901d Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Thu, 30 Aug 2018 17:36:06 +0200 Subject: [PATCH 103/176] Fix tests --- .../zalando/nakadi/controller/SettingsController.java | 10 +++++++++- .../org/zalando/nakadi/util/GzipBodyRequestFilter.java | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/controller/SettingsController.java b/src/main/java/org/zalando/nakadi/controller/SettingsController.java index 87e24cc265..860d87a371 100644 --- a/src/main/java/org/zalando/nakadi/controller/SettingsController.java +++ b/src/main/java/org/zalando/nakadi/controller/SettingsController.java @@ -3,15 +3,18 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.validation.Errors; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.NativeWebRequest; import org.zalando.nakadi.config.SecuritySettings; import org.zalando.nakadi.domain.ItemsWrapper; import org.zalando.nakadi.domain.ResourceAuthorization; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; +import org.zalando.nakadi.problem.ValidationProblem; import org.zalando.nakadi.security.Client; import org.zalando.nakadi.service.AdminService; import org.zalando.nakadi.service.BlacklistService; @@ -97,10 +100,15 @@ public ResponseEntity getAdmins() { } @RequestMapping(path = "/admins", method = RequestMethod.POST) - public ResponseEntity updateAdmins(@Valid @RequestBody final ResourceAuthorization authz) { + public ResponseEntity updateAdmins(@Valid @RequestBody final ResourceAuthorization authz, + final Errors errors, + final NativeWebRequest request) { if (!adminService.isAdmin(AuthorizationService.Operation.ADMIN)) { return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); } + if (errors.hasErrors()) { + return create(new ValidationProblem(errors), request); + } adminService.updateAdmins(authz.toPermissionsList(ADMIN_RESOURCE)); return ResponseEntity.ok().build(); } diff --git a/src/main/java/org/zalando/nakadi/util/GzipBodyRequestFilter.java b/src/main/java/org/zalando/nakadi/util/GzipBodyRequestFilter.java index 28b83a8783..3bd26c5674 100644 --- a/src/main/java/org/zalando/nakadi/util/GzipBodyRequestFilter.java +++ b/src/main/java/org/zalando/nakadi/util/GzipBodyRequestFilter.java @@ -49,7 +49,7 @@ public final void doFilter(final ServletRequest servletRequest, final ServletRes .map(encoding -> encoding.contains("gzip")) .orElse(false); - if (isGzipped && !POST.equals(request.getMethod())) { + if (isGzipped && !POST.matches(request.getMethod())) { reportNotAcceptableError((HttpServletResponse) servletResponse, request); return; } From 3cac09405536917d92422b2ee3f8d0657c2983b3 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Tue, 4 Sep 2018 12:52:18 +0200 Subject: [PATCH 104/176] Make architecture document public --- .../data_integration_at_zalando.md | 53 +++++++++++++++++++ docs/_documentation/intro.md | 2 +- 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 docs/_documentation/data_integration_at_zalando.md diff --git a/docs/_documentation/data_integration_at_zalando.md b/docs/_documentation/data_integration_at_zalando.md new file mode 100644 index 0000000000..b949e5c6a6 --- /dev/null +++ b/docs/_documentation/data_integration_at_zalando.md @@ -0,0 +1,53 @@ +--- +title: Data Integration at Zalando +position: 200 +--- + +## Introduction + +Teams running platform microservices encapsulate their datastores and data models in accordance with our [API Guidelines](http://zalando.github.io/restful-api-guidelines). The result is business intelligence and analysis, which are also teams running their own services, don’t have direct access to raw data. This demands a different approach to data integration compared to traditional techniques such as extra transform load (ETL) from application databases. + +### Event Based Integration + +The way we support data integration is twofold. First, teams take responsibility for providing data if there is demand for it or a platform requirement to do so, by publishing _Events_, defined according to an _Event Type_. Second, at the technical level, data integration happens by microservices publishing streams of event data to an _Event Broker_, which acts as managed infrastructure for the platform. + +We can call this style _"Event Based Integration"_. It allows providing access to local microservice datastores as logical data synchronization events written into data lake and can be used to reconstruct state for BI and DS analysis and reporting purposes. + +### Event Based Interchange + +While we mostly focus on data _integation_ in this section, we should mention that the architectural style can also be used for _interchange_. This is where events are also used for business and other events used e.g. for asynchronous service to service communication or process monitoring purposes. These events also use event infrastructure and are also stored in data lake and provided for further analysis. + +## Architectural Elements + +In the platform architecture, there are two foundational services used for event based integration. First, an _Event Broker_, which a managed deployment of the [Nakadi](https://nakadi.io) project. Second, the _Data Lake_, which captures and stores events from the broker, and is used by the data warehouse and other downstream systems. + + +![Event Based Integration - Architecture](./img/event_based_data_integration.svg) + +### Data Model: Event Types and Events + +Producers and consumers of events coordinate asynchronously via an event definition, called an _Event Type_, and its corresponding stream of _Events_ that conform to the type. Both event types and events are handled by the event broker, which supports a HTTP API. + +Events types allow an _Event Producer_ to define a data contract based on a JSON-Schema and an _Event Category_. An event producer owns the definition of the events it publishes and is responsible for sending those events to the broker, registering the schema for the event type, and managing the versioning and evolution of the data. Events are part of the service's interface to the outside world. + +_Event Consumers_ can connect to an HTTP event stream to receive events. Consumers can also use a _Subscription_ to have the broker manage their offset positions in an event stream. One event type can have many subscribing consumers, allowing new services to receive events without the producer having to know or directly integrate with each consumer. + +### The Event Broker: Nakadi + +Nakadi allows services to register types of event and have them published and enriched. Services can subscribe to events by type and consume them as a stream. Nakadi's publish/subscribe model preserves ordering for each received event, and supports expiration based retention and replay of events for its consumers. + +Nakadi supports HTTP APIs for event publish-subscribe and schema management. This API constrains events on the platform to be one of three categories: + +- Data Change Event: An event that represents a change to a record or other entity. + +- Business Event: An event that is part of, or drives a business process. + +- Undefined Event: Suitable for other kinds of events where schema validation still provides value. + +Documentation on event types is available in the [Nakadi Developer Manual - Event Types](https://nakadi.io/manual.html#using_event-types). + +### The Data Lake + +A significant consumer of events is the *Data Lake*, which subscribes to multiple event types (specified by use case) sent to the broker. The data lake prepares and makes available platform data for use by the data warehouse and other analytical systems. + +The Data Lake is not only capturing data for storage in the data lake, it also enables functions such as business process monitoring. For example, all EventLog events sent to the platform are captured by the Data Lake. diff --git a/docs/_documentation/intro.md b/docs/_documentation/intro.md index 182468446a..5cb2b5209d 100644 --- a/docs/_documentation/intro.md +++ b/docs/_documentation/intro.md @@ -31,7 +31,7 @@ The goal of Nakadi (**ნაკადი** means "stream" in Georgian) is to pro ### Links Read more to understand *The big picture* -[Architecture for data integration](https://pages.github.bus.zalan.do/core-platform/docs/architecture/data_integration.html) +[Architecture for data integration](https://zalando.github.io/nakadi/manual.html#data_integration_at_zalando) Watch the talk [Data Integration in the World of Microservices](https://clusterhq.com/2016/05/20/microservices-zalando/) From 9464bbf04844884484426161340aceac5cfdda3c Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Tue, 4 Sep 2018 12:52:51 +0200 Subject: [PATCH 105/176] Image --- docs/img/event_based_data_integration.svg | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 docs/img/event_based_data_integration.svg diff --git a/docs/img/event_based_data_integration.svg b/docs/img/event_based_data_integration.svg new file mode 100644 index 0000000000..b6b545f8ff --- /dev/null +++ b/docs/img/event_based_data_integration.svg @@ -0,0 +1,4 @@ + + + + From dfc0836b0062d84a3c3fa559506ef8c8b3e72619 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Tue, 4 Sep 2018 13:53:01 +0200 Subject: [PATCH 106/176] Fix link to video --- docs/_documentation/intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_documentation/intro.md b/docs/_documentation/intro.md index 5cb2b5209d..8c299d4e35 100644 --- a/docs/_documentation/intro.md +++ b/docs/_documentation/intro.md @@ -33,7 +33,7 @@ The goal of Nakadi (**ნაკადი** means "stream" in Georgian) is to pro Read more to understand *The big picture* [Architecture for data integration](https://zalando.github.io/nakadi/manual.html#data_integration_at_zalando) -Watch the talk [Data Integration in the World of Microservices](https://clusterhq.com/2016/05/20/microservices-zalando/) +Watch the talk [Data Integration in the World of Microservices](https://www.youtube.com/watch?v=SbVQBHRAFXA) ### Development status From 7e93e914fffc1732d5c906ff058d04541f5f31f8 Mon Sep 17 00:00:00 2001 From: Lionel Montrieux Date: Tue, 4 Sep 2018 15:40:08 +0200 Subject: [PATCH 107/176] Post-merge fix --- .../nakadi/config/SecurityConfiguration.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java index 2270ca8ee4..e906f79c5f 100644 --- a/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java +++ b/src/main/java/org/zalando/nakadi/config/SecurityConfiguration.java @@ -19,16 +19,10 @@ import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler; import org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint; import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices; -import org.springframework.security.web.firewall.FirewalledRequest; -import org.springframework.security.web.firewall.HttpFirewall; -import org.springframework.security.web.firewall.RequestRejectedException; -import org.springframework.security.web.firewall.StrictHttpFirewall; import org.zalando.problem.Status; import org.zalando.problem.StatusType; import org.zalando.stups.oauth2.spring.security.expression.ExtendedOAuth2WebSecurityExpressionHandler; -import javax.servlet.http.HttpServletRequest; -import javax.ws.rs.core.Response; import java.io.IOException; import java.text.MessageFormat; import java.util.ArrayList; @@ -198,4 +192,13 @@ public String getDetail() { } } + private static Status fromStatusCode(final int code) { + for (final Status status: Status.values()) { + if (status.getStatusCode() == code) { + return status; + } + } + return null; + } + } From 4512594c916b2edb4a5be8ae26ccb8d74b6929cc Mon Sep 17 00:00:00 2001 From: Per Ploug Date: Thu, 6 Sep 2018 09:13:37 +0200 Subject: [PATCH 108/176] Updated intro and replaced presentation links ClusterHQ presentation 404s so replaced with fosdem and goto --- README.md | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c45eeb8098..0c8922c9c5 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,20 @@ +## [Nakadi Event Broker](https://zalando.github.io/nakadi/) + [![Build Status](https://travis-ci.org/zalando/nakadi.svg?branch=master)](https://travis-ci.org/zalando/nakadi) [![codecov.io](https://codecov.io/github/zalando/nakadi/coverage.svg?branch=master)](https://codecov.io/github/zalando/nakadi?branch=master) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/785ccd4ab5e34867b760a8b07c3b62f1)](https://www.codacy.com/app/aruha/nakadi?utm_source=www.github.com&utm_medium=referral&utm_content=zalando/nakadi&utm_campaign=Badge_Grade) -## [Nakadi Event Broker](https://zalando.github.io/nakadi/) +Nakadi is a distributed event bus broker that implements a RESTful API abstraction on top of Kafka-like queues, which can be used to send, receive, and analyze streaming data in real time, reliable and highly available manner. + +One of the most prominent use case of Nakadi is to enable decoupling of micro-services by building data streams between producers and consumers. -Nakadi is a distributed event bus broker that implements a RESTful API abstraction on top of Kafka-like queues. +Main users of nakadi are developers and analysts. Nakadi provides features like REST based integration, multi consumer, ordered delivery, interactive UI, fully managed, security, ensuring data quality, abstraction of big data technology, and push model based consumption. + +Nakadi is currently in production inside Zalando as the backbone of our microservices sending millions of events daily with a throughput of more than hundreds gigabytes per second. In one line Nakadi is a **high-scalability data-stream for enterprise engineering teams**. ![Nakadi Deployment Diagram](docs/img/NakadiDeploymentDiagram.png) + More detailed information can be found on our [website](http://zalando.github.io/nakadi/). ### Project goal @@ -33,17 +40,19 @@ The goal of Nakadi (**ნაკადი** means *stream* in Georgian) is to pro The consumer connection has keepalive controls and support for managing stream offsets using [subscriptions](https://zalando.github.io/nakadi/manual.html#using_consuming-events-hila). -### Links -Watch the talk [Data Integration in the World of Microservices](https://clusterhq.com/2016/05/20/microservices-zalando/) +### Presentations + +- [Watch the talk on Nakadi at Fosdem](https://archive.fosdem.org/2018/schedule/event/nakadi/) +- [Background on the Zalando Microservices platform](https://www.youtube.com/watch?v=gEeHZwjwehs) + ### Development status -Nakadi is high-load production ready. -Zalando uses Nakadi as its central Event Bus Service. -Nakadi reliably handles the traffic from thousands event types with -the throughput of more than hundreds gigabytes per second. -The project is in active development. See the [CHANGELOG.md](CHANGELOG.md) +- Nakadi is high-load production ready. +- Zalando uses Nakadi as its central Event Bus Service. +- Nakadi reliably handles the traffic from thousands event types with the throughput of more than hundreds gigabytes per second. +- The project is in active development. See the [CHANGELOG.md](CHANGELOG.md) #### Features From e6e38291e0f6a127b59b4bb4f2950102e69953df Mon Sep 17 00:00:00 2001 From: Per Ploug Date: Thu, 6 Sep 2018 09:23:49 +0200 Subject: [PATCH 109/176] Update README.md --- README.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0c8922c9c5..ae390ddaf1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ One of the most prominent use case of Nakadi is to enable decoupling of micro-se Main users of nakadi are developers and analysts. Nakadi provides features like REST based integration, multi consumer, ordered delivery, interactive UI, fully managed, security, ensuring data quality, abstraction of big data technology, and push model based consumption. -Nakadi is currently in production inside Zalando as the backbone of our microservices sending millions of events daily with a throughput of more than hundreds gigabytes per second. In one line Nakadi is a **high-scalability data-stream for enterprise engineering teams**. +Nakadi is in active developement and is currently in production inside Zalando as the backbone of our microservices sending millions of events daily with a throughput of more than hundreds gigabytes per second. In one line Nakadi is a **high-scalability data-stream for enterprise engineering teams**. ![Nakadi Deployment Diagram](docs/img/NakadiDeploymentDiagram.png) @@ -40,20 +40,18 @@ The goal of Nakadi (**ნაკადი** means *stream* in Georgian) is to pro The consumer connection has keepalive controls and support for managing stream offsets using [subscriptions](https://zalando.github.io/nakadi/manual.html#using_consuming-events-hila). +### Development status + +- Nakadi is high-load production ready. +- Zalando uses Nakadi as its central Event Bus Service. +- Nakadi reliably handles the traffic from thousands event types with the throughput of more than hundreds gigabytes per second. +- The project is in active development. See the [CHANGELOG.md](CHANGELOG.md) ### Presentations - [Watch the talk on Nakadi at Fosdem](https://archive.fosdem.org/2018/schedule/event/nakadi/) - [Background on the Zalando Microservices platform](https://www.youtube.com/watch?v=gEeHZwjwehs) - -### Development status - -- Nakadi is high-load production ready. -- Zalando uses Nakadi as its central Event Bus Service. -- Nakadi reliably handles the traffic from thousands event types with the throughput of more than hundreds gigabytes per second. -- The project is in active development. See the [CHANGELOG.md](CHANGELOG.md) - #### Features * Stream: From bf50e1f0c73786914e9ee49393e676d851aada9f Mon Sep 17 00:00:00 2001 From: Per Ploug Date: Thu, 6 Sep 2018 10:45:08 +0200 Subject: [PATCH 110/176] Update README.md --- README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ae390ddaf1..1dc222f341 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,6 @@ Nakadi is in active developement and is currently in production inside Zalando a ![Nakadi Deployment Diagram](docs/img/NakadiDeploymentDiagram.png) - More detailed information can be found on our [website](http://zalando.github.io/nakadi/). ### Project goal @@ -101,14 +100,16 @@ Read more about latest development in our [CHANGELOG.md](CHANGELOG.md) The [zalando-nakadi](https://github.com/zalando-nakadi/) organisation contains many useful related projects like -* Client libraries +* [Use Nakadi with a client in your language of choice](https://nakadi.io/manual.html#using_clients) * SDK -* GUI +* [GUI](https://github.com/zalando-incubator/nakadi-ui) * DevOps tools and more -## Quickstart -You can run the project locally using [Docker](https://www.docker.com/). + +## How to contribute to Nakadi + +Read our [contribution guidelines]() on how to submit issues and pull requests, then get Nakadi up and running locally using Docker: ### Dependencies @@ -166,13 +167,14 @@ This will build the project and run docker compose with 4 services: - Kafka (9092) - Zookeeper (2181) -To stop the running Nakadi: +To stop the running Nakadi server: ```sh ./gradlew stopNakadi ``` -## API Usage Quickstart + +## Using Nakadi and its API Please read the [manual](https://zalando.github.io/nakadi/manual.html) for the full API usage details. @@ -182,7 +184,6 @@ The Nakadi API allows the publishing and consuming of _events_ over HTTP. To do this the producer must register an _event type_ with the Nakadi schema registry. - This example shows minimal `undefined` category event type with a wilcard schema - ```sh From 1766178ee4fe5b70781727d0e164a3ced9ed766d Mon Sep 17 00:00:00 2001 From: Per Ploug Date: Thu, 6 Sep 2018 10:46:05 +0200 Subject: [PATCH 111/176] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1dc222f341..89eac416b8 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ like ## How to contribute to Nakadi -Read our [contribution guidelines]() on how to submit issues and pull requests, then get Nakadi up and running locally using Docker: +Read our [contribution guidelines](contribute.md) on how to submit issues and pull requests, then get Nakadi up and running locally using Docker: ### Dependencies From 86d717cb35d53651ca127bef6aa66ee05d5d25fd Mon Sep 17 00:00:00 2001 From: Per Ploug Date: Thu, 6 Sep 2018 10:47:05 +0200 Subject: [PATCH 112/176] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 89eac416b8..347bc24eac 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ like ## How to contribute to Nakadi -Read our [contribution guidelines](contribute.md) on how to submit issues and pull requests, then get Nakadi up and running locally using Docker: +Read our [contribution guidelines](CONTRIBUTING.md) on how to submit issues and pull requests, then get Nakadi up and running locally using Docker: ### Dependencies From 561d64f08d75c91ba95bb3d301bd92db41538a11 Mon Sep 17 00:00:00 2001 From: Ricardo de Cillo Date: Thu, 6 Sep 2018 16:28:35 +0200 Subject: [PATCH 113/176] Refine definition of span_ctx Using additionalProperties string makes sure that only flat maps of strings are accepted in the span_ctx. This is considered a decent level of guarantees in terms of schema, keeping it flexible but also relatively well behaved. --- docs/_data/nakadi-event-bus-api.yaml | 2 ++ .../org/zalando/nakadi/validation/JsonSchemaEnrichment.java | 4 ++-- .../zalando/nakadi/validation/JSONSchemaValidationTest.java | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/_data/nakadi-event-bus-api.yaml b/docs/_data/nakadi-event-bus-api.yaml index fd8f312825..8d863b1524 100644 --- a/docs/_data/nakadi-event-bus-api.yaml +++ b/docs/_data/nakadi-event-bus-api.yaml @@ -2062,6 +2062,8 @@ definitions: to inspect or effectively use the payload, apart from the tracer implementation, can lead to vendor lock-in which should be avoided. type: object + additionalProperties: + type: string required: - eid - occurred_at diff --git a/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java b/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java index f1f89c6c75..7d9e123942 100644 --- a/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java +++ b/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java @@ -162,7 +162,7 @@ private static JSONObject addMetadata(final JSONObject schema, final EventType e .put("type", "string") .put("enum", Arrays.asList(new String[]{eventType.getName()})); final JSONObject string = new JSONObject().put("type", "string"); - final JSONObject object = new JSONObject().put("type", "object"); + final JSONObject stringMap = new JSONObject().put("type", "object").put("additionalProperties", string); final JSONObject dateTime = new JSONObject() .put("type", "string"); @@ -172,7 +172,7 @@ private static JSONObject addMetadata(final JSONObject schema, final EventType e metadataProperties.put("parent_eids", arrayOfUUIDs); metadataProperties.put("flow_id", string); metadataProperties.put("partition", string); - metadataProperties.put("span_ctx", object); + metadataProperties.put("span_ctx", stringMap); final ArrayList requiredFields = newArrayList("eid", "occurred_at"); if (eventType.getCleanupPolicy() == CleanupPolicy.COMPACT) { diff --git a/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java b/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java index c655e8be6d..fb4a784b72 100644 --- a/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java +++ b/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java @@ -2,6 +2,7 @@ import org.json.JSONObject; import org.junit.Test; +import org.zalando.nakadi.domain.CompatibilityMode; import org.zalando.nakadi.domain.EventCategory; import org.zalando.nakadi.domain.EventType; import org.zalando.nakadi.utils.EventTypeTestBuilder; @@ -40,7 +41,7 @@ public void validationOfBusinessEventShouldRequiredMetadata() { @Test public void validationOfBusinessEventShouldAllowSpanCtxtInMetadata() { final EventType et = EventTypeTestBuilder.builder().name("some-event-type") - .schema(basicSchema()).build(); + .schema(basicSchema()).compatibilityMode(CompatibilityMode.COMPATIBLE).build(); et.setCategory(EventCategory.BUSINESS); final JSONObject event = new JSONObject("{\"metadata\":{" + From 8488b557dac4bf9a6c903b511d63d3f6bd5848e2 Mon Sep 17 00:00:00 2001 From: Ricardo de Cillo Date: Thu, 6 Sep 2018 16:51:01 +0200 Subject: [PATCH 114/176] Add test to check error path --- .../validation/JSONSchemaValidationTest.java | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java b/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java index fb4a784b72..b6795a5fbf 100644 --- a/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java +++ b/src/test/java/org/zalando/nakadi/validation/JSONSchemaValidationTest.java @@ -44,7 +44,7 @@ public void validationOfBusinessEventShouldAllowSpanCtxtInMetadata() { .schema(basicSchema()).compatibilityMode(CompatibilityMode.COMPATIBLE).build(); et.setCategory(EventCategory.BUSINESS); - final JSONObject event = new JSONObject("{\"metadata\":{" + + final JSONObject validEvent = new JSONObject("{\"metadata\":{" + "\"occurred_at\":\"1992-08-03T10:00:00Z\"," + "\"eid\":\"329ed3d2-8366-11e8-adc0-fa7ae01bbebc\"," + "\"span_ctx\": {" + @@ -54,9 +54,24 @@ public void validationOfBusinessEventShouldAllowSpanCtxtInMetadata() { "}}," + "\"foo\": \"bar\"}"); - final Optional error = EventValidation.forType(et).validate(event); + final Optional noError = EventValidation.forType(et).validate(validEvent); - assertThat(error, isAbsent()); + assertThat(noError, isAbsent()); + + final JSONObject invalidEvent = new JSONObject("{\"metadata\":{" + + "\"occurred_at\":\"1992-08-03T10:00:00Z\"," + + "\"eid\":\"329ed3d2-8366-11e8-adc0-fa7ae01bbebc\"," + + "\"span_ctx\": {" + + " \"ot-tracer-spanid\": 42," + + " \"ot-tracer-traceid\": \"e9435c17dabe8238\"," + + " \"ot-baggage-foo\": \"bar\"" + + "}}," + + "\"foo\": \"bar\"}"); + + final Optional error = EventValidation.forType(et).validate(invalidEvent); + + assertThat(error.get().getMessage(), + equalTo("#/metadata/span_ctx/ot-tracer-spanid: expected type: String, found: Integer")); } @Test From 647c0179166f9e61137bfa3cac10985479f59072 Mon Sep 17 00:00:00 2001 From: cbornet Date: Wed, 12 Sep 2018 16:45:21 +0200 Subject: [PATCH 115/176] Put nakadi-event-bus-api.yaml under the api/ folder in docker --- Dockerfile | 2 +- src/main/resources/application.yml | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index c1a89678df..d3ace98ebc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ MAINTAINER Team Aruha, team-aruha@zalando.de WORKDIR / ADD build/libs/nakadi.jar nakadi.jar -ADD api/nakadi-event-bus-api.yaml nakadi-event-bus-api.yaml +ADD api/nakadi-event-bus-api.yaml api/nakadi-event-bus-api.yaml EXPOSE 8080 diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index f924b588a6..37ccbe82a4 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -128,7 +128,7 @@ nakadi: twintip: mapping: /api - yaml: "file:nakadi-event-bus-api.yaml" + yaml: "file:api/nakadi-event-bus-api.yaml" --- spring: @@ -156,9 +156,6 @@ kpi: spring: profiles: test -twintip: - mapping: /api - yaml: "file:api/nakadi-event-bus-api.yaml" --- From a06a092ee1cf7857e3b06efcf090a5f8d8f0983c Mon Sep 17 00:00:00 2001 From: Kunal Jha Date: Thu, 20 Sep 2018 14:15:46 +0200 Subject: [PATCH 116/176] Intitial changes for bug fix --- .idea/codeStyleSettings.xml | 16 ---------------- .../nakadi/controller/ExceptionHandling.java | 9 ++++++++- .../nakadi/domain/SubscriptionAuthorization.java | 11 +++++++++-- .../runtime/SubscriptionValidationException.java | 9 +++++++++ 4 files changed, 26 insertions(+), 19 deletions(-) delete mode 100644 .idea/codeStyleSettings.xml create mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionValidationException.java diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml deleted file mode 100644 index 754e68b6e6..0000000000 --- a/.idea/codeStyleSettings.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 604042b162..1e9d1f0df3 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -34,6 +34,7 @@ import org.zalando.nakadi.exceptions.runtime.TimelineException; import org.zalando.nakadi.exceptions.runtime.TopicCreationException; import org.zalando.nakadi.exceptions.runtime.UnprocessableSubscriptionException; +import org.zalando.nakadi.exceptions.runtime.SubscriptionValidationException; import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; import org.zalando.problem.spring.web.advice.ProblemHandling; @@ -200,7 +201,13 @@ public ResponseEntity handleEnrichmentException(final EnrichmentExcepti LOG.debug(exception.getMessage()); return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } - + @ExceptionHandler(SubscriptionValidationException.class) + public ResponseEntity handleSubscriptionValidationException(final + SubscriptionValidationException exception, + final NativeWebRequest request) { + LOG.debug(exception.getMessage()); + return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); + } @ExceptionHandler(NoSuchPartitionStrategyException.class) public ResponseEntity handleNoSuchPartitionStrategyException( final NoSuchPartitionStrategyException exception, diff --git a/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java b/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java index 4c345b879d..f5aab94a0a 100644 --- a/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java +++ b/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java @@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableMap; import org.zalando.nakadi.plugin.api.authz.AuthorizationAttribute; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; +import org.zalando.nakadi.exceptions.runtime.SubscriptionValidationException; import javax.validation.Valid; import javax.validation.constraints.NotNull; @@ -31,8 +32,14 @@ public SubscriptionAuthorization(@JsonProperty("admins") final List readers) { // actually these three properties should never be null but the validation framework first creates an object // and then uses getters to check if values are null or not, so we need to do this check to avoid exception - this.admins = admins == null ? null : Collections.unmodifiableList(admins); - this.readers = readers == null ? null : Collections.unmodifiableList(readers); + if(admins == null ){ + throw new SubscriptionValidationException("Admin cannot be null!!"); + } + if(readers== null){ + throw new SubscriptionValidationException("Reader cannot be null!!"); + } + this.admins = Collections.unmodifiableList(admins); + this.readers = Collections.unmodifiableList(readers); } public List getAdmins() { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionValidationException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionValidationException.java new file mode 100644 index 0000000000..ebe4fe23bf --- /dev/null +++ b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionValidationException.java @@ -0,0 +1,9 @@ +package org.zalando.nakadi.exceptions.runtime; + +public class SubscriptionValidationException extends NakadiBaseException { + + public SubscriptionValidationException(final String message) { + super(message); + } + +} \ No newline at end of file From 2dbff22118bfe5c2ef5387cf4fb1c2a44070f7bf Mon Sep 17 00:00:00 2001 From: Kunal Jha Date: Thu, 20 Sep 2018 16:03:18 +0200 Subject: [PATCH 117/176] Some correction --- .../nakadi/controller/ExceptionHandling.java | 9 +-------- .../domain/SubscriptionAuthorization.java | 14 ++++---------- .../SubscriptionValidationException.java | 9 --------- .../auth/DefaultAuthorizationService.java | 1 + .../nakadi/service/AuthorizationValidator.java | 18 ++++++++++++++++++ .../subscription/SubscriptionService.java | 2 ++ 6 files changed, 26 insertions(+), 27 deletions(-) delete mode 100644 src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionValidationException.java diff --git a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java index 1e9d1f0df3..604042b162 100644 --- a/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java +++ b/src/main/java/org/zalando/nakadi/controller/ExceptionHandling.java @@ -34,7 +34,6 @@ import org.zalando.nakadi.exceptions.runtime.TimelineException; import org.zalando.nakadi.exceptions.runtime.TopicCreationException; import org.zalando.nakadi.exceptions.runtime.UnprocessableSubscriptionException; -import org.zalando.nakadi.exceptions.runtime.SubscriptionValidationException; import org.zalando.problem.MoreStatus; import org.zalando.problem.Problem; import org.zalando.problem.spring.web.advice.ProblemHandling; @@ -201,13 +200,7 @@ public ResponseEntity handleEnrichmentException(final EnrichmentExcepti LOG.debug(exception.getMessage()); return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); } - @ExceptionHandler(SubscriptionValidationException.class) - public ResponseEntity handleSubscriptionValidationException(final - SubscriptionValidationException exception, - final NativeWebRequest request) { - LOG.debug(exception.getMessage()); - return Responses.create(UNPROCESSABLE_ENTITY, exception.getMessage(), request); - } + @ExceptionHandler(NoSuchPartitionStrategyException.class) public ResponseEntity handleNoSuchPartitionStrategyException( final NoSuchPartitionStrategyException exception, diff --git a/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java b/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java index f5aab94a0a..738c480088 100644 --- a/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java +++ b/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java @@ -5,7 +5,6 @@ import com.google.common.collect.ImmutableMap; import org.zalando.nakadi.plugin.api.authz.AuthorizationAttribute; import org.zalando.nakadi.plugin.api.authz.AuthorizationService; -import org.zalando.nakadi.exceptions.runtime.SubscriptionValidationException; import javax.validation.Valid; import javax.validation.constraints.NotNull; @@ -29,17 +28,12 @@ public class SubscriptionAuthorization implements ValidatableAuthorization { private final List readers; public SubscriptionAuthorization(@JsonProperty("admins") final List admins, - @JsonProperty("readers") final List readers) { + @JsonProperty("readers") final List readers) { // actually these three properties should never be null but the validation framework first creates an object // and then uses getters to check if values are null or not, so we need to do this check to avoid exception - if(admins == null ){ - throw new SubscriptionValidationException("Admin cannot be null!!"); - } - if(readers== null){ - throw new SubscriptionValidationException("Reader cannot be null!!"); - } - this.admins = Collections.unmodifiableList(admins); - this.readers = Collections.unmodifiableList(readers); + + this.admins = admins == null ? null : Collections.unmodifiableList(admins); + this.readers = readers == null ? null : Collections.unmodifiableList(readers); } public List getAdmins() { diff --git a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionValidationException.java b/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionValidationException.java deleted file mode 100644 index ebe4fe23bf..0000000000 --- a/src/main/java/org/zalando/nakadi/exceptions/runtime/SubscriptionValidationException.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.zalando.nakadi.exceptions.runtime; - -public class SubscriptionValidationException extends NakadiBaseException { - - public SubscriptionValidationException(final String message) { - super(message); - } - -} \ No newline at end of file diff --git a/src/main/java/org/zalando/nakadi/plugin/auth/DefaultAuthorizationService.java b/src/main/java/org/zalando/nakadi/plugin/auth/DefaultAuthorizationService.java index 51fd4a97f2..65602d97a7 100644 --- a/src/main/java/org/zalando/nakadi/plugin/auth/DefaultAuthorizationService.java +++ b/src/main/java/org/zalando/nakadi/plugin/auth/DefaultAuthorizationService.java @@ -13,6 +13,7 @@ public boolean isAuthorized(final Operation operation, final Resource resource) @Override public boolean isAuthorizationAttributeValid(final AuthorizationAttribute authorizationAttribute) { + return true; } } diff --git a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java index 1336f59f62..8afae068bf 100644 --- a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java +++ b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java @@ -49,11 +49,29 @@ public void validateAuthorization(@Nullable final ValidatableAuthorization auth) ServiceTemporarilyUnavailableException { if (auth != null) { final Map> authorization = auth.asMapValue(); + checkAuthAttributesEmpty(authorization); checkAuthAttributesAreValid(authorization); checkAuthAttributesNoDuplicates(authorization); } } + private void checkAuthAttributesEmpty(final Map> allAttributes) + throws UnableProcessException, ServiceTemporarilyUnavailableException { + try { + final String + emptyValErrMessage = allAttributes.entrySet().stream() + .filter(attr -> ((attr.getKey() == null)|| (attr.getValue() == null))) + .map(attr -> String.format("Authorization attribute %s:%s is Null", + attr.getKey(), attr.getValue())) + .collect(Collectors.joining(", ")); + if (!Strings.isNullOrEmpty(emptyValErrMessage)) { + throw new UnableProcessException(emptyValErrMessage); + } + } catch (final PluginException e) { + throw new ServiceTemporarilyUnavailableException("Error calling Null check plugin", e); + } + } + private void checkAuthAttributesNoDuplicates(final Map> allAttributes) throws UnableProcessException { final String duplicatesErrMessage = allAttributes.entrySet().stream() diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java index dcae6188d8..b3abbdd140 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java @@ -132,6 +132,8 @@ public Subscription createSubscription(final SubscriptionBase subscriptionBase) subscriptionValidationService.validateSubscription(subscriptionBase); + + final Subscription subscription = subscriptionRepository.createSubscription(subscriptionBase); nakadiKpiPublisher.publish(subLogEventType, () -> new JSONObject() From 87d221111f254c7c899cc8dfd14599a4e5b1a77b Mon Sep 17 00:00:00 2001 From: Kunal Jha Date: Thu, 20 Sep 2018 16:27:48 +0200 Subject: [PATCH 118/176] Added initialisation to Subscription Validation Test --- .../nakadi/service/SubscriptionValidationServiceTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java index b02b376fe4..243180b8fc 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java @@ -23,6 +23,7 @@ import org.zalando.nakadi.service.subscription.SubscriptionValidationService; import org.zalando.nakadi.service.timeline.TimelineService; import org.zalando.nakadi.view.SubscriptionCursorWithoutToken; +import org.zalando.nakadi.domain.SubscriptionAuthorization; import java.util.Collections; import java.util.HashMap; @@ -48,6 +49,7 @@ public class SubscriptionValidationServiceTest { public static final String ET3 = "et3"; public static final String P0 = "p0"; + private TopicRepository topicRepository; private EventTypeRepository etRepo; private SubscriptionValidationService subscriptionValidationService; @@ -89,6 +91,7 @@ public void setUp() throws InternalNakadiException { subscriptionBase = new SubscriptionBase(); subscriptionBase.setEventTypes(ImmutableSet.of(ET1, ET2, ET3)); subscriptionBase.setReadFrom(SubscriptionBase.InitialPosition.CURSORS); + subscriptionBase.setAuthorization(new SubscriptionAuthorization(null, null)); } @Test(expected = InconsistentStateException.class) From c0de8ccfef16e1167a024ccb03479006fe339c4d Mon Sep 17 00:00:00 2001 From: Kunal Jha Date: Fri, 21 Sep 2018 10:15:04 +0200 Subject: [PATCH 119/176] Removed the accidental spaces --- .../org/zalando/nakadi/domain/SubscriptionAuthorization.java | 3 +-- .../nakadi/plugin/auth/DefaultAuthorizationService.java | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java b/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java index 738c480088..202e4c4d85 100644 --- a/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java +++ b/src/main/java/org/zalando/nakadi/domain/SubscriptionAuthorization.java @@ -28,10 +28,9 @@ public class SubscriptionAuthorization implements ValidatableAuthorization { private final List readers; public SubscriptionAuthorization(@JsonProperty("admins") final List admins, - @JsonProperty("readers") final List readers) { + @JsonProperty("readers") final List readers){ // actually these three properties should never be null but the validation framework first creates an object // and then uses getters to check if values are null or not, so we need to do this check to avoid exception - this.admins = admins == null ? null : Collections.unmodifiableList(admins); this.readers = readers == null ? null : Collections.unmodifiableList(readers); } diff --git a/src/main/java/org/zalando/nakadi/plugin/auth/DefaultAuthorizationService.java b/src/main/java/org/zalando/nakadi/plugin/auth/DefaultAuthorizationService.java index 65602d97a7..51fd4a97f2 100644 --- a/src/main/java/org/zalando/nakadi/plugin/auth/DefaultAuthorizationService.java +++ b/src/main/java/org/zalando/nakadi/plugin/auth/DefaultAuthorizationService.java @@ -13,7 +13,6 @@ public boolean isAuthorized(final Operation operation, final Resource resource) @Override public boolean isAuthorizationAttributeValid(final AuthorizationAttribute authorizationAttribute) { - return true; } } From 54b92ddad27124148df57707080a4c5aef988594 Mon Sep 17 00:00:00 2001 From: Kunal Jha Date: Fri, 21 Sep 2018 10:33:46 +0200 Subject: [PATCH 120/176] Restored Check Style --- .idea/codeStyleSettings.xml | 16 ++++++++++++++++ .../nakadi/service/AuthorizationValidator.java | 6 +----- 2 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 .idea/codeStyleSettings.xml diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 0000000000..d77ede9c55 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java index 8afae068bf..b2fa139677 100644 --- a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java +++ b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java @@ -56,8 +56,7 @@ public void validateAuthorization(@Nullable final ValidatableAuthorization auth) } private void checkAuthAttributesEmpty(final Map> allAttributes) - throws UnableProcessException, ServiceTemporarilyUnavailableException { - try { + throws UnableProcessException{ final String emptyValErrMessage = allAttributes.entrySet().stream() .filter(attr -> ((attr.getKey() == null)|| (attr.getValue() == null))) @@ -67,9 +66,6 @@ private void checkAuthAttributesEmpty(final Map> allAttributes) From 0752c853e3eb3c43de30d8a6743a0fcf3663aff1 Mon Sep 17 00:00:00 2001 From: Kunal jha Date: Fri, 21 Sep 2018 11:01:28 +0200 Subject: [PATCH 121/176] Fixed spaces in the codeStyle --- .idea/codeStyleSettings.xml | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml index d77ede9c55..92311f27be 100644 --- a/.idea/codeStyleSettings.xml +++ b/.idea/codeStyleSettings.xml @@ -1,16 +1,15 @@ - - - - \ No newline at end of file + + + From 20ed10d59cf2de53cf027d4a4ce962522a33aeb2 Mon Sep 17 00:00:00 2001 From: dsorokin Date: Tue, 25 Sep 2018 13:37:33 +0200 Subject: [PATCH 122/176] ARUHA-1854 Introduce ordering_instance_ids rework documentation --- docs/_data/nakadi-event-bus-api.yaml | 17 ++++++++++++----- .../nakadi/service/EventTypeService.java | 12 +++++++++--- .../nakadi/validation/JsonSchemaEnrichment.java | 4 ++-- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/docs/_data/nakadi-event-bus-api.yaml b/docs/_data/nakadi-event-bus-api.yaml index 49d93dd6a2..6486e7efeb 100644 --- a/docs/_data/nakadi-event-bus-api.yaml +++ b/docs/_data/nakadi-event-bus-api.yaml @@ -309,6 +309,8 @@ paths: responses: '200': description: EventType is successfuly removed + '404': + description: EventType is not found in nakadi '401': description: Client is not authenticated schema: @@ -2640,17 +2642,22 @@ definitions: description: | This is only an informational field. - Specifies array of fields that are used to be event identifier. + Indicates which field represents the data instance identifier and scope in which ordering_key_fields + provides a strict order. It is typically a single field, but multiple fields for compound identifier + keys are also supported. + + This is an informational-only event type attribute without specific Nakadi semantics for specification of + application level ordering. It only can be used in combination with ordering_key_fields. This field can be modified at any moment, but event type owners are expected to notify consumer in advance about the change. items: type: string description: | - Indicates a single instance id field. This is a dot separated string, which is applied onto the whole event - object, including the contained metadata and data (in case of data change event). - - The field must be present in the schema. + Indicates a single key field. It is a simple path (dot separated) to the JSON leaf element of the whole + event object, including the contained metadata and data (in case of a data change event) objects, and it + must be present in the schema. + example: "data.order_number" audience: type: string x-extensible-enum: diff --git a/src/main/java/org/zalando/nakadi/service/EventTypeService.java b/src/main/java/org/zalando/nakadi/service/EventTypeService.java index 9d7d48cb80..5a5ecdae6b 100644 --- a/src/main/java/org/zalando/nakadi/service/EventTypeService.java +++ b/src/main/java/org/zalando/nakadi/service/EventTypeService.java @@ -223,7 +223,7 @@ public void delete(final String eventTypeName) throws EventTypeDeletionException } Closeable deletionCloser = null; final EventType eventType; - Multimap topicsToDelete = null; + final Multimap topicsToDelete; try { deletionCloser = timelineSync.workWithEventType(eventTypeName, nakadiSettings.getTimelineWaitTimeoutMs()); @@ -509,8 +509,14 @@ private void validateSchema(final EventTypeBase eventType) throws InvalidEventTy throw new InvalidEventTypeException("\"metadata\" property is reserved"); } - validateFieldsInSchema("ordering_key_fields", eventType.getOrderingKeyFields(), schema); - validateFieldsInSchema("ordering_instance_ids", eventType.getOrderingInstanceIds(), schema); + final List orderingInstanceIds = eventType.getOrderingInstanceIds(); + final List orderingKeyFields = eventType.getOrderingKeyFields(); + if (!orderingInstanceIds.isEmpty() && orderingKeyFields.isEmpty()) { + throw new InvalidEventTypeException( + "`ordering_instance_ids` field can not be defined without defining `ordering_key_fields`"); + } + validateFieldsInSchema("ordering_key_fields", orderingKeyFields, schema); + validateFieldsInSchema("ordering_instance_ids", orderingInstanceIds, schema); if (eventType.getCompatibilityMode() == CompatibilityMode.COMPATIBLE) { validateJsonSchemaConstraints(schemaAsJson); diff --git a/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java b/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java index 33487c92d5..ebd59c55b6 100644 --- a/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java +++ b/src/main/java/org/zalando/nakadi/validation/JsonSchemaEnrichment.java @@ -128,10 +128,10 @@ private static JSONObject wrapSchemaInData(final JSONObject schema, final EventT properties.put("data_type", new JSONObject().put("type", "string")); properties.put("data_op", new JSONObject().put("type", "string") - .put("enum", Arrays.asList(new String[]{"C", "U", "D", "S"}))); + .put("enum", Arrays.asList("C", "U", "D", "S"))); properties.put(DATA_CHANGE_WRAP_FIELD, schema); - wrapper.put("additionalProperties", false); + wrapper.put(ADDITIONAL_PROPERTIES, false); addToRequired(wrapper, new String[]{"data_type", "data_op", "data"}); From 7c38a11fa6ce8989df008b54d085e52b90adffae Mon Sep 17 00:00:00 2001 From: Kunal Jha Date: Tue, 25 Sep 2018 14:04:06 +0200 Subject: [PATCH 123/176] Acceptance test for the bug --- .DS_Store | Bin 0 -> 10244 bytes .../nakadi/webservice/hila/SubscriptionAT.java | 13 +++++++++++++ .../zalando/nakadi/domain/SubscriptionBase.java | 1 + .../nakadi/service/AuthorizationValidator.java | 12 +++++++----- .../subscription/SubscriptionService.java | 2 -- .../service/AuthorizationValidatorTest.java | 2 ++ .../SubscriptionValidationServiceTest.java | 1 - 7 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..dc9d25aa71520d6c6b949033a68ed2a7f204337f GIT binary patch literal 10244 zcmeHMO>7%Q6n>kZdJ_i{RY>iDRx44ULZM1plu+>_*R_F2C5^BHLJ(5_kyzb$jel@M zFv^8HHwqVeLvZGR#F0~SDiTm3A+D`BAOvSxzBjvF&l_(z5`<==oj0EM-n?(VH#@tt zAtEQ+tp)wNnT!M7qPyWVyp%QF0hb(P}Wxz6E8L$jk1}p>r z6$bFk=HjM9X=}@XWxz5JGr;?Uhl^z7Qa0AkdWG0fkp@as- z30)yWS0_4RIH5cGy~r*T$=y(f?&L&=4=0N3L?;wSMaTG_GAAb!N?Th7ECa&~@Y#Kg z&d>(csUyzs-+X&g*KGy4T(#S&5Z&4@fA`~AsjD8SYi?@a1a7V{g4F$Zv`Jkmi>Tx< zBEv$9y|?h$-QSWdVgv_R2pr+&5=LoJiK^sNP2hO=_Nh2ZY$0%b{m1bn3k^r2g~0Kc zhaqSjeAI!VMkRs4dG>p$)#C40`d>X`YU9`mS`pXzh~ti8=1r^tjMY#_CaMOaFQC;CX_h*w^e-oTIgW;G ze=W1JW@=+}30fUt`mP68ni?QfD>z;k60dU%wmRM^x=1h41zM&TDNmQ^GUOTBGUw@h zX!t!y72F{;)K{rZ9optq3eRis^^KT+8ooyn^D^ZSZyoXl)ckuHJ*#LHlj5t)U)M4} z9r+aL6NBX~v}u;MxQ0-LZc_u9>9 zf7vTH{d&7IH+Rb!866uxl5*Wick+SBwZdl5D|AYoZaZ6Qy}`d$N}bJe)Gh{rAGb^8 zSL?Oj`piQYgGQ%RZ`4}Kxn8Zo!8)=Vra9&Mox&6YjA`=bu};vbFu*&inljKH(W-QqkKcO^3hZ`ct&TBt;VF zhgDN=B;wa$y-3E8UL=HmXCNZ}yM7 zaKpWtWHCUSY#~sqAT$A<^WZ#(4CIrxZhr7MI`TB<6PaCA8-I~rPxRsp>t3VS7+X|H z$mkuBQDr6ASSo%FsFA;9;ly9MMxVW|5wm`4hUYzwM^Au1-^`O*Jvt)IQlO%dkL5TL z*%LpTS{ eventTypes = IntStream.range(0, 10).mapToObj(i -> createEventType()) diff --git a/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java b/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java index a420afb02e..b0e93666a3 100644 --- a/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java +++ b/src/main/java/org/zalando/nakadi/domain/SubscriptionBase.java @@ -42,6 +42,7 @@ public enum InitialPosition { private List initialCursors = ImmutableList.of(); @Nullable + @Valid private SubscriptionAuthorization authorization; public SubscriptionBase() { diff --git a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java index b2fa139677..d69cdbb6d1 100644 --- a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java +++ b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java @@ -48,6 +48,7 @@ public AuthorizationValidator( public void validateAuthorization(@Nullable final ValidatableAuthorization auth) throws UnableProcessException, ServiceTemporarilyUnavailableException { if (auth != null) { + final Map> authorization = auth.asMapValue(); checkAuthAttributesEmpty(authorization); checkAuthAttributesAreValid(authorization); @@ -55,15 +56,16 @@ public void validateAuthorization(@Nullable final ValidatableAuthorization auth) } } - private void checkAuthAttributesEmpty(final Map> allAttributes) + public void checkAuthAttributesEmpty(final Map> allAttributes) throws UnableProcessException{ - final String + final String emptyValErrMessage = allAttributes.entrySet().stream() - .filter(attr -> ((attr.getKey() == null)|| (attr.getValue() == null))) - .map(attr -> String.format("Authorization attribute %s:%s is Null", + .filter(attr -> ((attr.getKey().length() == 0) || (attr.getValue().isEmpty()))) + .map(attr -> String.format("authorization attribute %s:%s is null", attr.getKey(), attr.getValue())) .collect(Collectors.joining(", ")); - if (!Strings.isNullOrEmpty(emptyValErrMessage)) { + + if (!Strings.isNullOrEmpty(emptyValErrMessage)) { throw new UnableProcessException(emptyValErrMessage); } } diff --git a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java index b3abbdd140..dcae6188d8 100644 --- a/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java +++ b/src/main/java/org/zalando/nakadi/service/subscription/SubscriptionService.java @@ -132,8 +132,6 @@ public Subscription createSubscription(final SubscriptionBase subscriptionBase) subscriptionValidationService.validateSubscription(subscriptionBase); - - final Subscription subscription = subscriptionRepository.createSubscription(subscriptionBase); nakadiKpiPublisher.publish(subLogEventType, () -> new JSONObject() diff --git a/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java b/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java index 1f4c2396d2..bf93aabc5e 100644 --- a/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java +++ b/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java @@ -2,6 +2,7 @@ import com.google.common.collect.ImmutableList; + import org.junit.Test; import org.zalando.nakadi.domain.ResourceAuthorization; import org.zalando.nakadi.domain.ResourceAuthorizationAttribute; @@ -31,6 +32,7 @@ public class AuthorizationValidatorTest { private final AuthorizationAttribute attr2 = new ResourceAuthorizationAttribute("type2", "value2"); private final AuthorizationAttribute attr3 = new ResourceAuthorizationAttribute("type3", "value3"); private final AuthorizationAttribute attr4 = new ResourceAuthorizationAttribute("type4", "value4"); + private final AuthorizationAttribute attr5 = new ResourceAuthorizationAttribute(null, null); public AuthorizationValidatorTest() { authorizationService = mock(AuthorizationService.class); diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java index 243180b8fc..a430ef762a 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java @@ -49,7 +49,6 @@ public class SubscriptionValidationServiceTest { public static final String ET3 = "et3"; public static final String P0 = "p0"; - private TopicRepository topicRepository; private EventTypeRepository etRepo; private SubscriptionValidationService subscriptionValidationService; From dd7e40b5cf19ebdb7dac27d37532d3348e15b236 Mon Sep 17 00:00:00 2001 From: Kunal Jha Date: Tue, 25 Sep 2018 14:13:08 +0200 Subject: [PATCH 124/176] Removed not used variables --- .../org/zalando/nakadi/service/AuthorizationValidator.java | 7 ++----- .../zalando/nakadi/service/AuthorizationValidatorTest.java | 2 -- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java index d69cdbb6d1..c94cd16eb8 100644 --- a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java +++ b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java @@ -48,7 +48,6 @@ public AuthorizationValidator( public void validateAuthorization(@Nullable final ValidatableAuthorization auth) throws UnableProcessException, ServiceTemporarilyUnavailableException { if (auth != null) { - final Map> authorization = auth.asMapValue(); checkAuthAttributesEmpty(authorization); checkAuthAttributesAreValid(authorization); @@ -56,15 +55,13 @@ public void validateAuthorization(@Nullable final ValidatableAuthorization auth) } } - public void checkAuthAttributesEmpty(final Map> allAttributes) + private void checkAuthAttributesEmpty(final Map> allAttributes) throws UnableProcessException{ - final String - emptyValErrMessage = allAttributes.entrySet().stream() + final String emptyValErrMessage = allAttributes.entrySet().stream() .filter(attr -> ((attr.getKey().length() == 0) || (attr.getValue().isEmpty()))) .map(attr -> String.format("authorization attribute %s:%s is null", attr.getKey(), attr.getValue())) .collect(Collectors.joining(", ")); - if (!Strings.isNullOrEmpty(emptyValErrMessage)) { throw new UnableProcessException(emptyValErrMessage); } diff --git a/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java b/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java index bf93aabc5e..8ea8222855 100644 --- a/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java +++ b/src/test/java/org/zalando/nakadi/service/AuthorizationValidatorTest.java @@ -1,6 +1,5 @@ package org.zalando.nakadi.service; - import com.google.common.collect.ImmutableList; import org.junit.Test; @@ -32,7 +31,6 @@ public class AuthorizationValidatorTest { private final AuthorizationAttribute attr2 = new ResourceAuthorizationAttribute("type2", "value2"); private final AuthorizationAttribute attr3 = new ResourceAuthorizationAttribute("type3", "value3"); private final AuthorizationAttribute attr4 = new ResourceAuthorizationAttribute("type4", "value4"); - private final AuthorizationAttribute attr5 = new ResourceAuthorizationAttribute(null, null); public AuthorizationValidatorTest() { authorizationService = mock(AuthorizationService.class); From 25181e052f0adbb7a5a72f6aaa64b31ef9c98959 Mon Sep 17 00:00:00 2001 From: Kunal jha Date: Tue, 25 Sep 2018 14:50:56 +0200 Subject: [PATCH 125/176] Delete .DS_Store --- .DS_Store | Bin 10244 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index dc9d25aa71520d6c6b949033a68ed2a7f204337f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 zcmeHMO>7%Q6n>kZdJ_i{RY>iDRx44ULZM1plu+>_*R_F2C5^BHLJ(5_kyzb$jel@M zFv^8HHwqVeLvZGR#F0~SDiTm3A+D`BAOvSxzBjvF&l_(z5`<==oj0EM-n?(VH#@tt zAtEQ+tp)wNnT!M7qPyWVyp%QF0hb(P}Wxz6E8L$jk1}p>r z6$bFk=HjM9X=}@XWxz5JGr;?Uhl^z7Qa0AkdWG0fkp@as- z30)yWS0_4RIH5cGy~r*T$=y(f?&L&=4=0N3L?;wSMaTG_GAAb!N?Th7ECa&~@Y#Kg z&d>(csUyzs-+X&g*KGy4T(#S&5Z&4@fA`~AsjD8SYi?@a1a7V{g4F$Zv`Jkmi>Tx< zBEv$9y|?h$-QSWdVgv_R2pr+&5=LoJiK^sNP2hO=_Nh2ZY$0%b{m1bn3k^r2g~0Kc zhaqSjeAI!VMkRs4dG>p$)#C40`d>X`YU9`mS`pXzh~ti8=1r^tjMY#_CaMOaFQC;CX_h*w^e-oTIgW;G ze=W1JW@=+}30fUt`mP68ni?QfD>z;k60dU%wmRM^x=1h41zM&TDNmQ^GUOTBGUw@h zX!t!y72F{;)K{rZ9optq3eRis^^KT+8ooyn^D^ZSZyoXl)ckuHJ*#LHlj5t)U)M4} z9r+aL6NBX~v}u;MxQ0-LZc_u9>9 zf7vTH{d&7IH+Rb!866uxl5*Wick+SBwZdl5D|AYoZaZ6Qy}`d$N}bJe)Gh{rAGb^8 zSL?Oj`piQYgGQ%RZ`4}Kxn8Zo!8)=Vra9&Mox&6YjA`=bu};vbFu*&inljKH(W-QqkKcO^3hZ`ct&TBt;VF zhgDN=B;wa$y-3E8UL=HmXCNZ}yM7 zaKpWtWHCUSY#~sqAT$A<^WZ#(4CIrxZhr7MI`TB<6PaCA8-I~rPxRsp>t3VS7+X|H z$mkuBQDr6ASSo%FsFA;9;ly9MMxVW|5wm`4hUYzwM^Au1-^`O*Jvt)IQlO%dkL5TL z*%LpTS{ Date: Tue, 25 Sep 2018 16:53:41 +0200 Subject: [PATCH 126/176] Added the review changes --- .../nakadi/service/AuthorizationValidator.java | 13 ------------- .../service/SubscriptionValidationServiceTest.java | 3 +-- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java index c94cd16eb8..1336f59f62 100644 --- a/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java +++ b/src/main/java/org/zalando/nakadi/service/AuthorizationValidator.java @@ -49,24 +49,11 @@ public void validateAuthorization(@Nullable final ValidatableAuthorization auth) ServiceTemporarilyUnavailableException { if (auth != null) { final Map> authorization = auth.asMapValue(); - checkAuthAttributesEmpty(authorization); checkAuthAttributesAreValid(authorization); checkAuthAttributesNoDuplicates(authorization); } } - private void checkAuthAttributesEmpty(final Map> allAttributes) - throws UnableProcessException{ - final String emptyValErrMessage = allAttributes.entrySet().stream() - .filter(attr -> ((attr.getKey().length() == 0) || (attr.getValue().isEmpty()))) - .map(attr -> String.format("authorization attribute %s:%s is null", - attr.getKey(), attr.getValue())) - .collect(Collectors.joining(", ")); - if (!Strings.isNullOrEmpty(emptyValErrMessage)) { - throw new UnableProcessException(emptyValErrMessage); - } - } - private void checkAuthAttributesNoDuplicates(final Map> allAttributes) throws UnableProcessException { final String duplicatesErrMessage = allAttributes.entrySet().stream() diff --git a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java index a430ef762a..45a217fb5b 100644 --- a/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java +++ b/src/test/java/org/zalando/nakadi/service/SubscriptionValidationServiceTest.java @@ -23,7 +23,7 @@ import org.zalando.nakadi.service.subscription.SubscriptionValidationService; import org.zalando.nakadi.service.timeline.TimelineService; import org.zalando.nakadi.view.SubscriptionCursorWithoutToken; -import org.zalando.nakadi.domain.SubscriptionAuthorization; + import java.util.Collections; import java.util.HashMap; @@ -90,7 +90,6 @@ public void setUp() throws InternalNakadiException { subscriptionBase = new SubscriptionBase(); subscriptionBase.setEventTypes(ImmutableSet.of(ET1, ET2, ET3)); subscriptionBase.setReadFrom(SubscriptionBase.InitialPosition.CURSORS); - subscriptionBase.setAuthorization(new SubscriptionAuthorization(null, null)); } @Test(expected = InconsistentStateException.class) From 726921073a34462dc27e9890cf666c30c75f811e Mon Sep 17 00:00:00 2001 From: Kunal jha Date: Tue, 25 Sep 2018 16:56:09 +0200 Subject: [PATCH 127/176] Update codeStyleSettings.xml --- .idea/codeStyleSettings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml index 92311f27be..610b833b01 100644 --- a/.idea/codeStyleSettings.xml +++ b/.idea/codeStyleSettings.xml @@ -13,3 +13,4 @@