diff --git a/expressjs/.env b/expressjs/.env index e99a9f0..b615749 100644 --- a/expressjs/.env +++ b/expressjs/.env @@ -1,5 +1 @@ -K_SINK=http://localhost:31111 -PORT=8080 -GREETING=Hello -DELAY=0 CONTAINER_BASENAME=quay.io/openshift-knative/ diff --git a/expressjs/package-lock.json b/expressjs/package-lock.json index 588aa74..aea476a 100644 --- a/expressjs/package-lock.json +++ b/expressjs/package-lock.json @@ -17,6 +17,7 @@ "express-handlebars": "^6.0.6", "express-prom-bundle": "^6.6.0", "git-describe": "^4.1.1", + "joi": "^17.8.3", "morgan": "^1.10.0", "prom-client": "^14.1.1", "semver": "^7.3.8" @@ -675,6 +676,19 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -1163,6 +1177,24 @@ "node": ">= 8" } }, + "node_modules/@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "node_modules/@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", @@ -4685,6 +4717,18 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/joi": { + "version": "17.8.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.8.3.tgz", + "integrity": "sha512-q5Fn6Tj/jR8PfrLrx4fpGH4v9qM6o+vDUfD4/3vxxyg34OmKcNqYZ1qn2mpLza96S8tL0p0rIw2gOZX+/cTg9w==", + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "node_modules/js-sdsl": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", @@ -7661,6 +7705,19 @@ "strip-json-comments": "^3.1.1" } }, + "@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==" + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, "@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -8043,6 +8100,24 @@ "fastq": "^1.6.0" } }, + "@sideway/address": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz", + "integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==", + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==" + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==" + }, "@sinonjs/commons": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", @@ -10721,6 +10796,18 @@ } } }, + "joi": { + "version": "17.8.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.8.3.tgz", + "integrity": "sha512-q5Fn6Tj/jR8PfrLrx4fpGH4v9qM6o+vDUfD4/3vxxyg34OmKcNqYZ1qn2mpLza96S8tL0p0rIw2gOZX+/cTg9w==", + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.3", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, "js-sdsl": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", diff --git a/expressjs/package.json b/expressjs/package.json index c763167..948a151 100644 --- a/expressjs/package.json +++ b/expressjs/package.json @@ -43,6 +43,7 @@ "express-handlebars": "^6.0.6", "express-prom-bundle": "^6.6.0", "git-describe": "^4.1.1", + "joi": "^17.8.3", "morgan": "^1.10.0", "prom-client": "^14.1.1", "semver": "^7.3.8" diff --git a/expressjs/src/domain/entity/project.js b/expressjs/src/domain/entity/project.js index b26f8d2..20e366c 100644 --- a/expressjs/src/domain/entity/project.js +++ b/expressjs/src/domain/entity/project.js @@ -1,7 +1,7 @@ const semver = require('semver') class Platform { - constructor({ node, npm }) { + constructor({ node, express }) { /** * @type {string} @@ -11,7 +11,11 @@ class Platform { /** * @type {string} */ - this.npm = npm + this.express = express + } + + toString() { + return `Express/${this.express} Node/${this.node}` } } diff --git a/expressjs/src/index.js b/expressjs/src/index.js index fac1503..875612d 100644 --- a/expressjs/src/index.js +++ b/expressjs/src/index.js @@ -1,7 +1,7 @@ (async () => { const app = await require('./app').createApp() - const port = process.env.PORT + const port = require('./services/config').port() app.listen(port, () => { console.log(`Listening at http://localhost:${port}/`) diff --git a/expressjs/src/routes/index.js b/expressjs/src/routes/index.js index a0a0a53..38b5b49 100644 --- a/expressjs/src/routes/index.js +++ b/expressjs/src/routes/index.js @@ -2,17 +2,22 @@ const { oapi } = require('../middlewares/openapi') const { resolveProject } = require('../services/project') const config = require('../services/config') +/** + * @param {express.Express} app + */ module.exports = app => { - const project = resolveProject() app.get('/', getDoc(), async (req, res) => { try { + const project = await resolveProject() + const idx = new Index({ + artifact: project.artifact, + greeting: config.greet(), + }) + addResponseHeaders(res, project) if (shouldRenderJson(req)) { - return res.json(await project) - } - const data = { - project: await project, - config, + return res.json(idx) } + const data = { project, config } res.render('index', data) } catch (err) { console.error(err) @@ -23,7 +28,13 @@ module.exports = app => { app.options('/', optionsDoc(), async (_, res) => { try { - res.json(await project) + const project = await resolveProject() + const idx = new Index({ + artifact: project.artifact, + greeting: config.greet(), + }) + addResponseHeaders(res, project) + res.json(idx) } catch (err) { console.error(err) res.status(500) @@ -32,6 +43,38 @@ module.exports = app => { }) } +class Index { + constructor({ artifact, greeting }) { + + /** + * @type {string} + */ + this.artifact = artifact + + /** + * @type {string} + */ + this.greeting = greeting + } +} + +/** + * Adds response headers + * + * @param {*} res the response object + * @param {Project} project holds project info + */ +function addResponseHeaders(res, project) { + const { sink, greet, delay } = config + res.header('Server', project.platform) + .header('X-Version', project.version) + .header('X-Config', JSON.stringify({ + sink: sink(), + greet: greet(), + delay: delay(), + })) +} + function shouldRenderJson(req) { const ua = req.header('user-agent') if (ua && ua.startsWith('Mozilla')) { @@ -67,23 +110,12 @@ function optionsDoc() { schema: { type: 'object', properties: { - version: { type: 'string' }, - artifact: { type: 'string' }, - platform: { - type: 'object', - properties: { - node: { type: 'string' }, - npm: { type: 'string' } - } - } + greeting: { type: 'string' }, + artifact: { type: 'string' } }, example: { - version: 'v1.3.1', - artifact: '@openshift/knative-showcase', - platform: { - node: 'v12.19.0', - npm: 'v6.14.8' - } + greeting: 'Welcome', + artifact: 'knative-showcase' } } } diff --git a/expressjs/src/services/config.js b/expressjs/src/services/config.js index e8adc39..14b5205 100644 --- a/expressjs/src/services/config.js +++ b/expressjs/src/services/config.js @@ -1,21 +1,54 @@ +const Joi = require('joi') + function sink() { - return process.env.K_SINK + return process.env.K_SINK || 'http://localhost:31111' } -function greeting() { - return process.env.GREETING +function greet() { + return process.env.GREET || 'Welcome' } function delay() { - let d = parseInt(process.env.DELAY, 10) - if (isNaN(d) || d < 0) { - return 0 - } - return d + return parseInt(process.env.DELAY || '0', 10) +} + +function port() { + return process.env.PORT || 8080 } -module.exports = { +const config = { sink, - greeting, - delay + greet, + delay, + port } + +const schema = Joi.object({ + sink: Joi.string() + .uri({ scheme: /https?/ }) + .required(), + + greet: Joi.string() + .pattern(new RegExp('^[A-Z][a-z]+$')) + .required(), + + delay: Joi.number() + .min(0) + .required(), + + port: Joi.number() + .min(0) + .required() +}) + +const { error } = schema.validate({ + sink: config.sink(), + greet: config.greet(), + delay: config.delay(), + port: config.port() +}) +if (error) { + throw error +} + +module.exports = config diff --git a/expressjs/src/services/greeter.js b/expressjs/src/services/greeter.js index 0da52ad..e52168c 100644 --- a/expressjs/src/services/greeter.js +++ b/expressjs/src/services/greeter.js @@ -4,7 +4,7 @@ const { Notifier } = require('./notifier') let number = 0 class Greeter { - constructor({ sink, greeting, delay }) { + constructor({ sink, greet, delay }) { /** * @type {Notifier} @@ -14,7 +14,7 @@ class Greeter { /** * @type {() => string} */ - this.greeting = greeting + this.greet = greet /** * @type {() => Number} @@ -28,7 +28,7 @@ class Greeter { */ async hello(who) { const hello = new Hello({ - greeting: this.greeting(), + greeting: this.greet(), who, number: ++number }) diff --git a/expressjs/src/services/project.js b/expressjs/src/services/project.js index 9e9548c..d578609 100644 --- a/expressjs/src/services/project.js +++ b/expressjs/src/services/project.js @@ -1,4 +1,3 @@ -const { exec } = require('child_process') const { Project, Platform } = require('../domain/entity/project') const { isDirectory } = require('./fs') const packageJson = require('../../package.json') @@ -31,29 +30,18 @@ function cachedGitDescribe() { return require('../../build/git-describe') } -async function resolveNpmVersion() { - return new Promise((resolve, reject) => { - exec('npm -v', (err, stdout, stderr) => { - if (err) { - reject(err) - return - } - if (stderr) { - reject(stderr) - return - } - resolve(`v${stdout.trim()}`) - }) - }) +function resolveExpressVersion() { + const json = require('express/package.json') + return json.version } /** * @returns {Platform} */ -async function resolvePlatform() { +function resolvePlatform() { return new Platform({ - node: process.version, - npm: await resolveNpmVersion() + node: process.version.replace(/^v/, ''), + express: resolveExpressVersion() }) } @@ -62,7 +50,7 @@ async function resolvePlatform() { */ async function resolveProject() { const git = await computeGitDescribe() - const platform = await resolvePlatform() + const platform = resolvePlatform() const parts = packageJson.name.split('/', 2) const group = parts.length === 2 ? parts[0].replace(/^@/, '') : null diff --git a/expressjs/test/routes/hello.test.js b/expressjs/test/routes/hello.test.js index 090da8c..848bf99 100644 --- a/expressjs/test/routes/hello.test.js +++ b/expressjs/test/routes/hello.test.js @@ -21,7 +21,7 @@ describe('Route', () => { .expect(200, { who: 'James', number: 1, - greeting: 'Hello' + greeting: 'Welcome' }) expect(counter).toEqual(1) diff --git a/expressjs/test/services/greeter.test.js b/expressjs/test/services/greeter.test.js index c45bb35..51f30ab 100644 --- a/expressjs/test/services/greeter.test.js +++ b/expressjs/test/services/greeter.test.js @@ -32,7 +32,7 @@ describe('Greeter', () => { const config = { sink: () => url, - greeting: () => 'Hola', + greet: () => 'Hola', delay: () => 0, } const g = new Greeter(config) diff --git a/expressjs/test/services/project.test.js b/expressjs/test/services/project.test.js index 9a74893..0c750b9 100644 --- a/expressjs/test/services/project.test.js +++ b/expressjs/test/services/project.test.js @@ -25,8 +25,8 @@ describe('project', () => { expect(project.artifact).toEqual('knative-showcase') // ref: https://regex101.com/r/SqE4A0/1 expect(project.version).toMatch(/^v\d+\.\d+\.\d+(?:-\d+-g[0-9a-f]{7}(?:-dirty)?)?$/) - expect(project.platform.node).toMatch(/^v\d+\.\d+\.\d+$/) - expect(project.platform.npm).toMatch(/^v\d+\.\d+\.\d+$/) + expect(project.platform.node).toMatch(/^\d+\.\d+\.\d+$/) + expect(project.platform.express).toMatch(/^\d+\.\d+\.\d+$/) }) it('ensure Npm version matches git describe', async () => { diff --git a/expressjs/views/index.handlebars b/expressjs/views/index.handlebars index a410610..2e742d3 100644 --- a/expressjs/views/index.handlebars +++ b/expressjs/views/index.handlebars @@ -12,7 +12,7 @@
@@ -42,7 +42,7 @@
  • Group: {{ project.group }}
  • Artifact: {{ project.artifact }}
  • Version: {{ project.version }}
  • -
  • Node.JS Version: {{ project.platform.node }}
  • +
  • Platform: {{ project.platform }}
  • diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/AppConfiguration.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/AppConfiguration.java deleted file mode 100644 index d7788db..0000000 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/AppConfiguration.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.redhat.openshift.knative.showcase.config; - -import org.eclipse.microprofile.config.inject.ConfigProperty; -import pl.wavesoftware.eid.utils.EidExecutions; - -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import javax.inject.Provider; -import java.net.URI; -import java.util.Optional; - -@ApplicationScoped -class AppConfiguration implements - EventsConfiguration, GreetConfiguration, DelayConfiguration { - - private static final String UNSET_BROKER_ADDRESS = "http://localhost:31111"; - private static final String SINK_ADDRESS = "k.sink"; - - private final Provider sink; - private final Provider greet; - private final Provider delay; - - @Inject - AppConfiguration( - @ConfigProperty(name = SINK_ADDRESS, defaultValue = UNSET_BROKER_ADDRESS) - Provider sink, - @ConfigProperty(name = "greet", defaultValue = "Hello") - Provider greet, - @ConfigProperty(name = "delay", defaultValue = "0") - Provider delay - ) { - this.sink = sink; - this.greet = greet; - this.delay = delay; - } - - @Override - public URI sink() { - return EidExecutions.tryToExecute(() -> new URI(sink.get()), "20200302:153319"); - } - - @Override - public String greeting() { - return greet.get(); - } - - @Override - public Optional delayInMillis() { - var delayAsLong = delay.get(); - if (delayAsLong > 0L) { - return Optional.of(delayAsLong); - } - return Optional.empty(); - } - -} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/Config.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/Config.java new file mode 100644 index 0000000..60b1682 --- /dev/null +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/Config.java @@ -0,0 +1,74 @@ +package com.redhat.openshift.knative.showcase.config; + +import io.quarkus.arc.ClientProxy; +import io.quarkus.runtime.StartupEvent; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import pl.wavesoftware.eid.utils.EidExecutions; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.event.Observes; +import javax.inject.Inject; +import javax.validation.ConstraintViolationException; +import javax.validation.Validator; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import java.net.URI; +import java.net.URL; + +@ApplicationScoped +public class Config { + + public static final String GREETING_PROPERTY = "greet"; + public static final String DEFAULT_GREETING = "Welcome"; + private static final String SINK_PROPERTY = "k.sink"; + private static final String DEFAULT_SINK = "http://localhost:31111"; + + private final URL sink; + private final String greet; + private final Long delay; + + @Inject + Config( + @ConfigProperty(name = SINK_PROPERTY, defaultValue = DEFAULT_SINK) + URL sink, + @ConfigProperty(name = GREETING_PROPERTY, defaultValue = DEFAULT_GREETING) + String greet, + @ConfigProperty(name = "delay", defaultValue = "0") + Long delay + ) { + this.sink = sink; + this.greet = greet; + this.delay = delay; + } + + @NotNull + public URI getSink() { + return EidExecutions.tryToExecute(sink::toURI, "20230228:140112"); + } + + @Pattern(regexp = "[A-Z][a-z]+") + public String getGreet() { + return greet; + } + + @Min(0) + public Long getDelay() { + return delay; + } + + public static Config from(Config other) { + if (other instanceof ClientProxy) { + other = ClientProxy.unwrap(other); + } + return new Config(other.sink, other.greet, other.delay); + } + + void startup(@Observes StartupEvent ignoredEvent, Validator validator) { + var violations = validator.validate(this); + if (!violations.isEmpty()) { + throw new ConstraintViolationException(violations); + } + } + +} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/DelayConfiguration.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/DelayConfiguration.java deleted file mode 100644 index 754113c..0000000 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/DelayConfiguration.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.redhat.openshift.knative.showcase.config; - -import java.util.Optional; - -public interface DelayConfiguration { - Optional delayInMillis(); -} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/EventsConfiguration.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/EventsConfiguration.java deleted file mode 100644 index 74b2c68..0000000 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/EventsConfiguration.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.redhat.openshift.knative.showcase.config; - - -import java.net.URI; - -public interface EventsConfiguration { - URI sink(); -} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/GreetConfiguration.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/GreetConfiguration.java deleted file mode 100644 index 66d6a15..0000000 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/GreetConfiguration.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.redhat.openshift.knative.showcase.config; - -public interface GreetConfiguration { - String greeting(); -} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/ProjectInfo.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/Project.java similarity index 89% rename from quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/ProjectInfo.java rename to quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/Project.java index f75641d..77969d8 100644 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/ProjectInfo.java +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/config/Project.java @@ -6,7 +6,7 @@ prefix = "project", namingStrategy = ConfigMapping.NamingStrategy.KEBAB_CASE ) -public interface ProjectInfo { +public interface Project { String group(); String artifact(); String version(); diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/contract/HelloService.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/contract/HelloService.java deleted file mode 100644 index 0ad2e90..0000000 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/contract/HelloService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.redhat.openshift.knative.showcase.domain.contract; - -import com.redhat.openshift.knative.showcase.domain.entity.Hello; - -public interface HelloService { - Hello greet(String who); -} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/entity/Platform.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/entity/Platform.java deleted file mode 100644 index 1ef0731..0000000 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/entity/Platform.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.redhat.openshift.knative.showcase.domain.entity; - -import com.fasterxml.jackson.annotation.JsonProperty; -import pl.wavesoftware.utils.stringify.Stringify; - -import javax.validation.constraints.NotEmpty; - -public class Platform { - @JsonProperty - @NotEmpty - public String quarkus; - @JsonProperty - @NotEmpty - public String java; - - @Override - public String toString() { - return Stringify.of(this).toString(); - } -} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/entity/Project.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/entity/Project.java deleted file mode 100644 index 1197f2f..0000000 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/entity/Project.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.redhat.openshift.knative.showcase.domain.entity; - -import com.fasterxml.jackson.annotation.JsonProperty; -import com.redhat.openshift.knative.showcase.config.ProjectInfo; -import pl.wavesoftware.utils.stringify.Stringify; - -import javax.validation.Valid; -import javax.validation.constraints.NotEmpty; - -public class Project { - @JsonProperty - @NotEmpty - public String group; - @JsonProperty - @NotEmpty - public String artifact; - @JsonProperty - @NotEmpty - public String version; - @JsonProperty - @Valid - public Platform platform; - - public static Project from(ProjectInfo info) { - var p = new Project(); - p.group = info.group(); - p.artifact = info.artifact(); - p.version = info.version(); - p.platform = new Platform(); - p.platform.quarkus = info.platform(); - p.platform.java = System.getProperty("java.version"); - return p; - } - - @Override - public String toString() { - return Stringify.of(this).toString(); - } - -} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/HelloReceivedNotify.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/HelloReceivedNotify.java deleted file mode 100644 index 2499246..0000000 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/HelloReceivedNotify.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.redhat.openshift.knative.showcase.domain.logic; - -import com.redhat.openshift.knative.showcase.domain.entity.Hello; - -interface HelloReceivedNotify { - void notifyFor(Hello hello); -} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/HelloServiceImpl.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/HelloServiceImpl.java deleted file mode 100644 index 00180a3..0000000 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/HelloServiceImpl.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.redhat.openshift.knative.showcase.domain.logic; - -import com.redhat.openshift.knative.showcase.config.DelayConfiguration; -import com.redhat.openshift.knative.showcase.config.GreetConfiguration; -import com.redhat.openshift.knative.showcase.domain.contract.HelloService; -import com.redhat.openshift.knative.showcase.domain.entity.Hello; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; - -@ApplicationScoped -class HelloServiceImpl implements HelloService { - private static final Logger LOGGER = LoggerFactory.getLogger(HelloServiceImpl.class); - - private final GreetConfiguration greetConfiguration; - private final DelayConfiguration delayConfiguration; - private final HelloReceivedNotify helloReceivedNotify; - private final CounterService counterService; - - @Inject - HelloServiceImpl( - GreetConfiguration greetConfiguration, - DelayConfiguration delayConfiguration, - HelloReceivedNotify helloReceivedNotify, - CounterService counterService - ) { - this.greetConfiguration = greetConfiguration; - this.delayConfiguration = delayConfiguration; - this.helloReceivedNotify = helloReceivedNotify; - this.counterService = counterService; - } - - @Override - public Hello greet(String who) { - var greeting = greetConfiguration.greeting(); - var counter = counterService.getNumber(); - var hello = new Hello(greeting, who, counter); - helloReceivedNotify.notifyFor(hello); - delayConfiguration.delayInMillis() - .ifPresent(HelloServiceImpl::sleep); - return hello; - } - - private static void sleep(long delay) { - try { - Thread.sleep(delay); - } catch (InterruptedException ex) { - LOGGER.warn("Interrupted!", ex); - // Restore interrupted state... - Thread.currentThread().interrupt(); - } - } -} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/CloudEventsHelloReceivedNotify.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/CloudEventsNotifier.java similarity index 78% rename from quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/CloudEventsHelloReceivedNotify.java rename to quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/CloudEventsNotifier.java index 7b6171e..3f37aec 100644 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/CloudEventsHelloReceivedNotify.java +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/CloudEventsNotifier.java @@ -1,9 +1,8 @@ -package com.redhat.openshift.knative.showcase.domain.logic; +package com.redhat.openshift.knative.showcase.hello; import com.fasterxml.jackson.databind.ObjectMapper; import io.cloudevents.core.builder.CloudEventBuilder; -import com.redhat.openshift.knative.showcase.domain.entity.Hello; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pl.wavesoftware.eid.utils.EidExecutions; @@ -16,9 +15,10 @@ import java.util.UUID; @ApplicationScoped -class CloudEventsHelloReceivedNotify implements HelloReceivedNotify { +class CloudEventsNotifier implements Notifier { - private static final Logger LOGGER = LoggerFactory.getLogger(CloudEventsHelloReceivedNotify.class); + private static final Logger LOGGER = + LoggerFactory.getLogger(CloudEventsNotifier.class); public static final String SOURCE_URI = "//events/showcase"; public static final URI SOURCE = EidExecutions.tryToExecute( () -> new URI(SOURCE_URI), "20200302:154748" @@ -28,7 +28,7 @@ class CloudEventsHelloReceivedNotify implements HelloReceivedNotify { private final ObjectMapper objectMapper; @Inject - CloudEventsHelloReceivedNotify(EventSender eventSender, ObjectMapper objectMapper) { + CloudEventsNotifier(EventSender eventSender, ObjectMapper objectMapper) { this.eventSender = eventSender; this.objectMapper = objectMapper; } diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/CounterService.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Counter.java similarity index 67% rename from quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/CounterService.java rename to quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Counter.java index ee1f0da..0949605 100644 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/CounterService.java +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Counter.java @@ -1,9 +1,9 @@ -package com.redhat.openshift.knative.showcase.domain.logic; +package com.redhat.openshift.knative.showcase.hello; import javax.enterprise.context.ApplicationScoped; @ApplicationScoped -class CounterService { +class Counter { private int number = 0; diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/HelloEndpoint.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Endpoint.java similarity index 80% rename from quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/HelloEndpoint.java rename to quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Endpoint.java index 2300f0c..7e27263 100644 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/HelloEndpoint.java +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Endpoint.java @@ -1,6 +1,5 @@ -package com.redhat.openshift.knative.showcase.view; +package com.redhat.openshift.knative.showcase.hello; -import com.redhat.openshift.knative.showcase.domain.entity.Hello; import org.eclipse.microprofile.openapi.annotations.Operation; import javax.validation.constraints.Pattern; @@ -11,7 +10,7 @@ import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; -public interface HelloEndpoint { +public interface Endpoint { @GET @Operation( summary = "Basic hello operation", diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/EventSender.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/EventSender.java similarity index 60% rename from quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/EventSender.java rename to quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/EventSender.java index 889d682..9c49954 100644 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/EventSender.java +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/EventSender.java @@ -1,4 +1,4 @@ -package com.redhat.openshift.knative.showcase.domain.logic; +package com.redhat.openshift.knative.showcase.hello; import io.cloudevents.CloudEvent; diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/entity/Hello.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Hello.java similarity index 93% rename from quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/entity/Hello.java rename to quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Hello.java index 78de16a..7670eca 100644 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/entity/Hello.java +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Hello.java @@ -1,4 +1,4 @@ -package com.redhat.openshift.knative.showcase.domain.entity; +package com.redhat.openshift.knative.showcase.hello; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/MicroprofileRestClientEventSender.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/JaxrsEventSender.java similarity index 76% rename from quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/MicroprofileRestClientEventSender.java rename to quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/JaxrsEventSender.java index a2adf8e..4b887b6 100644 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/domain/logic/MicroprofileRestClientEventSender.java +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/JaxrsEventSender.java @@ -1,8 +1,8 @@ -package com.redhat.openshift.knative.showcase.domain.logic; +package com.redhat.openshift.knative.showcase.hello; +import com.redhat.openshift.knative.showcase.config.Config; import io.cloudevents.CloudEvent; import io.cloudevents.http.restful.ws.CloudEventsProvider; -import com.redhat.openshift.knative.showcase.config.EventsConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.helpers.MessageFormatter; @@ -19,20 +19,20 @@ import static pl.wavesoftware.eid.DefaultEid.eid; @ApplicationScoped -class MicroprofileRestClientEventSender implements EventSender { +class JaxrsEventSender implements EventSender { private static final Logger LOGGER = - LoggerFactory.getLogger(MicroprofileRestClientEventSender.class); + LoggerFactory.getLogger(JaxrsEventSender.class); - private final EventsConfiguration eventsConfiguration; + private final Config config; @Inject - MicroprofileRestClientEventSender(EventsConfiguration eventsConfiguration) { - this.eventsConfiguration = eventsConfiguration; + JaxrsEventSender(Config config) { + this.config = config; } @Override public void send(CloudEvent ce) { - var sink = eventsConfiguration.sink(); + var sink = config.getSink(); var target = webTarget(sink); var res = target .request() diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Notifier.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Notifier.java new file mode 100644 index 0000000..4f81313 --- /dev/null +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Notifier.java @@ -0,0 +1,5 @@ +package com.redhat.openshift.knative.showcase.hello; + +interface Notifier { + void notifyFor(Hello hello); +} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Rest.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Rest.java new file mode 100644 index 0000000..407d382 --- /dev/null +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Rest.java @@ -0,0 +1,36 @@ +package com.redhat.openshift.knative.showcase.hello; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.validation.Valid; +import javax.ws.rs.Path; + +@ApplicationScoped +@Path("") +class Rest implements Endpoint { + private static final Logger LOGGER = LoggerFactory.getLogger(Rest.class); + + private final Service service; + + @Inject + Rest(Service service) { + this.service = service; + } + + @Override + @Valid + public Hello hello(String who) { + try { + var hello = service.greet(who); + LOGGER.info("Received hello({}) for {}", hello.getNumber(), who); + LOGGER.debug("Responding with: {}", hello); + return hello; + } catch (RuntimeException ex) { + LOGGER.info("Received hello for: {}", who); + throw ex; + } + } +} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Service.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Service.java new file mode 100644 index 0000000..8b6242a --- /dev/null +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/hello/Service.java @@ -0,0 +1,49 @@ +package com.redhat.openshift.knative.showcase.hello; + +import com.redhat.openshift.knative.showcase.config.Config; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; + +@ApplicationScoped +class Service { + private static final Logger LOGGER = LoggerFactory.getLogger(Service.class); + + private final Config config; + private final Notifier notifier; + private final Counter counter; + + @Inject + Service(Config config, Notifier notifier, Counter counter) { + this.config = config; + this.notifier = notifier; + this.counter = counter; + } + + Hello greet(String who) { + var num = counter.getNumber(); + var hello = new Hello(config.getGreet(), who, num); + notifier.notifyFor(hello); + maybeSleep(); + return hello; + } + + private void maybeSleep() { + var d = config.getDelay(); + if (d > 0) { + sleep(d); + } + } + + private static void sleep(long delay) { + try { + Thread.sleep(delay); + } catch (InterruptedException ex) { + LOGGER.warn("Interrupted!", ex); + // Restore interrupted state... + Thread.currentThread().interrupt(); + } + } +} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/IndexEndpoint.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Endpoint.java similarity index 78% rename from quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/IndexEndpoint.java rename to quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Endpoint.java index 554cf70..5b60053 100644 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/IndexEndpoint.java +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Endpoint.java @@ -1,6 +1,5 @@ -package com.redhat.openshift.knative.showcase.view; +package com.redhat.openshift.knative.showcase.index; -import com.redhat.openshift.knative.showcase.domain.entity.Project; import org.eclipse.microprofile.openapi.annotations.Operation; import javax.ws.rs.GET; @@ -11,13 +10,13 @@ import javax.ws.rs.core.Response; @Path("") -public interface IndexEndpoint { +public interface Endpoint { @GET @Produces({MediaType.TEXT_HTML, MediaType.APPLICATION_JSON}) @Operation(summary = "Displays a index HTML page, or the project info in " + "JSON format if the Accept header is set to application/json or called " + "not from a browser") - Response index(); + Response home(); @OPTIONS @Produces(MediaType.APPLICATION_JSON) @@ -25,5 +24,5 @@ public interface IndexEndpoint { summary = "Retrives info about project", description = "Information about project like maven coordinates and versions" ) - Project project(); + Index info(); } diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Index.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Index.java new file mode 100644 index 0000000..9b4db55 --- /dev/null +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Index.java @@ -0,0 +1,23 @@ +package com.redhat.openshift.knative.showcase.index; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.redhat.openshift.knative.showcase.config.Config; +import com.redhat.openshift.knative.showcase.config.Project; + +import javax.validation.constraints.NotEmpty; + +public class Index { + @JsonProperty + @NotEmpty + public String artifact; + @JsonProperty + public String greeting; + + public static Index from(Project project, Config config) { + var p = new Index(); + p.artifact = project.artifact(); + p.greeting = config.getGreet(); + return p; + } + +} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/IndexMode.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Mode.java similarity index 86% rename from quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/IndexMode.java rename to quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Mode.java index 9818653..52e3215 100644 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/IndexMode.java +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Mode.java @@ -1,4 +1,4 @@ -package com.redhat.openshift.knative.showcase.view; +package com.redhat.openshift.knative.showcase.index; import io.vertx.core.http.HttpServerRequest; import org.jboss.resteasy.reactive.server.jaxrs.HttpHeadersImpl; @@ -9,12 +9,12 @@ import javax.ws.rs.core.MediaType; @RequestScoped -class IndexMode { +class Mode { private final HttpHeaders headers; @Inject - public IndexMode(HttpServerRequest request) { + public Mode(HttpServerRequest request) { this.headers = new HttpHeadersImpl(request.headers()); } diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Presenter.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Presenter.java new file mode 100644 index 0000000..0b52501 --- /dev/null +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Presenter.java @@ -0,0 +1,68 @@ +package com.redhat.openshift.knative.showcase.index; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.redhat.openshift.knative.showcase.config.Config; +import com.redhat.openshift.knative.showcase.config.Project; +import io.quarkus.qute.Location; +import io.quarkus.qute.Template; +import pl.wavesoftware.eid.utils.EidExecutions; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +@ApplicationScoped +class Presenter { + private final Template index; + private final Project project; + private final Config config; + private final ObjectMapper jackson; + + @Inject + Presenter( + @Location("index.html") Template index, + Project project, + Config config, + ObjectMapper jackson + ) { + this.index = index; + this.project = project; + this.config = config; + this.jackson = jackson; + } + + Response.ResponseBuilder asJson() { + return withHeaders(Response + .ok(project, MediaType.APPLICATION_JSON_TYPE) + .entity(index())); + } + + Response.ResponseBuilder asHtml() { + var body = index + .data("project", project) + .data("config", config) + .render(); + return withHeaders(Response.ok(body, MediaType.TEXT_HTML_TYPE)); + } + + Index index() { + return Index.from(project, config); + } + + private Response.ResponseBuilder withHeaders(Response.ResponseBuilder builder) { + return builder + .header("Server", project.platform()) + .header("X-Version", project.version()) + .header("X-Config", configAsJson()); + } + + private String configAsJson() { + return EidExecutions.tryToExecute(this::configAsJsonUnsafe, "20230228:144911"); + } + + private String configAsJsonUnsafe() throws JsonProcessingException { + return jackson.writeValueAsString(Config.from(config)); + } +} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Rest.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Rest.java new file mode 100644 index 0000000..7bd1a4d --- /dev/null +++ b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/index/Rest.java @@ -0,0 +1,38 @@ +package com.redhat.openshift.knative.showcase.index; + +import javax.enterprise.context.ApplicationScoped; +import javax.inject.Inject; +import javax.validation.Valid; +import javax.ws.rs.Path; +import javax.ws.rs.core.Response; + +@ApplicationScoped +@Path("") +class Rest implements Endpoint { + private final Presenter presenter; + private final Mode mode; + + @Inject + Rest(Presenter presenter, Mode mode) { + this.presenter = presenter; + this.mode = mode; + } + + @Override + public Response home() { + Response.ResponseBuilder builder; + if (mode.isJson()) { + builder = presenter.asJson(); + } else { + builder = presenter.asHtml(); + } + return builder.build(); + } + + @Override + @Valid + public Index info() { + return presenter.index(); + } + +} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/HelloEndpointBean.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/HelloEndpointBean.java deleted file mode 100644 index 4ce8003..0000000 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/HelloEndpointBean.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.redhat.openshift.knative.showcase.view; - -import com.redhat.openshift.knative.showcase.domain.contract.HelloService; -import com.redhat.openshift.knative.showcase.domain.entity.Hello; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import javax.validation.Valid; -import javax.ws.rs.Path; - -@ApplicationScoped -@Path("") -public class HelloEndpointBean implements HelloEndpoint { - private static final Logger LOGGER = LoggerFactory.getLogger(HelloEndpointBean.class); - - private final HelloService helloService; - - @Inject - HelloEndpointBean(HelloService helloService) { - this.helloService = helloService; - } - - @Override - @Valid - public Hello hello(String who) { - try { - var hello = helloService.greet(who); - LOGGER.info("Received hello({}) for: {}", hello.getNumber(), who); - LOGGER.debug("Responding with: {}", hello); - return hello; - } catch (RuntimeException ex) { - LOGGER.info("Received hello for: {}", who); - throw ex; - } - } -} diff --git a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/IndexEndpointBean.java b/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/IndexEndpointBean.java deleted file mode 100644 index 323d008..0000000 --- a/quarkus/src/main/java/com/redhat/openshift/knative/showcase/view/IndexEndpointBean.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.redhat.openshift.knative.showcase.view; - -import com.redhat.openshift.knative.showcase.config.EventsConfiguration; -import com.redhat.openshift.knative.showcase.config.ProjectInfo; -import com.redhat.openshift.knative.showcase.domain.entity.Project; -import io.quarkus.qute.Location; -import io.quarkus.qute.Template; - -import javax.enterprise.context.ApplicationScoped; -import javax.inject.Inject; -import javax.validation.Valid; -import javax.ws.rs.Path; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -@ApplicationScoped -@Path("") -public class IndexEndpointBean implements IndexEndpoint { - private final Template index; - private final ProjectInfo projectInfo; - private final EventsConfiguration eventsConfiguration; - private final IndexMode indexMode; - - @Inject - IndexEndpointBean( - @Location("index.html") Template index, - ProjectInfo projectInfo, - EventsConfiguration eventsConfiguration, - IndexMode indexMode - ) { - this.index = index; - this.projectInfo = projectInfo; - this.indexMode = indexMode; - this.eventsConfiguration = eventsConfiguration; - } - - @Override - public Response index() { - if (indexMode.isJson()) { - return Response - .ok(projectInfo, MediaType.APPLICATION_JSON_TYPE) - .entity(project()) - .build(); - } - var body = index - .data("project", Project.from(projectInfo)) - .data("config", eventsConfiguration) - .render(); - return Response.ok(body, MediaType.TEXT_HTML_TYPE).build(); - } - - @Override - @Valid - public Project project() { - return Project.from(projectInfo); - } - -} diff --git a/quarkus/src/main/resources/templates/index.html b/quarkus/src/main/resources/templates/index.html index 9acd235..040540d 100644 --- a/quarkus/src/main/resources/templates/index.html +++ b/quarkus/src/main/resources/templates/index.html @@ -1,5 +1,5 @@ -{@com.redhat.openshift.knative.showcase.domain.entity.Project project} -{@com.redhat.openshift.knative.showcase.config.EventsConfiguration config} +{@com.redhat.openshift.knative.showcase.config.Project project} +{@com.redhat.openshift.knative.showcase.config.Config config} @@ -14,7 +14,7 @@
    @@ -43,7 +43,7 @@

    Application

  • Group: {project.group}
  • Artifact: {project.artifact}
  • Version: {project.version}
  • -
  • Quarkus Version: {project.platform.quarkus}
  • +
  • Platform: {project.platform}
  • diff --git a/quarkus/src/main/templates/application.properties b/quarkus/src/main/templates/application.properties index 159a256..f329a70 100644 --- a/quarkus/src/main/templates/application.properties +++ b/quarkus/src/main/templates/application.properties @@ -6,7 +6,8 @@ quarkus.application.name = knative-showcase project.group = ${project.groupId} project.artifact = ${project.artifactId} project.version = ${project.version} -project.platform = ${quarkus.platform.version} +project.platform = Quarkus/${quarkus.platform.version} Java/${java.version} quarkus.openshift.jvm-dockerfile=src/main/container/jvm/Containerfile quarkus.openshift.native-dockerfile=src/main/container/native/Containerfile +quarkus.opentelemetry.enabled=true diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/Client.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/Client.java new file mode 100644 index 0000000..2408c07 --- /dev/null +++ b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/Client.java @@ -0,0 +1,9 @@ +package com.redhat.openshift.knative.showcase.hello; + + +import com.redhat.openshift.knative.showcase.support.Testing.Constants; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient(baseUri = Constants.DEFAULT_TEST_URL) +interface Client extends Endpoint { +} diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/domain/logic/CloudEventsHelloReceivedNotifyTest.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/CloudEventsNotifierTest.java similarity index 75% rename from quarkus/src/test/java/com/redhat/openshift/knative/showcase/domain/logic/CloudEventsHelloReceivedNotifyTest.java rename to quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/CloudEventsNotifierTest.java index 0ae47ef..2ffae57 100644 --- a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/domain/logic/CloudEventsHelloReceivedNotifyTest.java +++ b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/CloudEventsNotifierTest.java @@ -1,7 +1,6 @@ -package com.redhat.openshift.knative.showcase.domain.logic; +package com.redhat.openshift.knative.showcase.hello; import com.fasterxml.jackson.databind.ObjectMapper; -import com.redhat.openshift.knative.showcase.domain.entity.Hello; import io.cloudevents.CloudEvent; import org.junit.jupiter.api.Test; @@ -10,7 +9,7 @@ import static org.assertj.core.api.Assertions.assertThat; -class CloudEventsHelloReceivedNotifyTest { +class CloudEventsNotifierTest { @Test void notifyFor() { @@ -19,7 +18,7 @@ void notifyFor() { var objectMapper = new ObjectMapper(); var sent = new AtomicReference(); EventSender eventSender = sent::set; - var notify = new CloudEventsHelloReceivedNotify(eventSender, objectMapper); + var notify = new CloudEventsNotifier(eventSender, objectMapper); var now = OffsetDateTime.now(); // when diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/EndpointIT.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/EndpointIT.java new file mode 100644 index 0000000..5b71738 --- /dev/null +++ b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/EndpointIT.java @@ -0,0 +1,13 @@ +package com.redhat.openshift.knative.showcase.hello; + +import com.redhat.openshift.knative.showcase.support.Testing; +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +class EndpointIT extends EndpointTest { + public EndpointIT() { + // Execute the same tests but in native mode. + super(Testing.buildRestClient(Client.class)); + invalidHelloMessage = "Unknown error, status code 400"; + } +} diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HelloEndpointTest.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/EndpointTest.java similarity index 85% rename from quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HelloEndpointTest.java rename to quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/EndpointTest.java index 02a2329..743040d 100644 --- a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HelloEndpointTest.java +++ b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/hello/EndpointTest.java @@ -1,8 +1,10 @@ -package com.redhat.openshift.knative.showcase.view; +package com.redhat.openshift.knative.showcase.hello; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.matching.UrlPattern; -import com.redhat.openshift.knative.showcase.domain.entity.Hello; +import com.redhat.openshift.knative.showcase.support.EventSinkWiremock; +import com.redhat.openshift.knative.showcase.support.HasWiremockServer; +import com.redhat.openshift.knative.showcase.support.Testing; import io.quarkus.test.common.QuarkusTestResource; import io.quarkus.test.junit.QuarkusTest; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; @@ -25,15 +27,15 @@ @QuarkusTest @QuarkusTestResource(EventSinkWiremock.class) -class HelloEndpointTest implements HasWiremockServer { +class EndpointTest implements HasWiremockServer { protected String invalidHelloMessage = "hello.arg0: must match \"^[A-Z][a-z]+$\""; - private final HelloClient client; + private final Client client; private WireMockServer wireMockServer; @Inject - HelloEndpointTest(@RestClient HelloClient client) { + EndpointTest(@RestClient Client client) { this.client = client; } @@ -62,7 +64,7 @@ void hello() { assertThat(hello) .extracting(Hello::getGreeting, Hello::getWho, Hello::getNumber) - .containsExactly("Hello", name, 1); + .containsExactly(Testing.greeting(), name, 1); wireMockServer.verify(1, postRequestedFor(new UrlPattern(equalTo("/"), false)) diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/index/Client.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/index/Client.java new file mode 100644 index 0000000..49df31b --- /dev/null +++ b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/index/Client.java @@ -0,0 +1,9 @@ +package com.redhat.openshift.knative.showcase.index; + + +import com.redhat.openshift.knative.showcase.support.Testing.Constants; +import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; + +@RegisterRestClient(baseUri = Constants.DEFAULT_TEST_URL) +interface Client extends Endpoint { +} diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/index/EndpointIT.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/index/EndpointIT.java new file mode 100644 index 0000000..908c141 --- /dev/null +++ b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/index/EndpointIT.java @@ -0,0 +1,15 @@ +package com.redhat.openshift.knative.showcase.index; + +import com.redhat.openshift.knative.showcase.support.Testing; +import io.quarkus.test.junit.QuarkusIntegrationTest; + +import java.net.URI; + +@QuarkusIntegrationTest +class EndpointIT extends EndpointTest { + public EndpointIT() { + // Execute the same tests but in native mode. + super(Testing.buildRestClient(Client.class)); + rootUri = URI.create(Testing.Constants.DEFAULT_TEST_URL); + } +} diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/IndexEndpointTest.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/index/EndpointTest.java similarity index 64% rename from quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/IndexEndpointTest.java rename to quarkus/src/test/java/com/redhat/openshift/knative/showcase/index/EndpointTest.java index 8a95741..765f157 100644 --- a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/IndexEndpointTest.java +++ b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/index/EndpointTest.java @@ -1,6 +1,6 @@ -package com.redhat.openshift.knative.showcase.view; +package com.redhat.openshift.knative.showcase.index; -import com.redhat.openshift.knative.showcase.domain.entity.Project; +import com.redhat.openshift.knative.showcase.support.Testing; import io.quarkus.test.common.http.TestHTTPResource; import io.quarkus.test.junit.QuarkusTest; import org.eclipse.microprofile.rest.client.inject.RestClient; @@ -18,28 +18,34 @@ import static org.assertj.core.api.Assertions.assertThat; @QuarkusTest -class IndexEndpointTest { +class EndpointTest { private static final String FEDORA_FIREFOX_UA = "Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:109.0) " + "Gecko/20100101 Firefox/109.0"; - private final IndexClient client; + private final Client client; @TestHTTPResource("/") protected URI rootUri; @Inject - IndexEndpointTest(@RestClient IndexClient client) { + EndpointTest(@RestClient Client client) { this.client = client; } @Test void index() { - try (var response = client.index()) { + try (var response = client.home()) { assertThat(response.getMediaType()) .isEqualTo(MediaType.APPLICATION_JSON_TYPE); - var project = response.readEntity(Project.class); - assertProject(project); + var index = response.readEntity(Index.class); + assertIndex(index); + assertThat(response.getHeaderString("Server")) + .matches("^Quarkus/.* Java/.*$"); + assertThat(response.getHeaderString("X-Version")) + .isNotBlank(); + assertThat(response.getHeaderString("X-Config")) + .isNotBlank(); } } @@ -63,15 +69,18 @@ void indexAsBrowser() throws IOException, InterruptedException { @Test void project() { - var project = client.project(); + var index = client.info(); - assertProject(project); + assertIndex(index); } - private void assertProject(Project project) { - assertThat(project) - .extracting(p -> p.group, p -> p.artifact) - .containsExactly("com.redhat.openshift", "knative-showcase"); + private void assertIndex(Index index) { + assertThat(index) + .extracting(p -> p.artifact) + .isEqualTo("knative-showcase"); + assertThat(index) + .extracting(p -> p.greeting) + .isEqualTo(Testing.greeting()); } } diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/EventSinkWiremock.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/support/EventSinkWiremock.java similarity index 94% rename from quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/EventSinkWiremock.java rename to quarkus/src/test/java/com/redhat/openshift/knative/showcase/support/EventSinkWiremock.java index daefaf3..8a99ed7 100644 --- a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/EventSinkWiremock.java +++ b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/support/EventSinkWiremock.java @@ -1,4 +1,4 @@ -package com.redhat.openshift.knative.showcase.view; +package com.redhat.openshift.knative.showcase.support; import com.github.tomakehurst.wiremock.WireMockServer; import io.quarkus.test.common.QuarkusTestResourceLifecycleManager; diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HasWiremockServer.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/support/HasWiremockServer.java similarity index 73% rename from quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HasWiremockServer.java rename to quarkus/src/test/java/com/redhat/openshift/knative/showcase/support/HasWiremockServer.java index d3cee81..6bdd2a1 100644 --- a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HasWiremockServer.java +++ b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/support/HasWiremockServer.java @@ -1,4 +1,4 @@ -package com.redhat.openshift.knative.showcase.view; +package com.redhat.openshift.knative.showcase.support; import com.github.tomakehurst.wiremock.WireMockServer; diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/support/Testing.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/support/Testing.java new file mode 100644 index 0000000..d0b5896 --- /dev/null +++ b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/support/Testing.java @@ -0,0 +1,31 @@ +package com.redhat.openshift.knative.showcase.support; + +import com.redhat.openshift.knative.showcase.config.Config; +import org.eclipse.microprofile.rest.client.RestClientBuilder; + +import java.net.URI; +import java.util.Optional; + +public final class Testing { + + public static T buildRestClient(Class clazz) { + return RestClientBuilder + .newBuilder() + .baseUri(URI.create(Constants.DEFAULT_TEST_URL)) + .build(clazz); + } + + public static String greeting() { + return Optional.ofNullable(System.getenv( + Config.GREETING_PROPERTY.toUpperCase() + )).orElse(Config.DEFAULT_GREETING); + } + + public static class Constants { + public static final String DEFAULT_TEST_URL = "http://localhost:8081"; + + private Constants() { + // not reachable + } + } +} diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HelloClient.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HelloClient.java deleted file mode 100644 index f348fa6..0000000 --- a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HelloClient.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.redhat.openshift.knative.showcase.view; - - -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -@RegisterRestClient(baseUri = Testing.Constants.DEFAULT_TEST_URL) -interface HelloClient extends HelloEndpoint { -} diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HelloEndpointIT.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HelloEndpointIT.java deleted file mode 100644 index 4130dd0..0000000 --- a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/HelloEndpointIT.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.redhat.openshift.knative.showcase.view; - -import io.quarkus.test.junit.QuarkusIntegrationTest; - -@QuarkusIntegrationTest -class HelloEndpointIT extends HelloEndpointTest { - public HelloEndpointIT() { - // Execute the same tests but in native mode. - super(Testing.buildRestClient(HelloClient.class)); - invalidHelloMessage = "Unknown error, status code 400"; - } -} diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/IndexClient.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/IndexClient.java deleted file mode 100644 index ef302dd..0000000 --- a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/IndexClient.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.redhat.openshift.knative.showcase.view; - - -import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; - -@RegisterRestClient(baseUri = Testing.Constants.DEFAULT_TEST_URL) -interface IndexClient extends IndexEndpoint { -} diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/IndexEndpointIT.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/IndexEndpointIT.java deleted file mode 100644 index 75b6a8e..0000000 --- a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/IndexEndpointIT.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.redhat.openshift.knative.showcase.view; - -import io.quarkus.test.junit.QuarkusIntegrationTest; - -import java.net.URI; - -@QuarkusIntegrationTest -class IndexEndpointIT extends IndexEndpointTest { - public IndexEndpointIT() { - // Execute the same tests but in native mode. - super(Testing.buildRestClient(IndexClient.class)); - rootUri = URI.create(Testing.Constants.DEFAULT_TEST_URL); - } -} diff --git a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/Testing.java b/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/Testing.java deleted file mode 100644 index 9420962..0000000 --- a/quarkus/src/test/java/com/redhat/openshift/knative/showcase/view/Testing.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.redhat.openshift.knative.showcase.view; - -import org.jboss.resteasy.microprofile.client.RestClientBuilderImpl; - -import java.net.URI; - -final class Testing { - - static T buildRestClient(Class clazz) { - var br = new RestClientBuilderImpl(); - return br - .baseUri(URI.create(Constants.DEFAULT_TEST_URL)) - .build(clazz); - } - - class Constants { - public static final String DEFAULT_TEST_URL = "http://localhost:8081"; - - private Constants() { - // not reachable - } - } -} diff --git a/quarkus/src/test/resources/application.properties b/quarkus/src/test/resources/application.properties index e79a24a..a7678db 100644 --- a/quarkus/src/test/resources/application.properties +++ b/quarkus/src/test/resources/application.properties @@ -2,3 +2,4 @@ quarkus.rest-client.logging.scope = request-response quarkus.rest-client.logging.body-limit = 1024 quarkus.log.category."org.apache.http.wire".level = DEBUG quarkus.log.category."org.jboss.resteasy.reactive.client.logging".level = DEBUG +quarkus.log.category."com.redhat.openshift.knative".level = TRACE