Coder Social home page Coder Social logo

spring-guides / gs-async-method Goto Github PK

View Code? Open in Web Editor NEW
84.0 23.0 92.0 1.07 MB

Creating Asynchronous Methods :: Learn how to create asynchronous service methods.

Home Page: https://spring.io/guides/gs/async-method/

License: Apache License 2.0

Java 92.04% Shell 7.96%

gs-async-method's Introduction

This guide walks you through creating asynchronous queries to GitHub. The focus is on the asynchronous part, a feature often used when scaling services.

What You Will build

You will build a lookup service that queries GitHub user information and retrieves data through GitHub’s API. One approach to scaling services is to run expensive jobs in the background and wait for the results by using Java’s CompletableFuture interface. Java’s CompletableFuture is an evolution from the regular Future. It makes it easy to pipeline multiple asynchronous operations and merge them into a single asynchronous computation.

Starting with Spring Initializr

You can use this pre-initialized project and click Generate to download a ZIP file. This project is configured to fit the examples in this tutorial.

To manually initialize the project:

  1. Navigate to https://start.spring.io. This service pulls in all the dependencies you need for an application and does most of the setup for you.

  2. Choose either Gradle or Maven and the language you want to use. This guide assumes that you chose Java.

  3. Click Dependencies and select Spring Web.

  4. Click Generate.

  5. Download the resulting ZIP file, which is an archive of a web application that is configured with your choices.

Note
If your IDE has the Spring Initializr integration, you can complete this process from your IDE.
Note
You can also fork the project from Github and open it in your IDE or other editor.

Create a Representation of a GitHub User

Before you can create a GitHub lookup service, you need to define a representation for the data you will retrieve through GitHub’s API.

To model the user representation, create a resource representation class. To do so, provide a plain old Java object with fields, constructors, and accessors, as the following example (from src/main/java/com/example/asyncmethod/User.java) shows:

link:complete/src/main/java/com/example/asyncmethod/User.java[role=include]

Spring uses the Jackson JSON library to convert GitHub’s JSON response into a User object. The @JsonIgnoreProperties annotation tells Spring to ignore any attributes not listed in the class. This makes it easy to make REST calls and produce domain objects.

In this guide, we grab only the name and the blog URL for demonstration purposes.

Create a GitHub Lookup Service

Next, you need to create a service that queries GitHub to find user information. The following listing (from src/main/java/com/example/asyncmethod/GitHubLookupService.java) shows how to do so:

link:complete/src/main/java/com/example/asyncmethod/GitHubLookupService.java[role=include]

The GitHubLookupService class uses Spring’s RestTemplate to invoke a remote REST point (api.github.com/users/) and then convert the answer into a User object. Spring Boot automatically provides a RestTemplateBuilder that customizes the defaults with any auto-configuration bits (that is, MessageConverter).

The class is marked with the @Service annotation, making it a candidate for Spring’s component scanning to detect and add to the application context.

The findUser method is flagged with Spring’s @Async annotation, indicating that it should run on a separate thread. The method’s return type is CompletableFuture<User> instead of User, a requirement for any asynchronous service. This code uses the completedFuture method to return a CompletableFuture instance that is already completed with result of the GitHub query.

Note
Creating a local instance of the GitHubLookupService class does NOT allow the findUser method to run asynchronously. It must be created inside a @Configuration class or picked up by @ComponentScan.

The timing for GitHub’s API can vary. To demonstrate the benefits later in this guide, an extra delay of one second has been added to this service.

Make the Application Executable

To run a sample, you can create an executable jar. Spring’s @Async annotation works with web applications, but you need not set up a web container to see its benefits. The following listing (from src/main/java/com/example/asyncmethod/AsyncMethodApplication.java) shows how to do so:

link:complete/src/main/java/com/example/asyncmethod/AsyncMethodApplication.java[role=include]
Note
The Spring Initializr created an AsyncMethodApplication class for you. You can find it in the zip file that you downloaded from the Spring Initializr (in src/main/java/com/example/asyncmethod/AsyncMethodApplication.java). You can either copy that class to your project and then modify it or copy the class from the preceding listing.

