Should I put my business invariant check in controller - java

I am working with Spring MVC. I need to check duplicated premises name before saving premises.
In Controller
public void savePremises() {
// Check duplicate
Set<String> premiseNames = new HashSet<String>();
//premises is global variable which contain the list of premises to save
for (Premise premise : premises) {
String premiseName = premise.getPremiseName();
if (premiseNames.contains(premiseName)) {
Clients.showNotification("Duplicated primise name "
+ premiseName);
return;
} else {
premiseNames.add(premiseName);
}
}
..............
}
Because I will use this checking code for premises in another controller, so I want to put it in service class to reuse later.
Then I need to return 2 value from service function:
+ A boolean value to indicate the result of checking.
+ A string value for duplicated premise name.
I have a solution that returning null value for premise name to indicate no duplicated premise name. Is it bad practice to do this?
In Controller
public void savePremises(){
String premiseName =premiseService.isDuplicatedPremiseName(premises);
if( premiseName!=null) {
Clients.showNotification("Duplicated primise name "
+ premiseName);
return;
}
}
In Service
public String isDuplicatedPremiseName(List<Premise> premises) {
Set<String> premiseNames = new HashSet<String>();
for (Premise premise : premises) {
String premiseName = premise.getPremiseName();
if (premiseNames.contains(premiseName)) {
return premiseName;
} else {
premiseNames.add(premiseName);
}
}
return null;
}

Ideally, Spring MVC controllers should be a very thin adapter from service logic to HTTP (either HTML or a JSON/XML REST API). Besides basic DTO validation, business logic should be contained in your service classes. This makes the business logic easier to test and more reusable (e.g., between controllers that present both HTML and JSON).
In your case, unless the users are actively expecting to search for duplicates (perhaps in a search for public records), it would be better not to explicitly call the checker at all. The business logic should be responsible for ensuring that invariants are preserved and throw an exception if not. You can either catch the exception in the controller (usually the case for an HTML controller) or annotate it with Spring HTTP annotations and allow it to propagate (often the case for a JSON controller).

I have a solution that returning null value for premise name to indicate no duplicated premise name. Is it bad practice to do this?
Yes, returning null is definitely bad practice.
Instead, you can use Optional<T> class that contains value or contains indication that value is not available.
public Optional<String> GetFirstDuplicate(List<Premise> premises)
I need to check duplicated premises name before saving premises.
If your business logic doesn't allow duplicates in premise names, you should definitely check for duplication in controller before passing these names into business layer.
Exceptions in business layer are used to indicate coder's mistakes, not user's mistakes. Occasionally entering the same name twice is user's mistake.

Related

Ways to pass additional data to Custom RevisionEntity in Hibernate Envers?

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.

Solving LazyInitializationException via ignorance

