Java Ninja Chronicles By Norris Shelton

Things I learned in the pursuit of code

We had a need to submit request header information on every request to a specified system when we submit a REST call. We used the Springframework RestTemplate to perform our REST call. The RestTemplate provides a nice, easy way to modify all outbound requests via the ClientHttpRequestInterceptor interface.

The contents of the interceptor is:

package com.javaninja.core.spring;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

import java.io.IOException;

/**
 * Interceptor for the Rest calls.  The interceptor adds the System-Key that is required in order to authenticate.
 */
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor {
	private Logger logger = LoggerFactory.getLogger(getClass());

    @Value("#{properties.systemKey}")
	private String systemKey;

	/**
	 * The interceptor adds the SYSTEM-Key that they are looking for on their end.
	 *
	 * Intercept the given request, and return a response. The given {@link ClientHttpRequestExecution} allows the
	 * interceptor to pass on the request and response to the next entity in the chain.
	 * <p>
	 * <p>A typical implementation of this method would follow the following pattern:
	 * <ol>
	 *     <li>Examine the {@linkplain HttpRequest request} and body</li>
	 *     <li>Optionally {@linkplain org.springframework.http.client.support.HttpRequestWrapper wrap} the request to filter HTTP attributes.</li>
	 *     <li>Optionally modify the body of the request.</li>
	 * 	   <li><strong>Either</strong>
	 * 	   <ul>
	 * 	       <li>execute the request using {@link ClientHttpRequestExecution#execute(HttpRequest, byte[])},</li>
	 * 	       <strong>or</strong>
	 * 	       <li>do not execute the request to block the execution altogether.</li>
	 * 	   </ul>
	 * 	   <li>Optionally wrap the response to filter HTTP attributes.</li>
	 * </ol>
	 * @param request   the request, containing method, URI, and headers
	 * @param body      the body of the request
	 * @param execution the request execution
	 * @return the response
	 * @throws IOException in case of I/O errors
	 */
	@Override
	public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
	throws IOException {
		HttpHeaders headers = request.getHeaders();
		logger.debug("System-Key : {}", systemKey);
		headers.add("System-Key", systemKey);
		return execution.execute(request, body);
	}
}

Configuring the interceptor is fairly easy. It involves two steps. The first step is to declare the list of interceptors.

    <util:list id="interceptors">
          <bean id="vendorRestTemplateInterceptor" class="com.javaninja.core.spring.RestTemplateInterceptor"/>
    </util:list>

The next step is to associate the interceptors with the desired RestTemplate.

    <bean id="vendorRestTemplate" class="org.springframework.web.client.RestTemplate"
         p:interceptors-ref="interceptors"/>

Once you have that, you can use the RestTemplate as you normally would. Every outgoing request will have the basic authorization header added to the request automatically. As a note, in that application, we had a RestTemplate with an interceptor that was used to communicate with the vendor and another RestTemplate that did not have an interceptor that was used to communicate with an internal system.

December 9th, 2015

Posted In: Java, java ninja, Javaninja, Spring

Tags: , , , , , , ,

Leave a Comment

The dotCMS JSON API is pretty easy to use. It even tells you the query for the content that you are looking for. That makes it super easy to use. What I didn’t know was that the results default to a limit of 10 records.

Here was my original query.

http://youbet.com/api/content/render/false/query/+structureName:PokerTableNameAdjectives%20+(conhost:915f2552-793a-4f17-96d0-f0955fcc698f%20conhost:SYSTEM_HOST)%20+languageId:1*%20+deleted:false%20%20+working:true/orderby/modDate%20desc/limit/30

That was easy enough, but how to you specify more? You specify the optional limit. It’s pretty easy, once you know what you are looking for.

/api/content/limit/<integer-limit>

That was easy enough. Here is what the final query looks like.

http://youbet.com/api/content/render/false/query/+structureName:PokerTableNameAdjectives%20+(conhost:915f2552-793a-4f17-96d0-f0955fcc698f%20conhost:SYSTEM_HOST)%20+languageId:1*%20+deleted:false%20%20+working:true/orderby/modDate%20desc/api/content/limit/1000

February 26th, 2015

Posted In: Java, java ninja, Javaninja

Tags: , , , , ,

Leave a Comment

