I have created a quartz job, but I have seen that when I want to create a HttpClient from that job, it gets suspended when the program reaches the line
CloseableHttpClient clientToPost = HttpClients.createDefault();
Why does this happen?
Related
I am using the Spring WebFlux WebClient in a spring batch application and I am getting an error when I call block. The code is really simple but I am getting an error when the application I try launching a job from a Rest endpoint on a controller in the batch job.
The rest endpoint is like this:
#RequestMapping("/migration/products/catalog
class ProductController{
private final Job job;
ResponseEntity<Map<String,Object> loadProductCatalog(){
// Code to launch Product Catalog Job
}
}
Here is the method the calls a remote client to get Product Catalog information that can be used by the Controller to load information about products
public ProductInfo findProductInfo() {
try{
String url =....;
return webClient.get().uri(url)
.accept(MediaType.APPLICATION_JSON).retrieve().
bodyToMono(ProductInfo.class).share().block();
}catch(Exception e){
log.error("Exception during retrieval of ProductInfo Data [}", e);
return null;
}
}
The findProductInfo method is wrapped in a Service which is used to retrieve ProductInfo in the Controller.
I am using share() because the block() call to the Rest controller just hangs.
However, if I simply call block() with first calling share() the call to the controller returns but throws the following error. I'm very new to using WebFlux so I have no idea what is going on. I'd appreciate some help in deciphering what is going on and a solution to this problem
java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-2
When I use share() followed by block() my application hangs when I invoke the rest endpoint. However, if I use block() alone the method returns
Solved: My job was running in a single thread, so the share().block() was blocking the main thread of the job launcher. I figured out that from observing the task executor was synchronous and that gave me the clue, it suddenly made sense. I configured a task executor so the job would run in its own thread and viola!
I have a console application for the purposes of using quartz scheduling with masstransit. The related code is located in Task StartAsync(CancellationToken cancellationToken) implementation of IHostedService.
It looks like the following code
await _bus.ScheduleRecurringSend(new Uri($"queue_uri"),
new CustomMessageSchedule(),
new CustomMessage(),
cancellationToken: cancellationToken);
var scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
scheduler.JobFactory = new MassTransitJobFactory(_bus, _jobFactory);
await scheduler.Start(cancellationToken);
Scheduled messages are successfully published to the queue, but those are getting the same messageId. That causes some problems on a consumer side.
I've to make use of IFilter<SendContext<CustomMessage>> implementation, but it didn't work out. Maybe i wasn't using it right, but i'm not even sure if that's the right approach.
Any suggestions on the matter?
Scheduled messages are not modified by Quartz before being sent, other than including a few additional message headers. It might make sense to generate a new MessageId for recurring messages (since they're not a one-and-done scheduled message like regularly scheduled messages).
However, as of right now the behavior is as expected.
I'm using Activiti version 6.
I created a BPMN process from activiti-app.
Then I want to start that process from activiti-rest.war using the API.
http://localhost:8080/activiti-rest/service/runtime/process-instances
request body :
{
"processDefinitionKey":"cep_dispatch_process",
"businessKey":"myBusinessKey",
"returnVariables": false
}
header :
Content-Type:application/json
As I see in the LOG process is being started in tomcat threads.
referring latest GitHub code:
Activiti-activiti-6.0.0\modules\activiti-rest\src\main\java\org\activiti\rest\service\api\runtime\process\ProcessInstanceCollectionResource.java
When I see method,
#RequestMapping(value = "/runtime/process-instances", method = RequestMethod.POST, produces = "application/json")
public ProcessInstanceResponse createProcessInstance(#RequestBody ProcessInstanceCreateRequest request, HttpServletRequest httpRequest, HttpServletResponse response) {
I can see process is being started and not waiting for process to complete, HTTP response is 201. I can understand request is not being hold for process instance to complete.
instance = processInstanceBuilder.start();
response.setStatus(HttpStatus.CREATED.value());
Please refer the log snipped below, I can see process is executing in server thread and request is waiting till process completed.
276-DEBUG 17-01-2019 14:12:07,177- (http-nio-8080-exec-3) ExecutionEntityManagerImpl: Child execution Execution[ id '130023' ] - parent '130021' created with parent 130021
241-DEBUG 17-01-2019 14:12:07,178- (http-nio-8080-exec-3) ContinueProcessOperation: Executing boundary event activityBehavior class org.activiti.engine.impl.bpmn.behavior.BoundaryTimerEventActivityBehavior with execution 130023
171-DEBUG 17-01-2019 14:12:07,202- (http-nio-8080-exec-3) ContinueProcessOperation: Executing activityBehavior class org.activiti.engine.impl.bpmn.behavior.SubProcessActivityBehavior on activity 'sid-1A2A8DF5-764A-4960-8E5D-F347DC10207C' with execution 130021
276-DEBUG 17-01-2019 14:12:07,203- (http-nio-8080-exec-3) ExecutionEntityManagerImpl: Child execution Execution[ id '130025' ] - parent '130021' created with parent 130021
63-DEBUG 17-01-2019 14:12:07,203- (http-nio-8080-exec-3) DefaultActivitiEngineAgenda: Operation class org.activiti.engine.impl.agenda.ContinueProcessOperation added to agenda
70-DEBUG 17-01-2019 14:12:07,203- (http-nio-8080-exec-3) CommandInvoker: Executing operation class org.activiti.engine.impl.agenda.ContinueProcessOperation
Request must not wait for process to complete.
How can I solve this, request to start the process must not wait for process-instance to complete.
As you see in the response below:
{"id":"130028",
"url":"http://localhost:8080/activiti-rest/service/runtime/process-instances/130028",
"businessKey":"myBusinessKey",
"suspended":false,
"ended":true,
"processDefinitionId":"cep_dispatch_process:13:125033",
"processDefinitionUrl":"http://localhost:8080/activiti-rest/service/repository/process-definitions/cep_dispatch_process:13:125033"
,"processDefinitionKey":"cep_dispatch_process",
"activityId":null,
"variables":[],
"tenantId":"",
"name":null,
"completed":true
}
API is returning only after process completes, I add delay of 2 min in service task, I can see request will be waiting.
I'm not a big guru in Activiti but as a simplest solution I can suggest to activate Async executor and use Asynchronous Continuations for your service task. This could solve your problem. Activiti's behaviour is expected because until it has persisted state to DB it can't say for sure that process is created (because transaction could be rolled back due to DB error for example)
I am new to webflux and am not able to find the right material to continue with the implementation.
I want to issue a request and process the response asynchronously. In this case service call takes about 8-10 ms to respond, so we issue the request and continue doing other work, and look for the response when it is needed for further processing.
Mono<Map<String,Price>> resp = webClient.post()
.uri("/{type}",isCustomerPricing ? "customer" : "profile")
.body(Mono.just(priceDetailsRequest),PriceDetailsRequest.class)
.retrieve().bodyToMono(customerPriceDetailsType);
How do we make this call execute asynchronously on a different thread.(I tried subscriberOn with Schedulers.single/ Scheuldes.parallel), but didn't see the call getting executed until Mono.block() is called.
How do we achieve ?
We want this call execute in parallel on a separate thread, so the
current thread can continue with other work
When processing completes, set response to context
When the current thread looks for the response, if the service has not
completed, block until the call completes
You don't need to block for consuming the response. Just assign an operator to consume the response in the same chain. An example is given below.
Mono<Map<String,Price>> resp = webClient.post()
.uri("/{type}",isCustomerPricing ? "customer" : "profile")
.body(Mono.just(priceDetailsRequest),PriceDetailsRequest.class)
.retrieve()
.bodyToMono(CustomerPriceDetailsType.class)
.map(processor::responseToDatabaseEntity) // Create a persistable entity from the response
.map(priceRepository::save) // Save the entity to the database
.subscribe(); //This is to ensure that the flux is triggered.
Alternatively you can provide a consumer as a parameter of the subscribe() method.
I have one vert.x Standard Verticle Basically,it parses HttpRequest and prepare JsonObject then I am sending JSONObject through eventbus. In Another Worker verticle that event get consumed and it will kick off execution(includes call to Penthao Data Integration Java API) it is blocking API.It took around 30 minutes to complete execution of ".kjb" file. But vert.x is continuously warning about Worker Thread Block so my question is what would be best practice in vert.x to tackle this scenario.
Any help would be highly appreciated.
According to vertx doc all blocking operations need to perform in code
vertx.executeBlocking(future -> {
// Call some blocking API that takes a significant amount of time to return
String result = someAPI.blockingMethod("hello");
future.complete(result);
}, res -> {
System.out.println("The result is: " + res.result());
});
So it's the best practice for all blocking tasks.
You could also deploy your verticle as a worker.
This way:
vertx.deployVerticle(yourVerticleInstance, new DeploymentOptions().setWorker(true));