Skip to content

Commit 637bfb1

Browse files
author
Nicola Concetti
committed
fix(grpc): add support for grpc service methods with underscores and reserved keywords in BlockingServerInterceptor
1 parent 709485f commit 637bfb1

File tree

2 files changed

+148
-2
lines changed

2 files changed

+148
-2
lines changed

extensions/grpc/runtime/src/main/java/io/quarkus/grpc/runtime/supports/blocking/BlockingServerInterceptor.java

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,62 @@
3737
public class BlockingServerInterceptor implements ServerInterceptor, Function<String, Boolean>, Prioritized {
3838
private static final Logger log = Logger.getLogger(BlockingServerInterceptor.class);
3939

40+
// Reserved keywords, based on the jls, see:
41+
// https://github.com/grpc/grpc-java/blob/master/compiler/src/java_plugin/cpp/java_generator.cpp#L90
42+
private static final Set<String> GRPC_JAVA_RESERVED_KEYWORDS = Set.of(
43+
"abstract",
44+
"assert",
45+
"boolean",
46+
"break",
47+
"byte",
48+
"case",
49+
"catch",
50+
"char",
51+
"class",
52+
"const",
53+
"continue",
54+
"default",
55+
"do",
56+
"double",
57+
"else",
58+
"enum",
59+
"extends",
60+
"final",
61+
"finally",
62+
"float",
63+
"for",
64+
"goto",
65+
"if",
66+
"implements",
67+
"import",
68+
"instanceof",
69+
"int",
70+
"interface",
71+
"long",
72+
"native",
73+
"new",
74+
"package",
75+
"private",
76+
"protected",
77+
"public",
78+
"return",
79+
"short",
80+
"static",
81+
"strictfp",
82+
"super",
83+
"switch",
84+
"synchronized",
85+
"this",
86+
"throw",
87+
"throws",
88+
"transient",
89+
"try",
90+
"void",
91+
"volatile",
92+
"while",
93+
"true",
94+
"false");
95+
4096
private final Vertx vertx;
4197
private final Set<String> blockingMethods;
4298
private final Set<String> virtualMethods;
@@ -68,12 +124,22 @@ public BlockingServerInterceptor(Vertx vertx, List<String> blockingMethods, List
68124
@Override
69125
public Boolean apply(String name) {
70126
String methodName = name.substring(name.lastIndexOf("/") + 1);
71-
return blockingMethods.contains(methodName.toLowerCase());
127+
return blockingMethods.contains(toLowerCaseBeanSpec(methodName));
72128
}
73129

74130
public Boolean applyVirtual(String name) {
75131
String methodName = name.substring(name.lastIndexOf("/") + 1);
76-
return virtualMethods.contains(methodName.toLowerCase());
132+
return virtualMethods.contains(toLowerCaseBeanSpec(methodName));
133+
}
134+
135+
private String toLowerCaseBeanSpec(String name) {
136+
137+
// Methods cannot always be lowercased for comparison.
138+
// - gRPC allows using method names which normally would not work in java because of reserved keywords.
139+
// - Underscores are removed.
140+
141+
String lowerBeanSpec = name.toLowerCase().replace("_", "");
142+
return GRPC_JAVA_RESERVED_KEYWORDS.contains(lowerBeanSpec) ? lowerBeanSpec + "_" : lowerBeanSpec;
77143
}
78144

79145
@Override

extensions/grpc/runtime/src/test/java/io/quarkus/grpc/runtime/supports/BlockingServerInterceptorTest.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import static org.mockito.Mockito.when;
66

77
import java.util.Collections;
8+
import java.util.List;
89
import java.util.concurrent.CountDownLatch;
910

1011
import org.junit.jupiter.api.BeforeEach;
@@ -80,6 +81,85 @@ void testContextPropagation() throws Exception {
8081
}
8182
}
8283

84+
@Test
85+
void testGrpcMethodMappingWithReservedKeywords() {
86+
List<String> reservedKeywords = List.of(
87+
"abstract",
88+
"assert",
89+
"boolean",
90+
"break",
91+
"byte",
92+
"case",
93+
"catch",
94+
"char",
95+
"class",
96+
"const",
97+
"continue",
98+
"default",
99+
"do",
100+
"double",
101+
"else",
102+
"enum",
103+
"extends",
104+
"final",
105+
"finally",
106+
"float",
107+
"for",
108+
"goto",
109+
"if",
110+
"implements",
111+
"import",
112+
"instanceof",
113+
"int",
114+
"interface",
115+
"long",
116+
"native",
117+
"new",
118+
"package",
119+
"private",
120+
"protected",
121+
"public",
122+
"return",
123+
"short",
124+
"static",
125+
"strictfp",
126+
"super",
127+
"switch",
128+
"synchronized",
129+
"this",
130+
"throw",
131+
"throws",
132+
"transient",
133+
"try",
134+
"void",
135+
"volatile",
136+
"while",
137+
"true",
138+
"false");
139+
140+
List<String> javaMethodNames = reservedKeywords.stream().map(r -> r + "_").toList();
141+
BlockingServerInterceptor interceptor = new BlockingServerInterceptor(vertx,
142+
javaMethodNames, javaMethodNames, null, false) {
143+
};
144+
145+
reservedKeywords
146+
.forEach(reservedKeyword -> assertThat(interceptor.apply("my-service/" + reservedKeyword)).isTrue());
147+
reservedKeywords
148+
.forEach(reservedKeyword -> assertThat(interceptor.applyVirtual("my-service/" + reservedKeyword)).isTrue());
149+
}
150+
151+
@Test
152+
void testGrpcMethodMappingWithUnderscores() {
153+
154+
String javaMethodName = "javabeanspec";
155+
BlockingServerInterceptor interceptor = new BlockingServerInterceptor(vertx,
156+
Collections.singletonList(javaMethodName), Collections.singletonList(javaMethodName), null, false) {
157+
};
158+
159+
assertThat(interceptor.apply("my-service/J_Ava_BeanSpec")).isTrue();
160+
assertThat(interceptor.applyVirtual("my-service/J_Ava_BeanSpec")).isTrue();
161+
}
162+
83163
static class BlockingServerCallHandler implements ServerCallHandler {
84164
String threadName;
85165
String contextUserName;

0 commit comments

Comments
 (0)