Is it ok to use RequestContextHolder.currentRequestAttributes().request in production? - spring

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)
}
}

Related

Cannot understand mocks

I'm trying to write tests for my Spring Boot application that has some end points, it's a REST application.
I have the "usual" simple web application with a controller, a service and a repository. CRUD operations.
In my update endpoint I call the service layer to perform the update, like this:
#PutMapping
public Post updatePost(#RequestBody Post post) {
return postService.updatePost(post);
}
The updatePost method on the PostService class makes some checks about the object before updating in it, and if the checks all pass, then the update operation is perforrmed, like this:
public Post updatePost(Post post) {
if (post == null || post.getId() == null) {
throw new PostGenericException();
}
Post postToUpdate = postRepo.findById(post.getId()).orElseThrow(PostGenericException::new);
bool isOk = true;
// some other checks..
if (!isOk) {
throw new PostGenericException();
}
// update operation
postToUpdate.setMessage(post.getMessage());
....
return postRepo.save(postToUpdate);
}
From what I've seen online in the test class I have to do something like this:
#WebMvcTest(PostController.class)
public class PostControllerTest {
#Autowired
private MockMvc mockMvc;
#Autowired
private ObjectMapper mapper;
#MockBean
private PostService postService;
#Test
public void updatePost() throws Exception {
Post post = new Post(...);
Mockito.when(postService.updatePost(post)).thenReturn(post);
mockMvc.perform(MockMvcRequestBuilders.put("/posts")
.contentType(MediaType.APPLICATION_JSON)
.content(this.mapper.writeValueAsString(post)))
.andExpect(status().isOk())
.andExpect(jsonPath("$", notNullValue()));
}
}
So here in the test method I'm completely replacing the logic of the updatePost method of the service layer with a fake one.
How is this useful?
The only good reason I can think of is that here I'm trying to test the endpoint by itself, meaning that I simply want to check if I can reach that endpoint, but I don't really care about the implementation at all, i.e how the update operation is performed. I'm expecting that if I make a PUT request to that endpoint I get a result, if the test fails I know that the controller doesn't handler that endpoint anymore.
Is this all about it or am I missing something?
If I remember correctly, Kent Beck also said that you don't want to test the implementation but only the public APIs, it doesn't make much sense to test the implementation anyway, you could have a lot of tests and at some point have more test code than production code.
Using mocks may be against your testing philosophy, but looking at the practicalities:
Web layer is a nice chunk to be tested separately. There is a good amount of things that you can check:
routing
request and response deserialization
validation
error handling
authentication
This also allows business logic tests to skip these concerns.
Additional benefits:
they are easy to set up and run on a single machine (or even single process)
they are reasonably fast

Can we use Shedlock to lock the API calls

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

Why is it beneficial to make async REST services?

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:

Web API concurrency and scalability

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.

How to annotate user existence checking with Spring?

I want to manage users projects through a JSON API and I'd like to use a relative path controller. Like this:
#RequestMapping(value="/users/{userId}/projects",
headers="Accept=application/json")
#Controller
public class UserProjectsController {
#Autowired
private UserRepository userRepository;
#RequestMapping(method=RequestMethod.GET)
public #ResponseBody Object getAllUserProjects(#PathVariable String userId) {
User user = userRepository.findById(userId);
if (user == null) {
return new ResponseEntity<String>(HttpStatus.NOT_FOUND);
}
return user.getGivenProjects();
}
}
I'll add numerous methods and every time I'll have to check if the user exists. Instead of adding that piece of code:
User user = userRepository.findById(userId);
if (user == null) {
return new ResponseEntity<String>(HttpStatus.NOT_FOUND);
}
... at starting of every method, I'd like to create a custom annotation which will return a 404 if the user doesn't exist.
I found this tutorial to do that. Is this really as complicated as described? Do you know any other solution? (I'd like to avoid writing 2 classes and more than 50 lines of code only to annotate 4 lines.)
Thank you.
I firstly assume that this check has nothing to do with Security, does it?
I think WebArgumentResolver won't fit your needs. Returning a 404 status might be complicated.
Maybe a custom interceptor can be a better solution. It will be called in every request to your controllers. There you can examine the handler object in order to see if it has a parameter called userId annotated with #PathVariable, for example. Then, you can do the check and use response object for returning a 404 if it's necessary.
Another option would be create a custom #Aspect, but we maybe are overcomplicating the problem. So first, try the previous solution.

Resources