Create Async HTTP Process with Red Hat Fuse on Top of Openshift 3.11
Got a unique requirement yesterday where one process on Red Hat Fuse consuming a very long time, therefore creating lots of timeout error from frontend. It happen because some process on Fuse performing a very complicated task and we cannot modified existing api flow due to business requirements.
For this example, i want to simulate the same slowness on my Fuse + Spring Boot app,
package com.redhat.edw;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
A simple camel route,
package com.redhat.edw;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class Routes extends RouteBuilder {
@Override
public void configure() throws Exception {
restConfiguration("servlet")
.bindingMode(RestBindingMode.json)
;
rest()
.get("hello")
.route()
.setBody(method("helloRouteHandler", "setHelloWithName"))
.endRest()
;
}
}
A placeholder bean,
package com.redhat.edw;
import lombok.*;
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class HelloResponse {
private String content;
}
And a Handler class,
package com.redhat.edw;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Slf4j
@Component("helloRouteHandler")
public class HelloRouteHandler {
@Value("${name}")
private String name;
public HelloResponse setHelloWithName() throws Exception {
/*
* simulate a very long process (10second)
*/
Thread.sleep(10000);
/*
* this process will still getting called after 10 second regardless of sync or async
*/
log.info("calling hello for "+name);
return HelloResponse.builder().content(name).build();
}
}
And two simple properties file,
# The Camel context name camel.springboot.name=FuseHelloWorld # enable all management endpoints endpoints.enabled=true management.security.enabled=false camel.component.servlet.mapping.contextPath=/api/* name=Edwin
# OpenShift ConfigMap name spring.application.name=fuse-hello-world spring.cloud.kubernetes.reload.enabled=true spring.cloud.kubernetes.reload.strategy=restart_context spring.cloud.kubernetes.reload.monitoring-config-maps=true spring.cloud.kubernetes.reload.monitoring-secrets=true spring.cloud.kubernetes.reload.mode=polling
Run the project and try calling /api/hello api and see how much time is needed to give response time.

As you can see, 10seconds is not an acceptable response for a regular web user and wee need to improve it. The workaround is quite simple, Spring have an @Async method which we will utilize on Handler class,
package com.redhat.edw;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Slf4j
@Component("helloRouteHandler")
public class HelloRouteHandler {
@Value("${name}")
private String name;
@Async
public HelloResponse setHelloWithName() throws Exception {
/*
* simulate a very long process (10second)
*/
Thread.sleep(10000);
/*
* this process will still getting called after 10 second regardless of sync or async
*/
log.info("calling hello for "+name);
return HelloResponse.builder().content(name).build();
}
}
Which will give a faster response,

And we can deploy our code to Openshift by using this command,
mvn fabric8:deploy -Pfabric8
A successful deployment will looks like this,

And finally, the complete code can be downloaded from this url,
https://github.com/edwin/fuse-with-async-http







