com.stormpath.sdk.client.ClientBuilder Maven / Gradle / Ivy
/*
* Copyright 2014 Stormpath, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.stormpath.sdk.client;
import com.stormpath.sdk.cache.CacheManager;
/**
* A Builder design pattern used to
* construct {@link com.stormpath.sdk.client.Client} instances.
*
* The {@code ClientBuilder} is used to construct Client instances with Stormpath API Key,
* Proxy and Cache configuration. Understanding caching is extremely important when creating a Client instance, so
* please ensure you read the Caching section below.
*
* Usage
*
* The simplest usage is to just call the {@link #build() build()} method, for example:
*
*
* Client client = {@link Clients Clients}.builder().{@link #build() build()};
*
*
* This will:
*
* - Automatically enable a simple in-memory {@link CacheManager} for enhanced performance (but please read
* the Caching section below for effects/warnings).
* - Automatically attempt to find your API Key values in a number of default/conventional locations and then use
* the discovered values. Without any other configuration, the following locations will be each be checked,
* in order:
*
*
*
* - The default apiKey.properties file location of
*
System.getProperty("user.home") + "/.stormpath/apiKey.properties"
as
* recommended/documented in the Stormpath Java
* Quickstart.
* - A properties file that exists at the file path or URL specified by the {@code STORMPATH_API_KEY_FILE}
* variable. If this file exists and contains either the apiKey id or secret properties, these values
* override any values found in the default apiKey.properties file. The {@code STORMPATH_API_KEY_FILE}
* String can be an absolute file path, or it can be a URL or a classpath value by using the {@code url:} or
* {@code classpath:} prefixes respectively.
* - The environment variables {@code STORMPATH_API_KEY_ID} and {@code STORMPATH_API_KEY_SECRET}. If either of
* these values are present, they override any previously discovered value.
* - A properties file that exists at the file path or URL specified by the {@code stormpath.apiKey.file}
* system property. If this file exists and any values are present, the values override any
* previously discovered value. The {@code stormpath.apiKey.file} system property String can be an
* absolute file path, or it can be a URL or a classpath value by using the {@code url:} or
* {@code classpath:} prefixes respectively.
* - The system properties {@code stormpath.apiKey.id} and {@code stormpath.apiKey.secret}. If either of
* these values are present, they override any previously discovered values.
*
*
* SECURITY NOTICE: While the {@code stormpath.apiKey.secret} system property may be used to represent your
* API Key Secret as mentioned above, this is not recommended: process listings on a machine will expose process
* arguments (like system properties) and expose the secret value to anyone that can read process listings. As
* always, secret values should never be exposed to anyone other than the person that owns the API Key.
*
* While an API Key ID may be configured anywhere (and be visible by anyone), it is recommended to use a private
* read-only file or an environment variable to represent API Key secrets. Never commit secrets to source code
* or version control.
*
* Explicit API Key Configuration
*
* The above default API Key searching heuristics may not be suitable to your needs. In that case, you will likely
* need to explicitly configure your API Key. For example:
*
*
* ApiKey apiKey = {@link com.stormpath.sdk.api.ApiKeys ApiKeys}.builder()
* //specific configuration
* .{@link #build build()};
*
* Client client = {@link Clients Clients}.builder().setApiKey(apiKey).build();
*
*
* See the {@link com.stormpath.sdk.api.ApiKeyBuilder ApiKeyBuilder} JavaDoc for specific API Key configuration
* options.
*
* Caching
*
* By default, a simple production-grade in-memory {@code CacheManager} will be enabled when the Client instance is
* created. This {@code CacheManager} implementation has the following characteristics:
*
*
* - It assumes a default time-to-live and time-to-idle of 1 hour for all cache entries.
* - It auto-sizes itself based on your application's memory usage. It will not cause OutOfMemoryExceptions.
* (It does this by retaining only 100 strong references to cached objects. Additional cached objects are
* weakly referenced, ensuring the garbage collector can evict weakly referenced cache entries if it needs
* more memory for your application.).
*
*
*
* but, please note:
*
* The default cache manager is not suitable for an application deployed across multiple JVMs.
*
* This is because the default implementation is 100% in-memory (in-process) in the current JVM. If more than one
* JVM is deployed with the same application codebase - for example, a web application deployed on multiple identical
* hosts for scaling or high availability - each JVM would have it's own in-memory cache. Multiple disconnected caches
* for the same data will cause cache coherency problems and likely cause errors in your application!
*
* As a result, if your application that uses a Stormpath Client instance is deployed across multiple JVMs, you
* SHOULD ensure that the Client is configured with a {@code CacheManager} implementation that uses coherent and
* clustered/distributed memory.
*
* Custom CacheManager
*
* If you want to specify a custom {@code CacheManager} implementation:
*
*
* CacheManager cacheManager = new MyCacheManagerImplementation();
* Client client = {@link com.stormpath.sdk.client.Clients Clients}.builder().setCacheManager(cacheManager).build();
*
*
* Application deployed on a single JVM
*
* If your application is deployed on a single JVM and you still want to use the default
* {@code CacheManager} implementation, but the default cache configuration does not meet your
* needs, you can specify a different configuration. For example:
*
*
* import static com.stormpath.sdk.cache.Caches.*;
*
* ...
*
* {@link com.stormpath.sdk.cache.Caches Caches}.{@link com.stormpath.sdk.cache.Caches#newCacheManager() newCacheManager()}
* .withDefaultTimeToLive(2, TimeUnit.HOURS) // default
* .withDefaultTimeToIdle(1, TimeUnit.HOURS) //general default
* .withCache({@link com.stormpath.sdk.cache.Caches#forResource(Class) forResource}(Account.class) //Account-specific cache settings
* .withTimeToLive(1, TimeUnit.HOURS)
* .withTimeToIdle(30, TimeUnit.MINUTES))
* .withCache({@link com.stormpath.sdk.cache.Caches#forResource(Class) forResource}(Group.class) //Group-specific cache settings
* .withTimeToLive(2, TimeUnit.HOURS))
*
* //... etc ...
*
* .build(); //build the CacheManager
*
*
* See the {@link com.stormpath.sdk.cache.Caches Caches} utility class and the
* {@link com.stormpath.sdk.cache.CacheManagerBuilder CacheManagerBuilder} docs for more information.
*
* Application deployed across multiple JVMs
*
* If your application is deployed across multiple JVMs (for example a web app deployed on multiple web nodes for
* scale and/or high availability), you will likely need to specify a custom
* {@code CacheManager} implementation that is based on network distributed/coherent memory. For example, an
* implementation might delegate to a Hazelcast or
* Redis cluster. For example, if using the out-of-the-box Hazelcast plugin:
*
*
* import com.stormpath.sdk.hazelcast.HazelcastCacheManager;
* // ... etc ...
*
* //Get a HazelcastInstance from your app/config. This can be a HazelcastClient instance too:
* HazelcastInstance hazelcastInstance = getHazelcastInstanceOrHazelcastClient();
*
* CacheManager cacheManager = new HazelcastCacheManager(hazelcastInstance);
* Client client = {@link com.stormpath.sdk.client.Clients Clients}.builder().setCacheManager(cacheManager).build();
*
*
* NOTE: it should be noted that Memcache DOES NOT guarantee cache
* coherency. It is strongly recommended that you do not use Memcache as your clustered caching solution (memcache
* is fine for caching files, etc, but not data that is expected to be coherent across multiple cluster nodes).
*
* Disable Caching
*
* While production applications will usually enable a working CacheManager as described above, you might wish to disable caching
* entirely when testing or debugging to remove 'moving parts' for better clarity into request/response
* behavior. You can do this by configuring a disabled {@code CacheManager} instance. For example:
*
*
* Client client = {@link com.stormpath.sdk.client.Clients Clients}.builder().setCacheManager(
* Caches.newDisabledCacheManager()
* ).build();
*
*
* Single Instance
*
* Finally, it should be noted that, after building a {@code client} instance, that same instance should be used
* everywhere in your application. Creating multiple client instances in a single application could have
* negative side effects:
*
* As mentioned above, a client has a {@link #setCacheManager(com.stormpath.sdk.cache.CacheManager) CacheManager}
* reference. If your application uses multiple client instances, each client's referenced CacheManager would likely
* become out of sync with the others, making your cache
* incoherent. This will likely
* result in exposing stale data to your application and could data errors.
*
* If you must have multiple {@code Client} instances in your application, you should ensure that each client
* references the same exact {@code CacheManager} instance to guarantee cache coherency.
*
* @see com.stormpath.sdk.api.ApiKeyBuilder ApiKeyBuilder
* @since 1.0.beta
*/
public interface ClientBuilder {
/**
* Allows specifying an {@code ApiKey} instance directly instead of relying on the
* default location + override/fallback behavior defined in the {@link ClientBuilder documentation above}.
*
* Consider using an {@link com.stormpath.sdk.api.ApiKeyBuilder ApiKeyBuilder} to construct your
* {@code ApiKey} instance.
*
* @param apiKey the ApiKey to use to authenticate requests to the Stormpath API server.
* @return the ClientBuilder instance for method chaining.
* @see com.stormpath.sdk.api.ApiKeyBuilder
* @deprecated in 1.0.RC and will be removed before 1.0 final. Use {@link #setApiKey(com.stormpath.sdk.api.ApiKey)} instead.
*/
@Deprecated
ClientBuilder setApiKey(ApiKey apiKey);
/**
* Allows specifying an {@code ApiKey} instance directly instead of relying on the
* default location + override/fallback behavior defined in the {@link ClientBuilder documentation above}.
*
* Consider using an {@link com.stormpath.sdk.api.ApiKeyBuilder ApiKeyBuilder} to construct your
* {@code ApiKey} instance.
*
* @param apiKey the ApiKey to use to authenticate requests to the Stormpath API server.
* @return the ClientBuilder instance for method chaining.
* @see com.stormpath.sdk.api.ApiKeyBuilder
*/
ClientBuilder setApiKey(com.stormpath.sdk.api.ApiKey apiKey);
/**
* Sets the HTTP proxy to be used when communicating with the Stormpath API server. For example:
*
*
* Proxy proxy = new Proxy("whatever.domain.com", 443);
* Client client = {@link Clients Clients}.builder().setProxy(proxy).build();
*
*
* @param proxy the {@code Proxy} you need to use.
* @return the ClientBuilder instance for method chaining.
*/
ClientBuilder setProxy(Proxy proxy);
/**
* Sets the {@link CacheManager} that should be used to cache Stormpath REST resources, reducing round-trips to the
* Stormpath API server and enhancing application performance.
*
* Single JVM Applications
*
* If your application runs on a single JVM-based applications, the
* {@link com.stormpath.sdk.cache.CacheManagerBuilder CacheManagerBuilder} should be sufficient for your needs. You
* create a {@code CacheManagerBuilder} by using the {@link com.stormpath.sdk.cache.Caches Caches} utility class,
* for example:
*
*
* import static com.stormpath.sdk.cache.Caches.*;
*
* ...
*
* Client client = Clients.builder()...
* .setCacheManager(
* {@link com.stormpath.sdk.cache.Caches#newCacheManager() newCacheManager()}
* .withDefaultTimeToLive(1, TimeUnit.DAYS) //general default
* .withDefaultTimeToIdle(2, TimeUnit.HOURS) //general default
* .withCache({@link com.stormpath.sdk.cache.Caches#forResource(Class) forResource}(Account.class) //Account-specific cache settings
* .withTimeToLive(1, TimeUnit.HOURS)
* .withTimeToIdle(30, TimeUnit.MINUTES))
* .withCache({@link com.stormpath.sdk.cache.Caches#forResource(Class) forResource}(Group.class) //Group-specific cache settings
* .withTimeToLive(2, TimeUnit.HOURS))
* .build() //build the CacheManager
* )
* .build(); //build the Client
*
*
* The above TTL and TTI times are just examples showing API usage - the times themselves are not
* recommendations. Choose TTL and TTI times based on your application requirements.
*
* Multi-JVM / Clustered Applications
*
* The default {@code CacheManager} instances returned by the
* {@link com.stormpath.sdk.cache.CacheManagerBuilder CacheManagerBuilder} might not be sufficient for a
* multi-instance application that runs on multiple JVMs and/or hosts/servers, as there could be cache-coherency
* problems across the JVMs. See the {@link com.stormpath.sdk.cache.CacheManagerBuilder CacheManagerBuilder}
* JavaDoc for additional information.
*
* In these multi-JVM environments, you will likely want to create a simple CacheManager implementation that
* wraps your distributed Caching API/product of choice and then plug that implementation in to the Stormpath SDK
* via this method. Hazelcast is one known cluster-safe caching product, and the Stormpath SDK has out-of-the-box
* support for this as an extension module. See the top-level class JavaDoc for a Hazelcast configuration
* example.
*
* @param cacheManager the {@link CacheManager} that should be used to cache Stormpath REST resources, reducing
* round-trips to the Stormpath API server and enhancing application performance.
*/
ClientBuilder setCacheManager(CacheManager cacheManager);
/**
* Overrides the default (very secure)
* Stormpath SAuthc1 Digest
* Authentication Scheme used to authenticate every request sent to the Stormpath API server.
*
* It is not recommended that you override this setting unless your application is deployed in an
* environment that - outside of your application's control - manipulates request headers on outgoing HTTP requests.
* Google App Engine is one such environment, for example.
*
* As such, in these environments only, an alternative authentication mechanism is necessary, such as
* HTTP
* Basic Authentication. You can enable Basic Authentication as follows (again, only do this if your
* application runtime environment forces you to use it, like Google App Engine):
*
* Client client = Clients.builder()...
* // setApiKey, etc...
* .setAuthenticationScheme(AuthenticationScheme.BASIC) //set the basic authentication scheme
* .build(); //build the Client
*
*
* @param authenticationScheme the type of authentication to be used for communication with the Stormpath API server.
* @return the ClientBuilder instance for method chaining
*/
ClientBuilder setAuthenticationScheme(AuthenticationScheme authenticationScheme);
/**
* Sets both the timeout until a connection is established and the socket timeout (i.e. a maximum period of inactivity
* between two consecutive data packets). A timeout value of zero is interpreted as an infinite timeout.
*
* @param timeout connection and socket timeout in milliseconds
* @return the ClientBuilder instance for method chaining
* @since 1.0.RC3
*/
ClientBuilder setConnectionTimeout(int timeout);
/**
* Sets the base URL of the Stormpath REST API to use. If unspecified, this value defaults to
* {@code https://api.stormpath.com/v1} - the most common use case for Stormpath's public SaaS cloud.
*
* Customers using Stormpath's Enterprise HA cloud might need to configure this to be
* {@code https://enterprise.stormpath.io/v1} for example.
*
* @param baseUrl the base URL of the Stormpath REST API to use.
* @return the ClientBuilder instance for method chaining
* @since 1.0.RC4
*/
ClientBuilder setBaseUrl(String baseUrl);
/**
* Constructs a new {@link Client} instance based on the ClientBuilder's current configuration state.
*
* @return a new {@link Client} instance based on the ClientBuilder's current configuration state.
*/
Client build();
}