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
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");
}
}
I'm trying to add a GraphQLServlet to my existing webservice using graphql-spqr.
I have added the correct annotations and now only need to setup the GraphQL endpoint, which is where I am struggling.
All tutorials and google results that I found are referring to deprecated constructors for the class graphql.servlet.SimpleGraphQLServlet
I can create a servlet object like this:
UserService userService = new UserService();
GraphQLSchema schema = new GraphQLSchemaGenerator()
.withOperationsFromSingleton(userService)
.generate();
graphql.servlet.GraphQLServlet servlet = new Builder(schema).build();
But I can't figure out if and how you can register a servlet instance.
And search engines either misinterpret my search or come up empty.
I'm grateful for any pointers.
Using Servlet 3+, you can dynamically register the servlet. This is what I did for the exact same reason (I didn't want to use deprecated constructors).
#WebListener
public class GraphQLServletRegistrationServletContextListener implements ServletContextListener {
private GraphQLSchema schema;
public GraphQLServletRegistrationServletContextListener() {}
#Inject
public GraphQLServletRegistrationServletContextListener(final GraphQLSchema schema) {
this.schema = schema;
}
#Override
public void contextInitialized(final ServletContextEvent event) {
final ServletRegistration.Dynamic dynamicGraphQLServlet
= event.getServletContext().addServlet("GraphQLEndpoint", SimpleGraphQLServlet.create(schema));
dynamicGraphQLServlet.addMapping("/graphql");
}
#Override
public void contextDestroyed(final ServletContextEvent event) {}
}
I'm using CDI to inject the GraphQLSchema, but you can just ignore that and construct it manually any way you like.
UPDATE: As of graphql-java-servlet 6.x, this answer seems to be out of date
Unless you're using Spring, it's actually quite difficult to register a servlet instance yourself (and there's no standard way to do this), as the Servlet spec never really intended it to be used this way (the container is expected to take care of instantiating the servlets). And if you are using Spring, creating a servlet is unnecessary anyway. For this reason, using the SimpleGraphQLServlet is often unintuitive and inconvenient.
One way you can go about it is to subclass the SimpleGraphQLServlet, and let the container instantiate it for you as intended:
#WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends SimpleGraphQLServlet {
public GraphQLEndpoint() {
super(schema());
}
private static GraphQLSchema schema() {
UserService userService = new UserService();
GraphQLSchema schema = new GraphQLSchemaGenerator()
.withOperationsFromSingleton(userService)
.generate();
return schema;
}
}
You can also register GraphQLEndpoint the old-school way via web.xml.
You'll notice that you need to inline the entire setup as the call to super has to be the very first thing the constructor calls. This is what makes SimpleGraphQLServlet so inconvenient.
Another option is create your own servlet instead. There's really not that many things you need to do immediately. Just create the schema in its init method (no weird inline setup needed), store it in an instance field, and accept queries in doGet or doPost. There's of course the matter of handling errors, different URLs etc, which is a bit more complicated, but you don't need it right away for learning the basics.
You might also want to use a full-fledged framework, like Spring MVC or Boot. You can find an example of this in graphql-spqr samples.
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.
I have a servlet that does validation on XML files based on the address of the person contained in it. The validation is specific to each state, so I have several implementations of my validator, but I don't know which one to use until the request is parsed each time.
I am using Spring, and right now I am getting the correct validator with the following:
Validator validator = applicationContext.getBean(this.state + "Validator");
This seems to break some of the inversion of control. I thought about moving this to a factory class that essentially does the same thing, but abstracts it to a factory:
#Component
public class ValidatorFactory {
#Autowired
ApplicationContext applicationContext;
public Validator getValidator(String state) {
return applicationContext.getBean(state + "Validator");
}
}
It seems like there should be a better way to get the correct bean at runtime without using getBean(). Does anyone have any suggestions?
You can use a Map :
#Component
public class ValidatorFactory {
#Autowired
Map<String,Validator> validators;
public Validator getValidator(String state) {
return validators.get(state + "Validator");
}
}
You can pre-populate the map with the required beans throughs Spring.
I'm new to Spring AOP (and AOP in general), need to implement the following:
#HasPermission(operation=SecurityOperation.ACTIVITY_EDIT, object="#act")
public Activity updateActivity(Activity act)
{
...
}
#HasPermission is my custom annotation, which will be used to mark all methods requiring pre-authorization. I'm using my custom implementation of security checks based on Apache Shiro. Generally, I guess that I will need to define pointcut which matches all annotated methods and also provide implementation of the aspect (either before or around).
Questions I have are re. aspect implementation.
How do I extract operation and object parameters from the annotation?
How can I resolve SpEL expression in object definition and get object passed as 'act' parameter?
I know it's a late answer but after we were migrating some JavaEE project to Spring we made some basic security model based on AspectJ:
Firstly we annotate our service methods with custom #OperationAuthorization :
#OperationAuthorization
public ListOfUserGroupsTo getUserGroupsByClientId(Integer clientId) throws GenericException {
return userGroupRepository.getAllUserGroupsForClient(clientId);
}
Then we have a class with #Aspect & #Component annotations which intercepts methods with specific annotations:
#Aspect
#Component
public class AuthorizationAspect {
#Autowired
AuthorizationService authorizationService;
#Before(value = "#annotation(ch.avelon.alcedo.authorization.annotations.OperationAuthorization)")
public void before(JoinPoint joinPoint) throws Throwable {
Object[] args = joinPoint.getArgs();
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
authorizationService.checkOperationAuthorization(method, args);
}
In AuthorizationService a method with all arguments are passed. Check whether the client is authorized to get user groups. If it's not: throw our Exception and method stops.