Skip to content

Commit 5b4678f

Browse files
support Java exporter in CI
1 parent f588929 commit 5b4678f

File tree

9 files changed

+274
-2
lines changed

9 files changed

+274
-2
lines changed

.github/workflows/daily.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,27 @@ jobs:
112112
- name: Integration tests
113113
run: |
114114
npm run test:integration-ruby
115+
integration-tests-java:
116+
runs-on: ubuntu-latest
117+
steps:
118+
- uses: actions/checkout@v4
119+
- name: Setup node.js
120+
uses: actions/setup-node@v4
121+
- name: Install
122+
run: |
123+
npm install
124+
- name: Build
125+
run: |
126+
npm run build
127+
- name: Install Java
128+
uses: actions/setup-java@v5
129+
with:
130+
distribution: temurin
131+
java-version: 21
132+
- name: Prepare for testing
133+
run: |
134+
npm run
135+
npm run test:setup-java
136+
- name: Integration tests
137+
run: |
138+
JAVA_ES_REQUEST_CONVERTER_JAR=/home/runner/work/request-converter/request-converter/tests/integration/.java-es-request-converter/build/libs/java-es-request-converter-1.0-SNAPSHOT.jar npm run test:integration-java

.github/workflows/website.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ jobs:
2626
cd demo
2727
npm install
2828
npm install .. --install-links
29+
rm -rf ../node_modules/java-caller
30+
rm -rf node_modules/java-caller
2931
npm run build
3032
cd ..
3133
cp -R docs demo/dist

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@
2525
"test:setup-javascript": "./tests/integration/run-javascript.sh",
2626
"test:setup-php": "./tests/integration/run-php.sh",
2727
"test:setup-ruby": "./tests/integration/run-ruby.sh",
28+
"test:setup-java": "./tests/integration/run-java.sh",
2829
"test:integration": "jest tests/integration",
2930
"test:integration-curl": "./scripts/test-format.sh curl",
3031
"test:integration-python": "./scripts/test-format.sh python",
3132
"test:integration-javascript": "./scripts/test-format.sh javascript",
3233
"test:integration-php": "./scripts/test-format.sh php",
3334
"test:integration-ruby": "./scripts/test-format.sh ruby",
35+
"test:integration-java": "./scripts/test-format.sh java",
3436
"test:example": "./scripts/test-example.sh",
3537
"fix": "npm run fix:lint && npm run fix:prettier",
3638
"fix:lint": "eslint src tests --fix --ignore-pattern tests/wasm/",
@@ -72,6 +74,7 @@
7274
"commander": "^12.1.0",
7375
"find-my-way-ts": "^0.1.2",
7476
"handlebars": "^4.7.8",
77+
"java-caller": "^4.2.1",
7578
"prettier": "^2.8.8"
7679
},
7780
"directories": {

src/convert.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { CurlExporter } from "./exporters/curl";
66
import { JavaScriptExporter } from "./exporters/javascript";
77
import { PHPExporter } from "./exporters/php";
88
import { RubyExporter } from "./exporters/ruby";
9+
import { JavaExporter } from "./exporters/java";
910
import util from "util";
1011

1112
const isBrowser = typeof window !== "undefined";
@@ -35,6 +36,7 @@ export type ConvertOptions = {
3536
* This interface defines the structure of a language exporter.
3637
*/
3738
export interface FormatExporter {
39+
available?(): boolean;
3840
check(requests: ParsedRequest[]): Promise<boolean>;
3941
convert(requests: ParsedRequest[], options: ConvertOptions): Promise<string>;
4042
}
@@ -44,9 +46,10 @@ const EXPORTERS: Record<string, FormatExporter> = {
4446
php: new PHPExporter(),
4547
python: new PythonExporter(),
4648
ruby: new RubyExporter(),
49+
java: new JavaExporter(),
4750
curl: new CurlExporter(),
4851
};
49-
const LANGUAGES = ["JavaScript", "PHP", "Python", "Ruby", "curl"];
52+
const LANGUAGES = ["JavaScript", "PHP", "Python", "Ruby", "Java", "curl"];
5053

5154
/**
5255
* Return the list of available export formats.
@@ -55,7 +58,16 @@ const LANGUAGES = ["JavaScript", "PHP", "Python", "Ruby", "curl"];
5558
* to use in the `convertRequests()` function.
5659
*/
5760
export function listFormats(): string[] {
58-
return LANGUAGES;
61+
return LANGUAGES.filter((lang) => {
62+
const exporter = EXPORTERS[lang.toLowerCase()];
63+
if (!exporter) {
64+
return false;
65+
}
66+
if (!exporter.available) {
67+
return true;
68+
}
69+
return exporter.available();
70+
});
5971
}
6072

6173
/**

src/exporters/java.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import { FormatExporter, ConvertOptions } from "../convert";
2+
import { ParsedRequest, JSONValue } from "../parse";
3+
import { Request } from "../metamodel";
4+
import { JavaCaller } from "java-caller";
5+
6+
type JavaRequest = {
7+
api?: string;
8+
params: Record<string, string | undefined>;
9+
query?: Record<string, string>;
10+
body: JSONValue;
11+
};
12+
13+
function getCodeGenParamNames(
14+
params: Record<string, string | undefined>,
15+
request: Request,
16+
) {
17+
for (const [key, value] of Object.entries(params)) {
18+
if (request?.path) {
19+
for (const prop of request.path) {
20+
if (prop.name === key && prop.codegenName !== undefined) {
21+
delete params[key];
22+
params[prop.codegenName] = value;
23+
}
24+
}
25+
}
26+
}
27+
return params;
28+
}
29+
30+
export class JavaExporter implements FormatExporter {
31+
available(): boolean {
32+
return !!process.env.JAVA_ES_REQUEST_CONVERTER_JAR;
33+
}
34+
35+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
36+
async check(requests: ParsedRequest[]): Promise<boolean> {
37+
// only return true if all requests are for Elasticsearch
38+
return requests
39+
.map((req) => req.service == "es")
40+
.reduce((prev, curr) => prev && curr, true);
41+
}
42+
43+
async convert(
44+
requests: ParsedRequest[],
45+
options: ConvertOptions,
46+
): Promise<string> {
47+
const javaRequests: JavaRequest[] = [];
48+
for (const request of requests) {
49+
if (request.request) {
50+
const correctParams = getCodeGenParamNames(
51+
request.params,
52+
request.request,
53+
);
54+
const body = request.body ?? {};
55+
56+
const javaRequest: JavaRequest = {
57+
api: request.api,
58+
params: correctParams,
59+
query: request.query,
60+
body: body,
61+
};
62+
javaRequests.push(javaRequest);
63+
}
64+
}
65+
66+
const args = [];
67+
args.push(JSON.stringify(javaRequests));
68+
args.push(options.complete ? "true" : "false");
69+
args.push(options.elasticsearchUrl ?? "");
70+
71+
// preparing the java caller class to call the java request converter jar
72+
const java = new JavaCaller({
73+
minimumJavaVersion: 21,
74+
jar: process.env.JAVA_ES_REQUEST_CONVERTER_JAR,
75+
});
76+
const { status, stdout, stderr } = await java.run(args);
77+
// error
78+
if (status) {
79+
throw new Error(stderr);
80+
}
81+
// success!
82+
return stdout;
83+
}
84+
}

src/java-caller.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
declare module "java-caller";

tests/integration/convert.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const TEST_FORMATS: Record<string, string> = {
1717
php: "php",
1818
curl: "sh",
1919
ruby: "rb",
20+
java: "java",
2021
};
2122

2223
interface SchemaExample {

tests/integration/java-app/pom.xml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>com.example</groupId>
7+
<artifactId>app</artifactId>
8+
<version>1.0-SNAPSHOT</version>
9+
10+
<name>app</name>
11+
<!-- FIXME change it to the project's website -->
12+
<url>http://www.example.com</url>
13+
14+
<properties>
15+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
16+
<maven.compiler.release>17</maven.compiler.release>
17+
</properties>
18+
19+
<dependencyManagement>
20+
<dependencies>
21+
<dependency>
22+
<groupId>org.junit</groupId>
23+
<artifactId>junit-bom</artifactId>
24+
<version>5.11.0</version>
25+
<type>pom</type>
26+
<scope>import</scope>
27+
</dependency>
28+
</dependencies>
29+
</dependencyManagement>
30+
31+
<dependencies>
32+
<dependency>
33+
<groupId>org.junit.jupiter</groupId>
34+
<artifactId>junit-jupiter-api</artifactId>
35+
<scope>test</scope>
36+
</dependency>
37+
<!-- Optionally: parameterized tests support -->
38+
<dependency>
39+
<groupId>org.junit.jupiter</groupId>
40+
<artifactId>junit-jupiter-params</artifactId>
41+
<scope>test</scope>
42+
</dependency>
43+
44+
<dependency>
45+
<groupId>co.elastic.clients</groupId>
46+
<artifactId>elasticsearch-java</artifactId>
47+
<version>9.2.0</version>
48+
</dependency>
49+
</dependencies>
50+
51+
<build>
52+
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
53+
<plugins>
54+
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
55+
<plugin>
56+
<artifactId>maven-clean-plugin</artifactId>
57+
<version>3.4.0</version>
58+
</plugin>
59+
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
60+
<plugin>
61+
<artifactId>maven-resources-plugin</artifactId>
62+
<version>3.3.1</version>
63+
</plugin>
64+
<plugin>
65+
<artifactId>maven-compiler-plugin</artifactId>
66+
<version>3.13.0</version>
67+
</plugin>
68+
<plugin>
69+
<artifactId>maven-surefire-plugin</artifactId>
70+
<version>3.3.0</version>
71+
</plugin>
72+
<plugin>
73+
<artifactId>maven-jar-plugin</artifactId>
74+
<version>3.4.2</version>
75+
</plugin>
76+
<plugin>
77+
<artifactId>maven-install-plugin</artifactId>
78+
<version>3.1.2</version>
79+
</plugin>
80+
<plugin>
81+
<artifactId>maven-deploy-plugin</artifactId>
82+
<version>3.1.2</version>
83+
</plugin>
84+
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
85+
<plugin>
86+
<artifactId>maven-site-plugin</artifactId>
87+
<version>3.12.1</version>
88+
</plugin>
89+
<plugin>
90+
<artifactId>maven-project-info-reports-plugin</artifactId>
91+
<version>3.6.1</version>
92+
</plugin>
93+
<plugin>
94+
<artifactId>maven-assembly-plugin</artifactId>
95+
<configuration>
96+
<archive>
97+
<manifest>
98+
<mainClass>com.example.App</mainClass>
99+
</manifest>
100+
</archive>
101+
<descriptorRefs>
102+
<descriptorRef>jar-with-dependencies</descriptorRef>
103+
</descriptorRefs>
104+
</configuration>
105+
</plugin>
106+
</plugins>
107+
</pluginManagement>
108+
</build>
109+
</project>

tests/integration/run-java.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/bash -x
2+
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
3+
CURRENT_DIR=$(pwd)
4+
BRANCH=$(jq -r .version package.json | grep -Eo "^[0-9]+\.[0-9]+")
5+
6+
if [[ "$1" == "" ]]; then
7+
# the `test:setup` command runs this script without arguments to initialize
8+
# the environment, so we first delete any previous one
9+
rm -rf $SCRIPT_DIR/.java-es-request-converter
10+
rm -rf $SCRIPT_DIR/.java
11+
fi
12+
13+
if [[ ! -d $SCRIPT_DIR/.java-es-request-converter ]]; then
14+
git clone [email protected]:l-trotta/java-es-request-converter $SCRIPT_DIR/.java-es-request-converter
15+
cd $SCRIPT_DIR/.java-es-request-converter
16+
./gradlew jar
17+
cd $CURRENT_DIR
18+
fi
19+
20+
if [[ ! -d $SCRIPT_DIR/.java ]]; then
21+
mkdir $SCRIPT_DIR/.java
22+
echo "Installing from branch $BRANCH."
23+
git clone -b "$BRANCH" --depth=1 "https://github.com/elastic/elasticsearch-java.git" $SCRIPT_DIR/.java ||
24+
(echo "Branch $BRANCH not found. Cloning main branch." &&
25+
git clone -b "main" --depth=1 "https://github.com/elastic/elasticsearch-java.git" $SCRIPT_DIR/.java)
26+
fi
27+
28+
if [[ "$1" != "" ]]; then
29+
cd $SCRIPT_DIR/java-app
30+
mkdir -p src/main/java/com/example
31+
cp $CURRENT_DIR/$1 src/main/java/com/example/App.java
32+
mvn clean compile assembly:single
33+
if [[ "$?" == "0" ]]; then
34+
java -jar target/app-1.0-SNAPSHOT-jar-with-dependencies.jar
35+
fi
36+
fi

0 commit comments

Comments
 (0)