All Downloads are FREE. Search and download functionalities are using the official Maven repository.

es.prodevelop.pui9.utils.PuiExternalRequest Maven / Gradle / Ivy

package es.prodevelop.pui9.utils;

import java.util.Collections;
import java.util.Iterator;

import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClientResponseException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
import org.springframework.web.util.UriComponentsBuilder;

import es.prodevelop.pui9.data.converters.PuiGsonHttpMessageConverter;
import es.prodevelop.pui9.exceptions.PuiException;

/**
 * Utility class to make external request from PUI server to anywhere. POST and
 * GET methods are accepted. It uses the {@link RestTemplate} object of Spring
 * to make the requests
 * 
 * @author Marc Gil - [email protected]
 */
public class PuiExternalRequest {

	private static PuiExternalRequest singleton;
	private static final int defaultTimeout = 10000;

	public static PuiExternalRequest getSingleton() {
		if (singleton == null) {
			singleton = new PuiExternalRequest();
		}
		return singleton;
	}

	private final RestTemplate restTemplate;
	private final HttpHeaders httpHeaders;

	/**
	 * Configure the {@link RestTemplate} object with the valid converters for PUI
	 */
	private PuiExternalRequest() {
		restTemplate = new RestTemplate();
		httpHeaders = new HttpHeaders();

		if (restTemplate.getRequestFactory() instanceof SimpleClientHttpRequestFactory) {
			configureTemplateSetTimeouts(defaultTimeout);
		}

		configureTemplateRemoveJackson();
		configureTemplateSetConverters();
		configureTemplateEncoding();
		configureTemplateHeaders();
	}

	/**
	 * Change the timeout of the request. By default, 10000 milliseconds are set if
	 * the milliseconds parameter is null
	 * 
	 * @param milliseconds
	 */
	public void configureTemplateSetTimeouts(Integer milliseconds) {
		if (milliseconds == null) {
			milliseconds = defaultTimeout;
		}
		SimpleClientHttpRequestFactory factory = (SimpleClientHttpRequestFactory) restTemplate.getRequestFactory();
		factory.setReadTimeout(milliseconds);
		factory.setConnectTimeout(milliseconds);
	}

	protected void configureTemplateRemoveJackson() {
		for (Iterator> it = restTemplate.getMessageConverters().iterator(); it.hasNext();) {
			HttpMessageConverter next = it.next();
			if (next instanceof org.springframework.http.converter.json.GsonHttpMessageConverter
					|| next.getClass().getSimpleName().contains("Jackson")
					|| next instanceof AllEncompassingFormHttpMessageConverter) {
				it.remove();
			}
		}
	}

	protected void configureTemplateSetConverters() {
		PuiGsonHttpMessageConverter gsonConverter = new PuiGsonHttpMessageConverter();
		restTemplate.getMessageConverters().add(0, gsonConverter);
	}

	protected void configureTemplateEncoding() {
		DefaultUriBuilderFactory uriFactory = new DefaultUriBuilderFactory();
		uriFactory.setEncodingMode(EncodingMode.VALUES_ONLY);
		restTemplate.setUriTemplateHandler(uriFactory);
	}

	protected void configureTemplateHeaders() {
		httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		httpHeaders.setContentType(MediaType.APPLICATION_JSON);
	}

	/**
	 * Execute a GET request. This call is synchonous
	 * 
	 * @param url         The URL to be called. If you need to provide parameters,
	 *                    use the "params" attribute instead
	 * @param returnClass The type of the returning object (can be null if no
	 *                    response is expected)
	 * @param params      The list of parameters to be attached to the URL (can be
	 *                    null or empty)
	 * @param headers     The custom headers to be sent
	 * @return The result of the request as an object of the indicated type
	 * @throws PuiException If any exception is thrown in the request
	 */
	public  RETURN executeGet(String url, Class returnClass, MultiValueMap params,
			HttpHeaders headers) throws PuiException {
		if (!CollectionUtils.isEmpty(params)) {
			url = UriComponentsBuilder.fromHttpUrl(url).queryParams(params).toUriString();
		}

		HttpEntity entity = new HttpEntity<>(configureHeaders(headers));

		try {
			ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, entity, returnClass);
			return response.getBody();
		} catch (RestClientResponseException e) {
			throw new PuiException(e);
		}
	}

	/**
	 * Execute a POST request. This call is synchonous.
	 * 
	 * @param url         The URL to be called. If you need to provide parameters,
	 *                    use the "params" attribute instead
	 * @param returnClass The type of the returning object (can be null if no
	 *                    response is expected)
	 * @param body        The Body of the request (can be null)
	 * @param params      The list of parameters to be attached to the URL (can be
	 *                    null or empty)
	 * @param headers     The custom headers to be sent
	 * @return The result of the request as an object of the indicated type
	 * @throws PuiException If any exception is thrown in the request
	 */
	public  RETURN executePost(String url, Class returnClass, BODY body,
			MultiValueMap params, HttpHeaders headers) throws PuiException {
		if (!CollectionUtils.isEmpty(params)) {
			url = UriComponentsBuilder.fromHttpUrl(url).queryParams(params).toUriString();
		}

		HttpEntity entity = new HttpEntity<>(body, configureHeaders(headers));

		try {
			ResponseEntity response = restTemplate.postForEntity(url, entity, returnClass);
			return response.getBody();
		} catch (RestClientResponseException e) {
			throw new PuiException(e);
		}
	}

	/**
	 * Execute a POST request. This call is synchonous.
	 * 

* This method is distinct from * {@link #executePost(String, Class, Object, MultiValueMap)}, due to you can * specify a parameterized type instead of a concrete type (for instance, a * typed List or Map) * * @param url The URL to be called. If you need to provide parameters, * use the "params" attribute instead * @param returnType The type of the returning object (can be null if no * response is expected) * @param body The Body of the request (can be null) * @param params The list of parameters to be attached to the URL (can be * null or empty) * @param headers The custom headers to be sent * @return The result of the request as an object of the indicated type * @throws PuiException If any exception is thrown in the request */ public RETURN executePost(String url, ParameterizedTypeReference returnType, BODY body, MultiValueMap params, HttpHeaders headers) throws PuiException { if (!CollectionUtils.isEmpty(params)) { url = UriComponentsBuilder.fromHttpUrl(url).queryParams(params).toUriString(); } HttpEntity entity = new HttpEntity<>(body, configureHeaders(headers)); try { ResponseEntity response = restTemplate.exchange(url, HttpMethod.POST, entity, returnType); return response.getBody(); } catch (RestClientResponseException e) { throw new PuiException(e); } } /** * Configure a new {@link HttpHeaders} using the one provided by the user. If * headers are provided, they override the default headers * * @param headers The headers provided by the user * @return The new headers to be used */ private HttpHeaders configureHeaders(final HttpHeaders headers) { HttpHeaders newHeaders = headers != null ? headers : new HttpHeaders(); httpHeaders.forEach(newHeaders::putIfAbsent); newHeaders.putIfAbsent(HttpHeaders.ACCEPT_LANGUAGE, Collections.singletonList(PuiLanguageUtils.getSessionLanguage().getIsocode())); return newHeaders; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy