Skip to content

anthavio/hatatitla

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Hatatitla Build Status Coverage Status

Cloudbees DEV@cloud

Configurable and tweakable REST client library

  • Cool fluent interface
  • XML request/response payload support (JAXB)
  • JSON request/response payload support (Jackson)
  • Response caching (memory/ehcache/memcached)
  • Response content negotiation (content-type, charset, gzip)
  • Extensive configuration with reasonable defaults
  • Connection pooling - multithreaded by default
  • Asynchronous requests - java Future and ExecutorService infrastructure
  • Multiple transport options - Apache Httpclient4 / Apache Httpclient3 / HttpURLConnection

Maven Repository & coordinates

    <dependency>
        <groupId>net.anthavio</groupId>
        <artifactId>hatatitla</artifactId>
        <version>1.5.0</version>
    </dependency>

Fluent API

Fluent buiders pattern is used for complex request creation and execution

		//Create sender with utf-8 encoding, default timeouts and connection pool
		HttlSender sender = HttlSender.url("https://api.github.com").build();

		ExtractedResponse<String> extracted = sender.GET("/users").param("since", 333).extract(String.class);
		//Just print unprocessed JSON String
		System.out.println(extracted.getBody());

		//Free connection pool
		sender.close();

Request/Response Body marshalling

For XML payloads, standard JAXB used for marshalling requests and responses and no additional library is required.

For JSON payloads, Jackson 1 or Jackson 2 must be present on classpath, otherwise following exception will occur.

net.anthavio.httl.HttlRequestException: Marshaller not found for application/json

Java beans representing bodies must be existing. In this example, HttpbinIn and HttpbinOut are model beans.

		HttpClient4Sender sender = new HttpClient4Sender("http://httpbin.org");

		//Send HttpbinIn instance marshalled as JSON document
		HttpbinIn binIn = new HttpbinIn();
		binIn.setSomeDate(new Date());
		binIn.setSomeString("Hello!");

		//Using extract method will parse returned Httpbin JSON document into HttpbinOut instance
		ExtractedResponse<HttpbinOut> extract = sender.POST("/post").body(binIn, "application/json").extract(HttpbinOut.class);

		HttpbinOut body = extract.getBody(); //voila!

		sender.close();

Configuration

Hatatitla Sender is extensively configurable with reasonable default values.

		HttpClient4Config config = new HttpClient4Config("http://httpbin.org");

		//That pesky IIS is using Cyrillic? No problem!
		config.setEncoding("Cp1251"); //default utf-8

		//Life if boring without timeouts
		config.setConnectTimeoutMillis(3 * 1000); //default is 5 seconds
		config.setReadTimeoutMillis(10 * 1000); //default is 20 seconds

		//Connection pooling for maximal throughput
		config.setPoolMaximumSize(60); //default is 10
		//Timeout for getting connection from pool
		config.setPoolAcquireTimeoutMillis(5 * 1000); //default is 3 seconds
		//TTL for connections in pool
		config.setPoolReleaseTimeoutMillis(5 * 60 * 1000); //default is 65 seconds

		//BASIC and DIGEST Autentication at your service! BASIC is preemptive by default.
		config.setAuthentication(Authentication.BASIC("myusername", "mypassword"));

		config.setFollowRedirects(true); //default is false

		//Tired of setting Accept Header to every request?
		SenderConfigurer configurer = config.sender();
		configurer.setResponseMediaType("application/json"); //default is none

		//How to treat null or "" parameter values?
		boolean keepNullParams = false;
		boolean keepEmptyParams = true;
		boolean urlEncodeNames = false;
		boolean urlEncodeValues = true;
		String dateParamPattern = "dd-MM-yyyy";
		ConfigurableParamSetter paramSetter = new ConfigurableParamSetter(keepNullParams, keepEmptyParams, urlEncodeNames, urlEncodeValues, dateParamPattern);

		configurer.setParamSetter(paramSetter);

		HttlSender sender = configurer.build();
		//...send send send...
		sender.close();

Caching

Hatatitla can cache responses or extracted bodies of responses. Cached data can be refreshed synchronously or asynchronously during request or scheduled to be updated in the background.