The @EnableAsync annotation switches on Spring’s ability to run @Async methods in a background thread pool. This class also customizes the Executor by defining a new bean. Here, the method is named taskExecutor, since this is the specific method name for which Spring searches. In our case, we want to limit the number of concurrent threads to two and limit the size of the queue to 500. There are many more things you can tune. If you do not define an Executor bean, Spring uses ThreadPoolTaskExecutor.

There is also a CommandLineRunner that injects the GitHubLookupService and calls that service three times to demonstrate the method is executed asynchronously.

You also need a class to run the application. You can find that in src/main/java/com/example/asyncmethod/AppRunner.java. The following listing shows that class:

link:complete/src/main/java/com/example/asyncmethod/AppRunner.java[role=include]

The application shows logging output, showing each query to GitHub. With the help of the allOf factory method, we create an array of CompletableFuture objects. By calling the join method, it is possible to wait for the completion of all of the CompletableFuture objects.

The following listing shows typical output from this sample application:

2016-09-01 10:25:21.295  INFO 17893 --- [ GithubLookup-2] hello.GitHubLookupService                : Looking up CloudFoundry
2016-09-01 10:25:21.295  INFO 17893 --- [ GithubLookup-1] hello.GitHubLookupService                : Looking up PivotalSoftware
2016-09-01 10:25:23.142  INFO 17893 --- [ GithubLookup-1] hello.GitHubLookupService                : Looking up Spring-Projects
2016-09-01 10:25:24.281  INFO 17893 --- [           main] hello.AppRunner                          : Elapsed time: 2994
2016-09-01 10:25:24.282  INFO 17893 --- [           main] hello.AppRunner                          : --> User [name=Pivotal Software, Inc., blog=https://pivotal.io]
2016-09-01 10:25:24.282  INFO 17893 --- [           main] hello.AppRunner                          : --> User [name=Cloud Foundry, blog=https://www.cloudfoundry.org/]
2016-09-01 10:25:24.282  INFO 17893 --- [           main] hello.AppRunner                          : --> User [name=Spring, blog=https://spring.io/projects]

Note that the first two calls happen in separate threads (GithubLookup-2, GithubLookup-1) and the third one is parked until one of the two threads became available. To compare how long this takes without the asynchronous feature, try commenting out the @Async annotation and runing the service again. The total elapsed time should increase noticeably, because each query takes at least a second. You can also tune the Executor to increase the corePoolSize attribute for instance.

Essentially, the longer the task takes and the more tasks are invoked simultaneously, the more benefit you see from making things asynchronous. The trade off is handling the CompletableFuture interface. It adds a layer of indirection, because you are no longer dealing directly with the results.

Summary

Congratulations! You have just developed an asynchronous service that lets you scale multiple calls at once.

gs-async-method's People

Contributors

altfatterz avatar bclozel avatar btalbott avatar buzzardo avatar cbeams avatar gregturn avatar jchoffmann avatar pauldragoslav avatar robertmcnees avatar royclarkson avatar scoobi-wisdoom avatar snicoll avatar south37 avatar spring-operator avatar tiwarivikash avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gs-async-method's Issues

Missing unit test

I'm trying to use @Async to do some optimize in my app recently, but I didn't found a proper article/guide to do unit test with @Async methods, eg: If the controller invoked a service's async method, how do I confirm the service's async method is done in controller's unit test. Inject a lock into service object when testing? Override the Executor when testing or something else?

Please add a test case to the project and the guide here https://spring.io/guides/gs/async-method/

@Async feature confusion

I'm a bit confused by the documentation, is there any performance advantage of using Async annotation compared to direct use CompletableFeature ? see example https://github.com/AAZANOVICH/gs-async-method-test/blob/main/complete/src/main/java/com/example/asyncmethod/GitHubLookupService.java

. if I configure and pass executor (similar config) to completableFeatures.add(CompletableFuture.supplyAsync(() -> apiCall(userName)));

Will it be equivalent to the @async in terms of performance, or Spring doing some extra magic when @async is used?

Upgrade Spring Boot to the latest version

Update the guide to use the most recent Spring Boot version.

To do so, update the Spring Boot version in:

initial/build.gradle
initial/pom.xml
complete/build.gradle
complete/pom.xml

Add a note that the example does not work through proxy (unless, probably, specifically configured)

This is the output I see when running the example (with Gradle) being in a proxied intranet:

:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:findMainClass
:bootRun

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.1.5.RELEASE)

2014-08-28 13:36:42.909  INFO 3180 --- [           main] hello.Application                        : Starting Application on L-IT-05839 with PID 3180 (started by MBresciani in C:\Users\mbresciani\Desktop\Spring\Guides\Creating Asynchronous Methods)
2014-08-28 13:36:42.951  INFO 3180 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@162db19d: startup date [Thu Aug 28 13:36:42 CEST 2014]; root of context hierarchy
2014-08-28 13:36:43.363  INFO 3180 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.scheduling.annotation.ProxyAsyncConfiguration' of type [class org.springframework.scheduling.annotation.ProxyAsyncConfiguration$$EnhancerBySpringCGLIB$$dad8eba6] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2014-08-28 13:36:43.688  INFO 3180 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
Looking up CloudFoundry
Looking up SpringFramework
Looking up PivotalSoftware
Elapsed time: 1093
2014-08-28 13:36:44.945  INFO 3180 --- [           main] .b.l.ClasspathLoggingApplicationListener : Application failed to start with classpath: [file:/C:/Users/mbresciani/Desktop/Spring/Guides/Creating%20Asynchronous%20Methods/src/main/resources, file:/C:/Users/mbresciani/Desktop/Spring/Guides/Creating%20Asynchronous%20Methods/build/classes/main/, file:/C:/Users/mbresciani/Desktop/Spring/Guides/Creating%20Asynchronous%20Methods/build/resources/main, file:/C:/Users/mbresciani/.m2/repository/org/springframework/boot/spring-boot-starter/1.1.5.RELEASE/spring-boot-starter-1.1.5.RELEASE.jar, file:/C:/Users/mbresciani/.m2/repository/org/springframework/spring-web/4.0.6.RELEASE/spring-web-4.0.6.RELEASE.jar, file:/C:/Users/mbresciani/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.3.3/jackson-databind-2.3.3.jar, file:/C:/Users/mbresciani/.m2/repository/org/springframework/boot/spring-boot/1.1.5.RELEASE/spring-boot-1.1.5.RELEASE.jar, file:/C:/Users/mbresciani/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/1.1.5.RELEASE/spring-boot-autoconfigure-1.1.5.RELEASE.jar, file:/C:/Users/mbresciani/.m2/repository/org/springframework/boot/spring-boot-starter-logging/1.1.5.RELEASE/spring-boot-starter-logging-1.1.5.RELEASE.jar, file:/C:/Users/mbresciani/.m2/repository/org/springframework/spring-core/4.0.6.RELEASE/spring-core-4.0.6.RELEASE.jar, file:/C:/Users/mbresciani/.m2/repository/org/yaml/snakeyaml/1.13/snakeyaml-1.13.jar, file:/C:/Users/mbresciani/.m2/repository/org/springframework/spring-aop/4.0.6.RELEASE/spring-aop-4.0.6.RELEASE.jar, file:/C:/Users/mbresciani/.m2/repository/org/springframework/spring-beans/4.0.6.RELEASE/spring-beans-4.0.6.RELEASE.jar, file:/C:/Users/mbresciani/.m2/repository/org/springframework/spring-context/4.0.6.RELEASE/spring-context-4.0.6.RELEASE.jar, file:/C:/Users/mbresciani/.gradle/caches/modules-2/files-2.1/com.fasterxml.jackson.core/jackson-annotations/2.3.0/f5e853a20b60758922453d56f9ae1e64af5cb3da/jackson-annotations-2.3.0.jar, file:/C:/Users/mbresciani/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.3.3/jackson-core-2.3.3.jar, file:/C:/Users/mbresciani/.m2/repository/org/slf4j/jcl-over-slf4j/1.7.7/jcl-over-slf4j-1.7.7.jar, file:/C:/Users/mbresciani/.m2/repository/org/slf4j/jul-to-slf4j/1.7.7/jul-to-slf4j-1.7.7.jar, file:/C:/Users/mbresciani/.m2/repository/org/slf4j/log4j-over-slf4j/1.7.7/log4j-over-slf4j-1.7.7.jar, file:/C:/Users/mbresciani/.m2/repository/ch/qos/logback/logback-classic/1.1.2/logback-classic-1.1.2.jar, file:/C:/Users/mbresciani/.m2/repository/commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar, file:/C:/Users/mbresciani/.m2/repository/aopalliance/aopalliance/1.0/aopalliance-1.0.jar, file:/C:/Users/mbresciani/.m2/repository/org/springframework/spring-expression/4.0.6.RELEASE/spring-expression-4.0.6.RELEASE.jar, file:/C:/Users/mbresciani/.m2/repository/org/slf4j/slf4j-api/1.7.7/slf4j-api-1.7.7.jar, file:/C:/Users/mbresciani/.m2/repository/ch/qos/logback/logback-core/1.1.2/logback-core-1.1.2.jar]
2014-08-28 13:36:44.948  INFO 3180 --- [           main] utoConfigurationReportLoggingInitializer : 

Error starting ApplicationContext. To display the auto-configuration report enabled debug logging (start with --debug)


2014-08-28 13:36:44.963 ERROR 3180 --- [           main] o.s.boot.SpringApplication               : Application startup failed

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:680)
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:695)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
    at hello.Application.main(Application.java:45)
