Java - Event Sourcing - Event Sequence - java

So, while developing an app, I have to use event sourcing to track down all changes to model. The app itself is made using spring framework. The problem I encountered: for example, user A sends a command to delete an entity and it takes 1 second to complete this task. User B, at the same time, sends a request to modify, for example, an entity name and it takes 2 seconds to do so. So my program finishes deleting this entity (persisting an event that says this entity is deleted), and after it another event is persisted for the same entity, that says that we just modified its name. But no actions are allowed with deleted entities. Boom, we just broke the app logic. It seems to me, that I have to put methods that write to database in synchronized blocks, but is there are any other way to handle this issue? Like, I dunno, queuing events? The application is not huge, and not a lot of requests are expected, so users can wait for its request turn in the queue (of course I can return 202 HTTP Status Code to him, but like I said, requests are not resource heavy and there wont be a lot of them, so its unnecessary). So what is the best way for me to use here?
EDIT: Added code to illustrate the problem. Is using synchronized in this case is a good practice or there are other choices?
#RestController
#RequestMapping("/api/test")
public class TestController {
#Autowired
private TestCommandService testCommandService;
#RequestMapping(value = "/api/test/update", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.OK)
public void update(TestUpdateCommand command) {
testCommandService.update(command);
}
#RequestMapping(value = "/api/test/delete", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.OK)
public void delete(Long id) {
testCommandService.delete(id);
}
}
public class TestUpdateCommand {
private Long id;
private String name;
public TestUpdateCommand() {
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public interface TestCommandService {
void delete(Long id);
void update(TestRegisterCommand command);
}
#Service
public class TestCommandServiceImpl implements TestCommandService {
#Autowired
TestEventRepository testEventRepository;
#Override
#Transactional
public void delete(Long id) {
synchronized (TestEvent.class) {
//do logic, check if data is valid from the domain point of view. Logic is also in synchronized block
DeleteTestEvent event = new DeleteTestEvent();
event.setId(id);
testEventRepository.save(event);
}
}
#Override
#Transactional
public void update(TestUpdateCommand command) {
synchronized (TestEvent.class) {
//do logic, check if data is valid from the domain point of view. Logic is also in synchronized block
UpdateTestEvent event = new DeleteTestEvent();
event.setId(command.getId());
event.setName(command.getName());
testEventRepository.save(event);
}
}
}
#Entity
public abstract class TestEvent {
#Id
private Long id;
public Event() {
}
public Event(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
#Entity
public class DeleteTestEvent extends TestEvent {
}
#Entity
public class UpdateTestEvent extends TestEvent {
private String name;
public UpdateTestEvent() {
}
public UpdateTestEvent(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public interface TestEventRepository extends JpaRepository<TestEvent, Long>{
}

Make sure you read Don't Delete -- Just Don't by Udi Dahan.
I have to put methods that write to database in synchronized blocks, but is there are any other way to handle this issue?
Yes, but you have to be careful about identifying what the issue is...
In the simple version; as you have discovered, allowing multiple sources of "truth" can introduce a conflict. Synchronization blocks is one answer, but scaling synchronization is challenging.
Another approach is to use a "compare and swap approach" -- each of your writers loads the "current" copy of the state, calculates changes, and then swaps the new state for the "current" state. Imagine two writers, one trying to change state:A to state:B, and one trying to change state:A to state:C. If the first save wins the race, then the second save fails, because (A->C) isn't a legal write when the current state is B. The second writer needs to start over.
(If you are familiar with "conditional PUT" from HTTP, this is the same idea).
At a more advanced level, the requirement that the behavior of your system depends on the order that messages arrive is suspicious: see Udi Dahan's Race Conditions Don't Exist. Why is it wrong to change something after deleting it?
You might be interested in Martin Kleppmann's work on conflict resolution for eventual consistency. He specifically discusses examples where one writer edits an element that another writer deletes.

Related

How can i update a field of a ListItem (LiveData)

How can i update a field of a ListItem?
I have following POJO and ViewModel classes. Currently i am getting the complete list from LiveData object and then updating its data then re-setting the value of LiveData object, But I don't think this is the correct way to do it because to update just name of a single book i have to reset the complete LiveData Object.
Any other suggestion or Good practice to do it the correct way?
public class Book {
private long id;
private String name;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class BookProvider extends AndroidViewModel {
private final MutableLiveData<List<Book>> booksData;
public BookProvider(#NonNull Application application) {
super(application);
booksData = new MutableLiveData<>();
}
public LiveData<List<Book>> getBooksData() {
return booksData;
}
public void updateBookName(int position, String name) {
final List<Book> books = booksData.getValue();
if (books != null && books.size() > position) {
books.get(position).setName(name);
}
booksData.setValue(books);
}
}
LiveData is just a container holding a reference to your data and notifying possible observer of changes. So as far as LiveData is concerned this is the best you can do.
However LiveData does't support molecular changes so every change may results in the entire list invalidating and redrawn. It is strongly suggested that you use a different method if you have lot of changes in data (like real-time applications).

What is good practice to create pojo as having Class fields or simple

What is good practice to create pojo as having Class fields or simple fields.
I am creating pojo like this.
public class StatusDTO {
private String id;
private int totalNodes;
private int totalServlets;
private boolean status;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getTotalNodes() {
return totalNodes;
}
public void setTotalNodes(int totalNodes) {
this.totalNodes = totalNodes;
}
public int getTotalServlets() {
return totalServlets;
}
public void setTotalServlets(int totalServlets) {
this.totalServlets = totalServlets;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
}
someone recommanded me to do like this as below
public class StatusDTO {
private String id;
private boolean status;
private Total total;
public Total getTotal() {
return total;
}
public void setTotal(Total total) {
this.total = total;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public static class Total {
private int nodes;
private int servlets;
public int getNodes() {
return nodes;
}
public void setNodes(int nodes) {
this.nodes = nodes;
}
public int getServlets() {
return servlets;
}
public void setServlets(int servlets) {
this.servlets = servlets;
}
}
}
what difference does it make? what is good practice among those two?
I am using this class to set db info and send info to web socket client(stomp)
The answer, as always in such questions, is: It depends.
Simple classes like the first one have the advantage that they are simpler and smaller. The advantage on the second attempt is that if your class, maybe now, maybe later, gets extended, it might be easier if you create a separate Total class.
Good Objectoriented Programming, and Java is strongly OO, almost always requires you to put everything into it's own class.
As a rule of thumb, I create a separate class if:
there is some functionality you to your fields.
you have more then two, mabye three fields related to each other (e.g. connectionHost, connectionPort)
it's just a model class (e.g. Customer, Article)
I can use the field in multiple other classes
Of course there are more but those are some of the most important ones (comment if you think there is another important one I forgot to mention).
Well, one important thing in a good Java application is separation of concerns, for example in an airport application a service that give the last flight of a customer should not require as parameter an object with the first name, the last name, the social security number, the marital status, the gender or whatever other information about the customer that are completely useless (or should be) in retrieving the customer last flight, such that you need to have an object Customer (with all customer information) and another object CustomerId (with only the necessary bits to get the flights).
Another example is for a online shop application, a service that calculate the total price of the basket should not require all the information about all articles (photos, description, specifications, ...) in the basket but only the prices and the discounts which should be enclosed in another object.
Here you have to decide if the concerns of your Total (you need a better name) object could be taken separately of the concerns of your StatusDTO object, such that a method could require only the Total object without the associated StatusDTO object. If you can take them separately then you should have separate objects, if you can't then it's unnecessary.

How to set validation context with annotations

Imagine I've an action MyAction, with a field User with getters and setters.
Then I have two exposed public methods where I want to use visitor validation for the object User but with two different contexts, so that the User is validated in two different ways, depending on the method that has been called.
I want to do this with annotations only, no validation.xml.
See the example
public class MyAction extends ActionSupport {
private User user;
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user=user;
}
public string execute() {
//some code here ...
return SUCCESS;
}
#Validations(
visitorFields = {#VisitorFieldValidator(context="myContext1", fieldName="user", key="error.message", message="A default error message", shortCircuit=true)}
)
public string save() {
//some code here ...
return SUCCESS;
}
#Validations(
visitorFields = {#VisitorFieldValidator(context="myContext2", fieldName="user", key="error.message", message="A default error message", shortCircuit=true)}
)
public string update() {
//some code here ...
return SUCCESS;
}
//...
}
Now I'd like to specify the context (myContext1 and myContext2) into the annotations inside the User object, so that some validators fire when the save() method is called on MyAction while others fire when update() is called.
I imagine something like this:
public class User implements Serializable {
private Integer id;
private String name;
#RequiredFieldValidator(context="myContext2", message = "You must enter a value for data.")
public void setId(Integer id) {
this.id=id;
}
#RequiredFieldValidator(context="myContext1", message = "You must enter a value for data.")
public void setName(String name) {
this.name = name;
}
//some code... getters, etc...
}
I'd like to do this so that, for example, during creation operation (method save()) the name is required while during update operation (method update() ) the id is required. Unfortunately it seems to me that RequiredFieldValidator, so any other validator annotation in Struts2, does not support the "context" field.
I know that I can use a User-myContext1-validation.xml, and a User-myContext2-validation.xml file (I've not tried but I think I've understood it can be done) but I'd like to use annotations only.
Do you know How I can do this with annotations?

Save List changes with Hibernate

I have an Object named Token. it has id, name, and value. After saving some data to db, I have loaded them into a web page
_____________________________________________
|____name____|____value____|____operation____|
tkn1 10 ×
tkn2 20 ×
the × sign enable me to delete a token from server collection
now. I have added token tkn3 with value 30 and deleted tkn2 so
the table would be:
_____________________________________________
|____name____|____value____|____operation____|
tkn1 10 ×
tkn3 30 ×
With these changes to the collection, how can I reflect them into database
how to determine the records that deleted, and the records that added?
I applied tow solutions:
I have compared -in business logic layer- the old data with the new data
and find the differences between the then send to database two lists, the first contains
the added tokens and the second contains the ids of tokens to be deleted.
I added a flag named status to the object.. when I add the flag is NEW
when I delete I just set flag to DELETE, and in DB layer I iterate over the collection
one by one object and check the flag.. if NEW then add the record, if DELETE , delete it
and if SAVED (no changes) I do no changes to it..
My questions:
Is this way is good to do this task..?
Is there a Pattern to accomplish this task?
Can Hibernate help me to do that?
• Is this way is good to do this task..?
NO
• Is there a Pattern to accomplish this task?
YES
• Can Hibernate help me to do that?
Hibernate provides the solution for such situation using Cascade Attribute for List property
Refer
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/collections.html
http://www.mkyong.com/hibernate/hibernate-cascade-example-save-update-delete-and-delete-orphan/
The blow entity should solve your problem.
#Entity
public class MyEntity {
private static enum Status {
NEW,
PERSISTENT,
REMOVED
}
#Id
private Long id;
private String name;
private int value;
#Transient
private Status uiStatus = Status.NEW;
public Long getId() {
return this.id;
}
public String getName() {
return this.name;
}
public Status getUiStatus() {
return this.uiStatus;
}
public int getValue() {
return this.value;
}
#PostLoad
public void onLoad() {
this.uiStatus = Status.PERSISTENT;
}
public void setId(Long id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setUiStatus(Status uiStatus) {
this.uiStatus = uiStatus;
}
public void setValue(int value) {
this.value = value;
}
}

How am I misusing generics with commons beanutils?

I have two simple interfaces:
public interface HasId<ID extends Serializable> extends Serializable {
T getId();
}
And
public interface HasLongId extends HasId<Long> {
void setId(Long id);
}
Now, if I have a class:
public class Person implements HasLongId {
private Long id;
private String name;
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
And I instantiate a person, then pass it to BeanUtils I get strange behavior. For example sometimes setting id using BeanUtils works fine and other times, I get an exception because it can't find the "write" method for Id. It seems that during reflection it finds a getter for a Serializable, but not a Long and it does not find a setter for the Serializable. It does not do this consistently, so I suspect that calling person.getClass().getDeclaredMethod("id") will not always return the same Method, but I could be wrong about that.
Anyway, this inconsistent behavior is really maddening because, for example, it will work in Eclipse, but not in Maven, or it will work for a long time and then with some unrelated change somewhere else it will stop working.
Clearly I don't understand generics well enough to understand what is happening, but can anyone explain it to me and also explain how to work around it?
The version of Apache Commons BeanUtils I have used was not Java 5 aware, so it didn't know about Generics, bridge methods, and so on. I believe that's the problem, which version of BeanUtils are you using? and is it Java 5+ aware?
I don't care much for this design - I don't like interfaces merely for getters and setters.
I also wouldn't have that interface extend Serializable; single responsibility is the best advice here.
But I would try it like this:
public interface Identifiable<T extends Serializable> {
T getId();
void setId(T newId);
}
public class Person implements Identifiable<Long> {
private Long id;
public Long getId() { return this.id; }
public void setId(Long id) { this.id = id; }
}

Categories