How to add spring editing into config files - spring

I am very new to spring. I saw some spring validations where the code was embedded into java source code. Im am trying to avoid this.
Is there a way to put the editing into the bean config file using properties.
For example #Size min=6 max=10 to
<bean id ="myvalidator"
class = "org.some.spring.class.blahblahblah"
<property name="min" value="6">
<property name="max" value="10">
<property name="errormsg" value=${error.msg}>
/>
or something to that effect
How do I associate #annotation to "com.some.spring.classname"

Validation annotations do not belong to Spring Framework, usually they come from the javax.validation package, sometimes, they come from a vendor, like hibernate ones for example. Check the import statement to be sure about that.
So if your purpose of trying to get rid of the annotations is to not being dependant on any frameworks, unless you are using vendor specific validation annotations you shouldn't worry.
But anyways, if you still want to get rid of the annotations in your code and don't use any validation framework, one way is to create a Validator class elsewhere, and then use Spring for inject it whenever it is needed.
Let's say for example (i'm going to use JavaConfig style, because i'm not very familiar with XML)
#Component
public class MyValidator {
// some validation code
}
In some configuration class
#Configuration
public class MyConfigurationClass {
#Bean
public MyValidator myValidator() {
return new MyValidator();
}
}
And now you can inject with #Autowire an instance of your validator whenever you need it.
Edit: Btw, in this scenario, validation code should be coded manually, that is the price to pay if you want to get rid of the annotations.

Related

How to get Spring Boot to create a bean validator before creating all the other beans

I'm trying to add a LocalValidatorFactoryBean to an existing Spring Boot web application.
No matter what I have tried (listed in a moment) it only creates the validator after most other beans (verified with both logging and breakpoints), so they never get validated.
Tangentially, I have hibernate-validator on the classpath and am attempting to use javax.validation.constraints on my #Component properties.
Application class has #Configuration, #EnableAutoConfiguration and #ComponentScan({"my.package.**"}).
Adding an application.xml with the bean <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
Adding the above bean to validator.xml and adding #ImportResource("validator.xml")
Adding a new #Bean to the Application class. public Validator validator() { return new LocalValidatorFactoryBean(); }
Adding #Order(Ordered.HIGHEST_PRECEDENCE) to the above #Bean
Adding a BeanValidator #Component to the scanned packages.
And adding #Order to it.
In all cases, the validator is loaded only after FilterRegistrationBean has finished logging its business, but the beans I want to validate have already been created and used in setting up data connections and security for example.
Its been a few years since I've used Spring, but I don't remember these problems when defining everything in an application.xml. Is this just something that spring-boot doesn't support and I should move back to traditional Spring application config?
How can I get it to validate all my beans?
I forgot to make a BeanValidationPostProcessor.

A bunch of questions on Spring 3 framework

Here are the questions resulted from reading the Spring Reference, please help.
(1) Do I ever need manual creation of ApplicationContext? Do I ever need second instance of AplicationContext?
(2) We have the following config instructions:
<context:annotation-config/>
<context:component-scan base-package=".."/>
<mvc:annotation-driven/>
Do these instructions duplicate theirselfs? In which cases yes, in which no?
(3) I am a bit stuck with all that ways Spring introduces to convert from string to object: PropertyEditor, Conversions, Formatting..
Here is a simple use case:
I have a Spring MVC controller that processes some POST request. That request is a result of filling some form. The form is a web representation of some entity.
So, given a the user submits a new Project form. In that form exist a date field and a manager's name field to be selected from the list of existing managers. The entered date should be converted to Date property of Project object, and manager's name - to Manager property, created or located by this name (i.e. I want to inject Manager into his Project). What should I use in this case? Property editors, formatters, something else?
(4) Generally, may I say that all the #interface classes that are found on classpath can be used by Spring as annotations?
In other words, how can I know which annotations can be used in my project? All that can be found in my classpath, or I need to register them somehow?
(5) I tried to use spring aop without aspectj.jar: just created an Aspect and addred XML definition for this aspect (without any annotations). As a result it throws "class not found Exception: org/aspectj/weaver/BCException".
So looks like I cannot use Spring AOP without aspectJ library?
(1) Do I ever need manual creation of ApplicationContext? Do I ever need second instance of AplicationContext?
Spring is typically usd in two environments - in web development and in desktop applications/standalone servers. In the former case the ApplicationContext is created automatically via ContextLoaderListener defined in web.xml or WebContextInitializer in Servlet 3.0 container.
In the latter case (standalone application) you are responsible for creating and destroying the application context.
(2) We have the following config instructions:
<context:component-scan base-package=".."/> provides all the functionality of <context:annotation-config/> plus (surprise!) component scanning. <mvc:annotation-driven/> is completely independent and it recognizes spring-mvc annotations like #Controller.
[...]The entered date should be converted to Date property of Project object[...]
Register custom editor within #Controller:
#Controller
public class FooController {
#InitBinder
public void binder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
public void setAsText(String value) {
try {
setValue(new SimpleDateFormat("yy-MM-dd HH:mm:ss").parse(value));
} catch (ParseException e) {
setValue(null);
}
}
});
}
}
[...]how can I know which annotations can be used in my project?[...]
I found this awesome annotations support sheet some time ago (I am not an author). It will tell you which annotations are enabled when.
All that can be found in my classpath
#Inject is enabled if it is found on the CLASSPATH, other annotations need to be enabled manually, see above.
So looks like I cannot use Spring AOP without aspectJ library?
You can use Spring without CGLIB if you only use interface proxies (i.e. you only apply aspects on classes implementing at least one interface). Otherwise you need CGLIB to dynamically create subclasses.

Spring #Configuration (non-xml configuration) for annotation-driven tasks

Can anyone explain how to do achieve a basic configuration of a task using the #Scheduled annotation without any XML configuration? All the examples I can find use at least a minimal XML configuration. For example:
http://blog.springsource.com/2010/01/05/task-scheduling-simplifications-in-spring-3-0/
This uses a typical:
<context:component-scan base-package="org/springframework/samples/task/basic/annotation"/>
<task:annotation-driven/>
So I'm just using a #Configuration annotation with a bunch of #Bean annotations. They are all instantiated at startup but the one with the #Scheduled does not run. I've used that annotation successfully in the past when using XML configuration, but never with annotations only.
Just add #EnableScheduling on you WebMvcConfig class
#Configuration
#EnableWebMvc
#EnableAsync
#EnableScheduling
public class WebMvcConfig extends WebMvcConfigurerAdapter {
/** Annotations config Stuff ... **/
}
The <task:annotation-driven /> annotation ends up declaring a ScheduledAnnotationBeanPostProcessor to read the #Scheduled annotations in your code. See here: http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/scheduling/annotation/ScheduledAnnotationBeanPostProcessor.html.
That takes care of the <task:annotation-driven /> line. To get the component scanning you'll need to use AnnotationConfigApplicationContext. Not sure if/how that works with a web container though.
In Spring 3.0, you still need that little bit of XML. However, Spring 3.1 (still in beta) introduces additional annotation options to close the gap, removing any need for XML config.
See this blog entry for how it's done. Be very careful before using beta versions of Spring in production code, though - they really are unstable.
The answers so far are all helpful for earlier versions of Spring.
Here's one that's a bit more tailored to Spring 4:
Assume that you have your main Application class annotated for Component scan like this:
#ComponentScan({"com.my.class"})
And inside of that package, you have a job class that looks like this:
#Configuration
#EnableScheduling
public class MyJobClass {
#Scheduled (cron = "* * * * * *")
public void runJob() throws DocumentException {
thingsToDoOnSchedule();
}
}
Note that the method that you annotate with #Scheduled must return void and that your cron expression needs to have 6 characters (the example shown here runs every second, which makes testing what your job does easier).
You also need the class level annotations of both #Configuration and #EnableScheduling to make this work. Either by themselves seems to get ignored.
For further reading here is the Spring 4 Enable Scheduling Reference Doc.

aspectj and spring with aspectj-autoproxy

