1

My Project structure:

demo
    common
    demo-consumer

demo has two modules, common provided as a jar package to other modules, demo is a empty project

demo build.gradle

plugins {
    id 'org.springframework.boot' version '2.3.8.RELEASE'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

allprojects {
    apply plugin: 'java'
    apply plugin: 'org.springframework.boot'
    apply plugin: 'io.spring.dependency-management'


    configurations {
        compileOnly {
            extendsFrom annotationProcessor
        }
    }

    repositories {
        mavenLocal()
        mavenCentral()
    }

    ext {
        set('springCloudVersion', "Hoxton.SR9")
    }

    dependencies {

        implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
        implementation 'org.springframework.boot:spring-boot-starter-web'
        implementation 'org.springframework.boot:spring-boot-starter-web-services'
        compileOnly 'org.projectlombok:lombok'
        developmentOnly 'org.springframework.boot:spring-boot-devtools'
        runtimeOnly 'mysql:mysql-connector-java'
        annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
        annotationProcessor 'org.projectlombok:lombok'
        testImplementation('org.springframework.boot:spring-boot-starter-test') {
            exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
        }
    }

    dependencyManagement {
        imports {
            mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
        }
    }

    test {
        useJUnitPlatform()
    }
}

demo settings.gradke

rootProject.name = 'demo'
include 'common'
include 'demo-consumer'

Module Common Project structure:

src
  main
    java
     com.example.common
      config
       RestTemplateConfig.class
      App.class


My RestTemplateConfig.class:

package com.example.common.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}


My App.class:

package com.example.common;

public class App {

    public static void main(String[] args) {

    }
}

Module demo-consumer Project structure, a simple spring boot application:

src
  main
    java
     com.example.democonsumer
      controller
       TestController.class
     DemoConsumerApplication.class


My TestController.class:
    package com.example.democonsumer.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class TestController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/test0")
    public String test0(){
        return "Success";
    }

    @GetMapping("/test1")
    public String test1(){
        return restTemplate.getForObject("http://localhost:9999/test0", String.class);
    }
}

My DemoConsumerApplication.class:

package com.example.democonsumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}, scanBasePackages = {"com.example"})
public class DemoConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoConsumerApplication.class, args);
    }
}

demo-consumer's build.gradle:
dependencies {
    implementation project(":common")
}

I build common first and build the demo-consumer by gradle, put the demo-consumer.jar on the server; run the jar package, it failed

2021-01-20 11:24:17.463  INFO 4007 --- [           main] c.e.d.DemoConsumerApplication            : Starting DemoConsumerApplication on iZ2ze9tlmbs6w25xr1jp92Z with PID 4007 (/home/spring-cloud-template/demo-consumer.jar started by root in /home/spring-cloud-template)
2021-01-20 11:24:17.467  INFO 4007 --- [           main] c.e.d.DemoConsumerApplication            : No active profile set, falling back to default profiles: default
2021-01-20 11:24:19.555  INFO 4007 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.ws.config.annotation.DelegatingWsConfiguration' of type [org.springframework.ws.config.annotation.DelegatingWsConfiguration$$EnhancerBySpringCGLIB$$4d8ad8fc] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2021-01-20 11:24:19.740  INFO 4007 --- [           main] .w.s.a.s.AnnotationActionEndpointMapping : Supporting [WS-Addressing August 2004, WS-Addressing 1.0]
2021-01-20 11:24:20.545  INFO 4007 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9990 (http)
2021-01-20 11:24:20.578  INFO 4007 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2021-01-20 11:24:20.579  INFO 4007 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.41]
2021-01-20 11:24:20.746  INFO 4007 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2021-01-20 11:24:20.750  INFO 4007 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 3169 ms
2021-01-20 11:24:21.410  WARN 4007 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testController': Unsatisfied dependency expressed through field 'restTemplate'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.web.client.RestTemplate' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
2021-01-20 11:24:21.417  INFO 4007 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2021-01-20 11:24:21.468  INFO 4007 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-01-20 11:24:21.806 ERROR 4007 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field restTemplate in com.example.democonsumer.controller.TestController required a bean of type 'org.springframework.web.client.RestTemplate' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'org.springframework.web.client.RestTemplate' in your configuration.

Idea is running normally, jar package failed,how to fix it?

Asuka
  • 13
  • 4
  • Please put on entire error log. – ediron Jan 20 '21 at 03:21
  • edited , put on entire error log – Asuka Jan 20 '21 at 03:28
  • Try adding `@ComponentScan(basePackages={"com.example.common"})` to you `RestTemplateConfig`. I'm not sure your common config component is getting picked up from you demo consumer. – Hopey One Jan 20 '21 at 04:05
  • Your common project shouldn't have the spring boot plugin applied. When applying the plugin the jar will have a different structure compared to a regular jar and the classes won't be available. Ofcourse this is also explained in [the documentation](https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-create-an-additional-executable-jar). – M. Deinum Jan 20 '21 at 08:05
  • I solved this problem;change build.gradle in demo-consumer; implementation project(":common")==>compile project(":common"); build and run jar,;it is ok.But Why?? – Asuka Jan 20 '21 at 08:38
  • it seems implementation project(":common") or compile project(":common") all works for me.Don't know what the problem is – Asuka Jan 20 '21 at 08:45

1 Answers1

-1

Try to inject RestTemplate in this way:


RestTemplateConfig

@Bean
public ClientHttpRequestFactory clientHttpRequestFactory() {
    SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
    ClientHttpRequestFactory clientHttpRequestFactory = new BufferingClientHttpRequestFactory(simpleClientHttpRequestFactory);

    return clientHttpRequestFactory ;
}

@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory clientHttpRequestFactory) {
    RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
    return restTemplate;
}

OR

@Autowired
private RestTemplateBuilder builder;

// Use RestTemplateBuilder to instantiate the RestTemplate object, spring has injected the RestTemplateBuilder instance by default
@Bean
public RestTemplate restTemplate() {
    return builder.build();
}
ediron
  • 65
  • 3
  • thank,but not work,error:A component required a bean of type 'org.springframework.web.client.RestTemplate' that could not be found. – Asuka Jan 20 '21 at 03:49
  • This won't help. The issue is that there are 2 spring boot projects generated and you cannot use a spring boot build jar as a dependency due to the difference in structure. – M. Deinum Jan 20 '21 at 08:07