There are countless questions here, how to solve the "could not initialize proxy" problem via eager fetching, keeping the transaction open, opening another one, OpenEntityManagerInViewFilter, and whatever.
But is it possible to simply tell Hibernate to ignore the problem and pretend the collection is empty? In my case, not fetching it before simply means that I don't care.
This is actually an XY problem with the following Y:
I'm having classes like
class Detail {
#ManyToOne(optional=false) Master master;
...
}
class Master {
#OneToMany(mappedBy="master") List<Detail> details;
...
}
and want to serve two kinds of requests: One returning a single master with all its details and another one returning a list of masters without details. The result gets converted to JSON by Gson.
I've tried session.clear and session.evict(master), but they don't touch the proxy used in place of details. What worked was
master.setDetails(nullOrSomeCollection)
which feels rather hacky. I'd prefer the "ignorance" as it'd be applicable generally without knowing what parts of what are proxied.
Writing a Gson TypeAdapter ignoring instances of AbstractPersistentCollection with initialized=false could be a way, but this would depend on org.hibernate.collection.internal, which is surely no good thing. Catching the exception in the TypeAdapter doesn't sound much better.
Update after some answers
My goal is not to "get the data loaded instead of the exception", but "how to get null instead of the exception"
I
Dragan raises a valid point that forgetting to fetch and returning a wrong data would be much worse than an exception. But there's an easy way around it:
do this for collections only
never use null for them
return null rather than an empty collection as an indication of unfetched data
This way, the result can never be wrongly interpreted. Should I ever forget to fetch something, the response will contain null which is invalid.
You could utilize Hibernate.isInitialized, which is part of the Hibernate public API.
So, in the TypeAdapter you can add something like this:
if ((value instanceof Collection) && !Hibernate.isInitialized(value)) {
result = new ArrayList();
}
However, in my modest opinion your approach in general is not the way to go.
"In my case, not fetching it before simply means that I don't care."
Or it means you forgot to fetch it and now you are returning wrong data (worse than getting the exception; the consumer of the service thinks the collection is empty, but it is not).
I would not like to propose "better" solutions (it is not topic of the question and each approach has its own advantages), but the way that I solve issues like these in most use cases (and it is one of the ways commonly adopted) is using DTOs: Simply define a DTO that represents the response of the service, fill it in the transactional context (no LazyInitializationExceptions there) and give it to the framework that will transform it to the service response (json, xml, etc).
What you can try is a solution like the following.
Creating an interface named LazyLoader
#FunctionalInterface // Java 8
public interface LazyLoader<T> {
void load(T t);
}
And in your Service
public class Service {
List<Master> getWithDetails(LazyLoader<Master> loader) {
// Code to get masterList from session
for(Master master:masterList) {
loader.load(master);
}
}
}
And call this service like below
Service.getWithDetails(new LazyLoader<Master>() {
public void load(Master master) {
for(Detail detail:master.getDetails()) {
detail.getId(); // This will load detail
}
}
});
And in Java 8 you can use Lambda as it is a Single Abstract Method (SAM).
Service.getWithDetails((master) -> {
for(Detail detail:master.getDetails()) {
detail.getId(); // This will load detail
}
});
You can use the solution above with session.clear and session.evict(master)
I have raised a similar question in the past (why dependent collection isn't evicted when parent entity is), and it has resulted an answer which you could try for your case.
The solution for this is to use queries instead of associations (one-to-many or many-to-many). Even one of the original authors of Hibernate said that Collections are a feature and not an end-goal.
In your case you can get better flexibility of removing the collections mapping and simply fetch the associated relations when you need them in your data access layer.
You could create a Java proxy for every entity, so that every method is surrounded by a try/catch block that returns null when a LazyInitializationException is catched.
For this to work, all your entities would need to implement an interface and you'd need to reference this interface (instead of the entity class) all throughout your program.
If you can't (or just don't want) to use interfaces, then you could try to build a dynamic proxy with javassist or cglib, or even manually, as explained in this article.
If you go by common Java proxies, here's a sketch:
public static <T> T ignoringLazyInitialization(
final Object entity,
final Class<T> entityInterface) {
return (T) Proxy.newProxyInstance(
entityInterface.getClassLoader(),
new Class[] { entityInterface },
new InvocationHandler() {
#Override
public Object invoke(
Object proxy,
Method method,
Object[] args)
throws Throwable {
try {
return method.invoke(entity, args);
} catch (InvocationTargetException e) {
Throwable cause = e.getTargetException();
if (cause instanceof LazyInitializationException) {
return null;
}
throw cause;
}
}
});
}
So, if you have an entity A as follows:
public interface A {
// getters & setters and other methods DEFINITIONS
}
with its implementation:
public class AImpl implements A {
// getters & setters and other methods IMPLEMENTATIONS
}
Then, assuming you have a reference to the entity class (as returned by Hibernate), you could create a proxy as follows:
AImpl entityAImpl = ...; // some query, load, etc
A entityA = ignoringLazyInitialization(entityAImpl, A.class);
NOTE 1: You'd need to proxy collections returned by Hibernate as well (left as an excersice to the reader) ;)
NOTE 2: Ideally, you should do all this proxying stuff in a DAO or in some type of facade, so that everything is transparent to the user of the entities
NOTE 3: This is by no means optimal, since it creates a stacktrace for every access to an non-initialized field
NOTE 4: This works, but adds complexity; consider if it's really necessary.

