org.ambraproject.wombat.service.remote.JsonService.java Source code

Java tutorial

Introduction

Here is the source code for org.ambraproject.wombat.service.remote.JsonService.java

Source

/*
 * Copyright (c) 2017 Public Library of Science
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

package org.ambraproject.wombat.service.remote;

import com.google.common.base.Preconditions;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import org.ambraproject.wombat.service.EntityNotFoundException;
import org.ambraproject.wombat.util.CacheKey;
import org.apache.http.client.methods.HttpUriRequest;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;

/**
 * Abstract class for services that query a ReST backend that returns JSON.
 */
public class JsonService {

    @Autowired
    protected Gson gson;

    public String serialize(Object object) {
        return gson.toJson(object);
    }

    /**
     * Send a ReST request and serialize the response to an object. The serialization is controlled by the {@link
     * org.ambraproject.wombat.config.RootConfiguration#gson()} bean.
     *
     * @param target       the REST request to make
     * @param responseType the object type into which to serialize the JSON response
     * @param <T>          the type of {@code responseClass}
     * @return the response, serialized from JSON into an object
     * @throws IOException             if there is an error connecting to the server
     * @throws NullPointerException    if either argument is null
     * @throws EntityNotFoundException if the object at the address does not exist
     */
    public <T> T requestObject(RemoteService<? extends Reader> remoteService, HttpUriRequest target,
            Type responseType) throws IOException {
        Preconditions.checkNotNull(responseType);
        try (Reader reader = remoteService.request(target)) {
            return deserializeStream(responseType, reader, target.getURI());
        }
    }

    public <T> T requestObject(RemoteService<? extends Reader> remoteService, HttpUriRequest target,
            Class<T> responseClass) throws IOException {
        return requestObject(remoteService, target, (Type) responseClass);
    }

    /**
     * Serialize an object either through a REST request or from the cache. If there is a cached value, and the REST
     * service does not indicate that the value has been modified since the value was inserted into the cache, return that
     * value. Else, query the service for JSON and deserialize it to an object as usual.
     *
     * @param cacheKey  the cache parameters object containing the cache key at which to retrieve and store the value
     * @param target       the request to make to the SOA service if the value is not cached
     * @param responseType the type of object to deserialize
     * @param <T>          the type of {@code responseClass}
     * @return the deserialized object
     * @throws IOException
     */
    public <T> T requestCachedObject(CachedRemoteService<? extends Reader> remoteService, CacheKey cacheKey,
            HttpUriRequest target, final Type responseType) throws IOException {
        Preconditions.checkNotNull(responseType);
        return remoteService.requestCached(cacheKey, target,
                (Reader reader) -> deserializeStream(responseType, reader, target.getURI()));
    }

    /**
     * Serialize the content of a stream to an object.
     *
     * @param responseType the object type into which to serialize the JSON code
     * @param reader       the source of the JSON code
     * @param source       an object whose {@code toString()} describes where the JSON code came from (for logging only)
     * @return the deserialized object
     * @throws IOException
     */
    private <T> T deserializeStream(Type responseType, Reader reader, Object source) throws IOException {
        T value;
        try {
            value = gson.fromJson(reader, responseType);
        } catch (JsonSyntaxException e) {
            String message = String.format("Could not deserialize %s from stream at: %s. Message: %s",
                    responseType.getTypeName(), source, e.getMessage());
            throw new ServiceResponseFormatException(message, e);
        }
        if (value == null) {
            String message = String.format("Could not deserialize %s from null/empty stream at: %s",
                    responseType.getTypeName(), source);
            throw new ServiceResponseFormatException(message);
        }
        return value;
    }

}