The usual usage of a Springframework RestTemplate is to get back an object. Sometimes the object will contain a list. What needs to happen when you need to get back a list of Strings? RestTemplate accepts a parameter that tells it what the data it receives will be put in. I used a String array. It converts the JSON object into a String[] and away I go.

                    String[] pokerTableNames =
                        restTemplate.getForObject(pokerSettingsService.getValueByName(PokerSettings.IGP_ADAPTER_URL) + "/poker/tableNames",
                            String[].class);

February 20th, 2015

Posted In: Java, java ninja, Javaninja, json, Spring

Tags: , , , , , , ,

Leave a Comment

I had a RESTful call to a dotCMS 2.x server worked out. I called it later in the day and a new property was being sent. This resulted in the following exception.

Method threw 'com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException' exception.
class com.cdi.igp.models.dotcms.PokerClient
stInode
 size = 3
 (3 known properties: "version", "whatsNew", "clientType"])
 size = 3
[Source: {"contentlets":[{...removed for brevity...}]}; line: 1, column: 29]
Unrecognized field "stInode" (class com.cdi.igp.models.dotcms.PokerClient), not marked as ignorable
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "stInode" (class com.cdi.igp.models.dotcms.PokerClient), not marked as ignorable (3 known properties: "version", "whatsNew", "clientType"])
 at [Source: ...removed for brevity...]}; line: 1, column: 29] (through reference chain: com.cdi.igp.core.dotcms.DotCmsPokerClientResponse["contentlets"]->java.util.ArrayList[0]->com.cdi.igp.models.dotcms.PokerClient["stInode"])

 size = 0

I fixed it by adding the following to the top of the class that I was mapping the data into.

@JsonIgnoreProperties(ignoreUnknown = true)

Problem solved.

February 3rd, 2015

Posted In: Java, java ninja, Javaninja

Tags: , , , , , , ,

Leave a Comment

Using the Springframework RestTemplate is usually fairly straight forward. In this case, it didn’t work. I had a URL that would work when I pasted it into the web browser and would also work in the Chrome Advanced Rest Client. Each time I tried to call it with a Spring Rest Template, I got a HTTP 406.

    /**
     * Gets the poker client content objects from dotCMS.
     * @return poker clients model object
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public PokerClientsModel getPokerClients() throws InvocationTargetException, IllegalAccessException {

        String url = settingRepository.findSettingByIdSetting(SettingEnum.HOST_URL.key()).getValue() +
            "/api/content/render/false/query/+structureName:PokerClient%20+" +
            "(conhost:915f2552-793a-4f17-96d0-f0955fcc698f%20conhost:SYSTEM_HOST)" +
            "%20+languageId:1*%20+deleted:false%20%20+working:true/orderby/modDate%20desc";

        DotCmsPokerClientResponse dotCmsPokerClientResponse = restTemplate.getForObject(url,
                                                                                        DotCmsPokerClientResponse.class);
        PokerClientsModel pokerClientsModel = new PokerClientsModel();
        PokerClient pokerClient;
        for (DotCmsPokerClient dotCmsPokerClient : dotCmsPokerClientResponse.getDotCmsPokerClients()) {
            pokerClient = new PokerClient();
            BeanUtils.copyProperties(pokerClient, dotCmsPokerClient);
            pokerClientsModel.getPokerClients().add(pokerClient);
        }

        return pokerClientsModel;

    }

That just plain didn’t work.

Method threw 'org.springframework.web.client.HttpClientErrorException' exception.
406
Not Acceptable

 size = 8
UTF-8
406 Not Acceptable
org.springframework.web.client.HttpClientErrorException: 406 Not Acceptable

 size = 0

I thought about what the browser could be sending that I wasn’t. It hit me that the browser may be sending the content type as text/plain. It is a bit of a pain in the rear-end to send a content type on a get request. I eventually got to set the content type by using the Http Entity.

    /**
     * Gets the poker client content objects from dotCMS.
     * @return poker clients model object
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public PokerClientsModel getPokerClients() throws InvocationTargetException, IllegalAccessException {

        String url = settingRepository.findSettingByIdSetting(SettingEnum.HOST_URL.key()).getValue() +
            "/api/content/render/false/query/+structureName:PokerClient%20+" +
            "(conhost:915f2552-793a-4f17-96d0-f0955fcc698f%20conhost:SYSTEM_HOST)" +
            "%20+languageId:1*%20+deleted:false%20%20+working:true/orderby/modDate%20desc";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.TEXT_PLAIN);

        HttpEntity entity = new HttpEntity(headers);
        HttpEntity<String> dotCmsPokerClientResponse = restTemplate.exchange(url,
                                                                             HttpMethod.GET,
                                                                             entity,
                                                                             String.class);
        return pokerClientsModel;
    }

This did work better. No more HTTP 406, but the return object contained a blank contentlets array.

<200 OK,{"contentlets":[]},{Date=[Mon, 02 Feb 2015 15:26:09 GMT], Server=[Apache-Coyote/1.1], Content-Type=, Set-Cookie=[JSESSIONID=8CDC0C67730932FAEBBB729FBA5E2BBA; Path=/, ROUTEID=.1; path=/], Vary=[Accept-Encoding], Keep-Alive=[timeout=5, max=100], Connection=[Keep-Alive], Transfer-Encoding=[chunked]}>

Frustration set in and I was starting to get desperate. I got the idea of using HttpClient directly to make the call.

    /**
     * Gets the poker client content objects from dotCMS.
     * @return poker clients model object
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    public PokerClientsModel getPokerClients() throws InvocationTargetException, IllegalAccessException {

        String url = settingRepository.findSettingByIdSetting(SettingEnum.HOST_URL.key()).getValue() +
            "/api/content/render/false/query/+structureName:PokerClient%20+" +
            "(conhost:915f2552-793a-4f17-96d0-f0955fcc698f%20conhost:SYSTEM_HOST)" +
            "%20+languageId:1*%20+deleted:false%20%20+working:true/orderby/modDate%20desc";

        return get(url);
    }

    /**
     * Performs a HTTP get of the specified URL.
     * @param url the desired URL.
     * @return Http response body as a string
     */
    protected String get(String url) {
        HttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(url);
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        String responseBody = null;
        try {
            responseBody = httpClient.execute(httpGet, responseHandler);
        } catch (IOException e) {
            logger.error("IOException", e);
        } finally {
            // When HttpClient instance is no longer needed,
            // shut down the connection manager to ensure
            // immediate deallocation of all system resources
            httpClient.getConnectionManager().shutdown();
        }
        return responseBody;
    }

