Spring Boot execute a method at a specific time - spring-boot

Suppose I have the following method head in a service:
public void sentMail(LocalDateTime date, User user);
I want that when running this method an email is sent to this user etc. Sending an email is no problem, but I don't know how to make it so that this email can be sent exactly at this time.
I noticed that you can trigger method in a certain interval, but this doesn't look like "THE" solutions to me.

Related

Is it possible to make some action in a new Spring trascation before a user stars work with it?

I have Spring Boot JPA application.
An application user asks a new transaction from time to time.
I'd like to execute some action on a db connection that is related with the transaction just BEFORE the use can work with that transaction.
"Just BEFORE" means the action has been completed before the first statement of a method annotated with #Transactional is executed.
The action is an execution of a stored procedure with params depend on the current application user.
Application uses work with DB under a technical account.
Thank you in advance
First solution:
Put all in #Transacional annotated method, where your pre-transaction, however this may sound weird, part goes first.
This first part may perform any action and maybe throw en exception if anything goes wrong, thus forcing the transaction to roll back. This may be a #Repository method, a #Query annotated one if needed (like Josh Pospisil suggests) or whatever.
Second solution (I would prefer):
Put 3 method calls in your #RestController's method: first - determining the user, second - performing your pre-transactional action using this user's data, third - the actual #Transacional method doing the job.

Implementing a background service that sends out reminders based on the reminder time and user authentication using a token-based mechanism.

I am pretty new to Spring Boot, and working on developing a mini application for myself, that will able to implement a service that provides a set of APIs for managing a set of calendars for different users.
I am using STS IDE for this project and selected Apache Derby, JPA and Web dependencies for the same. I have created two Entity class for CalanderEvents and CalanderUser and the basic CRUD operation for both of them.
I have two questions:
1)I am using Postman app to implement CRUD operations and just cant figure out how to fetch Meeting time for Post master in STS so that I can create a background app that sends reminder 30 minutes prior to the meeting time.
Will #Async work here?
2) For user based authentication, I think JWT will do the work, but do I need to have a GUI just to implement token based authentication, or can I do it through postman?
I am not sure if I am able to clearly put up my query, please let me know if you think I need to add some more information.
Thanks.
Small precision -- you're not using Postman to implement CRUD; you're using Postman to test your implementation.
#Async is used to allow the execution of methods in an asynchronous manner (in other words, multiple methods can run at the same time). What you're looking for is probably #Scheduled.
#Scheduled allows you to schedule a task every X amount of time -- in your case, to schedule the execution of a method, you'd do something like that:
#Scheduled(fixedRate = 1800000)
public void sendMessagePeriodically() {
// ...
}
(1000ms * 60 * 30 = 1800000ms = 30min)
In order for the above to work, you can annotate a configuration class with #EnableScheduling:
#Configuration
#EnableScheduling
public class SchedulingConfiguration {
}
Alternatively, you can add #EnableScheduling on top of your main class (the one with #SpringBootApplication)
No, you don't need a GUI. All you need to do is implement an authentication system either with Spring Security (which would make your work much easier), or by using a controller. Then, you can simply communicate with that API using Postman in order to authenticate yourself.
Good luck.
Update
For instance, you can schedule a task that runs every minute and checks if there's any events scheduled in 30 minutes. If there is, then send a notification:
#Scheduled(fixedRate = 60000)
public void checkForUpcomingEvents() {
// get all events scheduled in ~30 minutes
List<Event> events = getEventsScheduledSoon();
for (Event event : events) { // for each event
event.notifyUsers(); // notify all users concerned
}
}
Note that it is important that you get all events that have an event in approximately 30 minutes (e.g. between 29 - 31), because while you can rely on #Scheduled to execute, you still need to consider potential delays. Following that logic, you also need to make sure that you don't notify the same person for the same event twice.
There are multiple variables to consider, for instance, how long does getting events take? How long does notifying the users take? Depending on those variables, you may need to adjust your configuration (e.g. run every 5 minutes instead of 1 minute).
There are really a lot of ways to go about this, your solution of using java's ExecutorService is also an excellent one, but as you have tagged your question with spring-boot and not java, I opted for the #Scheduled approach.

