I have an annotation based Spring web application controller which maps XML to an annotated plain old java object. Exemplary code as follows:
#Controller
#RequestMapping("/")
public class Endpoint {
#RequestMapping
public void send(...) {
...
}
...
The mapping is automatically done via Jaxb2RootElementHttpMessageConverter and at the moment it is possible to reference and replace content in the received XML.
My question is, is it possible -- for example via beans.xml -- to configure the Jaxb2RootElementHttpMessageConverter such that the replacement of entities is prevented?
The converter is automatically created by Spring.
If you want to overwrite a bean created by spring you just define your own bean of the same type. Additionally you can mark it #Primary. I haven't tried it with Jaxb2RootElementHttpMessageConverter, but it worked with ObjectMapper as described here :
http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper
Related
I'm looking at code in which I'm assuming spring decides to use Jackson behind the scenes to auto convert an object to json for a #RestController
#RestController
#RequestMapping("/api")
public class ApiController {
private RoomServices roomServices;
#Autowired
public ApiController(RoomServices roomServices) {
this.roomServices = roomServices;
}
#GetMapping("/rooms")
public List<Room> getAllRooms() {
return this.roomServices.getAllRooms();
}
}
The Room class is just a plain java class with some fields, getters/setters. There is no Jackson or any other explicit serialization going on in the code. Although this does return json when checking the url. I tried looking through the spring documentation but I'm not quite sure what I'm looking for. What is the name for this process in spring / how does it work? I tried with just #Controller and it broke. Is this functionality coming from #RestController?
If you are using Spring Boot Starter Web, you can see that it's using Spring Boot Starter JSON through the compile dependencies, and Jackson is the dependency of the Start JSON library. So, you're assumption is right (Spring is using Jackson for Json convertion by default)
Spring use it's AOP mechanism to intercept the mapping methods in #Controller (you can see that #RestController is actually a #Controller with #ResponseBody), spring create a proxy object (using JDK proxy or through cglib) for the class that annotated with #Controller.
When the request flow is processing, the program who really call the mapping method will be lead to the proxy first, the proxy will invoke the real #Controller object's method and convert it's returning value to Json String using Jackson Library (if the method is annotated with #ResponseBody) and then return the Json String back to the calling program.
I have a collection of classes which I want to be injected into the Spring application context. However, these classes can only be guaranteed to be annotated with one of a group of annotations I have written - i.e. I can assume it will be annotated with #MyAnnotation, but not #Component.
However, #MyAnnotation forms part of an API for my project, and I don't want to state an explicit dependency of this API on Spring. Thus, I can't annotate #MyAnnotation with #Component in order to have it be transitively picked up by Spring.
Is there a way to tell Spring to additionally include #MyAnnotation in its classpath scanning without adding this dependency to my API?
Currently I'm manipulating the bean definition registry to 'manually' add each class annotated with #MyAnnotation, but I'd prefer to rely on Spring's inbuilt support.
Thanks in advance.
It's possible if you create your own BeanDefinitionRegistryPostProcessor to register your own beans. If you implement the postProcessBeanDefinitionRegistry method, you can add beans to the registry by yourself, for example:
#Component
public class FooFactoryBean implements BeanDefinitionRegistryPostProcessor {
#Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
registry.registerBeanDefinition(..);
}
}
To obtain these bean definitions, you can use the ClassPathScanningCandidateComponentProvider class, which will create BeanDefinition objects for all classes found for a specific filter. In this case, an AnnotationTypeFilter will work:
ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
scanner.addIncludeFilter(new AnnotationTypeFilter(Foo.class));
Set<BeanDefinition> definitions = scanner.findCandidateComponents("com.example.my");
In this example, it will find all classes annotated with #Foo in the com.example.my package.
#Configuration classes and XML based configuration should work for you. Have a look at this tutorial: https://www.tutorialspoint.com/spring/spring_java_based_configuration.htm
But to get your #MyAnnotations picked up is more difficult (see #g00glen00b's answer), and I'm not sure it makes sense if the above mentioned solutions are available.
I have a custom annotation that is declared as a Spring managed Service:
#Service
public #interface MyServiceAnnotation {
// my service url
String url();
}
The above declaration enables my services to be autowired as Spring Managed beans.
#MyServiceAnnotation(url="/path/serviceLocation")
public class SomeService {
doWork();
}
However, there are certain services that have their bean definitions in an applicationContext.xml. Adding the #MyServiceAnnotation to such beans makes them both Autowiring enabled, as well as inject dependecy through the xml file.
Due to issues related to legacy code, I don't want to remove the xml bean definitions and make them all autowired.
So, is there a way in which I could turn off autowiring in this case, and still use #MyServiceAnnotation? Ideally I would like to have the #Service annotation on MyServiceAnnotation, the existing services would still use the #MyServiceAnnotation but would get their dependencies injected based on the xml. All the new services would be autowired without the xml bean definitions.
One possible approach is to create NonSpringManagedMyServiceAnnotation that is same as MyServiceAnnotation, but without the #Service annotation on it. The downside of this is that I'd have to duplicate rest of the code from MyServiceAnnotation, which I don't want to.
This is one approach, may not be that optimal though. I am assuming you would have specified a component-scan tag in your xml to scan the classes having the Spring stereotype annotations, these tags support a exclude-filter sub-tag to ignore specific patterns. If the files that you specify follow a specific pattern(specific packages, specific names etc) then you may simply be able to specify this sub-tag to ignore classes holding your annotation.
<context:component-scan base-package="mypackage">
<context:exclude-filter type="regex" expression=".*ToBeIgnoredNaming"/>
</context:component-scan>
I think you should try to maintain separation of concern.
Adding #Service on your annotation makes it a de facto Spring service : since this is not the behavior you want, you may simply have a simple #MyAnnotation (with url property) on each services (legacy and new).
Then you add Spring's #Service annotation on each new service to enable bean registration by annotation.
I am having bean AddressBean, which has some properties like addressLine1, city etc.
Before persisting it to DB using AddressBeanService, I am prevalidating it, and after saving, i am post validating it, using preValidate and postValidate function in ValidateAddressService. And all this i am triggering from a AddressBeanHelper class.
class AddressBeanHelper{
AddressBean bean =null;
AddressBeanHelper(AddressBean bean){
this.bean=bean;
}
ValidationService validate=new ValidateAddressService();
function doStuff(){
validate.preValidateAddressBean (bean);
//business logic for AddressBean
validate.preValidateAddressBean (bean);
}
}
class ValidateAddressService implements ValidationService <AddressBean>{
preValidateAddressBean (AddressBean bean){
//here is the issue
}
preValidateAddressBean (AddressBean bean){
//here is the issue
}
}
I want some framework or trick in spring by which i just need to write generic code in validation functions and externalize my validation rule outside the code itself.
Like a rule engine which can automatically validates each and every property of bean.
currently my application infrastructure is spring/hibernate for server side, jsp/jquery on client side and deployment server is on heroku.
Have a look at this one:
http://hillert.blogspot.com/2011/12/method-validation-with-hibernate.html
It supports JSR-303, so its a standard. Its very easy to implement, and it supports, custom and some predefined ready to use validators.
You can also find some references here:
http://java.dzone.com/articles/method-validation-spring-31
I'm writing a web app with Java & Spring 2.5.6 and using annotations for bean validation. I can get the basic annotation validation working fine, and Spring will even call a custom Validator declared with #Validator on the target bean. But it always instantiates a brand new Validator object to do it. This is bad because the new validator has none of the injected dependencies it needs to run, and so it throws a null pointer exception on validate. I need one of two things and I don't know how to do either.
Convince Spring to use the validator I have already configured.
Convince Spring to honor the #Autowired annotations when it creates the new validator.
The validator has the #Component annotation, like this.
#Component
public class AccessCodeBeanValidator implements Validator {
#Autowired
private MessageSource messageSource;
Spring finds the validator in the component scan, injects the autowired dependencies, but then ignores it and creates a new one at validation time.
The only thing that I can do at the moment is add a validator reference into the controller for each validator object and use that ref directly, instead of relying on the bean validation framework to call the validator for me. It looks like this.
// first validate via the annotations on the bean
beanValidator.validate(accessCodeBean, result);
// then validate using the specific validator class
acbValidator.validate(accessCodeBean, result);
if (result.hasErrors()) {
If anyone knows how to convince spring to use the existing validator, instead of creating a new one, or how to make it do the autowiring when it creates a new one, I'd love to know.
Edit:
Here is the code that tells spring what validator to use for the bean.
#Validator(AccessCodeBeanValidator.class)
public class AccessCodeBean {
It works, but is limited as described above.
And so, currently, I have the #Validator line commented out and instead I'm autowiring the validator to the controller like this.
#Resource(name="accessCodeBeanValidator")
public void setAcbValidator(Validator acbValidator) {
this.acbValidator = acbValidator;
}