RESTUtils.java

  1. /*******************************************************************************
  2.  * Copyright 2018 IIT-CNR
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5.  * use this file except in compliance with the License. You may obtain a copy
  6.  * of the License at
  7.  *
  8.  * http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12.  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13.  * License for the specific language governing permissions and limitations under
  14.  * the License.
  15.  ******************************************************************************/
  16. package it.cnr.iit.utility;

  17. import java.net.MalformedURLException;
  18. import java.net.URI;
  19. import java.net.URL;
  20. import java.util.Optional;
  21. import java.util.concurrent.CompletableFuture;
  22. import java.util.function.Supplier;
  23. import java.util.logging.Level;
  24. import java.util.logging.Logger;

  25. import org.springframework.http.HttpEntity;
  26. import org.springframework.http.HttpHeaders;
  27. import org.springframework.http.MediaType;
  28. import org.springframework.http.ResponseEntity;
  29. import org.springframework.web.client.RestTemplate;
  30. import org.springframework.web.reactive.function.BodyInserters;
  31. import org.springframework.web.reactive.function.client.WebClient;

  32. import it.cnr.iit.utility.errorhandling.Reject;

  33. import reactor.core.publisher.Mono;

  34. /**
  35.  * This class provides some static methods to perform synchronous or asynchronous
  36.  * rest operations.
  37.  *
  38.  * @author Antonio La Marra, Alessandro Rosetti
  39.  *
  40.  */
  41. public final class RESTUtils {

  42.     private static final Logger log = Logger.getLogger( RESTUtils.class.getName() );

  43.     private static final String MSG_ERR_POST = "Error posting to : {0}";

  44.     private RESTUtils() {

  45.     }

  46.     public static Optional<ResponseEntity<Void>> post( String baseUri, String api, Object obj ) {
  47.         return post( baseUri, api, obj, Void.class );
  48.     }

  49.     public static Optional<URI> parseUri( String str ) {
  50.         try {
  51.             URI uri = new URI( str );
  52.             return Optional.of( uri );
  53.         } catch( Exception e ) {
  54.             log.severe( e.getLocalizedMessage() );
  55.         }
  56.         return Optional.empty();
  57.     }

  58.     public static Optional<String> joinUrl( String base, String api ) {
  59.         try {
  60.             return Optional.of( new URL( new URL( base ), api ).toString() );
  61.         } catch( MalformedURLException e ) {
  62.             return Optional.empty();
  63.         }
  64.     }

  65.     public static <T, E> Optional<ResponseEntity<T>> post( String baseUri, String api, E obj, Class<T> responseClass ) {
  66.         Optional<String> url = joinUrl( baseUri, api );
  67.         Reject.ifAbsent( url );

  68.         Optional<String> jsonString = JsonUtility.getJsonStringFromObject( obj, false );
  69.         if( !jsonString.isPresent() ) {
  70.             return Optional.empty();
  71.         }

  72.         HttpHeaders headers = new HttpHeaders();
  73.         headers.setContentType( MediaType.APPLICATION_JSON );
  74.         HttpEntity<String> entity = new HttpEntity<>( jsonString.get(), headers );
  75.         RestTemplate restTemplate = new RestTemplate();
  76.         ResponseEntity<T> responseEntity = restTemplate.postForEntity( url.get(), entity, responseClass ); // NOSONAR

  77.         checkResponesEntity( responseEntity );

  78.         return Optional.of( responseEntity );
  79.     }

  80.     public static <E> CompletableFuture<ResponseEntity<Void>> asyncPost( String baseUri, String api, E obj ) {
  81.         return asyncPost( baseUri, api, obj, Void.class );
  82.     }

  83.     public static <T, E> CompletableFuture<ResponseEntity<T>> asyncPost( String baseUri, String api, E obj, Class<T> clazz ) {
  84.         Mono<ResponseEntity<T>> response = WebClient
  85.             .create( baseUri )
  86.             .post()
  87.             .uri( api )
  88.             .contentType( MediaType.APPLICATION_JSON )
  89.             .body( BodyInserters.fromObject( obj ) )
  90.             .exchange()
  91.             .flatMap( r -> r.toEntity( clazz ) );

  92.         return CompletableFuture.supplyAsync( getResponseEntity( response ) );
  93.     }

  94.     private static <T> Supplier<ResponseEntity<T>> getResponseEntity( Mono<ResponseEntity<T>> response ) {
  95.         return () -> {
  96.             ResponseEntity<T> responseEntity = response.block();
  97.             checkResponesEntity( responseEntity );
  98.             return responseEntity;
  99.         };
  100.     }

  101.     private static <T> void checkResponesEntity( ResponseEntity<T> responseEntity ) {
  102.         if( !responseEntity.getStatusCode().is2xxSuccessful() ) {
  103.             String uri = responseEntity.getHeaders().getLocation().toString();
  104.             log.log( Level.SEVERE, MSG_ERR_POST, uri );
  105.         }
  106.     }
  107. }