有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

rest无法使用Java中的Apache Olingo访问Dynamics 365 Business Central

我正在尝试使用Apache Olingo客户端通过REST api和OAuth2连接Dynamics 365 Business Central,出现以下错误:

Exception in thread "main" org.apache.olingo.client.core.http.OAuth2Exception: java.lang.IllegalStateException: Target host is null
    at com.plmc.AzureADOAuth2HttpClientFactoryForDBC.init(AzureADOAuth2HttpClientFactoryForDBC.java:149)
    at org.apache.olingo.client.core.http.AbstractOAuth2HttpClientFactory.create(AbstractOAuth2HttpClientFactory.java:78)
    at org.apache.olingo.client.core.communication.request.AbstractODataRequest.getHttpClient(AbstractODataRequest.java:363)
    at org.apache.olingo.client.core.communication.request.AbstractODataRequest.<init>(AbstractODataRequest.java:105)
    at org.apache.olingo.client.core.communication.request.AbstractODataBasicRequest.<init>(AbstractODataBasicRequest.java:57)
    at org.apache.olingo.client.core.communication.request.retrieve.AbstractODataRetrieveRequest.<init>(AbstractODataRetrieveRequest.java:47)
    at org.apache.olingo.client.core.communication.request.retrieve.ODataEntitySetIteratorRequestImpl.<init>(ODataEntitySetIteratorRequestImpl.java:49)
    at org.apache.olingo.client.core.communication.request.retrieve.RetrieveRequestFactoryImpl.getEntitySetIteratorRequest(RetrieveRequestFactoryImpl.java:101)
    at com.plmc.AccessDBC.main(AccessDBC.java:35)
Caused by: java.lang.IllegalStateException: Target host is null
    at org.apache.http.util.Asserts.notNull(Asserts.java:52)
    at org.apache.http.impl.conn.DefaultHttpRoutePlanner.determineRoute(DefaultHttpRoutePlanner.java:100)
    at org.apache.http.impl.client.DefaultRequestDirector.determineRoute(DefaultRequestDirector.java:756)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:375)
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:835)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
    at com.plmc.AzureADOAuth2HttpClientFactoryForDBC.init(AzureADOAuth2HttpClientFactoryForDBC.java:112)
    ... 8 more

我的主要课程如下:

import java.net.URI;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.olingo.client.api.ODataClient;
import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetIteratorRequest;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.domain.ClientEntity;
import org.apache.olingo.client.api.domain.ClientEntitySet;
import org.apache.olingo.client.api.domain.ClientEntitySetIterator;
import org.apache.olingo.client.core.ODataClientFactory;

public class AccessDBC {

    public static void main(final String[] args) throws Exception {
        String authority ="https://login.windows.net/<company domain>";
        String clientId = "<client ID>";
        String redirectURI = "http://localhost:8080/login";
        String resourceURI = "https://api.businesscentral.dynamics.com/v2.0";
        UsernamePasswordCredentials creds = new UsernamePasswordCredentials(
                        "user name",
                        "password");
        
        final AzureADOAuth2HttpClientFactoryForDBC oauth2HCF = new AzureADOAuth2HttpClientFactoryForDBC(authority, clientId, redirectURI, resourceURI, creds);
        
        String serviceUrl = "https://api.businesscentral.dynamics.com/v2.0/<ID>/Sandbox/ODataV4/Company('My%20Company')/";
        ODataClient client = ODataClientFactory.getClient();
            client.getConfiguration()
            .setHttpClientFactory(oauth2HCF);
     
        URI absoluteUri = client.newURIBuilder(serviceUrl).build();    
        System.out.println(absoluteUri);
        ODataEntitySetIteratorRequest<ClientEntitySet, ClientEntity> request = 
        client.getRetrieveRequestFactory().getEntitySetIteratorRequest(absoluteUri);
        request.setAccept("application/json;odata.metadata=minimal");
    
        ODataRetrieveResponse<ClientEntitySetIterator<ClientEntitySet, ClientEntity>> response = request.execute(); 
        System.out.println("Reponse status is code: " + response.getStatusCode());

    }
}

我的AzureADOAuth2HttpClientFactoryForDBC如下所示:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.olingo.client.core.http.AbstractOAuth2HttpClientFactory;
import org.apache.olingo.client.core.http.OAuth2Exception;

public class AzureADOAuth2HttpClientFactoryForDBC extends AbstractOAuth2HttpClientFactory {

  private final String clientId;

  private final String redirectURI;

  private final String resourceURI;

  private final UsernamePasswordCredentials creds;

  private ObjectNode token;

  public AzureADOAuth2HttpClientFactoryForDBC (final String authority, final String clientId,
          final String redirectURI, final String resourceURI, final UsernamePasswordCredentials creds) {

    super(URI.create(authority + "/oauth2/authorize"), URI.create(authority + "/oauth2/token"));
    this.clientId = clientId;
    this.redirectURI = redirectURI;
    this.resourceURI = resourceURI;
    this.creds = creds;
  }

  @Override
  protected boolean isInited() throws OAuth2Exception {
    return token != null;
  }

  private void fetchAccessToken(final DefaultHttpClient httpClient, final List<BasicNameValuePair> data) {
    token = null;

    InputStream tokenResponse = null;
    try {
      final HttpPost post = new HttpPost(oauth2TokenServiceURI);
      post.setEntity(new UrlEncodedFormEntity(data, "UTF-8"));

      final HttpResponse response = httpClient.execute(post);

      tokenResponse = response.getEntity().getContent();
      token = (ObjectNode) new ObjectMapper().readTree(tokenResponse);
    } catch (Exception e) {
      throw new OAuth2Exception(e);
    } finally {
      IOUtils.closeQuietly(tokenResponse);
    }
  }

