microsoftgraph / microsoftgraph/msgraph-sdk-java

Microsoft Graph - Error executing the request

未关闭
#2,159 2 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

Needs: Attention :wave: type:legacy-version
主要语言
Java
星标
444
派生
154
平均合并
18 小时 28 分钟
30 天内合并 PR
4

描述

Using version 3.0.0 i implemented batch because our app was being throttled and now i am randomly getting socket errors... it works few times then errors few times etc... How can i fix my error?

Error:

com.microsoft.graph.core.ClientException: Error executing the request at com.microsoft.graph.http.CoreHttpProvider.sendRequestInternal(CoreHttpProvider.java:388) at com.microsoft.graph.http.CoreHttpProvider.send(CoreHttpProvider.java:214) at com.microsoft.graph.http.CoreHttpProvider.send(CoreHttpProvider.java:191) at com.microsoft.graph.content.BatchRequest.post(BatchRequest.java:60) at com.company.myapp.microsoftgraph.MicrosoftGraphClient.getUserCalendarFreeSlots(MicrosoftGraphClient.java:205) at com.company.myapp.service.DataCacheService.getAvailability(DataCacheService.java:192) at com.company.myapp.service.DataCacheService.refreshAvailability(DataCacheService.java:178) at com.company.myapp.service.DataCacheService.refreshAvailabilityWithLocks(DataCacheService.java:90) at com.company.myapp.service.DataCacheRefresher.refreshAvailabilityCache(DataCacheRefresher.java:32) 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:503) at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:84) at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:95) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:826) Caused by: java.net.SocketTimeoutException: timeout at okio.SocketAsyncTimeout.newTimeoutException(JvmOkio.kt:143) at okio.AsyncTimeout.access$newTimeoutException(AsyncTimeout.kt:162) at okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:335) at okio.RealBufferedSource.indexOf(RealBufferedSource.kt:427) at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.kt:320) at okhttp3.internal.http1.HeadersReader.readLine(HeadersReader.kt:29) at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(Http1ExchangeCodec.kt:178) at okhttp3.internal.connection.Exchange.readResponseHeaders(Exchange.kt:106) at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.kt:79) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.kt:34) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.kt:95) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.kt:83) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.kt:76) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at com.microsoft.graph.httpcore.RedirectHandler.intercept(RedirectHandler.java:137) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at com.microsoft.graph.httpcore.RetryHandler.intercept(RetryHandler.java:176) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at com.microsoft.graph.httpcore.AuthenticationHandler.intercept(AuthenticationHandler.java:59) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at com.microsoft.graph.httpcore.TelemetryHandler.intercept(TelemetryHandler.java:69) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109) at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201) at okhttp3.internal.connection.RealCall.execute(RealCall.kt:154) at com.microsoft.graph.http.CoreHttpProvider.sendRequestInternal(CoreHttpProvider.java:385) ... 22 more Caused by: javax.net.ssl.SSLException: Socket closed at sun.security.ssl.Alert.createSSLException(Alert.java:127) at sun.security.ssl.TransportContext.fatal(TransportContext.java:331) at sun.security.ssl.TransportContext.fatal(TransportContext.java:274) at sun.security.ssl.TransportContext.fatal(TransportContext.java:269) at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1572) at sun.security.ssl.SSLSocketImpl.access$400(SSLSocketImpl.java:73) at sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:982) at okio.InputStreamSource.read(JvmOkio.kt:90) at okio.AsyncTimeout$source$1.read(AsyncTimeout.kt:129) ... 48 more Caused by: java.net.SocketException: Socket closed at java.net.SocketInputStream.read(SocketInputStream.java:204) at java.net.SocketInputStream.read(SocketInputStream.java:141) at sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:464) at sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(SSLSocketInputRecord.java:68) at sun.security.ssl.SSLSocketImpl.readApplicationRecord(SSLSocketImpl.java:1350) at sun.security.ssl.SSLSocketImpl.access$300(SSLSocketImpl.java:73) at sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:966) ... 50 more

Config:

    @Configuration
public class GraphClientConfig {
    @Value("${microsoft.graph.tenantId}") private String tenantId;
    @Value("${microsoft.graph.clientId}") private String clientId;
    @Value("${microsoft.graph.clientSecret}") private String clientSecret;
    @Value("${microsoft.graph.authority}") private String authority;
    @Value("${microsoft.graph.scopes}") private List<String> scopes; 
        
    @Bean 
    public ClientSecretCredential graphClientAuthProvider() {
        
        ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
                .clientId(clientId)
                .clientSecret(clientSecret)
                .tenantId(tenantId)
                .build();
        
        
        return clientSecretCredential;
    }
    
    @Bean
    public GraphServiceClient graphClient() {
        
        TokenCredentialAuthProvider authProvider = new TokenCredentialAuthProvider(scopes, graphClientAuthProvider());
                
        GraphServiceClient<?> graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient();
        return graphClient;
    }
        
}

MicrosoftGraphClient

@Component
public class MicrosoftGraphClient<IHttpRequest> {
    private static Logger logger = LoggerFactory.getLogger(MicrosoftGraphClient.class);
    private static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
    public static final String timeZone="Central Europe Standard Time";
    @Autowired GraphServiceClient graphClient;
    @Value("${microsoft.graph.defaultUserId}") private String defaultUserId;
        
