Skip to content

Commit

Permalink
add YAML mapper to JAX-RS
Browse files Browse the repository at this point in the history
  • Loading branch information
hoegertn committed Sep 23, 2018
1 parent ec49d7b commit efea34b
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* lazy-loading and refresh for Cognito JWT keys
* add property provider for EC2 metadata service
* BREAKING: Migrate Swagger to OpenAPI
* add YAML mapper to JAX-RS

# Version 1.28
* Update dependencies
Expand Down
19 changes: 19 additions & 0 deletions jaxrs/src/main/java/de/taimos/dvalin/jaxrs/MapperFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.joda.JodaModule;

Expand All @@ -46,4 +48,21 @@ public static ObjectMapper createDefault() {
return m;
}

public static ObjectMapper createDefaultYaml() {
YAMLFactory factory = new YAMLFactory();
factory.disable(YAMLGenerator.Feature.WRITE_DOC_START_MARKER);
factory.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES);
factory.enable(YAMLGenerator.Feature.SPLIT_LINES);
factory.enable(YAMLGenerator.Feature.ALWAYS_QUOTE_NUMBERS_AS_STRINGS);
ObjectMapper m = new ObjectMapper(factory);
m.registerModule(new JodaModule());
m.registerModule(new GuavaModule());
m.setSerializationInclusion(Include.NON_NULL);
m.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
m.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
m.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
m.enable(MapperFeature.AUTO_DETECT_GETTERS);
return m;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import javax.annotation.Priority;
import javax.ws.rs.Consumes;
import javax.ws.rs.InternalServerErrorException;
import javax.ws.rs.Priorities;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
Expand All @@ -48,12 +49,13 @@
@Produces(MediaType.WILDCARD)
public class JacksonProvider implements MessageBodyReader<Object>, MessageBodyWriter<Object> {

private final ObjectMapper mapper = MapperFactory.createDefault();
private final ObjectMapper jsonMapper = MapperFactory.createDefault();
private final ObjectMapper yamlMapper = MapperFactory.createDefaultYaml();


@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return mediaType.getSubtype().equals("json") || mediaType.getSubtype().endsWith("+json");
return this.isJson(mediaType) || this.isYaml(mediaType);
}

@Override
Expand All @@ -63,20 +65,43 @@ public long getSize(Object t, Class<?> type, Type genericType, Annotation[] anno

@Override
public void writeTo(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
entityStream.write(this.mapper.writeValueAsBytes(t));
if (this.isYaml(mediaType)) {
entityStream.write(this.yamlMapper.writeValueAsBytes(t));
} else if (this.isJson(mediaType)) {
entityStream.write(this.jsonMapper.writeValueAsBytes(t));
} else {
throw new InternalServerErrorException("Mapping error");
}
}

@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return mediaType.getSubtype().equals("json") || mediaType.getSubtype().endsWith("+json");
return this.isJson(mediaType) || this.isYaml(mediaType);
}

@Override
public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
final ObjectMapper mapper;
if (this.isYaml(mediaType)) {
mapper = this.yamlMapper;
} else if (this.isJson(mediaType)) {
mapper = this.jsonMapper;
} else {
throw new InternalServerErrorException("Mapping error");
}

if (genericType == null) {
return this.mapper.readValue(entityStream, type);
return mapper.readValue(entityStream, type);
}
return this.mapper.readValue(entityStream, TypeFactory.defaultInstance().constructType(genericType));
return mapper.readValue(entityStream, TypeFactory.defaultInstance().constructType(genericType));
}

private boolean isYaml(MediaType mediaType) {
return mediaType.getSubtype().equals("yaml") || mediaType.getSubtype().endsWith("+yaml");
}

private boolean isJson(MediaType mediaType) {
return mediaType.getSubtype().equals("json") || mediaType.getSubtype().endsWith("+json");
}

}
27 changes: 13 additions & 14 deletions jaxrs/src/main/java/de/taimos/dvalin/jaxrs/swagger/ApiListing.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,12 @@
import javax.ws.rs.ext.Provider;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import de.taimos.daemon.DaemonProperties;
import de.taimos.dvalin.jaxrs.JaxRsComponent;
import de.taimos.dvalin.jaxrs.ServiceAnnotationClassesProvider;
import de.taimos.dvalin.jaxrs.SpringCXFProperties;
import io.swagger.v3.core.util.Yaml;
import io.swagger.v3.jaxrs2.Reader;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.models.OpenAPI;
Expand All @@ -62,15 +59,21 @@
@JaxRsComponent
public class ApiListing {

@Autowired
private ServiceAnnotationClassesProvider annotationProvider;
private final ServiceAnnotationClassesProvider annotationProvider;

private final AtomicReference<OpenAPI> swaggerCache = new AtomicReference<>();

@Autowired(required = false)
private OpenApiModification config;

private final AtomicReference<OpenAPI> swaggerCache = new AtomicReference<>();
@Autowired
public ApiListing(ServiceAnnotationClassesProvider annotationProvider) {
this.annotationProvider = annotationProvider;
}

private static final Logger LOGGER = LoggerFactory.getLogger(ApiListing.class);
@Autowired(required = false)
public void setConfig(OpenApiModification config) {
this.config = config;
}

protected synchronized OpenAPI scan() {
Set<Class<?>> classes = this.classes();
Expand Down Expand Up @@ -160,12 +163,8 @@ public Response getListingJson() {
@Operation(hidden = true)
public Response getListingYaml() {
OpenAPI openAPI = this.process();
try {
if (openAPI != null) {
return Response.ok(Response.Status.OK).entity(Yaml.mapper().writeValueAsString(openAPI)).type("application/yaml").build();
}
} catch (Exception e) {
LOGGER.error("Failed to create YAML", e);
if (openAPI != null) {
return Response.ok().entity(openAPI).type("application/yaml").build();
}
return Response.status(404).build();
}
Expand Down

0 comments on commit efea34b

Please sign in to comment.