Using Spring RestControllers with hibernate validator.
Need to create some Validation annotation, that check the validating field presents in some dictionary (preset array or some DB).
For example, I have some bean
#Service
public class MyDict {
public boolean containsWord(String word) {
...
}
}
And some data, I check
public class ResponseData {
#IsInDictionary(MyDict.class)
private String word;
}
And when I call hibernate validation directly, or with #Valid annotation in RequestMapping method, I want validator to call MyDict bean method containsWord(word).
Does anybody have any ideas?
You need to define your own annotation and then define your own Validator where you will be performing your validation logic (in this case, a dictionary lookup)
You can read more about this here: https://docs.jboss.org/hibernate/validator/4.1/reference/en-US/html/validator-customconstraints.html#validator-customconstraints-constraintannotation
After creating your own annotation, you just extend ConstraintValidator<YourCustomAnnotation, String> and you are pretty much ready to go. Method isValid() needs to perform inside the logic you mentioned: containsWord(word)
The nice thing is that your custom validator can be a Spring-managed bean so you can freely inject stuff into it and for example, perform a DB lookup. So in this case, you would need to inject your dictionaries and perform a check there.
Related
Every request that my Java application receives, passes through 4 layers:
Handler --> Validator --> Processor --> DAO
Handler is the API Resource. (Handler.java)
Validator validates the input. (Validator.java)
Processor performs some business logic. (Processor.java)
DAO is the DB communication layer. (DAO.java)
The input request has a field called the request_type. Based on this request_type, I want to create different objects for all the layer classes, i.e:
request_type_A should pass through Handler1, Validator1, Processor1, DAO1 (instances)
request_type_B should pass through Handler2, Validator2, Processor2, DAO2 (instances)
request_type_C should pass through Handler3, Validator3, Processor3, DAO3 (instances).. and so on
To clarify, the requirement is to create different chain of objects for a given request type, so that two request having different request_type have entirely different object chain instances. Basically i want to shard my application's object based on a given request_type.
I am using Spring Boot. Is there a way that spring's ApplicationContext can provide different object chains for different object types. Or should I manage these instances by my own?
Is there a way I can create a library which would give me a new object instance for every layer, based on the request_type using Spring's ApplicationContext?
Or should i create multiple ApplicationContext?
Based on comments & question, I understand that you would be receiving 2 or 3 request_type.
So main idea which I have used here is to use constructor injection of chained objects with different configuration beans which will be used based on your request type.
Feel free to check-out this simple demonstration based code from github where I have proposed my idea : https://github.com/patilashish312/SpringObjectChaining
So based on this code, I can confirm that
This application is not creating chain of object per request but will re-use if same type of requests received by application
Objects assigned to one request type is not being used by other request type.
Below console output is proof :
displaying request MyRequest(id=1, name=Ashish, requestType=requestTypeA)
Printing handler bean com.spr.boot3.ConditionalVerification.Handler.MyHandler#31182e0a
Printing validator bean com.spr.boot3.ConditionalVerification.Validator.MyValidator#484e3fe7
Printing processor bean com.spr.boot3.ConditionalVerification.Processor.MyProcessor#70f9b9c7
Printing dao bean com.spr.boot3.ConditionalVerification.Dao.MyDao#2a8175d9
inside dao, doing DAO processing
displaying request MyRequest(id=1, name=Ashish, requestType=requestTypeA)
Printing handler bean com.spr.boot3.ConditionalVerification.Handler.MyHandler#31182e0a
Printing validator bean com.spr.boot3.ConditionalVerification.Validator.MyValidator#484e3fe7
Printing processor bean com.spr.boot3.ConditionalVerification.Processor.MyProcessor#70f9b9c7
Printing dao bean com.spr.boot3.ConditionalVerification.Dao.MyDao#2a8175d9
inside dao, doing DAO processing
displaying request MyRequest(id=1, name=Ashish, requestType=requestTypeB)
Printing handler bean com.spr.boot3.ConditionalVerification.Handler.MyHandler#55ea9008
Printing validator bean com.spr.boot3.ConditionalVerification.Validator.MyValidator#5b2d74c5
Printing processor bean com.spr.boot3.ConditionalVerification.Processor.MyProcessor#5f12fb78
Printing dao bean com.spr.boot3.ConditionalVerification.Dao.MyDao#1a107efe
inside dao, doing DAO processing
displaying request MyRequest(id=1, name=Ashish, requestType=requestTypeB)
Printing handler bean com.spr.boot3.ConditionalVerification.Handler.MyHandler#55ea9008
Printing validator bean com.spr.boot3.ConditionalVerification.Validator.MyValidator#5b2d74c5
Printing processor bean com.spr.boot3.ConditionalVerification.Processor.MyProcessor#5f12fb78
Printing dao bean com.spr.boot3.ConditionalVerification.Dao.MyDao#1a107efe
inside dao, doing DAO processing
I had a similar requirement in my solution. What I built was a general-purpose command handler, and used a decorator pattern of annotations on each command to provide the specification for which handlers, validators, processors, and dao.
In my implementation, I have API handlers which convert requests to specific commands. Command class was an subclass of an abstract command class with a generic type param.
API -> all API variables are copied into a wrapper data model. (This could encapsulate the entrypoint of your handler concept or request_type concept)
Command extends AbstractCommand where T is the wrapper data model.
Then I would have an annotation for each of your concepts: Handler, Validator, Processor, Dao.
The general purpose command handler would have a method that "process"es commands by reading their annotations and then lining up the annotation helper that corresponds to that annotation. This could use the application context to load the bean of the class referenced in the annotation value. By providing a sequencing property for each of the annotation helpers you could loop over the sorted helpers to perform actions in the right order.
In my implementation this was further augmented by whether or not the command included asynchronous behavior, so that all the synchronous behavior would occur first, and the asychronous behavior would be wrapped in a background thread.
The beans that are injected in the rest controller don't vary with the http request content. What you can do is factor your request_type as a path variable and create the desired chains in separate http mappings like so:
#PostMapping(value = "/request_type_A")
public Object handle1(args...){
// Validator1 --> Processor1 --> DAO1
}
#PostMapping(value = "/request_type_B")
public Object handle2(args...){
// Validator2 --> Processor2 --> DAO2
}
If this is not practical for whatever reason and you must specify the type dynamically in the #RequestBody, #PathVariable or #RequestParam, then I would suggest implementing a resolver bean similar to this:
#Component
public class Resolver {
private final RequestTypeAValidator requestTypeAValidator;
private final RequestTypeBValidator requestTypeBValidator;
...
public IValidator getValidator(String requestType) {
switch (requestType) {
case "request_type_A":
return requestTypeAValidator;
case "request_type_B":
return requestTypeBValidator;
default:
throw new IllegalArgumentException("cannot find validator");
}
}
}
The drawback of this approach is that it does not comply with the "Open-Closed" principle in the sense that for any new request type, you will need to edit the resolvers. That can be fixed by using a HashMap in the resolver and letting the beans register themselves to that map on #PostConstruct:
#Component
public class Resolver {
private final Map<String, IValidator> validators = new HashMap<>();
public IValidator getValidator(String requestType) {
IValidator result = validators.get(requestType);
if (Objects.isNull(result)) {
throw new IllegalArgumentException("cannot find validator");
}
return result;
}
public void register(String type, IValidator validator) {
validators.put(type, validator)
}
}
#Component
public class ValidatorA implements IValidator {
private final Resolver resolver;
#PostConstruct
private void register() {
resolver.register("request_type_A", this);
}
...
}
However, in this approach there is a direct dependency from all implementations back to the Resolver.
Lastly, you could inject dynamically like so:
#Component
public class Resolver {
private final ApplicationContext applicationContext;
...
public IValidator getValidator(String requestType) {
switch (requestType) {
case "request_type_A":
try {
return applicationContext.getBean(ValidatorA.class);
} catch (NoSuchBeanDefinitionException e) {
// handle exception
}
case "request_type_B":
try {
return applicationContext.getBean(ValidatorB.class);
} catch (NoSuchBeanDefinitionException e) {
// handle exception
}
default:
throw new IllegalArgumentException("cannot find validator");
}
}
}
Note: Avoid taking the client specified string as the class name or type directly in the applicationContext.getBean() call. That is not safe and may present a great security vulnerability, use a switch or dictionary to resolve the correct bean name or bean type.
If you want to inject multiple instances of the same classes, create a configuration class and declare the beans like this:
#Configuration
public class BeanConfiguration {
#Bean
public IValidator aValidator(){
return new ValidatorImpl(...);
}
#Bean
public IValidator bValidator(){
return new ValidatorImpl(...);
}
}
And then to inject it, you can either use the dynamic resolution by name as above, or use the #Qualifier annotation:
#Service
public class MyService {
private final ApplicationContext applicationContext;
private final IValidator bValidator;
public MyService(ApplicationContext applicationContext, #Qualifier("bValidator") IValidator bValidator) {
this.applicationContext = applicationContext;
this.bValidator = bValidator;
}
public void getDynamically(){
IValidator aValidator = (IValidator)applicationContext.getBean("aValidator");
}
}
We are using Spring's TransactionInterceptor to set some database partition information using ThreadLocal whenever a DAO method marked with the #Transactional annotation is executed. We need this to be able to route our queries to different database partitions.
This works fine for most DAO methods:
// this causes the invoke method to set a thread-local with the host name of
// the database server the partition is on
#Transactional
public int deleteAll() throws LocalDataException {
The problem is when we need to reference the DAO proxy object itself inside of the DAO. Typically we have to have the caller pass in the proxy-dao:
public Pager<Foo, Long> getPager(FooDao proxyDao) {
This looks like the following in code which is obviously gross.
fooDao.getPager(fooDao);
The problem is that when we are inside of FooDao, the this is not the proxy DAO that we need.
Is there a better mechanism for a bean to discover that it has a proxy wrapper around it? I've looked at the Spring AOPUtils but I see no way to find the proxy for an object. I don't want isAopProxy(...) for example. I've also read the Spring AOP docs but I can't see a solution there unless I implement my own AOP native code which I was hoping to avoid.
I suspect that I might be able to inject the DAO into itself with a ApplicationContextAware utility bean and a setProxyDao(...) method, but that seems like a hack as well. Any other ideas how I can detect the proxy so I can make use of it from within the bean itself? Thanks for any help.
A hacky solution along the lines of what you have suggested, considering that AspectJ compile time or load time weaving will not work for you:
Create an interface along these lines:
public interface ProxyAware<T> {
void setProxy(T proxy);
}
Let your Dao's implement the ProxyAware implementation, now create a BeanPostProcessor with an Ordered interface to run last, along these lines:
public class ProxyInjectingBeanPostProcessor implements BeanPostProcessor, Ordered {
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (AopUtils.isAopProxy((bean))){
try {
Object target = ((Advised)bean).getTargetSource().getTarget();
if (target instanceof ProxyAware){
((ProxyAware) target).setProxy(bean);
}
} catch (Exception e) {
// ignore
}
}
return bean;
}
#Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
It is ugly, but works.
There is a handy static utility AopContext.currentProxy() method provided by Spring which returns a proxy to object from which it was called.
Although using it is considered a bad practice, semantically the same method exists in Java EE as well: SessionContext.getBusinessObject().
I wrote few articles about this utility method and various pitfalls: 1, 2, 3.
Use Spring to inject a bean reference into the bean, even the same bean, just as you would for any other bean reference. No special action required.
The presence of such a variable explicitly acknowledges in the class design that the class expects to be proxied in some manner. This is not necessarily a bad thing, as aop can change behavior that breaks the class contract.
The bean reference would typically be for an interface, and that interface could even be a different one for the self-referenced internal methods.
Keep it simple. That way lies madness. :-)
More importantly, be sure that the semantics make sense. The need to do this may be a code smell that the class is mixing in multiple responsibilities best decomposed into separate beans.
I have a POJO class with a method annotated with #Transactional
public class Pojo {
#Transactional
public void doInTransaction() {
...
}
}
Spring declarative transaction management is based on AOP but I don't have any experience with that. My question is:
Is it possible that when invoking the (new Pojo).doInTransaction() alone, Spring will start a Transaction.
Spring declarative transaction
management is based on APO but I don't
have any experience with that.
I would recommend to start working with it and you will get the experience of using transaction advices using AOP. A good starting point is here.
Is it possible that when invoking the
(new Pojo).doInTransaction() alone,
Spring will start a Transaction.
No, you can't expect Spring to be aware of a bean that you manually invoked. However, it sounds like that you are wanting to avoid declarative transaction management and do programmatic transaction management. There is a way to do that with Spring using the Transaction Template. Is that what you were looking for?
It is somewhat possible, but in a cumbersome way: You must use the AutowireCapableBeanFactory mechanism.
Here is a transactional class as example
public interface FooBar{
void fooIze(Object foo);
}
public class FooBarImpl implements FooBar{
#Transactional
#Override
public void fooIze(final Object foo){
// do stuff here
}
}
And here is how we can use it:
public class FooService implements ApplicationContextAware{
private ApplicationContext applicationContext;
#Override
public void setApplicationContext(
final ApplicationContext applicationContext){
this.applicationContext = applicationContext;
}
public void serviceMethod(){
//declare variable as interface, initialize to implementation
FooBar fooBar = new FooBarImpl();
// try to use it, won't work, as it's not a proxy yet
Object target = new Object[0];
fooBar.fooIze(target); // no transaction
// now let spring create the proxy and re-assign the variable
// to the proxy:
fooBar = // this is no longer an instance of FooBarImpl!!!
(FooBar) applicationContext
.getAutowireCapableBeanFactory()
.applyBeanPostProcessorsAfterInitialization(fooBar,
"someBeanName");
fooBar.fooIze(fooBar); // this time it should work
}
}
This is not a best practice. For one thing, it makes your application highly aware of the Spring Framework and also, it violates the dependency injection principles. So use this only if there is no other way!
Yes, it is possible. Spring does not require the use of dynamic proxies for #Transactional to work. Instead, you can use "true AOP", as provided by AspectJ.
For the details, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative-aspectj
The way Spring handle the transaction through Annotation is using AOP as you've said.
The AOP bit is implemented using Dynamic Proxies (see doc)
So in order to do so you'll need to retrieve an instance of your class (Pojo here) through the spring container since to make it work, Spring will return you a Dynamic Proxy over your Pojo that will automatically surround any annotated method with the transaction management code.
If you simply do a
Pojo p = new Pojo();
p.doInTransaction();
Spring doesn't have any role to play here and your method call won't be inside a transaction.
so what you need to do is something like this
ApplicationContext springContext = ...;
Pojo p = (Pojo) springContext.getBean("your.pojo.id");
p.doInTransaction();
Note: this is an example, you should prefer dependency injection instead of retrieving your bean manually from the context
By doing so, and with a properly configured Spring Context, Spring should have lookout your classes to scan for transactional annotation and automatically wrapped your beans into annotation aware dynamic proxies instances. From your point of view that doesn't change anything, you'll still cast your object to your own Classes, but if you try to print out the class name of your spring context Pojo bean, you'll get something as Proxy$... and not your original class name.
Have a look at this link anyway : link text
Is JSR-303 also intended for method parameter validation?
If so, is there any example on the web? The biggest challenge I'm facing is how to get a validator within each method. With Spring 3, doesn't it mean that I'd have to inject virtually every class with a LocalValidatorFactoryBean?
Thanks!
Method level validation will be supported in the upcoming version 4.2 of JSR 303's reference implementation Hibernate Validator.
As pointed out in the previous answer this will allow constraint annotations (built-in as well as custom defined types) to be specified at method parameters and return values to specify pre- and post-conditions for a method's invocation.
Note that HV will only deal with the actual validation of method calls not with triggering such a validation. Validation invocation could be done using AOP or other method interception facilities such as JDK's dynamic proxies.
The JIRA issue for this is HV-347 [1], so you might want to add yourself as watcher to this issue.
[1] http://opensource.atlassian.com/projects/hibernate/browse/HV-347
The javadocs for each of the JSR 303 annotations tells the following:
#Target(value={METHOD,FIELD,ANNOTATION_TYPE,CONSTRUCTOR,PARAMETER})
See, PARAMETER is there. So, yes, it's technically possible.
Here's an example:
public void method(#NotNull String parameter) {
// ...
}
I'm however not sure how that integrates with Spring since I don't use it. You could just give it a try.
In Spring 3.1.0 you can use #Validated annotation to activate validation on a pojo.
Create an interface for the pojo class an put this annotation over it, then add your validation annotations in the methods definitions. ( the interface is required because Spring will create a proxy class using the interface as definition )
#Validated
public interface PojoClass {
public #NotNull String doSomething(#NotEmpty String input);
}
your pojo :
public class PojoClassImpl implements PojoClass {
public String doSomething(String input) {
return "";
}
}
Starting from a standard spring web application with active validation, remember to add in your spring configuration this bean declaration:
<bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor"/>
This sounds like a use case for AOP (AspectJ). Write a pointcut for methods that are annotated with javax.validation.constraints.*, inject a validator into the aspect (probably using Spring) and use a #Before or #Around advice to perform the validation before method execution.
Read AspectJ in Action for reference.
You can use jcabi-aspects (I'm a developer), which integrates JSR 303 with AspectJ. Actual validation is done by one of JSR 303 implementations, which you will have to add to class path, like Hibernate Validator, or Apache BVal.
I read few books on spring2.5 on these topic, but still cannot grab the concepts when to use #initBinder. can anyone share any reference or explain in what situation i can use this on web application? How propertyEditor relate to it?
Well I can't really put it any better than the books, but if your controller has any public methods annotated with #InitBinder, then these methods will be called by the container just before each request is processed, passing in the WebDataBinder being used by the framework.
The most common reason to do this is when you want to customise the way that Spring tries to bind request parameters on to your model, for example if your model has custom datatypes that Spring can't handle out of the box. You register your PropertyEditors against the WebDataBinder. A trivial example would be if you use the JodaTime library in your model, and you want to bind timestamp strings on to a Joda DateTime object.
With Spring 2.0, you use to have to override the protected initBinder() method from the controller superclass, but Spring 2.5 removes the need to do that, you can just use annotations now.
Another reason beside what skaffman mentioned, would be to set a custom validator on your WebDataBinder. What I will usually do is use JSR-303 bean validation, and then bind a validator that provides additional validation not provided by JSR-303.
Inside your controller:
#InitBinder
protected void initBinder(WebDataBinder webDataBinder) {
Validator validator = webDataBinder.getValidator();
webDataBinder.setValidator(new UserFormValidator(validator));
}
What I'm doing is taking in the bean validator, calling that inside my custom validator, and then calling my custom validations. Something like this:
public class UserFormValidator implements Validator {
private Validator validator;
public AuthUserFormValidator(Validator validator) {
this.validator = validator;
}
#Override
public boolean supports(Class<?> clazz) {
return UserForm.class.equals(clazz);
}
#Override
public void validate(Object target, Errors errors) {
// Run the bean validation...
validator.validate(target, errors);
// Do your custom validation on userForm here...
UserForm userForm = (UserForm) target;
// Validation on userForm...
}
}
It require Spring 2.5.1+
see https://jira.springsource.org/browse/SPR-4182