calling request trigger url of azure logic app from RestTemplate java

Viewed 838

I have Azure logic app with request trigger. I want to trigger this logic app from my java application. So, I am trying to call the request trigger url from my java API.

It is working fine if i am using DefaultHttpClient but getting 401 on calling it using RestTemplate in java.

DefaultHttpClient code:

try {
    DefaultHttpClient httpClient = new DefaultHttpClient();

    HttpGet getRequest = new HttpGet(
        "{url of azure logic app trigger}");

    //StringEntity input = new StringEntity("{\"qty\":100,\"name\":\"iPad 4\"}");
    //input.setContentType("application/json");
    //postRequest.setEntity(input);

    HttpResponse response = httpClient.execute(getRequest);

    BufferedReader br = new BufferedReader(
                    new InputStreamReader((response.getEntity().getContent())));

    String output;
    System.out.println("Output from Server .... \n");
    while ((output = br.readLine()) != null) {
        System.out.println(output);
    }


    httpClient.getConnectionManager().shutdown();
    return("Success");
} catch (ClientProtocolException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return("Error");
} catch (UnsupportedOperationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return("Error");
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    return("Error");
}

RestTemplate Code

@Service
public class SampleService {
@Autowired HttpClientService<String, String> httpClientService;
public String callURL() {
ResponseErrorHandler responseErrorHandler = new ResponseErrorHandler() {

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        System.out.print(response.toString());
        return false;
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        // TODO Auto-generated method stub
    }
};
UriComponentsBuilder builder = UriComponentsBuilder
        .fromUriString("{logic app url}")
        // Add query parameter
        .queryParam("api-version", {api-version})
        .queryParam("sp", {sp})
        .queryParam("sv", {sv})
        .queryParam("sig",{sig});

RequestDetailsDAO requestDetails = new RequestDetailsDAO(builder.build().toUri().toString(), HttpMethod.GET);
String response = httpClientService.execute(requestDetails, null, responseErrorHandler, String.class);
return response.toString();

HttpClientService.java

@Service
public class HttpClientService<T, V>  {
public RestTemplate restTemplate;

public HttpClientService(RestTemplateBuilder restTemplateBuilder) {
    this.restTemplate = restTemplateBuilder.setConnectTimeout(Duration.ofSeconds(5)).setReadTimeout(Duration.ofSeconds(5)).build();
}

public V execute(RequestDetailsDAO requestDetails, HttpEntity<T> entity, ResponseErrorHandler errorHandler,
                 Class<V> genericClass) {

    restTemplate.setErrorHandler(errorHandler);

    ResponseEntity<V> response = restTemplate.exchange(requestDetails.getUrl(), requestDetails.getRequestType(), entity, genericClass);
    return response.getBody();
}
}

RequestDetailsDAO.java

public class RequestDetailsDAO {
private String url;
private HttpMethod requestType;

public RequestDetailsDAO(String url, HttpMethod requestTyp) {
    super();
    this.url = url;
    this.requestType = requestTyp;
}
public String getUrl() {
    return url;
}
public void setUrl(String url) {
    this.url = url;
}
public HttpMethod getRequestType() {
    return requestType;
}
public void setRequestType(HttpMethod requestType) {
    this.requestType = requestType;
}

@Override
public String toString() {
    return "RequestDetails [url=" + url + ", requestType=" + requestType + "]";
}
}
2 Answers

So, it seems that there's nothing special about LogicApps being called using RestTemplate. It's just that RestTemplate by default URL encode the Uri given in parameter, and DefaultHttpClient does not - reference: apache vs resttemplate

In case of LogicApp URL, there is this "sp" parameter which is already URL endcoded, when you copy it from LogicApp - "%2Ftriggers%2Fmanual%2Frun", so you need to decode that and pass "/triggers/manual/run" to UriComponentsBuilder. And then it works.

My code:

    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    HttpEntity<Object> request = new HttpEntity<>(requestDto, headers);

    UriComponentsBuilder builder = UriComponentsBuilder
            .fromUriString("https://prod-123901.westeurope.logic.azure.com:443/workflows/<workflow_id>/triggers/manual/paths/invoke")
            .queryParam("api-version", "2016-10-01")
            .queryParam("sp", "/triggers/manual/run")
            .queryParam("sv", "1.0")
            .queryParam("sig", "<your_sig>");
    restTemplate.exchange(builder.build().toUri().toString(), HttpMethod.POST, request, Void.class);

update:

requestDto here is your custom dto object that goes in HTTP Body, like for example object of class:

public class RequestDto {
    private String id;
    private String name;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Please try with the simple standalone code with RestTemplate and check. I provide below small snippet.

try {
    ResponseEntity<ResponseVO> response = restTemplate.exchange({uri of azure logic app trigger}, HttpMethod.GET, request, ResponseVO.class);
} catch (HttpStatusCodeException ex) {
    int statusCode = ex.getStatusCode().value();
    System.out.println("Status Code :"+statusCode);
    ResponseEntity<?> resEntity = ResponseEntity.status(ex.getRawStatusCode()).headers(ex.getResponseHeaders())
                .body(ex.getResponseBodyAsString())
}

Here ResponseVO.class is the Response to be mapped to an object, in this case, you can set your own class. In this catch block, you can find the exception details.

Related