当前位置: 首页 > 知识库问答 >
问题:

Google Cloud Vision Client API-Java-异常:计算凭据元数据失败

巩子实
2023-03-14

我想在我基于谷歌云的应用程序中提供“搜索已经存储在谷歌云存储中的PDF或TIFF文件中的任何文本”功能。所以我复制了这个链接中给出的示例(第1217行到第1280行)https://github.com/GoogleCloudPlatform/java-docs-samples/blob/master/vision/cloud-client/src/main/java/com/example/vision/Detect.java加入我的项目。

尝试1的详细信息

appengine网站的内容。xml:

<?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE xml>
    <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
        <application>garbledappname</application>
        <version>1</version>
        <runtime>java8</runtime>
        <threadsafe>true</threadsafe>
        <system-properties>
            <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
        </system-properties>
        <sessions-enabled>true</sessions-enabled>
        <url-stream-handler>urlfetch</url-stream-handler>
    </appengine-web-app>

我得到了这个例外:

javax.servlet.ServletException: org.glassfish.jersey.server.ContainerException: java.io.IOException: The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information

所以我改变了appengine网站。尝试2的xml。。。。。

appengine网站第2次尝试内容的详细信息。xml:

<?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE xml>
    <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
        <application>garbledappname</application>
        <version>1</version>
        <runtime>java8</runtime>
        <threadsafe>true</threadsafe>
        <system-properties>
            <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
        </system-properties>
        <sessions-enabled>true</sessions-enabled>
        <url-stream-handler>urlfetch</url-stream-handler>
        <env-variables>
            <env-var    name="GOOGLE_APPLICATION_CREDENTIALS"
                        value="WEB-INF/myproject-eaa46206856e.json" />
        </env-variables>
    </appengine-web-app>

