Skip to content

Commit 577e605

Browse files
committed
Merge remote-tracking branch 'origin/JsonSchema-Schema-mapping' into JsonSchema-Schema-mapping
2 parents 42f1a90 + d174a59 commit 577e605

33 files changed

Lines changed: 1202 additions & 691 deletions

File tree

.github/workflows/release-build.yml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,16 @@ jobs:
101101
artifacts: "core/target/classes/com/predic8/membrane/core/config/json/membrane.schema.json,distribution/target/membrane-api-gateway-${{ steps.get_version.outputs.VERSION }}.zip,distribution/target/membrane-api-gateway-${{ steps.get_version.outputs.VERSION }}.zip.asc"
102102
token: ${{ secrets.PAT }}
103103

104-
- name: Trigger membrane api io pipeline
104+
- name: Trigger website pipeline on GitLab
105105
env:
106106
GITLAB_TRIGGER_TOKEN: ${{ secrets.GITLAB_TRIGGER_TOKEN }}
107107
run: |
108108
VERSION='${{ steps.get_version.outputs.VERSION }}'
109-
echo "Triggering GitLab pipeline for membrane-api.io with VERSION=${VERSION}"
110-
curl --request POST \
111-
--fail \
109+
curl -X POST --fail \
112110
--connect-timeout 10 \
113111
--max-time 30 \
114-
--form token="${GITLAB_TRIGGER_TOKEN}" \
115-
--form ref=main \
116-
--form "variables[MEMBRANE_VERSION]=${VERSION}" \
112+
-F token="${GITLAB_TRIGGER_TOKEN}" \
113+
-F ref=main \
114+
-F "variables[MEMBRANE_VERSION]=${VERSION}" \
117115
https://gitlab.predic8.de/api/v4/projects/prod%2Fmembrane-api.io/trigger/pipeline
118116

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77

88
<img src="docs/images/api-gateway-demo.gif" alt="Animated demo of Membrane API Gateway" width="800">
99

10-
Lightweight **API Gateway** for **REST**, **GraphQL** and **legacy SOAP Web Services**, easily extended with powerful plugins and Java.
10+
Lightweight **API Gateway** for **REST**, **GraphQL** and **legacy Web Services**, easily extended with powerful plugins.
1111

12-
Solve complex API requirements with simple configurations.
12+
Based on the Java platform, Membrane integrates smoothly with major enterprise technologies. Load tests show that Java provides an excellent foundation for high performance and scalability. On a 2021 MacBook Pro, Membrane handles more than 20,000 requests per second, supports up to 10,000 concurrent clients, and can host over 100,000 APIs on a single instance.
1313

14-
The following YAML configuration samples require Membrane version 7.0.0 or newer.
14+
The examples below demonstrate how to address a wide range of API Gateway requirements using simple configurations. Version **7.0.0 or newer** is required.
1515

1616
**Forwarding Requests from Port 2000 to a Backend:**
1717

@@ -580,7 +580,7 @@ When a JavaScript script returns a `Response` object as the last line of code, t
580580
The following example generates a JSON response and sends it directly to the client:
581581
582582
```yaml
583-
spec:
583+
api:
584584
port: 2000
585585
flow:
586586
- javascript:
@@ -731,7 +731,7 @@ api:
731731
...or into XML:
732732
733733
```yaml
734-
spec:
734+
api:
735735
port: 2000
736736
flow:
737737
- request:

annot/pom.xml

Lines changed: 48 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
1212
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
15-
--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
15+
-->
16+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
17+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
1618

17-
<modelVersion>4.0.0</modelVersion>
18-
<artifactId>service-proxy-annot</artifactId>
19-
<name>${project.artifactId}</name>
20-
<packaging>jar</packaging>
19+
<modelVersion>4.0.0</modelVersion>
20+
<artifactId>service-proxy-annot</artifactId>
21+
<name>${project.artifactId}</name>
22+
<packaging>jar</packaging>
2123

2224
<parent>
2325
<groupId>org.membrane-soa</groupId>
@@ -26,33 +28,15 @@
2628
<version>7.0.5-SNAPSHOT</version>
2729
</parent>
2830

