Is there any particulars on when to use the annotations in java, or to put it more precisely, is the answer to the following question Yes or No
Only under this condition, can this particular annotations be used.
Obviously, the this in the above statement can be anything or nothing.
The reason I ask this question is that I was given this code base and in their they had used some annotations to validate the classes, properties etc. Now, this is a web application and it makes use of all the spring beans and what not.
I tried the following code. (This is just normal java code, no spring or anything.This is the entire code)
public class AnnotationsTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
TestMe t = new TestMe();
System.out.println(t.getTest1());
}
}
class TestMe{
#NotNull
private String test1;
public String getTest1() {
return test1;
}
public void setTest1(String test1) {
this.test1 = test1;
}
}
This one prints out null as output. Why is not any validation happening?
Well, what I am guessing is that I've provided the annotations for this, but have not really validated. So I went to this link. Therein he had all sorts of ValidationFactory and what not.
So I wrote,
public class AnnotationsTest{
private static Validator validator;
public static void main(String[] args) {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
TestMe t = new TestMe();
Set<ConstraintViolation<TestMe>> constraintViolations =
validator.validate(t);
assertEquals(1, constraintViolations.size());
assertEquals("may not be null", constraintViolations.iterator().next().getMessage());
}
}
But this one give the following error
Exception in thread "main" javax.validation.ValidationException: Unable to find a default provider
at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:264)
at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:111)
at AnnotationsTest.main(AnnotationsTest.java:29)
So here's my questions:
1. What exactly happened in the two cases above?
2. I thought that annotations were enough, as in Autowired and stuff, they would just inject the classes on it's own. But here why do I need to do the extra stuff to validate. Why doesnt #NotNull validates the things on it's own.
Thanks.
What you need to understand about annotations is they are just metadata on code. Nothing more, nothing less.
In order for all the black magic to happen (in your case Validation, or in the case of #Autowired as you mentioned the registering into the Spring container), some other piece of code needs to read the class definitions, check and see if the annotations are present and if so, perform a while bunch of steps (which may include simple things like registering objects or more advanced things like creating proxies, manipulating bytecode etc.).
So in your case, although the metadata is present on the class in the form of annotations, however no code is present that actually handles them. In the case of validation, that code would be Hibernate Validator.
In order to use Hibernate Validator you could check out this link
Related
As the title suggests , I want to know how does field injection internally works in spring , I read many articles on this and got to know few things like below but didn't understood the exact reason behind it :
-> It should not be used because when you do unit testing then you are dependent upon the spring
container to instantiate the class in case of field injection.
-> You cannot use "final" keyword in case of field injection , means you cannot make the field immutable.
-> It internally uses reflection
I want to know how exactly does #Autowired works internally , how does it uses reflection , I am trying to understand the exact reason behind all the above mentioned points, what happens behind the scenes when we write the below code :
#Component
public class B {
#Autowired
private A a1;
}
I have read similar questions on stack overflow about this topic , but I couldn't find the exact explanation that I am looking.
Spring has a concept of Bean Post Processors.
When spring builds a bean it applies registered bean post processors that help to "initialize" the bean.
So, there is org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor that handles autowiring.
Basically it works with an newly created object. Spring introspects the fields of the beans (by using reflection). The fields that have #Autowired is a subject for processing with this bean post processor. It finds the candidate for injection in the application context and actually injects the value.
Now given this information, its understandable why final fields cannot be autowired. Leave alone spring, In pure Java, final fields must be instantiated directly right during the declaration (final int i = 123) or in the constructor of the class. But the autowiring happens after constructor, so its impossible to autowire the final fields.
As for the unit testing, the private properties must be somehow configured from the test. But since they're encapsulated (yes, spring kind of breaks encapsulation in this case for its usage), its impossible to write a good test for the class that contains fields injection. That's is a reason to switch to constructor injection.
public class FieldInjection {
#Autowired
private A a;
}
VS.
public class ConstructorInjection {
private final A a;
// this can be generated by lombok, you don't have to put #Autowired on constructor in the case of single constructor, spring will use it to create a bean
public ConstructorInjection(A a) {
this.a = a;
}
}
Now the test for FieldInjection class is impossible:
public class FieldInjectionTest {
#Test
void test() {
FieldInjection underTest = new FieldInjection();
how do you know that you should instantiate A a. ????
}
}
However in the case of constructor injection its a trivial task:
public class ConstructorInjectionTest {
#Test
void test() {
A a = mock(A.class);
ConstructorInjection underTest = new ConstructorInjection(a);
// the dependencies must be supplied in the constructor
// otherwise its impossible to create an object under test
}
}
Currently, I try to design some things with OO principles in mind. So let's say, before processing user input, I need to validate it. According to OO, a separate Validator class would be the correct way. This would look as follows:
public class Validator{
public void validate(String input) throws ValidationException{
if (input.equals("")) throw new ValidationException("Input was empty");
}
}
Then, my processing class, which got the validator object before via dependency injection would call validator.validate(input)
A good point about this design is, that
My processing class can get a mock for the validator via DI which makes testing easier
The Validator class can be tested independently
However, my doubts are in the design of the Validator. According to OO, it misses some kind of state. With this design, it is as util class and the validate method could be static. And I read a lot of times that (static) Util classes are bad OO design. So, how can this be done with more OO while keeping the two advantages I mentioned?
PS.: Maybe, OO is simply a bad solution for this kind of problem. However, I would like to see how the OO solution would look like and form my own opinion.
The validator in your example doesn't have a state (and doesn't need any), but another validator could require one (say with a format):
Example:
public class RegExValidator {
private Pattern pattern;
public RegExValidator(String re) {
pattern = Pattern.compile(re);
}
public void validate(String input) throws ValidationException {
if (!pattern.matcher(input).matches()) {
throw new ValidationException("Invalid syntax [" + input + "]");
}
}
}
Concentrating on the OOP aspect of your question (rather than the question if an Exception is the correct way to handle your validation):
Why have a single validator?
interface Validator<T> {
void validate(T toValidate) throws ValidationException;
}
would enable you to write classes that can validate any class T and be very testable. Your validator would look like this:
class EmptyStringValidator implements Validator<String> {
public void validate(String toValidate) {
if(toValidate == null || toValidate.isEmpty()) throw new ValidationException("empty!!!");
}
}
and you could test it very easily.
In fact, if you're using Java 8, this would be a functional interface, so a single utility class could host several validators:
class ValidationUtil {
public static void emptyString(String val) // same code as above
}
and ValidationUtil::emptyString would implement Validator<String>.
You would combine several validators with a composite pattern.
You could also have a validator with a state if that's what you need...
class ListIsSortedValidator implements Validator<Integer> {
private int lastInt = Integer.MIN_VALUE;
public void validate(Integer val) throw ValidationException {
if (val < lastInt) throw new ValidationException("not sorted");
lastInt = val;
}
}
That you could use to for instance validate a list:
List<Integer> list = createList();
Validator<Integer> validator = new ListIsSortedValidator();
list.forEach(validator::validate);
It depends on the circumstances of course, but I think your instinct is correct. This design could be more Object-Oriented.
It is not just that Validator has no state, which is a purely mechanical indicator that it is likely not a correct abstraction, but the name itself tells us something. Usually Validator (or even EmptyStringValidator) is not part of the problem domain. It is always a bad sign when you have to create something purely technical (although sometimes it is the less of two evils).
I assume you are not writing a web-framework, you are trying to write an application that has some domain. For example it has user registration. Then, RegistrationForm is part of the problem domain. Users know about the "registration form", you can talk about it and they will know what you mean.
In this case, an Object-Oriented solution for validation would be that this object is responsible for the validation of itself during the "submitting" of itself.
public final class RegistrationForm extends Form {
...
#Override
public void submit() {
// Do validation here
// Set input fields to error if there are problems
// If everything ok do logic
}
}
I know this is not the solution normally seen or even supported by web-frameworks. But it is how an Object-Oriented solution would look like.
The two important points to always keep in mind are:
Don't "get" data from objects, ask them to do something instead. This is as applicable to UI code as anything else.
OO makes sense when the objects focus on meaningful things, i.e. the problem domain. Avoid over-representing technical (unimportant) objects, like Validator (if that's not your application's domain).
This is the code I have:
#Cacheable(value = "configurationCache", key = "#myFile.lastModified()")
private Object foo(File myFile) throws IOException {
System.out.println(myFile.lastModified());
try {
Thread.sleep(6000);
} catch (InterruptedException ignored) {
}
final Object foo = new SomeObjectFromFile(myFile);
return foo;
}
I call this method twice passing file objects that have the same lastmodified value but caching does not work, the method will wait for 6 seconds.
Here is the output I am getting:
1456298573000
1456298573000
What am I doing wrong?
key = "#myFile.lastModified"
did not work either..
I am sure my configuration with ehcache is fine.
Juliens answer is probably the right one assuming you do not use aspectj. its not alone invoking a public method, but invoking a public method of an object where spring had the chance to wrap it's proxies around. So make sure you are injecting the service that you want to have enhanced with cacheable support.
For example
#Service
public SomeService {
#Autowired
private CacheEnhancedService css;
public void doSomething() {
css.getConfig(new File("./file"));
}
}
#Service
public CacheEnhancedService {
#Cacheable(value = "configurationCache", key = "#myFile.lastModified()")
public Object getConfig(File myFile) {
...
}
}
}
The issue lies with the fact that your method is private.
As mentioned in the documentation of the Spring Framework:
Method visibility and cache annotations
When using proxies, you should apply the cache annotations only to
methods with public visibility. If you do annotate protected, private
or package-visible methods with these annotations, no error is raised,
but the annotated method does not exhibit the configured caching
settings. Consider the use of AspectJ (see below) if you need to
annotate non-public methods as it changes the bytecode itself.
[...]
In proxy mode (which is the default), only external method calls
coming in through the proxy are intercepted. This means that
self-invocation, in effect, a method within the target object calling
another method of the target object, will not lead to an actual
caching at runtime even if the invoked method is marked with
#Cacheable - considering using the aspectj mode in this case. Also,
the proxy must be fully initialized to provide the expected behaviour
so you should not rely on this feature in your initialization code,
i.e. #PostConstruct.
You should either switch to a public method and make and external call or user AspectJ.
I have class Validator, which manage all validation criteria from files and database. But this criteria are loaded by Loader like this:
Validator validator = Loader.load("clients"); //get all from clients.cfg file
What is the best approach to determine from another class, which criteria are currently loaded?
Importer importer;
Validator clientsValidator = Loader.load("clients");
Validator addressValidator = Loader.load("address"); ...
importer.validate(data, clientsValidator, addressValidator);
public class Importer{
public void validate(Data data, Validator... validator){
...
validateClient(data, one of validators);
validateAddress(data, another of validator);
...
}
}
I need to know in Importer class, which Validator is for Clients, which for Addresses... Any good approaches?
The best way would be for you to be add a field and accompanying method to Validator to return the identifier (e.g. "clients") with which it was created.
Alternatively, if by using a different identifier when calling Loader.load() you get back instances of different classes implementing the Validator interface, then you can use the Object.getClass() method to tell those classes apart. If those classes are within a pretty small set you might even get away with using instanceof directly.
We would need more information, such as what Loader does exactly, what Validator is and how much you are allowed to change their code before being able to provide a more concrete answer.
EDIT:
Quite honestly, perhaps you should reconsider a redesign of your data model. As it stands, you can apparently mix clients and addresses without any checks. You should restructure your code to be able to rely on the type safety features of Java.
One way would be to have a generic class/interface Validator<T>, where T would the class of the validated objects:
public interface Validator<T> {
public boolean validate(T object);
}
You could then have specific Data subclasses for your data, such as Address or Client, and set typed Validator objects to Importer through specific methods:
public class Importer {
public void addAddressValidator(Validator<Address> validator) {
...
}
public void addClientValidator(Validator<Client> validator) {
...
}
}
This is far safer than mixing all validator objects in a single variadic method call, and it is also the preferred approach of most common frameworks in the wild.
Why not have a getSource() in Validator which gets set when Loader loads the source.
Thinking more about the specific question below :
I need to know in Importer class, which Validator is for Clients,
which for Addresses... Any good approaches?
Actually a better way to do this is if Loader can return a ClientValidator (implementation of Validator) for client and AddressValidator for addresses.
That way you can avoid the if-else conditions and directly call validate on the Validator class
Pass the validators by position. You must also check if the specific validator is null or not before you use.
public void validate(Data data,
Validator clientsValidator,
Validator addressValidator) {
...
if (clientsValidator != null) {
validateClient(data, clientsValidator);
}
if (addressValidator != null) {
validateAddress(data, addressValidator);
}
...
}
If have a Java class with some fields I want to validate using Hibernate Validator.
Now I want my users to be able to configure at runtime which validations take place.
For example:
public class MyPojo {
...
#NotEmpty
String void getMyField() {
...
}
...
}
Let's say I want to remove the NotEmpty check or replace it with Email or CreditCardNumber, how can I do it? Is it even possible? I guess it comes down to changing annotations at runtime...
You can't do it normally.
Here's what I've done to get more dynamic validations working via Hibernate Validator.
Extend the ClassValidator class.
Override the getInvalidVaues(Object myObj) method. First, call super.getInvalidValues(myObj), then add the hook to your customized validation.
Instantiate your custom validator and call getInvalidValues to validate. Any hibernate annotated validations will kick off at this point, and your custom dynamic validations (anything not supported by annotations) will kick off as well.
Example:
public class MyObjectValidator extends ClassValidator<MyObject>
{
public MyObjectValidator()
{
super(MyObject.class);
}
public InvalidValue[] getInvalidValues(MyObject myObj)
{
List<InvalidValue> invalids = new ArrayList<InvalidValue>();
invalids.addAll(Arrays.asList(super.getInvalidValues(myObj)));
// add custom validations here
invalids.addAll(validateDynamicStuff(myObj));
InvalidValue[] results = new InvalidValue[invalids.size()];
return invalids.toArray(results);
}
private List<InvalidValue> validateDynamicStuff(MyObject myObj)
{
// ... whatever validations you want ...
}
}
So your custom validation code can contain logic like "Do this validation, if the user configured it, otherwise do that one", etc. You may or may not be able to leverage the same code that powers the hibernate validations, but either way, what you are doing is more involved that the 'normal' use case for hibernate validator.
Actually it is possible in hibernate validator 4.1. Just read the documentation about programatic constraint creation.
I don't think you'll be able to remove or change the annotation, it's part of the class definition. You can build a new class, which is possible at runtime but a little involved. Hibernate may support programmatic access to the validations and allow you to override the annotation, I don't know the API that well. Hibernate does a bit of runtime class building itself... that might be a good place to learn how to do it if you're interested.