Understanding transactions in Spring Test

I have a little bit trouble with Integration Test and the transactions.
I have a Rest Service System. Behind all I have a JPA-Repository, with a Postgres database. Now to test them I build JunitTest where I made the calls on the System. The test loads the web-context and an other xy-context where I have the configuration of security and database connections. On the test method I have the #Transactional annotation.
The test makes 2 requests (This is only one example I have more of similar scenarios on other Object):
insert a new user
on this user create a Group and after bind this to the user
The test makes the first call, and returns me a id where I use to perform the second call.
The second call take the id and make the post and there I have several problems.
Details of the second call:
Test make a post on a controller
Controller takes the request and forward it to the Service
Service method (with #Transactional) take the request and do:
a research to find the inserted user
insert a group object
update the user with the groupId (generated on point 2)
Now one of the problems I had, it was a AccessDeniedException on point 3.1, because I have also ACL, and I have to check if there are enough permissions.
One of the things that I tried to do is to set:
#Transactional(propagation=Propagation.REQUIRES_NEW)
on the Service Method.
What I get after is the result that the AccessDeniedException was disappeared but the research at 3.1 gives me empty result (the research is ok, because on other scenario I have correct results), but is strange because the first post was ok, and how I understand Spring handles the #Transactions and "commits" to database so that a commit is performed when a transaction is closed. This brings me to an other idea to try: remove the #Transaction annotation on the test, but when i made this, then the database has all the data of this scenario until the end of the tests session (If you have a lot of test this is not desirable), and this is not a very good thing.
Now I wrote a little bit where are my doubts, and problems without posting a lot of code and of privacy problems, but on request I can post little pieces of codes.
It's also probable that the approach is incorrect.
The questions are:
-how can I make this service work?
-It's the correct way to set (propagation=Propagation.REQUIRES_NEW)?
-It's the correct way to set #Transactional on the test? (eventually with a Rollback?)
Txs a lot.
To make test I use mockMvc to make the request and some annotation on the class:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(locations = { ..... })
#Transactional
public class tests {
#Test
public void aTest(){
mockMvc = MockMvcBuilders
.webAppContextSetup(webApplicationContext)
.addFilter(new DelegatingFilterProxy("springSecurityFilterChain", webApplicationContext), "/*")
.build();
mockMvc.perform(post(.....))
}
}
To answer your question:
It's the correct way to set #Transactional on the test? (eventually with a Rollback?)
No really, but you can. Because you are doing two requests, the second depends on the first, and http request will not remember your transaction, if you insist to do it, you need flush your session between requests.
It's the correct way to set (propagation=Propagation.REQUIRES_NEW)?
It depends. REQUIRES_NEW means it will start new transaction, the influence is that everything in the existing transaction will be invisible in the new transaction, because the old one is not commited yet! if this server is the entry point of the transaction, it makes no difference, but be aware of the visibility problem.
how can I make this service work?
OK, forget what my answers of the previous questions. If I have to write the test, I will do it this way:
The test is not transactional. If you are doing integration test, you don't need to rollback single tests. If you wanna rollback the commit, then you are having wrong task case, you should have two test cases insert user and update group.
3 parts of the test
Send request to insert user and get the ID (single transaction)
Send request to update group(another transaction)
Send request to fetch the user and do the checks.
Hope this can help you.

Giving users immediate response in Event Driven Architecture

I have been reading a lot about Event Driven Architecture and it makes a lot of sense to me, but the issue of giving users immediate feedback is confusing me.
Say there is a service ('EmployeeService') that holds a list of all employees. The business logic for creating an employee is located in this service.
The UI from another system uses this service. The requirement is (whether you like it or not) that it has a grid of employees, and an 'add employee button' which brings up a form, and when you submit the form, it returns you to the gird with the new employee in it. The grid show derived fields which are calculated by the service (this is important to note!).
Traditionally, on submit, I would have displayed a loading screen, synchronously sent a WCF request to register the employee, and when that had completed, and forwarded to the grid (which would definately by now have the new employee).
With EDA, on submit, I would 'fire and forget' a command to register the user - but then what? I could forward to the grid but there is a chance the new employee might not be in there yet? I could manually add to the grid assuming all will be OK, but how do I display the derived data calculated by the service? Or maybe I could have a 'new employee pending graphic' displayed on the grid if it has not been created yet, then make the page check back every few secons until it has?
This is a common scenario so what is the common solution for this?
You can register a callback when sending the command and block until the command is complete.
If you've downloaded the NServiceBus package, just reference the AsyncPagesMvc3 sample solution. It has an example of exactly what you're looking for.
If your EmployeeService is a SOA service then the Add Employee Button also belongs to the EmployeeService. The user interface is simple a composite of multiple services. You can deploy part of the EmployeeService locally on the client which handles the employee creation and the calculation (if the calculation is not a complex one).
For example:
public class AddEmployeeView
{
public IBus Bus { get; set; }
public void AddNewClicked() {
// async calculate
// store directly in the employee service database
// or dispatch command internally
// refresh employee list as the service is the only owner of that data
Bus.Publish<NewEmployeeAdded>(m => { });
}
}
So the above AddEmployeeView belongs to the EmployeeService. The EmployeeService alone has knowledge how to calculate and store new employees (even in its own database) and is the only logical publisher of the NewEmployeeAdded event. And here goes away your complexity.

Validate/Change Password via REST API

I want to change a user password via a REST API. This is not a forgotten or reset password function, but a logged in user wanting to change their password.
The form requires the current password, the new password, and a confirmation for the new password. However, I want to validate each form field as the user fills it out. This is trivial for newPassword and confirmNewPassword (client side), but not for currentPassword. Currently performing update to the User object via PUT /users/:id. If a password parameter is passed, I check for the currentPassword parameter and ensure it is correct prior to saving. However, for validation, I'm unsure of the best approach.
I also have a POST /users/validate - not sure if this is best either. This validates a User object for both create and update, but only validates fields that belong to the User object (email, username, password). currentPassword isn't one of these. Wondering how to handle this. Some things I've considered:
POST /users/check_password,
POST /users/validate (adding in validation for currentPassword if that parameter is passed, and check that currentPassword matches the users existing password) and
POST /users/:id/validate (separate validation for existing user, requiring currentPassword).
Any thoughts or advice would be greatly appreciated. My first application that only exposes functionality via REST API.
I'll start by pointing out that authentication is often handled outside of a REST model. When a user provides their credentials, they are not providing a REpresentation of their account object's STate (REST); nor is the response they receive such a representation. Because the user account resource state does not include both 'current' and 'new' passwords, the provision of both a 'current' and a 'new' password in a request can never truly fit under the REST model, but professionals often describe a 'continuum' of RESTfulness, with some APIs being completely RESTful and others falling between RPC (Remote Procedure Call) and REST.
It's not uncommon to have a RESTful component of an API that handles the serving of data models, and a more RPC component of an API that handles user accounts. You get to decide between the two. If your project includes super users that manage multiple user accounts, I would suggest trying to shoe-horn that into a REST API. If each user manages only their own account, I would suggest RPC.
If you've decided to use REST for account management, then you must choose an appropriate HTTP method (GET, POST, DELETE, HEADERS, etc). Clearly you require a method that will effect a change on the server (POST, PUT, DELETE, etc). In contrast to user orbfish's conclusion above, I'm going to say that PUT would be an appropriate method, under certain restrictions.
From RFC 2616, which formally defines our HTTP methods:
"Methods can also have the property of 'idempotence' in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property. Also, the methods OPTIONS and TRACE SHOULD NOT have side effects, and so are inherently idempotent. "
Idempotency here means that if we make the same request n times in a row, the state of the server under the effects of the nth request will be the same as the state of the server under the effects of the first request. User orbfish correctly notes that if we make the request:
PUT /users/:id/account {current-password: 'a', new-password: 'b'}
and repeat it:
PUT /users/:id/account {current-password: 'a', new-password: 'b'}
that our first request should receive a response indicating success and our second request should receive a response indicating failure. However, the idempotency of PUT only requires that the state of the server is the same following both requests. And it is: after the first request the user's password is 'b' and after the second request the user's password is 'b'.
I mentioned restrictions above. You might want to lock a user out after m attempts to change a password unsuccessfully; this would provide security against brute-force password attacks. However, this would break the idempotency of the request: send a valid password request one time and you change your password, send it m more times and the server locks you out.
By specifying the PUT method, you are telling all clients that it's safe to send a request as many times as needed. If I as a client send a PUT request and our connection is interrupted such that I don't receive your response, I know that it is safe to send my PUT through again because it is idempotent: idempotency means that if you receive both requests it will be the same to your server as just receiving one. But if you're going to lock me out for an unsuccessful request, then it isn't safe to send a second request until I know whether you have received the first.
For this reason, you might consider PATCH or POST. I would suggest using PATCH. Whereas POST is described as either appending a new resource to a list or appending data to an existing resource, PATCH is described as a 'partial update' on a resource at a known URI. And unlike PUT, PATCH need not be idempotent.
I don't like /check_password or /validate because they're verbs; your first "update user" is better REST.
You can add the currentPassword to your User object as an unpersisted field, or as part of the Authentication header (username:password).
I would definitely change this from a PUT to a POST, though, because the same call with the same currentPassword cannot succeed twice (PUT is idempotent).
You are changing a property of the user resource (i.e., the password). If you use HTTP Basic for your authorization, you are already providing the current password, so there is no need to repeat it. I would simply PUT the entire user resource with the new password. Example:
PUT /users/fiddlerpianist HTTP/1.1
Content-Type: application/json
Authorization: Basic ZmlkZGxlcnBpYW5pc3Q6bXlub3Rzb2F3ZXNvbWVvbGRwYXNzd29yZA==
{
"password": "My awesome new password that no one will ever be able to guess!"
}
The other advantage of doing it this way is that you don't necessarily need to provide the old password, as long as you are a credentialed user that has access rights to modify the user resource. Maybe you're a customer support specialist who is never supposed to ask for the customer's old password but they are requesting a password change over the phone (after they've proven to you their identity and you've proven your identity to the system).
You want to avoid using a non-idempotent request in this case (such as PUT or PATCH), as that can lead to responses whose outcomes are uncertain (suppose the server returns a 500 for a non-idempotent request... you as the client have no idea what state the server left your resource in).
EDITED TO ADD: Note that, in a RESTful app, there is no concept of being "logged in." The communication from the client to the server is entirely stateless (it's the payload and method that communicates the state). Also, there really doesn't need to be a concept of validation the way you describe it, as a request to change the state of a resource can either be met with a 200 OK (if valid) or a 400 Bad Request (if invalid).
Another option is to create surrogate resources on user. If you're using HATEOAS you could link down to user/x/pwdchange from the user resource. And I want to clarify pwdchange is conceived as a noun/resource, not as a verb:
GET /user/jsmith/pwdchange List of password change requests (history)
POST /user/jsmith/pwdchange Create password change request, return id=1
GET /user/jsmith/pwdchange/1 Get password change resource, which would
include the outcome (success, failure, etc)
So, in short, I'm creating a resource named 'pwdchange' that is fully compliant with a REST view of the problem domain.
You might think about why you need to validate the current password as soon as it's entered. I've not seen a site do that. Second, it's perfectly fine to have a service that just validates something. Its called being practical verse beating yourself up trying to be RESTFul

Resources