Approve modification on entity before publish - postgresql

I am trying to create a system that requires an admin to approve a modification to an entity before being published. This system is a REST API with authentication/authorization already working, so that part is not important. Let's assume we have a model depicting an article, with a title and a body. A normal user is allowed to modify all the fields, but before the article is published, it must be approved by an admin. But while the article is in ``approval mode'', the old version of the article must be accessible by the REST API so to at least have a version that works (and the API does not return a 404).
The requirements are:
I am using Spring Data and PostgreSQL so the one that gives me less headaches while integrating it is the one I am going with
The less tinkering with weird checks, the better
If possible, it should be modifiable to be used with other entities
If possible, I would like to keep the old versions and who modified them. Non essential but would be nice
I have two different ideas, but I am not sure which one is the best one:
Create an abstract parent class, and then extend it with an approved and a non-approved version. Then, when the modification is approved the entity is transformed into an approved one and the API will return the new version:
public abstract class Article {}
public class ApprovedArticle extends Article {}
public class ModifiedArticle extends Article {}
Create a separate table where the modified entities are stored, and restrict the view to be admin only. In this case I would isolate the two types and make it easier when fetching info. But I am losing the ``history'' this way and I need to fetch from two different locations.
Simple boolean flag: this is my last resort, and I would love to avoid it!
Is there a better way or should I use one of the outlined examples?
Thanks!

Look into spring Auditing.
https://www.baeldung.com/database-auditing-jpa
So there is an idea:
for each table you have a history table, each history table has REVTYPE( “0” for adding, “1” for updating, “2” for removing an entity) and REV(change number) columns.
Besides these, you need an extra table named REVINFO will be generated by default, to have user details you need to extend default DefaultRevisionEntity class.
#Entity
#RevisionEntity(YOURRevisionListener.class)
#Table(name = "your_audit_info")
#AttributeOverrides(
{#AttributeOverride(name = "timestamp", column = #Column(name = "REVTSTMP")),
#AttributeOverride(name = "id", column = #Column(name = "REV"))})
public class AuditInfo extends DefaultRevisionEntity
{
private static final long serialVersionUID = 8458400378132903089L;
#Column(name = "UpdateUser", nullable = false)
private String userName;
public String getUserName()
{
return userName;
}
public void setUserName(
final String userName)
{
this.userName = userName;
}
}
with audit set up, you get user details if the change approved by admin then compare revisions number when the operation started and operation approved to avoid overwriting by others.
#PrePersist
public void onPrePersist() {
audit("INSERT");
}
#PreUpdate
public void onPreUpdate() {
audit("UPDATE");
}
#PreRemove
public void onPreRemove() {
audit("DELETE");
}
I know it is a very high-level approach, but it can work in your case

Related

How to deal with deleted event classes in event sourcing

I am trying to implement a pure event sourced service to see where I will get problems. Now I found a problem that I can not solve so far, so I would like to open a discussion about it.
Given the following aggregate:
class User
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public void Apply(UserNameChangedEvent domainEvent)
{
Name = domainEvent.NewName;
}
public void Apply(UserCreatedEvent domainEvent)
{
Name = domainEvent.Name;
Id = domainEvent.Id;
}
}
and those Domain Events
class UserCreatedEvent
{
public string NewName { get; }
public Guid Id { get; }
public UserCreatedEvent(string newName, Guid id)
{
NewName = newName;
Id = id;
}
}
class UserNameChangedEvent
{
public string NewName { get; }
public UserNameChangedEvent(string newName)
{
NewName = newName;
}
}
Lets say I create a user and change its name to "Peter" afterwards, then I have a UserCretedEvent and a UserChangedNameEvent persisted in my EventStore. Now the business says that changing a name is no longer possible and therefore I would remove the class UserChangedNameEvent and the function that handles it. But now I have the problem that I can not recreate the aggregate in its correct state, which would be with the name "Peter".
Of course I could start hacking around and mark the function and class as deprecated, so I could keep using it, but I might end up with a lot of event classes afterwards and this will be a nightmare to keep track of. I also heard you might create a new event that persists the change in the domain, but that also seems very hacky to me and not a very good style, as this is no domain event in my point of view.
So the question is, how do I deal the best with changes like this?
edit: just to clarify: I do not want to delete any event, just the class and the function where I use it, as the requirement is different now.
THE resource for questions related to changes in event schemas is Versioning in an Event Sourced System, by Greg Young.
So the question is, how do I deal the best with changes like this?
It depends on the real problem that you are trying to solve.
If the requirement is that users aren't allowed to change their names in the future, then you take away the logic in the domain model that creates new UserNameChangedEvents, but leave behind the correct processing where the events do appear.
If the requirement is that changes to user names should be ignored, then you also take the Apply(UserNameChanged) handler and turn it into a NoOp, just as you would for any other unrecognized event.
If the requirement is that information about name changes should be destroyed, then you migrate your event store to a new schema, that no longer includes the UserNameChanged event.
It may help to think through how you would solve the problem if you were storing your state in an RDBMS: is it enough to ignore the User Name column? do you need to delete the column? Do you need to (somehow) restore value in a column to a previously written value?
Knowing the problem in a traditional database that is analogous to the problem you want to solve in the event store should help identify the appropriate solution.
Also: pay attention to whether or not your domain model is the system of record for the data that needs changed, or if instead you are caching a representation of information published by a different authority.
Events captured facts about the system. If User name was changed at some point, it is a fact. Future business rule changes cannot affect past facts.
So you should not remove UserNameChanged events, and all associated handlers, events are there, and you should not rewrite past history.
In CQRS app, events are generated by command handlers. So this is a place where you specify business requirements. "Now the business says that changing a name is no longer possible" means that ChangeName command is no longer available: you can simply remove it, or just throw an error saying that you cannot change names anymore.

GWT Bean validation does not return all constraint violations in compiled mode

I am experiencing different behavior for client side bean validation when running in gwt development mode than in compiled mode. I have been trying to debug and resolve this issue for hours (days actually) but, although further still did not find the root cause and am currently stuck. Hence my request for help.
In general I have been following the approach advocated here http://www.gwtproject.org/doc/latest/DevGuideValidation.html
and was further more inspired by various articles and questions on StackOverlow. So I have the user enter an object on the client. Than I validate it client side via a call to the validator that has been created by the validator factory.
The problem I am experiencing is that when more than one constraint is validated (i.e. the user enters 2 or more "mistakes") the validator does not (always) return all constraint violations when running in compiled mode, while it does return them all when running in gwt development mode.
The object I try to validate is of the class EnvyMonUser
#Entity
public class EnvyMonUser implements Serializable, Obj<EnvyMonUser> {
private static final long serialVersionUID = 3L;
private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*#"
+ "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
#Id
private Long id;
#NotNull(message = "company must be selected")
#Index
private Key<Company> companyKey;
#Index
private String googleUserId;
#NotNull(message = "email address must be set")
#Pattern(regexp = EMAIL_PATTERN, message = "invalid email address")
#Index
private String email;
#NotNull(message = "name must be set")
#Size(min = 3, message = "must have a name of minimal 3 characters")
#Index
private String nickName;
#NotNull(message = "location must be selected")
#Index
private Key<SampleLocation> sampleLocationKey;
#NotNull(message = "result must be set")
#Index
private Long value;
...
Where Company and SampleLocation are two other classes. (The annotations #Entity, #Index, #Id and the class Key are of Objectify. I use the same entity class(es) client and server (gae) side. )
Once the user has entered an EnvyMonUser object I validate it via a validator, i.e.
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
...
EnvyMonUser obj = getView().getEditorDriver().flush();
Set<ConstraintViolation<O>> validate = validator.validate(obj);
where my validation factory is
public final class AppValidatorFactory extends AbstractGwtValidatorFactory {
#GwtValidation(value = { MonitorType.class, Measurement.class,
ProgramMeasurement.class, EnvyMonUser.class, Company.class,
SampleLocation.class })
public interface GwtValidator extends Validator {
}
#Override
public AbstractGwtValidator createValidator() {
return GWT.create(GwtValidator.class);
}
}
Am I doing something wrong?
Desperate as I was I tried removing and adding several fields but have not found any logical pattern. Depending on which fields I leave out and also on which of the fields are filled correctly by the user the (missing) constraint(s) in compiled mode change.
I have already tried multiple routes but no success so far. For example at some point I thought this was caused by using objectify. However when I remove sampleLocationKey member it works perfectly fine for companyKey member. I also tried removing the objectify attributes but this also doesn't seem to make a difference.
An interesting thing I did observe (by accident) is that when I remove (comment) some of the members from the hashCode and equals methods the behavior changes. Not sure why this is. Maybe it has something to do with how the validator generator is implemented.
Does anyone have any clue?
Also a pointer in the right direction is appreciated. Does someone for example know where I can find the validator that is generated. Or the sources of the validator generator?
Some versions of libraries I use:
gwt 2.6.0
hibernate-validator-4.1.0.Final.jar
hibernate-validator-4.1.0.Final-sources.jar
slf4j-api-1.6.1.jar
slf4j-log4j12-1.6.1.jar
log4j-1.2.16.jar
objectify 4.0.1
Turns out the problem was not in my code but a bug in gwt sources for com.google.gwt.validation.client.impl.ConstraintViolationImpl . See https://groups.google.com/forum/#!topic/Google-Web-Toolkit/xRVGnMWfttc for a full description of the problem and solution.
I had the same issue. The validations were working fine on dev mode and all the error messages were showing up on the UI but in the prod mode we could see only one error message at one time. Late on when debugged and found that my DTO has implemented equals and hashcode method and that what causing this issue. The moment is removed these two implementations from my DTO every things worked fine after that.
I am using GWT 2.6.1.