    public List<CalendarAvailabilityView> getUserCalendarFreeSlots(String userid, List<String> calendarIds, LocalDate startDate, LocalDate endDate){
        logger.info("getUserCalendarFreeSlots()");  
        
        if (userid == null)
            userid=defaultUserId;
        
        StopWatch sw = new StopWatch("getUserCalendarFreeSlots");
        
        LinkedList<Option> requestOptions = new LinkedList<Option>();
        requestOptions.add(new HeaderOption("Prefer", "outlook.timezone=\""+timeZone+"\""));
        requestOptions.add(new HeaderOption("Content-Type", "application/json"));
    
        LocalDateTime startDateTime = LocalDateTime.of(startDate, LocalTime.of(0, 0));
        LocalDateTime endDateTime = LocalDateTime.of(endDate, LocalTime.of(23, 59));
        
        // calculate dates between
        List<LocalDate> dates = new ArrayList<> ();
        for (LocalDate d = startDate; !d.isAfter(endDate); d = d.plusDays(1)) {
            dates.add(d);
        }
        
        DateTimeTimeZone startTime = new DateTimeTimeZone();
        startTime.dateTime = dtf.format(startDateTime);
        startTime.timeZone = timeZone;
        
        DateTimeTimeZone endTime = new DateTimeTimeZone();
        endTime.dateTime = dtf.format(endDateTime);
        endTime.timeZone = timeZone;
            
        int availabilityViewInterval = 30;
                
        List<List<String>> partitions = Lists.partition(calendarIds, 5);
        List<CalendarAvailabilityView> availability = new ArrayList<CalendarAvailabilityView>();
        
        CalendarGetScheduleCollectionRequest request = null;
        CalendarGetScheduleParameterSet req = null;
                
        for (List<String> schedulesList: partitions) {
            
            BatchRequestContent batchRequestContent = new BatchRequestContent();
            
            logger.info("reading partition: "+StringUtils.join(schedulesList, ", "));
            sw.start("get data");
                        
            req = CalendarGetScheduleParameterSet.newBuilder()
                    .withSchedules(schedulesList)
                    .withEndTime(endTime)
                    .withStartTime(startTime)
                    .withAvailabilityViewInterval(availabilityViewInterval).build();
                        
             request = graphClient.users()
                        .byId(userid).calendar().getSchedule(req)
                        .buildRequest(requestOptions);
             
            String requestId = batchRequestContent.addBatchRequestStep(request, HttpMethod.POST, req);
            
            BatchResponseContent batchResponseContent = graphClient.batch()
                    .buildRequest()
                    .post(batchRequestContent);
                                                    
            CalendarGetScheduleCollectionResponse response = new CalendarGetScheduleCollectionResponse();
            ISerializer serializer = graphClient.getSerializer();
            
            JsonObject obj = batchResponseContent.getResponseById(requestId).body.getAsJsonObject();
            
            // Populate CalendarGetScheduleCollectionResponse
            if (obj.has("value")) {
                JsonArray scheduleItems = obj.getAsJsonArray("value");
                List<ScheduleInformation> scheduleInformationList = new ArrayList<>();

                for (JsonElement item : scheduleItems) {
                    ScheduleInformation info = serializer.deserializeObject(item.toString(), ScheduleInformation.class);
                    scheduleInformationList.add(info);
                }

                response.value = scheduleInformationList;
            }
            
            CalendarGetScheduleCollectionPage page = request.buildFromResponse(response);
            
            List<ScheduleInformation> objects = new ArrayList<>();
            objects.addAll(page.getCurrentPage());
            
            CalendarGetScheduleCollectionRequestBuilder builder = page.getNextPage();
            
            while (builder != null) {
                request = builder.buildRequest();
                page = request.post();
                objects.addAll(page.getCurrentPage());
                builder = page.getNextPage();
            }
            
            sw.stop();
            
            if (objects != null && objects.size() > 0) {
                for (ScheduleInformation si: objects) {                 
                    String availabilityView = si.availabilityView;
                    WorkingHours workingHours =si.workingHours;
                    if (availabilityView != null) {
                        CalendarAvailabilityView calav=new CalendarAvailabilityView();
                        calav.setAvailabilityView(availabilityView);
                        calav.setIdCalendar(si.scheduleId);
                        calav.setWorkingHours(convert(workingHours));
                        calav.setDates(dates);
                        availability.add(calav);
                    }
                    
                }
            }
        }
        logger.info(sw.prettyPrint());
    
        return availability;
    }
        
    private Map<String, WorkingHour> convert(WorkingHours wh) {
        Map<String, WorkingHour> workingHoursMap = new LinkedHashMap<String, WorkingHour>();
        
        if (wh==null)
            return null;
        
        //List<com.microsoft.graph.models.generated.DayOfWeek> daysOfWeek = wh.daysOfWeek;
        List<com.microsoft.graph.models.DayOfWeek> daysOfWeek = wh.daysOfWeek;
        
        for (com.microsoft.graph.models.DayOfWeek dow: daysOfWeek) {
            WorkingHour workingHour = new WorkingHour();
        
            TimeOfDay endTime = wh.endTime;
            workingHour.setEndTime(LocalTime.of(endTime.getHour(), endTime.getMinute()));
            
            TimeOfDay startTime = wh.startTime;
            workingHour.setStartTime(LocalTime.of(startTime.getHour(), startTime.getMinute()));
            
                
            workingHoursMap.put(dow.name().toUpperCase(), workingHour);
        
        }
        
        return workingHoursMap;
    }
}

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

从 MicrosoftGraphClient.getUserCalendarFreeSlots 和 BatchRequest.post 调用开始,然后通过 CoreHttpProvider.sendRequestInternal 跟踪报告的故障。重现间歇性 batch request,并比较 timeout 和 socket-closed 情况;当原因已定位到 SDK 请求路径或所提供客户端的使用方式时,即视为完成。

由索引模型根据 Issue 内容生成。

评估

技术栈
java
领域
api
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
需要澄清
新手友好度
20/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。