Category Archives: Java

Redis data sharding – part 1

In one of my previous posts on Redis i provided a definition of data sharding, quoting a great book “Redis in Action” authored by Dr. Josiah L Carlson:

  • “Sharding is a method by which you partition your data into different pieces. In this case, you partition your data based on IDs embedded in the keys, based on the hash of keys, or some combination of the two. Through partitioning your data, you can store and fetch the data from multiple machines, which can allow a linear scaling in performance for certain problem domains.”


Today i’d like to elaborate some more on data sharding based on IDs embedded in the keys.


Let’s start with an example of a hypothetical data stored in an Redis instance:

redis>keys *
(empty list or set)
redis>set emails:1
redis>get emails:1

what i did here is to use the basic String data type to store an email of a user. As you can see, i embedded user id within the key (’emails:1′). Now, if a front-end application would ask for an email address of a user with id=1, on the back-end side i would concatenate the keyword which i usually use to denote keys i store emails under (ie. ’emails’) with the id of a user (‘1’), add a colon (‘:’) in between, and this way i’ll get the resulting key (’emails:1′) i should look after while making a call to the Redis instance.


This solution is nice but if i’ll have 1 million of users registered in my system and use Redis as the data store for keeping mappings between identifier of a user and his email, i will end up with 1 million keys (’emails:1′, ’emails:2′, ’emails:3′, etc.). This is a volume my Redis instance will easily handle (see my previous post on Redis Performance Basics) and it will use little more than 190MB to store everything in the memory (so much due to a lot of overhead when storing small keys and values; the ratio is much better with large keys/values), but this is only one attribute we’re talking about – and what about firstName, lastName, etc.?. Obviously, if my system will have millions of registered users and i’d use Redis as my primary data store for users-related info, i would be running multiple instances of Redis already and based on the id of a user, route the queries to a specific instance, but there’s still a lot we can do to optimize costs prior to thinking about scaling.


Small code snippet to generate 1M of emails stored in Redis using String data structure (and Spring Data Redis mentioned in my other post).