29-
<dependencies>
30-
<dependency>
31-
<groupId>org.springframework</groupId>
32-
<artifactId>spring-beans</artifactId>
33-
</dependency>
34-
<dependency>
35-
<groupId>org.springframework</groupId>
36-
<artifactId>spring-context</artifactId>
37-
</dependency>
38-
<dependency>
39-
<groupId>org.junit.jupiter</groupId>
40-
<artifactId>junit-jupiter-api</artifactId>
41-
<scope>test</scope>
42-
</dependency>
43-
<dependency>
44-
<groupId>org.junit.jupiter</groupId>
45-
<artifactId>junit-jupiter-engine</artifactId>
46-
<scope>test</scope>
47-
</dependency>
48-
<dependency>
49-
<groupId>org.apache.logging.log4j</groupId>
50-
<artifactId>log4j-slf4j2-impl</artifactId>
51-
</dependency>
52-
<dependency>
53-
<groupId>org.apache.logging.log4j</groupId>
54-
<artifactId>log4j-core</artifactId>
55-
</dependency>
31+
<dependencies>
32+
<dependency>
33+
<groupId>org.springframework</groupId>
34+
<artifactId>spring-beans</artifactId>
35+
</dependency>
36+
<dependency>
37+
<groupId>org.springframework</groupId>
38+
<artifactId>spring-context</artifactId>
39+
</dependency>
5640
<dependency>
5741
<groupId>com.fasterxml.jackson.core</groupId>
5842
<artifactId>jackson-databind</artifactId>
@@ -73,6 +57,27 @@
7357
<version>2.0.0</version>
7458
</dependency>
7559

60+
<!-- Test dependencies -->
61+
<dependency>
62+
<groupId>org.apache.logging.log4j</groupId>
63+
<artifactId>log4j-slf4j2-impl</artifactId>
64+
<scope>test</scope>
65+
</dependency>
66+
<dependency>
67+
<groupId>org.apache.logging.log4j</groupId>
68+
<artifactId>log4j-core</artifactId>
69+
<scope>test</scope>
70+
</dependency>
71+
<dependency>
72+
<groupId>org.junit.jupiter</groupId>
73+
<artifactId>junit-jupiter-api</artifactId>
74+
<scope>test</scope>
75+
</dependency>
76+
<dependency>
77+
<groupId>org.junit.jupiter</groupId>
78+
<artifactId>junit-jupiter-engine</artifactId>
79+
<scope>test</scope>
80+
</dependency>
7681
<dependency>
7782
<groupId>org.hamcrest</groupId>
7883
<artifactId>hamcrest</artifactId>
@@ -81,15 +86,15 @@
8186
</dependency>
8287
</dependencies>
8388

84-
<build>
85-
<plugins>
86-
<plugin>
87-
<artifactId>maven-compiler-plugin</artifactId>
88-
<configuration>
89-
<!-- Disable annotation processing for ourselves. -->
90-
<compilerArgument>-proc:none</compilerArgument>
91-
</configuration>
92-
</plugin>
93-
</plugins>
94-
</build>
89+
<build>
90+
<plugins>
91+
<plugin>
92+
<artifactId>maven-compiler-plugin</artifactId>
93+
<configuration>
94+
<!-- Disable annotation processing for ourselves. -->
95+
<compilerArgument>-proc:none</compilerArgument>
96+
</configuration>
97+
</plugin>
98+
</plugins>
99+
</build>
95100
</project>

annot/src/main/java/com/predic8/membrane/annot/generator/JsonSchemaGenerator.java

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,28 @@
1313
limitations under the License. */
1414
package com.predic8.membrane.annot.generator;
1515

