Arefe
Arefe

Reputation: 12397

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder

I have issue with reading the values from the application.properties file and get the following errors,

[ERROR] Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.7.RELEASE:run (default-cli) on project wedding-card: An exception occurred while running. null: InvocationTargetException: Error creating bean with name 'weddingCardConfiguration': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'aws.s3.access.key' in value "${aws.s3.access.key}" -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.1.7.RELEASE:run (default-cli) on project wedding-card: An exception occurred while running. null
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:215)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)


Caused by: org.apache.maven.plugin.MojoExecutionException: An exception occurred while running. null
    at org.springframework.boot.maven.AbstractRunMojo$IsolatedThreadGroup.rethrowUncaughtException (AbstractRunMojo.java:512)
    at org.springframework.boot.maven.RunMojo.runWithMavenJvm (RunMojo.java:94)
    at org.springframework.boot.maven.AbstractRunMojo.run (AbstractRunMojo.java:244)


Caused by: java.lang.reflect.InvocationTargetException
    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:498)
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:543)
    at java.lang.Thread.run (Thread.java:748)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'weddingCardConfiguration': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'aws.s3.access.key' in value "${aws.s3.access.key}"
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties (AutowiredAnnotationBeanPostProcessor.java:380)

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'aws.s3.access.key' in value "${aws.s3.access.key}"

The pom.xml file is provided:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.wedcard</groupId>
    <artifactId>wedding-card</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>wedding-card</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

        <dependency>
            <groupId>org.liquibase</groupId>
            <artifactId>liquibase-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.8</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.16</version>
        </dependency>

        <dependency>
            <groupId>com.stripe</groupId>
            <artifactId>stripe-java</artifactId>
            <version>10.0.2</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk</artifactId>
            <version>1.11.163</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>com.github.jhonnymertz</groupId>
            <artifactId>java-wkhtmltopdf-wrapper</artifactId>
            <version>1.1.11-RELEASE</version>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
<!--        <resources>-->
<!--            <resource>-->
<!--                <directory>resources</directory>-->
<!--                <targetPath>${project.build.outputDirectory}</targetPath>-->
<!--                <includes>-->
<!--                    <include>application.properties</include>-->
<!--                </includes>-->
<!--            </resource>-->
<!--        </resources>-->
    </build>

    <repositories>
        <repository>
            <id>spring.io</id>
            <url>https://repo.spring.io/plugins-release/</url>
        </repository>
    </repositories>

</project>

The configuration source file is here:

@Configuration
@EnableSwagger2
@EnableScheduling
//@PropertySource(value = "classpath:application.properties")
public class WeddingCardConfiguration implements WebMvcConfigurer {
//    @Value("${spring.mail.host}")
//    private String smtpMailHost;
//    @Value("${spring.mail.port}")
//    private int smtpMailPort;
//    @Value("${spring.mail.username}")
//    private String mailUsername;
//    @Value("${spring.mail.password}")
//    private String mailPassword;

    @Value("${aws.s3.access.key}")
    private String awsS3AccessKey;
    @Value("${aws.s3.access.secret}")
    private String awsS3AccessSecret;
    @Value("${aws.s3.bucket.region.name}")
    private String awsBucketRegionName;


    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*");
    }

//    @Bean
//    public JavaMailSender javaMailSender() {
//        JavaMailSenderImpl sender = new JavaMailSenderImpl();
//        Properties prop = new Properties();
//        prop.put("mail.smtp.auth", "true");
//        prop.put("mail.smtp.starttls.enable", "true"); //TLS
//        sender.setJavaMailProperties(prop);
//        sender.setHost(smtpMailHost);
//        sender.setPort(smtpMailPort);
//        sender.setUsername(mailUsername);
//        sender.setPassword(mailPassword);
//
//        return sender;
//    }

    @Bean
    public AmazonS3 awsS3Client() {
        AWSCredentials credentials = new BasicAWSCredentials(awsS3AccessKey, awsS3AccessSecret);

        return AmazonS3ClientBuilder
                .standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withRegion(awsBucketRegionName)
                .build();
    }
}

The project has standard file structure provided:

enter image description here

I have tried to provide the property source information to the configuration class but still get the same error:

@Configuration
@EnableSwagger2
@EnableScheduling
@PropertySource(value = "classpath:application.properties")
public class WeddingCardConfiguration implements WebMvcConfigurer {


}

I have also tried to provide explicitly the resources info to the pom file:

     <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <directory>resources</directory>
                <targetPath>${project.build.outputDirectory}</targetPath>
                <includes>
                    <include>application.properties</include>
                </includes>
            </resource>
        </resources>
    </build>

I keep getting the same error. Whats the issue here and how to solve it?

ps: The email config values are commented purposefully and the error is not related to that

Upvotes: 3

Views: 31810

Answers (2)

Arefe
Arefe

Reputation: 12397

I needed to add a bean in the configuration file that would read the extra properties file,

    @Bean
    public PropertyPlaceholderConfigurer properties() {
        final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer();
//        ppc.setIgnoreUnresolvablePlaceholders(true);
        ppc.setIgnoreResourceNotFound(true);

        final List<Resource> resourceLst = new ArrayList<Resource>();

        resourceLst.add(new ClassPathResource("application.properties"));
        resourceLst.add(new ClassPathResource("application-local.properties"));

        ppc.setLocations(resourceLst.toArray(new Resource[]{}));
        return ppc;
    }

Afterwards, its working fine.

Upvotes: -1

julz256
julz256

Reputation: 2712

Check that those properties are actually defined in application.properties. There is also an application-aws.properties file, if the properties are only in that file then you will need to tell Spring Boot to enable the aws profile with SPRING_PROFILES_ACTIVE=aws, or add the aws properties with empty values in application.properties.

If no Spring Boot profile is activated, it will only use the properties defined in application.properties.

If you enable the aws profile, it will use use properties from application.properties as defaults, and then any matching properties defined in application-aws.properties will override those from application.properties if defined.

If what you are trying to do it only use those AWS properties when deployed to AWS, then you might need to make a Configuration object that holds those properties in it(which is a better practice than including properties with @Value in code), and make the AmazonS3 bean creation conditional on those properties being set.

Given that your project structure is a standard Maven structure, convention over configuration should apply and there should be no need to try and explicitly include application.properties with additional class path configuration. I.e everything under /src/main/resources should be available on the class path and to the application at runtime.

Upvotes: 2

Related Questions