Success!!!!!

{"contentlets":[{"stInode":"d5af8654-aa65-4f2f-b2cd-bc6bf54753d5","owner":"norris.shelton","lastReview":"2015-01-30 16:21:56.226","modUser":"norris.shelton","identifier":"42ee0e8c-bd3c-4bae-ac51-b7837dc8e832","version":"000.000.000","clientType":"android","sortOrder":0,"modDate":"2015-01-30 16:21:56.238","host":"915f2552-793a-4f17-96d0-f0955fcc698f","whatsNew":"Initial Android Version","languageId":1,"inode":"ef33dbd6-2e47-44f7-a47f-daaa5c52e74b","folder":"SYSTEM_FOLDER"},{"stInode":"d5af8654-aa65-4f2f-b2cd-bc6bf54753d5","owner":"norris.shelton","lastReview":"2015-01-30 16:21:41.265","modUser":"norris.shelton","identifier":"b670a674-fb54-425a-93b8-432c8443e02d","version":"000.000.000","clientType":"ios","sortOrder":0,"modDate":"2015-01-30 16:21:41.278","host":"915f2552-793a-4f17-96d0-f0955fcc698f","whatsNew":"Initial IOS version","languageId":1,"inode":"929fb049-1c85-4376-bc9f-143981466a0a","folder":"SYSTEM_FOLDER"},{"stInode":"d5af8654-aa65-4f2f-b2cd-bc6bf54753d5","owner":"norris.shelton","lastReview":"2015-01-30 16:21:29.787","modUser":"norris.shelton","identifier":"df0ce56f-8e43-4169-9632-eb05fddd442f","version":"000.000.000","clientType":"flash","sortOrder":0,"modDate":"2015-01-30 16:21:29.8","host":"915f2552-793a-4f17-96d0-f0955fcc698f","whatsNew":"Initial Flash version","languageId":1,"inode":"8ff7fe3f-8064-42cf-8d9a-eaf6f65b52f9","folder":"SYSTEM_FOLDER"}]}

February 2nd, 2015

Posted In: Java, java ninja, Javaninja

Tags: , , , , , , , ,

Leave a Comment