In memory, EHCache and SpyMemcache caches are available out of the box. Other implementation can be easily created by extending RequestCache class.

		//Create normal HttpSender
		HttpClient4Sender sender = new HttpClient4Sender("http://httpbin.org");
		//Provide cache instance - Simple Heap Hashmap in this case
		RequestCache<Object> cache = new HeapMapRequestCache<Object>();
		//Create Caching Extractor
		CachingExtractor cextractor = new CachingExtractor(sender, cache);

		//Create normal request
		GetRequest get = new GetRequest("/get");
		
		//Response will kept in cache for 10 seconds (hard TTL) and will be refreshed every 5 seconds (soft TTL) using background thread.

		//Use fluent interface to execute/extract
		for (int i = 0; i < 1000; ++i) {
			HttpbinOut out = cextractor.request(get).ttl(10, 5, TimeUnit.SECONDS).extract(HttpbinOut.class);//Cache hit
		}

		//Precreated Caching request
		CachingExtractorRequest<HttpbinOut> crequest = cextractor.request(get).ttl(10, 5, TimeUnit.SECONDS)
				.build(HttpbinOut.class);
		for (int i = 0; i < 1000; ++i) {
			HttpbinOut out = cextractor.extract(crequest); //Cache hit
		}

		//Precreated Caching request
		CachingExtractorRequest<HttpbinOut> crequest2 = new CachingExtractorRequest<HttpbinOut>(get, HttpbinOut.class, 10,
				5, TimeUnit.SECONDS, RefreshMode.REQUEST_SYNC);
		for (int i = 0; i < 1000; ++i) {
			HttpbinOut out = cextractor.extract(crequest2);//Cache hit
		}

		cache.close();
		cextractor.close();

Example of the automatic response refresh/update

		//Create normal HttpSender
		HttpSender sender = new HttpClient4Sender("http://httpbin.org");
		//Provide cache instance - Simple Heap Hashmap in this case
		RequestCache<Object> cache = new HeapMapRequestCache<Object>();
		//Setup asynchronous support
		ExecutorService executor = ExecutorServiceBuilder.builder().setMaximumPoolSize(1).setMaximumQueueSize(1).build();
		//Create Caching Extractor
		CachingExtractor cextractor = new CachingExtractor(sender, cache, executor);
		//Create normal request
		GetRequest get = new GetRequest("/get");

		//Response will kept in cache for 60 seconds (hatr TTL) and will be refreshed every 3 seconds (soft TTL) using background thread. 
		//Unavailability could happen only when remote service became unaccessible for more than 60-3 seconds
		CachingExtractorRequest<HttpbinOut> crequest = cextractor.request(get).ttl(60, 3, TimeUnit.SECONDS)
				.refresh(RefreshMode.SCHEDULED).build(HttpbinOut.class);

		HttpbinOut out1 = cextractor.extract(crequest); //cache put
		HttpbinOut out2 = cextractor.extract(crequest); //cache hit
		Assert.assertTrue(out1 == out2); //same instance from cache

		//sleep until background refresh is performed
		try {
			Thread.sleep(4 * 1000);
		} catch (InterruptedException ix) {
			ix.printStackTrace();
		}

		HttpbinOut out3 = cextractor.extract(crequest);
		Assert.assertTrue(out1 != out3); //different instance now

		sender.close();
		executor.shutdown();
		cache.close();

Sender Implementations

URLHttpSender - Easy to start with

		//No additional dependency - vanilla java
		HttlSender urlSender = HttlSender.url("https://graph.facebook.com").build();

HttpClient4Sender - Recommended choice

		HttpClient4Config http4config = HttlSender.url("https://api.twitter.com").httpClient4();
		HttlSender http4sender = http4config.sender().build();

Dependency - http://hc.apache.org/httpcomponents-client-ga/

		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.2.3</version>
		</dependency>

Missing dependency - java.lang.IllegalStateException: HttClient 4 classes not found in classpath

HttpClient3Sender - Legacy choice

		HttpClient3Config http3config = HttlBuilder.httpClient3("https://api.twitter.com");
		HttlSender http3sender = http3config.sender().build();

Dependency - http://hc.apache.org/httpclient-3.x/

		<dependency>
			<groupId>commons-httpclient</groupId>
			<artifactId>commons-httpclient</artifactId>
			<version>3.1</version>
		</dependency>

Missing dependency - java.lang.IllegalStateException: HttClient 3.1 classes not found in classpath

About

Tweakable REST client library you have been dreaming of

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages