4

I'm trying to execute simplest async REST controller using java.util.concurrent.Callable:

@RequestMapping("/AsyncRequest")
public Callable asyncRequest() {
    return () -> {
        Thread.sleep(3000);
        return "reply";
    };
}

Then I run http://localhost/AsyncRequest two times in browser. The first answer I get in 3 seconds, but the second just after 6 seconds. It seems like that the requests processed not asynchronously. Why this happen?

3
  • It would appear it's the same thread handling both requests. Commented Dec 27, 2016 at 19:12
  • @Christopher Schneider, I checked threads ids, they were different. Commented Dec 27, 2016 at 19:15
  • No idea... I just wrote something functionally identical and cannot reproduce your results. This was with Java 7 and Pivotal tc Server 3.1.3 Commented Dec 27, 2016 at 19:53

1 Answer 1

3

Spring Boot behavior really depends on version and configuration.

The following configuration and code works for me:

Starter

package com.stackoverflow.spring.boot.async;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Import;

@Import(WebConfig.class)
@SpringBootApplication
public class WebMain {
  private final SpringApplication application;

  public WebMain() {
    final SpringApplicationBuilder applicationBuilder = new SpringApplicationBuilder(WebMain.class);
    application = applicationBuilder.build();
  }

  public SpringApplication getApplication() { return application; }

  public static void main(final String[] args) {
    new WebMain().getApplication().run(args);
  }
}

Configuration

package com.stackoverflow.spring.boot.async;


import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter implements EmbeddedServletContainerCustomizer
{
  public void customize(final ConfigurableEmbeddedServletContainer container) {}
}

Controller

I've changed sleep time here to 6 second and added some payload into response.

package com.stackoverflow.spring.boot.async;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Date;
import java.util.concurrent.Callable;

@Controller
public class AsyncController {
  @RequestMapping(path = "/AsyncRequest", method = RequestMethod.GET)
  @ResponseBody
  public Callable<String> asyncRequest() {
    return () -> {
      final long currentThread = Thread.currentThread().getId();
      final Date requestProcessingStarted = new Date();

      Thread.sleep(6000L);

      final Date requestProcessingFinished = new Date();

      return String.format(
          "request: [threadId: %s, started: %s - finished: %s]"
          , currentThread, requestProcessingStarted, requestProcessingFinished);
    };
  }
}

pom.xml

    <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/maven-v4_0_0.xsd">

      <modelVersion>4.0.0</modelVersion>

      <groupId>com.stackoverflow.spring.boot</groupId>
      <artifactId>async</artifactId>
      <packaging>jar</packaging>
      <version>1.0-SNAPSHOT</version>

      <properties>
        <java.version>1.8</java.version>
        <spring-boot.version>1.4.1.RELEASE</spring-boot.version>
      </properties>

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

        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot</artifactId>
          <version>${spring-boot.version}</version>
        </dependency>

        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
          <version>${spring-boot.version}</version>
        </dependency>

        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
          <version>${spring-boot.version}</version>
        </dependency>
      </dependencies>

      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <inherited>true</inherited>
            <configuration>
              <source>${java.version}</source>
              <target>${java.version}</target>
            </configuration>
          </plugin>

          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>${spring-boot.version}</version>
            <executions>
              <execution>
                <goals>
                  <goal>repackage</goal>
                </goals>
                <configuration>
                  <classifier>exec</classifier>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>

    </project>

Testing

java -version
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)

--
mvn spring-boot:run
...
--
# start following command from different consoles:
curl http://localhost:8080/AsyncRequest

Results

request: [threadId: 33, started: 15:50:28 - finished: 15:50:34]
request: [threadId: 35, started: 15:50:29 - finished: 15:50:35]
request: [threadId: 37, started: 15:50:30 - finished: 15:50:36]
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the answer. It helped me to find out the problem. The reason of my problem was google chrome: It optimized requests for the same url. In your answer you used curl. I've tried to test server with it too and I got the right result.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.