Entity Framework not updating navigation proprties with automatic change tracking disabled

I have one unitOfWork in my Domain Logic that retrieves tens of thousands of XML nodes, creates disconnected entities called retreivedBooks from the XML and updates Book entities in the database based on the retreivedBooks. For this particular unitOfWork's dbContext in my application, I have disabled change tracking due to very bad performance when there are lots of entities in the database. This has improved performance - great.
However it is no longer updating navigation properties. Here is a made up example to demonstrate the problem:
public class Book
{
public string Title;
public string Author;
public virtual List<Page> Pages;
}
_unitOfWork.Context.Configuration.AutoDetectChangesEnabled = false;
_unitOfWork.Context.Configuration.ValidateOnSaveEnabled = false;
foreach(Book retreivedBook in retreivedBooks )
{
Book existingBook= _unitOfWork.BookRepository.SingleOrDefault(b=>b.Id=retreivedBook.Id);
if(book!=null)
{
existingBook.Title=retreivedBook.Title;
existingBook.Author=retreivedBook.Author;
existingBook.Pages=retreivedBook.Pages;
_unitOfWork.Context.Entry(existingBook).State = EntityState.Modified;
}
}
_unitOfWork.Save();
In the example above, the Title and Author properties of books in the database get updated correctly, but the list of Pages does not.
By the way, I don't check for existing Pages based on retrieved Pages. We can assume that pages are always different every time so the book.Pages property will be replaced on every update.
Why does the pages property does not get updated in the database?
Due to the way Entity Framework works when you set _unitOfWork.Context.Configuration.AutoDetectChangesEnabled = false; it's much likely for the child entities to not get updated. In order to fix it should be enough to change the status to true before saving changes. In other words try this in your code:
...
_unitOfWork.Context.Entry(existingBook).State = EntityState.Modified;
}
}
_unitOfWork.Context.Configuration.AutoDetectChangesEnabled = true;
_unitOfWork.Save();

EntityFramework with Repository Pattern and no Database