简而言之,在尝试2中,我添加了“GOOGLE_APPLICATION_CREDENTIALS”env变量,并将其指向json密钥文件(该文件是在我的电脑上从谷歌云平台控制台创建并下载的https://console.cloud.google.com/iam-admin/serviceaccounts.

为了完整起见,我复制了json文件的内容:

{
      "type": "service_account",
      "project_id": "garbledappname",
      "private_key_id": "garbled_key_id",
      "private_key": "-----BEGIN PRIVATE KEY-----\garbled_private_key\n-----END PRIVATE KEY-----\n",
      "client_email": "r\garbled@garbled.iam.gserviceaccount.com",
      "client_id": "108443712409676506799",
      "auth_uri": "https://accounts.google.com/o/oauth2/auth",
      "token_uri": "https://oauth2.googleapis.com/token",
      "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
      "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/myOrg-demo-vison%40garbled.iam.gserviceaccount.com"
    }

更改appengine网站后。xml如上所述,构建、部署和执行应用程序时,我遇到了一个例外:

org.eclipse.jetty.servlet.ServletHandler doHandle:  (ServletHandler.java:624)
javax.servlet.ServletException: com.google.api.gax.rpc.UnauthenticatedException: io.grpc.StatusRuntimeException: UNAUTHENTICATED: Failed computing credential metadata

在我的代码中,这是上面跟踪中报告的行:

BatchAnnotateFilesResponse response = imageAnnotatorClient.batchAnnotateFiles(request);

这就是整个方法:

setQualifiedFiles           =   mapOfQualifiedReportFiles.keySet();
itrOverSetOfQualifiedFiles  =   setQualifiedFiles.iterator();
while(itrOverSetOfQualifiedFiles.hasNext()) {
    try (ImageAnnotatorClient imageAnnotatorClient = ImageAnnotatorClient.create()) {
        qualifiedFileName   =   itrOverSetOfQualifiedFiles.next();
        fileNameOnCloud     =   mapOfQualifiedReportFiles.get(qualifiedFileName);
        gcsFileName         =   new GcsFilename(bucketNameExtVendorReports, fileNameOnCloud);
        gcsPath             =   "gs://" + bucketNameExtVendorReports + "/" + fileNameOnCloud;
        logger.info("gcsPath = " + gcsPath);
        GcsSource gcsSource = GcsSource.newBuilder().setUri(gcsPath).build();
        InputConfig inputConfig = InputConfig.newBuilder().setGcsSource(gcsSource).build();
        Feature.Type type = Feature.Type.DOCUMENT_TEXT_DETECTION;
        Feature featuresElement = Feature.newBuilder().setType(type).build();
        List<Feature> features = Arrays.asList(featuresElement);
        int pagesElement = 1;
        int pagesElement2 = 2;
        List<Integer> pages = Arrays.asList(pagesElement, pagesElement2);
        AnnotateFileRequest requestsElement = AnnotateFileRequest.newBuilder()
                                            .setInputConfig(inputConfig)
                                            .addAllFeatures(features)
                                            .addAllPages(pages)
                                            .build();
        List<AnnotateFileRequest> requests = Arrays.asList(requestsElement);
        BatchAnnotateFilesRequest request =                                 BatchAnnotateFilesRequest.newBuilder().addAllRequests(requests).build();
        BatchAnnotateFilesResponse response = imageAnnotatorClient.batchAnnotateFiles(request);
        for (AnnotateImageResponse imageResponse :
          response.getResponsesList().get(0).getResponsesList()) {
          System.out.printf("Full text: %s\n", imageResponse.getFullTextAnnotation().getText());
           for (Page page : imageResponse.getFullTextAnnotation().getPagesList()) {
               for (Block block : page.getBlocksList()) {
                 System.out.printf("\nBlock confidence: %s\n", block.getConfidence());
                 for (Paragraph par : block.getParagraphsList()) {
                    System.out.printf("\tParagraph confidence: %s\n", par.getConfidence());
                    for (Word word : par.getWordsList()) {
                      System.out.printf("\t\tWord confidence: %s\n", word.getConfidence());
                      for (Symbol symbol : word.getSymbolsList()) {
                        System.out.printf("\t\t\tSymbol: %s, (confidence: %s)\n",
                                    symbol.getText(), symbol.getConfidence());
                      }
                    }
                  }
                }
              }
            }
        }
    }

我(相信我)已经遵循了创建服务帐户的所有说明。我怀疑这样创建的服务帐户缺少一个在云上访问谷歌云视觉应用编程接口时可能是强制性的角色。

有人能帮帮我吗?

以下是我试图展示一个由Jon Skeet提出的“最小的、可复制的示例”。

客户端:

package com.myOrg.myApp;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

import org.codehaus.jackson.map.ObjectMapper;

import com.myOrg.myApp.entities.Patient;
import com.myOrg.myApp.entities.returntypes.ServerResponse;
import com.google.gson.Gson;

public class VisionAPIClient    {

    public  VisionAPIClient()   {
    }

    public static void main(String[] args) {
        VisionAPIClient visionAPIClient =   null;

        visionAPIClient =   new VisionAPIClient();
        visionAPIClient.search(args[0], args[1], args[2]);

    }

    private void    search(String paramIPAddress, String paramSearchString, String paramBucketNameOnGCS)    {

        BufferedReader  bfr                     =   null;
        int             iValues                 =   0;
        int             iResponseCode           =   0;
        Patient         patient                 =   null;
        ServerResponse  response                =   null;
        String          retVal                  =   null;
        String          urlToVisionAPIServer    =   null;
        URL             url                     =   null;
        URLConnection   urlConnection           =   null;

        try {
            urlToVisionAPIServer    =   paramIPAddress + "/visionAPIServer/searchTextWithinFiles?queryString=" + new Gson().toJson(paramSearchString + "@@@" + paramBucketNameOnGCS);
            url                     =   new URL(urlToVisionAPIServer);
            urlConnection           =   url.openConnection();
            bfr                     =   new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
            retVal                  =   bfr.readLine();
            response                =   new ObjectMapper().readValue(retVal, ServerResponse.class);
            iValues                 =   response.getValues().size();
            iResponseCode           =   response.getResponseCode();
            if(iResponseCode == 200)    {
                for(int i=0 ; i<iValues ; i++)  {
                   System.out.println("contents = " + new ObjectMapper().readValue((String)response.getValues().get(i), String.class));
                }
            }
        }
        catch(Exception e)  {
            System.out.println(e.getMessage());
        }
    }
}

服务器

package com.myOrg.myApp.serverApp;

import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;
import org.codehaus.jackson.map.ObjectMapper;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.google.appengine.tools.cloudstorage.GcsService;
import com.google.appengine.tools.cloudstorage.GcsServiceFactory;
import com.google.appengine.tools.cloudstorage.ListOptions;
import com.google.appengine.tools.cloudstorage.ListResult;
import com.google.appengine.tools.cloudstorage.RetryParams;
import com.google.cloud.vision.v1.AnnotateFileRequest;
import com.google.cloud.vision.v1.AnnotateImageResponse;
import com.google.cloud.vision.v1.BatchAnnotateFilesRequest;
import com.google.cloud.vision.v1.BatchAnnotateFilesResponse;
import com.google.cloud.vision.v1.Block;
import com.google.cloud.vision.v1.Feature;
import com.google.cloud.vision.v1.GcsSource;
import com.google.cloud.vision.v1.ImageAnnotatorClient;
import com.google.cloud.vision.v1.InputConfig;
import com.google.cloud.vision.v1.Page;
import com.google.cloud.vision.v1.Paragraph;
import com.google.cloud.vision.v1.Symbol;
import com.google.cloud.vision.v1.Word;

@Path("/visionAPIServer")
public  class   VisionAPIServer {

    @Context 
    private         HttpServletRequest  request             =   null;
    private static  Logger              logger              =   Logger.getLogger("visionAPIServer");


    @GET
    @Path("/searchTextWithinFiles")
    @Produces(MediaType.TEXT_PLAIN)
    public  synchronized    Response searchTextWithinFiles(@QueryParam("queryString")String paramQueryString)
            throws Exception    {

        logger.info("//////////////////////////////////////////////////////////////////////////////////////");
        logger.info("begin new method: " + new Object(){}.getClass().getEnclosingMethod().getName());
        logger.info("\t\tparamQueryString = " + paramQueryString);
        logger.info("//////////////////////////////////////////////////////////////////////////////////////");

        AnnotateFileRequest         requestsElement =   null; 
        BatchAnnotateFilesRequest   request         =   null;
        BatchAnnotateFilesResponse  response        =   null;
        Feature                     featuresElement =   null;
        Feature.Type                type            =   null; 
        GcsService                  gcsService      =   null;
        GcsSource                   gcsSource       =   null;
        InputConfig                 inputConfig     =   null;
        int                         pagesElement    =   0;
        int                         pagesElement2   =   0;
        List<AnnotateFileRequest>   requests        =   null;
        List<Feature>               features        =   null;
        List<Integer>               pages           =   null;
        ListResult                  listResult      =   null;
        String                      paramBucketName =   null;
        String                      paramSearchText =   null;
        String                      jsonReturnValue =   null;
        String                      fileNameOnCloud =   null;
        String                      gcsPath         =   null;
        String[]                    arrOfValues     =   null;

        arrOfValues =   (new ObjectMapper().readValue(paramQueryString, String.class)).split("@@@");
        if(arrOfValues.length == 2) {
            paramSearchText =   arrOfValues[0].trim();
            paramBucketName =   arrOfValues[1].trim();
            if(null != paramBucketName && !("".equals(paramBucketName)) && (null != paramSearchText && !("".equals(paramSearchText))))  {
                gcsService                  =   GcsServiceFactory.createGcsService  (   new RetryParams.Builder()
                                                                                            .initialRetryDelayMillis(10)
                                                                                            .retryMaxAttempts(10)
                                                                                            .totalRetryPeriodMillis(15000)
                                                                                            .build());
                listResult                  =   gcsService.list(paramBucketName, ListOptions.DEFAULT);
                if(null != listResult)  {
                    while(listResult.hasNext()) {
                        try (ImageAnnotatorClient imageAnnotatorClient = ImageAnnotatorClient.create()) {
                            fileNameOnCloud     =   listResult.next().getName();
                            gcsPath             =   "gs://" + paramBucketName + "/" + fileNameOnCloud;
                            gcsSource           =   GcsSource.newBuilder().setUri(gcsPath).build();
                            inputConfig         =   InputConfig.newBuilder().setGcsSource(gcsSource).build();
                            type                =   Feature.Type.DOCUMENT_TEXT_DETECTION;
                            featuresElement     =   Feature.newBuilder().setType(type).build();
                            features            =   Arrays.asList(featuresElement);
                            pagesElement        =   1;
                            pagesElement2       =   2;
                            pages               =   Arrays.asList(pagesElement, pagesElement2);
                            requestsElement     =   AnnotateFileRequest.newBuilder()
                                                                        .setInputConfig(inputConfig)
                                                                        .addAllFeatures(features)
                                                                        .addAllPages(pages)
                                                                        .build();
                            requests            =   Arrays.asList(requestsElement);
                            request             =   BatchAnnotateFilesRequest.newBuilder().addAllRequests(requests).build();
                            response            =   imageAnnotatorClient.batchAnnotateFiles(request);
                            for (AnnotateImageResponse imageResponse :
                                response.getResponsesList().get(0).getResponsesList()) {
                                jsonReturnValue =   imageResponse.getFullTextAnnotation().getText();
                                System.out.printf("Full text: %s\n", imageResponse.getFullTextAnnotation().getText());
                                for (Page page : imageResponse.getFullTextAnnotation().getPagesList()) {
                                    for (Block block : page.getBlocksList()) {
                                        System.out.printf("\nBlock confidence: %s\n", block.getConfidence());
                                        for (Paragraph par : block.getParagraphsList()) {
                                            System.out.printf("\tParagraph confidence: %s\n", par.getConfidence());
                                            for (Word word : par.getWordsList()) {
                                                System.out.printf("\t\tWord confidence: %s\n", word.getConfidence());
                                                for (Symbol symbol : word.getSymbolsList()) {
                                                    System.out.printf("\t\t\tSymbol: %s, (confidence: %s)\n",symbol.getText(), symbol.getConfidence());
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return  Response.ok(jsonReturnValue)
                .header("Access-Control-Allow-Origin", "*")
                .header("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS")
                .header("Access-Control-Allow-Headers", "Content-Type")
                .header("Content-Disposition", "inline")
                .build();
    }
}

appengine-web.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xml>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <application>myApp</application>
    <version>1</version>
    <runtime>java8</runtime>
    <threadsafe>true</threadsafe>
    <system-properties>
        <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
    </system-properties>
    <sessions-enabled>true</sessions-enabled>
    <url-stream-handler>urlfetch</url-stream-handler>
    <env-variables>
        <env-var    name="GOOGLE_APPLICATION_CREDENTIALS"
                    value="WEB-INF/myapp-eba46306896e.json" />
    </env-variables>
</appengine-web-app>

回复:我试图展示一个“最小的、可复制的示例”......如上所述,我引用...视觉应用编程接口可以检测和转录存储在云存储中的PDF和TIFF文件中的文本...结束引用。

因此,前面发布的“mre”的客户端部分在谷歌应用引擎上对应用程序进行https调用。在这样做的同时,它传递要搜索的文本和包含要搜索的文件的桶的名称(在谷歌云存储上)。

在2019年12月26日根据杰夫·程的建议添加:那里有两个链接。我之前也遵循了其中的指示,并在杰夫的帖子后再次遵循了它们。

令人不快的代码仍然是:

response = imageAnnotatorClient.batchAnnotateFiles(request);  

所以我用一个try get聚类包围了该行,结果堆栈跟踪显示了这一点:

com.google.api.gax.rpc.UnauthenticatedException: io.grpc.StatusRuntimeException: UNAUTHENTICATED: Failed computing credential metadata  

Caused by: com.google.apphosting.api.ApiProxy$CallNotFoundException: Can't make API call urlfetch.Fetch in a thread that is neither the original request thread nor a thread created by ThreadManager  

关于如何解决这个问题有什么建议吗?谷歌搜索会出现一些其他人面临这个问题的帖子(由:com.goo.引起......),但似乎没有解决方案。
感谢任何帮助。

共有1个答案

董谦
2023-03-14

这似乎只是一个身份验证问题,看起来与视觉应用编程接口无关。身份验证错误发生在视觉应用编程接口调用期间,因为在进行应用编程接口调用之前,凭据被延迟加载/刷新。

还显示您正在将应用程序部署到应用程序引擎。如果是这样,本地设置的任何环境变量(如GOOGLE_APPLICATION_CREDENTIALS)都不会产生任何影响。您可能希望查看授予应用程序对应用程序引擎云服务的访问权限的留档。授予访问权限的最直接方法是授予默认应用程序引擎服务帐户的权限。

 类似资料:
  • 我试图解决预编译的F#Azure函数中的MissingMethodException。从FSharp调用扩展方法时引发异常。数据css选择扩展。 该函数是在一个函数中定义的。Net框架4.6。2.班级图书馆。我正在使用当前版本的FSharp。堆芯(4.2.3)和FSharp。数据(2.3.3)。(我尝试了这两个版本的旧版本,但问题仍然存在。)我为FSharp添加了绑定重定向。根据这类问题的标准指南

  • 我正在用PHP创建一个应用程序,我想集成Twilio API来发送短信。我只想处理出站消息。我使用的是官方的Twilio-PHP包装器库。

  • 问题内容: 假设我有一个包含3列的数据框:日期,股票行情,值(无索引,至少从此开始)。我有很多约会,很多股票,但是每个元组都是唯一的。(但是很显然,同一日期将显示在多行中,因为它将在多个行情中出现,而同一行情显示将在多行中显示,因为它将存在许多日期。) 最初,我的行以特定顺序排列,但没有按任何列进行排序。 我想计算每个股票报价的第一个差异(每日变化)(按日期排序),并将其放在数据框中的新列中。在这

  • Reselect 库可以创建可记忆的(Memoized)、可组合的 selector 函数。Reselect selectors 可以用来高效地计算 Redux store 里的衍生数据。 可记忆的 Selectors 初衷 首先访问 Todos 列表示例: containers/VisibleTodoList.js import { connect } from 'react-redux' im

  • 在从DB表检索记录时,我们得到了异常。我在另一张桌子上也做了同样的尝试,它起作用了,但在这张桌子上,它不起作用了。我使用的是 在这里,我创建了一个具有 get 映射的 Controller 类 我收到此异常 SEVERE:Servlet.service()的servlet[调度服务器]在上下文中与路径[]抛出异常(请求处理失败;嵌套异常org.springframework.core.conver

  • 线程“main”java.lang.error:未解决的编译问题:类型不匹配:无法从java.sql.statement转换为com.mysql.jdbc.statement 我是java初学者,我正在尝试使用mysql数据库,我已经从mysql.com下载了mysql-connector-java-5.1.23-bin.jar文件,并且我已经将这个jar文件添加到我的项目的构建路径中,但是线程“