Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove dependency on Jackson via SmallRye - 1.x #1457

Merged
merged 30 commits into from
Mar 9, 2020
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
8137ec0
Custom SnakeYAML parser and serializer and supporting changes
tjquinno Nov 11, 2019
3f0894b
Update with concurrent changes
tjquinno Dec 10, 2019
21192c8
Incorporate concurrent changes
tjquinno Jan 23, 2020
fa6ee3c
Adopt SmallRye OpenAPI 1.1.21-SNAPSHOT (until they release 1.1.21)
tjquinno Feb 4, 2020
2168007
Add custom AnnotationScannerExtension to parse extensions; clean up c…
tjquinno Feb 5, 2020
b6fc4db
Fine-tune the plug-in uses to extract (and therefore process) just th…
tjquinno Feb 7, 2020
75b8ec5
Numerous changes to, among other things, suppress anchors and referen…
tjquinno Feb 22, 2020
b02b86b
Work around SnakeYAML and MP OpenAPI TCK bugs; various other improvem…
tjquinno Feb 24, 2020
58ed362
Remove 'rights reserved' clause from copyright notices of changed files
tjquinno Feb 24, 2020
5b71208
Concurrent changes
tjquinno Feb 24, 2020
95137df
Use presence of 'default' property in prop list of TypeDescription, r…
tjquinno Feb 24, 2020
8dbbb1a
Residual changes to move all default-property-handling logic to this …
tjquinno Feb 24, 2020
196de47
Move enum management from plug-in into this module; remove unneeded d…
tjquinno Feb 24, 2020
58dbb03
Remove SnakeYAML workaround (not needed); refine tag suppression to a…
tjquinno Feb 24, 2020
f1a25da
Remove unused code; add warning if openAPI TCK workaround doesn't qui…
tjquinno Feb 25, 2020
47f816b
Fix copyright, spotbugs, style errors
tjquinno Feb 25, 2020
e4d0674
Add comments
tjquinno Feb 27, 2020
c8fa49a
Some more tidying up
tjquinno Feb 28, 2020
18e97c1
Correct jackson-dataformat-yaml groupId in pom excludes
tjquinno Feb 28, 2020
01e8845
Merge with concurrent changes.
tjquinno Feb 28, 2020
1d661af
Respond to review comments
tjquinno Mar 3, 2020
24fd0d8
Remove unused import
tjquinno Mar 4, 2020
340ebd2
Incorporate review comments
tjquinno Mar 4, 2020
068f5d0
Update build-tools version to 1.2.0
tjquinno Mar 4, 2020
96c822c
Trivial change to trigger pipeline
tjquinno Mar 4, 2020
88edf0e
Add exclusion to keep JSON-B via jakarta out (the TCK uses Jackson)
tjquinno Mar 8, 2020
111a62d
Concurrent changes
tjquinno Mar 9, 2020
4e5dcbb
Fix missing quote marks around numeric key in example openapi yaml file
tjquinno Mar 9, 2020
b2639aa
Fix copyright error
tjquinno Mar 9, 2020
2c2183d
Old exclusion no longer needed; just the one for jakarta.json.bind-ap…
tjquinno Mar 9, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 103 additions & 11 deletions openapi/pom.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2019-2020 Oracle and/or its affiliates.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -14,26 +14,96 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.helidon</groupId>
<artifactId>helidon-project</artifactId>
<version>1.4.2-SNAPSHOT</version>
</parent>

<groupId>io.helidon.openapi</groupId>
<artifactId>helidon-openapi</artifactId>

<name>Helidon OpenAPI</name>

<description>
Helidon OpenAPI implementation
</description>

<packaging>jar</packaging>