I have a web api project that I'm building on an N-Tier system. Without causing too many changes to the overall system, I will not be touching the data server that has access to the database. Instead, I'm using .NET remoting to create a tcp channel that will allow me to send requests to the data server, which will then query the database and send back a response object.
On my application, I would like to use entity framework to create my datacontexts (unit of work), then create a repository pattern that interfaces with those contexts, which will be called by the web api project that I created.
However, I'm having problems with entity framework as it requires me to have a connection with the database. Is there anyway I can create a full entity framework project without any sqlconnections to the database? I just need dbcontexts, which I will be mapping my response objects and I figure that EF would do what I needed (ie help with design, and team collabs, and provide a nice graphical designer); but it throws an error insisting that I need a connection string.
I've been searching high and low for tutorials where a database is not needed, nor any sql connection string (this means no localdb either).
Okay as promised, I have 3 solutions for this. I personally went with #3.
Note: Whenever there is a repository pattern present, and "datacontext" is used, this is interpreted as your UnitOfWork.
Solution 1: Create singletons to represent your datacontext.
http://www.breezejs.com/samples/nodb
I found this idea after going to BreezeJS.com's website and checked out their samples. They have a sample called NoDb, which allows them to create a singleton, which can create an item and a list of items, and a method to populate the datacontext. You create singletons that would lock a space in memory to prevent any kind of thread conflicts. Here is a tid bit of the code:
//generates singleton
public class TodoContext
{
static TodoContext{ }
private TodoContext() { }
public static TodoContext Instance
{
get
{
if (!__instance._initialized)
{
__instance.PopulateWithSampleData();
__instance._initialized = true;
}
return __instance;
}
}
public void PopulateWithSampleData()
{
var newList = new TodoItem { Title = "Before work"};
AddTodoList(newList);
var listId = newList.TodoListId;
var newItem = new TodoItem {
TodoListId = listId, Title = "Make coffee", IsDone = false };
AddTodoItem(newItem);
newItem = new TodoItem {
TodoListId = listId, Title = "Turn heater off", IsDone = false };
AddTodoItem(newItem);
}
//SaveChanges(), SaveTodoList(), AddTodoItem, etc.
{ ... }
private static readonly Object __lock = new Object();
private static readonly TodoContext __instance = new TodoContext();
private bool _initialized;
private readonly List<TodoItem> _todoLists = new List<TodoItem>();
private readonly List<KeyMapping> _keyMappings = new List<KeyMapping>();
}
There's a repository included which directs how to save the context and what needs to be done before the context is saved. It also allows the list of items to be queryable.
Problem I had with this:
I felt like there was higher maintenance when creating new datacontexts. If I have StateContext, CityContext, CountryContext, the overhead of creating them would be too great. I'd have problems trying to wrap my head around relating them to each other as well. Plus I'm not too sure how many people out there who agree with using singletons. I've read articles that we should avoid singletons at all costs. I'm more concerns about anyone who'd be reading this much code.
Solution 2: Override the Seed() for DropCreateDatabaseAlways
http://www.itorian.com/2012/10/entity-frameworks-database-seed-method.html
For this trick, you have to create a class called SampleDatastoreInitializer that inherits from System.Data.Entity.DropCreateDatabaseAlways where T is the datacontext, which has a reference to a collection of your POCO model.
public class State
{
[Key()]
public string Abbr{ get; set; }
public string Name{ get; set; }
}
public class StateContext : DbContext
{
public virtual IDbSet<State> States { get; set; }
}
public class SampleDatastoreInitializer : DropCreateDatabaseAlways<StateContext>
{
protected override void Seed (StateContext context)
{
var states = new List<State>
{
new State { Abbr = "NY", Name = "New York" },
new State { Abbr = "CA", Name = "California" },
new State { Abbr = "AL", Name = "Alabama" },
new State { Abbr = "Tx", Name = "Texas" },
};
states.ForEach(s => context.States.Add(s));
context.SaveChanges();
}
}
This will actually embed the data in a cache, the DropCreateDatabaseAlways means that it will drop the cache and recreate it no matter what. If you use some other means of IDatabaseInitializer, and your model has a unique key, you might get an exception error, where you run it the first time, it works, but run it again and again, it will fail because you're violating the constraints of primary key (since you're adding duplicate rows).
Problem I had with this:
This seems like it should only be used to provide sample data when you're testing the application, not for production level. Plus I'd have to continously create a new initializer for each context, which plays a similar problem noted in solution 1 of maintainability. There is nothing automatic happening here. But if you want a way to inject sample code without hooking up to a database, this is a great solution.
Solution 3: Entity framework with Repository (In-memory persistence)
I got this solution from this website:
http://www.roelvanlisdonk.nl/?p=2827
He first sets up an edmx file, using EF5 and the code generator templates for EF5 dbcontexts you can get from VS extension libraries.
He first uses the edmx to create the contexts and changes the tt templates to bind to the repository class he made, so that the repository will keep track of the datacontext, and provide the options of querying and accessing the data through the repository; in his website though he calls the repository as MemoryPersistenceDbSet.
The templates he modified will be used to create datacontexts that will bind to an interface (IEntity) shared by all. Doing it this way is nice because you are establishing a Dependency Injection, so that you can add any entity you want through the T4 templates, and there'd be no complaints.
Advantage of this solution:
Wrapping up the edmx in repository pattern allows you to leverage the n-tier architecture, so that any changes done to the backend won't affect the front end, and allows you to separate the interface between the front end and backend so there are no coupled dependencies. So maybe later on, I can replace my edmx with petapoco, or massive, or some other ORM, or switch from in-memory persistence to fetching data from a database.
I followed everything exactly as explained. I made one modification though:
In the t4 template for .Context.tt, where DbSetInConstructor is added, I had the code written like this:
public string DbSetInConstructor(EntitySet entitySet)
{
return string.Format(
CultureInfo.InvariantCulture,
“this.{1} = new BaseRepository();”,
_typeMapper.GetTypeName(entitySet.ElementType), entitySet);
}
Because in my case I had the entityset = Persons and entityname = Person. So there’d be discrepancy. But this should cover all bases.
Final step:
So whether you picked solution 1, 2, or 3. You have a method to automatically populate your application. In these cases, the stubs are embedded in the code. In my case, what I've done is have my web server (containing my front end app), contact my data server, have the data server query the database. The data server will receive a dataset, serialize it, and pass it back to the web server. The web server will take that dataset, deserialize it, and auto-map to an object collection (list, or enumberable, or objectcollection, etc).
I would post the solutions more fully but there's way too much detail between all 3 of these solutions. Hopefully these solutions would point anyone in the right direction.
Dependency Injection
If anyone wants some information about how to allow DI to api controllers, Peter Provost provides a very useful blog that explains how to do it. He does a very very good job.
http://www.peterprovost.org/blog/2012/06/19/adding-ninject-to-web-api/
few more helpful links of repository wrapping up edmx:
http://blogs.msdn.com/b/wriju/archive/2013/08/23/using-repository-pattern-in-entity-framework.aspx
http://www.codeproject.com/Articles/688929/Repository-Pattern-and-Unit-of