16-
import com.fasterxml.jackson.databind.node.*;
17-
import com.predic8.membrane.annot.*;
18-
import com.predic8.membrane.annot.generator.kubernetes.*;
16+
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
17+
import com.predic8.membrane.annot.ProcessingException;
18+
import com.predic8.membrane.annot.generator.kubernetes.AbstractGrammar;
1919
import com.predic8.membrane.annot.generator.kubernetes.model.*;
2020
import com.predic8.membrane.annot.model.*;
21-
import com.predic8.membrane.annot.model.doc.*;
22-
import org.jetbrains.annotations.*;
23-
24-
import javax.annotation.processing.*;
25-
import javax.lang.model.element.*;
26-
import javax.tools.*;
27-
import java.io.*;
28-
import java.util.*;
29-
import java.util.stream.*;
21+
import com.predic8.membrane.annot.model.doc.Doc;
22+
import org.jetbrains.annotations.NotNull;
23+
24+
import javax.annotation.processing.ProcessingEnvironment;
25+
import javax.lang.model.element.Element;
26+
import javax.lang.model.element.TypeElement;
27+
import javax.tools.FileObject;
28+
import java.io.BufferedWriter;
29+
import java.io.IOException;
30+
import java.util.ArrayList;
31+
import java.util.HashMap;
32+
import java.util.List;
33+
import java.util.Map;
3034

3135
import static com.predic8.membrane.annot.generator.kubernetes.model.SchemaFactory.*;
32-
import static com.predic8.membrane.annot.generator.util.SchemaGeneratorUtil.*;
33-
import static javax.tools.StandardLocation.*;
36+
import static com.predic8.membrane.annot.generator.util.SchemaGeneratorUtil.escapeJsonContent;
37+
import static javax.tools.StandardLocation.CLASS_OUTPUT;
3438

3539
/**
3640
* TODOs:
@@ -76,13 +80,20 @@ private void assemble(Model m, MainInfo main) throws IOException {
7680

7781
private void addTopLevelProperties(Model m, MainInfo main) {
7882
schema.additionalProperties(false);
79-
List<AbstractSchema<?>> kinds = main.getElements().values().stream()
83+
84+
var top = main.getElements().values().stream()
8085
.filter(e -> e.getAnnotation().topLevel())
81-
.map(e -> createTopLevelProperty(e, m))
82-
.collect(Collectors.toUnmodifiableList());
86+
.toList();
87+
88+
for (ElementInfo e : top) {
89+
String name = e.getAnnotation().name();
90+
String refName = "#/$defs/" + e.getXSDTypeName(m);
91+
schema.property(ref(name).ref(refName));
92+
}
8393

84-
if (!kinds.isEmpty())
85-
schema.oneOf(kinds);
94+
if (!top.isEmpty()) {
95+
schema.minProperties(1).maxProperties(1);
96+
}
8697
}
8798

8899
private AbstractSchema<?> createTopLevelProperty(ElementInfo e, Model m) {
@@ -93,6 +104,7 @@ private AbstractSchema<?> createTopLevelProperty(ElementInfo e, Model m) {
93104
schema.property(ref(name).ref(refName));
94105

95106
return object()
107+
.title(name)
96108
.additionalProperties(false)
97109
.property(ref(name)
98110
.ref(refName)
@@ -251,17 +263,18 @@ private void processMCChilds(Model m, MainInfo main, ElementInfo i, AbstractSche
251263
continue;
252264

253265
sos.add(object()
266+
.title(ei.getAnnotation().name())
254267
.additionalProperties(false)
255268
.property(ref(ei.getAnnotation().name())
256-
.ref("#/$defs/" + ei.getXSDTypeName(m))
257-
.required(true)));
269+
.ref("#/$defs/" + ei.getXSDTypeName(m))));
258270
}
259271
// Allow referencing a component instance directly on list-item level:
260272
// flow:
261273
// - $ref: ...
262274
sos.add(object()
275+
.title("componentRef")
263276
.additionalProperties(false)
264-
.property( string("$ref").required(true)));
277+
.property( string("$ref")));
265278
return sos;
266279
}
267280

@@ -377,17 +390,17 @@ private SchemaObject createComponentsMapParser(Model m, MainInfo main, ElementIn
377390
var variants = new ArrayList<SchemaObject>();
378391

379392
for (ElementInfo comp : main.getElements().values()) {
380-
if (!comp.getAnnotation().component())
381-
continue;
393+
if (!comp.getAnnotation().component()) continue;
394+
if (comp.getAnnotation().topLevel()) continue;
382395

383-
if (comp.getAnnotation().topLevel())
384-
continue;
396+
String n = comp.getAnnotation().name();
385397

386398
variants.add(object()
399+
.title(n)
387400
.additionalProperties(false)
388-
.property(ref(comp.getAnnotation().name())
389-
.ref("#/$defs/" + comp.getXSDTypeName(m))
390-
.required(true)));
401+
.minProperties(1)
402+
.property(ref(n)
403+
.ref("#/$defs/" + comp.getXSDTypeName(m))));
391404
}
392405
return variants;
393406
}

annot/src/main/java/com/predic8/membrane/annot/generator/kubernetes/model/AbstractSchema.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public abstract class AbstractSchema<T extends AbstractSchema<T>> implements ISc
2222

2323
protected static final JsonNodeFactory jnf = JsonNodeFactory.instance;
2424

25+
protected String title;
2526
protected String name;
2627
protected String type;
2728
protected String description;
@@ -63,6 +64,11 @@ public T required(boolean b) {
6364
return self();
6465
}
6566

67+
public T title(String title) {
68+
this.title = title;
69+
return self();
70+
}
71+
6672
public T name(String name) {
6773
this.name = name;
6874
return self();
@@ -84,8 +90,12 @@ public boolean isObject() {
8490

8591
@Override
8692
public ObjectNode json(ObjectNode node) {
93+
if (title != null && !title.isBlank())
94+
node.put("title", title);
95+
8796
if (type != null)
8897
node.put("type", type);
98+
8999
return node;
90100
}
91101
}

annot/src/main/java/com/predic8/membrane/annot/generator/kubernetes/model/Schema.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,10 @@
1313
limitations under the License. */
1414
package com.predic8.membrane.annot.generator.kubernetes.model;
1515

