Repository: smallnest/Jax-RS-Performance-Comparison
Branch: master
Commit: 47fd3974b80b
Files: 70
Total size: 145.5 KB
Directory structure:
gitextract_5f2xv914/
├── .gitignore
├── LICENSE
├── README.md
├── TestData.md
├── act/
│ ├── .gitignore
│ ├── README.md
│ ├── pom.xml
│ ├── run_dev
│ ├── run_dev.bat
│ ├── run_e2e
│ ├── run_e2e.bat
│ ├── run_prod
│ └── src/
│ └── main/
│ ├── java/
│ │ └── benchmark/
│ │ └── act/
│ │ └── AppEntry.java
│ └── resources/
│ ├── benchmark/
│ │ └── act/
│ │ └── .version
│ ├── conf/
│ │ ├── app.properties
│ │ ├── prod/
│ │ │ └── app.properties
│ │ └── uat/
│ │ └── app.properties
│ ├── e2e/
│ │ └── scenarios.yml
│ ├── logback.xml
│ └── routes.conf
├── armeria/
│ ├── pom.xml
│ └── src/
│ └── main/
│ ├── java/
│ │ └── com/
│ │ └── colobu/
│ │ └── armeria/
│ │ └── Main.java
│ └── thrift/
│ └── v1/
│ └── main.thrift
├── dropwizard/
│ ├── hello.yml
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── colobu/
│ └── rest/
│ └── dropwizard/
│ ├── Main.java
│ ├── MyApplication.java
│ ├── MyConfiguration.java
│ └── MyHealthCheck.java
├── go/
│ └── main.go
├── go-fasthttp/
│ └── main.go
├── jaxrs-common/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── colobu/
│ └── rest/
│ └── jaxrs/
│ ├── HelloResource.java
│ ├── HelloResourceAsync.java
│ └── MyApplication.java
├── jersey-grizzly2/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── colobu/
│ └── rest/
│ └── jerseygrizzly2/
│ └── Main.java
├── jersey-jetty/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── colobu/
│ └── rest/
│ └── jerseyjetty/
│ └── Main.java
├── light-java/
│ ├── pom.xml
│ └── src/
│ └── main/
│ ├── java/
│ │ └── Example.java
│ └── resources/
│ ├── META-INF/
│ │ └── services/
│ │ └── com.networknt.server.HandlerProvider
│ └── logback.xml
├── nativenetty/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── colobu/
│ └── rest/
│ └── nativenetty/
│ ├── HelloWorldHandler.java
│ └── Main.java
├── node.js/
│ ├── install.sh
│ └── server.js
├── pom.xml
├── resteasy-jetty/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── colobu/
│ └── rest/
│ └── resteasyjetty/
│ └── Main.java
├── resteasy-netty/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── colobu/
│ └── rest/
│ └── resteasynetty/
│ └── Main.java
├── resteasy-netty4/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── colobu/
│ └── rest/
│ └── resteasynetty4/
│ └── Main.java
├── resteasy-undertow/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── colobu/
│ └── rest/
│ └── resteasyundertow/
│ └── Main.java
├── springboot/
│ ├── pom.xml
│ └── src/
│ └── main/
│ ├── java/
│ │ └── com/
│ │ └── colobu/
│ │ └── rest/
│ │ └── springboot/
│ │ ├── HelloController.java
│ │ └── Main.java
│ └── resources/
│ └── application.properties
├── springboot-undertow/
│ ├── pom.xml
│ └── src/
│ └── main/
│ ├── java/
│ │ └── com/
│ │ └── colobu/
│ │ └── rest/
│ │ └── springboot/
│ │ ├── HelloController.java
│ │ └── Main.java
│ └── resources/
│ └── application.properties
├── testdata.xlsx
├── vertx/
│ ├── pom.xml
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── colobu/
│ └── rest/
│ └── vertx/
│ └── Main.java
└── vertx-verticles/
├── pom.xml
└── src/
└── main/
└── java/
└── com/
└── colobu/
└── rest/
└── vertx/
└── Main.java
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.idea/
.settings/
target/
*.iml
*.log
*.class
dependency-reduced-pom.xml
# mvn versions files
pom.xml.versionsBackup
# eclipse
.classpath
.project
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.ear
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
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.
================================================
FILE: README.md
================================================
# Jax-RS-Performance-Comparison
Performance Comparison of Jax-RS implementations and embedded containers
[](https://drone.io/github.com/smallnest/Jax-RS-Performance-Comparison/latest)
[Gajotres](http://www.gajotres.net/best-available-java-restful-micro-frameworks/#author-box) have written an article: [Top 8 Java RESTful Micro Frameworks](http://www.gajotres.net/best-available-java-restful-micro-frameworks/). He listed 8 best light weight Java RESTful framework.
Personally, I perfer jax-rs implementations and micro frameworks for deploying applications as micro services and those micro services can be deployed in docker containers.
So I have test five Jax-RS implementations plus embedded containers despite business logics. The RESTful service is very simple and it only returns a "hello world" string. Remember, tests don't contain any business logics even JSON libraries.
There are other articles to dicuss serialization framework. For example, [my test](http://colobu.com/2014/08/26/java-serializer-comparison/)
I have added more RESTful framework besides Jax-RS implementation, which contains:
* Spring-boot
* RESTEasy + Netty4
* Native Netty
* Vert.x
* Go
You can check the test result and the performancre chart.
### Compile applications
It is a multiple-module maven project.
You can run "mvn package" in parent directory to packge each module.
It generates a fat-jar in target directories of modules for each module.
It is easy.
### Test Environment
**Server**
AWS C3.2xlarge
- 8 cores (E5-2666 v3 @ 2.90GHz)
- memory: 16G (only allocate 4G for restful applications)
**Java**
1.8.0_51
**Test tool**
[wrk](https://github.com/wg/wrk)
the test cmd is like: `wrk -t16 -c1000 -d30s http://127.0.0.1:8080/rest/hello `.
I use 16 threads and 100/200/500/1000 connnections to test each case.
**Starting Server**
```
java -Xmx4g -Xms4g -jar jersey-grizzly2-1.0-SNAPSHOT.jar
java -Xmx4g -Xms4g -jar jersey-jetty-1.0-SNAPSHOT.jar
java -Xmx4g -Xms4g -jar dropwizard-1.0-SNAPSHOT.jar hello.yml
java -Xmx4g -Xms4g -jar resteasy-netty-1.0-SNAPSHOT.jar
java -Xmx4g -Xms4g -jar resteasy-undertow-1.0-SNAPSHOT.jar
java -Xmx4g -Xms4g -jar springboot-1.0-SNAPSHOT.jar
java -Xmx4g -Xms4g -jar resteasy-netty4-1.0-SNAPSHOT.jar
java -Xmx4g -Xms4g -jar nativenetty-1.0-SNAPSHOT.jar
java -Xmx4g -Xms4g -jar vertx-1.0-SNAPSHOT.jar
java -Xmx4g -Xms4g -jar swagger-light-java-1.0.0.jar
```
### Test Result
Test data is [here](TestData.md)

### Conclusion
It looks Resteasy is better than jersey whatever jersey uses grizzly2 or jetty container.
It is predictable that performance of dropwizard is same to jersey+jetty.
Resteasy is excellent in undertow and netty.
To my surprise is resteasy+undertow is a little better than resteasy+netty. Maybe they are all developed by JBoss and they have done some optimization.
I do not recommend you use spring boot in large projects because its performance and style.
Of course native netty is number one but my test has not contains a http router so maybe you can't say it is RESTful framework. But I like its perforamnce.
Performance of RESTEasy+netty4 is lower than what i expect. but RESTEasy+netty3 is very good.
~~One interesting framework is Vert.x. I like its functional programming style but its performance is not so good.~~
I have not monitored the CPU usage and memory usage. You can try it.
### Update
* 2015/11/19 add native go, go-restful codes
================================================
FILE: TestData.md
================================================
### jersey-grizzly2
```
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c100 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.98ms 2.06ms 48.92ms 92.37%
Req/Sec 3.71k 274.18 9.93k 82.39%
1774190 requests in 30.10s, 191.32MB read
Requests/sec: 58944.39
Transfer/sec: 6.36MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c200 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.32ms 1.89ms 41.80ms 91.65%
Req/Sec 3.86k 237.06 10.04k 86.86%
1844871 requests in 30.10s, 198.94MB read
Requests/sec: 61292.59
Transfer/sec: 6.61MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 8.14ms 2.35ms 211.50ms 88.87%
Req/Sec 3.84k 365.89 12.98k 96.16%
1835462 requests in 30.10s, 197.92MB read
Requests/sec: 60971.94
Transfer/sec: 6.57MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c1000 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 16.04ms 3.88ms 224.75ms 88.42%
Req/Sec 3.88k 517.01 22.61k 96.20%
1846019 requests in 30.09s, 199.06MB read
Requests/sec: 61357.23
Transfer/sec: 6.62MB
```
### jersey-jetty
```
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c100 -d30s http://127.0.0.1:8080/hello
Running 30s test @ http://127.0.0.1:8080/hello
16 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 4.09ms 8.88ms 163.37ms 93.57%
Req/Sec 3.51k 675.65 8.22k 72.92%
1677456 requests in 30.10s, 259.16MB read
Requests/sec: 55721.64
Transfer/sec: 8.61MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c200 -d30s http://127.0.0.1:8080/hello
Running 30s test @ http://127.0.0.1:8080/hello
16 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.66ms 11.76ms 216.25ms 94.88%
Req/Sec 3.72k 769.93 12.15k 78.25%
1777091 requests in 30.10s, 274.55MB read
Requests/sec: 59040.40
Transfer/sec: 9.12MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/hello
Running 30s test @ http://127.0.0.1:8080/hello
16 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 8.70ms 4.85ms 221.85ms 74.93%
Req/Sec 3.61k 436.24 10.79k 83.47%
1727962 requests in 30.09s, 266.96MB read
Requests/sec: 57420.08
Transfer/sec: 8.87MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c1000 -d30s http://127.0.0.1:8080/hello
Running 30s test @ http://127.0.0.1:8080/hello
16 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 16.38ms 7.79ms 115.97ms 77.13%
Req/Sec 3.80k 387.32 10.29k 75.07%
1817317 requests in 30.08s, 280.77MB read
Requests/sec: 60419.20
Transfer/sec: 9.33MB
```
### resteasy-netty https://github.com/resteasy/Resteasy/tree/master/jaxrs/server-adapters/resteasy-netty4
```
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c100 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.55ms 1.79ms 39.29ms 88.35%
Req/Sec 5.17k 473.68 16.08k 82.22%
2470498 requests in 30.10s, 235.61MB read
Requests/sec: 82078.17
Transfer/sec: 7.83MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c200 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.72ms 2.68ms 212.44ms 86.44%
Req/Sec 5.16k 536.58 10.62k 89.71%
2460323 requests in 30.10s, 234.63MB read
Requests/sec: 81742.81
Transfer/sec: 7.80MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.14ms 4.29ms 218.98ms 65.61%
Req/Sec 5.32k 399.82 13.75k 85.94%
2546559 requests in 30.10s, 242.86MB read
Requests/sec: 84604.20
Transfer/sec: 8.07MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c1000 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 11.73ms 6.59ms 240.40ms 72.53%
Req/Sec 5.29k 735.57 24.29k 95.86%
2530059 requests in 30.09s, 241.29MB read
Requests/sec: 84077.04
Transfer/sec: 8.02MB
```
### resteasy-undertow https://github.com/resteasy/Resteasy/tree/master/jaxrs/server-adapters/resteasy-undertow
```
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c100 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.35ms 1.26ms 29.65ms 89.78%
Req/Sec 5.11k 482.19 13.41k 70.58%
2445424 requests in 30.10s, 319.50MB read
Requests/sec: 81245.94
Transfer/sec: 10.62MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c200 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.34ms 1.24ms 20.15ms 82.58%
Req/Sec 5.27k 402.57 10.10k 70.97%
2524874 requests in 30.10s, 329.88MB read
Requests/sec: 83896.30
Transfer/sec: 10.96MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.53ms 1.37ms 211.98ms 82.84%
Req/Sec 5.58k 468.63 12.95k 89.39%
2672701 requests in 30.10s, 349.20MB read
Requests/sec: 88808.18
Transfer/sec: 11.60MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c1000 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 10.71ms 4.21ms 222.46ms 94.80%
Req/Sec 5.63k 1.07k 20.80k 91.21%
2697266 requests in 30.09s, 352.41MB read
Requests/sec: 89646.47
Transfer/sec: 11.71MB
```
### Dropwizard
```
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c100 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 10.56ms 20.00ms 331.02ms 87.74%
Req/Sec 3.69k 1.02k 12.27k 70.18%
1764292 requests in 30.10s, 190.13MB read
Requests/sec: 58617.07
Transfer/sec: 6.32MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c200 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 12.31ms 24.45ms 373.46ms 89.65%
Req/Sec 3.73k 1.07k 11.42k 69.94%
1778938 requests in 30.10s, 191.71MB read
Requests/sec: 59104.61
Transfer/sec: 6.37MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 13.47ms 21.35ms 398.83ms 91.93%
Req/Sec 3.79k 1.00k 14.20k 68.85%
1815458 requests in 30.09s, 195.64MB read
Requests/sec: 60338.83
Transfer/sec: 6.50MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c1000 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 33.55ms 88.33ms 1.20s 95.32%
Req/Sec 3.75k 1.06k 13.18k 69.77%
1791296 requests in 30.09s, 193.04MB read
Requests/sec: 59534.43
Transfer/sec: 6.42MB
```
### spring boot 1.3.0.RELEASE
```
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c100 -d30s http://127.0.0.1:8080/hello
Running 30s test @ http://127.0.0.1:8080/hello
16 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.39ms 4.10ms 58.23ms 90.89%
Req/Sec 2.31k 301.34 6.31k 70.86%
1107622 requests in 30.10s, 162.87MB read
Requests/sec: 36799.74
Transfer/sec: 5.41MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c200 -d30s http://127.0.0.1:8080/hello
Running 30s test @ http://127.0.0.1:8080/hello
16 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.34ms 8.62ms 125.04ms 95.44%
Req/Sec 2.38k 263.37 6.62k 75.76%
1138849 requests in 30.09s, 167.46MB read
Requests/sec: 37847.67
Transfer/sec: 5.57MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/hello
Running 30s test @ http://127.0.0.1:8080/hello
16 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 12.99ms 5.43ms 123.32ms 82.28%
Req/Sec 2.43k 183.80 5.77k 76.53%
1161165 requests in 30.09s, 170.74MB read
Requests/sec: 38592.82
Transfer/sec: 5.67MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c1000 -d30s http://127.0.0.1:8080/hello
Running 30s test @ http://127.0.0.1:8080/hello
16 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 25.73ms 4.36ms 72.17ms 78.96%
Req/Sec 2.42k 177.95 6.94k 80.52%
1156937 requests in 30.10s, 170.11MB read
Requests/sec: 38436.42
Transfer/sec: 5.65MB
```
### native netty
```
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c100 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.45ms 2.65ms 46.81ms 90.93%
Req/Sec 8.30k 787.93 12.00k 72.23%
3976832 requests in 30.10s, 379.26MB read
Requests/sec: 132124.20
Transfer/sec: 12.60MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c200 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.03ms 2.78ms 208.05ms 90.77%
Req/Sec 8.60k 749.64 13.75k 73.19%
4118101 requests in 30.10s, 392.73MB read
Requests/sec: 136819.26
Transfer/sec: 13.05MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.83ms 3.33ms 47.72ms 88.67%
Req/Sec 9.49k 1.10k 40.84k 87.81%
4540119 requests in 30.10s, 432.98MB read
Requests/sec: 150848.85
Transfer/sec: 14.39MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c1000 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.51ms 4.04ms 223.29ms 67.61%
Req/Sec 9.88k 1.50k 37.86k 91.72%
4726224 requests in 30.10s, 450.73MB read
Requests/sec: 157019.56
Transfer/sec: 14.97MB
```
### resteasy-netty4
```
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c100 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.02ms 3.21ms 80.07ms 91.22%
Req/Sec 2.45k 253.41 7.26k 78.40%
1169843 requests in 30.10s, 131.65MB read
Requests/sec: 38868.78
Transfer/sec: 4.37MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c200 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.11ms 3.62ms 63.82ms 72.81%
Req/Sec 2.54k 231.56 8.90k 81.83%
1214528 requests in 30.10s, 136.68MB read
Requests/sec: 40350.45
Transfer/sec: 4.54MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 11.83ms 6.04ms 272.64ms 77.88%
Req/Sec 2.61k 532.48 10.15k 93.05%
1237327 requests in 30.10s, 139.24MB read
Requests/sec: 41110.09
Transfer/sec: 4.63MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c1000 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 21.91ms 9.22ms 305.95ms 80.44%
Req/Sec 2.59k 0.90k 13.48k 85.05%
1223592 requests in 30.09s, 137.70MB read
Requests/sec: 40663.64
Transfer/sec: 4.58MB
```
### Vert.x 3.2.1
```
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c100 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.66ms 4.62ms 62.15ms 87.53%
Req/Sec 5.96k 746.59 13.79k 71.94%
2851265 requests in 30.10s, 222.97MB read
Requests/sec: 94730.86
Transfer/sec: 7.41MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c200 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.50ms 6.72ms 328.68ms 91.33%
Req/Sec 5.86k 1.25k 35.44k 89.77%
2765198 requests in 30.10s, 216.24MB read
Requests/sec: 91869.80
Transfer/sec: 7.18MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.01ms 5.50ms 223.97ms 86.45%
Req/Sec 6.18k 770.53 22.22k 91.66%
2946029 requests in 30.10s, 230.38MB read
Requests/sec: 97880.51
Transfer/sec: 7.65MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c1000 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 10.59ms 6.59ms 225.84ms 62.30%
Req/Sec 6.04k 610.92 15.94k 89.73%
2891948 requests in 30.10s, 226.15MB read
Requests/sec: 96082.80
Transfer/sec: 7.51MB
```
### Go
```
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c100 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.12ms 7.10ms 131.22ms 90.98%
Req/Sec 7.25k 1.67k 15.54k 70.00%
3465942 requests in 30.04s, 423.09MB read
Requests/sec: 115388.10
Transfer/sec: 14.09MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c200 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 4.51ms 9.40ms 199.98ms 91.84%
Req/Sec 6.75k 1.28k 13.88k 69.83%
3225967 requests in 30.04s, 393.79MB read
Requests/sec: 107394.44
Transfer/sec: 13.11MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 13.11ms 23.94ms 394.80ms 89.51%
Req/Sec 7.08k 2.12k 64.25k 73.32%
3378959 requests in 30.09s, 412.47MB read
Requests/sec: 112292.01
Transfer/sec: 13.71MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c1000 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 33.20ms 62.20ms 908.16ms 89.62%
Req/Sec 7.17k 2.88k 16.91k 68.73%
3417812 requests in 30.04s, 417.21MB read
Requests/sec: 113775.80
Transfer/sec: 13.89MB
```
### go-restful (iris)
```
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c100 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.84ms 5.40ms 80.97ms 90.77%
Req/Sec 6.03k 1.65k 19.35k 75.03%
2885226 requests in 30.09s, 319.18MB read
Requests/sec: 95899.44
Transfer/sec: 10.61MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c200 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 4.90ms 7.72ms 104.81ms 87.61%
Req/Sec 6.61k 1.01k 15.55k 70.15%
3162116 requests in 30.07s, 349.81MB read
Requests/sec: 105175.35
Transfer/sec: 11.64MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/rest/hello
[root@ip-172-31-4-198 ~]# wrk -t16 -c500 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 500 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 14.58ms 23.04ms 278.81ms 86.94%
Req/Sec 6.90k 1.02k 12.04k 69.27%
3297379 requests in 30.03s, 364.78MB read
Requests/sec: 109786.38
Transfer/sec: 12.15MB
[smallnest@ip-xxx-xxx-xxx-xxx ~]# wrk -t16 -c1000 -d30s http://127.0.0.1:8080/rest/hello
Running 30s test @ http://127.0.0.1:8080/rest/hello
16 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 35.13ms 57.20ms 553.38ms 86.80%
Req/Sec 6.91k 1.05k 18.11k 70.85%
3309745 requests in 30.10s, 366.14MB read
Requests/sec: 109966.09
Transfer/sec: 12.17MB
```
================================================
FILE: act/.gitignore
================================================
*.iml
target
.idea
classes
*.log
*.DS_Store
*all.sql
tmp/
**/.act*
**/.classpath
**/.settings
**/.project
**/.settings/
store1/
test.mv.db
test.trace.db
act.pid
.workspace
*.geany
================================================
FILE: act/README.md
================================================
# Jax-RS-Performance-Comparison - ActFramework implementation
[ActFramework](https://github.com/actframework/actframework) is a Java based full stack framework, could be used to quickly develop MVC or RESTful service application.
## Requirements
You must have Java 7+ and maven to run this application.
## Run
To run this application in PROD mode, type `./run_prod`.
This application is configured to listen on port `8080`
## Test
To run end to end test, type `./run_e2e`
================================================
FILE: act/pom.xml
================================================
4.0.0benchmark.actrest-hello1.0-SNAPSHOTactorg.actframeworkact-starter-parent1.8.8.41.8benchmark.act.AppEntryorg.actframeworkact-e2e0.0.7
================================================
FILE: act/run_dev
================================================
#!/bin/sh
echo building ...
mvn -q compile act:run
================================================
FILE: act/run_dev.bat
================================================
echo building ...
mvn -q compile act:run
================================================
FILE: act/run_e2e
================================================
#!/bin/sh
echo building ...
mvn -q compile act:e2e
================================================
FILE: act/run_e2e.bat
================================================
echo building ...
mvn -q compile act:e2e
================================================
FILE: act/run_prod
================================================
#!/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
./run $*
================================================
FILE: act/src/main/java/benchmark/act/AppEntry.java
================================================
package benchmark.act;
import act.Act;
/**
* A simple hello world service 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")
public class AppEntry {
public static void main(String[] args) throws Exception {
Act.start();
}
}
================================================
FILE: act/src/main/resources/benchmark/act/.version
================================================
artifact=${project.artifactId}
version=${project.version}
build=${buildNumber}
================================================
FILE: act/src/main/resources/conf/app.properties
================================================
##############################################
# Application configuration
# act-1.8.8-RC8
##############################################
# When `api_doc` is enabled it can navigate to
# http://localhost:5460/~/apidoc
# 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
# `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=
# 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.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
# `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` set the `Access-Control-Expose-Headers` response header.
#
# Default value is `Content-Type, X-HTTP-Method-Override`
#cors.headers=
# `cors.headers.expose` set the `Access-Control-Expose-Headers` response header.
#
# Default value is empty.
#cors.headers.expose=
# `cors.headers.allowed` set the `Access-Control-Allow-Headers` response header.
#
# Default value is empty.
#cors.headers.allowed=
# `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
# `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=8080
# `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=
# `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=
# `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;...
# `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
#
# Defautl value: `TemplatePathResolver`
#resolver.template_path
# `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=
# `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=7cCKNhrzENbuyPtUIHaiYny2UmAwY00ww5l2yHC2K1AS8m06gJ97NjyREl27joUn
# `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.encrypted` 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.encrypted=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
# `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=
================================================
FILE: act/src/main/resources/conf/prod/app.properties
================================================
##############################################
# Application configuration for prod profile
# act-1.8.8-RC8
##############################################
act.secret=mHklV2nkYwkWAVuWRulJfkNnncZ4j3yvFoFzi9hfH94kmg0HM0ZcJxQoxM26vg3t
================================================
FILE: act/src/main/resources/conf/uat/app.properties
================================================
##############################################
# Application configuration for uat profile
# act-1.8.8-RC8
##############################################
act.secret=bHn8o3k7r9tKuCFgRFjKVUwVVxxUcZXRynuMWgzK0zBJUBeh6q9UQJh0cIXz0NUu
================================================
FILE: act/src/main/resources/e2e/scenarios.yml
================================================
Scenario(REST Hello Service):
description: a service says hello
interactions:
- description: send request to hello service without parameter
request:
method: GET
url: /rest/hello
response:
text: Hello world # response text must be "Hello world"
================================================
FILE: act/src/main/resources/logback.xml
================================================
true%date %highlight(%-5level) %cyan(%logger{5}@[%-4.30thread]) - %msg%ntrue%msg%nact.log%d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/act.%i.log.zip1102MBe2e.log%msg%nact-db.log%d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/act-db.%i.log.zip1102MBact-metric.log%d{yyyy-MM-dd_HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n/act-metric.%i.log.zip1102MB
================================================
FILE: act/src/main/resources/routes.conf
================================================
GET /rest/hello echo:Hello world
================================================
FILE: armeria/pom.xml
================================================
restful-servicescom.colobu1.0-SNAPSHOT../pom.xml4.0.0com.colobuarmeria1.0-SNAPSHOT4.1.0.CR70.97.00.9.3com.linecorp.armeriaarmeria${armeria.version}dtrotthttps://maven.davidtrott.com/repositoryorg.apache.maven.pluginsmaven-shade-plugin2.4.2true*:*META-INF/*.SFMETA-INF/*.DSAMETA-INF/*.RSApackageshadecom.colobu.armeria.Mainorg.codehaus.mojoexec-maven-plugin1.2.1javacom.colobu.armeria.Mainorg.apache.thrift.toolsmaven-thrift-plugin0.1.10thrift-sourcesgenerate-sourcescompilethrift-test-sourcesgenerate-test-sourcestestCompile
================================================
FILE: armeria/src/main/java/com/colobu/armeria/Main.java
================================================
package com.colobu.armeria;
import com.colobu.armeria.service.thrift.v1.HelloService;
import com.linecorp.armeria.common.SerializationFormat;
import com.linecorp.armeria.common.SessionProtocol;
import com.linecorp.armeria.server.Server;
import com.linecorp.armeria.server.ServerBuilder;
import com.linecorp.armeria.server.docs.DocService;
import com.linecorp.armeria.server.thrift.ThriftService;
import org.apache.thrift.TException;
import org.apache.thrift.async.AsyncMethodCallback;
public class Main {
public static void main(String[] args) {
HelloService.AsyncIface helloHandler = new HelloService.AsyncIface(){
@Override
public void hello(AsyncMethodCallback resultHandler) throws TException {
resultHandler.onComplete("Hello world");
}
};
ServerBuilder sb = new ServerBuilder();
sb.port(8080, SessionProtocol.HTTP);
sb.serviceAt("/hello", ThriftService.of(helloHandler, SerializationFormat.THRIFT_BINARY))
.serviceUnder("/docs/", new DocService());
Server server= sb.build();
server.start();
}
}
================================================
FILE: armeria/src/main/thrift/v1/main.thrift
================================================
namespace java com.colobu.armeria.service.thrift.v1
service HelloService {
string hello()
}
================================================
FILE: dropwizard/hello.yml
================================================
server:
type: default
rootPath: /rest/*
applicationConnectors:
- type: http
bindHost: 0.0.0.0
port: 8080
adminConnectors:
- type: http
bindHost: 127.0.0.1
port: 8081
logging:
level: INFO
loggers:
"com.colobu.rest.dropwizard": DEBUG
================================================
FILE: dropwizard/pom.xml
================================================
restful-servicescom.colobu1.0-SNAPSHOT../pom.xml4.0.0dropwizardjaxrs-commoncom.colobu${project.version}io.dropwizarddropwizard-core${dropwizard.version}org.apache.maven.pluginsmaven-shade-plugin2.4.2true*:*META-INF/*.SFMETA-INF/*.DSAMETA-INF/*.RSApackageshadecom.colobu.rest.dropwizard.Mainorg.apache.maven.pluginsmaven-jar-plugin2.4trueorg.codehaus.mojoexec-maven-plugin1.2.1javacom.colobu.rest.dropwizard.Mainserver${project.basedir}/hello.yml
================================================
FILE: dropwizard/src/main/java/com/colobu/rest/dropwizard/Main.java
================================================
package com.colobu.rest.dropwizard;
public class Main {
public static void main(String[] args) throws Exception {
new MyApplication().run(args);
}
}
================================================
FILE: dropwizard/src/main/java/com/colobu/rest/dropwizard/MyApplication.java
================================================
package com.colobu.rest.dropwizard;
import com.colobu.rest.jaxrs.HelloResource;
import com.colobu.rest.jaxrs.HelloResourceAsync;
import io.dropwizard.Application;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
public class MyApplication extends Application {
@Override
public String getName() {
return "rest";
}
@Override
public void initialize(Bootstrap bootstrap) {
// nothing to do yet
}
@Override
public void run(MyConfiguration myConfiguration, Environment environment) throws Exception {
environment.healthChecks().register("healthcheck", new MyHealthCheck());
environment.jersey().register(new HelloResource());
environment.jersey().register(new HelloResourceAsync());
}
}
================================================
FILE: dropwizard/src/main/java/com/colobu/rest/dropwizard/MyConfiguration.java
================================================
package com.colobu.rest.dropwizard;
import io.dropwizard.Configuration;
// add configuration if necessary.
public class MyConfiguration extends Configuration {
}
================================================
FILE: dropwizard/src/main/java/com/colobu/rest/dropwizard/MyHealthCheck.java
================================================
package com.colobu.rest.dropwizard;
import com.codahale.metrics.health.HealthCheck;
public class MyHealthCheck extends HealthCheck {
@Override
protected Result check() throws Exception {
//Result.unhealthy
return Result.healthy();
}
}
================================================
FILE: go/main.go
================================================
package main
import (
"log"
"net/http"
)
// There are some golang RESTful libraries and mux libraries but i use the simplest to test.
func main() {
http.HandleFunc("/rest/hello", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello world"))
})
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
================================================
FILE: go-fasthttp/main.go
================================================
package main
import (
"log"
"github.com/valyala/fasthttp"
)
func main() {
err := fasthttp.ListenAndServe(":8080", fastHTTPHandler)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
func fastHTTPHandler(ctx *fasthttp.RequestCtx) {
if string(ctx.Method()) == "GET" {
switch string(ctx.Path()) {
case "/rest/hello":
ctx.Write([]byte("Hello world"))
default:
ctx.Error("Unsupported path", fasthttp.StatusNotFound)
}
return
}
}
================================================
FILE: jaxrs-common/pom.xml
================================================
restful-servicescom.colobu1.0-SNAPSHOT../pom.xml4.0.0jaxrs-commonorg.jboss.spec.javax.ws.rsjboss-jaxrs-api_2.0_spec1.0.0.Finalprovided
================================================
FILE: jaxrs-common/src/main/java/com/colobu/rest/jaxrs/HelloResource.java
================================================
package com.colobu.rest.jaxrs;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/rest/hello")
public class HelloResource {
public HelloResource() {
System.out.println("HelloResource()");
}
@GET
@Produces(MediaType.TEXT_PLAIN)
public String helloAsync() {
return "Hello world";
}
}
================================================
FILE: jaxrs-common/src/main/java/com/colobu/rest/jaxrs/HelloResourceAsync.java
================================================
package com.colobu.rest.jaxrs;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.container.AsyncResponse;
import javax.ws.rs.container.Suspended;
import javax.ws.rs.core.MediaType;
@Path("/rest/helloAsync")
public class HelloResourceAsync {
private ExecutorService executor = Executors
.newFixedThreadPool(Integer.getInteger("com.colobu.rest.jaxrs.concurrency", 16));
public HelloResourceAsync() {
System.out.println("HelloResourceAsync()");
}
@GET
@Produces(MediaType.TEXT_PLAIN)
public void helloAsync(@Suspended final AsyncResponse response) {
executor.execute(() -> {
response.resume("Hello world");
});
}
}
================================================
FILE: jaxrs-common/src/main/java/com/colobu/rest/jaxrs/MyApplication.java
================================================
package com.colobu.rest.jaxrs;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
@ApplicationPath("")
public class MyApplication extends Application {
@Override
public Set> getClasses() {
return Collections.emptySet();
}
@Override
public Set