diff --git a/.github/workflows/downstream-native-image.yaml b/.github/workflows/downstream-native-image.yaml
new file mode 100644
index 000000000..4a4f947ee
--- /dev/null
+++ b/.github/workflows/downstream-native-image.yaml
@@ -0,0 +1,41 @@
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+
+# Keeping this file separate as the dependencies check would use more
+# repositories than needed this downstream check for GraalVM native image
+# compilation.
+name: downstream
+jobs:
+ # GraalVM job ensures the compatibility of GraaVM version
+ graalvm:
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ graalvm: [22.1.0, 22.0.0.2, 21.3.2]
+ java: [11, 17]
+ repo:
+ # GAPIC library that doesn't use a real GCP project in integration tests
+ - orgpolicy
+ steps:
+ - uses: actions/checkout@v2
+ - uses: stCarolas/setup-maven@v4
+ with:
+ maven-version: 3.8.1
+ - uses: ayltai/setup-graalvm@v1
+ with:
+ java-version: ${{matrix.java}}
+ # When a new version of native-maven-plugin fails to run in a downstream
+ # library, it's likely to be an incompatibility with the GraalVM version.
+ # In that case, you need to upgrade the Docker container used in the
+ # tests in the downstream repositories (not just this value below).
+ # Example: https://github.com/googleapis/testing-infra-docker/pull/195
+ graalvm-version: ${{matrix.graalvm}}
+ native-image: true
+ - run: java -version
+ - run: sudo apt-get update -y
+ - run: sudo apt-get install libxml2-utils
+ - run: .kokoro/downstream-client-library-check.sh ${{matrix.repo}} graalvm
\ No newline at end of file
diff --git a/.github/workflows/downstream.yaml b/.github/workflows/downstream.yaml
index b521e571d..45e45fa25 100644
--- a/.github/workflows/downstream.yaml
+++ b/.github/workflows/downstream.yaml
@@ -11,7 +11,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- java: [8]
+ java: [11]
repo:
# This list needs to be updated manually until an automated solution is in place.
- accessapproval
@@ -141,4 +141,4 @@ jobs:
- run: java -version
- run: sudo apt-get update -y
- run: sudo apt-get install libxml2-utils
- - run: .kokoro/downstream-client-library-check.sh ${{matrix.repo}}
+ - run: .kokoro/downstream-client-library-check.sh ${{matrix.repo}} test
diff --git a/.kokoro/downstream-client-library-check.sh b/.kokoro/downstream-client-library-check.sh
index 51c23d1c0..7916e1c08 100755
--- a/.kokoro/downstream-client-library-check.sh
+++ b/.kokoro/downstream-client-library-check.sh
@@ -18,6 +18,9 @@ set -eo pipefail
set -x
CLIENT_LIBRARY=$1
+
+# Example JOB_TYPE: "test" or "graalvm"
+export JOB_TYPE=$2
## Get the directory of the build script
scriptDir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
## cd to the parent directory, i.e. the root of the git repo
@@ -86,7 +89,9 @@ if [[ $CLIENT_LIBRARY == "bigtable" ]]; then
popd
fi
-mvn verify install -B -V -ntp -fae \
--Dmaven.javadoc.skip=true \
--Dgcloud.download.skip=true \
--Denforcer.skip=true
+echo "Modification on the shared dependencies BOM:"
+git diff
+echo
+
+# This reads the JOB_TYPE environmental variable ("test" or "graalvm")
+.kokoro/build.sh
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e5728e152..d0ac384f2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,24 @@
# Changelog
+## [2.18.0](https://github.com/googleapis/gax-java/compare/v2.17.0...v2.18.0) (2022-05-18)
+
+
+### Features
+
+* [REGAPIC] Add support for additional bindings ([#1680](https://github.com/googleapis/gax-java/issues/1680)) ([59b3699](https://github.com/googleapis/gax-java/commit/59b3699b6acbc98c55dc043bf8665b457a0615a9))
+* upgrade graal-sdk to 22.1.0 ([#1683](https://github.com/googleapis/gax-java/issues/1683)) ([46f899d](https://github.com/googleapis/gax-java/commit/46f899de06e60a792f5a6c1dc617673f0f180c00))
+
+
+### Bug Fixes
+
+* **java:** remove conflicting reflection configuration to address UnsupportedFeatureException with GraalVM 22.1.0 ([#1682](https://github.com/googleapis/gax-java/issues/1682)) ([97c6c8b](https://github.com/googleapis/gax-java/commit/97c6c8bfa0d5397e30d3699e92f823e09ee283e6))
+* remove svm dependency ([#1679](https://github.com/googleapis/gax-java/issues/1679)) ([c1b88e3](https://github.com/googleapis/gax-java/commit/c1b88e3788ab866bcc1ba3db94c2998198a0b35e))
+
+
+### Dependencies
+
+* update dependency com.google.api:api-common to 2.2.0 ([#1685](https://github.com/googleapis/gax-java/issues/1685)) ([a5a316b](https://github.com/googleapis/gax-java/commit/a5a316bde322733eb5a80093206eb12b36945580))
+
## [2.17.0](https://github.com/googleapis/gax-java/compare/v2.16.0...v2.17.0) (2022-05-10)
diff --git a/build.gradle b/build.gradle
index 8d2e06d7e..05cabe4a1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -13,7 +13,7 @@ plugins {
}
// TODO: Populate this from dependencies.properties version property (for proper Gradle-Bazel sync)
-project.version = "2.17.0" // {x-version-update:gax:current}
+project.version = "2.18.0" // {x-version-update:gax:current}
allprojects {
group = 'com.google.api'
diff --git a/dependencies.properties b/dependencies.properties
index 5ce365af1..fbc282273 100644
--- a/dependencies.properties
+++ b/dependencies.properties
@@ -8,16 +8,16 @@
# Versions of oneself
# {x-version-update-start:gax:current}
-version.gax=2.17.0
+version.gax=2.18.0
# {x-version-update-end}
# {x-version-update-start:gax:current}
-version.gax_grpc=2.17.0
+version.gax_grpc=2.18.0
# {x-version-update-end}
# {x-version-update-start:gax:current}
-version.gax_bom=2.17.0
+version.gax_bom=2.18.0
# {x-version-update-end}
# {x-version-update-start:gax-httpjson:current}
-version.gax_httpjson=0.102.0
+version.gax_httpjson=0.103.0
# {x-version-update-end}
# Versions for dependencies which actual artifacts differ between Bazel and Gradle.
@@ -62,16 +62,15 @@ maven.com_google_errorprone_error_prone_annotations=com.google.errorprone:error_
maven.com_google_j2objc_j2objc_annotations=com.google.j2objc:j2objc-annotations:1.3
maven.com_google_auto_value_auto_value=com.google.auto.value:auto-value:1.9
maven.com_google_auto_value_auto_value_annotations=com.google.auto.value:auto-value-annotations:1.9
-maven.com_google_api_api_common=com.google.api:api-common:2.1.5
+maven.com_google_api_api_common=com.google.api:api-common:2.2.0
maven.org_threeten_threetenbp=org.threeten:threetenbp:1.5.0
-maven.com_google_api_grpc_grpc_google_iam_v1=com.google.api.grpc:grpc-google-iam-v1:1.0.9
-maven.com_google_api_grpc_proto_google_iam_v1=com.google.api.grpc:proto-google-iam-v1:1.0.9
+maven.com_google_api_grpc_grpc_google_iam_v1=com.google.api.grpc:grpc-google-iam-v1:1.3.4
+maven.com_google_api_grpc_proto_google_iam_v1=com.google.api.grpc:proto-google-iam-v1:1.3.4
maven.com_google_http_client_google_http_client=com.google.http-client:google-http-client:1.41.5
maven.com_google_http_client_google_http_client_gson=com.google.http-client:google-http-client-gson:1.41.5
maven.org_codehaus_mojo_animal_sniffer_annotations=org.codehaus.mojo:animal-sniffer-annotations:1.18
maven.javax_annotation_javax_annotation_api=javax.annotation:javax.annotation-api:1.3.2
-maven.org_graalvm_nativeimage_svm=org.graalvm.nativeimage:svm:22.0.0.2
-maven.org_graalvm_sdk=org.graalvm.sdk:graal-sdk:21.3.2
+maven.org_graalvm_sdk=org.graalvm.sdk:graal-sdk:22.1.0
# Testing maven artifacts
maven.junit_junit=junit:junit:4.13.2
diff --git a/gax-bom/build.gradle b/gax-bom/build.gradle
index c99f109fb..07d5b5e8a 100644
--- a/gax-bom/build.gradle
+++ b/gax-bom/build.gradle
@@ -5,7 +5,7 @@ plugins {
archivesBaseName = 'gax-bom'
-project.version = "2.17.0" // {x-version-update:gax-bom:current}
+project.version = "2.18.0" // {x-version-update:gax-bom:current}
def mavenJavaDir = "$buildDir/publications/mavenJava"
def mavenJavaBomOutputFile = file(mavenJavaDir + '/pom-default.xml')
diff --git a/gax-bom/pom.xml b/gax-bom/pom.xml
index f5b7eb41e..f4fda7366 100644
--- a/gax-bom/pom.xml
+++ b/gax-bom/pom.xml
@@ -3,7 +3,7 @@
4.0.0
com.google.api
gax-bom
- 2.17.0
+ 2.18.0
pom
GAX (Google Api eXtensions) for Java
Google Api eXtensions for Java
@@ -33,34 +33,34 @@
com.google.api
gax
- 2.17.0
+ 2.18.0
com.google.api
gax
- 2.17.0
+ 2.18.0
testlib
com.google.api
gax-grpc
- 2.17.0
+ 2.18.0
com.google.api
gax-grpc
- 2.17.0
+ 2.18.0
testlib
com.google.api
gax-httpjson
- 0.102.0
+ 0.103.0
com.google.api
gax-httpjson
- 0.102.0
+ 0.103.0
testlib
diff --git a/gax-grpc/BUILD.bazel b/gax-grpc/BUILD.bazel
index 5ae856c4f..f1dfe02fc 100644
--- a/gax-grpc/BUILD.bazel
+++ b/gax-grpc/BUILD.bazel
@@ -31,7 +31,6 @@ _COMPILE_DEPS = [
"@io_netty_netty_tcnative_boringssl_static//jar",
"@javax_annotation_javax_annotation_api//jar",
"//gax:gax",
- "@org_graalvm_nativeimage_svm//jar",
"@org_graalvm_sdk//jar"
]
diff --git a/gax-grpc/build.gradle b/gax-grpc/build.gradle
index b31066aff..b15d901b2 100644
--- a/gax-grpc/build.gradle
+++ b/gax-grpc/build.gradle
@@ -1,7 +1,7 @@
archivesBaseName = 'gax-grpc'
// TODO: Populate this from dependencies.properties version property (for proper Gradle-Bazel sync)
-project.version = "2.17.0" // {x-version-update:gax-grpc:current}
+project.version = "2.18.0" // {x-version-update:gax-grpc:current}
dependencies {
api(project(':gax'),
@@ -23,8 +23,7 @@ dependencies {
runtimeOnly libraries['maven.io_grpc_grpc_googleapis']
compileOnly(libraries['maven.com_google_auto_value_auto_value'],
- libraries['maven.org_graalvm_sdk'],
- libraries['maven.org_graalvm_nativeimage_svm'])
+ libraries['maven.org_graalvm_sdk'])
testImplementation( project(':gax').sourceSets.test.output,
libraries['maven.junit_junit'],
diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/GrpcNettyFeature.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/GrpcNettyFeature.java
index 62ddd609b..c2cf0a28d 100644
--- a/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/GrpcNettyFeature.java
+++ b/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/GrpcNettyFeature.java
@@ -124,7 +124,5 @@ private static void loadMiscClasses(BeforeAnalysisAccess access) {
registerClassForReflection(access, "com.google.api.FieldBehavior");
registerForUnsafeFieldAccess(access, "javax.net.ssl.SSLContext", "contextSpi");
- registerClassForReflection(access, "java.lang.management.ManagementFactory");
- registerClassForReflection(access, "java.lang.management.RuntimeMXBean");
}
}
diff --git a/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/substitutions/NettyInternalLoggerFactorySubstitutions.java b/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/substitutions/NettyInternalLoggerFactorySubstitutions.java
deleted file mode 100644
index b81a0c171..000000000
--- a/gax-grpc/src/main/java/com/google/api/gax/grpc/nativeimage/substitutions/NettyInternalLoggerFactorySubstitutions.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2022 Google LLC
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google LLC nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.google.api.gax.grpc.nativeimage.substitutions;
-
-import com.oracle.svm.core.annotate.Substitute;
-import com.oracle.svm.core.annotate.TargetClass;
-import io.grpc.netty.shaded.io.netty.util.internal.logging.InternalLoggerFactory;
-import io.grpc.netty.shaded.io.netty.util.internal.logging.JdkLoggerFactory;
-import java.util.function.BooleanSupplier;
-
-/**
- * Substitutions for {@link InternalLoggerFactory} which are needed to avoid dynamic loading of
- * logging library.
- */
-@TargetClass(
- className = "io.grpc.netty.shaded.io.netty.util.internal.logging.InternalLoggerFactory",
- onlyWith = NettyInternalLoggerFactorySubstitutions.OnlyIfInClassPath.class)
-final class NettyInternalLoggerFactorySubstitutions {
-
- private NettyInternalLoggerFactorySubstitutions() {}
-
- @Substitute
- private static InternalLoggerFactory newDefaultFactory(String name) {
- return JdkLoggerFactory.INSTANCE;
- }
-
- static class OnlyIfInClassPath implements BooleanSupplier {
-
- @Override
- public boolean getAsBoolean() {
- try {
- // Note: Set initialize = false to avoid initializing the class when looking it up.
- Class.forName(
- "io.grpc.netty.shaded.io.netty.util.internal.logging.InternalLoggerFactory",
- false,
- Thread.currentThread().getContextClassLoader());
- return true;
- } catch (ClassNotFoundException e) {
- return false;
- }
- }
- }
-}
diff --git a/gax-grpc/src/main/resources/META-INF/native-image/com.google.api/gax-grpc/native-image.properties b/gax-grpc/src/main/resources/META-INF/native-image/com.google.api/gax-grpc/native-image.properties
index 33ea6695b..116da7f46 100644
--- a/gax-grpc/src/main/resources/META-INF/native-image/com.google.api/gax-grpc/native-image.properties
+++ b/gax-grpc/src/main/resources/META-INF/native-image/com.google.api/gax-grpc/native-image.properties
@@ -3,6 +3,8 @@ Args = --initialize-at-run-time=io.grpc.netty.shaded.io.netty.handler.ssl.OpenSs
io.grpc.netty.shaded.io.netty.internal.tcnative.CertificateVerifier,\
io.grpc.netty.shaded.io.netty.internal.tcnative.SSLPrivateKeyMethod,\
io.grpc.netty.shaded.io.netty.internal.tcnative.AsyncSSLPrivateKeyMethod,\
+ io.grpc.netty.shaded.io.netty.util.internal.logging.Slf4JLoggerFactory,\
+ io.grpc.netty.shaded.io.netty.util.internal.logging.Log4JLogger,\
io.grpc.netty.shaded.io.grpc.netty,\
io.grpc.netty.shaded.io.netty.channel.epoll,\
io.grpc.netty.shaded.io.netty.channel.unix,\
diff --git a/gax-httpjson/build.gradle b/gax-httpjson/build.gradle
index d2e931b34..4c62ef38c 100644
--- a/gax-httpjson/build.gradle
+++ b/gax-httpjson/build.gradle
@@ -1,7 +1,7 @@
archivesBaseName = 'gax-httpjson'
// TODO: Populate this from dependencies.properties version property (for proper Gradle-Bazel sync)
-project.version = "0.102.0" // {x-version-update:gax-httpjson:current}
+project.version = "0.103.0" // {x-version-update:gax-httpjson:current}
dependencies {
api(project(':gax'),
diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestFormatter.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestFormatter.java
index 3d42b313d..a60bf08e9 100644
--- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestFormatter.java
+++ b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestFormatter.java
@@ -29,7 +29,9 @@
*/
package com.google.api.gax.httpjson;
+import com.google.api.core.BetaApi;
import com.google.api.pathtemplate.PathTemplate;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -48,4 +50,10 @@ public interface HttpRequestFormatter {
/** Path template for endpoint URL path. */
PathTemplate getPathTemplate();
+
+ /** Additional (alternative) path templates for endpoint URL path. */
+ @BetaApi
+ default List getAdditionalPathTemplates() {
+ return Collections.emptyList();
+ }
}
diff --git a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatter.java b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatter.java
index f0d31ac07..f04a16edb 100644
--- a/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatter.java
+++ b/gax-httpjson/src/main/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatter.java
@@ -29,11 +29,14 @@
*/
package com.google.api.gax.httpjson;
+import com.google.api.core.BetaApi;
import com.google.api.core.InternalApi;
import com.google.api.pathtemplate.PathTemplate;
import com.google.protobuf.Message;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
/** Creates parts of a HTTP request from a protobuf message. */
public class ProtoMessageRequestFormatter
@@ -47,28 +50,35 @@ public class ProtoMessageRequestFormatter
private final String rawPath;
private final PathTemplate pathTemplate;
private final FieldsExtractor> pathVarsExtractor;
+ private final List additionalRawPaths;
+ private final List additionalPathTemplates;
private ProtoMessageRequestFormatter(
FieldsExtractor requestBodyExtractor,
FieldsExtractor>> queryParamsExtractor,
String rawPath,
PathTemplate pathTemplate,
- FieldsExtractor> pathVarsExtractor) {
+ FieldsExtractor> pathVarsExtractor,
+ List additionalRawPaths,
+ List additionalPathTemplates) {
this.requestBodyExtractor = requestBodyExtractor;
this.queryParamsExtractor = queryParamsExtractor;
this.rawPath = rawPath;
this.pathTemplate = pathTemplate;
this.pathVarsExtractor = pathVarsExtractor;
+ this.additionalRawPaths = additionalRawPaths;
+ this.additionalPathTemplates = additionalPathTemplates;
}
public static
ProtoMessageRequestFormatter.Builder newBuilder() {
- return new Builder<>();
+ return new Builder().setAdditionalPaths();
}
public Builder toBuilder() {
return new Builder()
.setPath(rawPath, pathVarsExtractor)
+ .setAdditionalPaths(additionalRawPaths.toArray(new String[] {}))
.setQueryParamsExtractor(queryParamsExtractor)
.setRequestBodyExtractor(requestBodyExtractor);
}
@@ -91,6 +101,12 @@ public String getPath(RequestT apiMessage) {
return pathTemplate.instantiate(pathVarsExtractor.extract(apiMessage));
}
+ @BetaApi
+ @Override
+ public List getAdditionalPathTemplates() {
+ return additionalPathTemplates;
+ }
+
/* {@inheritDoc} */
@Override
public PathTemplate getPathTemplate() {
@@ -104,6 +120,7 @@ public static class Builder {
private FieldsExtractor>> queryParamsExtractor;
private String rawPath;
private FieldsExtractor> pathVarsExtractor;
+ private List rawAdditionalPaths;
public Builder setRequestBodyExtractor(
FieldsExtractor requestBodyExtractor) {
@@ -124,6 +141,12 @@ public Builder setPath(
return this;
}
+ @BetaApi
+ public Builder setAdditionalPaths(String... rawAdditionalPaths) {
+ this.rawAdditionalPaths = Arrays.asList(rawAdditionalPaths);
+ return this;
+ }
+
@InternalApi
public Builder updateRawPath(String target, String replacement) {
this.rawPath = this.rawPath.replace(target, replacement);
@@ -136,7 +159,9 @@ public ProtoMessageRequestFormatter build() {
queryParamsExtractor,
rawPath,
PathTemplate.create(rawPath),
- pathVarsExtractor);
+ pathVarsExtractor,
+ rawAdditionalPaths,
+ rawAdditionalPaths.stream().map(PathTemplate::create).collect(Collectors.toList()));
}
}
}
diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java
index 310f13e4a..ca3e8893e 100644
--- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java
+++ b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/HttpJsonDirectCallableTest.java
@@ -65,13 +65,14 @@ public class HttpJsonDirectCallableTest {
.setRequestFormatter(
ProtoMessageRequestFormatter.newBuilder()
.setPath(
- "/fake/v1/name/{name}",
+ "/fake/v1/name/{name=bob/*}",
request -> {
Map fields = new HashMap<>();
ProtoRestSerializer serializer = ProtoRestSerializer.create();
serializer.putPathParam(fields, "name", request.getName());
return fields;
})
+ .setAdditionalPaths("/fake/v1/name/{name=john/*}")
.setQueryParamsExtractor(
request -> {
Map> fields = new HashMap<>();
@@ -212,7 +213,7 @@ public void testErrorNullContentFailedResponse() throws InterruptedException {
private Field createTestMessage() {
return Field.newBuilder() // "echo" service
- .setName("imTheBestField")
+ .setName("john/imTheBestField")
.setNumber(2)
.setCardinality(Cardinality.CARDINALITY_OPTIONAL)
.setDefaultValue("blah")
diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatterTest.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatterTest.java
index 69b96065d..8a8c0ac66 100644
--- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatterTest.java
+++ b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/ProtoMessageRequestFormatterTest.java
@@ -44,7 +44,7 @@
public class ProtoMessageRequestFormatterTest {
private Field field;
- private HttpRequestFormatter formatter;
+ private ProtoMessageRequestFormatter formatter;
@Before
public void setUp() {
@@ -60,36 +60,28 @@ public void setUp() {
formatter =
ProtoMessageRequestFormatter.newBuilder()
.setPath(
- "/api/v1/names/{name}/aggregated",
- new FieldsExtractor>() {
- @Override
- public Map extract(Field request) {
- Map fields = new HashMap<>();
- ProtoRestSerializer serializer = ProtoRestSerializer.create();
- serializer.putPathParam(fields, "name", request.getName());
- serializer.putPathParam(fields, "kindValue", request.getKindValue());
- return fields;
- }
+ "/api/v1/names/{name=field_name1/**}/aggregated",
+ request -> {
+ Map fields = new HashMap<>();
+ ProtoRestSerializer serializer = ProtoRestSerializer.create();
+ serializer.putPathParam(fields, "name", request.getName());
+ serializer.putPathParam(fields, "kindValue", request.getKindValue());
+ return fields;
})
.setQueryParamsExtractor(
- new FieldsExtractor>>() {
- @Override
- public Map> extract(Field request) {
- Map> fields = new HashMap<>();
- ProtoRestSerializer serializer = ProtoRestSerializer.create();
- serializer.putQueryParam(fields, "number", request.getNumber());
- serializer.putQueryParam(fields, "typeUrl", request.getTypeUrl());
- return fields;
- }
+ request -> {
+ Map> fields = new HashMap<>();
+ ProtoRestSerializer serializer = ProtoRestSerializer.create();
+ serializer.putQueryParam(fields, "number", request.getNumber());
+ serializer.putQueryParam(fields, "typeUrl", request.getTypeUrl());
+ return fields;
})
.setRequestBodyExtractor(
- new FieldsExtractor() {
- @Override
- public String extract(Field request) {
- ProtoRestSerializer serializer = ProtoRestSerializer.create();
- return serializer.toBody("field", request);
- }
+ request -> {
+ ProtoRestSerializer serializer = ProtoRestSerializer.create();
+ return serializer.toBody("field", request);
})
+ .setAdditionalPaths("/api/v1/names/{name=field_name1/**}/hello")
.build();
}
@@ -100,6 +92,12 @@ public void getQueryParamNames() {
expected.put("number", Arrays.asList("2"));
expected.put("typeUrl", Arrays.asList(""));
Truth.assertThat(queryParamNames).isEqualTo(expected);
+
+ // Test toBuilder() case
+ queryParamNames = formatter.toBuilder().build().getQueryParamNames(field);
+ expected.put("number", Arrays.asList("2"));
+ expected.put("typeUrl", Arrays.asList(""));
+ Truth.assertThat(queryParamNames).isEqualTo(expected);
}
@Test
@@ -117,12 +115,20 @@ public void getRequestBody() {
+ " }]\n"
+ "}";
Truth.assertThat(bodyJson).isEqualTo(expectedBodyJson);
+
+ // Test toBuilder() case
+ formatter.toBuilder().build().getRequestBody(field);
+ Truth.assertThat(bodyJson).isEqualTo(expectedBodyJson);
}
@Test
public void getPath() {
String path = formatter.getPath(field);
Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/aggregated");
+
+ // Test toBuilder() case
+ path = formatter.toBuilder().build().getPath(field);
+ Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/aggregated");
}
@Test
@@ -130,5 +136,40 @@ public void getPathTemplate() {
String path =
formatter.getPathTemplate().instantiate(Collections.singletonMap("name", "field_name1"));
Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/aggregated");
+
+ // Test toBuilder() case
+ path =
+ formatter
+ .toBuilder()
+ .build()
+ .getPathTemplate()
+ .instantiate(Collections.singletonMap("name", "field_name1"));
+ Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/aggregated");
+ }
+
+ @Test
+ public void getPathTemplates() {
+ String path =
+ formatter
+ .getAdditionalPathTemplates()
+ .get(0)
+ .instantiate(Collections.singletonMap("name", "field_name1"));
+ Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/hello");
+
+ // Test toBuilder() case
+ path =
+ formatter
+ .toBuilder()
+ .build()
+ .getAdditionalPathTemplates()
+ .get(0)
+ .instantiate(Collections.singletonMap("name", "field_name1"));
+ Truth.assertThat(path).isEqualTo("api/v1/names/field_name1/hello");
+ }
+
+ @Test
+ public void updateRawPath() {
+ String path = formatter.toBuilder().updateRawPath("/v1/", "/v1beta1/").build().getPath(field);
+ Truth.assertThat(path).isEqualTo("api/v1beta1/names/field_name1/aggregated");
}
}
diff --git a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/testing/MockHttpService.java b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/testing/MockHttpService.java
index 3a4d81ceb..b2ebee14d 100644
--- a/gax-httpjson/src/test/java/com/google/api/gax/httpjson/testing/MockHttpService.java
+++ b/gax-httpjson/src/test/java/com/google/api/gax/httpjson/testing/MockHttpService.java
@@ -208,8 +208,11 @@ public MockLowLevelHttpResponse getHttpResponse(String httpMethod, String fullTa
}
PathTemplate pathTemplate = methodDescriptor.getRequestFormatter().getPathTemplate();
- // Server figures out which RPC method is called based on the endpoint path pattern.
- if (!pathTemplate.matches(relativePath)) {
+ List additionalPathTemplates =
+ methodDescriptor.getRequestFormatter().getAdditionalPathTemplates();
+ // Server figures out which RPC method is called based on the endpoint path pattern(s).
+ if (!pathTemplate.matches(relativePath)
+ && additionalPathTemplates.stream().noneMatch(pt -> pt.matches(relativePath))) {
continue;
}
diff --git a/gax/BUILD.bazel b/gax/BUILD.bazel
index ede88dee4..0152f2503 100644
--- a/gax/BUILD.bazel
+++ b/gax/BUILD.bazel
@@ -26,7 +26,6 @@ _COMPILE_DEPS = [
"@com_google_code_gson_gson//jar",
"@com_google_guava_failureaccess//jar",
"@javax_annotation_javax_annotation_api//jar",
- "@org_graalvm_nativeimage_svm//jar",
"@org_graalvm_sdk//jar"
]
diff --git a/gax/build.gradle b/gax/build.gradle
index c8fb03548..ce55a2829 100644
--- a/gax/build.gradle
+++ b/gax/build.gradle
@@ -1,7 +1,7 @@
archivesBaseName = "gax"
// TODO: Populate this from dependencies.properties version property (for proper Gradle-Bazel sync)
-project.version = "2.17.0" // {x-version-update:gax:current}
+project.version = "2.18.0" // {x-version-update:gax:current}
dependencies {
api(libraries['maven.com_google_api_api_common'],
@@ -15,13 +15,13 @@ dependencies {
libraries['maven.io_opencensus_opencensus_api'])
compileOnly(libraries['maven.com_google_auto_value_auto_value'],
- libraries['maven.org_graalvm_sdk'],
- libraries['maven.org_graalvm_nativeimage_svm'])
+ libraries['maven.org_graalvm_sdk'])
testImplementation(libraries['maven.junit_junit'],
libraries['maven.org_mockito_mockito_core'],
libraries['maven.com_google_truth_truth'],
- libraries['maven.com_google_auto_value_auto_value'])
+ libraries['maven.com_google_auto_value_auto_value'],
+ libraries['maven.org_graalvm_sdk'])
annotationProcessor libraries['maven.com_google_auto_value_auto_value']
testAnnotationProcessor libraries['maven.com_google_auto_value_auto_value']
diff --git a/gax/src/main/java/com/google/api/gax/core/GaxProperties.java b/gax/src/main/java/com/google/api/gax/core/GaxProperties.java
index 5d3bf40e8..483cbe9c8 100644
--- a/gax/src/main/java/com/google/api/gax/core/GaxProperties.java
+++ b/gax/src/main/java/com/google/api/gax/core/GaxProperties.java
@@ -29,6 +29,9 @@
*/
package com.google.api.gax.core;
+import static org.graalvm.nativeimage.ImageInfo.PROPERTY_IMAGE_CODE_KEY;
+import static org.graalvm.nativeimage.ImageInfo.PROPERTY_IMAGE_CODE_VALUE_RUNTIME;
+
import com.google.api.core.InternalApi;
import java.io.IOException;
import java.io.InputStream;
@@ -81,6 +84,12 @@ public static String getLibraryVersion(Class> libraryClass, String propertyNam
/** Returns the version of the running JVM */
public static String getJavaVersion() {
+ // When running the application as a native image, append `-graalvm` to the
+ // version.
+ String imageCode = System.getProperty(PROPERTY_IMAGE_CODE_KEY);
+ if (imageCode != null && imageCode.equals(PROPERTY_IMAGE_CODE_VALUE_RUNTIME)) {
+ return System.getProperty("java.version") + "-graalvm";
+ }
return JAVA_VERSION;
}
diff --git a/gax/src/main/java/com/google/api/gax/nativeimage/GoogleJsonClientFeature.java b/gax/src/main/java/com/google/api/gax/nativeimage/GoogleJsonClientFeature.java
index 222f58264..baa4bac92 100644
--- a/gax/src/main/java/com/google/api/gax/nativeimage/GoogleJsonClientFeature.java
+++ b/gax/src/main/java/com/google/api/gax/nativeimage/GoogleJsonClientFeature.java
@@ -32,10 +32,7 @@
import static com.google.api.gax.nativeimage.NativeImageUtils.registerClassForReflection;
-import com.oracle.svm.core.configure.ResourcesRegistry;
-import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.hosted.Feature;
-import org.graalvm.nativeimage.impl.ConfigurationCondition;
/** Configures Native Image settings for the Google JSON Client. */
final class GoogleJsonClientFeature implements Feature {
@@ -69,17 +66,6 @@ private void loadApiClient(BeforeAnalysisAccess access) {
access.registerSubtypeReachabilityHandler(
(duringAccess, subtype) -> registerClassForReflection(access, subtype.getName()),
access.findClassByName(GOOGLE_API_CLIENT_REQUEST_CLASS));
-
- // Resources
- ResourcesRegistry resourcesRegistry = ImageSingletons.lookup(ResourcesRegistry.class);
- resourcesRegistry.addResources(
- ConfigurationCondition.alwaysTrue(),
- "\\Qcom/google/api/client/googleapis/google-api-client.properties\\E");
- resourcesRegistry.addResources(
- ConfigurationCondition.alwaysTrue(), "\\Qcom/google/api/client/googleapis/google.p12\\E");
- resourcesRegistry.addResources(
- ConfigurationCondition.alwaysTrue(),
- "\\Qcom/google/api/client/http/google-http-client.properties\\E");
}
}
diff --git a/gax/src/main/java/com/google/api/gax/nativeimage/substitutions/ApiClientVersionSubstitutions.java b/gax/src/main/java/com/google/api/gax/nativeimage/substitutions/ApiClientVersionSubstitutions.java
deleted file mode 100644
index c054bf03d..000000000
--- a/gax/src/main/java/com/google/api/gax/nativeimage/substitutions/ApiClientVersionSubstitutions.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2022 Google LLC
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google LLC nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.google.api.gax.nativeimage.substitutions;
-
-import com.oracle.svm.core.annotate.Alias;
-import com.oracle.svm.core.annotate.Substitute;
-import com.oracle.svm.core.annotate.TargetClass;
-import java.util.function.BooleanSupplier;
-
-/** Substitution for setting Java version correctly in the Google Java Http Client. */
-@TargetClass(
- className =
- "com.google.api.client.googleapis.services.AbstractGoogleClientRequest$ApiClientVersion",
- onlyWith = ApiClientVersionSubstitutions.OnlyIfInClassPath.class)
-final class ApiClientVersionSubstitutions {
-
- @Alias private String versionString;
-
- @Substitute
- public String toString() {
- String[] tokens = versionString.split(" ");
-
- if (tokens.length > 0 && tokens[0].startsWith("gl-java")) {
- tokens[0] += "-graalvm";
- return String.join(" ", tokens);
- } else {
- return versionString;
- }
- }
-
- private ApiClientVersionSubstitutions() {}
-
- static class OnlyIfInClassPath implements BooleanSupplier {
-
- @Override
- public boolean getAsBoolean() {
- try {
- // Note: Set initialize = false to avoid initializing the class when looking it up.
- Class.forName(
- "com.google.api.client.googleapis.services."
- + "AbstractGoogleClientRequest$ApiClientVersion",
- false,
- Thread.currentThread().getContextClassLoader());
- return true;
- } catch (ClassNotFoundException e) {
- return false;
- }
- }
- }
-}
diff --git a/gax/src/main/java/com/google/api/gax/nativeimage/substitutions/GaxPropertiesSubstitutions.java b/gax/src/main/java/com/google/api/gax/nativeimage/substitutions/GaxPropertiesSubstitutions.java
deleted file mode 100644
index 611b36c84..000000000
--- a/gax/src/main/java/com/google/api/gax/nativeimage/substitutions/GaxPropertiesSubstitutions.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2022 Google LLC
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google LLC nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package com.google.api.gax.nativeimage.substitutions;
-
-import com.oracle.svm.core.annotate.Alias;
-import com.oracle.svm.core.annotate.RecomputeFieldValue;
-import com.oracle.svm.core.annotate.RecomputeFieldValue.Kind;
-import com.oracle.svm.core.annotate.TargetClass;
-import java.util.function.BooleanSupplier;
-
-/**
- * This file contains the GaxProperties substitution to correctly set the Java language string in
- * API call headers for Native Image users.
- */
-@TargetClass(
- className = "com.google.api.gax.core.GaxProperties",
- onlyWith = GaxPropertiesSubstitutions.OnlyIfInClassPath.class)
-final class GaxPropertiesSubstitutions {
-
- @Alias
- @RecomputeFieldValue(kind = Kind.FromAlias)
- private static String JAVA_VERSION = System.getProperty("java.version") + "-graalvm";
-
- private GaxPropertiesSubstitutions() {}
-
- static class OnlyIfInClassPath implements BooleanSupplier {
-
- @Override
- public boolean getAsBoolean() {
- try {
- // Note: Set initialize = false to avoid initializing the class when looking it up.
- Class.forName(
- "com.google.api.gax.core.GaxProperties",
- false,
- Thread.currentThread().getContextClassLoader());
- return true;
- } catch (ClassNotFoundException e) {
- return false;
- }
- }
- }
-}
diff --git a/gax/src/main/resources/META-INF/native-image/com.google.api/gax/resource-config.json b/gax/src/main/resources/META-INF/native-image/com.google.api/gax/resource-config.json
index fdc788936..bc40a95d5 100644
--- a/gax/src/main/resources/META-INF/native-image/com.google.api/gax/resource-config.json
+++ b/gax/src/main/resources/META-INF/native-image/com.google.api/gax/resource-config.json
@@ -1,6 +1,9 @@
{
"resources":[
{"pattern":"\\QMETA-INF/services/jdk.vm.ci.services.JVMCIServiceLocator\\E"},
- {"pattern":"\\Qdependencies.properties\\E"}],
+ {"pattern":"\\Qdependencies.properties\\E"},
+ {"pattern":"\\Qcom/google/api/client/googleapis/google-api-client.properties\\E"},
+ {"pattern":"\\Qcom/google/api/client/googleapis/google.p12\\E"},
+ {"pattern":"\\Qcom/google/api/client/http/google-http-client.properties\\E"}],
"bundles":[]
}
diff --git a/gax/src/test/java/com/google/api/gax/core/GaxPropertiesTest.java b/gax/src/test/java/com/google/api/gax/core/GaxPropertiesTest.java
index a748b9aee..27d942e69 100644
--- a/gax/src/test/java/com/google/api/gax/core/GaxPropertiesTest.java
+++ b/gax/src/test/java/com/google/api/gax/core/GaxPropertiesTest.java
@@ -29,6 +29,8 @@
*/
package com.google.api.gax.core;
+import static org.graalvm.nativeimage.ImageInfo.PROPERTY_IMAGE_CODE_KEY;
+import static org.graalvm.nativeimage.ImageInfo.PROPERTY_IMAGE_CODE_VALUE_RUNTIME;
import static org.junit.Assert.assertTrue;
import java.util.regex.Pattern;
@@ -54,4 +56,11 @@ public void testGaxVersion() {
assertTrue(minor >= 56);
}
}
+
+ @Test
+ public void testGetVersion_nativeImage() {
+ System.setProperty(PROPERTY_IMAGE_CODE_KEY, PROPERTY_IMAGE_CODE_VALUE_RUNTIME);
+ String javaVersion = GaxProperties.getJavaVersion();
+ assertTrue(javaVersion.endsWith("-graalvm"));
+ }
}
diff --git a/versions.txt b/versions.txt
index 97713765f..3c7613a42 100644
--- a/versions.txt
+++ b/versions.txt
@@ -1,7 +1,7 @@
# Format:
# module:released-version:current-version
-gax:2.17.0:2.17.0
-gax-bom:2.17.0:2.17.0
-gax-grpc:2.17.0:2.17.0
-gax-httpjson:0.102.0:0.102.0
+gax:2.18.0:2.18.0
+gax-bom:2.18.0:2.18.0
+gax-grpc:2.18.0:2.18.0
+gax-httpjson:0.103.0:0.103.0