uk.org.openeyes.oink.itest.adapters.ITFacadeToProxy.java Source code

Java tutorial

Introduction

Here is the source code for uk.org.openeyes.oink.itest.adapters.ITFacadeToProxy.java

Source

/*******************************************************************************
 * OINK - Copyright (c) 2014 OpenEyes Foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package uk.org.openeyes.oink.itest.adapters;

import static org.ops4j.pax.exam.CoreOptions.maven;
import static org.ops4j.pax.exam.MavenUtils.asInProject;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.replaceConfigurationFile;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
import static org.junit.Assert.*;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URI;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.hl7.fhir.instance.model.AtomFeed;
import org.hl7.fhir.instance.model.ResourceType;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.ops4j.pax.exam.ExamSystem;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.TestContainer;
import org.ops4j.pax.exam.options.MavenArtifactUrlReference;
import org.ops4j.pax.exam.options.MavenUrlReference;
import org.ops4j.pax.exam.spi.PaxExamRuntime;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Bundle;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.rest.client.HttpBasicAuthInterceptor;
import ca.uhn.fhir.rest.client.IGenericClient;
import ca.uhn.fhir.rest.client.IRestfulClientFactory;
import uk.org.openeyes.oink.fhir.BundleParser;
import uk.org.openeyes.oink.it.ITSupport;

/**
 * 
 * Tests the intercompability of the standard Facade and the standard
 * Proxy adapter running on the same Karaf container.
 * 
 * The proxy adapter is bound to an OpenEyes instance
 * 
 * @author Oliver Wilkie
 */
public class ITFacadeToProxy {

    private static Properties facadeProps;
    private static Properties proxyProps;

    private static TestContainer examContainer;

    @BeforeClass
    public static void setUp() throws IOException, InterruptedException {

        facadeProps = ITSupport.getPropertiesBySystemProperty("it.facadeToProxy.config");

        proxyProps = ITSupport.getPropertiesBySystemProperty("it.proxy.config");

        // Start Pax Exam
        ExamSystem system = PaxExamRuntime.createServerSystem(config());
        examContainer = PaxExamRuntime.createContainer(system);
        examContainer.start();

        // TODO Fix - For some reason a large wait is required
        Thread.sleep(45000);
    }

    @AfterClass
    public static void tearDown() {
        examContainer.stop();
    }

    @Before
    public void before() throws InterruptedException {
        // Even though the bundles have started, the spring dm contexts may not
        // be started yet so we must wait
        Thread.sleep(15000);
    }

    @Test
    public void testCanGetMetadataOfOpenEyes() {

        String facadeUri = (String) facadeProps.get("facade.uri");

        // Create a context and get the client factory so it can be configured
        FhirContext ctx = new FhirContext();
        IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();

        // Create an HTTP Client Builder
        HttpClientBuilder builder = HttpClientBuilder.create();

        // This interceptor adds HTTP username/password to every request
        String username = (String) proxyProps.get("proxy.username");
        String password = (String) proxyProps.get("proxy.password");
        builder.addInterceptorFirst(new HttpBasicAuthInterceptor(username, password));

        builder.addInterceptorFirst(new HttpRequestInterceptor() {
            @Override
            public void process(HttpRequest req, HttpContext context) throws HttpException, IOException {
                req.addHeader("Accept", "application/json+fhir; charset=UTF-8");
            }
        });

        // Use the new HTTP client builder
        clientFactory.setHttpClient(builder.build());

        IGenericClient client = clientFactory.newGenericClient(facadeUri);

        Conformance c = client.conformance();

        assertNotNull(c);

    }

    @Test
    public void testGetPatients() {
        String facadeUri = (String) facadeProps.get("facade.uri");

        // Create a context and get the client factory so it can be configured
        FhirContext ctx = new FhirContext();
        IRestfulClientFactory clientFactory = ctx.getRestfulClientFactory();

        // Create an HTTP Client Builder
        HttpClientBuilder builder = HttpClientBuilder.create();

        // This interceptor adds HTTP username/password to every request
        String username = (String) proxyProps.get("proxy.username");
        String password = (String) proxyProps.get("proxy.password");
        builder.addInterceptorFirst(new HttpBasicAuthInterceptor(username, password));

        builder.addInterceptorFirst(new HttpRequestInterceptor() {
            @Override
            public void process(HttpRequest req, HttpContext context) throws HttpException, IOException {
                req.addHeader("Accept", "application/json+fhir; charset=UTF-8");
            }
        });

        // Use the new HTTP client builder
        clientFactory.setHttpClient(builder.build());

        IGenericClient client = clientFactory.newGenericClient(facadeUri);

        Bundle response = client.search().forResource(Patient.class).execute();

        assertNotNull(response);
        assertNotEquals(0, response.getEntries().size());

    }

