dnaiel
dnaiel

Reputation: 447

Post request failing with Invalid file path error

I am making a POST request with the body as JSON using postman. The URL is localhost:8080/replicate. I see the following errors:
https://docs.google.com/document/d/10XCAMHPjSsNScd8VOFQA4G6br48hT7ZAv3QgDKJEk0A/edit?usp=sharing
Here is a snippet from the error logs:

org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.io.IOError: java.io.FileNotFoundException: Invalid file path
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1076)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) 
...  
...  
Caused by: java.io.FileNotFoundException: Invalid file path
    at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:229)
    at java.base/java.io.FileOutputStream.<init>(FileOutputStream.java:123)
    at org.xnio.channels.Channels$4.run(Channels.java:1098)
    ... 77 common frames omitted  
...  
...  
...  
R=2022-05-25 11:03:58,331|ERROR|io.undertow.request|[[email protected]@,]|UT005023: Exception handling request to /replicate
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.io.IOError: java.io.FileNotFoundException: Invalid file path
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1076)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:652)  
...  
...  
...  

The corresponding code which maps to the controller with the mapping is:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.cloud.bigquery.InsertAllResponse;
import com.google.common.base.Stopwatch;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController

public class ReplicationController {

    @Autowired
    private ReplicationService replicationService;
    ObjectMapper mapper = new ObjectMapper();


    @Autowired
    OpenCensusMetricsExporter openCensusMetricsExporter;

    @PostMapping("/replicate")
    public ResponseEntity<String> writeReplicationData(@RequestBody String message) {
        System.out.println("Inside replicationcontroller");
        ReplicationData replicationData = null;
        Stopwatch timer = Stopwatch.createStarted();
        String route = "writeReplicationData";
        try {
            replicationData = mapMessageToReplicationData(message, mapper);
            if (validateRequest(replicationData)) {
                log.error("Bad Request");
                openCensusMetricsExporter.logHttpResponseTimeAndStatus(timer, route, MetricsExporterConstants.BAD_REQUEST);
                return ResponseEntity.badRequest().build();
            }
            InsertAllResponse response = replicationService.processReplication(replicationData);
            if (response != null && response.hasErrors()) {
                openCensusMetricsExporter.logHttpResponseTimeAndStatus(timer, route, MetricsExporterConstants.FAILURE);
                return new ResponseEntity<>(Util.getErrorMessage(response), HttpStatus.INTERNAL_SERVER_ERROR);
            } else {
                openCensusMetricsExporter.logHttpResponseTimeAndStatus(timer, route, MetricsExporterConstants.SUCCESS);
                return new ResponseEntity<>("Saved successfully", HttpStatus.CREATED);
            }
        } catch (ReplicationException e) {
            if(replicationData!=null)
                log.error(
                    "Replication: Processing is completed for Dataset: {}, Table: {}, TransactionId: {}, with errors: {}",
                    replicationData.getMetadata().getDataSet(), replicationData.getMetadata().getTableName(),
                    replicationData.getMetadata().getTransactionId(), e.getMessage());
            openCensusMetricsExporter.logHttpResponseTimeAndStatus(timer, route, MetricsExporterConstants.FAILURE);
            return new ResponseEntity<>("Failed to write to table", HttpStatus.INTERNAL_SERVER_ERROR);
        }catch (Exception e) {
            return new ResponseEntity<>("Failed to write to table", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    private boolean validateRequest(@RequestBody ReplicationData replicationData) {
        return (StringUtils.isEmpty(replicationData) || StringUtils.isEmpty(replicationData.getMetadata())
                || StringUtils.isEmpty(replicationData.getMetadata().getProjectName())
                || StringUtils.isEmpty(replicationData.getMetadata().getDataSet())
                || StringUtils.isEmpty(replicationData.getMetadata().getTableName())
                || StringUtils.isEmpty(replicationData.getData()) || replicationData.getData().size() == 0);
    }

    private ReplicationData mapMessageToReplicationData(String message, ObjectMapper mapper)
            throws ReplicationException, JsonProcessingException {

        ReplicationData replicationData = null;
        try {
            replicationData = mapper.readValue(message, ReplicationData.class);
        } catch (Exception e) {
            log.error(ReplicationDataConstants.REPLICATION_CONTROLLER_PROCESSING_ERROR_FORMAT,
                    ReplicationDataConstants.REPLICATION_PROCESSING_ERROR, message,
                    "Error parsing message", e);
            replicationService.processReplicationErrors(null, message, e.getMessage());
        }
        return replicationData;
    }
}

The post request doesn't enter inside the corresponding function writeReplicationData
And the error is TR=2022-05-25 11:03:58,331|ERROR|io.undertow.request|[[email protected]@,]|UT005023: Exception handling request to /replicate org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.io.IOError: java.io.FileNotFoundException: Invalid file path
That is confusing, where did a file path come from in this?
Adding pom.xml:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.0</version>
        <relativePath/>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <name>observability-service</name>
    <description>It consumes contract and persist into bigquery</description>
    <artifactId>observability-service</artifactId>
    <packaging>pom</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <modules>
        <module>config</module>
        <module>observability</module>
        <module>egress-healthcheck</module>
    </modules>

    <properties>
        <java.version>11</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <lombok.version>1.18.6</lombok.version>
        <stub.runner.version>2.1.1.RELEASE</stub.runner.version>
        <spring-cloud.version>2020.0.2</spring-cloud.version>
        <spring-cloud-gcp.version>1.2.2.RELEASE</spring-cloud-gcp.version>
        <spring.cloud.stream.version>1.3.4.RELEASE</spring.cloud.stream.version>
        <bigquery.version>1.116.3</bigquery.version>
        <junit-jupiter.version>5.3.2</junit-jupiter.version>
        <rest.assured.version>3.1.1</rest.assured.version>
        <metrics-core.version>3.2.6</metrics-core.version>
        <webmvc.version>5.1.8.RELEASE</webmvc.version>
        <surfire.plugin.version>2.22.0</surfire.plugin.version>
        <maven.jacoco.plugin.version>0.8.3</maven.jacoco.plugin.version>
        <maven.compiler.plugin>3.8.0</maven.compiler.plugin>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <jruby.version>1.7.26</jruby.version>
        <org.mapstruct.version>1.4.2.Final</org.mapstruct.version>
        <snippetsDirectory>${project.build.directory}/snippets</snippetsDirectory>
    
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.7.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-starter-data-spanner</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-starter-pubsub</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-integration</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>
        <dependency>
            <groupId>io.dropwizard.metrics</groupId>
            <artifactId>metrics-core</artifactId>
            <version>${metrics-core.version}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>google-cloud-bigquery</artifactId>
            <version>${bigquery.version}</version>
        </dependency>
        <dependency>
            <groupId>com.google.http-client</groupId>
            <artifactId>google-http-client-apache-v2</artifactId>
            <version>1.33.0</version>
         </dependency>
        <!-- Dependencies needed for error reporting -->
        <dependency>
            <groupId>com.google.api.grpc</groupId>
            <artifactId>proto-google-cloud-logging-v2</artifactId>
            <version>0.84.2</version>
        </dependency>
        <dependency>
            <groupId>com.google.cloud</groupId>
            <artifactId>google-cloud-logging</artifactId>
            <version>1.101.2</version>
        </dependency>
      
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-text</artifactId>
            <version>1.9</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-dependencies</artifactId>
            <version>${spring-cloud-gcp.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-autoconfigure</artifactId>
            <version>${spring-cloud-gcp.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.1.6.RELEASE</version>
            <type>pom</type>
            <scope>provided</scope>
        </dependency>
        <!-- START:Sleuth and Stackdriver-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-starter-logging</artifactId>
            <version>1.2.3.RELEASE</version>
        </dependency>
        <!-- END:Sleuth and Stackdriver-->
        <!-- Test Dependencies Start -->
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-contract-wiremock</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-contract-verifier</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-commons</artifactId>
            <version>1.5.2</version>
        </dependency>
        <!-- exclude junit 4 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!-- junit 5 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit-jupiter.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <version>${rest.assured.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-stream-test-support</artifactId>
            <version>2.1.1.RELEASE</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-pubsub-stream-binder</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-starter-pubsub</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>io.github.resilience4j</groupId>
            <artifactId>resilience4j-spring-boot2</artifactId>
            <version>1.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</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</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>net.logstash.logback</groupId>
            <artifactId>logstash-logback-encoder</artifactId>
            <version>6.4</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-gcp-dependencies</artifactId>
                <version>${spring-cloud-gcp.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <finalName>observability-service</finalName>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.sonarsource.scanner.maven</groupId>
                <artifactId>sonar-maven-plugin</artifactId>
                <version>3.6.0.1398</version>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>${surfire.plugin.version}</version>
                <configuration>
                    <failIfNoTests>false</failIfNoTests>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>1.3.1.Final</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

My thoughts:
Could it be due to some dependency conflict in pom.xml?
I tried running the project using the command mvn spring-boot:run
from power-shell JDK-11 and directly running from Intellij with JDK-11
and JDK-18, got the same error
Tried running with JDK-8, but got the error - java: warning: source release 11 requires target release 11 Module egress-healthcheck SDK 1.8 is not compatible with the source version 11. Upgrade Module SDK in project settings to 11 or higher. Open project settings.
Probably that means the project is not compatible with Java 8, also it
uses the String class isBlank method

Upvotes: 3

Views: 3133

Answers (2)

Michał Jabłoński
Michał Jabłoński

Reputation: 1277

This is caused by a known JDK bug, that I was able to reproduce under JDK 11.0.15 and JDK 17.0.3 in Windows. To work around the problem you need to set Djdk.io.File.enableADS system property. To do it, in Intellij go to Run -> Edit configurations -> and paste -Djdk.io.File.enableADS=true in VM options field.

Alternatively, you can downgrade your JDK to previous minor version, for example 11.0.14 or 17.0.2. Next minor versions (11.0.16 and 17.0.4, respectively) will have the issue fixed.

Upvotes: 3

Ashish Patil
Ashish Patil

Reputation: 4604

At currently you might need to update your question with pom.xml so that we can have a look what is issue.

Moreover, as a workaround, you can use @PostMapping(path = "/replicate") just in case your spring container is specifically looking for path variable. I will try to update answer if this does not resolve & if pom.xml is shared.

Upvotes: 0

Related Questions