DEV Community

Michael Fomenko
Michael Fomenko

Posted on

Check out Spring Undo ↩️ v0.0.1!

I just published Spring Undo v0.0.1

The library is still in development, but you can already try it out, all basic functionality works.
Just don't use it for production yet :)

GitHub: https://github.com/michaelfmnk/spring-undo

Spring Undo is a spring boot starter that provides a way to easily implement undo functionality in your Spring Boot application.

The main features are:

  • It drastically simplifies undo implementation. Reduces boilerplate that otherwise you need to manage.
  • It supports application scaling. Persist-module can use shared storage between all instances of your application. So you can call undo from any instance.
  • Spring-Undo is a Spring Boot Starter. You don't need to write any additional configuration for setting up Spring-Undo.

Usage

Add the following dependencies in your build.gradle file:

implementation 'dev.fomenko:spring-undo-core:v0.0.1'
implementation 'dev.fomenko:spring-undo-redis:v0.0.1'
Enter fullscreen mode Exit fullscreen mode

or pom.xml file:

<dependency>
    <groupId>dev.fomenko</groupId>
    <artifactId>spring-undo-core</artifactId>
    <version>0.0.1</version>
</dependency>
<dependency>
    <groupId>dev.fomenko</groupId>
    <artifactId>spring-undo-redis</artifactId>
    <version>0.0.1</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

For spring-undo-redis you need to have redis up & configured in your application.

First thing - you create a simple DTO that represents an event that can be undone.

@Data
@NoArgsConstructor
@AllArgsConstructor
public class EmailChangedEvent {
    private String oldEmail;
    private String newEmail;
}
Enter fullscreen mode Exit fullscreen mode

Then register an event listener that will be called when either undo timeout is reached, or undo is called.

@Component
public class EmailChangedUndoEventListener extends UndoEventListener<EmailChangedEvent> {
    @Override
    public void onUndo(EmailChangedEvent action) {
        // handle here undo logic: reset db state
    }

    @Override
    public void onPersist(EmailChangedEvent action) {
        // handle here what to do when event is persisted
        // For example, you can send notification to the new & old email address
    }
}
Enter fullscreen mode Exit fullscreen mode

Now autowire Undo bean and publish any object that represents an undoable action. publish returns an identifier of the action. You can use it to cancel action.

@RestController
@RequiredArgsConstructor
class UserController {
    private final Undo undo;

    @PutMapping("/email")
    public String changeEmail(ChangeEmailRequest request) {
        // main application logic
        var undoableEvent = new EmailChangedEvent("oldEmail@gmail.com", "newEmail@gmail.com");

        // publish method returns event id that can be used to undo the action
        return undo.publish(undoableEvent);
    }
}
Enter fullscreen mode Exit fullscreen mode

And lastly, create a controller that will undo the action by its identifier.

@RestController
public class UndoController {
    private final Undo undo;

    @GetMapping("/undo/{id}")
    public String undo(@PathVariable String id) {
        undo.undo(id);
        return "Undo successful";
    }
}
Enter fullscreen mode Exit fullscreen mode

You're done! 🎉

That's it. Now each time you want to implement an undo, you just create DTO event object & implement listener that will be called by Spring Undo on one of two cases: (1) undo was called, (2) timeout ended & undo was not called.

Contacts

Message me if you have any questions, suggestions or ideas for collaboration: michael@fomenko.dev

Discussion (0)