Spring allows a method annotated with #RequestMapping to return a variety of objects, including a CompletableFuture or a Future. This allows me to spawn off an async method and let spring return the value whenever it is ready. What I am not sure I am understanding is if there are any benefits to this. For instance:
#RestController
public class MyController {
#RequestMapping("/user/{userId}")
public CompletableFuture<User> getUser(#PathVariable("userId") String userId) {
return CompletableFuture.supplyAsync(
() -> this.dataAccess.getUser(userId));
}
In this case, even though the actual computation is happening in the background, the connection will still not close and the request thread will still be active till it is done. How is it better than say:
#RequestMapping("/user/{userId}")
public User getUser(#PathVariableS("userId") String userId) {
return this.dataAccess.getUser(userId);
}
From first glances, this seems to be a better approach as there is no overhead with an additional thread and a watcher that looks for completion.
This takes advantage of Servlet 3 asynchronous request processing, using request.startAsync() method. Read here and here
To achieve this, a Servlet 3 web application can call request.startAsync() and use the returned AsyncContext to continue to write to the response from some other separate thread. At the same time from a client's perspective the request still looks like any other HTTP request-response interaction. It just takes longer to complete. The following is the sequence of events:
Related
Do I have to make the method check() thread-safe?
#Component
public class MyHealthIndicator implements HealthIndicator {
#Autowired
private MyComponent myComponent;
#Override
public Health health() {
int errorCode = myComponent.check();
if (errorCode != 0) {
return Health.down().withDetail("Error Code", errorCode).build();
}
return Health.up().build();
}
}
Is the request to the corresponding actuator endpoint executed in a separated thread?
The app logic itself has only one thread.
To answer the direct question you asked ...
Do I have to make the method check() thread-safe?
You don't have to make it thread-safe, but if your application requires that myComponent.check() is only executed by a single thread at once, then yes, you'll need to mark it synchronized.
To answer the more general question
Is HealthIndicator thread safe?
By default, each health check initiated (often by an HTTP call, perhaps to /actuator/health) will run on a single thread, and check the health of each component that's registered a HealthIndicator sequentially, and thus the individual request is single-threaded.
HOWEVER ... there's nothing to stop multiple clients each making a request to /actuator/health at the same time, and thus there may be multiple health checks in progress at the same time, each of which will be executing on a different thread.
Therefore, if there's some reason why myComponent.check() should not be executed by more than one thread concurrently, you will need to mark it synchronized or else add in some other concurrency limiting mechanisms (e.g. java.util.concurrent.Semaphore).
In our project we are using ShedLock to prevents concurrent execution of scheduled Spring task. Sometimes we need to call this task manually, so to our front end we added a button which when clicked will call(API) this task. Now can we use ShedLock so that when the user clicks the button multiple times it will only execute the task one time and lock until it is complete.
You can certainly do that with dlock. Imagine Controller A and Service A where Controller A calls Service A. If you have a method doSomeWork at service A annotated by dlock, you can safely call the method from controller A as many as you want and it would run the service only once until the timeout. Here's a concrete example.
Service A should be something like this.
#TryLock(name = "doSomeWork", owner = "serviceA", lockFor = ONE_MINUTE)
public void doSomeWork() {
//...
}
Controller A would be something like this.
#RequestMapping(method = RequestMethod.POST)
#ResponseStatus(HttpStatus.CREATED)
#ResponseBody
public void doSomeWork() {
serviceA.doSomeWork();
}
See this post for more information.
From the API method, uou can use the lock manually as described in the documentation
LockingTaskExecutor executor // injected by Spring
...
Instant lockAtMostUntil = Instant.now().plusSeconds(600);
executor.executeWithLock(runnable, new LockConfiguration("lockName", lockAtMostUntil));
Did You tried to use proxy method?
#EnableSchedulerLock(mode = PROXY_METHOD, defaultLockAtMostFor = "PT30S")
https://github.com/lukas-krecan/ShedLock#scheduled-method-proxy
I am building an app in java.I hit api more than 15000 times in loop and get the response ( response is static only )
Example
**
username in for loop
GET api.someapi/username
processing
end loop
**
It is taking hours to complete all the calls. Suggest me any way (any cache technology) to reduce the call time.
P.S :
1) i am hitting api from java rest client(Spring resttemplate)
2) that api i am hitting is the public one, not developed by me
3) gonna deploy in heroku
Try using Springs Cache Abstraction, docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html.
You can use this abstraction in the method which has the restTemplate call.
Any method calls response can be cached using this abstraction, with the method parameters as the keys and the return type as the response.
#Cacheable("username")
public UserResponse getUser(String username){
// Code to call your rest api
}
This creates a Spring AOP advice around the method. Every time the method is called it checks if the data is available in the cache for this key(username), if yes then returns the response from the Cache and not calls the actual method. If the data is not available in the Cache then it calls the actual method and caches the data in the cache, so next time when the same method is called with same key the data can be picked from Cache.
This cache abstraction can be backed by simple JVM caches like Guava or more sophisticated cache implementations like EHCache, Redis, HazelCast as well.
One very important note to that answer: If you ever plan to update those (cached) values, don't forget to use #CacheEvict on save() and delete() in the repositories. Else you will have problems fetching the new record when it is updated.
I have implemented my solution (with EhCache) this way (in the repository):
CurrencyRepository.java:
// define a cacheable statement
#Cacheable("currencyByIdentifier")
public Currency findOneByIdentifier(String identifier);
CacheConfiguration.java: // Define that cache in EhCache Configuration
#Bean
public JCacheManagerCustomizer cacheManagerCustomizer() {
return cm -> {
cm.createCache("currencyByIdentifier", jcacheConfiguration);
cm.createCache("sourceSystemByIdentifier", jcacheConfiguration);
};
}
CurrencyRepository.java:
// evict on save and delete by overriding the default method
#Override
#CacheEvict("currencyByIdentifier")
<S extends Currency> S save(S currency);
#Override
#CacheEvict("currencyByIdentifier")
void delete(Currency currency);
I hope that helps :)
Does RequestContextHolder.currentRequestAttributes().request has any performance impact? I know that this is not good to access request inside service methods but I really need it. So if I call RequestContextHolder.currentRequestAttributes().request 20-30 times per request does it slow down performance?
The problem is not related to perfomance. Ipotetically a service method can be called outside of a request (for example in a quartz scheduled job). Probably in this case RequestContextHolder.currentRequestAttributes().request will throw an exception. The best way I think is to pass the request as parameter to service method that need it.
class MyService{
def method(def request){
//do what you want with the request
}
}
And from a controller
class MyController{
def myService
def index = {
myService.method(request)
}
}
We are faced with the task to convert a REST service based on custom code to Web API. The service has a substantial amount of requests and operates on data that could take some time to load, but once loaded it can be cached and used to serve all of the incoming requests. The previous version of the service would have one thread responsible for loading the data and getting it into the cache. To prevent the IIS from running out of worker threads clients would get a "come back later" response until the cache was ready.
My understanding of Web API is that it has an asynchronous behavior built in by operating on tasks, and as a result the number of requests will not directly relate to the number of physical threads being held.
In the new implementation of the service I am planning to let the requests wait until the cache is ready and then make a valid reply. I have made a very rough sketch of the code to illustrate:
public class ContactsController : ApiController
{
private readonly IContactRepository _contactRepository;
public ContactsController(IContactRepository contactRepository)
{
if (contactRepository == null)
throw new ArgumentNullException("contactRepository");
_contactRepository = contactRepository;
}
public IEnumerable<Contact> Get()
{
return _contactRepository.Get();
}
}
public class ContactRepository : IContactRepository
{
private readonly Lazy<IEnumerable<Contact>> _contactsLazy;
public ContactRepository()
{
_contactsLazy = new Lazy<IEnumerable<Contact>>(LoadFromDatabase,
LazyThreadSafetyMode.ExecutionAndPublication);
}
public IEnumerable<Contact> Get()
{
return _contactsLazy.Value;
}
private IEnumerable<Contact> LoadFromDatabase()
{
// This method could be take a long time to execute.
throw new NotImplementedException();
}
}
Please do not put too much value in the design of the code - it is only constructed to illustrate the problem and is not how we did it in the actual solution. IContactRepository is registered in the IoC container as a singleton and is injected into the controller. The Lazy with LazyThreadSafetyMode.ExecutionAndPublication ensures only the first thread/request is running the initialization code, the following rquests are blocked until the initialization completes.
Would Web API be able to handle 1000 requests waiting for the initialization to complete while other requests not hitting this Lazy are being service and without the IIS running out of worker threads?
Returning Task<T> from the action will allow the code to run on the background thread (ThreadPool) and release the IIS thread. So in this case, I would change
public IEnumerable<Contact> Get()
to
public Task<IEnumerable<Contact>> Get()
Remember to return a started task otherwise the thread will just sit and do nothing.
Lazy implementation while can be useful, has got little to do with the behaviour of the Web API. So I am not gonna comment on that. With or without lazy, task based return type is the way to go for long running operations.
I have got two blog posts on this which are probably useful to you: here and here.