A simple case. A user has many photos. When a user gets deleted, all of his/her photos should be deleted too (rule of cascades).
I want however to be able to execute some custom code right before every photo is deleted.
Unfortunately, when deleting users, all I am doing is call userDAO.deleteUser(userID), so no specific action is taken on photos (they are deleted by Hibernate itself)
Also, I don't really want the userDAO to have the knowledge that a user has photos, so this custom code should be inserted somewhere else.
I wish it were as simple as giving an OnDelete callback when I annote my entity classes, but I haven't seen any such specification in the Hibernate docs
Then I Think you need to apply SPring AOP on the function which deletes user.
for example:
public void deleteUser(User user){
Session session = sessionFactory.getcurrentSection();
//delete the object
}
What you need to do is to apply #Around advice
#Pointcut("execution(* com.vanilla.dao.*.*(..))")
public void deleteUserMethods() { }
#Around("deleteUserMethods()")
public Object profile(ProceedingJoinPoint pjp) throws Throwable {
Object output = pjp.proceed();
///perform any operations on an pjp and its parameters.
return output;
}
I recommend you to see this example:
http://veerasundar.com/blog/2010/01/spring-aop-example-profiling-method-execution-time-tutorial/
and Spring documentation will be also very helpful:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-schema
Related
I want to publish an event if and only if there were changes to the DB. I'm running under #Transaction is Spring context and I come up with this check:
Session session = entityManager.unwrap(Session.class);
session.isDirty();
That seems to fail for new (Transient) objects:
#Transactional
public Entity save(Entity newEntity) {
Entity entity = entityRepository.save(newEntity);
Session session = entityManager.unwrap(Session.class);
session.isDirty(); // <-- returns `false` ):
return entity;
}
Based on the answer here https://stackoverflow.com/a/5268617/672689 I would expect it to work and return true.
What am I missing?
UPDATE
Considering #fladdimir answer, although this function is called in a transaction context, I did add the #Transactional (from org.springframework.transaction.annotation) on the function. but I still encounter the same behaviour. The isDirty is returning false.
Moreover, as expected, the new entity doesn't shows on the DB while the program is hold on breakpoint at the line of the session.isDirty().
UPDATE_2
I also tried to change the session flush modes before calling the repo save, also without any effect:
session.setFlushMode(FlushModeType.COMMIT);
session.setHibernateFlushMode(FlushMode.MANUAL);
First of all, Session.isDirty() has a different meaning than what I understood. It tells if the current session is holding in memory queries which still haven't been sent to the DB. While I thought it tells if the transaction have changing queries. When saving a new entity, even in transaction, the insert query must be sent to the DB in order to get the new entity id, therefore the isDirty() will always be false after it.
So I ended up creating a class to extend SessionImpl and hold the change status for the session, updating it on persist and merge calls (the functions hibernate is using)
So this is the class I wrote:
import org.hibernate.HibernateException;
import org.hibernate.internal.SessionCreationOptions;
import org.hibernate.internal.SessionFactoryImpl;
import org.hibernate.internal.SessionImpl;
public class CustomSession extends SessionImpl {
private boolean changed;
public CustomSession(SessionFactoryImpl factory, SessionCreationOptions options) {
super(factory, options);
changed = false;
}
#Override
public void persist(Object object) throws HibernateException {
super.persist(object);
changed = true;
}
#Override
public void flush() throws HibernateException {
changed = changed || isDirty();
super.flush();
}
public boolean isChanged() {
return changed || isDirty();
}
}
In order to use it I had to:
extend SessionFactoryImpl.SessionBuilderImpl to override the openSession function and return my CustomSession
extend SessionFactoryImpl to override the withOptions function to return the extended SessionFactoryImpl.SessionBuilderImpl
extend AbstractDelegatingSessionFactoryBuilderImplementor to override the build function to return the extended SessionFactoryImpl
implement SessionFactoryBuilderFactory to implement getSessionFactoryBuilder to return the extended AbstractDelegatingSessionFactoryBuilderImplementor
add org.hibernate.boot.spi.SessionFactoryBuilderFactory file under META-INF/services with value of my SessionFactoryBuilderFactory implementation full class name (for the spring to be aware of it).
UPDATE
There was a bug with capturing the "merge" calls (as tremendous7 comment), so I end up capturing the isDirty state before any flush, and also checking it once more when checking isChanged()
The following is a different way you might be able to leverage to track dirtiness.
Though architecturally different than your sample code, it may be more to the point of your actual goal (I want to publish an event if and only if there were changes to the DB).
Maybe you could use an Interceptor listener to let the entity manager do the heavy lifting and just TELL you what's dirty. Then you only have to react to it, instead of prod it to sort out what's dirty in the first place.
Take a look at this article: https://www.baeldung.com/hibernate-entity-lifecycle
It has a lot of test cases that basically check for dirtiness of objects being saved in various contexts and then it relies on a piece of code called the DirtyDataInspector that effectively listens to any items that are flagged dirty on flush and then just remembers them (i.e. keeps them in a list) so the unit test cases can assert that the things that SHOULD have been dirty were actually flushed as dirty.
The dirty data inspector code is on their github. Here's the direct link for ease of access.
Here is the code where the interceptor is applied to the factory so it can be effective. You might need to write this up in your injection framework accordingly.
The code for the Interceptor it is based on has a TON of lifecycle methods you can probably exploit to get the perfect behavior for "do this if there was actually a dirty save that occured".
You can see the full docs of it here.
We do not know your complete setup, but as #Christian Beikov suggested in the comment, is it possible that the insertion was already flushed before you call isDirty()?
This would happen when you called repository.save(newEntity) without a running transaction, since the SimpleJpaRepository's save method is annotated itself with #Transactional:
#Transactional
#Override
public <S extends T> S save(S entity) {
...
}
This will wrap the call in a new transaction if none is already active, and flush the insertion to the DB at the end of the transaction just before the method returns.
You might choose to annotate the method where you call save and isDirty with #Transactional, so that the transaction is created when your method is called, and propagated to the repository call. This way the transaction would not be committed when the save returns, and the session would still be dirty.
(edit, just for completeness: in case of using an identity ID generation strategy, the insertion of newly created entity is flushed during a repository's save call to generate the ID, before the running transaction is committed)
I'm trying to understand SRP principle and most of the sof threads didn't answer this particular query I'm having,
Use-case
I'm trying to send an email to the user's email address to verify himself whenever he tries to register/create an user-account in a website.
Without SRP
class UserRegistrationRequest {
String name;
String emailId;
}
class UserService {
Email email;
boolean registerUser(UserRegistrationRequest req) {
//store req data in database
sendVerificationEmail(req);
return true;
}
//Assume UserService class also has other CRUD operation methods()
void sendVerificationEmail(UserRegistrationRequest req) {
email.setToAddress(req.getEmailId());
email.setContent("Hey User, this is your OTP + Random.newRandom(100000));
email.send();
}
}
The above class 'UserService' violates SRP rule as we are clubbing 'UserService' CRUD operations and triggering verification email code into 1 single class.
Hence I do,
With SRP
class UserService {
EmailService emailService;
boolean registerUser(UserRegistrationRequest req) {
//store req data in database
sendVerificationEmail(req);
return true;
}
//Assume UserService class also has other CRUD operation methods()
void sendVerificationEmail(UserRegistrationRequest req) {
emailService.sendVerificationEmail(req);
}
}
class EmailService {
void sendVerificationEmail(UserRegistrationRequest req) {
email.setToAddress(req.getEmailId());
email.setContent("Hey User, this is your OTP + Random.newRandom(100000));
email.send();
}
But even 'with SRP', UserService as a class again holds a behaviour of sendVerificationEmail(), though this time it didn't hold the entire logic of sending the email.
Isn't it again we are clubbing crud operation's and sendVerificationEmail() into 1 single class even after applying SRP?
Your feeling is absolutely right. I agree with you.
I think your problem starts with your naming style, since you seem to be quite aware what SRP means. Class names like '...Service' or '...Manager' carry a very vague meaning or semantics. They describe a more generalized context or concept. In other words a '...Manager' class invites you to put everything inside and it still feels right, because it's a manager.
When you get more concrete by trying to focus on the true concepts of your classes or their responsibilities, you will automatically find bigger names with a stronger meaning or semantics. This will really help you to split up classes and to identify responsibilities.
SRP:
There should never be more than one reason to change a certain module.
You could start with renaming the UserService to UserDatabaseContext. Now this would automatically force you to only put database related operations into this class (e.g. CRUD operations).
You even can get more specific here. What are you doing with a database? You read from and write to it. Obviously two responsibilities, which means two classes: one for read operations and another responsible for write operations. This could be very general classes that can just read or write anything. Let's call them DatabaseReader and DatabaseWriter and since we are trying to decouple everything we are going to use interfaces everywhere. This way we get the two IDatabaseReader and IDatabaseWriter interfaces. This types are very low level since they know the database (Microsoft SQL or MySql), how to connect to it and the exact language to query it (using e.g. SQL or MySql):
// Knows how to connect to the database
interface IDatabaseWriter {
void create(Query query);
void insert(Query query);
...
}
// Knows how to connect to the database
interface IDatabaseReader {
QueryResult readTable(string tableName);
QueryResult read(Query query);
...
}
On top, you could implement a more specialized layer of read and write operations, e.g. user related data. We would introduce a IUserDatabaseReader and a IUserDatabaseWriter interface. This interfaces don't know how to connect to the database or what type of database is used. This interfaces only know what information is required to read or write user details (e.g. using a Query object that is transformed into a real query by the low level IDatabaseReader or IDatabaseWriter):
// Knows only about structure of the database (e.g. there is a table called 'user')
// Implementation will internally use IDatabaseWriter to access the database
interface IUserDatabaseWriter {
void createUser(User newUser);
void updateUser(User user);
void updateUserEmail(long userKey, Email emailInfo);
void updateUserCredentials(long userKey, Credential userCredentials);
...
}
// Knows only about structure of the database (e.g. there is a table called 'user')
// Implementation will internally use IDatabaseReader to access the database
interface IUserDatabaseReader {
User readUser(long userKey);
User readUser(string userName);
Email readUserEmail(string userName);
Credential readUserCredentials(long userKey);
...
}
We are still not done with the persistence layer. We can introduce another interface IUserProvider. The idea is to decouple the database access from the rest of our application. In other words we consolidate the user related data query operations into this class. So, IUserProvider will be the only type that has direct access to the data layer. It forms the interface to the application's persistence layer:
interface IUserProvider {
User getUser(string userName);
void saveUser(User user);
User createUser(string userName, Email email);
Email getUserEmail(string userName);
}
The implementation of IUserProvider. The only class in the whole application that has direct access to the data layer by referencing IUserDatabaseReader and IUserDatabaseWriter. It wraps reading and writing of data to make data handling more convenient. The responsibility of this type is to provide user data to the application:
class UserProvider {
IUserDatabaseReader userReader;
IUserDatabaseWriter userWriter;
// Constructor
public UserProvider (IUserDatabaseReader userReader,
IUserDatabaseWriter userWriter) {
this.userReader = userReader;
this.userWriter = userWriter;
}
public User getUser(string userName) {
return this.userReader.readUser(username);
}
public void saveUser(User user) {
return this.userWriter.updateUser(user);
}
public User createUser(string userName, Email email) {
User newUser = new User(userName, email);
this.userWriter.createUser(newUser);
return newUser;
}
public Email getUserEmail(string userName) {
return this.userReader.readUserEmail(userName);
}
}
Now that we tackled the database operations we can focus on the authentication process and continue to extract the authentication logic from the UserService by adding a new interface IAuthentication:
interface IAuthentication {
void logIn(User user)
void logOut(User);
void registerUser(UserRegistrationRequest registrationData);
}
The implementation of IAuthentication implements the special authentication procedure:
class EmailAuthentication implements IAuthentication {
EmailService emailService;
IUserProvider userProvider;
// Constructor
public EmailAuthentication (IUserProvider userProvider,
EmailService emailService) {
this.userProvider = userProvider;
this.emailService = emailService;
}
public void logIn(string userName) {
Email userEmail = this.userProvider.getUserEmail(userName);
this.emailService.sendVerificationEmail(userEmail);
}
public void logOut(User user) {
// logout
}
public void registerUser(UserRegistrationRequest registrationData) {
this.userProvider.createNewUser(registrationData.getUserName, registrationData.getEmail());
this.emailService.sendVerificationEmail(registrationData.getEmail());
}
}
To decouple the EmailService from the EmailAuthentication class, we can remove the dependency on UserRegistrationRequest by letting sendVerificationEmail() take an Email` parameter object instead:
class EmailService {
void sendVerificationEmail(Email userEmail) {
email.setToAddress(userEmail.getEmailId());
email.setContent("Hey User, this is your OTP + Random.newRandom(100000));
email.send();
}
Since the authentication is defined by an interface IAuthentication, you can create a new implementation at any time when you decide to use a different procedure (e.g. WindowsAuthentication), but without modifying existing code. This will also work with the IDatabaseReader and IDatabaseWriter once you decide to switch to a different database (e.g. Sqlite). The IUserDatabaseReader and IUserDatabaseWriter implementations will still work without any modification.
With this class design, you now have exactly one reason to modify each existing type:
EmailService when you need to change the implementation (e.g. use
different email API)
IUserDatabaseReader or IUserDatabaseWriter when you want to add additional user related read or write operations (e.g. to handle user role)
provide new implementations of IDatabaseReader or IDatabaseWriter when you want to switch underlying database or you need to modify database access
implementations of IAuthentication when the procedure changes (e.g. using build in OS authentication)
Now everything is cleanly separated. Authentication doesn't mix with CRUD operations. We have an additional layer between application and persistence layer to add flexibility regarding the underlying persistence system. So CRUD operations don't mix with the actual persistence operations.
As a tip: in future you better start with the thinking (design) part first: what must my application do?
handle authentication
handle users
handle a database
handle email
create user responses
show view pages to the user
etc.
As you can see, you can start to implement each step or requirement separately. But this doesn't mean each requirement is realized by exactly one class. As you remember, we split up database access into four responsibilities or classes: read and write to real database (low level), read and write to database abstraction layer, to reflect concrete use cases (high level). Using interfaces adds flexibility and testability to the application.
There is already a great answer to this question by #BionicCode. I just wan't to add a short summary and some of my thoughts on the matter.
The SRP can be a tricky one.
In my experience the granularity of the responsibilities and the number of abstactions that you place in your system will affect it's ease of use and it's size.
You can add a-lot of abstractions and break everything down to very small components. This indeed is something that we should strive for.
Now the question then is: When to stop?
This will depend on:
The size of your application
What parts of it will change more frequently than others
Do you need to compose objects together, or most of the time your modules are independent of one another and you don't reause many objects.
What time do you have
What is the size of your team
A lot of other stuff...
Let's start with how big is the team.
One reason we break our code into separate modules and classes into seprate files is so that we can work in a team and avoid too many merges in our favorite source control system. If you need to change a file that contains a component of your system and someone else needs to change it too, this may get ugly pretty fast. Now if you do separate modules using SRP you get more but smaller modules that most of the time will change independent of one another.
What if the team isn't that big and our modules are not that big too? Do you need to generate more of them?
Here's an example.
Let's say that you have a mobile application that has setings. We may say that containg these settigns in one responsibility and add it to one interface IApplicationSettings to hold all of them.
In the case where we have 30 settings this interface will be huge and that's bad. It also means that we are probably violating the SRP again as this interface will probably hold settings for multiple different categories.
So we decide to apply Interface seggregation principle and SRP and divide the settings to multiple interfaces ISomeCategorySettings, IAnotherCategorySettings etc.
Now let's say that our applications isn't too big (yet) and we have 5 settings. Even if they are from different categories, is it bad to keep these settings in one interface?
I would say that it's fine to have all settigns in one interface as long as it doesn't start to slow us down or start to get ugly (30 or more settigns!).
Is it that bad to construct an email and send it from your service object? This indeed is something that can get ugly pretty quickly, so you better move this responsibility from the service object to an EmailSender fast.
If you have a service object that contains 5 methods, do you realy need to break this into 5 different objects for every operation? If these methods are big, yes. If they small, keeping them in one object it's that big of a problem.
SRP is great, but take granularity into account and choose it wisely based on code size, team size etc.
It's RESTful web app. I am using Hibernate Envers to store historical data. Along with revision number and timestamp, I also need to store other details (for example: IP address and authenticated user). Envers provides multiple ways to have a custom revision entity which is awesome. I am facing problem in setting the custom data on the revision entity.
#RevisionEntity( MyCustomRevisionListener.class )
public class MyCustomRevisionEntity extends DefaultRevisionEntity {
private String userName;
private String ip;
//Accessors
}
public class MyCustomRevisionListener implements RevisionListener {
public void newRevision( Object revisionEntity ) {
MyCustomRevisionEntity customRevisionEntity = ( MyCustomRevisionEntity ) revisionEntity;
//Here I need userName and Ip address passed as arguments somehow, so that I can set them on the revision entity.
}
}
Since newRevision() method does not allow any additional arguments, I can not pass my custom data (like username and ip) to it. How can I do that?
Envers also provides another approach as:
An alternative method to using the org.hibernate.envers.RevisionListener is to instead call the getCurrentRevision( Class revisionEntityClass, boolean persist ) method of the org.hibernate.envers.AuditReader interface to obtain the current revision, and fill it with desired information.
So using the above approach, I'll have to do something like this:
Change my current dao method like:
public void persist(SomeEntity entity) {
...
entityManager.persist(entity);
...
}
to
public void persist(SomeEntity entity, String userName, String ip) {
...
//Do the intended work
entityManager.persist(entity);
//Do the additional work
AuditReader reader = AuditReaderFactory.get(entityManager)
MyCustomRevisionEntity revision = reader.getCurrentRevision(MyCustomRevisionEntity, false);
revision.setUserName(userName);
revision.setIp(ip);
}
I don't feel very comfortable with this approach as keeping audit data seems a cross cutting concern to me. And I obtain the userName and Ip and other data through HTTP request object. So all that data will need to flow down right from entry point of application (controller) to the lowest layer (dao layer).
Is there any other way in which I can achieve this? I am using Spring.
I am imagining something like Spring keeping information about the 'stack' to which a particular method invocation belongs. So that when newRevision() in invoked, I know which particular invocation at the entry point lead to this invocation. And also, I can somehow obtain the arguments passed to first method of the call stack.
One good way to do this would be to leverage a ThreadLocal variable.
As an example, Spring Security has a filter that initializes a thread local variable stored in SecurityContextHolder and then you can access this data from that specific thread simply by doing something like:
SecurityContext ctx = SecurityContextHolder.getSecurityContext();
Authorization authorization = ctx.getAuthorization();
So imagine an additional interceptor that your web framework calls that either adds additional information to the spring security context, perhaps in a custom user details object if using spring security or create your own holder & context object to hold the information the listener needs.
Then it becomes a simple:
public class MyRevisionEntityListener implements RevisionListener {
#Override
public void newRevision(Object revisionEntity) {
// If you use spring security, you could use SpringSecurityContextHolder.
final UserContext userContext = UserContextHolder.getUserContext();
MyRevisionEntity mre = MyRevisionEntity.class.cast( revisionEntity );
mre.setIpAddress( userContext.getIpAddress() );
mre.setUserName( userContext.getUserName() );
}
}
This feels like the cleanest approach to me.
It is worth noting that the other API getCurrentRevision(Session,boolean) was deprecated as of Hibernate 5.2 and is scheduled for removal in 6.0. While an alternative means may be introduced, the intended way to perform this type of logic is using a RevisionListener.
Let's say there is an object TaskList which can be edited and deleted only by its owner. Other users should only by able to take a task and update its status.
The following options come to my mind:
check the ownership and access in the controller of the web application
let the repository return proxy object which throws exception on certain operations, but the controller (or view) would still need to know which actions (in form of links or form fields) should be visible
pass the caller (user) to the method of the domain object, so that the domain object can itself check whether the caller ist allowed or not.
The used technology is Java.
Any other/better ideas?
Interesting articles about security and DDD
Domain Object Security with the Spring framework
Security in Domain-Driven Design
I have accepted my own answer now, because that is what I actually use, but further suggestions are welcome.
I would not encode the ownership/permissions model into the TaskList domain object. That sort of business logic should be external. I also don't like the idea of a proxy object. Although it would certainly work, it would confuse debugging and is, in this case at least, unnecessarily complex. I would also not check it in the controller.
Instead I would create a business logic object which oversees the permissions for TaskList. So the TaskList would have an owner field but you would have something like:
public class TaskListAccessor {
private TaskList taskList;
private User reader;
public void updateStatus(Status status) {
// everyone can do this
taskList.updateStatus(status);
}
/** Return true if delete operation is allowed else false */
public boolean isDeleteAllowed() {
return taskList.getOwner().equals(reader);
}
/** Delete the task. Only owners can do this. Returns true if worked else false */
public boolean delete() {
if (isDeleteAllowed()) {
taskList.delete();
return true;
} else {
return false;
}
}
// ... other accessors with other is*Allowed methods
}
If you need to require that all operations on TaskList objects go through accessors then you could create a factory class which is the only one who creates TaskList using package constructors or something. Maybe the factory is the only one who would use the DAO to look up the TaskList from the data store.
However, if there are too many methods to control in this fashion then a proxy might be easier. In both cases having TaskList be an interface would be recommended, with the implementation class hidden by the proxy or the accessor.
I found it unnecessarily complex to create accessor classes for each protected domain class as suggested by 'Gray'. My solution is probably not perfect, but simple to use and - more important - robust. You cannot forget to use a certain object or to check conditions outside.
public class TaskList {
private SystemUser owner;
private List<Task> tasks = new ArrayList<>();
public TastList(SystemUser owner) {
this.owner = owner;
}
public void Add(Task task) {
Guard.allowFor(owner);
tasks.add(task);
}
}
The Guard knows the current user (from a thread local for example) and compares it to the owner passed as parameter to allowFor(owner). If access is denied a security exception will be thrown.
That is simple, robust and even easy to maintain since only the guard has to be changed if the underlying authentication changes.
In a web app,I am letting the user create an Item.The db manipulations are done through dao implementations
which use hibernate.The generic dao implementation uses Criteria for the query
The name of an Item is unique.So,I have to prevent a user from creating two items with the same name.
How should I do this in the code?Each time a user attempts to create an item,should I call itemDao.findItemByName(newname),
and if an item exists, give the user an error message?Or should I put the item creation code in a try catch block,catch exception,
and tell the user,the attempt to create a new item failed?
It seems to me ,the first approach will let me give a more precise error message to the user.But it will involve one db check call
for every attempt to create item.The second will be some exception boiling up from the dao class and less specific.
I would appreciate some advice on this..
sincerely
Jim
GenericDaoImpl
...
public T findUniqueItemByProperty(String propName,String propVal){
Class clz = getPersistentClass();
Session session = getSession();
logger.info("session="+session.hashCode());
Criteria cri = session.createCriteria(clz).add(Restrictions.eq(propName,propVal));
return (T)cri.uniqueResult();
}
public void saveOrUpdate(T obj) {
getSession().saveOrUpdate(obj);
}
...
ItemDao
...
public Item findItemByName(String name){
return findUniqueItemByProperty("name",name);
}
public void saveOrUpdateItem(Item item){
saveOrUpdate(item);
}
Either is valid. Alex gives some other alternatives in his answer. If you're worried about performance, you usually don't need to. Write it the way that seems right. Optimize later, when it's proven to be needed. This code is very clean and easy to understand compared to how else it could be written:
if (dao.checkForExistence(something)) {
return duplicateSomethingResponse();
}
dao.makePersistent(something);
You can do conditional update with where name=? and if number of updated rows is 0 do insert. And if you make name a key, Hibernate will take care of it for you with saveOrUpdate. Anyway, name, probably, should be indexed.