-
Notifications
You must be signed in to change notification settings - Fork 3.9k
servlet: Implement gRPC server as a Servlet #8596
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
133 commits
Select commit
Hold shift + click to select a range
a0c92df
POC: Implement gRPC server as a Servlet
dapengzhang0 8719377
better-logging
dapengzhang0 46d00ec
get rid of public ServerImpl
dapengzhang0 4fa6271
rename files
dapengzhang0 e793c7c
fix serverListener NPE
dapengzhang0 393fcf6
fix onSendingBytes()
dapengzhang0 706a3c9
favor ConcurrentLinkedQueue for library
dapengzhang0 5e11674
refactor ServletAdapterImpl to ServletAdapter
dapengzhang0 1776917
not to use CDI for simplicity
dapengzhang0 bb3a720
add GrpcServlet(ServletServerBuilder serverBuilder)
dapengzhang0 4c7cd4f
add UndertowInteropTest and UndertowAbstractTest
dapengzhang0 af7f6a3
fix codecov
dapengzhang0 2fc04fc
minor enhancements
dapengzhang0 6fb4fc2
Merge branch 'master' of https://github.com/grpc/grpc-java into servl…
dapengzhang0 8b78b6d
update example gradle files
dapengzhang0 680872b
Merge branch 'master' of https://github.com/grpc/grpc-java into servl…
dapengzhang0 b3473df
Merge branch 'master' of https://github.com/grpc/grpc-java into servl…
dapengzhang0 3728866
revert core/src/test/java/io/grpc/internal/AbstractTransportTest.java
dapengzhang0 58fce63
ignore some transport tests
dapengzhang0 5b02064
cleanup GrpcServlet constructor
dapengzhang0 d59f81e
better way to get authority
dapengzhang0 5b7496e
comment SPSC
dapengzhang0 e98e4f8
attributes.toBuilder()
dapengzhang0 6aa26e4
move writeState and WriteListener
dapengzhang0 c3dfaba
Merge branch 'master' of https://github.com/grpc/grpc-java into servl…
dapengzhang0 44ea5f3
revert AbstractTransportTest reformat
dapengzhang0 ef5f879
temp
dapengzhang0 47e3e95
fix some of review comments
dapengzhang0 c5fc2bd
create util methods
dapengzhang0 63e8cb2
minor cleanup
dapengzhang0 986a885
Merge branch 'master' of https://github.com/grpc/grpc-java into servl…
dapengzhang0 3fd4ca8
factor out write path so that easy to replace with other implementation
dapengzhang0 09967c1
xds: gate xDS timeout with env variable (v1.33.x backport) (#7504) (#…
voidzcy 7d8410f
Update README etc to reference 1.33.0
dapengzhang0 a53114b
Merge commit '38952b0b3' into servletasync
niloc132 ae0085f
Update servlet build to catch up to changes at around the 1.25 release
niloc132 9a02c82
Merge commit '2d592642a' into servletasync
niloc132 7977de6
Merge commit '04cf90a9a' into servletasync
niloc132 811fcbe
Update test to use the new conventions
niloc132 ccbfd8d
Merge commit 'df1b67869' into servletasync
niloc132 5d017a3
Merge commit '5c31dc6d7' into servletasync
niloc132 0180d29
Merge commit 'a86fc47c0' into servletasync
niloc132 7bb191c
Add explicit guava dependency
niloc132 59d9754
Merge commit '7047209ba' into servletasync
niloc132 1f4b0ca
Simple typos
niloc132 ccc5cd6
Merge commit 'v1.33.0^' into servletasync
niloc132 7d90af8
Merge commit '620d26667' into servletasync
niloc132 aea3351
Merge commit '73fe68eec' into servletasync
niloc132 70ca920
Merge commit '7d9ee8f05' into servletasync
niloc132 83d405e
Merge commit '828b03da2' into servletasync
niloc132 18d20d3
Merge commit 'd2160ea70' into servletasync
niloc132 f4c0c87
Merge commit 'dc74a31be' into servletasync
niloc132 b12370e
Merge commit '1e858921e' into servletasync
niloc132 a39be4c
tomcat
dapengzhang0 dea10c6
amend tomcat/jetty tests so they build after cherry-pick
niloc132 2154764
Relax jetty rate control
niloc132 bf5c225
Fix typo in log config, though apparently not used?
niloc132 a0b5852
Update tests to keep classpaths apart, fix/ignore failures
niloc132 512a2d3
Tomcat test cleanup, note about intermittent test
niloc132 4bed353
Typo in test class
niloc132 907f432
Restore another test setup piece, with fixed dependencies
niloc132 75f9b82
Update to java-library plugin, build javadoc
niloc132 cf3decb
Stubbed in servlet-jakarta project, rewrite commit with vers
niloc132 00b8f76
Simplify tests for javax.servlet
niloc132 35e0af2
Checkpoint before rewriting without this jakarta plugin...
niloc132 0c5664c
Working build+test on jakarta, with markers to delete jetty9 workaround
niloc132 8162d6e
Finish removing jakarta plugin
niloc132 8e25c4c
Merge remote-tracking branch 'upstream/master' into servletasync
niloc132 3bcd0af
Handle Java8 as well as Java11
niloc132 034771f
Disable another intermittent tomcat test
niloc132 da85cf8
Import cleanup
niloc132 f84a156
Upgrade various versions to latest, add some details about specific
niloc132 f7677f6
Example servlet readme
niloc132 dc2ddcf
Remove note that no longer applies
niloc132 cc9eb3f
Correct a different maven repo url
niloc132 67eb249
Rearrange test code, add jetty transport test
niloc132 c8eea3b
Update jakarta servlet tests too
niloc132 36c4e08
Merge remote-tracking branch 'upstream/master' into servletasync
niloc132 490abf2
Fix readme link error
niloc132 0db2bdf
Address JdkObsolete build errors
niloc132 6440b3b
Revert attempt to avoid StringBuffer, and add JdkObsolete suppress in…
niloc132 cc2297d
Fix build bug preventing jetty10 tests from running
niloc132 6197088
Merge branch 'master' into servlet-niloc132
dapengzhang0 9acba27
Make buildTransportServers() package private and VisibleForTesting
dapengzhang0 44fc657
fix bad import
dapengzhang0 6764b77
remove logging in test
dapengzhang0 7cce389
use org.apache.tomcat:annotations-api instead of javax.annotation
dapengzhang0 33639da
update RELEASING.md
dapengzhang0 822701e
remove unnecessary line
niloc132 f1a2ff3
Correctly publish jakarta artifact
niloc132 2a26e5e
Use empty() rather than making an empty byte[]
niloc132 a72bed1
Remove jetty 9 workaround
niloc132 a67519c
Update to latest servlet impls for tests
niloc132 0741d02
Configure tomcat to allow tests, remove skipped tests this fixes
niloc132 c88e1ce
retain test SourceSet for (future) normal unit test
dapengzhang0 4a55684
disable checkstyle in servlet-jakarta completely
dapengzhang0 d77973e
Revert "update RELEASING.md"
dapengzhang0 e632dde
make grpc-core an implementation dependency
dapengzhang0 c903d75
cleanup AsyncServletOutputStreamWriter
dapengzhang0 0bc4dcc
workaround tomcat outputStream.isReayd NPE after asyncCtx.complete
dapengzhang0 d73bad1
remove timeout rule for UndertowTransportTest
dapengzhang0 714e81b
Merge branch 'master' into servlet-niloc132
dapengzhang0 1962a0e
add jacoco coverage
dapengzhang0 022c66c
fix jacoco
dapengzhang0 bfef2a2
Change packages for jakarta servlet types
niloc132 bd3d791
Suppress java9+ warnings/errors from tomcat illegal reflective access
niloc132 533bd21
Merge branch 'master' into servlet-niloc132
dapengzhang0 6f7e626
bump grpc version in example
dapengzhang0 bc802ae
Un-ignore JettyInteropTest.gracefulShutdown
dapengzhang0 b1da336
Add servlet to grpc-all:javadoc
dapengzhang0 93f1c6f
fix jakarta build warning
dapengzhang0 0e64316
Concurrency correctness test for AsyncServletOutputStreamWriter
dapengzhang0 38c0585
enhance lincheck test
dapengzhang0 5cb764a
add test for builder scheduler and GrpcServlet constructor
dapengzhang0 986ee81
add test for builder scheduler and GrpcServlet constructor 2
dapengzhang0 95c350f
ignore flaky undertow test
dapengzhang0 7a90a53
add Test annotation
dapengzhang0 f8b9950
improve builder test
dapengzhang0 576d64e
response with error code for GET method
dapengzhang0 50020b3
fix executorPool and TIMER_SERVICE leak after servlet.destroy()
dapengzhang0 79dc180
Merge branch 'master' into servlet-niloc132
dapengzhang0 6d58c9b
bump grpc version in example
dapengzhang0 dda244d
Merge commit '78ccc81fd' into servletasync
niloc132 5829381
Merge branch 'master' of https://github.com/grpc/grpc-java into servl…
dapengzhang0 7ae71dc
bump grpc version in example
dapengzhang0 639084a
Use Gradle's version catalog
dapengzhang0 b13d505
regression while bumping to v1.47.0
dapengzhang0 5bbaea3
Merge commit '7bdca0c0e' into servletasync
niloc132 524bbe9
Merge commit 'e998955d1' into servletasync
niloc132 129628e
Merge commit 'a82ea0cb0' into servletasync
niloc132 4c68cfb
Merge commit 'e325dc911' into servletasync
niloc132 f26201a
Merge remote-tracking branch 'upstream/master' into servletasync
niloc132 7929461
Review feedback, version bump
niloc132 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# Hello World Example using Servlets | ||
|
||
This example uses Java Servlets instead of Netty for the gRPC server. This example requires `grpc-java` | ||
and `protoc-gen-grpc-java` to already be built. You are strongly encouraged to check out a git release | ||
tag, since these builds will already be available. | ||
|
||
```bash | ||
git checkout v<major>.<minor>.<patch> | ||
``` | ||
Otherwise, you must follow [COMPILING](../../COMPILING.md). | ||
|
||
To build the example, | ||
|
||
1. **[Install gRPC Java library SNAPSHOT locally, including code generation plugin](../../COMPILING.md) (Only need this step for non-released versions, e.g. master HEAD).** | ||
|
||
2. In this directory, build the war file | ||
```bash | ||
$ ../gradlew war | ||
``` | ||
|
||
To run this, deploy the war, now found in `build/libs/example-servlet.war` to your choice of servlet | ||
container. Note that this container must support the Servlet 4.0 spec, for this particular example must | ||
use `javax.servlet` packages instead of the more modern `jakarta.servlet`, though there is a `grpc-servlet-jakarta` | ||
artifact that can be used for Jakarta support. Be sure to enable http/2 support in the servlet container, | ||
or clients will not be able to connect. | ||
|
||
To test that this is working properly, build the HelloWorldClient example and direct it to connect to your | ||
http/2 server. From the parent directory: | ||
|
||
1. Build the executables: | ||
```bash | ||
$ ../gradlew installDist | ||
``` | ||
2. Run the client app, specifying the name to say hello to and the server's address: | ||
```bash | ||
$ ./build/install/examples/bin/hello-world-client World localhost:8080 | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
plugins { | ||
// ASSUMES GRADLE 5.6 OR HIGHER. Use plugin version 0.8.10 with earlier gradle versions | ||
id 'com.google.protobuf' version '0.8.17' | ||
// Generate IntelliJ IDEA's .idea & .iml project files | ||
id 'idea' | ||
id 'war' | ||
} | ||
|
||
repositories { | ||
maven { // The google mirror is less flaky than mavenCentral() | ||
url "https://maven-central.storage-download.googleapis.com/maven2/" } | ||
mavenLocal() | ||
} | ||
|
||
sourceCompatibility = 1.8 | ||
targetCompatibility = 1.8 | ||
|
||
def grpcVersion = '1.53.0-SNAPSHOT' // CURRENT_GRPC_VERSION | ||
def protocVersion = '3.21.7' | ||
|
||
dependencies { | ||
implementation "io.grpc:grpc-protobuf:${grpcVersion}", | ||
"io.grpc:grpc-servlet:${grpcVersion}", | ||
"io.grpc:grpc-stub:${grpcVersion}" | ||
|
||
providedImplementation "javax.servlet:javax.servlet-api:4.0.1", | ||
"org.apache.tomcat:annotations-api:6.0.53" | ||
} | ||
|
||
protobuf { | ||
protoc { artifact = "com.google.protobuf:protoc:${protocVersion}" } | ||
plugins { grpc { artifact = "io.grpc:protoc-gen-grpc-java:${grpcVersion}" } } | ||
generateProtoTasks { | ||
all()*.plugins { grpc {} } | ||
} | ||
} | ||
|
||
// Inform IDEs like IntelliJ IDEA, Eclipse or NetBeans about the generated code. | ||
sourceSets { | ||
main { | ||
java { | ||
srcDirs 'build/generated/source/proto/main/grpc' | ||
srcDirs 'build/generated/source/proto/main/java' | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
pluginManagement { | ||
repositories { | ||
maven { // The google mirror is less flaky than mavenCentral() | ||
url "https://maven-central.storage-download.googleapis.com/maven2/" | ||
} | ||
gradlePluginPortal() | ||
} | ||
} |
79 changes: 79 additions & 0 deletions
79
.../example-servlet/src/main/java/io/grpc/servlet/examples/helloworld/HelloWorldServlet.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* Copyright 2018 The gRPC Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package io.grpc.servlet.examples.helloworld; | ||
|
||
import io.grpc.stub.StreamObserver; | ||
import io.grpc.examples.helloworld.GreeterGrpc; | ||
import io.grpc.examples.helloworld.HelloReply; | ||
import io.grpc.examples.helloworld.HelloRequest; | ||
import io.grpc.servlet.ServletAdapter; | ||
import io.grpc.servlet.ServletServerBuilder; | ||
import java.io.IOException; | ||
import javax.servlet.annotation.WebServlet; | ||
import javax.servlet.http.HttpServlet; | ||
import javax.servlet.http.HttpServletRequest; | ||
import javax.servlet.http.HttpServletResponse; | ||
|
||
/** | ||
* A servlet that hosts a gRPC server over HTTP/2 and shares the resource URI for the normal servlet | ||
* clients over HTTP/1.0+. | ||
* | ||
* <p>For creating a servlet that solely serves gRPC services, do not follow this example, simply | ||
* extend or register a {@link io.grpc.servlet.GrpcServlet} instead. | ||
*/ | ||
@WebServlet(urlPatterns = {"/helloworld.Greeter/SayHello"}, asyncSupported = true) | ||
public class HelloWorldServlet extends HttpServlet { | ||
private static final long serialVersionUID = 1L; | ||
|
||
private final ServletAdapter servletAdapter = | ||
new ServletServerBuilder().addService(new GreeterImpl()).buildServletAdapter(); | ||
|
||
private static final class GreeterImpl extends GreeterGrpc.GreeterImplBase { | ||
GreeterImpl() {} | ||
|
||
@Override | ||
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) { | ||
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build(); | ||
responseObserver.onNext(reply); | ||
responseObserver.onCompleted(); | ||
} | ||
} | ||
|
||
@Override | ||
protected void doGet(HttpServletRequest request, HttpServletResponse response) | ||
throws IOException { | ||
response.setContentType("text/html"); | ||
response.getWriter().println("<p>Hello World!</p>"); | ||
} | ||
|
||
@Override | ||
protected void doPost(HttpServletRequest request, HttpServletResponse response) | ||
throws IOException { | ||
if (ServletAdapter.isGrpc(request)) { | ||
servletAdapter.doPost(request, response); | ||
} else { | ||
response.setContentType("text/html"); | ||
response.getWriter().println("<p>Hello non-gRPC client!</p>"); | ||
} | ||
} | ||
|
||
@Override | ||
public void destroy() { | ||
servletAdapter.destroy(); | ||
super.destroy(); | ||
} | ||
} |
37 changes: 37 additions & 0 deletions
37
examples/example-servlet/src/main/proto/helloworld/helloworld.proto
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// Copyright 2015 The gRPC Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
syntax = "proto3"; | ||
|
||
option java_multiple_files = true; | ||
option java_package = "io.grpc.examples.helloworld"; | ||
option java_outer_classname = "HelloWorldProto"; | ||
option objc_class_prefix = "HLW"; | ||
|
||
package helloworld; | ||
|
||
// The greeting service definition. | ||
service Greeter { | ||
// Sends a greeting | ||
rpc SayHello (HelloRequest) returns (HelloReply) {} | ||
} | ||
|
||
// The request message containing the user's name. | ||
message HelloRequest { | ||
string name = 1; | ||
} | ||
|
||
// The response message containing the greetings | ||
message HelloReply { | ||
string message = 1; | ||
} |
6 changes: 6 additions & 0 deletions
6
examples/example-servlet/src/main/webapp/WEB-INF/glassfish-web.xml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- Need this file for deployment to GlassFish --> | ||
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd"> | ||
<glassfish-web-app error-url=""> | ||
<class-loader delegate="false"/> | ||
</glassfish-web-app> |
9 changes: 9 additions & 0 deletions
9
examples/example-servlet/src/main/webapp/WEB-INF/jboss-web.xml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- Need this file for deployment to WildFly --> | ||
<jboss-web xmlns="http://www.jboss.com/xml/ns/javaee" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation=" | ||
http://www.jboss.com/xml/ns/javaee | ||
http://www.jboss.org/j2ee/schema/jboss-web_5_1.xsd"> | ||
<context-root>/</context-root> | ||
</jboss-web> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be nice to build out such an example/docs - since servlets are instantiated via their default constructor, it can be irritating expose the set of bindableservices that will be expected to be served (via a runtime Set), while also offering a configuration like this annotation that describes the urls to map to.
This might suggest offering a Filter in addition to a Servlet, which can check its set of bindings and only handle the call if it matches (checking the req.getRequestURI().substring(1) as ServletAdapter.doPost does, and comparing against its set), otherwise letting some later filter/servlet take over. It could also perform the content-type check.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree we should have an example to use extension of
GrpcServlet
directly, maybe implementing the routeguide service, in addition to the existing example.As for Filter, that might be something we can add after this PR being merged, and have this PR only support the most basic servlet API. Same for the grpc-web support.