  @Override
  protected void init() throws OAuth2Exception {
    final DefaultHttpClient httpClient = wrapped.create(null, null);

    // 1. access the OAuth2 grant service (with authentication)
    String code = null;
    try {
      final URIBuilder builder = new URIBuilder(oauth2GrantServiceURI).
              addParameter("response_type", "code").
              addParameter("client_id", clientId).
              addParameter("redirect_uri", redirectURI);

      HttpResponse response = httpClient.execute(new HttpGet(builder.build()));
      System.out.println(response.getStatusLine().getStatusCode());
      final String loginPage = EntityUtils.toString(response.getEntity());
      
      String postURL = StringUtils.substringBefore(
              StringUtils.substringAfter(loginPage, "<form id=\"credentials\" method=\"post\" action=\""),
              "\">");
      final String ppsx = StringUtils.substringBefore(
              StringUtils.substringAfter(loginPage, "<input type=\"hidden\" id=\"PPSX\" name=\"PPSX\" value=\""),
              "\"/>");
      final String ppft = StringUtils.substringBefore(
              StringUtils.substringAfter(loginPage, "<input type=\"hidden\" name=\"PPFT\" id=\"i0327\" value=\""),
              "\"/>");

      List<BasicNameValuePair> data = new ArrayList<BasicNameValuePair>();
      data.add(new BasicNameValuePair("login", creds.getUserName()));
      data.add(new BasicNameValuePair("passwd", creds.getPassword()));
      data.add(new BasicNameValuePair("PPSX", ppsx));
      data.add(new BasicNameValuePair("PPFT", ppft));

      HttpPost post = new HttpPost(postURL);
      
      post.setEntity(new UrlEncodedFormEntity(data, "UTF-8"));

      response = httpClient.execute(post);
    
      final String samlPage = EntityUtils.toString(response.getEntity());

      postURL = StringUtils.substringBefore(
              StringUtils.substringAfter(samlPage, "<form name=\"fmHF\" id=\"fmHF\" action=\""),
              "\" method=\"post\" target=\"_top\">");
      final String wctx = StringUtils.substringBefore(
              StringUtils.substringAfter(samlPage, "<input type=\"hidden\" name=\"wctx\" id=\"wctx\" value=\""),
              "\">");
      final String wresult = StringUtils.substringBefore(StringUtils.substringAfter(samlPage,
              "<input type=\"hidden\" name=\"wresult\" id=\"wresult\" value=\""), "\">");
      final String wa = StringUtils.substringBefore(
              StringUtils.substringAfter(samlPage, "<input type=\"hidden\" name=\"wa\" id=\"wa\" value=\""),
              "\">");

      data = new ArrayList<BasicNameValuePair>();
      data.add(new BasicNameValuePair("wctx", wctx));
      data.add(new BasicNameValuePair("wresult", wresult.replace("&quot;", "\"")));
      data.add(new BasicNameValuePair("wa", wa));

      post = new HttpPost(postURL);
      post.setEntity(new UrlEncodedFormEntity(data, "UTF-8"));

      response = httpClient.execute(post);

      final Header locationHeader = response.getFirstHeader("Location");
      if (response.getStatusLine().getStatusCode() != 302 || locationHeader == null) {
        throw new OAuth2Exception("Unexpected response from server");
      }

      final String[] oauth2Info = StringUtils.split(
              StringUtils.substringAfter(locationHeader.getValue(), "?"), '&');
      code = StringUtils.substringAfter(oauth2Info[0], "=");

      EntityUtils.consume(response.getEntity());
    } catch (Exception e) {
      throw new OAuth2Exception(e);
    }

    if (code == null) {
      throw new OAuth2Exception("No OAuth2 grant");
    }

    // 2. ask the OAuth2 token service
    final List<BasicNameValuePair> data = new ArrayList<BasicNameValuePair>();
    data.add(new BasicNameValuePair("grant_type", "authorization_code"));
    data.add(new BasicNameValuePair("code", code));
    data.add(new BasicNameValuePair("client_id", clientId));
    data.add(new BasicNameValuePair("redirect_uri", redirectURI));
    data.add(new BasicNameValuePair("resource", resourceURI));

    fetchAccessToken(httpClient, data);

    if (token == null) {
      throw new OAuth2Exception("No OAuth2 access token");
    }
  }

  @Override
  protected void accessToken(final DefaultHttpClient client) throws OAuth2Exception {
    client.addRequestInterceptor(new HttpRequestInterceptor() {

      @Override
      public void process(final HttpRequest request, final HttpContext context) throws HttpException, IOException {
        request.removeHeaders(HttpHeaders.AUTHORIZATION);
        request.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + token.get("access_token").asText());
      }
    });
  }

  @Override
  protected void refreshToken(final DefaultHttpClient client) throws OAuth2Exception {
    final List<BasicNameValuePair> data = new ArrayList<BasicNameValuePair>();
    data.add(new BasicNameValuePair("grant_type", "refresh_token"));
    data.add(new BasicNameValuePair("refresh_token", token.get("refresh_token").asText()));

    fetchAccessToken(wrapped.create(null, null), data);

    if (token == null) {
      throw new OAuth2Exception("No OAuth2 refresh token");
    }
  }

}

谁能帮帮我,我做错了什么? 基本上,我希望能够使用OAuth2连接到Dynamics 365 Business Central,并使用Olingo框架进行一些REST调用。目前,我正在尝试连接Dynamics 365 Business Central,但出现了错误。我将感谢任何帮助


共 (0) 个答案