16-
import com.fasterxml.jackson.databind.*;
17-
import com.fasterxml.jackson.databind.node.*;
18-
import com.fasterxml.jackson.databind.util.*;
16+
import com.fasterxml.jackson.databind.node.ObjectNode;
1917

20-
import java.util.*;
18+
import java.util.ArrayList;
19+
import java.util.List;
2120

2221
import static com.predic8.membrane.annot.generator.kubernetes.model.SchemaFactory.OBJECT;
2322

annot/src/main/java/com/predic8/membrane/annot/generator/kubernetes/model/SchemaObject.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ public class SchemaObject extends AbstractSchema<SchemaObject> {
3131
private List<AbstractSchema<?>> allOf;
3232
private final Map<String, AbstractSchema<?>> patternProperties = new LinkedHashMap<>();
3333

34+
private Integer minProperties;
35+
private Integer maxProperties;
36+
3437
SchemaObject(String name) {
3538
super(name);
3639
type = OBJECT;
@@ -47,6 +50,9 @@ public class SchemaObject extends AbstractSchema<SchemaObject> {
4750
public ObjectNode json(ObjectNode node) {
4851
super.json(node);
4952

53+
if (minProperties != null) node.put("minProperties", minProperties);
54+
if (maxProperties != null) node.put("maxProperties", maxProperties);
55+
5056
if (!additionalProperties && isObject()) {
5157
node.put("additionalProperties", false);
5258
}
@@ -168,6 +174,9 @@ public SchemaObject allOf(List<AbstractSchema<?>> allOf) {
168174
return this;
169175
}
170176

177+
public SchemaObject minProperties(int n) { this.minProperties = n; return this; }
178+
public SchemaObject maxProperties(int n) { this.maxProperties = n; return this; }
179+
171180
public boolean hasProperty(String name) {
172181
return properties.stream().anyMatch(p -> name.equals(p.getName()));
173182
}

annot/src/test/java/com/predic8/membrane/annot/YAMLComponentsParsingTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ public void componentDefinitionWithNoComponentKeyError() {
211211
components:
212212
x: {}
213213
"""));
214-
assertSchemaErrorContains(ex, "required property", "not found");
214+
assertSchemaErrorContains(ex, "must have at least 1 properties");
215215
}
216216

217217
@Test

0 commit comments

Comments
 (0)