GxRest/GxJRS/Requests

From Gcube Wiki
Revision as of 05:07, 1 May 2018 by Manuele.simi (Talk | contribs) (Types of Requests)

Jump to: navigation, search

Introduction

Types of Requests

As of version 0.0.2, there are two types of requests, both implementing the org.gcube.common.gxrest.request.GXHTTP interface:

/**
 * HTTP methods for requests.
 * 
 * @author Manuele Simi (ISTI CNR)
 *
 */
interface GXHTTP {
 
	/**
	 * Sends the PUT request to the web application.
	 * @return the response
	 */
	GXInboundResponse put() throws Exception;
 
	/**
	 * Sends the DELETE request to the web application.
	 * @return the response
	 */
	GXInboundResponse delete() throws Exception;
 
	/**
	 * Sends the HEAD request to the web application.
	 * @return the response
	 */
	GXInboundResponse head() throws Exception;
 
	/**
	 * Sends the GET request to the web application.
	 * @return the response
	 */
	GXInboundResponse get() throws Exception;
 
	/**
	 * Sends the POST request to the web application.
	 * @return the response
	 * @throws Exception
	 */
	GXInboundResponse post() throws Exception;
 
}

The returned GXInboundResponse can be consumed as explained here.

GXHTTPRequest

This type of request is entirely based on plain HTTP. It does not require any other software than the standard Java java.net and java.io packages to work.

This is basic example that sends a Post request to create a new resource in the context collection:

import org.gcube.common.gxrest.response.inbound.GXInboundResponse;
import org.gcube.common.gxrest.request.GXHTTPRequest;
 
GXHTTPRequest request = GXHTTPRequest.newRequest("http://host:port/service/").from("GXRequestTest");
 
//prepare some parameters
String context ="json serialization (not shown)";
Map<String,String> queryParams = new WeakHashMap<>();
String DEFAULT_RR_URL = "url of resource registry to contact";
queryParams.put("rrURL", DEFAULT_RR_URL);
 
try {
	GXInboundResponse response = request.path("context")
	  .queryParams(queryParams).withBody(context).post();
} catch (Exception e) {
	e.printStackTrace();
	System.err.println("Failed to send a POST request");
}

GXWebTargetAdapterRequest

This type of request is also generic but it relies on a JAX-RS runtime implementation. It dynamically loads the first WebTarget available on the classpath and uses it for modeling and sending the request. The reference implementation for JAX-RS is named Jersey, but it is not included in Java SE. If you want to use this request you must explicitly add a JAR-RS implementation to your classpath.

This is basic example that sends a Post request to create a new resource:

import org.gcube.common.gxrest.response.inbound.GXInboundResponse;
import org.gcube.common.gxrest.request.GXWebTargetAdapterRequest;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
 
//...
GXWebTargetAdapterRequest request = 
        GXWebTargetAdapterRequest.newRequest("http://host:port/service/").from("GXRequestTest");
 
//prepare some parameters
String context ="json serialization (not shown)";
Map<String,String> queryParams = new WeakHashMap<>();
String DEFAULT_RR_URL = "url of resource registry to contact";
queryParams.put("rrURL", DEFAULT_RR_URL);
 
 
//send the request to the context resource's collection
GXInboundResponse response = request.path("context")
		.queryParams(queryParams).withEntity(Entity.entity(context, MediaType.APPLICATION_JSON)).post();

Overriding the security context

By default, the security token available in the current thread is attached to the request.

However, if there is the need to force a specific token to be used, this can be done by invoking the setSecurityToken() method on the request object:

GXWebTargetAdapterRequest request = 
        GXWebTargetAdapterRequest.newRequest("http://host:port/service/").from("GXRequestTest");
request.setSecurityToken("my token");

Registering JAX-RS components

The following example shows how to register an instance of a custom JAX-RS component (a feature in this case) to be instantiated and used in the scope of the request:

import javax.ws.rs.core.Feature;
 