In a previous post HttpClient 4 Json Post I showed how to post a Json object to a URL. That was useful, but required writing a method for each type of object you needed posted. A cleaner way is to use Java Generics to make a method that can accept multiple types of objects and can even return specific objects instead of a Json string.

    /**
     * Returns the http response as the specified object.
     * @param url the url to request
     * @param object the object to convert to the json payload
     * @param responseType the object type to convert the json response into
     * @throws IOException
     */
    public static <T> T postForObject(String url, Object object, Class<T> responseType) throws IOException {
        log.debug("Post: " + url);
        String response = "";
        HttpClient httpclient = new DefaultHttpClient();
        try {
            HttpPost httpPost = new HttpPost(url);
            StringEntity stringEntity = new StringEntity(JsonUtils.toJson(object));
            httpPost.setEntity(stringEntity);
            httpPost.setHeader("Content-type", "application/json");
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            response = httpclient.execute(httpPost, responseHandler);
        } catch (IOException e) {
            log.error("IOException from " + url + " with " + object , e);
            throw e;
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
        return JsonUtils.toObject(response, responseType);
    }

The method return type is modified to return T and the method signature is changed to include Class responseType. Then responseType is used to tell the Json library what type of object is desired.

Here is a simple usage of the post method.

            AccountResponse accountResponse =
                    HttpUtils.postForObject(Server.IGP_ADAPTER_URL + "/accountBalances",
                            accountRequest,
                            AccountResponse.class);

December 11th, 2014

Posted In: Java

Tags: , , , , , , ,

Leave a Comment

Posting JSON to a URL is a common use case. Here is a follow-on to HttpClient Post for a String.

    /**
     * Performs HTTP post.
     * @param url http resource to post
     * @return string response
     */
    protected String post(String url, MyJsonObject myJsonObject) {
        HttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        ResponseHandler<String> responseHandler = new BasicResponseHandler();
        String responseBody = null;
        try {
            HttpPost httpPost = new HttpPost(url);
            StringEntity stringEntity = new StringEntity(JsonUtils.toJson(myJsonObject));
            httpPost.setEntity(stringEntity);
            httpPost.setHeader("Content-type", "application/json");
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            responseBody = httpclient.execute(httpPost, responseHandler);
        } catch (IOException e) {
            log.error("IOException from " + url + " with " + object , e);
            throw e;
        } finally {
            httpclient.getConnectionManager().shutdown();
        }
        return responseBody;
    }

Line 13 and 14 convert the object to be posted into a Json string and set it as the payload to be sent to the URL.
Line 15 sets the content type so the URL knows that you can accept JSON as a response.

December 11th, 2014

Posted In: Java

Tags: , , , ,

5 Comments

Springframework P-notation was made to make creating spring config files a little neater and shorter. Here is what a typical file would look like.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc     http://www.springframework.org/schema/mvc/spring-mvc.xsd
                           http://www.springframework.org/schema/util    http://www.springframework.org/schema/util/spring-util.xsd">

    <context:component-scan base-package="com.cdi.rng"/>
    <mvc:annotation-driven/>

    <util:constant id="mediaTypeJson" static-field="org.springframework.http.MediaType.APPLICATION_JSON"/>

    <bean id="contentNegotiatingViewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="contentNegotiationManager" ref="contentNegotiationManager"/>
    </bean>
    <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
        <property name="defaultContentType" ref="mediaTypeJson"/>
    </bean>

</beans>

Here is what it looks like once the P-notation is used.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/mvc     http://www.springframework.org/schema/mvc/spring-mvc.xsd
                           http://www.springframework.org/schema/util    http://www.springframework.org/schema/util/spring-util.xsd">

    <context:component-scan base-package="com.cdi.rng"/>
    <mvc:annotation-driven/>
    <util:constant id="mediaTypeJson" static-field="org.springframework.http.MediaType.APPLICATION_JSON"/>

    <bean id="contentNegotiatingViewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"
          p:contentNegotiationManager-ref="contentNegotiationManager"/>
    <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"
          p:defaultContentType-ref="mediaTypeJson"/>

</beans>

Springframework P-notation does not add capability, but does reduce the number of characters needed to define the Spring context.

December 8th, 2014

Posted In: Spring

Tags: , , , , , ,

One Comment

LinkedIn Auto Publish Powered By : XYZScripts.com