<properties>
<openapi-interfaces-dir>${project.build.directory}/extracted-sources/openapi-interfaces</openapi-interfaces-dir>
<openapi-impls-dir>${project.build.directory}/extracted-sources/openapi-impls</openapi-impls-dir>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-openapi-interfaces</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<classifier>sources</classifier>
<failOnMissingClassifierArtifact>true</failOnMissingClassifierArtifact>
<outputDirectory>${openapi-interfaces-dir}</outputDirectory>
<includeGroupIds>org.eclipse.microprofile.openapi</includeGroupIds>
<includeArtifactIds>microprofile-openapi-api</includeArtifactIds>
<includes>org/eclipse/microprofile/openapi/models/**/*.java</includes>
</configuration>
</execution>
<execution>
<id>unpack-openapi-impls</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<classifier>sources</classifier>
<failOnMissingClassifierArtifact>true</failOnMissingClassifierArtifact>
<outputDirectory>${openapi-impls-dir}</outputDirectory>
<includeGroupIds>io.smallrye</includeGroupIds>
<includeArtifactIds>smallrye-open-api</includeArtifactIds>
<includes>io/smallrye/openapi/api/models/**/*.java</includes>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>io.helidon.build-tools</groupId>
<artifactId>snakeyaml-codegen-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-snakeyaml-parsing-helper</id>
<goals>
<goal>generate</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<outputClass>io.helidon.openapi.SnakeYAMLParserHelper</outputClass>
<interfacesConfig>
<inputDirectory>${openapi-interfaces-dir}</inputDirectory>
</interfacesConfig>
<implementationsConfig>
<inputDirectory>${openapi-impls-dir}</inputDirectory>
</implementationsConfig>
<implementationPrefix>io.smallrye</implementationPrefix>
<interfacePrefix>org.eclipse.microprofile.openapi</interfacePrefix>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.helidon.webserver</groupId>
Expand All @@ -42,11 +112,38 @@
<dependency>
<groupId>io.smallrye</groupId>
<artifactId>smallrye-open-api</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.helidon.media.jsonp</groupId>
<artifactId>helidon-media-jsonp-server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>yasson</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config</artifactId>
Expand Down Expand Up @@ -74,16 +171,11 @@
<artifactId>jersey-client</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.helidon.config</groupId>
<artifactId>helidon-config-yaml</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
104 changes: 104 additions & 0 deletions openapi/src/main/java/io/helidon/openapi/CustomConstructor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* Copyright (c) 2019-2020 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package io.helidon.openapi;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.microprofile.openapi.models.PathItem;
import org.eclipse.microprofile.openapi.models.Paths;
import org.eclipse.microprofile.openapi.models.callbacks.Callback;
import org.eclipse.microprofile.openapi.models.media.Content;
import org.eclipse.microprofile.openapi.models.media.MediaType;
import org.eclipse.microprofile.openapi.models.responses.APIResponse;
import org.eclipse.microprofile.openapi.models.responses.APIResponses;
import org.eclipse.microprofile.openapi.models.security.Scopes;
import org.eclipse.microprofile.openapi.models.security.SecurityRequirement;
import org.eclipse.microprofile.openapi.models.servers.ServerVariable;
import org.eclipse.microprofile.openapi.models.servers.ServerVariables;
import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.MappingNode;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.SequenceNode;

/**
* Specialized SnakeYAML constructor for modifying {@code Node} objects for OpenAPI types that extend {@code Map} to adjust the
* type of the child nodes of such nodes.
* <p>
* Several MicroProfile OpenAPI interfaces extend {@code Map}. For example, {@code Paths} extends {@code Map
* <String, PathItem>} and {@code SecurityRequirement} extends {@code Map<String, List<String>>}. When SnakeYAML builds the node
* corresponding to one of these types, it correctly creates each child node as a {@code MappingNode} but it assigns those
* child nodes a type of {@code Object} instead of the mapped type -- {@code PathItem} in the example above.
* </p>
* <p>
* This class customizes the preparation of the node tree in these situations by setting the types for the child nodes explicitly
* to the corresponding child type. In OpenAPI 1.1.2 there are two situations, depending on whether the mapped-to type is a
* {@code List} or not.
* </p>
* <p>
* The MicroProfile OpenAPI 2.0 versions of the interfaces no longer use this construct of an interface extending {@code Map}, so
* ideally we can remove this workaround when we adopt 2.0.
* </p>
*/
final class CustomConstructor extends Constructor {

// maps OpenAPI interfaces which extend Map<?, type> to the mapped-to type where that mapped-to type is NOT List
private static final Map<Class<?>, Class<?>> CHILD_MAP_TYPES = new HashMap<>();

// maps OpenAPI interfaces which extend Map<?, List<type>> to the type that appears in the list
private static final Map<Class<?>, Class<?>> CHILD_MAP_OF_LIST_TYPES = new HashMap<>();

static {
CHILD_MAP_TYPES.put(Paths.class, PathItem.class);
CHILD_MAP_TYPES.put(Callback.class, PathItem.class);
CHILD_MAP_TYPES.put(Content.class, MediaType.class);
CHILD_MAP_TYPES.put(APIResponses.class, APIResponse.class);
CHILD_MAP_TYPES.put(ServerVariables.class, ServerVariable.class);
CHILD_MAP_TYPES.put(Scopes.class, String.class);
CHILD_MAP_OF_LIST_TYPES.put(SecurityRequirement.class, String.class);
}

CustomConstructor(TypeDescription td) {
super(td);
}

@Override
protected void constructMapping2ndStep(MappingNode node, Map<Object, Object> mapping) {
Class<?> parentType = node.getType();
if (CHILD_MAP_TYPES.containsKey(parentType)) {
Class<?> childType = CHILD_MAP_TYPES.get(parentType);
node.getValue().forEach(tuple -> {
Node valueNode = tuple.getValueNode();
if (valueNode.getType() == Object.class) {
valueNode.setType(childType);
}
});
} else if (CHILD_MAP_OF_LIST_TYPES.containsKey(parentType)) {
Class<?> childType = CHILD_MAP_OF_LIST_TYPES.get(parentType);
node.getValue().forEach(tuple -> {
Node valueNode = tuple.getValueNode();
if (valueNode.getNodeId() == NodeId.sequence) {
SequenceNode seqNode = (SequenceNode) valueNode;
seqNode.setListType(childType);
}
});
}
super.constructMapping2ndStep(node, mapping);
}
}
Loading