From 014bd591a39fa8e853af3012f6d0f82b91c21117 Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Mon, 5 Dec 2022 10:02:39 +1100 Subject: [PATCH 1/2] Fix #1332 - use FQCN plus method name as metrics label --- src/main/java/act/metric/MetricEnhancer.java | 8 +- testapps/GH1332/pack | 6 + testapps/GH1332/pack.bat | 5 + testapps/GH1332/pom.xml | 52 + testapps/GH1332/run_dev | 3 + testapps/GH1332/run_dev.bat | 2 + testapps/GH1332/run_prod | 13 + .../main/java/com/mycom/gh1322/AppEntry.java | 49 + .../main/resources/com/mycom/gh1322/.version | 3 + .../src/main/resources/conf/app.properties | 933 ++++++++++++++++++ .../src/main/resources/conf/cron.properties | 24 + .../main/resources/conf/prod/app.properties | 3 + .../src/main/resources/conf/test.properties | 52 + .../main/resources/conf/uat/app.properties | 3 + .../GH1332/src/main/resources/logback.xml | 100 ++ testapps/GH1332/test | 3 + testapps/GH1332/test.bat | 2 + 17 files changed, 1259 insertions(+), 2 deletions(-) create mode 100755 testapps/GH1332/pack create mode 100644 testapps/GH1332/pack.bat create mode 100644 testapps/GH1332/pom.xml create mode 100755 testapps/GH1332/run_dev create mode 100755 testapps/GH1332/run_dev.bat create mode 100755 testapps/GH1332/run_prod create mode 100644 testapps/GH1332/src/main/java/com/mycom/gh1322/AppEntry.java create mode 100644 testapps/GH1332/src/main/resources/com/mycom/gh1322/.version create mode 100644 testapps/GH1332/src/main/resources/conf/app.properties create mode 100644 testapps/GH1332/src/main/resources/conf/cron.properties create mode 100644 testapps/GH1332/src/main/resources/conf/prod/app.properties create mode 100644 testapps/GH1332/src/main/resources/conf/test.properties create mode 100644 testapps/GH1332/src/main/resources/conf/uat/app.properties create mode 100644 testapps/GH1332/src/main/resources/logback.xml create mode 100755 testapps/GH1332/test create mode 100644 testapps/GH1332/test.bat diff --git a/src/main/java/act/metric/MetricEnhancer.java b/src/main/java/act/metric/MetricEnhancer.java index e4cb7efff..ce3e521d0 100644 --- a/src/main/java/act/metric/MetricEnhancer.java +++ b/src/main/java/act/metric/MetricEnhancer.java @@ -81,7 +81,7 @@ public MethodVisitor visitMethod(int access, String name, String desc, String si public AnnotationVisitor visitAnnotation(String desc, boolean visible) { AnnotationVisitor av = super.visitAnnotation(desc, visible); if (DESC_MEASURE_TIME.equals(desc)) { - timeLabel = methodName; + timeLabel = metricsLabel(); return new AnnotationVisitor(ASM5, av) { @Override public void visit(String name, Object value) { @@ -92,7 +92,7 @@ public void visit(String name, Object value) { } }; } else if (DESC_MEASURE_COUNT.equals(desc)) { - countLabel = methodName; + countLabel = metricsLabel(); return new AnnotationVisitor(ASM5, av) { @Override public void visit(String name, Object value) { @@ -162,6 +162,10 @@ private void onFinally(int opcode) { mv.visitVarInsn(ALOAD, posTimer); mv.visitMethodInsn(INVOKEINTERFACE, "act/metric/Timer", "close", "()V", true); } + + private String metricsLabel() { + return S.pathConcat(className, '.', methodName); + } }; } } diff --git a/testapps/GH1332/pack b/testapps/GH1332/pack new file mode 100755 index 000000000..d4daf2bc9 --- /dev/null +++ b/testapps/GH1332/pack @@ -0,0 +1,6 @@ +#!/bin/sh +echo build ... +mvn -q compile +echo run test and then package ... +mvn -q package +echo package has been built up and stored in target/dist dir \ No newline at end of file diff --git a/testapps/GH1332/pack.bat b/testapps/GH1332/pack.bat new file mode 100644 index 000000000..44b5e3aa2 --- /dev/null +++ b/testapps/GH1332/pack.bat @@ -0,0 +1,5 @@ +echo build ... +mvn -q compile +echo run test and then package ... +mvn -q package +echo package has been built up and stored in target/dist dir \ No newline at end of file diff --git a/testapps/GH1332/pom.xml b/testapps/GH1332/pom.xml new file mode 100644 index 000000000..28f03db51 --- /dev/null +++ b/testapps/GH1332/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + + com.mycom.helloworld + GH1332 + 1.0-SNAPSHOT + + My Awesome Application + + + org.actframework + act-starter-parent + 1.9.2.0 + + + + com.mycom.gh1322.AppEntry + + + + + + + + + + + + org.actframework + act + 1.9.3-SNAPSHOT + + + + \ No newline at end of file diff --git a/testapps/GH1332/run_dev b/testapps/GH1332/run_dev new file mode 100755 index 000000000..56d7f76cd --- /dev/null +++ b/testapps/GH1332/run_dev @@ -0,0 +1,3 @@ +#!/bin/sh +echo building ... +mvn -q compile act:run \ No newline at end of file diff --git a/testapps/GH1332/run_dev.bat b/testapps/GH1332/run_dev.bat new file mode 100755 index 000000000..28b0270e1 --- /dev/null +++ b/testapps/GH1332/run_dev.bat @@ -0,0 +1,2 @@ +echo building ... +mvn -q compile act:run \ No newline at end of file diff --git a/testapps/GH1332/run_prod b/testapps/GH1332/run_prod new file mode 100755 index 000000000..451f36553 --- /dev/null +++ b/testapps/GH1332/run_prod @@ -0,0 +1,13 @@ +#!/bin/sh +if [ ! -f target/dist/start ]; then + echo building ... + mvn -q clean package + cd target/dist + tar xzf *.tar.gz +else + cd target/dist +fi +# we want to disable session secure as this is running +# in the local host, we don't expect there are SSL +# certificate enabled. +./run -Dsession.secure=false $* \ No newline at end of file diff --git a/testapps/GH1332/src/main/java/com/mycom/gh1322/AppEntry.java b/testapps/GH1332/src/main/java/com/mycom/gh1322/AppEntry.java new file mode 100644 index 000000000..b1546f4fe --- /dev/null +++ b/testapps/GH1332/src/main/java/com/mycom/gh1322/AppEntry.java @@ -0,0 +1,49 @@ +package com.mycom.gh1322; + +import act.Act; +import act.metric.MeasureCount; +import act.metric.MeasureTime; +import org.osgl.logging.LogManager; +import org.osgl.logging.Logger; +import org.osgl.mvc.annotation.GetAction; +import org.osgl.util.S; +import osgl.version.Version; +import osgl.version.Versioned; + +/** + * A simple hello world app entry + * + * Run this app, try to update some of the code, then + * press F5 in the browser to watch the immediate change + * in the browser! + */ +@SuppressWarnings("unused") +@Versioned +public class AppEntry { + + /** + * Version of this application + */ + public static final Version VERSION = Version.of(AppEntry.class); + + /** + * A logger instance that could be used throughout the application + */ + public static final Logger LOGGER = LogManager.get(AppEntry.class); + + @GetAction + public String getFoo() { + return foo(); + } + + @MeasureCount + @MeasureTime + private String foo() { + return S.random(); + } + + public static void main(String[] args) throws Exception { + Act.start(); + } + +} diff --git a/testapps/GH1332/src/main/resources/com/mycom/gh1322/.version b/testapps/GH1332/src/main/resources/com/mycom/gh1322/.version new file mode 100644 index 000000000..ea0c26126 --- /dev/null +++ b/testapps/GH1332/src/main/resources/com/mycom/gh1322/.version @@ -0,0 +1,3 @@ +artifact=${project.artifactId} +version=${project.version} +build=${buildNumber} \ No newline at end of file diff --git a/testapps/GH1332/src/main/resources/conf/app.properties b/testapps/GH1332/src/main/resources/conf/app.properties new file mode 100644 index 000000000..2cc17c62b --- /dev/null +++ b/testapps/GH1332/src/main/resources/conf/app.properties @@ -0,0 +1,933 @@ +# Application configuration +# act-1.9.2 + +# When `api_doc` is enabled it can navigate to +# http://localhost:5460/~/api +# for API Document. +# +# API doc is enabled by default +# +# uncomment to disable API doc +#api_doc=false + +# When `api_doc.built_in.hide` is enabled the API document +# will not display built-in endpoints, e.g. +# `/~/info` +# +# built-in endpoints is visible in API doc by default +# +# uncomment to hide built-in endpoints in API doc +#api_doc.built_in.hide=true + +# `app.name` set application name +# +# default value: archetype-quickstart +#app.name=archetype-quickstart + +# `basic_authentication` is not used by actframework +# core, however plugins like `act-aaa-plugin` use +# this configuration to check if HTTP basic +# authentication is allowed. +# +# basic authentication is disabled by default +# +# uncomment to enable basic authentication +#basic_authentication=true + +# When `built_in_req_handler` is disabled it will +# not be able to access framework built-in endpoints +# including `/~/info`, `/~/version` etc. +# However the following built-in endpoints is still +# available: +# * GET /~/job/{id}/progress - required by runtime application +# * GET /~/api/book/** - only available in dev mode +# +# built-in endpoints is enabled by default +# +# uncomment to disable built endpoints +#built_in_req_handler=false + +# Configure the cache implementation used by ActFramework. +# The cache class specified must implement +# `org.osgl.cache.CacheServiceProvider` interface. +# +# If not specified cache implementation is determined by +# osgl-cache library automatically depending on the +# libraries available in the following order: +# 1. Memcached service +# 2. EhCache service +# 3. OSGL implemented Simple Cache service based on concurrent hash map +# +# uncomment to set your own cache implementation +#cache.impl= + +# Specify the default cache name +# +# default value: _act_app_ +#cache.name= + +# Specify session cache name +# +# If not specified then the name is the value of 'cache.name' +# +# default value: configuration of 'cache.name' +#cache.name.session= + +# By default @CacheFor annotation is not effective in `dev` mode. +# the `cacheFor.dev` configuration can be used to turn on +# @CacheFor in `dev` mode. +# +# uncomment to enable @CacheFor annotation in `dev` mode +#cacheFor.dev=true + +# CLI service listens to local ip addresses to provide telent +# access for command line access to the running app. +# +# CLI service is enabled by default +# +# uncomment to disable CLI service +#cli=false + +# By default CLI port is `5461` +# +# uncomment to set CLI port +#cli.port= + +# `cli.page.size.json` specifies the number of records to display +# per page for CLI JSON view. +# +# Default CLI JSON view page size is 10 records +# +# uncomment to set CLI JSON view page size +#cli.page.size.json= + +# `cli.page.size.table` specifies the number of records to display +# per page for CLI tabular view. +# +# Default CLI table view page size is 22 records +# +# uncomment to set CLI table view page size +#cli.page.size.table= + +# `cli.progress-bar.style` specifies how the CLI progress bar +# should be rendered. +# +# At the moment there are two options: +# * unicode - default option, use unicode chars to render progress bar +# * ascii - use ASCII char to render progress bar +# +# Default value: block +# +#cli.progress-bar.style=block|ascii + +# `cli.session.ttl` specifies the number of seconds a CLI +# session will be terminated without interaction. +# +# The default CLI session ttl is 300 seconds, i.e. 5 minutes +# +# uncomment to set CLI session ttl +#cli.session.ttl + +# `cli.session.max.int` specifies the maximum concurrent CLI session +# +# The default limits is 3 +# +# uncomment to set CLI session max +#cli.session.max.int + +# `conf-loader.impl` +# specify customized application configuration loader. +# it should be a class name of an implementation of +# `act.conf.ExtendedAppConfLoader` +# +# Default value: `act.conf.ExtendedAppConfLoader.DumbLoader` +#conf-loader.impl= + +# `conf-server.endpoint` specify the remote configuration server endpoint +# Once this is set when app configuration initialised it will send a GET +# request to `${conf-server.endpoint}?key=${app.key} +# +# Note once `conf-server.endpoint` is configured then it assume the +# `conf.private-key` is configured correctly, otherwise the framework +# will refuse to pull configuration from the `conf-server.endpont` and +# raise an exception. +# +# Default value: null +#conf-server.endpoint=https://conf-server/conf + +# `conf.id` set application key - could be used to fetch configuration +# from configuration server. +# +# Default value: ${app.name}-${profile} +#conf.id=${app.name}-${profile} + +# `conf.private-key` set the private key for the app_key. +# the private key is used to decrypt the response coming from +# `conf-server.endpoint`. +# +# Default value: null +#conf.private-key=... + +# `cookie.prefix` specifies the session/flash cookie prefix. +# +# The default cookie prefix is the `shortId` of the application. +# +# uncomment to customize session/flash cookie prefix. +#cookie.prefix= + +# When `cors` is enabled ActFramework will automatically populate the +# CORS relevant headers in HTTP response. +# +# When `cors` is disabled all other `cors` relevant settings is not effective. +# +# By default `CORS` is disabled +# +# uncomment to enable CORS support +#cors=true + + +# `cors.origin` set the `Access-Control-Allow-Origin` response header. +# +# Default CORS origin header value is `*` +#cors.origin= + +# `cors.headers` +# +# THIS CONFIGURATION IS DEPRECATED SINCE 1.8.29 +#cors.headers= + +# `cors.headers.expose` set the `Access-Control-Expose-Headers` response header. +# +# Default value: `Act-Session-Expires, Authorization, X-XSRF-Token, X-CSRF-Token, Location, Link, Content-Disposition, Content-Length`. +#cors.headers.expose=Act-Session-Expires, Authorization, X-XSRF-Token, X-CSRF-Token, Location, Link, Content-Disposition, Content-Length + +# `cors.headers.allowed` set the `Access-Control-Allow-Headers` response header. +# +# Default value: `X-HTTP-Method-Override, X-Requested-With, Authorization, X-XSRF-Token, X-CSRF-Token`. +#cors.headers.allowed=X-HTTP-Method-Override, X-Requested-With, Authorization, X-XSRF-Token, X-CSRF-Token + +# `cors.max_age` set the `Access-Control-Max-Age` response header +# +# Default value is `30*60` i.e. 30 minutes +#cors.max_age + +# `cors.allow_credentials.enabled` set the `Access-Control-Allow-Credential` response header +# +# By default this setting is disabled +# +# Uncomment the set `Access-Control-Allow-Credential` to `true` +#cors.allow_credentials=true + +# If `content_suffix.aware` is enabled the framework adjust Request `Accept` +# header based on URL suffix. +# +# E.g. `/customer/123/json` will match the route `/customer/123` +# and set the `Accept` header of the incoming request to `application/json` +# +# By default `content_suffix.aware` is disabled. +# +# Uncomment to enable `content_suffix.aware.enabled` +#content_suffix.aware.enabled=true + +# `csp` set the `Content-Security-Policy` response header value. +# +# By default `csp` is not set. +#csp= + +# `csrf` turn on/off the CSRF protection. +# See https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) +# +# By default `csrf` protection is disabled +# +# uncomment to turn on CSRF protection. +#csrf=true + +# `csrf.param_name` specifies the http request param name +# used to convey the csrf token. +# +# Default value: `__csrf__` +#csrf.param_name + +# `csrf.header.name` specifies name of the http request header +# used to convey the csrf token sent from AJAX client. +# +# Default value: `X-Xsrf-Token` +#csrf.header_name= + +# `csrf.cookie_name` specify the name of the cookie used to +# convey the csrf token generated on the server for the first GET +# request coming from a client. +# +# Default value: `XSRF-TOKEN` +#csrf.cookie_name + +# `csrf.protector` specifies the implementation of `act.security.CSRFProtector`. +# +# Default protector implementation is `HMAC` +# +# uncomment to set csrf protector implementation +#csrf.protector=RANDOM|className + +# `db.seq_gen` specifies the implementation of `act.db.util._SequenceNumberGenerator` +# +# Default value is `null` or an implementation specified by db plugin +#db.seq_gen= + +# `dsp.token` specifies the name of "double submission protect token" +# +# Default value: `act_dsp_token` +#dsp.token= + +# `enum.resolving.exact_match` specify whether it shall resolve enum value +# in exact matching way or Keyword based variation way. +# +# Keyword based variation matching explain: +# +# Suppose we have an enum defination: `enum TestEnum {FOO_BAR} +# All the following string variations can be resolved to `TestEnum.FOO_BAR`: +# +# * FOO_BAR +# * Foo-Bar +# * Foo.Bar +# * foo-bar +# * foo_bar +# * FooBar +# * fooBar +# +# Default value is `false` meaning enum type value resolving is +# non-exact matching +# +# uncomment to make Enum type parameter resolving be exact matching +#enum.resolving.exact_match=false + +# `fmt.date` specifies the pattern for Date type value resolving +# +# The setting can be any one of +# - long +# - medium +# - short +# - custom pattern, e.g. `EEE yyyy MMM dd` +# +# Note custom pattern shall not contain any symbol for time, e.g. `H` or `m` +# Default value: `medium` +#fmt.date= + +# `fmt..date` specifies the pattern for Date type for specific locale +# +# It can specify date formats for multiple locales +# +# Default value: `medium` +# see also: `fmt.date` +#fmt.zh_cn.date=yyyy年MM月dd日 + + +# `fmt.data_time` specifies the pattern for DataTime type value resolving. +# +# The setting can be any one of +# - long +# - medium +# - short +# - custom pattern, e.g. `EEE yyyy MMM dd` +# +# Default value: `medium` +#fmt.date_time= + +# `fmt..date_time` specifies the pattern for DateTime type for specific locale +# +# It can specify date_time formats for multiple locales +# +# Default value: `medium` +# see also: `fmt.date_time` +#fmt.zh_cn.date_time=yyyy年MM月dd日 HH:mm + +# `fmt.time` specifies the pattern for Time type value resolving +# +# The setting can be any one of +# - long +# - medium +# - short +# - custom pattern, e.g. `HHmmss` +# +# Note custom pattern shall not contain any symbol for date, e.g. `y` or `M` +# Default value: `medium` +#fmt.time= + +# `fmt..time` specifies the pattern for Time type for specific locale. +# +# It can specify time formats for multiple locales +# +# Default value: `medium` +# see also: `fmt.time` +#fmt.zh_cn.time=HH:mm + +# `globalReturnValueAdvice` specifies the global `ReturnValueAdvice` implementation +# +# Default value: `null` +#globalReturnValueAdvice=ghissues.Gh835$GlobalAdvice + +# `handler.csrf_check_failure` specifies the implemetation of `MissingAuthenticationHandler` +# to be called when CSRF checking failed. +# +# Default value is the setting of `handler.missing_authentication` +#handler.csrf_check_failure= + +# `handler.missing_authentication` specifies the implemetation of `MissingAuthenticationHandler` +# to be called when authentication is failed on an non-AJAX request. +# +# Default value is `act.util.RedirectToLoginUrl` if login URL is in the route table. +# otherwise it is `act.util.ReturnUnauthorized` +#handler.missing_authentication= + +# `handler.missing_authentication` specifies the implemetation of `MissingAuthenticationHandler` +# to be called when authentication is failed on an AJAX request. +# +# Default value is the setting of `handler.missing_authentication` +#handler.missing_authentication.ajax= + +# `handler.unknown_http_method` specifies the handler implementation to be called +# when ActFramework found the HTTP method of an incoming request is not supported +# +# Default value is `UnknownHttpMethodProcessor.METHOD_NOT_ALLOWED`, i.e. +# respond `405 Method Not Allowed` response. +#handler.unknown_http_method= + +# `act.header.overwrite` turn on/off HTTP HEADER overwrite. +# +# Once this config is turned on, then it can overwrite header +# with HTTP Query parameter or HTTP post form field. The naming +# convention of the param/field is: +# +# ``` +# act_header_ +# ``` +# +# For example, if it needs to overwrite `Content-Type`, use +# `act_header_content_type` as the query parameter name. +# +# Default value: `false` +#header.overwrite=true + + +# `header.session.expiration` specifies name of the HTTP response header to be +# used to convey the JWT/session cookie expiration time. +# +# Default value is `Act-Session-Expires` +#header.session.expiration= + +# `host` specifies the hostname of the application. +# +# This setting is often used to concatentate full URL including host +# in email template. +# +# Default value: `localhost` +#host= + +# `http.external_server` specify if the app is running behind a frontend +# http server, e.g. nginx. +# +# Default value: `true` when running in `prod` mode or `false` when running in `dev` mode +#http.external_server=true|false + +# `http.params.max` specifies the maximum number of http parameters. +# +# This setting can be to prevent the hash collision DOS attack. +# +# Default value: 128 +#http.params.max= + +# `http.port` specifies the default HTTP port number +# +# Default value: 5460 +#http.port= + +# `http.port.external` specifies the default HTTP port number of +# frontend HTTP server (if exists). +# +# Default value: 80 +#http.port.external= + +# `http.port.external.secure` specifies the default HTTPS port number of +# the frontend HTTP server (if exists) +# +# Default value: 443 +#http.port.external.secure= + +# `http.secure` specifies whether the default http port is running in +# an secure HTTP channel +# +# Default value: `true` when running in `prod` mode or `false` in `dev` mode +#http.secure=true|false + +# `https.port` specify the https port - only effect +# when `ssl` is enabled. +# +# Default value: `5443` +#https.port= + +# `i18n` turn on/off i18n support in ActFramework. +# +# Default value: false +#i18n=true|false + +# `i18n.locale.param_name` specifies the param name to set client locale +# in http request +# +# Default value: `act_locale` +#i18n.locale.param_name= + +# `i18n.locale.cookie_name` specifies the name for the locale cookie +# +# Default value: `act_locale` +#i18n.locale.cookie_name= + +# `idgen.node_id.provider` specifies the implementation of +# `act.util.IdGenerator.NodeIdProvider` which is called when generating the +# CUID (Custer Unique Identifier) +# +# Default value: `act.util.IdGenerator.NodeIdProvider.IpProvider` +#idgen.node_id.provider= + +# `idgen.node_id.effective_ip_bytes.size` specifies how many bytes in the ip address +# will be used to calculate node ID. Usually in a cluster environment, the ip address will +# be different at only (last) one byte or (last) two bytes, in which case it could set this +# configuration to `1` or `2`. When the configuration is set to `4` then it means all 4 IP +# bytes will be used to calculate the node ID +# +# Default value: 4 +#idgen.node_id.effective_ip_bytes.size=1|2|3|4 + +# `idgen.start_id.provider` specifies the `act.util.IdGenerator.StartIdProvider` +# implementation which is called when generating the CUID +# +# Default value: `act.util.IdGenerator.StartIdProvider.DefaultStartIdProvider` +# which read/write the file specified by `idgen.start_id.file` setting in +# the project dir. +#idgen.start_id.provider= + +# `idgen.start_id.file` specifies the start id persistent file. +# This setting is used by `act.util.IdGenerator.StartIdProvider.DefaultStartIdProvider` +# +# Default value: `.act.id-app` +#idgen.start_id.file= + +# `idgen.seq_id.provider` specifies the `act.util.IdGenerator.SequenceProvider` +# implementation which is called when generating the CUID. +# +# Default value: `act.util.IdGenerator.SequenceProvider.AtomicLongSeq` +#idgen.seq_id.provider= + +# `idgen.encoder` specifies the `act.util.IdGenerator.LongEncoder` implementation +# which is called when generating the CUID. +# +# Default value: `act.util.IdGenerator.SafeLongEncoder` which generates URL +# safe and slighty longer string for long value encoding. +#idgen.encoder=act.util.IdGenerator.SafeLongEncoder|act.util.IdGenerator.UnsafeLongEncoder + +# `job.pool.size` specifies the maximum number of threads +# can exists in the application's job manager's thread pool +# +# Default value: 10 +#job.pool.size= + +# `jwt` enable/disable JWT support. +# This is actually a combination of the following settings: +# * session.codec=act.session.JsonWebTokenSessionCodec +# * session.header.payload.prefix="Bearer " # note the space after `Bearer` +# * session.header=Authorization +#jwt=true|false + +# `jwt.algo` specifies the algorithm used to encrypt/decrypt JWT. +# +# Default value: SHA256 +#jwt.algo=SHA256|SHA384|SHA512 + +# `jwt.issuer` specify `iss` payload of JWT +# +# Default value: the setting of `cookie.prefix` +#jwt.issuer= + +# `json_body_patch` enable/disable JSON body patch +# +# Default value: `true` +#json_body_patch.enabled=true + +# `locale` specifies the application default locale +# +# Default value: the result of calling `java.util.Locale#getDefault()` +#locale= + +# `metric` turn on/off internal metrics. +# +# Default value: true +#metric=true|false + +# `modules` declare additional app base (for multi-module maven projects) +#modules= + +# `monitor.enabled` specifies whether turn on monitor thread +# +# default value: `false` +# monitor.enabled=true + +# `namedPorts` specifies a list of port names this +# application listen to. These are additional ports other than +# the default `http.port` setting. +# +# Default value: null +#namedPorts=admin:8888;ipc:8899;... + +# `param_binding.keyword_matching` turn on/off keyword matching in HTTP param binding +# process. +# +# When this configuration is turned on the framework is able to do keyword matching +# to bind the HTTP parameter, e.g. when it declare to bind a parameter named `fooBar`, +# when request is sending with parameter named `foo_bar`, it can still finish the bind. +# +# **Note** turning on this configuration might cause slightly performance degrade. +# +# Default value: `false` +#param_binding.keyword_matching=false + +# `password.spec` specify default password spec which is used to +# validate user password. +# +# Default value: +# * dev mode: `a[3,]`, meaning require lower case letter and min length is 3 characters. +# * prod mode: `aA0[6,]`, meaning require lower case letter, uppercase letter, digit and min length is 6 characters. +# +# Developer can also specify a `Password.Validator` implementation +# class for this configuration, in which case, the framework will instantiate the user +# specified validator instead of `act.validation.PasswordSpec` as the default +# password validator. +# +#password.spec= + +# `ping.path` specify the ping path. +# If this setting is specified, then when session resolving, system +# will check if the current URL matches the setting. If matched +# then session cookie expiration time will not be changed. Otherwise +# the expiration time will refresh +# +# Default value: `null` +#ping.path= + +# `req.throttle` specifies the maximum number of requests +# that can be handled per second from the same ip address +# when `@Throttled` annotation is presented without `value` +# specified on a request handler method. +# +# Default value: 2 +#req.throttle= + +# `req.throttle.expire.scale` turn on/off request throttle +# expiry time increment. +# +# Default value: `false` +#req.throttle.expire.scale=true|false + +# `render.json.content_type.ie` specify whether the content type +# of JSON response on request initiated from an IE browser. +# +# Note early IE browser does not support the `application/json` content type. +# +# Default value: `null` +#render.json.content_type.ie= + +# `resolver.template_path` specifies the class that extends +# `TemplatePathResolver`. Application developer could use this +# configuration to add some flexibility to +# template path resolving logic, e.g. different home +# for different locale or different home for different device +# type etc +# +# Default value: `TemplatePathResolver` +#resolver.template_path + +# +# Enable/disable resource filtering (only impact dev mode) +# +# Default value: `true` +#resource.filtering=true + +# `resource.preload.size.limit` Specifies the maximum number of bytes of +# a resource that can be preload into memory. Specify the setting to +# `0` or negative value disable resource preload feature. +# +# Default value: `1024 * 10`, i.e. 10KB +#resource.preload.size.limit= + +# `resource_bundle.encoding` specifies encoding of resource bundles. +# This configuration allows override the default resource bundle +# encoding setting used by specific Java runtime: +# - Before Java 9: ISO-8859-1 +# - Java 9 and above: UTF-8 +# +# Default value: `null` meaning follow JDK default encoding setting +#resource_bundle.encoding=utf-8 + +# `scan_package` specify the app package in which all classes is subject +# to bytecode processing, e.g enhancement and injection. +# +# By default ActFramework will infer the scan package +# from the app entry class which contains the main method +# starting act. +# +#scan_package= + +# `act.secret` Specifies the secret key the application used to do general +# encrypt/decrypt/sign etc +# +# Note application must set this configuration to secure the communication +act.secret=xCGE8jBC3v1KUm38gnqLoJAQ23l25rcYXJ1ExpLqtZjshUhyZ6LwVRmkHJvXV6WK + +# `secret.rotate` turn on app secret rotation for session/flash +# token signing and encrypt. This feature makes it even harder +# to crack as secret changes regularly. +# +# Default value: false +#secret.rotate=true|false + +# `secret.rotate.period` set the secret rotate period in terms of minute. +# +# **Note** the number of minute must be a factor of 60. Any number that +# is not the factor of 60 then it will be up rounded: +# +# * 1 -> 1 +# * 2 -> 2 +# * 3 -> 4 +# * 4 -> 4 +# * 5 -> 5 +# * 6 -> 6 +# * 7 -> 10 +# * 8 -> 10 +# * 33 -> 30 +# * 50 -> 60 +# +# the rotation period less than hour will be count from the beginning of +# the current hour. +# +# If the number minutes exceeds 60, then it must be a factor of 60 * 24. Any +# number if not will be rounded: +# +# * 65 -> 60 +# * 60 * 3 -> 60 * 3 +# * 60 * 5 -> 60 * 6 +# * 60 * 7 -> 60 * 6 +# * 60 * 10 -> 60 * 12 (half day) +# +# if the number of minutes equals of exceeds 120, the rotation period will +# be counted from the beginning of the day. +# +# The maximum period is `60 * 24`, i.e. 24 hours. Any setting exceed that number +# will be cut off down to 24 hours. +# +# Default value: `30` minutes, ie. half an hour +#secret.rotate.period= + +# `server.header` specifies the server header to be output to the response +# +# Default value: `act/${act-version}` +#server.header= + +#`session.outputExpiration.enabled` turn on/off expiration output to +# response header. +# +# This setting only effective when it is using token to +# map session payload. +# +# Default value: `true` +#session.outputExpiration=true|false + +# `session.ttl` specifies the session duration in seconds. +# If user failed to interact with server for amount of time that +# exceeds the setting then the session will be destroyed +# +# Default value: `60 * 30` i.e half an hour +#session.ttl= + +# `session.persistent` specify whether the system +# should treat session cookie as persistent cookie. If this setting +# is enabled, then the user's session will not be destroyed after +# browser closed. +# +# Refer to http://en.wikipedia.org/wiki/HTTP_cookie#Persistent_cookie +# +# Default value: `false` +#session.persistent=true|false + +# `session.encrypt` specify whether the system should +# encrypt the key/value pairs in the session cookie. Enable session +# encryption will greatly improve the security but with the cost +# of additional CPU usage and a little bit longer time on request +# processing. +# +# Default value: `false` +#session.encrypt=true|false + +# `session.key.username` specifies the session key for username +# +# Default value: `username` +#session.key.username= + +# `session.mapper` specifies the implementation of `act.session.SessionMapper` +# Predefined session mappers: +# * `act.session.CookieSessionMapper` - map session data to session cookie +# * `act.session.HeaderTokenSessionMapper` - map session data to header token +# * `act.session.CookieAndHeaderSessionMapper` - map session data to both cookie and header +# +# Default value:`act.session.CookieSessionMapper` +#session.mapper= + +# `session.codec` specifies the implementation of `act.session.SessionCodec` +# Predefined session codec: +# * `act.session.DefaultSessionCodec` +# * `act.session.JsonWebTokenSessionCodec` +# +# Default value: `act.session.DefaultSessionCodec` when `jwt` is `false` +# or `act.session.JsonWebTokenSessionCodec` when `jwt` is `true` +#session.codec= + +# `session.header` - specify the session header name. +# +# Effective only when `act.session.SessionMapper` is `act.session.HeaderTokenSessionMapper` +# +# Default value: X-Act-Session when `jwt` is `false` +# or `Authorization` when `jwt` is `true` +#session.header= + +# `session.header.payload.prefix` set the session payload prefix, e.g. `Bearer ` +# +# Default value: `null` when `jwt` is `false` +# or `Bearer ` when `jwt` is `true` +#session.header.payload.prefix= + +# `session.secure` specifies whether the session cookie should +# be set as secure. Enable secure session will cause session cookie only +# effective in https connection. Literally this will enforce the web site to run +# default by https. +# +# Default value: `true` +# +# **Note** when {@link Act Act server} is running in {@link Act.Mode#DEV mode} +# session http only will be disabled without regarding to the `session.secure.enabled` +# setting +#session.secure=true|false + +# `source.version` specifies the java version +# of the src code. This configuration is used only +# in dev mode. +# +# Default value: 1.7 +#source.version= + +# `ssl` turn on/off SSL support. +# +# Default value: `false` +# +# **Note** this is experimental feature +#ssl=true|false + +# `system.self-healing` turn on/off system self healing. +# Refer GH #1234 +# +# Default value: `false` +# +#system.self-healing=true|false + +# `target.version` specifies the java version of the compile +# target code. This configuration is used only in dev mode. +# +# Default value: 1.7 +#target.version= + +# `template.home` specifies where the view templates resides. +# If not specified then will use the {@link View#name() view name +# in lower case} as the template home if that view is used. +# +# Default value: the result of `View.name()` +#template.home= + +# `threadlocal_buf.limit` set the maximum buffer size of thread local instance +# of `org.osgl.util.S.Buffer` and `org.osgl.util.ByteArrayBuffer`. If the buffer +# size exceeds the limit, the thread local instance will be dropped and new +# instance will be created as the thread local instance. +# +# Default value: 1024 * 8 (i.e. 8k) +#threadlocal_buf.limit= + +# `trace.handler` turn on/off handle invocation calls. +# +# When this configuration is turned on, every call to the +# action handler/job handler/mail sender method will be logged. +# +# Default value: `false` +#trace.handler=true|false + +# `trace.request` turn on/off incoming request log +# +# When this configuration is turned on, every incoming request +# will be logged +# +# default value: `false` +#trace.request=true|false + +# `upload.in_memory.threshold` +# +# If file upload content length is less than this configuration then +# the file will not get written into disk, instead it will get cached +# into a in memory byte array +# +# Default value: `1024 * 10` +#upload.in_memory.threshold + +# `url.context` specifies the app global URL context. +# +# If this configuration is specified then all route configured will +# be attached to the configured context path. +# +# Default value: `null` +#url.context= + +# `url.login` specifies the login URL which is used +# by {@link act.util.RedirectToLoginUrl} +# +# Default value: `/login` +#url.login= + +# `url.login.ajax` specifies the login URL which is used +# by {@link act.util.RedirectToLoginUrl} when request is AJAX +# +# Default value: the value of `url.login` setting +#url.login.ajax + +# `view.default` specifies the default view solution. If there +# are multiple views registered and default view are available, then +# it will be used at priority to load the templates +# +# Default value: `rythm` +#view.default= + +# `ws.key.ticket` +# +# Specifies the parameter variable name to get websocket ticket +# +# Default value: `ws_ticket` +#ws.key.ticket=ws_ticket + +# `ws.purge-closed-conn.period` +# +# Specifies the waiting period in seconds to purge closed websocket connections +# +# Default value: `10` in PROD mode, `1` in DEV mode +#ws.purge-closed-conn.period=10 + + +# `xio.worker_threads.max` specifies the maximum worker thread for XIO. +# +# Default value: `0`, meaning let system to decide the number of worker threads +#xio.worker_threads.max=0 + +# `xio.statistics.enabled` turn on/off statistics in XIO layer +# +# Default value: `false` +#xio.statistics.enabled=false diff --git a/testapps/GH1332/src/main/resources/conf/cron.properties b/testapps/GH1332/src/main/resources/conf/cron.properties new file mode 100644 index 000000000..eb2031340 --- /dev/null +++ b/testapps/GH1332/src/main/resources/conf/cron.properties @@ -0,0 +1,24 @@ +# A few sample cron settings that could be +# referred by app +# +# act-1.9.2 + +# NOTE - this file is deprecated +# It recommend to use the constant +# defined in act.job.Cron annotation +# e.g. Cron.CRON_2AM or Cron.CRON_12PM etc + +# triggered at 12am every day +#cron.midnight=0 0 0 * * * + +# triggered at 12am every weekdays (Mon to Fri) +#cron.midnight.weekdays=0 0 0 * * 1-5 + +# triggered at 12am every last day of a month +#cron.midnight.last-day-of-mon=0 0 0 * * L + +# triggered at 12pm every day +#cron.noon=0 0 12 * * * + +# triggered at 12pm every weekdays (Mon to Fri) +#cron.noon=0 0 12 * * 1-5 diff --git a/testapps/GH1332/src/main/resources/conf/prod/app.properties b/testapps/GH1332/src/main/resources/conf/prod/app.properties new file mode 100644 index 000000000..d836ad62f --- /dev/null +++ b/testapps/GH1332/src/main/resources/conf/prod/app.properties @@ -0,0 +1,3 @@ +# Application configuration for prod profile +# act-1.9.2 +act.secret=znC2CEqPCYfU5OF5DRB5n7GIN5syhFZC8lg7AyEUue7PxKxqEjgF4vuGGjYAvj9s \ No newline at end of file diff --git a/testapps/GH1332/src/main/resources/conf/test.properties b/testapps/GH1332/src/main/resources/conf/test.properties new file mode 100644 index 000000000..8636c1273 --- /dev/null +++ b/testapps/GH1332/src/main/resources/conf/test.properties @@ -0,0 +1,52 @@ +# Application configuration for test support +# act-1.9.2 + +# Specify application model package here. +# once this is set it can refer to model class name +# directly in fixture.yml files, no need for +# full qualified class name +# +# default value: null +#test.model-packages=demo.models + +# Specify application issue template URL +# once this is set, it will enable link test scenario to +# application issue in issue tracking system automatically +# +# default value null +#test.issueUrlTemplate=https://github.com/act-gallery/bookmark/issues/%s +#test.issueUrlTemplate=https://www.atlassian.com/software/jira/%s + +# Specify common URL context used in scenario files +# +# default value: null +#test.urlContext=/api/v1 + +# `test.delay` specifies the seconds it shall wait before starting automate test. +# the value must be in integer, the unit of the value is second. +# +# Default value: 0 +#test.delay=5 +#test.delay=0 + +# `test.timeout` specifies automate test http agent timeout in seconds. +# +# Default value: 10 in automate test mode, 60 * 60 in dev mode (for debugging purpose) +#test.timeout=60 + +# Specify where the framework should load data fixtures +# the folder will be used to patch fixture file name +# specified in scenario.yml file when loading it. +# +# default value: /test/fixtures/ +#test.fixture-folder=/test/fixtures/ + +# +# The following are test inbox SMTP settings +# Once they are set, then framework can login +# to the inbox and verify email sending +#test.inbox.account=your-testing-email +#test.inbox.password=your-secret-password +test.inbox.protocol=imaps # current imaps is the only supported protocol +#test.inbox.host=your-inbox-host.com +#test.inbox.port=your-inbox-port diff --git a/testapps/GH1332/src/main/resources/conf/uat/app.properties b/testapps/GH1332/src/main/resources/conf/uat/app.properties new file mode 100644 index 000000000..41e5515f2 --- /dev/null +++ b/testapps/GH1332/src/main/resources/conf/uat/app.properties @@ -0,0 +1,3 @@ +# Application configuration for uat profile +# act-1.9.2 +act.secret=klpXODEAKtJFn3WPE8GYGQIyAKebPTiaFj6c18wXczTmipF4pvBQDFPe9CfIodOt \ No newline at end of file diff --git a/testapps/GH1332/src/main/resources/logback.xml b/testapps/GH1332/src/main/resources/logback.xml new file mode 100644 index 000000000..953d7d90d --- /dev/null +++ b/testapps/GH1332/src/main/resources/logback.xml @@ -0,0 +1,100 @@ + + + + + + + + + true + + %date %highlight(%-5level) %cyan(%logger{5}@[%-4.30thread]) - %msg%n + + + + + + + true + + %msg%n + + + + + + act.log + + %d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + /act.%i.log.zip + 1 + 10 + + + + 2MB + + + + + + test.log + + %msg%n + + + + + act-db.log + + %d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + /act-db.%i.log.zip + 1 + 10 + + + + 2MB + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testapps/GH1332/test b/testapps/GH1332/test new file mode 100755 index 000000000..e32ec2e85 --- /dev/null +++ b/testapps/GH1332/test @@ -0,0 +1,3 @@ +#!/bin/sh +echo building ... +mvn -q compile act:test \ No newline at end of file diff --git a/testapps/GH1332/test.bat b/testapps/GH1332/test.bat new file mode 100644 index 000000000..a324f34a0 --- /dev/null +++ b/testapps/GH1332/test.bat @@ -0,0 +1,2 @@ +echo building ... +mvn -q compile act:test \ No newline at end of file From 4631dffb896aed75d3fc709f8114cfa4fd874123 Mon Sep 17 00:00:00 2001 From: Gelin Luo Date: Mon, 5 Dec 2022 11:08:59 +1100 Subject: [PATCH 2/2] Test sceanrio yaml file shall be able to refer values defined in app config properties file #1429 --- src/main/java/act/test/TestSession.java | 14 +++++++++++++- testapps/GHIssues/.gitignore | 3 ++- testapps/GHIssues/pom.xml | 2 +- .../GHIssues/src/main/java/ghissues/Gh1429.java | 17 +++++++++++++++++ .../src/main/resources/conf/1429.properties | 1 + .../src/test/resources/scenarios/1429.yml | 8 ++++++++ 6 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 testapps/GHIssues/src/main/java/ghissues/Gh1429.java create mode 100644 testapps/GHIssues/src/main/resources/conf/1429.properties create mode 100644 testapps/GHIssues/src/test/resources/scenarios/1429.yml diff --git a/src/main/java/act/test/TestSession.java b/src/main/java/act/test/TestSession.java index 918c27b62..f62ea52eb 100644 --- a/src/main/java/act/test/TestSession.java +++ b/src/main/java/act/test/TestSession.java @@ -432,8 +432,20 @@ private Object getVal(String key) { return evalFunc(key); } catch (Exception e) { try { - return getLastVal(key); + o = getLastVal(key); + if (null == o) { + o = App.instance().config().get(key); + if (null != o) { + return o; + } + throw E.unexpected("Unable to get value by key: %s", key); + } + return o; } catch (Exception e1) { + o = App.instance().config().get(key); + if (null != o) { + return o; + } throw E.unexpected("Unable to get value by key: %s", key); } } diff --git a/testapps/GHIssues/.gitignore b/testapps/GHIssues/.gitignore index 0577ee63e..0f3be5cec 100644 --- a/testapps/GHIssues/.gitignore +++ b/testapps/GHIssues/.gitignore @@ -17,4 +17,5 @@ test.trace.db act.pid .workspace *.geany -upload* \ No newline at end of file +*.db +upload* diff --git a/testapps/GHIssues/pom.xml b/testapps/GHIssues/pom.xml index d9ba8cb88..64bb9b455 100644 --- a/testapps/GHIssues/pom.xml +++ b/testapps/GHIssues/pom.xml @@ -25,7 +25,7 @@ org.actframework act - 1.9.2-SNAPSHOT + 1.9.3-SNAPSHOT org.actframework diff --git a/testapps/GHIssues/src/main/java/ghissues/Gh1429.java b/testapps/GHIssues/src/main/java/ghissues/Gh1429.java new file mode 100644 index 000000000..2553b8cbf --- /dev/null +++ b/testapps/GHIssues/src/main/java/ghissues/Gh1429.java @@ -0,0 +1,17 @@ +package ghissues; + +import act.controller.annotation.UrlContext; +import act.util.JsonView; +import act.util.PropertySpec; +import org.osgl.mvc.annotation.GetAction; +import org.osgl.util.N; +import org.osgl.util.S; + +@UrlContext("1429") +public class Gh1429 extends BaseController { + + @GetAction + public String echo(String message) { + return message; + } +} diff --git a/testapps/GHIssues/src/main/resources/conf/1429.properties b/testapps/GHIssues/src/main/resources/conf/1429.properties new file mode 100644 index 000000000..eb90551bf --- /dev/null +++ b/testapps/GHIssues/src/main/resources/conf/1429.properties @@ -0,0 +1 @@ +gh1429.message=hello \ No newline at end of file diff --git a/testapps/GHIssues/src/test/resources/scenarios/1429.yml b/testapps/GHIssues/src/test/resources/scenarios/1429.yml new file mode 100644 index 000000000..3f95fab37 --- /dev/null +++ b/testapps/GHIssues/src/test/resources/scenarios/1429.yml @@ -0,0 +1,8 @@ +Scenario(1429): + description: "Test sceanrio yaml file shall be able to refer values defined in app config properties file" + interactions: + - description: test + request: + get: 1429?message=${gh1429.message} + response: + result: ${gh1429.message} \ No newline at end of file