Consuming Jive REST API

Version 1

    Introduction

     

    I was looking for data migration capabilities from an external system into Jive. The first thing that came up was using the REST API. Which makes absolutely sense because the data contains also documents. By using the REST interface we don't need to know about the underlying database schema and the documents gets indexed and are immediately available.

    With this in mind i decided to setup an Spring integration project which reads from the external source and writes to the Jive target system. Spring comes with a set of tools such as the RestTemplate which integrates with MessageConverters and so on. Setting up such a project takes just minutes. The bad thing is that the Jive REST API responses are not returning pure JSON objects. So wiring up and using the RestTemplate along with the Jackson message converter is not possible.

     

    How to

     

    First of all we have to replace the RestTemplate functionality with something that can handle those responses. This is a http client implementation from the apache project.

    Tackling the preemptive auth requires a client context holding the auth cache and credentials. Therefore i created a context factory which is able to wire up this.

     

    public class HttpContextFactory {

       

        @Autowired

        private RestConfiguration configuration;

       

        private String host;

     

        private int port = -1;

     

        private String schema;

       

        public void init () {

             host = configuration.getHost();

             port = configuration.getPort();

             schema = configuration.getSchema();

        }

     

        public HttpClientContext getClientContext(String username, String password) {

     

        HttpHost targetHost = new HttpHost(host, port, schema);

     

        CredentialsProvider credsProvider = new BasicCredentialsProvider();

        credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()),

            new UsernamePasswordCredentials(username, password));

     

        // Create AuthCache instance along with basic schema

        AuthCache authCache = new BasicAuthCache();

        BasicScheme basicAuth = new BasicScheme();

        authCache.put(targetHost, basicAuth);

     

        // Add AuthCache to the execution context

        HttpClientContext context = HttpClientContext.create();

        context.setCredentialsProvider(credsProvider);

        context.setAuthCache(authCache);

     

        return context;

     

        }

     

    }

     

    The http client implementation give us the posibility to use a ResponseHandler. As a first test i implemented this accessing my profile:

     

    public class UserResponseHandler implements ResponseHandler<User> {

     

        private ObjectMapper objectMapper = new ObjectMapper();

     

        @Override

        public User handleResponse(HttpResponse response) throws ClientProtocolException {

     

        try {

           

            // parse the response

            StringWriter writer = new StringWriter();

            IOUtils.copy(response.getEntity().getContent(), writer, Charset.forName("UTF-8"));

            String jsonObject = writer.toString().replace("throw 'allowIllegalResourceCall is false.';", "");

     

            // map the json to an object

            return objectMapper.readValue(jsonObject, User.class);

           

        } catch (JsonParseException jpe) {

     

        } catch (JsonMappingException jme) {

     

        } catch (IOException ioe) {

     

        }

     

        return null;

        }

     

    }

     

    First of all we need to skip the first line from the response. This is the place where we can use the Jackson deserializing. The user class looks like this:

     

    @JsonIgnoreProperties(ignoreUnknown = true)

    public class User {

     

        private long id;

     

        private Map<String, String>[] emails;

       

        private String displayName;

       

        public long getId() {

            return id;

        }

     

        public void setId(long id) {

            this.id = id;

        }

     

        public String getDisplayName() {

            return displayName;

        }

     

        public void setDisplayName(String displayName) {

            this.displayName = displayName;

        }

     

     

        public Map<String, String>[] getEmails() {

            return emails;

        }

     

        public void setEmails(Map<String, String>[] emails) {

            this.emails = emails;

        }

    }

     

    With this in place and some configuration wiring calling the REST API is just a view lines:

     

    HttpGet httpget = new HttpGet( serviceEndpoint + "/username/xxx");

    ResponseHandler<User> responseHandler = new UserResponseHandler();

    httpclient.execute(host, httpget, responseHandler, httpClientContextFactory.getClientContext());


    Let me know if there are other options how to tackle this.