├── .editorconfig
├── .github
├── settings.xml
└── workflows
│ ├── build.yml
│ ├── close_stale.yml
│ ├── codeql-analysis.yml
│ ├── release.yml
│ └── trigger-release.yml
├── .gitignore
├── .mvn
└── wrapper
│ ├── MavenWrapperDownloader.java
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── .travis_after_success.sh
├── LICENSE
├── README.md
├── maven_deploy_settings.xml
├── mvnw
├── mvnw.cmd
├── pom.xml
├── renovate.json
├── spotbugs.xml
└── src
├── main
├── java
│ └── io
│ │ └── dropwizard
│ │ └── jersey
│ │ └── protobuf
│ │ ├── Converters.java
│ │ ├── InvalidProtocolBufferExceptionMapper.java
│ │ ├── ProtobufBundle.java
│ │ ├── ProtocolBufferMediaType.java
│ │ └── ProtocolBufferMessageBodyProvider.java
└── proto
│ └── dropwizard.proto
└── test
├── java
└── io
│ └── dropwizard
│ └── jersey
│ └── protobuf
│ ├── ConvertersTest.java
│ ├── InvalidProtocolBufferExceptionMapperTest.java
│ └── ProtocolBufferMessageBodyProviderTest.java
└── proto
└── dropwizard.proto
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Configuration file for EditorConfig: http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_style = space
8 | indent_size = 4
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.properties]
13 | charset = latin1
14 |
15 | [travis.yml]
16 | indent_size = 2
17 | indent_style = space
18 |
19 | [*.md]
20 | trim_trailing_whitespace = false
21 |
--------------------------------------------------------------------------------
/.github/settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 | jcenter
23 | JCenter
24 | https://jcenter.bintray.com
25 | central
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Build
3 | # yamllint disable-line rule:truthy
4 | on:
5 | push:
6 | branches:
7 | - release/*
8 | pull_request:
9 | jobs:
10 | yamllint:
11 | uses: dropwizard/workflows/.github/workflows/yamllint.yml@main
12 | build:
13 | strategy:
14 | fail-fast: false
15 | matrix:
16 | java-version: ['11', '17', '21']
17 | uses: dropwizard/workflows/.github/workflows/maven.yml@main
18 | secrets: inherit
19 | with:
20 | java-version: ${{ matrix.java-version }}
21 |
--------------------------------------------------------------------------------
/.github/workflows/close_stale.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: "Close stale issues"
3 | # yamllint disable-line rule:truthy
4 | on:
5 | schedule:
6 | - cron: "0 0 * * *"
7 | jobs:
8 | stale:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
12 | with:
13 | repo-token: ${{ secrets.GITHUB_TOKEN }}
14 | # yamllint disable rule:line-length
15 | stale-issue-message: 'This issue is stale because it has been open 90 days with no activity. Remove the "stale" label or comment or this will be closed in 14 days.'
16 | stale-pr-message: 'This pull request is stale because it has been open 90 days with no activity. Remove the "stale" label or comment or this will be closed in 14 days.'
17 | # yamllint enable rule:line-length
18 | days-before-stale: 90
19 | days-before-close: 14
20 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: "CodeQL"
3 | # yamllint disable-line rule:truthy
4 | on:
5 | push:
6 | branches:
7 | - 2.1.x
8 | - 3.0.x
9 | - 4.0.x
10 | pull_request:
11 | # The branches below must be a subset of the branches above
12 | branches:
13 | - 2.1.x
14 | - 3.0.x
15 | - 4.0.x
16 | paths:
17 | - "**.java"
18 | - "pom.xml"
19 | schedule:
20 | - cron: '0 21 * * 1'
21 |
22 | jobs:
23 | CodeQL-Build:
24 | # yamllint disable rule:line-length
25 | # CodeQL runs on ubuntu-latest, windows-latest, and macos-latest
26 | runs-on: ubuntu-latest
27 |
28 | steps:
29 | - name: Checkout repository
30 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
31 |
32 | # Initializes the CodeQL tools for scanning.
33 | - name: Initialize CodeQL
34 | uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3
35 | # Override language selection by uncommenting this and choosing your languages
36 | # with:
37 | # languages: go, javascript, csharp, python, cpp, java
38 |
39 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
40 | # If this step fails, then you should remove it and run the build manually (see below).
41 | - name: Autobuild
42 | uses: github/codeql-action/autobuild@fca7ace96b7d713c7035871441bd52efbe39e27e # v3
43 |
44 | # ℹ️ Command-line programs to run using the OS shell.
45 | # 📚 https://git.io/JvXDl
46 |
47 | # ✏️ If the Autobuild fails above, remove it and uncomment the following
48 | # three lines and modify them (or add more) to build your code if your
49 | # project uses a compiled language
50 |
51 | # - run: |
52 | # make bootstrap
53 | # make release
54 |
55 | - name: Perform CodeQL Analysis
56 | uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # v3
57 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Release
3 | # yamllint disable-line rule:truthy
4 | on:
5 | push:
6 | tags:
7 | - v*
8 | jobs:
9 | release:
10 | uses: dropwizard/workflows/.github/workflows/release.yml@main
11 | secrets: inherit
12 |
--------------------------------------------------------------------------------
/.github/workflows/trigger-release.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # yamllint disable rule:comments rule:line-length
3 | name: Trigger Release
4 | # yamllint disable-line rule:truthy
5 | on:
6 | workflow_dispatch:
7 | inputs:
8 | releaseVersion:
9 | description: Version of the next release
10 | required: true
11 | type: string
12 | developmentVersion:
13 | description: Version of the next development cycle (must end in "-SNAPSHOT")
14 | required: true
15 | type: string
16 | jobs:
17 | release:
18 | uses: dropwizard/workflows/.github/workflows/trigger-release.yml@main
19 | secrets: inherit
20 | with:
21 | releaseVersion: ${{ inputs.releaseVersion }}
22 | developmentVersion: ${{ inputs.developmentVersion }}
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .classpath
3 | .project
4 | .settings
5 | target
6 | release.properties
7 | .apt_generated_tests
8 |
--------------------------------------------------------------------------------
/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | import java.net.*;
21 | import java.io.*;
22 | import java.nio.channels.*;
23 | import java.util.Properties;
24 |
25 | public class MavenWrapperDownloader {
26 |
27 | /**
28 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
29 | */
30 | private static final String DEFAULT_DOWNLOAD_URL =
31 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
32 |
33 | /**
34 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
35 | * use instead of the default one.
36 | */
37 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
38 | ".mvn/wrapper/maven-wrapper.properties";
39 |
40 | /**
41 | * Path where the maven-wrapper.jar will be saved to.
42 | */
43 | private static final String MAVEN_WRAPPER_JAR_PATH =
44 | ".mvn/wrapper/maven-wrapper.jar";
45 |
46 | /**
47 | * Name of the property which should be used to override the default download url for the wrapper.
48 | */
49 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
50 |
51 | public static void main(String args[]) {
52 | System.out.println("- Downloader started");
53 | File baseDirectory = new File(args[0]);
54 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
55 |
56 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
57 | // wrapperUrl parameter.
58 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
59 | String url = DEFAULT_DOWNLOAD_URL;
60 | if(mavenWrapperPropertyFile.exists()) {
61 | FileInputStream mavenWrapperPropertyFileInputStream = null;
62 | try {
63 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
64 | Properties mavenWrapperProperties = new Properties();
65 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
66 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
67 | } catch (IOException e) {
68 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
69 | } finally {
70 | try {
71 | if(mavenWrapperPropertyFileInputStream != null) {
72 | mavenWrapperPropertyFileInputStream.close();
73 | }
74 | } catch (IOException e) {
75 | // Ignore ...
76 | }
77 | }
78 | }
79 | System.out.println("- Downloading from: : " + url);
80 |
81 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
82 | if(!outputFile.getParentFile().exists()) {
83 | if(!outputFile.getParentFile().mkdirs()) {
84 | System.out.println(
85 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
86 | }
87 | }
88 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
89 | try {
90 | downloadFileFromURL(url, outputFile);
91 | System.out.println("Done");
92 | System.exit(0);
93 | } catch (Throwable e) {
94 | System.out.println("- Error downloading");
95 | e.printStackTrace();
96 | System.exit(1);
97 | }
98 | }
99 |
100 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
101 | URL website = new URL(urlString);
102 | ReadableByteChannel rbc;
103 | rbc = Channels.newChannel(website.openStream());
104 | FileOutputStream fos = new FileOutputStream(destination);
105 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
106 | fos.close();
107 | rbc.close();
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dropwizard/dropwizard-protobuf/eee9dcb0cd2c8e71cf545101665f3e957c8bd8c3/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.9.10/apache-maven-3.9.10-bin.zip
--------------------------------------------------------------------------------
/.travis_after_success.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [[ "${TRAVIS_JDK_VERSION}" != "openjdk11" ]]; then
4 | echo "Skipping after_success actions for JDK version \"${TRAVIS_JDK_VERSION}\""
5 | exit
6 | fi
7 |
8 | if [[ -n ${TRAVIS_TAG} ]]; then
9 | echo "Skipping deployment for tag \"${TRAVIS_TAG}\""
10 | exit
11 | fi
12 |
13 | if [[ ${TRAVIS_BRANCH} != 'master' ]]; then
14 | echo "Skipping deployment for branch \"${TRAVIS_BRANCH}\""
15 | exit
16 | fi
17 |
18 | if [[ "$TRAVIS_PULL_REQUEST" = "true" ]]; then
19 | echo "Skipping deployment for pull request"
20 | exit
21 | fi
22 |
23 | ./mvnw -B deploy --settings maven_deploy_settings.xml -Dmaven.test.skip=true
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Dropwizard Protobuf
2 | ===================
3 | [](https://travis-ci.org/dropwizard/dropwizard-protobuf)
4 | [](https://maven-badges.herokuapp.com/maven-central/io.dropwizard.modules/dropwizard-protobuf/)
5 | [](https://github.com/dropwizard/dropwizard-protobuf/tree/master)
6 |
7 |
8 | `dropwizard-protobuf` is a [Jersey](https://eclipse-ee4j.github.io/jersey/) [JAX-RS Entity Provider](https://www.oracle.com/technical-resources/articles/java/jax-rs.html) that allows reading and writing messages in Google's [Protocol Buffers](https://developers.google.com/protocol-buffers/) format.
9 |
10 |
11 | Usage
12 | -----
13 |
14 | Just add the `ProtocolBundle` to your Dropwizard application inside the [`Application#initialize`](https://javadoc.io/static/io.dropwizard/dropwizard-project/2.0.7/io/dropwizard/Application.html#initialize-io.dropwizard.setup.Bootstrap-) method.
15 |
16 | ```java
17 | @Override
18 | public void initialize(Bootstrap bootstrap) {
19 | bootstrap.addBundle(new ProtobufBundle());
20 | }
21 | ```
22 |
23 | Maven Artifacts
24 | ---------------
25 |
26 | This project is available on Maven Central. To add it to your project simply add the following dependencies to your `pom.xml`:
27 |
28 | ```xml
29 |
30 | io.dropwizard.modules
31 | dropwizard-protobuf
32 | 2.0.7-1
33 |
34 | ```
35 |
36 | Support
37 | -------
38 |
39 | Please file bug reports and feature requests in [GitHub issues](https://github.com/dropwizard/dropwizard-protobuf/issues).
40 |
41 |
42 | License
43 | -------
44 |
45 | Copyright (c) 2020 Smoke Turner, LLC
46 |
47 | This library is licensed under the Apache License, Version 2.0.
48 |
49 | See http://www.apache.org/licenses/LICENSE-2.0.html or the LICENSE file in this repository for the full license text.
50 |
--------------------------------------------------------------------------------
/maven_deploy_settings.xml:
--------------------------------------------------------------------------------
1 |
18 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | sonatype-nexus-snapshots
30 | ${env.CI_DEPLOY_USERNAME}
31 | ${env.CI_DEPLOY_PASSWORD}
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | #
58 | # Look for the Apple JDKs first to preserve the existing behaviour, and then look
59 | # for the new JDKs provided by Oracle.
60 | #
61 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK ] ; then
62 | #
63 | # Apple JDKs
64 | #
65 | export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home
66 | fi
67 |
68 | if [ -z "$JAVA_HOME" ] && [ -L /System/Library/Java/JavaVirtualMachines/CurrentJDK ] ; then
69 | #
70 | # Apple JDKs
71 | #
72 | export JAVA_HOME=/System/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
73 | fi
74 |
75 | if [ -z "$JAVA_HOME" ] && [ -L "/Library/Java/JavaVirtualMachines/CurrentJDK" ] ; then
76 | #
77 | # Oracle JDKs
78 | #
79 | export JAVA_HOME=/Library/Java/JavaVirtualMachines/CurrentJDK/Contents/Home
80 | fi
81 |
82 | if [ -z "$JAVA_HOME" ] && [ -x "/usr/libexec/java_home" ]; then
83 | #
84 | # Apple JDKs
85 | #
86 | export JAVA_HOME=`/usr/libexec/java_home`
87 | fi
88 | ;;
89 | esac
90 |
91 | if [ -z "$JAVA_HOME" ] ; then
92 | if [ -r /etc/gentoo-release ] ; then
93 | JAVA_HOME=`java-config --jre-home`
94 | fi
95 | fi
96 |
97 | if [ -z "$M2_HOME" ] ; then
98 | ## resolve links - $0 may be a link to maven's home
99 | PRG="$0"
100 |
101 | # need this for relative symlinks
102 | while [ -h "$PRG" ] ; do
103 | ls=`ls -ld "$PRG"`
104 | link=`expr "$ls" : '.*-> \(.*\)$'`
105 | if expr "$link" : '/.*' > /dev/null; then
106 | PRG="$link"
107 | else
108 | PRG="`dirname "$PRG"`/$link"
109 | fi
110 | done
111 |
112 | saveddir=`pwd`
113 |
114 | M2_HOME=`dirname "$PRG"`/..
115 |
116 | # make it fully qualified
117 | M2_HOME=`cd "$M2_HOME" && pwd`
118 |
119 | cd "$saveddir"
120 | # echo Using m2 at $M2_HOME
121 | fi
122 |
123 | # For Cygwin, ensure paths are in UNIX format before anything is touched
124 | if $cygwin ; then
125 | [ -n "$M2_HOME" ] &&
126 | M2_HOME=`cygpath --unix "$M2_HOME"`
127 | [ -n "$JAVA_HOME" ] &&
128 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
129 | [ -n "$CLASSPATH" ] &&
130 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
131 | fi
132 |
133 | # For Migwn, ensure paths are in UNIX format before anything is touched
134 | if $mingw ; then
135 | [ -n "$M2_HOME" ] &&
136 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
137 | [ -n "$JAVA_HOME" ] &&
138 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
139 | # TODO classpath?
140 | fi
141 |
142 | if [ -z "$JAVA_HOME" ]; then
143 | javaExecutable="`which javac`"
144 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
145 | # readlink(1) is not available as standard on Solaris 10.
146 | readLink=`which readlink`
147 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
148 | if $darwin ; then
149 | javaHome="`dirname \"$javaExecutable\"`"
150 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
151 | else
152 | javaExecutable="`readlink -f \"$javaExecutable\"`"
153 | fi
154 | javaHome="`dirname \"$javaExecutable\"`"
155 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
156 | JAVA_HOME="$javaHome"
157 | export JAVA_HOME
158 | fi
159 | fi
160 | fi
161 |
162 | if [ -z "$JAVACMD" ] ; then
163 | if [ -n "$JAVA_HOME" ] ; then
164 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
165 | # IBM's JDK on AIX uses strange locations for the executables
166 | JAVACMD="$JAVA_HOME/jre/sh/java"
167 | else
168 | JAVACMD="$JAVA_HOME/bin/java"
169 | fi
170 | else
171 | JAVACMD="`which java`"
172 | fi
173 | fi
174 |
175 | if [ ! -x "$JAVACMD" ] ; then
176 | echo "Error: JAVA_HOME is not defined correctly." >&2
177 | echo " We cannot execute $JAVACMD" >&2
178 | exit 1
179 | fi
180 |
181 | if [ -z "$JAVA_HOME" ] ; then
182 | echo "Warning: JAVA_HOME environment variable is not set."
183 | fi
184 |
185 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
186 |
187 | # For Cygwin, switch paths to Windows format before running java
188 | if $cygwin; then
189 | [ -n "$M2_HOME" ] &&
190 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
191 | [ -n "$JAVA_HOME" ] &&
192 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
193 | [ -n "$CLASSPATH" ] &&
194 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
195 | fi
196 |
197 | # traverses directory structure from process work directory to filesystem root
198 | # first directory with .mvn subdirectory is considered project base directory
199 | find_maven_basedir() {
200 | local basedir=$(pwd)
201 | local wdir=$(pwd)
202 | while [ "$wdir" != '/' ] ; do
203 | if [ -d "$wdir"/.mvn ] ; then
204 | basedir=$wdir
205 | break
206 | fi
207 | wdir=$(cd "$wdir/.."; pwd)
208 | done
209 | echo "${basedir}"
210 | }
211 |
212 | # concatenates all lines of a file
213 | concat_lines() {
214 | if [ -f "$1" ]; then
215 | echo "$(tr -s '\n' ' ' < "$1")"
216 | fi
217 | }
218 |
219 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-$(find_maven_basedir)}
220 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
221 |
222 | # Provide a "standardized" way to retrieve the CLI args that will
223 | # work with both Windows and non-Windows executions.
224 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
225 | export MAVEN_CMD_LINE_ARGS
226 |
227 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
228 |
229 | exec "$JAVACMD" \
230 | $MAVEN_OPTS \
231 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
232 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
233 | ${WRAPPER_LAUNCHER} $MAVEN_CMD_LINE_ARGS
234 |
235 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
40 |
41 | @REM set %HOME% to equivalent of $HOME
42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
43 |
44 | @REM Execute a user defined script before this one
45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
49 | :skipRcPre
50 |
51 | @setlocal
52 |
53 | set ERROR_CODE=0
54 |
55 | @REM To isolate internal variables from possible post scripts, we use another setlocal
56 | @setlocal
57 |
58 | @REM ==== START VALIDATION ====
59 | if not "%JAVA_HOME%" == "" goto OkJHome
60 |
61 | echo.
62 | echo Error: JAVA_HOME not found in your environment. >&2
63 | echo Please set the JAVA_HOME variable in your environment to match the >&2
64 | echo location of your Java installation. >&2
65 | echo.
66 | goto error
67 |
68 | :OkJHome
69 | if exist "%JAVA_HOME%\bin\java.exe" goto init
70 |
71 | echo.
72 | echo Error: JAVA_HOME is set to an invalid directory. >&2
73 | echo JAVA_HOME = "%JAVA_HOME%" >&2
74 | echo Please set the JAVA_HOME variable in your environment to match the >&2
75 | echo location of your Java installation. >&2
76 | echo.
77 | goto error
78 |
79 | @REM ==== END VALIDATION ====
80 |
81 | :init
82 |
83 | set MAVEN_CMD_LINE_ARGS=%MAVEN_CONFIG% %*
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 |
121 | set WRAPPER_JAR=""%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar""
122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
123 |
124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CMD_LINE_ARGS%
125 | if ERRORLEVEL 1 goto error
126 | goto end
127 |
128 | :error
129 | set ERROR_CODE=1
130 |
131 | :end
132 | @endlocal & set ERROR_CODE=%ERROR_CODE%
133 |
134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
138 | :skipRcPost
139 |
140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
142 |
143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
144 |
145 | exit /B %ERROR_CODE%
146 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 | 4.0.0
21 |
22 | io.dropwizard.modules
23 | module-parent
24 | 4.0.4
25 |
26 |
27 |
28 | io.dropwizard.modules
29 | dropwizard-protobuf
30 | 4.0.7-SNAPSHOT
31 | jar
32 |
33 | Dropwizard Protocol Buffers Support
34 | Support for reading and writing Google Protocol Buffer objects
35 |
36 |
37 | 4.31.1
38 | dropwizard_dropwizard-protobuf
39 |
40 |
41 |
42 |
43 |
44 | com.google.protobuf
45 | protobuf-bom
46 | ${protobuf.version}
47 | pom
48 | import
49 |
50 |
51 |
52 |
53 |
54 |
55 | io.dropwizard
56 | dropwizard-core
57 |
58 |
59 | com.google.protobuf
60 | protobuf-java
61 |
62 |
63 | com.google.protobuf
64 | protobuf-java-util
65 |
66 |
67 | org.junit.jupiter
68 | junit-jupiter
69 | test
70 |
71 |
72 | org.assertj
73 | assertj-core
74 | test
75 |
76 |
77 |
78 |
79 |
80 |
81 | kr.motd.maven
82 | os-maven-plugin
83 | 1.7.1
84 |
85 |
86 |
87 |
88 |
89 | org.xolstice.maven.plugins
90 | protobuf-maven-plugin
91 | 0.6.1
92 | true
93 |
94 | com.google.protobuf:protoc:${protobuf.version}:exe:${os.detected.classifier}
95 |
96 |
97 |
98 |
99 | compile
100 | test-compile
101 |
102 |
103 |
104 |
105 |
106 | com.spotify.fmt
107 | fmt-maven-plugin
108 | 2.25
109 |
110 |
111 |
112 | format
113 |
114 | process-sources
115 |
116 |
117 |
118 |
119 | com.google.googlejavaformat
120 | google-java-format
121 | 1.24.0
122 |
123 |
124 |
125 |
126 | org.apache.maven.plugins
127 | maven-release-plugin
128 |
129 | v@{project.version}
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "local>dropwizard/renovate-config"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------
/spotbugs.xml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/main/java/io/dropwizard/jersey/protobuf/Converters.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2019 Smoke Turner, LLC (github@smoketurner.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.dropwizard.jersey.protobuf;
17 |
18 | import com.google.common.base.Converter;
19 | import com.google.protobuf.Timestamp;
20 | import com.google.protobuf.util.Durations;
21 | import com.google.protobuf.util.Timestamps;
22 | import java.text.ParseException;
23 | import java.time.Duration;
24 | import java.time.Instant;
25 | import java.time.OffsetDateTime;
26 | import java.time.ZoneOffset;
27 | import java.time.ZonedDateTime;
28 |
29 | public class Converters {
30 |
31 | public static final Converter toStringUTC =
32 | Converter.from(
33 | Timestamps::toString,
34 | s -> {
35 | try {
36 | return Timestamps.parse(s);
37 | } catch (ParseException e) {
38 | return null;
39 | }
40 | });
41 |
42 | public static final Converter toInstantUTC =
43 | Converter.from(
44 | t -> Instant.ofEpochSecond(t.getSeconds(), t.getNanos()),
45 | i -> Timestamp.newBuilder().setSeconds(i.getEpochSecond()).setNanos(i.getNano()).build());
46 |
47 | public static final Converter toOffsetDateTimeUTC =
48 | Converter.from(
49 | t -> toInstantUTC.convert(t).atOffset(ZoneOffset.UTC),
50 | o -> toInstantUTC.reverse().convert(o.toInstant()));
51 |
52 | public static final Converter toZonedDateTimeUTC =
53 | Converter.from(
54 | t -> toOffsetDateTimeUTC.convert(t).toZonedDateTime(),
55 | z -> toOffsetDateTimeUTC.reverse().convert(z.toOffsetDateTime()));
56 |
57 | public static final Converter toDuration =
58 | Converter.from(
59 | d -> Duration.ofSeconds(d.getSeconds(), d.getNanos()),
60 | d ->
61 | com.google.protobuf.Duration.newBuilder()
62 | .setSeconds(d.getSeconds())
63 | .setNanos(d.getNano())
64 | .build());
65 |
66 | public static final Converter toDurationString =
67 | Converter.from(
68 | Durations::toString,
69 | s -> {
70 | try {
71 | return Durations.parse(s);
72 | } catch (ParseException e) {
73 | return null;
74 | }
75 | });
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/io/dropwizard/jersey/protobuf/InvalidProtocolBufferExceptionMapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2019 Smoke Turner, LLC (github@smoketurner.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.dropwizard.jersey.protobuf;
17 |
18 | import com.google.protobuf.InvalidProtocolBufferException;
19 | import io.dropwizard.jersey.protobuf.protos.DropwizardProtos.ErrorMessage;
20 | import jakarta.ws.rs.core.Response;
21 | import jakarta.ws.rs.ext.ExceptionMapper;
22 | import jakarta.ws.rs.ext.Provider;
23 | import org.slf4j.Logger;
24 | import org.slf4j.LoggerFactory;
25 |
26 | @Provider
27 | public class InvalidProtocolBufferExceptionMapper
28 | implements ExceptionMapper {
29 | private static final Logger LOGGER =
30 | LoggerFactory.getLogger(InvalidProtocolBufferExceptionMapper.class);
31 |
32 | @Override
33 | public Response toResponse(InvalidProtocolBufferException exception) {
34 | final ErrorMessage message =
35 | ErrorMessage.newBuilder()
36 | .setMessage("Unable to process protocol buffer")
37 | .setCode(Response.Status.BAD_REQUEST.getStatusCode())
38 | .build();
39 |
40 | LOGGER.debug("Unable to process protocol buffer message", exception);
41 | return Response.status(Response.Status.BAD_REQUEST)
42 | .type(ProtocolBufferMediaType.APPLICATION_PROTOBUF_TYPE)
43 | .entity(message)
44 | .build();
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/io/dropwizard/jersey/protobuf/ProtobufBundle.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2019 Smoke Turner, LLC (github@smoketurner.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.dropwizard.jersey.protobuf;
17 |
18 | import io.dropwizard.core.Configuration;
19 | import io.dropwizard.core.ConfiguredBundle;
20 | import io.dropwizard.core.setup.Bootstrap;
21 | import io.dropwizard.core.setup.Environment;
22 |
23 | public class ProtobufBundle implements ConfiguredBundle {
24 |
25 | @Override
26 | public void initialize(Bootstrap> bootstrap) {
27 | // nothing to initialize
28 | }
29 |
30 | @Override
31 | public void run(C configuration, Environment environment) {
32 | environment.jersey().register(ProtocolBufferMessageBodyProvider.class);
33 | environment.jersey().register(InvalidProtocolBufferExceptionMapper.class);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/io/dropwizard/jersey/protobuf/ProtocolBufferMediaType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2019 Smoke Turner, LLC (github@smoketurner.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.dropwizard.jersey.protobuf;
17 |
18 | import jakarta.ws.rs.core.MediaType;
19 |
20 | public class ProtocolBufferMediaType extends MediaType {
21 |
22 | /** "application/x-protobuf" */
23 | public static final String APPLICATION_PROTOBUF = "application/x-protobuf";
24 |
25 | /** "application/x-protobuf" */
26 | public static final MediaType APPLICATION_PROTOBUF_TYPE =
27 | new MediaType("application", "x-protobuf");
28 |
29 | /** "application/x-protobuf-text-format" */
30 | public static final String APPLICATION_PROTOBUF_TEXT = "application/x-protobuf-text-format";
31 |
32 | /** "application/x-protobuf-text-format" */
33 | public static final MediaType APPLICATION_PROTOBUF_TEXT_TYPE =
34 | new MediaType("application", "x-protobuf-text-format");
35 |
36 | /** "application/x-protobuf-json-format" */
37 | public static final String APPLICATION_PROTOBUF_JSON = "application/x-protobuf-json-format";
38 |
39 | /** "application/x-protobuf-json-format" */
40 | public static final MediaType APPLICATION_PROTOBUF_JSON_TYPE =
41 | new MediaType("application", "x-protobuf-json-format");
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/io/dropwizard/jersey/protobuf/ProtocolBufferMessageBodyProvider.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2019 Smoke Turner, LLC (github@smoketurner.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.dropwizard.jersey.protobuf;
17 |
18 | import com.google.protobuf.InvalidProtocolBufferException;
19 | import com.google.protobuf.Message;
20 | import com.google.protobuf.TextFormat;
21 | import com.google.protobuf.util.JsonFormat;
22 | import jakarta.ws.rs.Consumes;
23 | import jakarta.ws.rs.Produces;
24 | import jakarta.ws.rs.WebApplicationException;
25 | import jakarta.ws.rs.core.MediaType;
26 | import jakarta.ws.rs.core.MultivaluedMap;
27 | import jakarta.ws.rs.ext.MessageBodyReader;
28 | import jakarta.ws.rs.ext.MessageBodyWriter;
29 | import jakarta.ws.rs.ext.Provider;
30 | import java.io.IOException;
31 | import java.io.InputStream;
32 | import java.io.InputStreamReader;
33 | import java.io.OutputStream;
34 | import java.lang.annotation.Annotation;
35 | import java.lang.reflect.Method;
36 | import java.lang.reflect.Type;
37 | import java.nio.charset.StandardCharsets;
38 | import java.util.Map;
39 | import java.util.concurrent.ConcurrentHashMap;
40 |
41 | /**
42 | * A Jersey provider which enables using Protocol Buffers to parse request entities into objects and
43 | * generate response entities from objects.
44 | */
45 | @Provider
46 | @Consumes({
47 | ProtocolBufferMediaType.APPLICATION_PROTOBUF,
48 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_TEXT,
49 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_JSON
50 | })
51 | @Produces({
52 | ProtocolBufferMediaType.APPLICATION_PROTOBUF,
53 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_TEXT,
54 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_JSON
55 | })
56 | public class ProtocolBufferMessageBodyProvider
57 | implements MessageBodyReader, MessageBodyWriter {
58 |
59 | private final Map, Method> methodCache = new ConcurrentHashMap<>();
60 |
61 | @Override
62 | public boolean isReadable(
63 | final Class> type,
64 | final Type genericType,
65 | final Annotation[] annotations,
66 | final MediaType mediaType) {
67 | return Message.class.isAssignableFrom(type);
68 | }
69 |
70 | @Override
71 | public Message readFrom(
72 | final Class type,
73 | final Type genericType,
74 | final Annotation[] annotations,
75 | final MediaType mediaType,
76 | final MultivaluedMap httpHeaders,
77 | final InputStream entityStream)
78 | throws IOException {
79 |
80 | final Method newBuilder =
81 | methodCache.computeIfAbsent(
82 | type,
83 | t -> {
84 | try {
85 | return t.getMethod("newBuilder");
86 | } catch (Exception e) {
87 | return null;
88 | }
89 | });
90 |
91 | final Message.Builder builder;
92 | try {
93 | builder = (Message.Builder) newBuilder.invoke(type);
94 | } catch (Exception e) {
95 | throw new WebApplicationException(e);
96 | }
97 |
98 | if (mediaType.getSubtype().contains("text-format")) {
99 | TextFormat.merge(new InputStreamReader(entityStream, StandardCharsets.UTF_8), builder);
100 | return builder.build();
101 | } else if (mediaType.getSubtype().contains("json-format")) {
102 | JsonFormat.parser()
103 | .ignoringUnknownFields()
104 | .merge(new InputStreamReader(entityStream, StandardCharsets.UTF_8), builder);
105 | return builder.build();
106 | } else {
107 | return builder.mergeFrom(entityStream).build();
108 | }
109 | }
110 |
111 | @Override
112 | public long getSize(
113 | final Message m,
114 | final Class> type,
115 | final Type genericType,
116 | final Annotation[] annotations,
117 | final MediaType mediaType) {
118 |
119 | if (mediaType.getSubtype().contains("text-format")) {
120 | final String formatted = m.toString();
121 | return formatted.getBytes(StandardCharsets.UTF_8).length;
122 | } else if (mediaType.getSubtype().contains("json-format")) {
123 | try {
124 | final String formatted = JsonFormat.printer().omittingInsignificantWhitespace().print(m);
125 | return formatted.getBytes(StandardCharsets.UTF_8).length;
126 | } catch (InvalidProtocolBufferException e) {
127 | // invalid protocol message
128 | return -1L;
129 | }
130 | }
131 |
132 | return m.getSerializedSize();
133 | }
134 |
135 | @Override
136 | public boolean isWriteable(
137 | final Class> type,
138 | final Type genericType,
139 | final Annotation[] annotations,
140 | final MediaType mediaType) {
141 | return Message.class.isAssignableFrom(type);
142 | }
143 |
144 | @Override
145 | public void writeTo(
146 | final Message m,
147 | final Class> type,
148 | final Type genericType,
149 | final Annotation[] annotations,
150 | final MediaType mediaType,
151 | final MultivaluedMap httpHeaders,
152 | final OutputStream entityStream)
153 | throws IOException {
154 |
155 | if (mediaType.getSubtype().contains("text-format")) {
156 | entityStream.write(m.toString().getBytes(StandardCharsets.UTF_8));
157 | } else if (mediaType.getSubtype().contains("json-format")) {
158 | final String formatted = JsonFormat.printer().omittingInsignificantWhitespace().print(m);
159 | entityStream.write(formatted.getBytes(StandardCharsets.UTF_8));
160 | } else {
161 | m.writeTo(entityStream);
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/src/main/proto/dropwizard.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto2";
2 |
3 | package dropwizard;
4 |
5 | option java_package = "io.dropwizard.jersey.protobuf.protos";
6 | option java_outer_classname = "DropwizardProtos";
7 | option optimize_for = SPEED;
8 |
9 | message ErrorMessage {
10 | required string message = 1;
11 | optional int32 code = 2 [default = 500];
12 | optional string details = 3;
13 | };
14 |
--------------------------------------------------------------------------------
/src/test/java/io/dropwizard/jersey/protobuf/ConvertersTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2019 Smoke Turner, LLC (github@smoketurner.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.dropwizard.jersey.protobuf;
17 |
18 | import static org.assertj.core.api.Assertions.assertThat;
19 |
20 | import com.google.protobuf.Timestamp;
21 | import java.time.Duration;
22 | import java.time.Instant;
23 | import java.time.OffsetDateTime;
24 | import java.time.ZonedDateTime;
25 | import org.junit.jupiter.api.Test;
26 |
27 | public class ConvertersTest {
28 |
29 | @Test
30 | public void testToString() {
31 | final Timestamp timestamp =
32 | Timestamp.newBuilder().setSeconds(1515761132).setNanos(123000000).build();
33 |
34 | final String actual = Converters.toStringUTC.convert(timestamp);
35 | final String expected = "2018-01-12T12:45:32.123Z";
36 |
37 | assertThat(actual).isEqualTo(expected);
38 | }
39 |
40 | @Test
41 | public void testFromString() {
42 | final String instant = "2018-01-12T12:45:32.123Z";
43 |
44 | final Timestamp actual = Converters.toStringUTC.reverse().convert(instant);
45 | final Timestamp expected =
46 | Timestamp.newBuilder().setSeconds(1515761132).setNanos(123000000).build();
47 |
48 | assertThat(actual).isEqualTo(expected);
49 | }
50 |
51 | @Test
52 | public void testToInstant() {
53 | final Timestamp timestamp =
54 | Timestamp.newBuilder().setSeconds(1515761132).setNanos(123000000).build();
55 |
56 | final Instant actual = Converters.toInstantUTC.convert(timestamp);
57 | final Instant expected = Instant.parse("2018-01-12T12:45:32.123Z");
58 |
59 | assertThat(actual).isEqualTo(expected);
60 | }
61 |
62 | @Test
63 | public void testFromInstant() {
64 | final Instant instant = Instant.parse("2018-01-12T12:45:32.123Z");
65 |
66 | final Timestamp actual = Converters.toInstantUTC.reverse().convert(instant);
67 | final Timestamp expected =
68 | Timestamp.newBuilder().setSeconds(1515761132).setNanos(123000000).build();
69 |
70 | assertThat(actual).isEqualTo(expected);
71 | }
72 |
73 | @Test
74 | public void testToOffsetDateTime() {
75 | final Timestamp timestamp =
76 | Timestamp.newBuilder().setSeconds(1515761132).setNanos(123000000).build();
77 |
78 | final OffsetDateTime actual = Converters.toOffsetDateTimeUTC.convert(timestamp);
79 | final OffsetDateTime expected = OffsetDateTime.parse("2018-01-12T12:45:32.123Z");
80 |
81 | assertThat(actual).isEqualTo(expected);
82 | }
83 |
84 | @Test
85 | public void testFromOffsetDateTime() {
86 | final OffsetDateTime offset = OffsetDateTime.parse("2018-01-12T12:45:32.123Z");
87 |
88 | final Timestamp actual = Converters.toOffsetDateTimeUTC.reverse().convert(offset);
89 | final Timestamp expected =
90 | Timestamp.newBuilder().setSeconds(1515761132).setNanos(123000000).build();
91 |
92 | assertThat(actual).isEqualTo(expected);
93 | }
94 |
95 | @Test
96 | public void testToZonedDateTime() {
97 | final Timestamp timestamp =
98 | Timestamp.newBuilder().setSeconds(1515761132).setNanos(123000000).build();
99 |
100 | final ZonedDateTime actual = Converters.toZonedDateTimeUTC.convert(timestamp);
101 | final ZonedDateTime expected = ZonedDateTime.parse("2018-01-12T12:45:32.123Z");
102 |
103 | assertThat(actual).isEqualTo(expected);
104 | }
105 |
106 | @Test
107 | public void testFromZonedDateTime() {
108 | final ZonedDateTime offset = ZonedDateTime.parse("2018-01-12T12:45:32.123Z");
109 |
110 | final Timestamp actual = Converters.toZonedDateTimeUTC.reverse().convert(offset);
111 | final Timestamp expected =
112 | Timestamp.newBuilder().setSeconds(1515761132).setNanos(123000000).build();
113 |
114 | assertThat(actual).isEqualTo(expected);
115 | }
116 |
117 | @Test
118 | public void testToDuration() {
119 | final com.google.protobuf.Duration duration =
120 | com.google.protobuf.Duration.newBuilder().setSeconds(20).setNanos(345_000_000).build();
121 |
122 | final Duration actual = Converters.toDuration.convert(duration);
123 | final Duration expected = Duration.parse("PT20.345S");
124 |
125 | assertThat(actual).isEqualTo(expected);
126 | }
127 |
128 | @Test
129 | public void testFromDuration() {
130 | final Duration duration = Duration.parse("PT20.345S");
131 |
132 | final com.google.protobuf.Duration actual = Converters.toDuration.reverse().convert(duration);
133 | final com.google.protobuf.Duration expected =
134 | com.google.protobuf.Duration.newBuilder().setSeconds(20).setNanos(345_000_000).build();
135 |
136 | assertThat(actual).isEqualTo(expected);
137 | }
138 |
139 | @Test
140 | public void testToDurationString() {
141 | final com.google.protobuf.Duration duration =
142 | com.google.protobuf.Duration.newBuilder().setSeconds(20).setNanos(345_000_000).build();
143 |
144 | final String actual = Converters.toDurationString.convert(duration);
145 | final String expected = "20.345s";
146 |
147 | assertThat(actual).isEqualTo(expected);
148 | }
149 |
150 | @Test
151 | public void testFromDurationString() {
152 | final String duration = "20.345s";
153 |
154 | final com.google.protobuf.Duration actual =
155 | Converters.toDurationString.reverse().convert(duration);
156 | final com.google.protobuf.Duration expected =
157 | com.google.protobuf.Duration.newBuilder().setSeconds(20).setNanos(345_000_000).build();
158 |
159 | assertThat(actual).isEqualTo(expected);
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/src/test/java/io/dropwizard/jersey/protobuf/InvalidProtocolBufferExceptionMapperTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2019 Smoke Turner, LLC (github@smoketurner.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.dropwizard.jersey.protobuf;
17 |
18 | import static org.assertj.core.api.Assertions.assertThat;
19 |
20 | import com.google.protobuf.InvalidProtocolBufferException;
21 | import jakarta.ws.rs.core.Response;
22 | import jakarta.ws.rs.core.Response.Status;
23 | import org.junit.jupiter.api.Test;
24 |
25 | public class InvalidProtocolBufferExceptionMapperTest {
26 |
27 | @Test
28 | public void testExceptionMapperReturnsBadRequestResponseWhenInvalidProtocolBufferException() {
29 | final InvalidProtocolBufferExceptionMapper mapper = new InvalidProtocolBufferExceptionMapper();
30 | final Response actual =
31 | mapper.toResponse(new InvalidProtocolBufferException("Something went wrong"));
32 |
33 | assertThat(actual.getStatus()).isEqualTo(Status.BAD_REQUEST.getStatusCode());
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/test/java/io/dropwizard/jersey/protobuf/ProtocolBufferMessageBodyProviderTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright © 2019 Smoke Turner, LLC (github@smoketurner.com)
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package io.dropwizard.jersey.protobuf;
17 |
18 | import static org.assertj.core.api.Assertions.assertThat;
19 | import static org.assertj.core.api.Assertions.failBecauseExceptionWasNotThrown;
20 |
21 | import com.google.protobuf.InvalidProtocolBufferException;
22 | import com.google.protobuf.Message;
23 | import io.dropwizard.jersey.protobuf.protos.DropwizardProtosTest.Example;
24 | import io.dropwizard.jersey.protobuf.protos.DropwizardProtosTest.Example2;
25 | import io.dropwizard.jersey.protobuf.protos.DropwizardProtosTest.ExampleNewVersion;
26 | import jakarta.ws.rs.core.MultivaluedHashMap;
27 | import java.io.ByteArrayInputStream;
28 | import java.io.ByteArrayOutputStream;
29 | import java.io.IOException;
30 | import java.lang.annotation.Annotation;
31 | import java.nio.charset.StandardCharsets;
32 | import org.glassfish.jersey.internal.util.collection.StringKeyIgnoreCaseMultivaluedMap;
33 | import org.junit.jupiter.api.Test;
34 |
35 | public class ProtocolBufferMessageBodyProviderTest {
36 | private final Annotation[] NONE = new Annotation[0];
37 | private final ProtocolBufferMessageBodyProvider provider =
38 | new ProtocolBufferMessageBodyProvider();
39 | private final Example example = Example.newBuilder().setId(1337L).build();
40 | private final Example2 example2 = Example2.newBuilder().setName("example").build();
41 | private final ExampleNewVersion exampleNewVersion =
42 | ExampleNewVersion.newBuilder().setId(1337L).setNewValidField("example").build();
43 |
44 | @Test
45 | public void readsDeserializableTypes() throws Exception {
46 | assertThat(provider.isReadable(Example.class, null, null, null)).isTrue();
47 | }
48 |
49 | @Test
50 | public void writesSerializableTypes() throws Exception {
51 | assertThat(provider.isWriteable(Example.class, null, null, null)).isTrue();
52 | }
53 |
54 | @Test
55 | public void deserializesRequestEntities() throws Exception {
56 | final Object actualExample1 =
57 | readFrom(provider, Example.class, new ByteArrayInputStream(example.toByteArray()));
58 | assertThat(actualExample1).isInstanceOf(Example.class);
59 | assertThat(((Example) actualExample1).getId()).isEqualTo(1337L);
60 |
61 | final Object actualExample2 =
62 | readFrom(provider, Example.class, new ByteArrayInputStream(example.toByteArray()));
63 | assertThat(actualExample2).isInstanceOf(Example.class);
64 | assertThat(((Example) actualExample2).getId()).isEqualTo(1337L);
65 |
66 | final Object actualExample3 =
67 | readFrom(provider, Example2.class, new ByteArrayInputStream(example2.toByteArray()));
68 | assertThat(actualExample3).isInstanceOf(Example2.class);
69 | assertThat(((Example2) actualExample3).getName()).isEqualTo("example");
70 |
71 | final Object actualExample4 =
72 | readFrom(
73 | provider,
74 | ExampleNewVersion.class,
75 | new ByteArrayInputStream(exampleNewVersion.toByteArray()));
76 | assertThat(actualExample4).isInstanceOf(ExampleNewVersion.class);
77 | assertThat(((ExampleNewVersion) actualExample4).getId()).isEqualTo(1337L);
78 | assertThat(((ExampleNewVersion) actualExample4).getNewValidField()).isEqualTo("example");
79 |
80 | final Object actualExample5 =
81 | readFrom(
82 | provider, Example.class, new ByteArrayInputStream(exampleNewVersion.toByteArray()));
83 | assertThat(actualExample5).isInstanceOf(Example.class);
84 | assertThat(((Example) actualExample5).getId()).isEqualTo(1337L);
85 | }
86 |
87 | private Object readFrom(
88 | ProtocolBufferMessageBodyProvider provider, Class> clazz, ByteArrayInputStream entity)
89 | throws IOException {
90 | final Object obj =
91 | provider.readFrom(
92 | (Class) clazz,
93 | clazz,
94 | NONE,
95 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_TYPE,
96 | new MultivaluedHashMap(),
97 | entity);
98 | return obj;
99 | }
100 |
101 | @Test
102 | public void deserializesRequestTextEntities() throws Exception {
103 | final Object actualExample1 =
104 | readStringFrom(
105 | provider,
106 | Example.class,
107 | new ByteArrayInputStream(example.toString().getBytes(StandardCharsets.UTF_8)));
108 | assertThat(actualExample1).isInstanceOf(Example.class);
109 | assertThat(((Example) actualExample1).getId()).isEqualTo(1337L);
110 |
111 | final Object actualExample2 =
112 | readFrom(provider, Example2.class, new ByteArrayInputStream(example2.toByteArray()));
113 | assertThat(actualExample2).isInstanceOf(Example2.class);
114 | assertThat(((Example2) actualExample2).getName()).isEqualTo("example");
115 | }
116 |
117 | private Object readStringFrom(
118 | ProtocolBufferMessageBodyProvider provider, Class> clazz, ByteArrayInputStream entity)
119 | throws IOException {
120 | final Object obj =
121 | provider.readFrom(
122 | (Class) clazz,
123 | clazz,
124 | NONE,
125 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_TEXT_TYPE,
126 | new MultivaluedHashMap(),
127 | entity);
128 | return obj;
129 | }
130 |
131 | @Test
132 | public void deserializesRequestJsonEntities() throws Exception {
133 | final Object actualExample1 =
134 | readJsonFrom(
135 | provider,
136 | Example.class,
137 | new ByteArrayInputStream("{\"id\":\"1337\"}".getBytes(StandardCharsets.UTF_8)));
138 | assertThat(actualExample1).isInstanceOf(Example.class);
139 | assertThat(((Example) actualExample1).getId()).isEqualTo(1337L);
140 |
141 | final Object actualExample2 =
142 | readJsonFrom(
143 | provider,
144 | Example2.class,
145 | new ByteArrayInputStream("{\"name\":\"example\"}".getBytes(StandardCharsets.UTF_8)));
146 | assertThat(actualExample2).isInstanceOf(Example2.class);
147 | assertThat(((Example2) actualExample2).getName()).isEqualTo("example");
148 |
149 | final Object actualExample3 =
150 | readJsonFrom(
151 | provider,
152 | ExampleNewVersion.class,
153 | new ByteArrayInputStream(
154 | "{\"id\":\"1337\", \"newValidField\":\"example\"}"
155 | .getBytes(StandardCharsets.UTF_8)));
156 | assertThat(actualExample3).isInstanceOf(ExampleNewVersion.class);
157 | assertThat(((ExampleNewVersion) actualExample3).getId()).isEqualTo(1337L);
158 | assertThat(((ExampleNewVersion) actualExample3).getNewValidField()).isEqualTo("example");
159 |
160 | final Object actualExample4 =
161 | readJsonFrom(
162 | provider,
163 | Example.class,
164 | new ByteArrayInputStream(
165 | "{\"id\":\"1337\", \"newValidField\":\"example\"}"
166 | .getBytes(StandardCharsets.UTF_8)));
167 | assertThat(actualExample4).isInstanceOf(Example.class);
168 | assertThat(((Example) actualExample4).getId()).isEqualTo(1337L);
169 | }
170 |
171 | private Object readJsonFrom(
172 | ProtocolBufferMessageBodyProvider provider, Class> clazz, ByteArrayInputStream entity)
173 | throws IOException {
174 | final Object obj =
175 | provider.readFrom(
176 | (Class) clazz,
177 | clazz,
178 | NONE,
179 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_JSON_TYPE,
180 | new MultivaluedHashMap(),
181 | entity);
182 | return obj;
183 | }
184 |
185 | @Test
186 | public void throwsInvalidProtocolBufferExceptionForMalformedRequestEntities() throws Exception {
187 | final ByteArrayInputStream entity =
188 | new ByteArrayInputStream("{\"id\":-1d".getBytes(StandardCharsets.UTF_8));
189 |
190 | try {
191 | final Class> klass = Example.class;
192 | provider.readFrom(
193 | (Class) klass,
194 | Example.class,
195 | NONE,
196 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_TYPE,
197 | new MultivaluedHashMap(),
198 | entity);
199 | failBecauseExceptionWasNotThrown(InvalidProtocolBufferException.class);
200 | } catch (InvalidProtocolBufferException e) {
201 | }
202 | }
203 |
204 | @Test
205 | public void serializesResponseEntities() throws Exception {
206 | final ByteArrayOutputStream output = new ByteArrayOutputStream();
207 |
208 | final Example example = Example.newBuilder().setId(1L).build();
209 |
210 | provider.writeTo(
211 | example,
212 | Example.class,
213 | Example.class,
214 | NONE,
215 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_TYPE,
216 | new StringKeyIgnoreCaseMultivaluedMap<>(),
217 | output);
218 |
219 | assertThat(output.toByteArray()).isEqualTo(example.toByteArray());
220 | }
221 |
222 | @Test
223 | public void serializesResponseTextEntities() throws Exception {
224 | final ByteArrayOutputStream output = new ByteArrayOutputStream();
225 |
226 | final Example example = Example.newBuilder().setId(1L).build();
227 |
228 | provider.writeTo(
229 | example,
230 | Example.class,
231 | Example.class,
232 | NONE,
233 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_TEXT_TYPE,
234 | new StringKeyIgnoreCaseMultivaluedMap<>(),
235 | output);
236 |
237 | assertThat(output.toString()).isEqualTo("id: 1\n");
238 | }
239 |
240 | @Test
241 | public void serializesResponseJsonEntities() throws Exception {
242 | final ByteArrayOutputStream output = new ByteArrayOutputStream();
243 |
244 | final Example example = Example.newBuilder().setId(1L).build();
245 |
246 | provider.writeTo(
247 | example,
248 | Example.class,
249 | Example.class,
250 | NONE,
251 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_JSON_TYPE,
252 | new StringKeyIgnoreCaseMultivaluedMap<>(),
253 | output);
254 |
255 | assertThat(output.toString()).isEqualTo("{\"id\":\"1\"}");
256 | }
257 |
258 | @Test
259 | public void responseEntitySize() throws Exception {
260 | final Example example = Example.newBuilder().setId(1L).build();
261 |
262 | final long size =
263 | provider.getSize(
264 | example,
265 | Example.class,
266 | Example.class,
267 | NONE,
268 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_TYPE);
269 |
270 | assertThat(size).isEqualTo(2L);
271 | }
272 |
273 | @Test
274 | public void responseTextEntitySize() throws Exception {
275 | final Example example = Example.newBuilder().setId(1L).build();
276 |
277 | final long size =
278 | provider.getSize(
279 | example,
280 | Example.class,
281 | Example.class,
282 | NONE,
283 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_TEXT_TYPE);
284 |
285 | assertThat(size).isEqualTo(6L);
286 | }
287 |
288 | @Test
289 | public void responseJsonEntitySize() throws Exception {
290 | final Example example = Example.newBuilder().setId(1L).build();
291 |
292 | final long size =
293 | provider.getSize(
294 | example,
295 | Example.class,
296 | Example.class,
297 | NONE,
298 | ProtocolBufferMediaType.APPLICATION_PROTOBUF_JSON_TYPE);
299 |
300 | assertThat(size).isEqualTo(10L);
301 | }
302 | }
303 |
--------------------------------------------------------------------------------
/src/test/proto/dropwizard.proto:
--------------------------------------------------------------------------------
1 | syntax = "proto3";
2 |
3 | package dropwizard;
4 |
5 | option java_package = "io.dropwizard.jersey.protobuf.protos";
6 | option java_outer_classname = "DropwizardProtosTest";
7 | option optimize_for = SPEED;
8 |
9 | message Example {
10 | int64 id = 1;
11 | };
12 |
13 | message Example2 {
14 | string name = 1;
15 | };
16 |
17 | message ExampleNewVersion {
18 | int64 id = 1;
19 | string newValidField = 2;
20 | };
21 |
--------------------------------------------------------------------------------