Caused by: java.util.concurrent.ExecutionException: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://graph.facebook.com/PivotalSoftware":Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
    at java.util.concurrent.FutureTask.get(FutureTask.java:83)
    at hello.Application.run(Application.java:39)
    at org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:677)
    ... 5 common frames omitted
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://graph.facebook.com/PivotalSoftware":Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: connect
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:561)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:506)
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:243)
    at hello.FacebookLookupService.findPage(FacebookLookupService.java:18)
    at hello.FacebookLookupService$$FastClassBySpringCGLIB$$a8016679.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:708)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:97)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.lang.Thread.run(Thread.java:619)
Caused by: java.net.ConnectException: Connection refused: connect
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
    at java.net.Socket.connect(Socket.java:529)
    at java.net.Socket.connect(Socket.java:478)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:163)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:394)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:529)
    at sun.net.www.http.HttpClient.<init>(HttpClient.java:233)
    at sun.net.www.http.HttpClient.New(HttpClient.java:306)
    at sun.net.www.http.HttpClient.New(HttpClient.java:323)
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:860)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:801)
    at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:726)
    at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:78)
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48)
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:52)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:545)
    ... 11 common frames omitted

2014-08-28 13:36:44.965  INFO 3180 --- [           main] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@162db19d: startup date [Thu Aug 28 13:36:42 CEST 2014]; root of context hierarchy
2014-08-28 13:36:44.966  INFO 3180 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
:bootRun FAILED

BUILD FAILED

Total time: 7.423 secs

This is the stacktrace:

gradle.bat : Exception in thread "main" java.lang.IllegalStateException: Failed to execute CommandLineRunner
In riga:1 car:2
+ & <<<<  'C:\Program Files (x86)\gradle-2.0\bin\gradle.bat' bootRun --stacktrace > output.txt 2> error.txt
    + CategoryInfo          : NotSpecified: (Exception in th...mmandLineRunner:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError

    at org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:680)

    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:695)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
    at hello.Application.main(Application.java:45)
Caused by: java.util.concurrent.ExecutionException: org.springframework.web.client.ResourceAccessException: I/O error o
n GET request for "http://graph.facebook.com/PivotalSoftware":Connection refused: connect; nested exception is java.net
.ConnectException: Connection refused: connect

    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)

    at java.util.concurrent.FutureTask.get(FutureTask.java:83)

    at hello.Application.run(Application.java:39)

    at org.springframework.boot.SpringApplication.runCommandLineRunners(SpringApplication.java:677)

    ... 5 more
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://graph.facebook.
com/PivotalSoftware":Connection refused: connect; nested exception is java.net.ConnectException: Connection refused: co
nnect
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:561)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:506)
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:243)
    at hello.FacebookLookupService.findPage(FacebookLookupService.java:18)
    at hello.FacebookLookupService$$FastClassBySpringCGLIB$$a8016679.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:708)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.aop.interceptor.AsyncExecutionInterceptor$1.call(AsyncExecutionInterceptor.java:97)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.lang.Thread.run(Thread.java:619)
Caused by: java.net.ConnectException: Connection refused: connect
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
    at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
    at java.net.Socket.connect(Socket.java:529)
    at java.net.Socket.connect(Socket.java:478)
    at sun.net.NetworkClient.doConnect(NetworkClient.java:163)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:394)
    at sun.net.www.http.HttpClient.openServer(HttpClient.java:529)
    at sun.net.www.http.HttpClient.<init>(HttpClient.java:233)
    at sun.net.www.http.HttpClient.New(HttpClient.java:306)
    at sun.net.www.http.HttpClient.New(HttpClient.java:323)
    at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:860)
    at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:801)
    at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:726)
    at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpReques
t.java:78)

    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRe
quest.java:48)

    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:52)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:545)

    ... 11 more



FAILURE: 
Build failed with an exception.




* What went wrong:

Execution failed for task ':bootRun'.

> 
Process 'command 'C:\Program Files\Java\jdk1.6.0_21\bin\java.exe'' finished with non-zero exit value 1



* Try:

Run with 
--info
 or 
--debug
 option to get more log output.



* Exception is:

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':bootRun'.

    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.jav
a:69)

    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)

    at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecu
ter.java:35)

    at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)

    at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)

    at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecute
r.java:42)

    at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java
:52)

    at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)

    at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java
:43)

    at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:296)

    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.
java:79)

    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.
java:63)

    at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)

    at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)

    at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:86)
    at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:29)
    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:61)

    at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)

    at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:67)

    at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)

    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:61)

    at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:54)

    at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:148)

    at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:105)

    at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:85)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.ja
va:81)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:33)
    at org.gradle.launcher.cli.ExecuteBuildAction.run(ExecuteBuildAction.java:24)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:39)
    at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:29)
    at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:50)
    at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:171)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237)
    at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
    at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206)
    at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
    at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
    at org.gradle.launcher.Main.doAction(Main.java:33)
    at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
    at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
    at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
Caused by: org.gradle.process.internal.ExecException: Process 'command 'C:\Program Files\Java\jdk1.6.0_21\bin\java.exe'
' finished with non-zero exit value 1
    at org.gradle.process.internal.DefaultExecHandle$ExecResultImpl.assertNormalExitValue(DefaultExecHandle.java:365)
    at org.gradle.process.internal.DefaultJavaExecAction.execute(DefaultJavaExecAction.java:31)
    at org.gradle.api.tasks.JavaExec.exec(JavaExec.java:60)
    at org.springframework.boot.gradle.run.BootRunTask.exec(BootRunTask.java:56)
    at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:63)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(Annotat
ionProcessingTaskFactory.java:218)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(Annotatio
nProcessingTaskFactory.java:211)
    at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(Annotatio
nProcessingTaskFactory.java:200)

    at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:570)

    at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:553)

    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java
:80)

    at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.jav
a:61)

    ... 44 more

Example fails with HTTP status code 400 (Bad Request)

Running the example throws the following exception:
org.springframework.web.client.HttpClientErrorException: 400 Bad Request

The reason is that Facebook's Graph API requires an access token for these requests.

Suggestion: Use (e.g.) Github's API by changing the requests generated from

to

Happy to provide a pull request if desired.

The Configuration doesn't work well

I found the configuration below in example doesn't work well, the executor still is org.springframework.core.task.SimpleAsyncTaskExecutor.

  @Bean
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("GithubLookup-");
        executor.initialize();
        return executor;
    }

Instead, I try below and it works well:

package com.ericsson.cdm.api.v2.config;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@Configuration
public class AsyncConfiguration implements AsyncConfigurer {
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(5000);
        executor.setThreadNamePrefix("GithubLookup-");
        executor.initialize();
        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

Associate the async service to the TaskExecutor

I think this example misses the association between the task executor and the service in an unfortunate way, i.e. how this is being set up (quote from the Javadoc): "By default, Spring will be searching for an associated thread pool definition: either a unique TaskExecutor bean in the context, or an Executor bean named "taskExecutor" otherwise. If neither of the two is resolvable, a SimpleAsyncTaskExecutor will be used to process async method invocations."

I think it could be beneficial for this guide, and for the possibility of using this code as a template, to add an explicit association between the executor and the async service by naming the executor bean and specifying the name of if in the @async annotation.

Otherwise I think it would be good to rename the the Executor bean to the expected name "taskExecutor"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.