I am developing my project on spring+hibernate+annotations. I need to apply some set of validations on the data.
presently the code seems like this.
public class SomeClass{
boolean error = false;
if(!error){
check condition1
if(fails) {
error = true;
}
}
if(!error){
check condition2
if(fails) {
error = true;
}
}
if(!error){
check condition3
if(fails) {
error = true;
}
}
// similarly i have 5 to 10 validations.
}
Is there any design pattern that can replace the above scenario.
Thanks.
spring offers validation classes, see org.springframework.validation
the reference supplies a full tutorial of the way spring handles validation errors. http://static.springsource.org/spring/docs/2.5.x/reference/validation.html
On my current project we went a bit further, we crated a ValidationTemplate class that is abstract. We have 2 methods, a validate method that calls an abstract method with a List<Error>
When we want to validate we can just create an anonymous instance of that abstract class and implement the doInValidation method. This allows you to
new ValidationTemplate(){
doInValidation(List<Error> errors){
if(!condition) {
errors.add(new Error("reason");
}
}.validate();
you can implement the validation method as you want, you could throw an exception or return the list with errors if you want a more elegant result.
Unfortunately I cannot post the exact source instead of this piece of pseudo code.
You should be looking Hibernate Validator.
Related
I'm new to AOP and I need to use AspectJ on my project.
I need to use around advice but I have a problem using it, I've the following code in my .aj class,
pointcut checkUser(ProceedingJoinPoint jp,User user): call(* com.example.UserAccount.MyUI.checkUser(..))&& args(jp,user);
void around(ProceedingJoinPoint jp,User user) throws Throwable : checkUser(jp,user){
// Condition checks one of the user boolean property
if(condition){
jp.proceed();
}else{
// Do nothing
}
}
but I get this warning all the time,
advice defined in Aspects.UserAccount has not been applied [Xlint:adviceDidNotMatch]
By the way, I tried it without ProceedingJoinPoint and tried just proceed(); but then got this warning, too few arguments to proceed, expected 1
I'm thankful for any single help or hint!
Reza
First I recommend to read the AspectJ documentation in order to learn the syntax. As you are using native AspectJ syntax, this is like learning a new programming language or at least a Java extension. What you are doing is mix native syntax with annotation-based syntax. Try to stick with one. I am sure that you did not find this in any tutorial but ended up with that syntax via trial and error.
You do not need to bind a joinpoint parameter in native syntax because it is there implicitly and automatically. The automatically bound joinpoint is always named thisJoinPoint as all tutorials surely show you. Only in annotation-based syntax you need to bind the joinpoint and can name it as you wish, but even then I recommend to stick with thisJoinPoint because then refactoring from annotation to native syntax is easier and your eyes get used to spotting that variable name in your aspect code.
The warning you get means that the pointcut you defined does not match any part of your code, at least not any part which is visible to the aspect weaver or compiler. There could be plenty of reasons why this can occur, e.g. misspelled package or class names, wrong around advice return type (return type must be Object for non-void methods or more specifically match what the method you want to intercept returns). Assuming that e.g. checkUser(..) returns a boolean, the around advice should do the same. I made up an example using your package and class names. Besides, package names should be lower-case but I used yours, assuming they are really package names and not inner classes:
Helper class:
package com.example.UserAccount;
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return "User(" + name + ")";
}
}
Class targeted by aspect + sample main method:
package com.example.UserAccount;
public class MyUI {
public boolean checkUser(User user) {
return user.getName().toUpperCase().contains("ADMIN");
}
public static void main(String[] args) {
MyUI ui = new MyUI();
System.out.println(ui.checkUser(new User("Administrator")));
System.out.println(ui.checkUser(new User("john")));
System.out.println(ui.checkUser(new User("xander")));
System.out.println(ui.checkUser(new User("admiral")));
System.out.println(ui.checkUser(new User("SySaDmiN")));
}
}
As you can see, we expect an output of "true" for the first and last entry, but "false" for the ones in between due to the check logic I made up for checkUser(..).
Now let us write an aspect which also returns "true" for a user named "Xander", e.g. in order to give him admin rights or whatever. I am making this up because you did not provide an MCVE as you always should on StackOverflow, but just an incoherent code snippet which keeps everyone trying to answer your question guessing what the heck you might want to achieve and how to reproduce your problem.
Aspect:
package Aspects;
import com.example.UserAccount.User;
import com.example.UserAccount.MyUI;
public aspect UserAccount {
pointcut checkUser(User user) :
execution(boolean MyUI.checkUser(*)) && args(user);
boolean around(User user) : checkUser(user) {
System.out.println(thisJoinPoint + " -> " + user);
if (user.getName().equalsIgnoreCase("xander"))
return true;
return proceed(user);
}
}
I just imported the MyUI class, so there is no need to use a fully-qualified class name here. Again, this is an advantage of native syntax, in annotation-based syntax you would have to use the fully qualified name.
I also replaced the generic * MyUI.checkUser(..) (which would also work) by the more explicit boolean MyUI.checkUser(*) because we already know that the method returns a boolean and has exactly one parameter, which both we assume anyway by returning a boolean from the around advice and by binding exactly one parameter via args(). You could also be even more specific and use boolean MyUI.checkUser(User).
Furthermore, I am using execution() rather than call() because it is more efficient, as it weaves the advice code just into the executing method once instead of five times for each method call in the main method. You only need to use call() if the MyUI class is out of reach of the AspectJ weaver/compiler, i.e. because it is not in the module you compile with AspectJ Maven.
Console log:
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(Administrator)
true
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(john)
false
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(xander)
true
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(admiral)
false
execution(boolean com.example.UserAccount.MyUI.checkUser(User)) -> User(SySaDmiN)
true
Et voilĂ , the aspect works. It makes the target method return "true" for user "xander".
I have been using the togglz since last few days.
I am trying to find out if there is annotation based approach available in togglez API.
I want to do it like below -
public class Application {
public static void main(String[] args) {
Application application = new Application();
boolean first=false;
first=application.validate1();
System.out.println(first);
}
#Togglz(feature = "FEATURE_01")
public boolean validate1() {
System.out.println("validate1");
return false;
}
}
Is there anything available in togglz.
I could not find it anywhere , if you have any idea about such annotation please help.
My requirement is to skip the method execution based on feature value passed into it
No, there is no such annotation in Togglz. You will need some framework that support interceptors for that (like Spring, CDI, EJB). Then you can implement such an interceptor yourself.
However, to be honest I'm not sure if such an annotation would make sense. What should be the result if the feature is off? What does the method return? null? Explicit feature checks using a simple if statement are more straight forward to use in theses cases. But that's just my opinion. ;-)
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.
We have the validate() method directly available in our action classes in which we can put our own logic to perform some kind of validations we need.
For example, if I need to validate two fields regarding date-time, I can put my own logic in the validate() method something like the following.
public final class DiscountAction extends ActionSupport implements ValidationAware, ModelDriven<Discount>
{
private Discount entity=new Discount();
#Override
public Discount getModel() {
return entity;
}
#Override
public void validate()
{
if(entity.getDiscountStartDate()!=null&&entity.getDiscountEndDate()!=null)
{
final int period=30;
final DateTime startDate=entity.getDiscountStartDate().withZone(DateTimeZone.forID("Asia/Kolkata")).withMillisOfSecond(0);
final DateTime endDate=entity.getDiscountEndDate().withZone(DateTimeZone.forID("Asia/Kolkata")).withMillisOfSecond(0);
final DateTime currentDate=new DateTime(DateTimeZone.forID("Asia/Kolkata"));
final int daysBetween = Days.daysBetween(startDate, endDate).getDays();
if(startDate.isAfter(endDate))
{
addFieldError("discountStartDate", "The start date must be earlier than the end date.");
}
else if(startDate.equals(endDate))
{
addFieldError("discountEndDate", "Both the dates can not be same.");
}
else if(DateTimeComparator.getDateOnlyInstance().compare(currentDate, endDate)==0 || endDate.isBefore(currentDate))
{
addFieldError("discountEndDate", "Can not be today's date or any day before today.");
}
else if(Days.daysBetween(startDate, endDate).getDays()<1)
{
addFieldError("discountEndDate", "There must be an interval of at least one day.");
}
else if(daysBetween>period)
{
addFieldError("discountEndDate", "The discount period is valid only upto "+period+(period==1?" day":" days")+" period which it excceds. The actual difference is "+daysBetween);
}
}
}
}
Assuming entity is an instance of the model class.
Why do we need a custom validator here? I have not yet tried a custom validator, since it is not needed yet.
Could you please show me a real situation/example where a custom validator is precisely need?
Custom validators are used when:
You want to use annotation- or XML-based validation
You want to re-use the same validation across many actions, with the caveat that...
...if the validation already exists in external logic, which it should anyway, you can re-use it in validate methods as well
The business logic for custom validators should already exist as a separate entity. It should not exist as code embedded in an action; it makes both the action, and the validation, much harder to test.
When the logic is located in its appropriate place, it's easy to use in either a validator or a validate method. The advantage is easy re-use in XML and/or annotations.
In such point-of-view, I can also claim that Struts2 is not needed too because I can implement my web application using C++. Could you accept? I think no, because using an MVC pattern such Struts2 makes your application more clean and maintainable. Also, you do not have to redo things again yourself when they're implemented already.
In same way, if you want to use already implemented and tested best practices and also if you would like to save time and money by not doing things from scratch, and if you like maintainable codes using separated concerns ... then you need to use Struts2 custom validators instead of that ugly validate method (It's ugly because aspects such validations should not mixed with business logic - see AOP).
I'm wanting to use two custom matchers for a single method. Basically, if I pass the method VALUE_A, I want it to return RESULT_A, and if I pass it VALUE_B, I want it to return RESULT_B. So here's a code excerpt :
class IsNonEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
//For some reason, this method is called when I assign the IsEmpty matcher to MockHtable.get()
//When this happens, the value of the get argument is null, so this method throws an NPE
return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key));
}
}
class IsEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
return !(Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key)));
}
}
[...]
//This line executes just fine
Mockito.when(mockHTable.get(Mockito.argThat(new IsNonEmpty()))).thenReturn(dbResult);
[...]
//This line calls IsNonEmpty.matches() for some reason. IsNonEmpty.matches() throws an NPE
Mockito.when(mockHTable.get(Mockito.argThat(new IsEmpty()))).thenReturn(emptyResult);
When I assign the IsEmpty custom matcher to mockHTable.get() method, it calls the IsNonEmpty.matches() function. No idea why it's doing this. So I change the IsNonEmpty class to this :
class IsNonEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
//For some reason, this method is called when I assign the IsEmpty matcher. Weird, no?
if(get == null) {
return false;
}
return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key));
}
}
and then everything works just fine! IsNonEmpty.matches() is still called when I assign the IsEmpty matcher to the mockHTable.get() function, but my matchers work exactly how they should.
So what's the deal? Why does this happen? Is my work-around an adequate way to compensate for this quirky behavior, or am I Doing It Wrong?
The reason why IsNonEmpty.matches() gets called on the second line of stubbing is that the Mockito.argThat(new IsEmpty()) returns null, which is then passed to mockHTable.get(). This call has to be checked against the earlier stubbing, to see whether it's a match; and that means calling IsNonEmpty.matches().
I'm not sure why this makes your test fail - it's hard to tell without seeing all of the code.
But, I would seriously recommend using doReturn...when instead of when...thenReturn whenever you have to stub the same mock more than once. You won't encounter issues like this if you do. In fact, I prefer to use doReturn...when in preference to when...thenReturn always (and similarly doThrow and doAnswer), although most people prefer when...thenReturn.
Re-writing one of your stubbing lines with the doReturn...when syntax looks like the following. The other is similar.
Mockito.doReturn(dbResult).when(mockHTable).get(Mockito.argThat(new IsNonEmpty()));
Lastly, a plea, on behalf of the Mockito development team (of which I am a member). If you think there is a bug in Mockito here - and from your description, I think there may well be - please EITHER
send a message to the Mockito mailing group (mockito#googlegroups.com) OR
raise an issue on the Mockito issues list (http://code.google.com/p/mockito/issues/list).
It's useful to the Mockito team if you can actually post a complete example, rather than just what you think the key lines are - sometimes the cause of a Mockito problem is in quite an unexpected place.