Skip to content

Commit a51ac28

Browse files
committed
2 parents d7ef02a + 319c113 commit a51ac28

40 files changed

Lines changed: 1580 additions & 856 deletions

README.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ For a guided tour, take a look at the [quick start
4444
guide](https://grpc.io/docs/languages/java/quickstart) or the more explanatory [gRPC
4545
basics](https://grpc.io/docs/languages/java/basics).
4646

47-
The [examples](https://github.com/grpc/grpc-java/tree/v1.75.0/examples) and the
48-
[Android example](https://github.com/grpc/grpc-java/tree/v1.75.0/examples/android)
47+
The [examples](https://github.com/grpc/grpc-java/tree/v1.76.0/examples) and the
48+
[Android example](https://github.com/grpc/grpc-java/tree/v1.76.0/examples/android)
4949
are standalone projects that showcase the usage of gRPC.
5050

5151
Download
@@ -56,42 +56,42 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`:
5656
<dependency>
5757
<groupId>io.grpc</groupId>
5858
<artifactId>grpc-netty-shaded</artifactId>
59-
<version>1.75.0</version>
59+
<version>1.76.0</version>
6060
<scope>runtime</scope>
6161
</dependency>
6262
<dependency>
6363
<groupId>io.grpc</groupId>
6464
<artifactId>grpc-protobuf</artifactId>
65-
<version>1.75.0</version>
65+
<version>1.76.0</version>
6666
</dependency>
6767
<dependency>
6868
<groupId>io.grpc</groupId>
6969
<artifactId>grpc-stub</artifactId>
70-
<version>1.75.0</version>
70+
<version>1.76.0</version>
7171
</dependency>
7272
```
7373

7474
Or for Gradle with non-Android, add to your dependencies:
7575
```gradle
76-
runtimeOnly 'io.grpc:grpc-netty-shaded:1.75.0'
77-
implementation 'io.grpc:grpc-protobuf:1.75.0'
78-
implementation 'io.grpc:grpc-stub:1.75.0'
76+
runtimeOnly 'io.grpc:grpc-netty-shaded:1.76.0'
77+
implementation 'io.grpc:grpc-protobuf:1.76.0'
78+
implementation 'io.grpc:grpc-stub:1.76.0'
7979
```
8080

8181
For Android client, use `grpc-okhttp` instead of `grpc-netty-shaded` and
8282
`grpc-protobuf-lite` instead of `grpc-protobuf`:
8383
```gradle
84-
implementation 'io.grpc:grpc-okhttp:1.75.0'
85-
implementation 'io.grpc:grpc-protobuf-lite:1.75.0'
86-
implementation 'io.grpc:grpc-stub:1.75.0'
84+
implementation 'io.grpc:grpc-okhttp:1.76.0'
85+
implementation 'io.grpc:grpc-protobuf-lite:1.76.0'
86+
implementation 'io.grpc:grpc-stub:1.76.0'
8787
```
8888

8989
For [Bazel](https://bazel.build), you can either
9090
[use Maven](https://github.com/bazelbuild/rules_jvm_external)
9191
(with the GAVs from above), or use `@io_grpc_grpc_java//api` et al (see below).
9292

9393
[the JARs]:
94-
https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.75.0
94+
https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.76.0
9595

9696
Development snapshots are available in [Sonatypes's snapshot
9797
repository](https://central.sonatype.com/repository/maven-snapshots/).
@@ -121,9 +121,9 @@ For protobuf-based codegen integrated with the Maven build system, you can use
121121
<artifactId>protobuf-maven-plugin</artifactId>
122122
<version>0.6.1</version>
123123
<configuration>
124-
<protocArtifact>com.google.protobuf:protoc:3.25.5:exe:${os.detected.classifier}</protocArtifact>
124+
<protocArtifact>com.google.protobuf:protoc:3.25.8:exe:${os.detected.classifier}</protocArtifact>
125125
<pluginId>grpc-java</pluginId>
126-
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.75.0:exe:${os.detected.classifier}</pluginArtifact>
126+
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.76.0:exe:${os.detected.classifier}</pluginArtifact>
127127
</configuration>
128128
<executions>
129129
<execution>
@@ -149,11 +149,11 @@ plugins {
149149
150150
protobuf {
151151
protoc {
152-
artifact = "com.google.protobuf:protoc:3.25.5"
152+
artifact = "com.google.protobuf:protoc:3.25.8"
153153
}
154154
plugins {
155155
grpc {
156-
artifact = 'io.grpc:protoc-gen-grpc-java:1.75.0'
156+
artifact = 'io.grpc:protoc-gen-grpc-java:1.76.0'
157157
}
158158
}
159159
generateProtoTasks {
@@ -182,11 +182,11 @@ plugins {
182182
183183
protobuf {
184184
protoc {
185-
artifact = "com.google.protobuf:protoc:3.25.5"
185+
artifact = "com.google.protobuf:protoc:3.25.8"
186186
}
187187
plugins {
188188
grpc {
189-
artifact = 'io.grpc:protoc-gen-grpc-java:1.75.0'
189+
artifact = 'io.grpc:protoc-gen-grpc-java:1.76.0'
190190
}
191191
}
192192
generateProtoTasks {

binder/src/main/java/io/grpc/binder/internal/BinderServer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ public synchronized boolean handleTransaction(int code, Parcel parcel) {
185185
streamTracerFactories,
186186
OneWayBinderProxy.IDENTITY_DECORATOR,
187187
callbackBinder);
188-
transport.setServerTransportListener(listener.transportCreated(transport));
188+
transport.start(listener.transportCreated(transport));
189189
return true;
190190
}
191191
}

binder/src/main/java/io/grpc/binder/internal/BinderServerTransport.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616
package io.grpc.binder.internal;
1717

18+
import static com.google.common.base.Preconditions.checkNotNull;
19+
import static com.google.common.base.Preconditions.checkState;
20+
1821
import android.os.IBinder;
1922
import com.google.errorprone.annotations.concurrent.GuardedBy;
2023
import io.grpc.Attributes;
@@ -57,9 +60,17 @@ public BinderServerTransport(
5760
setOutgoingBinder(OneWayBinderProxy.wrap(callbackBinder, getScheduledExecutorService()));
5861
}
5962

60-
public synchronized void setServerTransportListener(
61-
ServerTransportListener serverTransportListener) {
62-
this.serverTransportListener = serverTransportListener;
63+
/**
64+
* Initializes this transport instance.
65+
*
66+
* <p>Must be called exactly once, even if {@link #shutdown} or {@link #shutdownNow} was called
67+
* first.
68+
*
69+
* @param serverTransportListener where this transport will report events
70+
*/
71+
public synchronized void start(ServerTransportListener serverTransportListener) {
72+
checkState(this.serverTransportListener == null, "Already started!");
73+
this.serverTransportListener = checkNotNull(serverTransportListener, "serverTransportListener");
6374
if (isShutdown()) {
6475
setState(TransportState.SHUTDOWN_TERMINATED);
6576
notifyTerminated();

binder/src/main/java/io/grpc/binder/internal/BinderTransport.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,15 +320,16 @@ final void shutdownInternal(Status shutdownStatus, boolean forceTerminate) {
320320
inbound.closeAbnormal(shutdownStatus);
321321
}
322322
}
323-
synchronized (this) {
324-
notifyTerminated();
325-
}
326-
releaseExecutors();
327-
323+
328324
for (Future<?> future : futuresToCancel) {
329325
// Not holding any locks here just in case some listener runs on a direct Executor.
330326
future.cancel(false); // No effect if already isDone().
331327
}
328+
329+
synchronized (this) {
330+
notifyTerminated();
331+
}
332+
releaseExecutors();
332333
});
333334
}
334335
}

binder/src/test/java/io/grpc/binder/internal/BinderServerTransportTest.java

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,21 @@
2020
import static org.mockito.ArgumentMatchers.any;
2121
import static org.mockito.ArgumentMatchers.anyInt;
2222
import static org.mockito.ArgumentMatchers.isNull;
23-
import static org.mockito.Mockito.when;
23+
import static org.mockito.Mockito.doThrow;
2424
import static org.robolectric.Shadows.shadowOf;
2525

2626
import android.os.IBinder;
2727
import android.os.Looper;
2828
import android.os.Parcel;
29+
import android.os.RemoteException;
2930
import com.google.common.collect.ImmutableList;
3031
import io.grpc.Attributes;
32+
import io.grpc.ServerStreamTracer;
3133
import io.grpc.Status;
3234
import io.grpc.internal.FixedObjectPool;
3335
import io.grpc.internal.MockServerTransportListener;
36+
import io.grpc.internal.ObjectPool;
37+
import java.util.List;
3438
import java.util.concurrent.ScheduledExecutorService;
3539
import org.junit.Before;
3640
import org.junit.Rule;
@@ -60,26 +64,74 @@ public final class BinderServerTransportTest {
6064

6165
@Before
6266
public void setUp() throws Exception {
63-
transport =
64-
new BinderServerTransport(
65-
new FixedObjectPool<>(executorService),
66-
Attributes.EMPTY,
67-
ImmutableList.of(),
68-
OneWayBinderProxy.IDENTITY_DECORATOR,
69-
mockBinder);
7067
transportListener = new MockServerTransportListener(transport);
7168
}
7269

70+
// Provide defaults so that we can "include only relevant details in tests."
71+
BinderServerTransportBuilder newBinderServerTransportBuilder() {
72+
return new BinderServerTransportBuilder()
73+
.setExecutorServicePool(new FixedObjectPool<>(executorService))
74+
.setAttributes(Attributes.EMPTY)
75+
.setStreamTracerFactories(ImmutableList.of())
76+
.setBinderDecorator(OneWayBinderProxy.IDENTITY_DECORATOR)
77+
.setCallbackBinder(mockBinder);
78+
}
79+
7380
@Test
74-
public void testSetupTransactionFailureCausesMultipleShutdowns_b153460678() throws Exception {
81+
public void testSetupTransactionFailureReportsMultipleTerminations_b153460678() throws Exception {
7582
// Make the binder fail the setup transaction.
76-
when(mockBinder.transact(anyInt(), any(Parcel.class), isNull(), anyInt())).thenReturn(false);
77-
transport.setServerTransportListener(transportListener);
83+
doThrow(new RemoteException())
84+
.when(mockBinder)
85+
.transact(anyInt(), any(Parcel.class), isNull(), anyInt());
86+
transport = newBinderServerTransportBuilder().setCallbackBinder(mockBinder).build();
87+
shadowOf(Looper.getMainLooper()).idle();
88+
transport.start(transportListener);
7889

79-
// Now shut it down.
90+
// Now shut it down externally *before* executing Runnables scheduled on the executor.
8091
transport.shutdownNow(Status.UNKNOWN.withDescription("reasons"));
8192
shadowOf(Looper.getMainLooper()).idle();
8293

8394
assertThat(transportListener.isTerminated()).isTrue();
8495
}
96+
97+
static class BinderServerTransportBuilder {
98+
ObjectPool<ScheduledExecutorService> executorServicePool;
99+
Attributes attributes;
100+
List<ServerStreamTracer.Factory> streamTracerFactories;
101+
OneWayBinderProxy.Decorator binderDecorator;
102+
IBinder callbackBinder;
103+
104+
public BinderServerTransport build() {
105+
return new BinderServerTransport(
106+
executorServicePool, attributes, streamTracerFactories, binderDecorator, callbackBinder);
107+
}
108+
109+
public BinderServerTransportBuilder setExecutorServicePool(
110+
ObjectPool<ScheduledExecutorService> executorServicePool) {
111+
this.executorServicePool = executorServicePool;
112+
return this;
113+
}
114+
115+
public BinderServerTransportBuilder setAttributes(Attributes attributes) {
116+
this.attributes = attributes;
117+
return this;
118+
}
119+
120+
public BinderServerTransportBuilder setStreamTracerFactories(
121+
List<ServerStreamTracer.Factory> streamTracerFactories) {
122+
this.streamTracerFactories = streamTracerFactories;
123+
return this;
124+
}
125+
126+
public BinderServerTransportBuilder setBinderDecorator(
127+
OneWayBinderProxy.Decorator binderDecorator) {
128+
this.binderDecorator = binderDecorator;
129+
return this;
130+
}
131+
132+
public BinderServerTransportBuilder setCallbackBinder(IBinder callbackBinder) {
133+
this.callbackBinder = callbackBinder;
134+
return this;
135+
}
136+
}
85137
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
substitutions:
2+
_GAE_SERVICE_ACCOUNT: appengine-testing-java@grpc-testing.iam.gserviceaccount.com
3+
options:
4+
env:
5+
- BUILD_ID=$BUILD_ID
6+
- KOKORO_GAE_SERVICE=java-gae-interop-test
7+
- DUMMY_DEFAULT_VERSION=dummy-default
8+
- GRADLE_OPTS=-Dorg.gradle.jvmargs='-Xmx1g'
9+
- GRADLE_FLAGS=-PskipCodegen=true -PskipAndroid=true
10+
logging: CLOUD_LOGGING_ONLY
11+
machineType: E2_HIGHCPU_8
12+
13+
steps:
14+
- id: clean-stale-deploys
15+
name: gcr.io/cloud-builders/gcloud
16+
allowFailure: true
17+
script: |
18+
#!/usr/bin/env bash
19+
set -e
20+
echo "Cleaning out stale deploys from previous runs, it is ok if this part fails"
21+
# If the test fails, the deployment is leaked.
22+
# Delete all versions whose name is not 'dummy-default' and is older than 1 hour.
23+
# This expression is an ISO8601 relative date:
24+
# https://cloud.google.com/sdk/gcloud/reference/topic/datetimes
25+
(gcloud app versions list --format="get(version.id)" \
26+
--filter="service=$KOKORO_GAE_SERVICE AND NOT version : '$DUMMY_DEFAULT_VERSION' AND version.createTime<'-p1h'" \
27+
| xargs -i gcloud app services delete "$KOKORO_GAE_SERVICE" --version {} --quiet) || true
28+
29+
- name: gcr.io/cloud-builders/docker
30+
args: ['build', '-t', 'gae-build', 'buildscripts/gae-build/']
31+
32+
- id: build
33+
name: gae-build
34+
script: |
35+
#!/usr/bin/env bash
36+
exec ./gradlew $GRADLE_FLAGS :grpc-gae-interop-testing-jdk8:appengineStage
37+
38+
- id: deploy
39+
name: gcr.io/cloud-builders/gcloud
40+
args:
41+
- app
42+
- deploy
43+
- gae-interop-testing/gae-jdk8/build/staged-app/app.yaml
44+
- --service-account=$_GAE_SERVICE_ACCOUNT
45+
- --no-promote
46+
- --no-stop-previous-version
47+
- --version=cb-$BUILD_ID
48+
49+
- id: runInteropTestRemote
50+
name: eclipse-temurin:17-jdk
51+
env:
52+
- PROJECT_ID=$PROJECT_ID
53+
script: |
54+
#!/usr/bin/env bash
55+
exec ./gradlew $GRADLE_FLAGS --stacktrace -PgaeDeployVersion="cb-$BUILD_ID" \
56+
-PgaeProjectId="$PROJECT_ID" :grpc-gae-interop-testing-jdk8:runInteropTestRemote
57+
58+
- id: cleanup
59+
name: gcr.io/cloud-builders/gcloud
60+
script: |
61+
#!/usr/bin/env bash
62+
set -e
63+
echo "Performing cleanup now."
64+
gcloud app services delete "$KOKORO_GAE_SERVICE" --version "cb-$BUILD_ID" --quiet

buildscripts/gae-build/Dockerfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FROM eclipse-temurin:17-jdk
2+
3+
# The AppEngine Gradle plugin downloads and runs its own gcloud to get the .jar
4+
# to link against, so we need Python even if we use gcloud deploy directly
5+
# instead of using the plugin.
6+
RUN export DEBIAN_FRONTEND=noninteractive && \
7+
apt-get update && \
8+
apt-get upgrade -y && \
9+
apt-get install -y --no-install-recommends python3 && \
10+
rm -rf /var/lib/apt/lists/*

0 commit comments

Comments
 (0)