A good practice to present service level validation errors to the user using Spring MVC

Are there some good practices to present service layer validation errors using Spring MVC after "shallow" user input validation has been performed using Spring MVC Validators? For example, having this code:
#Autowired
private UserService userService;
#RequestMapping(value = "user/new", method = RequestMethod.POST)
public String createNewUser(#ModelAttribute("userForm") UserForm userForm, BindingResult result, Model model){
UserFormValidator validator = new UserFormValidator(); //extending org.springframework.validation.Validator
validator.validate(userForm, result);
if(result.hasErrors()){
model.addAttribute("userForm", userForm);
return "user/new";
}
// here, for example, the user already might exist
userService.createUser(userForm.getName(), userForm.getPassword());
return "redirect:user/home";
}
While it may seem trivial having this code as an example, it seems to be a delicate story to me when validation at service layer is a complex task. Despite being an absurd scenario, the UserService might take a list of users to create, and if one of them already exists, then the view tier must somehow be notified about which of them is not valid (e.g. does already exist).
I am looking for a good practice how to design a piece of code, which makes it possible to
1) handle validation errors at the service layer having complex data as input, and
2) to present these validation errors to the user
as easy as possible. Any suggestions?
The choice is typically exceptions vs. error codes (or response codes), but the best practice, at least Bloch's, is to only use exceptions in exceptional circumstances, which disqualifies them in this situation, since a user picking an existing username isn't unheard of.
The issue in your service call is that you assume createUser is an imperative command with no return value. You should think of it as "try to create a user, and give me a result" instead. That result could then be
an integer code (horrible idea)
a constant from a shared Result enum (still a bad idea due to maintainability)
a constant from something more specific like a UserOperationResult enum (better idea since you might want to return USER_ALREADY_EXISTS both when you create a new user and when you try to modify a user)
a UserCreationResult object that's completely custom to this call (not a good idea because you'll get an explosion of these)
a Result<T> or UserOperationResult<T> wrapper object that combines a response code constant (ResultCode or UserOperationResultCode respectively) and a return value T, or a wildcard ? when there is no return value ... just watch out for pointcuts and the like that don't expect the wrapper)
The beauty of unchecked exceptions is that they avoid all this crap, but they come with their own set of issues. I'd personally stick to the last option, and have had decent luck with it in the past.
An alternative to throwing an exception/returning an error code would be to pass the Errors to userService.createUser(). The duplicate username check could then be performed at the service level - and any error appended to the Errors. This would ensure that all errors (shallow and more complex) could all be collected up and presented to the view at the same time.
So you could rework your controller method slightly:
#RequestMapping(value = "user/new", method = RequestMethod.POST)
public String createNewUser(#ModelAttribute("userForm") UserForm userForm, BindingResult result, Model model){
UserFormValidator validator = new UserFormValidator();
validator.validate(userForm, result);
// Pass the BindingResult (which extends Errors) to the service layer call
userService.createUser(userForm.getName(), userForm.getPassword(), result);
if(result.hasErrors()){
model.addAttribute("userForm", userForm);
return "user/new";
}
return "redirect:user/home";
}
And your UserServiceImpl would then check for duplicate users itself - for example:
public void createUser(String name, String password, Errors errors) {
// Check for a duplicate user
if (userDao.findByName(name) != null) {
errors.rejectValue("name", "error.duplicate", new String[] {name}, null);
}
// Create the user if no duplicate found
if (!errors.hasErrors()) {
userDao.createUser(name, password);
}
}
The Errors class is part of Spring's validation framework - so although there would be a dependency on Spring, the service layer wouldn't have any dependency on any web related code.

Play 2.0/Java - Is there a way to get the validation done post request data binding?

In play 2.0 you can get the request binding with validation done (via annotations) by :
ABCForm abcForm=(ABCForm)form(ABCForm.class).bindFromRequest().get();
The problem I have is , I want to get the validation done after trimming the form values.
So is there a way to either defer or call the validation stuff post binding in play 2.0 ?
Binding and validation are combined. So validation after the binding is not possible, as far as I know. However you can create a validate() method, in which you trim your values before validating them. For example:
public class User {
public String name;
public String validate() {
name.trim
if(name == "") {
return "Name is required";
}
return null;
}
}
The validate() method will be invoked when you bind a form. So you can make sure your data is valid, but errors won't be automatically added to the Form.Field objects. So it is certainly a nice solution.
There are also pretty much discussions about Form validation in Play's Google Group, so if you want to know more about the binding/validation problems I recommend reading them: https://groups.google.com/forum/#!searchin/play-framework/%5B2.0%5D$20validation.
If you need to modify your values before validation. You can create a setter for your field and do your trims there.

Good practice to validate immutable values objects

Suppose a MailConfiguration class specifying settings for sending mails :
public class MailConfiguration {
private AddressesPart addressesPart;
private String subject;
private FilesAttachments filesAttachments;
private String bodyPart;
public MailConfiguration(AddressesPart addressesPart, String subject, FilesAttachments filesAttachements,
String bodyPart) {
Validate.notNull(addressesPart, "addressesPart must not be null");
Validate.notNull(subject, "subject must not be null");
Validate.notNull(filesAttachments, "filesAttachments must not be null");
Validate.notNull(bodyPart, "bodyPart must not be null");
this.addressesPart = addressesPart;
this.subject = subject;
this.filesAttachements = filesAttachements;
this.bodyPart = bodyPart;
}
// ... some useful getters ......
}
So, I'm using two values objects : AddressesPart and FilesAttachment.
Theses two values objects have similar structures so I'm only going to expose here AddressesPart :
public class AddressesPart {
private final String senderAddress;
private final Set recipientToMailAddresses;
private final Set recipientCCMailAdresses;
public AddressesPart(String senderAddress, Set recipientToMailAddresses, Set recipientCCMailAdresses) {
validate(senderAddress, recipientToMailAddresses, recipientCCMailAdresses);
this.senderAddress = senderAddress;
this.recipientToMailAddresses = recipientToMailAddresses;
this.recipientCCMailAdresses = recipientCCMailAdresses;
}
private void validate(String senderAddress, Set recipientToMailAddresses, Set recipientCCMailAdresses) {
AddressValidator addressValidator = new AddressValidator();
addressValidator.validate(senderAddress);
addressValidator.validate(recipientToMailAddresses);
addressValidator.validate(recipientCCMailAdresses);
}
public String getSenderAddress() {
return senderAddress;
}
public Set getRecipientToMailAddresses() {
return recipientToMailAddresses;
}
public Set getRecipientCCMailAdresses() {
return recipientCCMailAdresses;
}
}
And the associated validator : AddressValidator
public class AddressValidator {
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,})$";
public void validate(String address) {
validate(Collections.singleton(address));
}
public void validate(Set addresses) {
Validate.notNull(addresses, "List of mail addresses must not be null");
for (Iterator it = addresses.iterator(); it.hasNext(); ) {
String address = (String) it.next();
Validate.isTrue(address != null && isAddressWellFormed(address), "Invalid Mail address " + address);
}
}
private boolean isAddressWellFormed(String address) {
Pattern emailPattern = Pattern.compile(EMAIL_PATTERN);
Matcher matcher = emailPattern.matcher(address);
return matcher.matches();
}
}
Thus, I have two questions :
1) If for some reasons, later, we want to validate differently an address mail (for instance to include/exclude some aliases matching to existing mailingList), should I expose a kind of IValidator as a constructor parameter ? like the following rather than bringing concrete dependence (like I made):
public AddressValidator(IValidator myValidator) {
this.validator = myValidator;
}
Indeed, this will respect the D principle of SOLID principle : Dependency injection.
However, if we follow this logical, would a majority of Values Objects own an abstract validator or it's just an overkill the most of time (thinking to YAGNI ?) ?
2) I've read in some articles than in respect of DDD, all validations must be present and only present in Aggregate Root, means in this case : MailConfiguration.
Am I right if I consider that immutable objects should never be in an uncohesive state ? Thus, would validation in constructor as I made be preferred in the concerned entity (and so avoiding aggregate to worry about validation of it's "children" ?
There's a basic pattern in DDD that perfectly does the job of checking and assembling objects to create a new one : the Factory.
I've read in some articles than in respect of DDD, all validations
must be present and only present in Aggregate Root
I strongly disagree with that. There can be validation logic in a wide range of places in DDD :
Validation upon creation, performed by a Factory
Enforcement of an aggregate's invariants, usually done in the Aggregate Root
Validation spanning accross several objects can be found in Domain Services.
etc.
Also, I find it funny that you bothered to create an AddressesPart value object -which is a good thing, without considering making EMailAddress a value object in the first place. I think it complicates your code quite a bit because there's no encapsulated notion of what an email address is, so AddressesPart (and any object that will manipulate addresses for that matter) is forced to deal with the AddressValidator to perform validation of its addresses. I think it shouldn't be its responsibility but that of an AddressFactory.
I'm not quite sure if I follow you 100%, but one way to handle ensuring immutable objects are only allowed to be created if they are valid is to use the Essence Pattern.
In a nutshell, the idea is that the parent class contains a static factory that creates immutable instances of itself based on instances of an inner "essence" class. The inner essence is mutable and allows objects to be built up, so you can put the pieces together as you go, and can be validated along the way as well.
The SOLID principals and good DDD is abided by since the parent immutable class is still doing only one thing, but allows others to build it up through it's "essence".
For an example of this, check out the Ldap extension to the Spring Security library.
Some observations first.
Why no generics? J2SE5.0 came out in 2004.
Current version of Java SE has Objects.requiresNonNull as standard. Bit of a mouthful and the capitalisation is wrong. Also returns the passed object so doesn't need a separate line.
this.senderAddress = requiresNonNull(senderAddress);
Your classes are not quite immutable. They are subclassable. Also they don't make a safe copy of their mutable arguments (Sets - shame there aren't immutable collection types in the Java library yet). Note, copy before validation.
this.recipientToMailAddresses = validate(new HashSet<String>(
recipientToMailAddresses
));
The use of ^ and $ in the regex is a little misleading.
If the validation varies, then there's two obvious (sane) choices:
Only do the widest variation in this class. Validate more specifically in the context it is going to be used.
Pass in the validator used and have this as a property. To be useful, client code would have to check and do something reasonable with this information, which is unlikely.
It doesn't make a lot of sense to pass the validator into the constructor and then discard it. That's making the constructor overcomplicated. Put it in a static method, if you must.
The enclosing instance should check that its argument are valid for that particular use, but should not overlap with classes ensuring that they are generally valid. Where would it end?
Although an old question but for anyone stumbling upon the subject matter, please keep it simple with POJOs (Plain Old Java Objects).
As for validations, there is no single truth because for a pure DDD you need to keep the context always in mind.
For example a user with no credit card data can and should be allowed to create an account. But credit card data is needed when checking out on some shopping basket page.
How this is beautifully solved by DDD is by moving the bits and pieces of code to the Entities and Value Objects where it naturally belong.
As a second example, if address should never be empty in the context of a domain level task, then Address value object should force this assertion inside the object instead of using asking a third party library to check if a certain value object is null or not.
Moreover Address as a standalone value object doesn't convey much at its own when compared with ShippingAddress, HomeAddress or CurrentResidentialAddress ... the ubiquitous language, in other words names convey their intent.

Categories

Resources