    @Test
    public void testGetPractitioners() throws Exception {
        String facadeUri = (String) facadeProps.get("facade.uri");

        URIBuilder builder = new URIBuilder(facadeUri);
        URI uri = builder.setPath(builder.getPath() + "/Practitioner")
                .setParameter("_profile", "http://openeyes.org.uk/fhir/1.7.0/profile/Practitioner/Gp").build();

        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(uri);
        httpGet.addHeader("Accept", "application/json+fhir; charset=UTF-8");
        CloseableHttpResponse response1 = httpclient.execute(httpGet);

        assertEquals(200, response1.getStatusLine().getStatusCode());
        String json = null;
        try {
            HttpEntity entity1 = response1.getEntity();
            json = EntityUtils.toString(entity1);
        } finally {
            response1.close();
        }

        assertNotNull(json);

        BundleParser conv = new BundleParser();
        AtomFeed response = conv.fromJsonOrXml(json);

        assertNotEquals(0, response.getEntryList().size());
    }

    @Test
    public void testCreateAndDeletePractitioners() throws Exception {
        String facadeUri = (String) facadeProps.get("facade.uri");

        URIBuilder builder = new URIBuilder(facadeUri);
        URI uri = builder.setPath(builder.getPath() + "/Practitioner")
                .setParameter("_profile", "http://openeyes.org.uk/fhir/1.7.0/profile/Practitioner/Gp").build();

        System.out.println(uri.toString());

        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(uri);
        httpPost.addHeader("Accept", "application/json+fhir; charset=UTF-8");
        httpPost.addHeader("Category",
                "http://openeyes.org.uk/fhir/1.7.0/profile/Practitioner/Gp; scheme=\"http://hl7.org/fhir/tag/profile\"; label=\"\"");
        httpPost.addHeader("Content-Type", "application/json+fhir");
        InputStream is = getClass().getResourceAsStream("/example-messages/fhir/practitioner.json");

        StringWriter writer = new StringWriter();
        IOUtils.copy(is, writer);
        String theString = writer.toString();

        StringEntity isEntity = new StringEntity(theString);

        httpPost.setEntity(isEntity);

        CloseableHttpResponse response1 = httpclient.execute(httpPost);

        assertEquals(201, response1.getStatusLine().getStatusCode());

        // Note location header is the real end-server location not the facade
        // e.g. http://192.168.1.100/api/Practitioner/gp-4/_history/1401366763
        String locationHeader = response1.getHeaders("Location")[0].getValue();
        assertNotNull(locationHeader);

        String resourceId = extractResourceIdFromUri(locationHeader);
        assertNotNull(resourceId);

        URIBuilder builder2 = new URIBuilder(facadeUri);
        URI uri2 = builder2.setPath(builder2.getPath() + "/Practitioner/" + resourceId)
                .setParameter("_profile", "http://openeyes.org.uk/fhir/1.7.0/profile/Practitioner/Gp").build();

        HttpDelete httpDelete = new HttpDelete(uri2);
        CloseableHttpResponse response2 = httpclient.execute(httpDelete);
        assertEquals(204, response2.getStatusLine().getStatusCode());
    }

    private String extractResourceIdFromUri(String locationUri) {

        String[] parts = locationUri.split("/");
        for (int i = 0; i < parts.length - 1; i++) {
            try {
                ResourceType res = ResourceType.valueOf(parts[i]);
                return parts[i + 1];
            } catch (Exception ex) {
                continue;
            }
        }
        return null;
    }

    public static Option[] config() {
        MavenArtifactUrlReference karafUrl = maven().groupId("uk.org.openeyes.oink.karaf").artifactId("distro")
                .version(asInProject()).type("tar.gz");

        MavenUrlReference oinkFeaturesRepo = maven().groupId("uk.org.openeyes.oink.karaf")
                .artifactId("oink-features").version(asInProject()).type("xml").classifier("features");

        return new Option[] {
                // Provision and launch a container based on a distribution of
                // Karaf (Apache ServiceMix).
                karafDistributionConfiguration().frameworkUrl(karafUrl).unpackDirectory(new File("target/pax"))
                        .useDeployFolder(false),
                // It is really nice if the container sticks around after the
                // test so you can check the contents
                // of the data directory when things go wrong.
                keepRuntimeFolder(),
                // Don't bother with local console output as it just ends up
                // cluttering the logs
                configureConsole().ignoreLocalConsole(),
                // Force the log level to INFO so we have more details during
                // the test. It defaults to WARN.
                //logLevel(LogLevel.DEBUG),
                // Provision the example feature exercised by this test
                features(oinkFeaturesRepo, "oink-adapter-facade"),
                replaceConfigurationFile("etc/uk.org.openeyes.oink.facade.cfg",
                        ITSupport.getPropertyFileBySystemProperty("it.facadeToProxy.config")),
                features(oinkFeaturesRepo, "oink-adapter-proxy"),
                replaceConfigurationFile("etc/uk.org.openeyes.oink.proxy.cfg",
                        ITSupport.getPropertyFileBySystemProperty("it.proxy.config")),
                replaceConfigurationFile("etc/org.ops4j.pax.logging.cfg",
                        new File("src/test/resources/log4j.properties")),

                // Remember that the test executes in another process. If you want to
                // debug it, you need
                // to tell Pax Exam to launch that process with debugging enabled.
                // Launching the test class itself with
                // debugging enabled (for example in Eclipse) will not get you the
                // desired results.
                // debugConfiguration("5005", true),
        };
    }

}