在 Java 中使用 Microsoft 自适应卡

Posted

技术标签:

【中文标题】在 Java 中使用 Microsoft 自适应卡【英文标题】:Using Microsoft adaptive cards in Java 【发布时间】:2022-01-01 16:04:49 【问题描述】:

我正在尝试使用自适应卡片在 Java 中实现一个聊天机器人,就像 C# 示例 here。

我可以让机器人在 Teams 中显示卡片,但我无法处理任何响应,因为我总是遇到此异常:

2021-11-23T05:32:35.715171392Z: [INFO]  

java.util.concurrent.CompletionException: com.microsoft.bot.builder.ActivityHandler$InvokeResponseException
2021-11-23T05:32:35.715176693Z: [INFO]      at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(Unknown Source) ~[na:na]
2021-11-23T05:32:35.715182093Z: [INFO]      at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(Unknown Source) ~[na:na]
2021-11-23T05:32:35.715186993Z: [INFO]      at java.base/java.util.concurrent.CompletableFuture.thenCompose(Unknown Source) ~[na:na]
2021-11-23T05:32:35.715191793Z: [INFO]      at com.microsoft.bot.builder.ActivityHandler.onTurn(ActivityHandler.java:105) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715196594Z: [INFO]      at com.microsoft.bot.builder.MiddlewareSet.receiveActivityInternal(MiddlewareSet.java:99) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715201494Z: [INFO]      at com.microsoft.bot.builder.MiddlewareSet.lambda$receiveActivityInternal$1(MiddlewareSet.java:110) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715206394Z: [INFO]      at com.microsoft.bot.builder.BotFrameworkAdapter$TenantIdWorkaroundForTeamsMiddleware.onTurn(BotFrameworkAdapter.java:1430) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715211294Z: [INFO]      at com.microsoft.bot.builder.MiddlewareSet.receiveActivityInternal(MiddlewareSet.java:109) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715216095Z: [INFO]      at com.microsoft.bot.builder.MiddlewareSet.receiveActivityInternal(MiddlewareSet.java:74) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715220795Z: [INFO]      at com.microsoft.bot.builder.MiddlewareSet.receiveActivityWithStatus(MiddlewareSet.java:67) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715225395Z: [INFO]      at com.microsoft.bot.builder.BotAdapter.runPipeline(BotAdapter.java:206) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715243796Z: [INFO]      at com.microsoft.bot.builder.BotFrameworkAdapter.lambda$processActivity$2(BotFrameworkAdapter.java:478) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715248396Z: [INFO]      at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(Unknown Source) ~[na:na]
2021-11-23T05:32:35.715252696Z: [INFO]      at java.base/java.util.concurrent.CompletableFuture.thenCompose(Unknown Source) ~[na:na]
2021-11-23T05:32:35.715256997Z: [INFO]      at com.microsoft.bot.builder.BotFrameworkAdapter.processActivity(BotFrameworkAdapter.java:476) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715261997Z: [INFO]      at com.microsoft.bot.builder.BotFrameworkAdapter.lambda$processActivity$1(BotFrameworkAdapter.java:433) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715266297Z: [INFO]      at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(Unknown Source) ~[na:na]
2021-11-23T05:32:35.715270397Z: [INFO]      at java.base/java.util.concurrent.CompletableFuture.thenCompose(Unknown Source) ~[na:na]
2021-11-23T05:32:35.715274597Z: [INFO]      at com.microsoft.bot.builder.BotFrameworkAdapter.processActivity(BotFrameworkAdapter.java:433) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715278798Z: [INFO]      at com.microsoft.bot.integration.BotFrameworkHttpAdapter.processIncomingActivity(BotFrameworkHttpAdapter.java:102) ~[bot-integration-core-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715283098Z: [INFO]      at com.microsoft.bot.integration.spring.BotController.incoming(BotController.java:84) ~[bot-integration-spring-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.715287298Z: [INFO]      at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
2021-11-23T05:32:35.715291498Z: [INFO]      at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
2021-11-23T05:32:35.715295699Z: [INFO]      at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[na:na]
2021-11-23T05:32:35.715299799Z: [INFO]      at java.base/java.lang.reflect.Method.invoke(Unknown Source) ~[na:na]
2021-11-23T05:32:35.715303799Z: [INFO]      at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197) ~[spring-web-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.715308199Z: [INFO]      at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141) ~[spring-web-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.715312499Z: [INFO]      at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.715317000Z: [INFO]      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:893) ~[spring-webmvc-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.715321400Z: [INFO]      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:807) ~[spring-webmvc-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.715325800Z: [INFO]      at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.715330300Z: [INFO]      at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1061) ~[spring-webmvc-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.715338401Z: [INFO]      at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.715342801Z: [INFO]      at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.715347001Z: [INFO]      at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.715351101Z: [INFO]      at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.39.jar!/:4.0.FR]
2021-11-23T05:32:35.715355202Z: [INFO]      at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.715359702Z: [INFO]      at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.39.jar!/:4.0.FR]
2021-11-23T05:32:35.715364102Z: [INFO]      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.715368302Z: [INFO]      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.715372902Z: [INFO]      at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719456008Z: [INFO]      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719463708Z: [INFO]      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719468709Z: [INFO]      at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.719473209Z: [INFO]      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.719477709Z: [INFO]      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719482209Z: [INFO]      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719497610Z: [INFO]      at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.719502910Z: [INFO]      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.719507111Z: [INFO]      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719511411Z: [INFO]      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719515611Z: [INFO]      at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.719529412Z: [INFO]      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar!/:5.3.1]
2021-11-23T05:32:35.719533812Z: [INFO]      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719538012Z: [INFO]      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719542212Z: [INFO]      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719546413Z: [INFO]      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719550513Z: [INFO]      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719554813Z: [INFO]      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719559013Z: [INFO]      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719563113Z: [INFO]      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719567314Z: [INFO]      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719572214Z: [INFO]      at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719576414Z: [INFO]      at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719580514Z: [INFO]      at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719584714Z: [INFO]      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719588815Z: [INFO]      at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719593015Z: [INFO]      at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
2021-11-23T05:32:35.719597015Z: [INFO]      at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
2021-11-23T05:32:35.719601115Z: [INFO]      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.39.jar!/:9.0.39]
2021-11-23T05:32:35.719605216Z: [INFO]      at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
2021-11-23T05:32:35.719609216Z: [INFO]  Caused by: com.microsoft.bot.builder.ActivityHandler$InvokeResponseException: null
2021-11-23T05:32:35.719613216Z: [INFO]      at com.microsoft.bot.builder.ActivityHandler.getAdaptiveCardInvokeValue(ActivityHandler.java:712) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.719621116Z: [INFO]      at com.microsoft.bot.builder.ActivityHandler.onInvokeActivity(ActivityHandler.java:408) ~[bot-builder-4.14.0.jar!/:4.14.0]
2021-11-23T05:32:35.719625517Z: [INFO]      ... 68 common frames omitted
2021-11-23T05:32:35.719629517Z: [INFO]