public class MyFeature implements Feature {
 @Override
    public boolean configure(FeatureContext context) {
        boolean enabled = false;
 
         //decides if the feature is enabled...
 
        return enabled;
    }
}
 
GXWebTargetAdapterRequest request = 
        GXWebTargetAdapterRequest.newRequest("http://host:port/service/").from("GXRequestTest");
request.register(MyFeature.class)

A Feature is a special type of JAX-RS configuration meta-provider. Once a feature is registered, its configure() method is invoked during JAX-RS runtime configuration and bootstrapping phase allowing the feature to further configure the runtime context in which it has been registered.

How to integrate with the FeatherWeight Stack

If common-jaxrs-client is used to discover and call a remote service, gxRest can be integrated with the call.

This example shows how to extend the org.gcube.common.clients.Plugin and resolve the request in the delegate:

import javax.ws.rs.client.WebTarget;
import javax.xml.transform.dom.DOMResult;
import javax.xml.ws.EndpointReference;
import org.gcube.common.clients.Plugin;
 
import org.gcube.common.calls.jaxrs.GcubeService;
import org.gcube.common.calls.jaxrs.TargetFactory;
import org.gcube.common.clients.config.ProxyConfig;
import org.gcube.common.clients.delegates.ProxyDelegate;
import org.gcube.common.gxrest.request.GXWebTargetAdapterRequest;
 
import org.w3c.dom.Node;
 
public class ClassificationPlugin extends Plugin<GXWebTargetAdapterRequest,ClassificationClient> {
 
	public ClassificationPlugin() {
		super("species-products-discovery/gcube/service");
	}
 
	@Override
	public Exception convert(Exception e, ProxyConfig<?, ?> arg1) {
		return e;
	}
 
	@Override
	public ClassificationClient newProxy(ProxyDelegate<GXWebTargetAdapterRequest> delegate) {
		return new DefaultClassification(delegate);
	}
 
	@Override
	public GXWebTargetAdapterRequest resolve(EndpointReference epr, ProxyConfig<?, ?> config)
			throws Exception {
		/*DOMResult result = new DOMResult();
		epr.writeTo(result);
		Node node =result.getNode();
		Node child=node.getFirstChild();
		String address = child.getTextContent();
		GcubeService service = GcubeService.service().withName(Constants.CLASSIFICATION_QNAME).andPath("taxon");
		return TargetFactory.stubFor(service).at(address);*/
 
	}
}

And here it is an example how to override the Call object and delegate the call:

import org.gcube.common.clients.Call;
import org.gcube.common.clients.delegates.ProxyDelegate;
import org.gcube.common.gxrest.response.inbound.GXInboundResponse;
import org.gcube.common.gxrest.request.GXWebTargetAdapterRequest;
 
public class DefaultClassification implements ClassificationClient {
 
    private final ProxyDelegate<GXWebTargetAdapterRequest> delegate;
 
    public DefaultClassification(ProxyDelegate<GXWebTargetAdapterRequest> config){
        this.delegate = config;
    }
 
    @Override
    public AnyResponse getTaxonChildrenById(final String id)
            throws UnsupportedPluginException, UnsupportedCapabilityException, InvalidIdentifierException {
 
        Call<GXWebTargetAdapterRequest, MultiLocatorResponse> call = new Call<GXWebTargetAdapterRequest, MultiLocatorResponse>() {
            @Override
            public MultiLocatorResponse call(GXWebTargetAdapterRequest manager) throws Exception {
                GXInboundResponse response =  manager.path(“children”).path(id).get();
                if (response.hasGXError()) {
                    //manage the error (TODO: show how to fetch and throw exceptions
                }
                return response.readContentAs(MultiLocatorResponse.class);
            }
        };
        try {
            MultiLocatorResponse results = delegate.make(call);
            // consume the results
 
        }catch(Exception e) {
            throw new RuntimeException(e);
        }
    }
}