Spring Data JPA Auditing never getting called at runtime

I'm presently struggling with getting Spring Data JPA Auditing to work, it is presently not setting the fields and doesn't seem to be getting called in any way when working with Entities. In particular any insight into how it hooks into the standard flow of persisting Entities would be helpful.
I'm presently using Spring Data JPA 1.5.0.M1 with Spring 3.2.6 and the basic configuration for the auditing piece is:
#Configuration
#EnableJpaAuditing(auditorAwareRef = "auditorAware")
#EnableJpaRepositories(basePackages = "org.myproject.dao")
#EnableTransactionManagement
public class JpaConfig {
...}
the relevant entity at the moment is marked up with the annotations and the interface while trying to work this out (the annotations would be preferred). I realize this should not be done but I copied and pasted for the moment.
#Entity
public class AutoDraft implements Auditable<Long, Long> {
#SequenceGenerator(name="seq_auto_draft", sequenceName="SEQ_AUTO_DRAFT")
#GeneratedValue(strategy=GenerationType.SEQUENCE,generator="seq_auto_draft")
#Id
private Long id;
#CreatedDate
#Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime createdDate;
#LastModifiedDate
#Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime lastModifiedDate;
In the logs the relevant beans are being set up and I can catch the AuditingHandler being properly configured within the AuditingEntityListener on startup, but nothing seems to be getting triggered at runtime, nor are there any audit related logging messages associated with specific entities or repositories. My attention is presently drawn by the AuditingBeanFactoryPostProcessor, but I've already spent too long on this so could use any assistance.
I know this is an old question, but I hit the same problem and a comment helped me resolve it. So I thought I would make it clearer if anyone falls on this question again.
The documentation for Spring Data is a bit misleading in that it implies that you can enable auditing simply by annotating a #Configuration class with #EnableJpaAuditing.
However, the part I found unclear is that you still need to modify the orm.xml file (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#auditing):
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="….data.jpa.domain.support.AuditingEntityListener" />
</entity-listeners>
</persistence-unit-defaults>
However, if you are using a pure annotation based solution, you may not have an orm.xml file. As indicated by Matt Whipple in a comment, you have to add the #EntityListeners annotation to you entity classes so that the JPA persistence library calks the Spring auditing class when persisting the objects (which in turn deals with the auditing).
So a complete example could be something like:
#Configuration
#EnableJpaAuditing
#PropertySource({ "application.properties" })
public class AppConfig {
/**
* Stubbed method for the auditor as the app does not concern itself with auditing any User fields
* Consequently, return null for the current auditor
* #return
*/
#Bean
public AuditorAware<User> auditorProvider(){
return new AuditorAware<User>() {
#Override
public User getCurrentAuditor() {
return <User object that is Logged In>;
}
};
}
}
Then on your entity:
#Entity
#EntityListeners(AuditingEntityListener.class)
public class Log {
#Id
#GeneratedValue
private long id;
#CreatedDate
#Column(nullable=false)
private Date createdOn;
// bunch of other audit fields (and other fields)
...
...
}
It seems like you forgot to configure AuditingEntityListener in the orm.xml (which is still neccessary). Add this lines to your orm.xml:
<persistence-unit-metadata>
<persistence-unit-defaults>
<entity-listeners>
<entity-listener class="….data.jpa.domain.support.AuditingEntityListener" />
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>
see: Spring data jpa documentation: Auditing.