我已将问题缩小到 com.microsoft.bot.builder.ActivityHandler 类中的这段代码:

Object obj = activity.getValue();
JsonNode node = null;
if (obj instanceof JsonNode) 
  node = (JsonNode) obj;
 else 
  AdaptiveCardInvokeResponse response = createAdaptiveCardInvokeErrorResponse(
      HttpURLConnection.HTTP_BAD_REQUEST, "BadRequest", "Value property instanceof not properly formed");
  throw new InvokeResponseException(HttpURLConnection.HTTP_BAD_REQUEST, response);

从这段代码中我可以看到,如果activity.getValue() 对象不是JsonNode 的实例,则会抛出InvokeResponseException

我什至将这段代码提取到我自己的类中并注销了返回的实际对象类型:

Object obj = activity.getValue();
JsonNode node = null;
LOGGER.error("obj type: " + obj.getClass().getName());
if (obj instanceof JsonNode) 
  node = (JsonNode) obj;
 else 
  AdaptiveCardInvokeResponse response = createAdaptiveCardInvokeErrorResponse(
      HttpURLConnection.HTTP_BAD_REQUEST, "BadRequest", "Value property instanceof not properly formed");
  throw new InvokeResponseException(HttpURLConnection.HTTP_BAD_REQUEST, response);

实际的对象类型是java.util.LinkedHashMap

那么这里的解决方案是什么?是否有一个配置选项可以更改标准聊天机器人项目对活动响应的反序列化方式?我的代码基于使用 Yeoman yo botbuilder-java -T "echo" 描述的 here 创建的示例项目。

【问题讨论】:

【参考方案1】:

这似乎是 Java Bot Framework SDK 的一个错误,但与此同时,我已经解决了一个接受来自 activity.getValue() 的 Map 的中间类的问题(参见 invokeValue = objectMapper.convertValue(obj, AdaptiveCardInvokeValue.class); 行):

package com.matthewcasperson;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.bot.builder.ActivityHandler;
import com.microsoft.bot.builder.InvokeResponse;
import com.microsoft.bot.builder.TurnContext;
import com.microsoft.bot.connector.Async;
import com.microsoft.bot.schema.Activity;
import com.microsoft.bot.schema.AdaptiveCardInvokeResponse;
import com.microsoft.bot.schema.AdaptiveCardInvokeValue;
import com.microsoft.bot.schema.Serialization;
import com.microsoft.bot.schema.SignInConstants;
import java.net.HttpURLConnection;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FixedActivityHandler extends ActivityHandler 
  private static final Logger LOGGER = LoggerFactory.getLogger(CateringBot.class);

  @Override
  protected CompletableFuture<InvokeResponse> onInvokeActivity(TurnContext turnContext) 
    if (StringUtils.equals(turnContext.getActivity().getName(), "adaptiveCard/action")) 
      AdaptiveCardInvokeValue invokeValue = null;
      try 
        invokeValue = getAdaptiveCardInvokeValue(turnContext.getActivity());
       catch (InvokeResponseException e) 
        return Async.completeExceptionally(e);
      
      return onAdaptiveCardInvoke(turnContext, invokeValue).thenApply(result -> createInvokeResponse(result));
    

    if (
        StringUtils.equals(
            turnContext.getActivity().getName(), SignInConstants.VERIFY_STATE_OPERATION_NAME
        ) || StringUtils.equals(
            turnContext.getActivity().getName(), SignInConstants.TOKEN_EXCHANGE_OPERATION_NAME
        )
    ) 
      return onSignInInvoke(turnContext).thenApply(aVoid -> createInvokeResponse(null))
          .exceptionally(ex -> 
            if (
                ex instanceof CompletionException
                    && ex.getCause() instanceof InvokeResponseException
            ) 
              InvokeResponseException ire = (InvokeResponseException) ex.getCause();
              return new InvokeResponse(500, "");
             else if (ex instanceof InvokeResponseException) 
              InvokeResponseException ire = (InvokeResponseException) ex;
              return new InvokeResponse(500, "");
            
            return new InvokeResponse(HttpURLConnection.HTTP_INTERNAL_ERROR, null);
          );
    

    CompletableFuture<InvokeResponse> result = new CompletableFuture<>();
    result.complete(new InvokeResponse(HttpURLConnection.HTTP_NOT_IMPLEMENTED, null));
    return result;
  

  private AdaptiveCardInvokeValue getAdaptiveCardInvokeValue(Activity activity) throws InvokeResponseException 
    if (activity.getValue() == null) 
      AdaptiveCardInvokeResponse response = createAdaptiveCardInvokeErrorResponse(
          HttpURLConnection.HTTP_BAD_REQUEST, "BadRequest", "Missing value property");
      throw new InvokeResponseException(HttpURLConnection.HTTP_BAD_REQUEST, response);
    

    /*
      The original code required activity.getValue() to be a JsonNode. It is in fact a
      LinkedHashMap, so this change allows the response to proceed.
     */
    Object obj = activity.getValue();
    AdaptiveCardInvokeValue invokeValue = null;
    if (obj instanceof JsonNode) 
      invokeValue = Serialization.treeToValue((JsonNode) obj, AdaptiveCardInvokeValue.class);
     else if (obj instanceof Map) 
      final ObjectMapper objectMapper = new ObjectMapper();
      objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
      invokeValue = objectMapper.convertValue(obj, AdaptiveCardInvokeValue.class);
     else 
      AdaptiveCardInvokeResponse response = createAdaptiveCardInvokeErrorResponse(
          HttpURLConnection.HTTP_BAD_REQUEST, "BadRequest", "Value property instanceof not properly formed");
      throw new InvokeResponseException(HttpURLConnection.HTTP_BAD_REQUEST, response);
    
    /*
      End of changes
     */

    if (invokeValue == null) 
      AdaptiveCardInvokeResponse response = createAdaptiveCardInvokeErrorResponse(
          HttpURLConnection.HTTP_BAD_REQUEST, "BadRequest", "Value property instanceof not properly formed");
      throw new InvokeResponseException(HttpURLConnection.HTTP_BAD_REQUEST, response);
    

    if (invokeValue.getAction() == null) 
      AdaptiveCardInvokeResponse response = createAdaptiveCardInvokeErrorResponse(
          HttpURLConnection.HTTP_BAD_REQUEST, "BadRequest", "Missing action property");
      throw new InvokeResponseException(HttpURLConnection.HTTP_BAD_REQUEST, response);
    

    if (!invokeValue.getAction().getType().equals("Action.Execute")) 
      AdaptiveCardInvokeResponse response = createAdaptiveCardInvokeErrorResponse(
          HttpURLConnection.HTTP_BAD_REQUEST, "NotSupported",
          String.format("The action '%s'is not supported.", invokeValue.getAction().getType()));
      throw new InvokeResponseException(HttpURLConnection.HTTP_BAD_REQUEST, response);
    

    return invokeValue;
  

  private AdaptiveCardInvokeResponse createAdaptiveCardInvokeErrorResponse(
      Integer statusCode,
      String code,
      String message
  ) 
    AdaptiveCardInvokeResponse adaptiveCardInvokeResponse = new AdaptiveCardInvokeResponse();
    adaptiveCardInvokeResponse.setStatusCode(statusCode);
    adaptiveCardInvokeResponse.setType("application/vnd.getmicrosoft().error");
    com.microsoft.bot.schema.Error error = new com.microsoft.bot.schema.Error();
    error.setCode(code);
    error.setMessage(message);
    adaptiveCardInvokeResponse.setValue(error);
    return adaptiveCardInvokeResponse;
  

【讨论】:

以上是关于在 Java 中使用 Microsoft 自适应卡的主要内容,如果未能解决你的问题,请参考以下文章

如何使用自适应卡操作从自适应卡获取用户响应。使用 Microsoft Bot Framework 从 MS Teams 频道提交操作?

自适应卡片 js 渲染 - 不支持卡片

如何在后续瀑布步骤中检索自适应卡的表单提交

Microsoft Teams - 在聊天中呈现自适应卡片的问题

适用于常见问题的自适应卡内的自适应卡

microsoft botframework bot 如何在自适应卡片中提及用户?