I've declared my aspects using the #Aspect annotation, but the advice does not seem to get applied. The aspect works in a few other projects that I have, and the key difference seems to be that the other projects are completely wired using annotations, and this particular project is xml wired. The only bean that is annotation wired is the Aspect. So I'm wondering if spring's aspectj support, when using aspectj-autoproxy is sensitive to order that the beans are defined in the xml.
For example, will beans declared after aspectj-autoproxy in xml be considered for AOP pointcuts?
EDIT:
I moved the <aop:aspectj-autoproxy /> until after all beans are created and still no luck.
Basically my code consists of:
#Component
#Aspect
public class SomeAspect {
#Pointcut("#annotation(MyAnnotation)")
public void isX() {}
#After("isX()")
public void XX() {
System.out.println("Called aspect");
}
}
And my controller has something like:
public class XController extends AbstractCommandController {
#MyAnnotation
public void handleX(...) {
// do stuff
}
#Override
protected void handle(...) {
return handleX(...);
}
}
And then the spring xml is:
<context:component-scan base-package="package.of.some.aspect" />
<aop:aspectj-autoproxy />
<!-- the rest of the beans below -->
<bean id="someController" class="..." />
My previous projects captured and loaded all beans via the component-scan. That's what's different this time.
EDIT2:
The other difference is that the other projects are using #Controller, and #RequestMethod. And in this case I'm using a derived class of AbstractCommmandController. I'm wondering if this applies:
http://forum.springsource.org/archive/index.php/t-46637.html
Namely that I can't apply advice to any method except handleRequest().
EDIT3:
My latest try is to override handleRequest() and apply my annotation there. Under the assumption that when spring proxies my controller it will see the annotation and apply the advice, since it's calling through the public, externally called method. This still doesn't work.
I see that you are calling the method handleX directly from another method in the same class. This will not respect the annotiation, as the work of processing AOP annotations is done by a JDK proxy that wraps your class and exposes the same interfaces.
It's possible that you can work around this by using CGLIB instead of JDK proxies, but in my experience, the most reliable solution is just not to rely on any AOP annotations for methods called internally.

How to Inject Spring ReloadableResourceBundleMessageSource

In order to programmatically refresh the resource bundle cache, I am using Spring's ReloadableResourceBundleMessageSource. I am having trouble injecting it into my bean where I want to invoke the clearCache() method.
I've had to resort to the following:
private ReloadableResourceBundleMessageSource messageSource;
#Autowired
public void setMessageSource(MessageSource messageSource) {
this.messageSource = (ReloadableResourceBundleMessageSource((DelegatingMessageSource)messageSource).getParentMessageSource();
}
This works, but there must be a better way. The message resource is defined as follows:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames" >
<list>
<value>WEB-INF/content/Content</value>
</list>
</property>
</bean>
I don't understand why Spring is injecting a message source of type DelegatingMessageSource.
I don't think that autowiring by type will work in this case, as the autowire candidate will most likely be the ApplicationContext itself (see section 3.8.2 of the reference documentation). This leads to all those layers you have to dig through to get your original ReloadableResourceBundleMessageSource.
Try passing a reference to the messageSource bean via XML configuration instead. Annotating the property with #Qualifier('messageSource') should work as well.
You usually get the DelegatingMessageSource injected when Spring can't find "messageSource" defined. Are you sure you're defining it properly or that it's visible where necessary? I think the problem here is how the XML configuration has been setup.
I had a similar situation with Spring Web Flow and the form action stuff. In my XML configuration the "messageSource" wasn't visible and causing the DelegatingMessageSource to be injected. I placed the "messageSource" bean definition into the webflow configuration and then everything worked and I stopped getting the DelegationMessageSource object. However, this is an ugly fix since now I have "messageSource" defined in two places.
Anyway, this problem only started after I switched to Spring 2.5.6. I'm using Webflow 1. Once I have a chance I will try and update to Webflow 2 and see what happens. Maybe that will fix the issue.
have you tried to define the method as:
public void setMessageSource(ReloadableResourceBundleMessageSource messageSoure) {
this.messageSoure = messageSoure;
}
When you try to run it through messageSource in your controller, you get NOTHING, empty string. And if you look closely, you will find that you have a DelegatingMessageSource in your messageSource property, with an empty parent source, which means it is EMPTY, i.e. always returns blank and this exception occurs in controller
ReloadableResourceBundleMessageSource incompatible with org.springframework.context.support.DelegatingMessageSource
Read more..

Resources