Could not find class [org.springframework.boot.autoconfigure.condition.OnPropertyCondition]

目录

1、异常信息

2、异常代码实现(优化前)

3、原因分析

4、本文解决方案

5、其它解决方案

6、小结


        最近做一个导出聊天记录的需求,为了提高接口响应速度,我便使用CompletableFuture开启两个线程,一个下载文件,另一个生成PDF,两个线程都执行完成再压缩返回;本来一切顺利推进,但线上环境一个偶然出现的异常信息引起了我的注意,奇怪的是在本地调试没有遇到过,而且此异常的触发条件是在线上打包部署后第一次调用此接口才有几率复现这个问题;emm........mmp,原本想睁一只眼闭一只眼不管这个问题,我不说测试也不一定能发现对吧;可惜我是有点强迫症的,怎么能允许自己的接口有一丁点的瑕疵呢,誓与bug不共戴天,于是一场艰难的战斗打响了...

1、异常信息

2022-10-17 20:18:06,949 [TID: N/A] [ERROR] [sendMessage-0] c.z.r.s.NewRocketApiService [NewRocketApiService.java : 346] fileTask exception:
java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: Could not find class [org.springframework.boot.autoconfigure.condition.OnPropertyCondition]
	at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
	at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1739)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: Could not find class [org.springframework.boot.autoconfigure.condition.OnPropertyCondition]
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:600)
	at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:678)
	at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:737)
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:159)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
	at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:661)
	at com.zzw.redops.service.NewRocketApiService.lambda$exportChatRecords$6(NewRocketApiService.java:328)
	at java.base/java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1736)
	... 3 common frames omitted
Caused by: java.lang.IllegalArgumentException: Could not find class [org.springframework.boot.autoconfigure.condition.OnPropertyCondition]
	at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:334)
	at org.springframework.context.annotation.ConditionEvaluator.getCondition(ConditionEvaluator.java:124)
	at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:96)
	at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:88)
	at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:71)
	at org.springframework.context.annotation.AnnotatedBeanDefinitionReader.doRegisterBean(AnnotatedBeanDefinitionReader.java:254)
	at org.springframework.context.annotation.AnnotatedBeanDefinitionReader.registerBean(AnnotatedBeanDefinitionReader.java:147)
	at org.springframework.context.annotation.AnnotatedBeanDefinitionReader.register(AnnotatedBeanDefinitionReader.java:137)
	at org.springframework.context.annotation.AnnotationConfigApplicationContext.register(AnnotationConfigApplicationContext.java:162)
	at org.springframework.cloud.context.named.NamedContextFactory.createContext(NamedContextFactory.java:120)
	at org.springframework.cloud.context.named.NamedContextFactory.getContext(NamedContextFactory.java:102)
	at org.springframework.cloud.netflix.ribbon.SpringClientFactory.getContext(SpringClientFactory.java:131)
	at org.springframework.cloud.context.named.NamedContextFactory.getInstance(NamedContextFactory.java:146)
	at org.springframework.cloud.netflix.ribbon.SpringClientFactory.getInstance(SpringClientFactory.java:121)
	at org.springframework.cloud.netflix.ribbon.SpringClientFactory.getClientConfig(SpringClientFactory.java:75)
	at org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient.getClientConfig(LoadBalancerFeignClient.java:98)
	at org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient.execute(LoadBalancerFeignClient.java:82)
	at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:119)
	at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89)
	at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:100)
	at com.sun.proxy.$Proxy189.getObjectFile(Unknown Source)
	at com.zzw.redops.service.NewRocketApiService.lambda$null$5(NewRocketApiService.java:334)
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
	at java.base/java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:290)
	at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:746)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:183)
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.autoconfigure.condition.OnPropertyCondition
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:398)
	at org.springframework.util.ClassUtils.forName(ClassUtils.java:284)
	at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:324)
	... 31 common frames omitted

2、异常代码实现(优化前)

CompletableFuture<Void> fileTask = CompletableFuture.runAsync(() -> {
			recordsVOList.parallelStream().filter(item-> RocketConstants.MESSAGE_TYPE_FILE.equals(item.getType())).forEach(item->{
				JSONObject jsonObject = JSONObject.parseObject(item.getMsg());
				String fileName = jsonObject.getString("fileName");
				String fileURI = jsonObject.getString("fileURI");
				String objectName = fileURI.substring(fileURI.lastIndexOf("/") + 1);
				Response res = ossClient.getObjectFile("redops-test", objectName);
				File downloadFile = new File("downloadFile/"+fileName);
				try {
					FileUtils.copyInputStreamToFile(res.body().asInputStream(), downloadFile);
				} catch (IOException e) {
					log.error("copyInputStreamToFile exception:",e);
				}
				files.add(downloadFile);
			});
			log.info("文件完成");
		}, threadPool).exceptionally(e->{
			log.error("fileTask exception:",e);
			return null;
		});

3、原因分析

        找了许久也没找到适用的解决方案,最终在GitHub的开源项目spring-cloud-openfeign中看到了相似问题的描述,我从中的理解是由于在异步任务中使用并行流通过openfeign调用其它模块的接口造成,可能是本身就存在这个问题,原文如下

原文链接:`ClassNotFoundException` when calling a `FeignBlockingLoadBalancerClient` in a parallel stream (multiple threads) · Issue #600 · spring-cloud/spring-cloud-openfeign · GitHubDescribe the bug When calling a @FeignClient (FeignBlockingLoadBalancerClient) in a parallel stream (stream.parallel()), the following error arises, only when executing it as an uber/executable jar. It seems to be related (kind of) to so...https://github.com/spring-cloud/spring-cloud-openfeign/issues/600

原文链接:https://github.com/spring-cloud/spring-cloud-openfeign/issues/475

官方维护团队不建议使用此种写法,这个问题并未关闭,维护团队并未给出好的解决方案

 4、本文解决方案

        原本使用的是并行流下载文件,现改为串行流,问题解决

CompletableFuture<Void> fileTask = CompletableFuture.runAsync(() -> {
			recordsVOList.stream().filter(item-> RocketConstants.MESSAGE_TYPE_FILE.equals(item.getType())).forEach(item->{
				JSONObject jsonObject = JSONObject.parseObject(item.getMsg());
				String fileName = jsonObject.getString("fileName");
				String fileURI = jsonObject.getString("fileURI");
				String objectName = fileURI.substring(fileURI.lastIndexOf("/") + 1);
				Response res = ossClient.getObjectFile("redops-test", objectName);
				File downloadFile = new File("downloadFile/"+fileName);
				try {
					FileUtils.copyInputStreamToFile(res.body().asInputStream(), downloadFile);
				} catch (IOException e) {
					log.error("copyInputStreamToFile exception:",e);
				}
				files.add(downloadFile);
			});
			log.info("文件完成");
		}, threadPool).exceptionally(e->{
			log.error("fileTask exception:",e);
			return null;
		});

5、其它解决方案

        自定义LoadBalancerClientFactory

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
    <version>3.1.1</version>
</dependency>
@Bean
@ConditionalOnMissingBean
public LoadBalancerClientFactory loadBalancerClientFactory(ObjectProvider<List<LoadBalancerClientSpecification>> configurations) {
    LoadBalancerClientFactory clientFactory = new LoadBalancerClientFactory(){            
        @Override
        protected AnnotationConfigApplicationContext createContext(String name) {
            // FIXME: temporary switch classloader to use the correct one when creating the 		   context
            ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
            Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
            AnnotationConfigApplicationContext context = super.createContext(name);
            Thread.currentThread().setContextClassLoader(originalClassLoader);
            return context;
        }
    };
    clientFactory.setConfigurations(configurations.getIfAvailable(Collections::emptyList));
    return clientFactory;
}

6、小结

        博主实力有限,暂时没有能力深究其中的原因,大家可根据实际情况尝试使用本文中的方法看是否有效;大家也可关注spring-cloud-openfeign官方维护团队的动态,看官方给出什么样的解决方案,说不定在新的版本中就解决了

        有任何问题,欢迎大家指正!

        转载请注明出处!

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
根据提供的引用内容,出现类似“could not find class org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication”的错误通常是由于Spring Boot版本不兼容或者缺少相关依赖所致。解决此问题的方法如下: 1. 确认Spring Boot版本是否兼容。可以在pom.xml文件中检查Spring Boot的版本是否与其他依赖项兼容。如果不兼容,则需要升级或降级Spring Boot版本。 2. 确认是否缺少相关依赖。可以在pom.xml文件中检查是否缺少相关依赖。如果缺少,则需要添加相关依赖。 3. 清除Maven本地仓库。有时候Maven本地仓库中的依赖可能会损坏或者不完整,可以尝试清除Maven本地仓库并重新构建项目。 下面是一个示例pom.xml文件,其中包含了Spring Boot和相关依赖: ```xml <dependencies> <!-- Spring Boot --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- Spring Boot Actuator --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- Spring Boot Test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- Spring Boot Security --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <!-- Spring Boot Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- MySQL Connector --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值