Skip to content

Commit

Permalink
Remove dependency on Jackson via SmallRye - 1.x (#1457)
Browse files Browse the repository at this point in the history
  • Loading branch information
tjquinno authored Mar 9, 2020
1 parent dc6b595 commit a960f90
Show file tree
Hide file tree
Showing 18 changed files with 2,757 additions and 61 deletions.
4 changes: 2 additions & 2 deletions examples/openapi/src/main/resources/META-INF/openapi.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# 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 Down Expand Up @@ -51,7 +51,7 @@ paths:
summary: Example greeting message to update
value: New greeting message
responses:
200:
"200":
description: OK
content:
application/json: {}
Expand Down
4 changes: 2 additions & 2 deletions microprofile/tests/tck/tck-rest-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
<exclusions>
<exclusion>
<!-- TCK requires Jackson, not JSON-B -->
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-binding</artifactId>
<groupId>jakarta.json.bind</groupId>
<artifactId>jakarta.json.bind-api</artifactId>
</exclusion>
</exclusions>
</dependency>
Expand Down
107 changes: 99 additions & 8 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, 2020 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 Down Expand Up @@ -33,7 +33,76 @@
</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 +111,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 +170,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

0 comments on commit a960f90

Please sign in to comment.