A small recipe application that demonstrates the simple usage of conjure tooling.
This example project uses the following tools and libraries, please consult their respective documentation for more information.
- conjure - IDL for defining APIs once and generating client/server interfaces in different languages.
- conjure-java-runtime - conjure libraries for HTTP&JSON-based RPC using Retrofit, Feign, OkHttp as clients and Jetty/Jersey as servers
- conjure-java - conjure generator for java clients and servers
- conjure-typescript - conjure generator for typescript clients
- gradle - a highly flexible build tool. Some of the gradle plugins applied are:
- gradle-conjure - a gradle plugin that contains tasks to generate conjure bindings.
- gradle-baseline - a gradle plugin for configuring code quality tools in builds and projects.
- dropwizard - a simple framework for building web services
-
recipe-example-api
- a sub-project that defines recipe-example APIs in Conjure and generates both java and typescript bindings.This is what the api project looks like:
├── recipe-example-api │ ├── build.gradle │ ├── recipe-example-api-jersey │ ├── recipe-example-api-objects │ ├── recipe-example-api-typescript │ └── src │ └── main │ └── conjure │ └── recipe-example-api.yml
- build.gradle - a gradle script that
- configures sub-projects with needed dependencies to generate java bindings. e.g.
recipe-example-api-jersey
- configures
publishTypescript
task to generate.npmrc
in the generated root folder,recipe-example-api-typescript/src
for publishing the generated npm module. - modifies the
conjure
extension to specify the package name under which the npm module will be published.
- configures sub-projects with needed dependencies to generate java bindings. e.g.
- recipe-example-api-jersey - the sub-project where all generated service interfaces live.
- recipe-example-api-objects - the sub-project where all generated object classes live.
- recipe-example-api-typescript - the sub-project where all generated typescript bindings live.
- src/main/conjure - directory containing conjure definition yml files where recipe APIs are defined, please refer to specification.md for more details.
- build.gradle - a gradle script that
-
recipe-example-server
- a dropwizard application project that uses conjure generated jersey binding for resource class implementationThis is what the server project looks like:
├── recipe-example-server │ ├── build.gradle │ ├── src │ │ ├── main/java │ │ └── test/java │ └── var │ └── conf │ └── recipes.yml
- build.gradle - configures the project with needed dependencies and applies the
gradle-conjure
andapplication plugins
, so we can run the server locally or in IDE. - src/main/java - source classes for the dropwizard application. e.g. RecipeBookResource.java class
implements
the generated Jersey interface. - test/main/java - test source classes for simple integration tests that uses generated jersey interface for client interaction.
- var/conf/recipes.yml - the dropwizard application configuration yml file
- build.gradle - configures the project with needed dependencies and applies the
-
build.gradle - the root level gradle script where a set of gradle plugins are configured, including gradle-conjure.
-
settings.gradle - the gradle settings file where all sub projects are configured.
-
versions.props - a property file of the nebula version recommender plugin with which we can specify versions of project dependencies, including conjure generators.
./gradlew tasks
for tasks available in this project../gradlew idea
for IntelliJ./gradlew eclipse
for Eclipse./gradlew run
for running the server or use IDE to debug it
To modify the existing bindings in this project:
- Make changes to the
recipe-example-api.yml
file - Run
./gradlew compileConjure
or a more specific task such as./gradlew compileConjureObjects
, to check if the changes compile - Or run
./gradlew idea
or./gradlew eclipse
to update the bindings for your IDE
To generate bindings for a new language. Note that currently gradle-conjure
plugin only supports generation of java, typescript, and python bindings.
- Add a new sub project under
recipe-example-api
by modifying thesettings.gradle
file.... include 'example-api:example-api-typescript' +include 'example-api:example-api-python'
- Optional: use the gradle script
configure
closure inrecipe-example-api/build.gradle
to configure project specific settings for the new sub project. - Specify conjure python dependency versions in versions.props
+com.palantir.conjure.python:* = 3.4.0
- run
./gradlew compileConjure
to generate new bindings for python.
Similar to how we add the conjure generation for python above, we can add a new project to generate java retrofit interfaces
- add a new sub project under
recipe-example-api
by modifying thesettings.gradle
file.... include 'example-api:example-api-typescript' +include 'recipe-example-api:recipe-example-api-retrofit'
- Optional: use the gradle script
configure
closure inrecipe-example-api/build.gradle
to configure project specific settings for the new sub project. - run
./gradlew compileConjureRetrofit
to generate new bindings for retrofit2.
Please see the following subsections for examples of writing recipe clients in different languages.
To dev against this recipe application, you can either run the server locally via ./gradlew run
or spin up a docker
container using the palantir/recipe-example-server:latest
image.
The tests in recipe-example-server/src/test/java
illustrate simple examples of how you would use a Conjure jaxrs client to interact with the application. E.g.
RecipeBookService recipeBook = JaxRsClient.create(
RecipeBookService.class,
UserAgent.of(Agent.of("test", "0.0.0")),
NoOpHostEventsSink.INSTANCE,
ClientConfigurations.of(ServiceConfiguration
.builder()
.addUris(String.format("http://localhost:%d/examples/api/", RULE.getLocalPort()))
.security(SslConfiguration.of(Paths.get(TRUSTSTORE_PATH)))
.build()));
Recipe recipe = recipeBook.getRecipe(recipeName);
Please refer to conjure-typescript-example for an example implementation.
/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\
/!\ Please do not use these certificates in prod! /!\
/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\/!\
The certificates presented with this server are an example so that the tests run in HTTPs. These were generated by following the steps below. All passwords are "changeit"
keytool -genkey -alias bmc -keyalg RSA -keystore keystore.jks -keysize 2048 -dname "CN=localhost,OU=AQ,O=AQ,C=AQ" -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -validity 3650
openssl req -new -x509 -keyout ca-key -out ca-cert
keytool -keystore KeyStore.jks -alias bmc -certreq -file cert-file
openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days 365 -CAcreateserial -passin pass:changeit
keytool -keystore KeyStore.jks -alias CARoot -import -file ca-cert
keytool -keystore KeyStore.jks -alias bmc -import -file cert-signed
keytool -keystore truststore.jks -alias bmc -import -file ca-cert