package uk.ac.ebi.biosamples;

import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpResponse;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class Application {
	
	//this is needed to read nonstrings from properties files
	//must be static for lifecycle reasons
	@Bean
	public static PropertySourcesPlaceholderConfigurer getPropertySourcesPlaceholderConfigurer() {
		return new PropertySourcesPlaceholderConfigurer();
	}
	
	//sets resttemplate to use connection pooling
	@Bean
	public ClientHttpRequestFactory getClientHttpRequestFactory() {

    	PoolingHttpClientConnectionManager conman = new PoolingHttpClientConnectionManager();
    	conman.setMaxTotal(128);
    	conman.setDefaultMaxPerRoute(64);
    	conman.setValidateAfterInactivity(0);
    	
    	ConnectionKeepAliveStrategy keepAliveStrategy = new ConnectionKeepAliveStrategy() {
            @Override
            public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
            	//see if the user provides a live time
                HeaderElementIterator it = new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));
                while (it.hasNext()) {
                    HeaderElement he = it.nextElement();
                    String param = he.getName();
                    String value = he.getValue();
                    if (value != null && param.equalsIgnoreCase("timeout")) {
                        return Long.parseLong(value) * 1000;
                    }
                }
                //default to one second live time 
                return 1 * 1000;
            }
        };
    	
    	CloseableHttpClient httpClient = HttpClients.custom()
    			.setKeepAliveStrategy(keepAliveStrategy)
    			.setConnectionManager(conman).build();
    	
    	return new HttpComponentsClientHttpRequestFactory(httpClient);
	}
	
	@Bean
	public RestTemplate getRestTemplate() {
		RestTemplate restTemplate = new RestTemplate();
		restTemplate.setRequestFactory(getClientHttpRequestFactory());
		return restTemplate;
	}

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

@@ -24,16 +24,40 @@
 mples;%0A%0A
+import java.util.List;%0A%0A
 import o
@@ -790,24 +790,125 @@
 Configurer;%0A
+import org.springframework.hateoas.hal.Jackson2HalModule;%0Aimport org.springframework.http.MediaType;%0A
 import org.s
@@ -1070,31 +1070,294 @@
 ork.
-web.client.RestTemplate
+http.converter.HttpMessageConverter;%0Aimport org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;%0Aimport org.springframework.web.client.RestTemplate;%0A%0Aimport com.fasterxml.jackson.databind.DeserializationFeature;%0Aimport com.fasterxml.jackson.databind.ObjectMapper
 ;%0A%0A@
@@ -3098,169 +3098,1174 @@
 %0A%09%0A%09
-@Bean%0A%09public RestTemplate getRestTemplate() %7B%0A%09%09RestTemplate restTemplate = new RestTemplate();%0A%09%09restTemplate.setRequestFactory(getClientHttpRequestFactory());
+/**%0A%09 * Creates a rest template for use with the other components. Configures it to support hal+json%0A%09 * and to use connection pooling%0A%09 *  %0A%09 * @param clientHttpRequestFactory%0A%09 * @param mapper%0A%09 * @return%0A%09 */%0A%09@Bean%0A%09public RestTemplate getRestTemplate(ClientHttpRequestFactory clientHttpRequestFactory, ObjectMapper mapper) %7B%0A%09%09RestTemplate restTemplate = new RestTemplate();%0A%09%09restTemplate.setRequestFactory(clientHttpRequestFactory);%0A%09%09%0A%09%09//need to create a new message converter to handle hal+json%0A%09%09//ObjectMapper mapper = new ObjectMapper();%0A%09%09mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);%0A%09%09mapper.registerModule(new Jackson2HalModule());%0A%09%09MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();%0A%09%09converter.setSupportedMediaTypes(MediaType.parseMediaTypes(%22application/hal+json%22));%0A%09%09converter.setObjectMapper(mapper);%0A%0A%09%09//add the new converters to the restTemplate%0A%09%09//but make sure it is BEFORE the existing converters%0A%09%09List%3CHttpMessageConverter%3C?%3E%3E converters = restTemplate.getMessageConverters();%0A%09%09converters.add(0,converter);%0A%09%09restTemplate.setMessageConverters(converters);%0A%09%09%0A%09%09
 %0A%09%09r

handle hal+json rest