int i = 0;
while(i<1000000) {
    redisTemplate.opsForValue().set(String.format("emails:%s", i++), "");

the loop above executes in 2 mins on my Windows 8 64bit i7 laptop and the ‘redis-server’ process allocates ca 190 MB of memory.


Now, what will happen if we change the data structure let’s say to a Redis Hash?

Next code snippet and we’re getting just that:

int i = 0;
while(i<1000000) {
    String userId = String.valueOf(i++);
    String emailAddress = String.format("", userId);
    redisTemplate.opsForHash().put("emails", emailAddress, userId)

2 mins and 165 MB of memory allocated – a 15 % gain absolutely for free.


Let’s try with data sharding/partitioning. Another code snippet using Redis Hash data structure and there you go:

int shardSize = 1024;
int i = 0;
while(i<1000000) {
    int shardKey = i/shardSize;
    String userId = String.valueOf(i++);
    String emailAddress = String.format("", userId);
    redisTemplate.opsForHash().put(String.format("emailsbucket:%s", shardKey), emailAddress, userId);

2 mins later and… only 30 MB allocated – now you’re talking Mariusz!

Staggering 530 % increase in memory allocation efficiency!


Hope you enjoyed the first part of this brief tutorial.







Spring Data Redis overview

If you are, like me, a great fan of the Spring Framework, you probably know already the Spring Data product and corresponding spring-data-redis module. If not, let me introduce this wonderful tool in this brief post.


Spring Data Redis offers the following features (copied from the product homepage):

  • Connection package as low-level abstraction across multiple Redis drivers/connectors (Jedis,  JRedisLettuceSRP and RJC)
  • Exception translation to Spring’s portable Data Access exception hierarchy for Redis driver exceptions
  • RedisTemplate that provides a high level abstraction for performing various redis operations, exception translation and serialization support
  • Pubsub support (such as a MessageListenerContainer for message-driven POJOs)
  • JDK, String, JSON and Spring Object/XML mapping serializers
  • JDK Collection implementations on top of Redis
  • Atomic counter support classes
  • Sorting and Pipelining functionality
  • Dedicated support for SORT, SORT/GET pattern and returned bulk values
  • Redis implementation for Spring 3.1 cache abstraction


As of the time of writing this post, the latest product release is labeled ‘1.0.6.RELEASE’, and available as a Maven dependency:



Using Spring Data Redis in your project is as easy as defining the above dependency in your master pom.xml file, and configuring the RedisTemplate bean in either xml context file (example below) or using Java configuration:

    <context:property-placeholder location=""/>

    <bean id="connectionFactory"
          p:usePool="${redis.pool}" />

    <bean id="stringRedisSerializer" class="" />

    <bean id="redisTemplate" class=""
          p:defaultSerializer-ref="stringRedisSerializer" />


and the corresponding redis.config file:

# Redis settings


…in code you’re using the RedisTemplate like this:

private RedisTemplate redisTemplate;

    public void saveEmail(String email, long userId) {
        redisTemplate.opsForHash().put("emails", String.valueOf(userId), email);


I did also i quick overview of the extend to which Redis native API commands, related to performing operations on 5 basic Redis data types, have been implemented in the product. Below you’ll find a short visual summary:


  • Strings

Spring Data Redis String



  • Lists

Spring Data Redis List



  • Sets

Spring Data Redis Set



  • Hashes

Spring Data Redis Hash



  • ZSets

Spring Data Redis ZSet








Custom Validation Annotations

Let’s say we want to task the back-end REST API application with validating the syntax of an email address provided by a new user while doing the registration. Aside from the fact that the “first level” validation should always happen on the front-end side (using for example a JavaScript solution) it is still a good idea to do a “second level” validation on the back-end (a user can have JavaScript support disabled in his/her browser or try some dirty hacks on our webpage and be sending invalid data to the server causing inconsistencies at best).

What would be a nice approach to handle server-side validation? A custom annotation – something like @ValidEmailSyntax

Here’s an idea on how to implement it:


1) Create an interface for the Validation Annotation:

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Constraint(validatedBy = EmailSyntaxValidator.class)
public @interface ValidEmailSyntax {

    String message() default "Invalid email syntax";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default { };

  • As you can see from the code above, our @ValidEmailSyntax annotation can be used to annotate a field, method or another annotation
  • “Invalid email syntax” is the message returned by the server in case of failed validation


2) Create a EmailSyntaxValidator class that will be responsible for making decision whether the subject of validation (field, method, etc…) is valid or not:

public class EmailSyntaxValidator implements ConstraintValidator<ValidEmailSyntax, EmailAddressType> {

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    public void initialize(ValidEmailSyntax constraintAnnotation) {
        logger.debug("EmailSyntaxValidator initialization successful");

    public boolean isValid(EmailAddressType value, ConstraintValidatorContext context) {

        return value == null || Pattern.compile(EmailStructure.PATTERN, Pattern.CASE_INSENSITIVE).matcher(value.getEmail()).matches();




3) The validator class above will validate the the email represented by following EmailAddressType object:

@JsonSerialize(using = ToStringSerializer.class)
public class EmailAddressType implements Serializable {

    private static final long serialVersionUID = 1L;

    private String email;

    public EmailAddressType(String email) { = email;

    public String getEmail() {
        return email;

    public void setEmail(String email) { = email;

    public String toString() {
        return email;



4) …against the following email structure pattern (represented by an EmailStructure interface):

public interface EmailStructure {

    static final String ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~-]";
    static final String DOMAIN = "(" + ATOM + "+(\\." + ATOM + "+)+";
    static final String IP_DOMAIN = "\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\]";

    static final String PATTERN = "^" + ATOM + "+(\\." + ATOM + "+)*@" + DOMAIN + "|" + IP_DOMAIN + ")$";



5) finally this is how we will use the validation annotation in our code:

public class User {

    private EmailAddressType email;
    //getters and setters ommited




Happy coding! 🙂

Tomcat, JNDI and Spring bean application configuration

While setting up a Continuous Integration environment recently i faced an issue related to application (REST API in this case) configuration not being deployment-environment independent. Namely as the code pushed to Git repository and picked up by Jenkins build server was later on automatically deployed across several server environments (DEV, INT, STAGING, PROD) it turned out that in each of those environments the API application (war archive deployed in Tomcat container) requires to be fed with a specific/different configuration (environment-specific settings).


This is how i managed to solve this issue:


1. I created the following Tomcat context entry in “conf/context.xml” file:

    <Resource name="config/Api"
        sso="" />


2. Created the “CustomApiJNDIFactory” class:

public class CustomApiJNDIFactory implements ObjectFactory {

    public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?,?> environment) throws Exception {

        validateProperty(obj, "Invalid JNDI object reference");

        String scheme = null;
        String host = null;
        String port = null;
        String version = null;
        String sso = null;

        Reference ref = (Reference) obj;

        Enumeration props = ref.getAll();

        while (props.hasMoreElements()) {

            RefAddr addr = props.nextElement();
            String propName = addr.getType();
            String propValue = (String) addr.getContent();

            switch (propName) {
                case "scheme":
                    scheme = propValue;
                case "host":
                    host = propValue;
                case "port":
                    port = propValue;
                case "version":
                    version = propValue;
                case "sso":
                    sso = propValue;


        // validate properties
        validateProperty(scheme, "Invalid or empty scheme type");
        validateProperty(host, "Invalid or empty server host name");
        validateProperty(port, "Invalid or empty port number");
        validateProperty(version, "Invalid or empty API version number");
        validateProperty(sso, "Invalid or empty SSO server name");

        //create API Configuration Bean
        return new ApiConfigBean(scheme, host, port, version, sso);


     * Validate internal String properties
     * @param property the property
     * @param errorMessage the error message
     * @throws javax.naming.NamingException
    private void validateProperty(String property, String errorMessage) throws NamingException {

        if (property == null || property.trim().equals("")) {
            throw new NamingException(errorMessage);




3. Defined an jndi-lookup entry in my “spring-api-context.xml” file that will read Tomcat JNDI configuration entry and expose it as a Spring bean of name jndiApi:

<jee:jndi-lookup id="jndiApi" jndi-name="java:/comp/env/config/Api" expected-type="com.mycompany.model.ApiConfigBean" />


4. Created the “jndiApi” Spring bean backing pojo

public class ApiConfigBean {

    private String scheme;
    private String host;
    private String port;
    private String version;
    private String sso;

    public ApiConfigBean(String scheme, String host, String port, String version, String sso) {
        this.scheme = scheme; = host;
        this.port = port;
        this.version = version;
        this.sso = sso;

    // getters and setters ommited.



5. and finally wired-in the bean to my classes where i needed to make use of the “externalized” configuration:

private ApiConfigBean apiConfigBean;

    public void foo() {

        String host = apiConfigBean.getHost();




That’s it! Have a wonderful day! 🙂

Spring localized exception handling in REST API

In today’s post i’ll share with you the way we’re handling Internationalization (i18n) and Localization (L10n) in our REST API which is based on Spring MVC (3.2.3.RELEASE).

Our front-end web client is an SPA (Single Page Application) built using AngularJS framework and occasionally it needs to handle Java exceptions messages thrown by the back-end. The way it has been implemented is that it intercepts JSON error responses, wraps them in a pre-defined web page template and displays to the user in a unified and nice way.

“Localization” of back-end related error messages happens …at the back-end level.


After this quick intro let’s get familiar with following two definitions:

  • Internationalization – process of designing software applications so that they can be adapted to various languages and regions without engineering changes.
  • Localization – process of adapting internationalized applications for a specific region or language by adding locale-specific components and translating text.

OK, this is how message bundles look like:

exception.npe=Unrecognized error: We're sorry.

and the project view so you get a feel on how maven-managed multi-module project is structured (i use IntelliJ IDEA)



The ‘resourceBundle’ spring bean is located in ‘spring-locale-context.xml’

<bean id="resourceBundle"
      p:defaultEncoding="UTF-8" />


As you can see i’m using ‘ReloadableResourceBundleMessageSource‘ which i prefer over ‘ResourceBundleMessageSource‘ – here’s why (according to Spring framework spec.)

  • ResourceBundleMessageSource – MessageSource implementation that accesses resource bundles using specified basenames. This class relies on the underlying JDK’s ResourceBundle implementation, in combination with the JDK’s standard message parsing provided by MessageFormat. This MessageSource caches both the accessed ResourceBundle instances and the generated MessageFormats for each message. It also implements rendering of no-arg messages without MessageFormat, as supported by the AbstractMessageSource base class. The caching provided by this MessageSource is significantly faster than the built-in caching of the java.util.ResourceBundle class. Unfortunately, java.util.ResourceBundle caches loaded bundles forever: Reloading a bundle during VM execution is not possible. As this MessageSource relies on ResourceBundle, it faces the same limitation. Consider ReloadableResourceBundleMessageSource for an alternative that is capable of refreshing the underlying bundle files.
  • ReloadableResourceBundleMessageSource – Spring-specific MessageSource implementation that accesses resource bundles using specified basenames, participating in the Spring ApplicationContext‘s resource loading. In contrast to the JDK-based ResourceBundleMessageSource, this class uses Properties instances as its custom data structure for messages, loading them via a PropertiesPersister strategy from Spring Resource handles. This strategy is not only capable of reloading files based on timestamp changes, but also of loading properties files with a specific character encoding. It will detect XML property files as well. In contrast to ResourceBundleMessageSource, this class supports reloading of properties files through the "cacheSeconds" setting, and also through programmatically clearing the properties cache. Since application servers typically cache all files loaded from the classpath, it is necessary to store resources somewhere else (for example, in the “WEB-INF” directory of a web app). Otherwise changes of files in the classpath will not be reflected in the application. This MessageSource implementation is usually slightly faster than ResourceBundleMessageSource, which builds on ResourceBundle – in the default mode, i.e. when caching forever. With “cacheSeconds” set to 1, message lookup takes about twice as long – with the benefit that changes in individual properties files are detected with a maximum delay of 1 second. Higher “cacheSeconds” values usually do not make a significant difference.


Now, let’s make our resourceBundle accessible to exception handlers:

public class AbstractExceptionHandler {

    private ReloadableResourceBundleMessageSource resourceBundle;

    public ReloadableResourceBundleMessageSource getResourceBundle() {
        return resourceBundle;

    public void setResourceBundle(ReloadableResourceBundleMessageSource resourceBundle) {
        this.resourceBundle = resourceBundle;



Create an MVC REST Controller:

@RequestMapping(value = "/users")
public class UserController {

    private UserService service;

     * Handling GET request to retrieve all {@link User}'s
     * @return Collection<User> a collection of users
    @RequestMapping(method = RequestMethod.GET)
    public @ResponseBody
    Collection<User> getUsers() {
        return service.findAllUsers();



…and an exception handler that will intercept (NPE in this case) exceptions thrown by the controller:

public class BusinessExceptionHandler extends AbstractExceptionHandler {

    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody DefaultErrorMessage handleNullPointerException() {

        String error = getResourceBundle().getMessage("exception.npe", null, Locale.getDefault());

        return new DefaultErrorMessage("RS00230", "SYSTEM_ERROR", error);




As you can see above, I did two things:

  • fed the error string with exception.npe message that comes from the message bundle and used Locale.getDefault()
  • and defined a custom DefaultErrorMessage which basically is a POJO send over to the client as a JSON response which looks like this:
  "code" : "RS00230",
  "status" : "SYSTEM_ERROR",
  "errors" : [ "Unrecognized error: We're sorry." ]


Hope you find this brief example helpful. Cheers!




MOM and JMS primer (ActiveMQ example)

I’ve been reading recently a very good book on Message-oriented middleware (MOM) broker server Apache ActiveMQ which is an open source implementation of the Java Message Service (JMS) spec. and makes for a reliable hub in any message-oriented enterprise application and integrates beautifully with Java EE containers, ESBs, and other JMS providers.

The book “ActiveMQ in Action” (authored by Bruce Snyder, Dejan Bosanac, and Rob Davies) starts from the anatomy of a JMS message and moves quickly through connectors, message persistence, authentication, and authorization.

Please find below few notes i made while reading:


Standard Message Headers:


  • Header Field: JMSDestination
  • Set By: JMS provider
  • Set mode: auto
  • Meaning: where to send the message
  • Example: queue://


  • Header Field: JMSDeliveryMode
  • Set By: JMS provider
  • Set mode: auto
  • Meaning: persistent or non-persistent*
  • Example: Persistent


  • Header Field: JMSExpiration
  • Set By: JMS provider
  • Set mode: auto
  • Meaning: when should the message expire (in ms)
  • Example: 0 (never)


  • Header Field: JMSPriority
  • Set By: JMS provider
  • Set mode: auto
  • Meaning: priority 0-9 (0-4 normal, 5-9 expedited)
  • Example: 4 (standard)


  • Header Field: JMSDestination
  • Set By: JMS provider
  • Set mode: auto
  • Meaning: identifier of the message
  • Example: ID:POL-MPRZYDATEK-63606-1370265295842-1:2:1:1:1


  • Header Field: JMSTimestamp
  • Set By: JMS provider
  • Set mode: auto
  • Meaning: when the event occurred
  • Example: 2013-06-03 15:15:27:196 CEST


  • Header Field: JMSCorrelationID
  • Set By: JMS Client
  • Set mode: manual
  • Meaning: link one message with another (eg. conversation-style msg. ex.)


  • Header Field: JMSReplyTo
  • Set By: JMS Client
  • Set mode: manual
  • Meaning: where (destination) is the reply expected


  • Header Field: JMSType
  • Set By: JMS Client
  • Set mode: manual
  • Meaning: used by few vendors to semantically identify the message type


  • Header Field: JMSRedelivered
  • Set By: JMS provider
  • Set mode: auto
  • Meaning: if set to true, it is likely that the msg was delivered but not acknowledged
  • Example: false

* Persistent messages are intended to survive system failures of the JMS provider (the message server). Persistent messages are written to disk as soon as the message server receives them from the JMS client. After the message is persisted to disk the message server can then attempt to deliver the message to its intended consumer. As the messaging server delivers the message to the consumers it keeps track of which consumers successfully receive the message. If the JMS provider fails while delivering the message, the message server will pick up where it left off following a recovery. Persistent messages are delivered once-and-only-once. Persistent messages incur
more overhead due to the need to store the message, and value reliability over performance.
* Nonpersistent messages are not written to disk when they are received by the message server, so if the JMS provider fails, the message will be lost. In general nonpersistent messages perform better than persistent messages. They are delivered more quickly and require less system resources on the message server. However, nonpersistent messages should only be used when a loss of messages due to a JMS provider failures is not an issue.


Request/reply messaging pattern

  • is an asynchronous back-and-forth conversational pattern utilizing either the PTP domain or the pub/sub domain through a combination of the JMSReplyTo and JMSCorrelationID message headers and temporary destinations.
  • The JMSReplyTo specifies the destination where a reply should be sent, and the JMSCorrelationID in the reply message specifies the JMSMessageID of the request message.
  • These headers are used to link the reply message(s) to the original request message.
  • Temporary destinations are those that are created only for the duration of a connection and can only be consumed from by the connection that created them.
  • These restrictions make temporary destinations useful for request/reply.


Distinguishing message durability from message persistence

  • Message durability can only be achieved with the pub/sub domain. When clients connect to a topic, they can do so using a durable or a nondurable subscription
    • Durable subscription—A durable subscription is infinite. It’s registered with the topic subscription to tell the JMS provider to preserve the subscription state in the event that the subscriber disconnects. If a durable subscriber disconnects the JMS provider will hold all messages until that subscriber connects again or until the subscriber explicitly unsubscribes from the topic.
    • Nondurable subscription—A nondurable subscription is finite. It’s registered with the topic subscription to tell the JMS provider to not preserve the subscription state in the event that the subscriber disconnects. If a subscriber disconnects, the JMS provider won’t hold any messages during the disconnection period
    • Message persistence is independent of the message domain. Message persistence is a quality of service property used to indicate the JMS application’s ability to handle missing messages in the event of a JMS provider failure


Four types of message persistence:

  • KahaDB
    • recommended message store for general-purpose messages since ActiveMQ version 5.3 is KahaDB.
    • a file-based message store that combines a transactional journal, for reliable message storage and recovery, with good performance and scalability
    • the structure of the KahaDB store has been streamlined especially for the requirements of a message broker.
    • The KahaDB message store uses a transactional log for its indexes and only uses one index file for all its destinations.
    • It’s been used in production environments with 10,000 active connections, each connection having a separate queue
  • AMQ
    • like KahaDB, is a combination of a transactional journal for reliable persistence (to survive system crashes) and high-performance indexes, which makes this store the best option when message throughput is the main requirement for an application.
    • But because it uses two separate files for every index, and there’s an index per destination, the AMQ message store shouldn’t be used if you intend to use thousands of queues per broker.
    • Also, recovery can be slow if the ActiveMQ broker isn’t shut down cleanly. This is because all the indexes need to be rebuilt, which requires the broker to traverse all its data logs to accurately build the indexes again.
  • JDBC
    • JDBC persistence is definitely not superior in performance to KahaDB nor AMQ
    • the use of a shared database is particularly useful for making a redundant master/slave topology out of multiple brokers. When a group of ActiveMQ brokers is configured to use a shared database, they’ll all try to connect and grab a lock in the lock table, but only one will succeed and become the master. The remaining brokers will be slaves, and will be in a wait state, not accepting client connections until the master fails.
  • memory
    • memory message store holds all persistent messages in memory. No active caching is involved, so you have to be careful that both the JVM and the memory limits you set for the broker are large enough to accommodate all the messages that may exist in this message store at one time.
    • The memory message store can be useful if you know that the broker will only store a finite amount of messages, which will typically be consumed quickly


Caching messages in the broker for consumers

  • Although one of the most important aspects of message persistence is that the messages will survive in long-term storage, there are a number of cases where messages are required to be available for consumers that were disconnected from the broker, but persisting the messages in a data store is too slow
  • ActiveMQ supports the caching of messages for these types of systems using message caching in the broker by using something called a subscription recovery policy. This configurable policy is used for deciding which types of messages should be cached, how many, and for how long
  • subscription recovery policies:
    • fixed (memory) size subscription recovery policy
    • fixed count (messages) subscription recovery policy
    • query-based subscription recovery policy – Caches only messages that match the query
    • timed subscription recovery policy (The time in milliseconds to keep messages in the cache
    • NO SUBSCRIPTION RECOVERY POLICY (disables message caching for topics)



  • Simple authentication plug-in—Handles credentials directly in the XML configuration file or in a properties file
  • JAAS authentication plug-in—Implements the JAAS API and provides a more powerful and customizable authentication solution (JAAS provides pluggable authentication, which means ActiveMQ will use the same authentication API regardless of the technique used to verify user credentials (a text file, a relational database, LDAP, and so on)
  • custom plug-in for handling security (BrokerFilter implementation)



  • operation-level
    • Read—The ability to receive messages from the destination
    • Write—The ability to send messages to the destination
    • Admin—The ability to administer the destination
  • message-level
    • remote address
    • message headers


Hope you find this short summary useful.


Disabling SSL Certificate Validation

Recently i came across two SSL-related exceptions when writing a testing Spring-based client application using RestTemplate. Because both of them are related to an untrusted connection when making HTTPS calls (as a result of self-signed SSL certificate configured in Tomcat), and both have one common solution, i thought i’ll share it with You.


Exceptions thrown:

  • No name matching found; nested exception is
  • PKIX path building failed: unable to find valid certification path to requested target


  • disabling SSL certificate validation (unless you want to go the “hard way” of installing a correct/SSL Authority-signed certificate)
  • This is how i did it in Java:



public class SSLCertificateValidation {

    public static void disable() {
        try {
            SSLContext sslc = SSLContext.getInstance("TLS");
            TrustManager[] trustManagerArray = { new NullX509TrustManager() };
            sslc.init(null, trustManagerArray, null);
            HttpsURLConnection.setDefaultHostnameVerifier(new NullHostnameVerifier());
        } catch(Exception e) {

    private static class NullX509TrustManager implements X509TrustManager {
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];

    private static class NullHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;


The complete example is available as a Gist.


What you now have to do, is to invoke SSLCertificateValidation.disable() prior to making a HTTPS call using RestClient. Simple as that.