Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add manually publishing cascade events in implementation of DAOs instead of using EntityListeners #3342

Merged
merged 1 commit into from
Jan 12, 2017

Conversation

sleshchenko
Copy link
Member

@sleshchenko sleshchenko commented Dec 9, 2016

What does this PR do?

Add:

  • rethrowing original exception while cascade operation
  • manually publishing cascade events in implementation of DAOs instead of using EntityListeners.
  • flushing of data by EntityManager#flush to produce consistency exception in right place.
  • CascadeEventLister that is able to throw any of Exception. If listener throws exception then all data changes should be canceled.
  • base events(PersistEvent, RemoveEvent, UpdateEvent). CascadeEventService throws only right exceptions for each use case. When thrown by listener exception should not be thrown by contract of this operation, then it will be wrapped into ServerException.

What issues does this PR fix or reference?

#3399

Previous behavior

Post[Persist|Remove|Update] events are thrown EntityListener, and it is not allowed to change(store new, remove or update existing) any objects on these events.
User is not able to see original exception while cascade removing.

New behavior

New approach allows us to perform any operations on post events or rollback transaction if is fails.
So post events must be thrown by implementations of DAOs. It allows to perform any operation on event and rollback transaction if one of subscriber fails.
To fails original operation event subscriber should extend CascadeEventSubscriber

@sleshchenko sleshchenko force-pushed the cascadeEvents branch 3 times, most recently from 31bdcd1 to 7aaeb81 Compare December 12, 2016 16:08
@sleshchenko sleshchenko changed the title [WIP] Replace manually publishing cascade operation instead of using EntityListeners [WIP] Add manually publishing cascade events in implementation of DAOs instead of using EntityListeners Dec 12, 2016
@sleshchenko sleshchenko force-pushed the cascadeEvents branch 2 times, most recently from f186ffa to 95c0cd1 Compare December 13, 2016 13:55
@sleshchenko sleshchenko changed the title [WIP] Add manually publishing cascade events in implementation of DAOs instead of using EntityListeners Add manually publishing cascade events in implementation of DAOs instead of using EntityListeners Dec 13, 2016
return user;

final UserImpl user = manager.find(UserImpl.class, id);
if (user != null) {
Copy link
Contributor

@voievodin voievodin Dec 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd change it to

if (user == null) {
    return Optional.empty();
}
eventService.publish(new BeforeUserRemovedEvent(user));
manager.remove(user);
return Optional.of(user);

as Optional.ofNullable(user) causes another null check

Copy link
Contributor

@voievodin voievodin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach won't propagate the original exception

public class RemovalContext {
private Exception cause;
public class CascadeContext {
private ApiException cause;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me, REST-api oriented exception looks a bit strange here.

Copy link
Member Author

@sleshchenko sleshchenko Dec 22, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same as throwing REST-api oriented exception by Dao. But we do it. :) And we save original REST-api oriented exception that is thrown by listener for rethrowing

@@ -159,7 +161,9 @@ protected FactoryImpl doUpdate(FactoryImpl update) throws NotFoundException {
if (update.getWorkspace() != null) {
update.getWorkspace().getProjects().forEach(ProjectConfigImpl::prePersistAttributes);
}
return manager.merge(update);
FactoryImpl merged = manager.merge(update);
manager.flush();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is those changes are necessary if we didn't publish any events here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because this operation can be performed by listener. And then integrity exception will be catched in wrong place

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can hardly imagine the listener which will create factory in some case :)) But for purposes of uniformity it's ok.

* <p>If the method throws an exception it will be set to context
* to break event publishing and rethrow exception.
* Original exception can be rethrown to publisher
* or it can be wrapped in {@link SecurityException} instance.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SecurityException ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oooops 😄

@sleshchenko sleshchenko force-pushed the cascadeEvents branch 8 times, most recently from 2076f6d to 8d6e87d Compare December 27, 2016 15:47
@sleshchenko sleshchenko force-pushed the cascadeEvents branch 2 times, most recently from 064ed10 to f0bd904 Compare January 5, 2017 08:59
@sleshchenko sleshchenko force-pushed the cascadeEvents branch 3 times, most recently from c77e373 to 77f1da4 Compare January 10, 2017 14:47
@codenvy-ci
Copy link

@sleshchenko sleshchenko force-pushed the cascadeEvents branch 2 times, most recently from d9bf21c to 2200464 Compare January 12, 2017 13:53
@sleshchenko sleshchenko added this to the 5.1.0 milestone Jan 12, 2017
@sleshchenko sleshchenko force-pushed the cascadeEvents branch 4 times, most recently from a61907b to 2289e59 Compare January 12, 2017 15:15
…ration as cascade.

Also contains following changes:
- Fixes rethrowing original exception while cascade operation.
- Add manually publishing cascade events in implementation of DAOs instead of using EntityListeners.
- Add flushing of data by EntityManager#flush to produce consistency exception in right place.
- Add CascadeEventLister that is able to throw any of Exception. If listener throws exception then all data changes should be canceled.
- Add base events(PersistEvent, RemoveEvent, UpdateEvent). CascadeEventService throws only right exceptions for each use case. When thrown by listener exception should not be thrown by contract of this operation, then it will be wrapped into ServerException.
@sleshchenko sleshchenko merged commit 0675a62 into eclipse-che:master Jan 12, 2017
@sleshchenko sleshchenko deleted the cascadeEvents branch January 12, 2017 16:06
@codenvy-ci
Copy link

@JamesDrummond JamesDrummond mentioned this pull request Jan 31, 2017
9 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants