0

我被赋予了将我们的应用程序从 WebLogic 12.1.3 迁移到 Payara 4.1 的任务,并且遇到了一个问题,我觉得我或多或少地处于故障排除线的末尾。我们有一个 EJB(无状态 bean),它有两种方法,一种调用 Google Maps Directions API,另一种调用 Google Maps Geocoding API,两者都使用相同的凭据和 Google 的 Java 客户端库。这两种方法都可以在 WebLogic 上完美运行,但是在切换到 Payara 后,使用 Directions API 的方法给了我一个错误。这是堆栈跟踪的相关部分:

java.io.IOException: Server Error: 403 Forbidden
    at com.google.maps.internal.OkHttpPendingResult.parseResponse(OkHttpPendingResult.java:258)
    at com.google.maps.internal.OkHttpPendingResult.await(OkHttpPendingResult.java:167)
    at com.google.maps.PendingResultBase.await(PendingResultBase.java:56)
    at com.somecompany.integration.GoogleDirectionsIntegration.getDirections(GoogleDirectionsIntegration.java:XXX)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)

因此,地理编码方法仍然适用于两个平台,但是在尝试调用 Directions API 时,我从 Google 收到了 403,表明我的凭据被弄乱了,但同样的凭据适用于地理编码调用。代码没有以任何方式从一个平台切换到另一个平台。

更令人困惑的是,如果我从日志中获取调用 Google 的实际 URL 并在我的浏览器中尝试,即粘贴“ https://maps.googleapis.com/maps/api/directions/json?client= gme-company&mode=driving&arrival_time=1435825037&o rigin =Somewhere&destination=Somewhere+else&alternat ives=false&signature=nfre3XYZ2kmuDX8Qibce87ZFKQQ=" 进入 Chrome,它可以工作。我从谷歌得到了正确的答案。(顺便说一句,这些不是我使用的实际凭据或来源和目的地,它们已被“匿名化”:-))。我还检查了此 URL(由客户端库构建)在两个平台上运行时是否相同,并且在 Google 的开发人员页面上使用了 URL 签名调试器,但无济于事。我的凭据应该没有问题。

我真的走到了尽头,花了几天的时间进行故障排除和在线搜索,但没有找到解决方案。

没那么重要,但我自己没有编写这段代码,当然写的人不再在这里工作了:-P

无论如何,这是代码(有点匿名):

@Stateless
public class GoogleDirectionsIntegration {

private static final Logger LOGGER = Logger.getLogger(GoogleDirectionsIntegration.class.getName());

private GeoApiContext context = null;

/**
 * Initializer
 */
@PostConstruct
public void init() {
    LOGGER.log(Level.INFO, "initiating {0}", this.getClass().getSimpleName());
    this.context = new GeoApiContext().setEnterpriseCredentials("gme-company", "companyGoogleCryptographicSecret");
    this.context.setReadTimeout(1, TimeUnit.SECONDS)
            .setRetryTimeout(1, TimeUnit.SECONDS)
            .setConnectTimeout(1, TimeUnit.SECONDS)
            .setWriteTimeout(1, TimeUnit.SECONDS);
    OkHttpRequestHandler okHttpRequestHandler = null;
    OkHttpClient okHttpClient = null;

    try {
        Field requestField = this.context.getClass().getDeclaredField("requestHandler");
        requestField.setAccessible(true);
        okHttpRequestHandler = (OkHttpRequestHandler) requestField.get(this.context);
        Field f = okHttpRequestHandler.getClass().getDeclaredField("client");
        f.setAccessible(true);
        okHttpClient = (OkHttpClient) f.get(okHttpRequestHandler);
    } catch (NoSuchFieldException | SecurityException | IllegalAccessException | IllegalArgumentException e) {
        throw new IllegalStateException("Failed to create SSL context", e);
    }

    SSLContext sslCtx = this.getSslContext();

    if (sslCtx != null && okHttpClient != null) {
        SSLSocketFactory sslSocketFactory = sslCtx.getSocketFactory();
        okHttpClient.setSslSocketFactory(sslSocketFactory);
    }
}

private SSLContext getSslContext() {
    TrustManager[] tm = new TrustManager[] {
            new CustomTrustManager()
    };

    SSLContext sslContext = null;
    try {
        sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(null, tm, new SecureRandom());
    } catch (NoSuchAlgorithmException | KeyManagementException ex) {
        throw new IllegalStateException("Failed to create SSL context", ex);
    }
    return sslContext;
}

public DirectionsRoute getDirections(final String origin, final String destination, final DistanceUnit distanceUnit,
        @Nullable TransportMode mode, @NotNull Instant arrivalTime) throws NotFoundException {
    TransportMode actualMode = mode == null ? TransportMode.CAR : mode;
    DirectionsRoute[] directionsRoutes;

    DirectionsApiRequest directionsApiRequest = DirectionsApi.getDirections(this.context, origin, destination);
    directionsApiRequest.arrivalTime(new Instant(arrivalTime));
    directionsApiRequest.alternatives(false);
    directionsApiRequest.mode(this.toTravelMode(actualMode));

    try {
        DirectionsResult res = directionsApiRequest.await(); // THIS IS WHERE IT BREAKS!
        directionsRoutes = res.routes;
    } catch (Exception e) {
        LOGGER.log(Level.WARNING, e.getMessage(), e);
        throw new NotFoundException(e.getMessage());
    }

    if (directionsRoutes.length != 1) {
        throw new NotFoundException("Failed to fetch valid directions");
    }

    return directionsRoutes[0];
}

public void getAddress(LatLng startLocation, Location location, boolean cacheOverride) throws Exception {
    com.google.maps.model.LatLng gLatLng = new com.google.maps.model.LatLng(startLocation.getLat(), startLocation.getLng());
    GeocodingApiRequest geocodingApiRequest = GeocodingApi.reverseGeocode(this.context, gLatLng);
    GeocodingResult[] geocodingResults;
    geocodingResults = geocodingApiRequest.await();
    if (0 < geocodingResults.length) {
        //.. Code that does stuff with the result..
    } else {
        LOGGER.log(Level.WARNING, "Received empty results from Google reverse geocode for [{0}].", startLocation);
    }
}

}
4

1 回答 1

0

所以我解决了。问题不在于代码,而在于依赖项,或者更确切地说是对依赖项之一 - OkHttp 的依赖。我只是更改了版本,它现在可以工作了。

于 2017-06-05T11:52:11.013 回答