Constructor injection and arrays with Spring - java

I would like to understand whether there is a clean way to use constructor injection with arrays in spring-boot (1.3.5.RELEASE).
I've created this simple app that better explains my question:
package com.stackoverflow;
import java.util.Arrays;
import java.util.stream.IntStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class Application {
private static class Car { }
#Bean
public Car[] cars() {
return IntStream.range(0, 10).mapToObj(i -> new Car()).toArray(Car[]::new);
}
#Component
private static class Road implements CommandLineRunner {
private final Car[] cars;
#Autowired
public Road(Car[] cars) {
this.cars = cars;
}
// #Resource
// private Car[] cars;
#Override
public void run(String... args) throws Exception {
System.out.println(Arrays.toString(cars));
}
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I understand that #Autowired works by type, so the reason why the previous application does not work is because when the Car[] has to be injected, Spring first tries to find all Car beans but, since there is no Car bean, the following exception is thrown:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'application.Road' defined in file [/spring-array-injection/target/classes/com/stackoverflow/Application$Road.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [com.stackoverflow.Application$Car[]]: No qualifying bean of type [com.stackoverflow.Application$Car] found for dependency [array of com.stackoverflow.Application$Car]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.stackoverflow.Application$Car] found for dependency [array of com.stackoverflow.Application$Car]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:185) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at com.stackoverflow.Application.main(Application.java:44) [classes/:na]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.stackoverflow.Application$Car] found for dependency [array of com.stackoverflow.Application$Car]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1044) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:813) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
... 19 common frames omitted
I also understand that if I replace the constructor injection with field injection + #Resource everything works because the array is injected by name instead of type.
So, am I missing something or is it a real spring limitation (i.e. it is currently not possible to use constructor injection with arrays/lists of object in spring)?
UPDATE 1
Wow, I thought this question had a shorter life but the case is not solved yet. I will post the two (ugly) workarounds I've tested so far:
A wrapper around the array is injected instead of the plain array:
package com.stackoverflow.workaround.arrayholder;
import java.util.Arrays;
import java.util.stream.IntStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class Application {
private static class ArrayHolder<T> {
private final T array;
public ArrayHolder(T array) {
this.array = array;
}
public T getArray() {
return array;
}
}
private static class Car { }
#Bean
public ArrayHolder<Car[]> cars() {
return new ArrayHolder<>(IntStream.range(0, 10).mapToObj(i -> new Car()).toArray(Car[]::new));
}
#Component
private static class Road implements CommandLineRunner {
private final Car[] cars;
#Autowired
public Road(ArrayHolder<Car[]> cars) {
this.cars = cars.getArray();
}
#Override
public void run(String... args) throws Exception {
System.out.println(Arrays.toString(cars));
}
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The beans are dynamically created and registered using the BeanFactoryPostProcessor:
package com.stackoverflow.workaround.dynamicregistration;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;
#SpringBootApplication
public class Application implements BeanFactoryPostProcessor {
private static class Car { }
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
AtomicInteger atomicInteger = new AtomicInteger();
IntStream.range(0, 10)
.mapToObj(i -> new Car())
.forEach(car -> beanFactory.registerSingleton(String.valueOf(atomicInteger.getAndIncrement()), car));
}
#Component
private static class Road implements CommandLineRunner {
private final Car[] cars;
#Autowired
public Road(Car[] cars) {
this.cars = cars;
}
#Override
public void run(String... args) throws Exception {
System.out.println(Arrays.toString(cars));
}
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Update 2
It turns out that constructor injection of arrays, collections and maps will be possible starting from Spring 4.3 (see issue).

As stated in the docs:
6.9.4 Fine-tuning annotation-based autowiring with qualifiers
If you intend to express annotation-driven injection by name, do not primarily use #Autowired, even if is technically capable of referring to a bean name through #Qualifier values. Instead, use the JSR-250 #Resource annotation, which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process.
As a specific consequence of this semantic difference, beans that are themselves defined as a collection or map type cannot be injected through #Autowired, because type matching is not properly applicable to them. Use #Resource for such beans, referring to the specific collection or map bean by unique name.
#Autowired applies to fields, constructors, and multi-argument methods, allowing for narrowing through qualifier annotations at the parameter level. By contrast, #Resource is supported only for fields and bean property setter methods with a single argument. As a consequence, stick with qualifiers if your injection target is a constructor or a multi-argument method.
And arrays are treated the same way as collections:
6.4.5 Autowiring collaborators
With byType or constructor autowiring mode, you can wire arrays and typed-collections. In such cases all autowire candidates within the container that match the expected type are provided to satisfy the dependency. You can autowire strongly-typed Maps if the expected key type is String. An autowired Maps values will consist of all bean instances that match the expected type, and the Maps keys will contain the corresponding bean names.
6.9.2 #Autowired
It is also possible to provide all beans of a particular type from the ApplicationContext by adding the annotation to a field or method that expects an array of that type: [...]
The same applies for typed collections: [...]
Even typed Maps can be autowired as long as the expected key type is String. The Map values will contain all beans of the expected type, and the keys will contain the corresponding bean names: [...]

Related

How to solve Unsatisfied Dependency Exception? Problem with Annotation Qualifiers

I trying to implemet a singleton design pattern in Spring. I am running in an error wwhen running my code.
my configuration file is:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan("springdemo3")
public class AppConfig {
}
I have created a service interface as follow:
package springdemo3;
public interface Service {
void doSomething();
}
I have created interface called Pump as follow;
public interface Pump {
void features();
}
Created two types of pumps electric and water pump both implementing pump interface, as follow:
package springdemo3;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
#Component
public class ElectricPump implements Pump{
#Override
#Primary
public void features() {
System.out.println("This pump is an "
+ "electric pump");
}
}
package springdemo3;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
#Component
public class WaterPump implements Pump{
#Override
public void features() {
System.out.println("This pump is pumping"
+ " water");
}
}
My serviceB bean is created as follow:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
#Component //This is a bean
public class ServiceB implements Service{
#Autowired
#Qualifier("electricpump")
private Pump mPump;
public Pump getMpump() {
return mPump;
}
public void setMpump(Pump mPump) {
this.mPump = mPump;
}
public void doSomething() {
System.out.println("We have a water"
+ " pump running here");
mPump.features();
}
}
While my main function is as follow:
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/*** Here I'm not using XML configuration and using Singleton Design Pattern */
public class SpringDemo3 {
public static void main(String[] args) {
ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
ServiceB mServiceB = context.getBean(ServiceB.class);
mServiceB.doSomething();
}
}
When I run it, I get the following error:
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'serviceB': Unsatisfied dependency expressed through field 'mPump'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'springdemo3.Pump' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier("electricpump")}
I'm trying to understand Spring Framework. Please note all these classes are in the same package. What is it that I'm doing wrong here?
But this worked
Please bear in mind that default naming convetion for spring beans is camel case, so in fact the proper name for your bean should be electricPump instead of electricpump. Then, you should be able to autowire the bean.
Other than that, field autowiring is not recommended as it makes unit testing of your service more difficult. Use constructor autowiring preferably.
Also, you've placed #Primary in the incorrect position, as it is the annotation which marks the bean to be the first preference for autowiring. It can be used on method level but it only makes sense when the method is defining a bean and is annotated with #Bean annotation as well.
As mentioned in my comment #Qualifier("electricpump") needed a capital P for Pump.
I created a branch and made a pull request to your project:
Restructured your project
Added a maven pom.xml (because I couldn't run your project)
Fixed the bean name 'electricPump'
Consider always using some project management tool. This way among other things, people can easily set up you project and help you out.

Getting Exception while creating beans using #Bean Spring annotation

I was trying to understand difference between #component and #Bean in Spring framework, and referred to this SO question.
Based on the answer, I got a fair understanding, and tried to reinforce the concept by implementing a simple example (to check whether I really understood the concept).
The below is the code which I wrote. I wanted to see #Bean for "third party" libs (so that it can be instantiated using #Bean annotation)
package com.example.thirdparty.code;
public class ThirdPartyUtil {
public ThirdPartyUtil() {
}
public void print(String str) {
System.out.println("String passed is --> " + str);
}
}
In above, I tried to simulate a "third party lib/class - NON spring" which isn't a spring based (and so there won't be any #component in that class.
Now, below is the main application which I created:
package com.example.spring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import com.example.thirdparty.code.ThirdPartyUtil;
#Configuration
#ComponentScan(basePackages = { "com.example.spring" })
#Component
public class SpringBasedMainApp {
#Autowired
private ApplicationContext ctx;
#Autowired
private static ThirdPartyUtil thirdPartyUtil;
#Bean
public ThirdPartyUtil beanThirdPartyUtil() {
try {
Class c = getClass().getClassLoader().loadClass("com.example.thirdparty.code.ThirdPartyUtil");
return (ThirdPartyUtil) ctx.getBean(c);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Exception");
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringBasedMainApp.class);
System.out.println("thirdPartyUtil is " + thirdPartyUtil);
}
}
I was hoping that using #Bean annotation, it would create ThirdPartyUtil as Spring bean, and then inject using #Autowired into field thirdPartyUtil.
However, when I run this program, I got altogether a surprising exception, listed below:
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'beanThirdPartyUtil' defined in com.example.spring.SpringBasedMainApp: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.thirdparty.code.ThirdPartyUtil]: Factory method 'beanThirdPartyUtil' threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanThirdPartyUtil': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:627)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:456)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:88)
at com.example.spring.SpringBasedMainApp.main(SpringBasedMainApp.java:41)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.thirdparty.code.ThirdPartyUtil]: Factory method 'beanThirdPartyUtil' threw exception; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanThirdPartyUtil': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622)
... 14 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'beanThirdPartyUtil': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:339)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:215)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:224)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1112)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:407)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:341)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:335)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1101)
at com.example.spring.SpringBasedMainApp.beanThirdPartyUtil(SpringBasedMainApp.java:33)
at com.example.spring.SpringBasedMainApp$$EnhancerBySpringCGLIB$$d93c67f4.CGLIB$beanThirdPartyUtil$0(<generated>)
at com.example.spring.SpringBasedMainApp$$EnhancerBySpringCGLIB$$d93c67f4$$FastClassBySpringCGLIB$$9349d69b.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
at com.example.spring.SpringBasedMainApp$$EnhancerBySpringCGLIB$$d93c67f4.beanThirdPartyUtil(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 15 more
I didn't understand why it is giving this exception. I am creating an applicationContext using AnnotationConfigApplicationContext and passing the necessary details to it.
I expected it to work, however got the above exception (which I have seen maiden time).
Why has this exception been thrown, is my understanding not correct about #Bean?
The goal of the #Bean annotation is to annotate a method whose responsibility is to create an object, that will then be registered as a bean by Spring.
But inside your method, you ask Spring (using ctx.getBean()) to give you the bean that you're currently creating. So you get that exception.
Here's what your methd should look like:
#Bean
public ThirdPartyUtil beanThirdPartyUtil() {
return new ThirdPartyUtil();
}
To extend #JB Nizet answer, instantiate your third party class in spring constructor like below.
#Autowired
private static ThirdPartyUtil thirdPartyUtil;
#Autowired
public SpringBean() {
this.thirdPartyUtil = new ThirdPartyUtil();
}

Spring Boot JSR-303/349 configuration

In my Spring Boot 1.5.1 application I'm trying to configure support of JSR-303 / JSR-349 validation.
I have added a following annotations #NotNull #Size(min = 1) to my method:
#Service
#Transactional
public class DecisionDaoImpl extends BaseDao implements DecisionDao {
#Override
public Decision create(#NotNull #Size(min = 1) String name, String description, String url, String imageUrl, Decision parentDecision, Tenant tenant, User user) {
...
}
}
I'm trying to invoke this method from my test, but it does not fail on the validation constraints.
This is my test and configs:
#SpringBootTest(classes = { TestConfig.class, Neo4jTestConfig.class })
#RunWith(SpringRunner.class)
#Transactional
public class TenantTest {
#Test
public void testCreateDecision() {
User user1 = userService.createUser("test1", "test1", "test1#test.com", null, null);
Tenant tenant1 = tenantDao.create("Tenant 1", "Tenant 1 description", false, user1);
// the following line should fail on the validation constraint because name parameter is null but it doesn't
final Decision rootDecision = decisionDao.create(null, "Root decision 1 description", null, tenant1, user1);
...
#Configuration
#ComponentScan("com.example")
#SpringBootApplication(exclude={Neo4jDataAutoConfiguration.class})
public class TestConfig {
}
What am I doing wrong and how to configure JSR-303 there ?
UPDATED
I have added
public Decision create(#Valid #NotNull #Size(min = 1) String name, String description, Decision parentDecision, Tenant tenant, User author) {
but it still doesn't work
I have added #Validated to my DecisionDaoImpl but it fails now with a following exception:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'decisionDaoImpl': Bean with name 'decisionDaoImpl' has been injected into other beans [criterionGroupDaoImpl,characteristicGroupDaoImpl,tenantDaoImpl] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:585)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
... 43 common frames omitted
I have also added #Lazy annotation in a places where I'm autowiring my DecisionDao but right now my test fails with a following exception:
javax.validation.ConstraintDeclarationException: HV000151: A method overriding another method must not alter the parameter constraint configuration, but method public com.example.domain.model.entity.decision.Decision com.example.domain.dao.decision.DecisionDaoImpl.create(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.Long,java.lang.Long,com.example.domain.model.entity.user.User) changes the configuration of public abstract com.example.domain.model.entity.decision.Decision com.example.domain.dao.decision.DecisionDao.create(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.Long,java.lang.Long,com.example.domain.model.entity.user.User).
at org.hibernate.validator.internal.metadata.aggregated.rule.OverridingMethodMustNotAlterParameterConstraints.apply(OverridingMethodMustNotAlterParameterConstraints.java:24)
at org.hibernate.validator.internal.metadata.aggregated.ExecutableMetaData$Builder.assertCorrectnessOfConfiguration(ExecutableMetaData.java:456)
Move your validation to interface, as follows:
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
public interface DecisionDao {
Decision create(#Valid #NotNull #Size(min = 1) String name,
String description, String url, String imageUrl);
}
Annotate your DecisionDaoImpl with #Validated, as follows:
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
#Service
#Validated
public class DecisionDaoImpl extends BaseDao implements DecisionDao {
#Override
public Decision create(String name,
String description, String url, String imageUrl) {
System.out.println(name);
return new Decision();
}
}
Modify your test case to verify for javax.validation.ConstraintViolationException using assertj or ExpectedException, as follows:
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import javax.validation.ConstraintViolationException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
#ContextConfiguration(classes = { TenantTest.Config.class })
#RunWith(SpringRunner.class)
public class TenantTest {
#Autowired
private DecisionDao decisionDao;
#Rule
public ExpectedException expectedException = ExpectedException.none();
#Test
public void testCreateDecisionUsingAssertj() {
assertThatExceptionOfType(ConstraintViolationException.class)
.isThrownBy(
() -> decisionDao.create(null,
"Root decision 1 description", null, null));
}
#Test
public void testCreateDecision() {
expectedException.expect(ConstraintViolationException.class);
decisionDao.create(null, "Root decision 1 description", null, null);
}
#Configuration
public static class Config {
#Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
#Bean
public DecisionDao decisionDao() {
return new DecisionDaoImpl();
}
}
}
Make sure you have hibernate-validator in your classpath along with #StanislavL answer:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
And an optional dependency for org.assertj.core.api.Assertions.assertThatExceptionOfType, as:
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>
For sample example, you can refer arpitaggarwal/jsr-303
You need #Valid annotation
Marks a property, method parameter or method return type for validation cascading.
Constraints defined on the object and its properties are be validated when the
property, method parameter or method return type is validated.
The constraint annotations are meant to applied to JavaBeans. See http://beanvalidation.org/1.0/spec/#constraintsdefinitionimplementation-constraintdefinition
You have the constraint annotation #NotNull, #Size, etc. applied within the DAO. You must create a Java Bean, e.g. "Person", that wraps those attributes (name, description, etc.), then pass "Person" as a parameter to the Controller method. If you need to use a DAO instead of a controller, it will need to be instrumented to perform the validation. You may be on your own in that regard with regard to AOP, etc., unless something has changed since this post: http://forum.spring.io/forum/spring-projects/container/82643-annotation-driven-jsr-303-validation-on-service-and-dao-tier
Update: Well, looks like it (method level validation JSR-349) is supported now see http://blog.codeleak.pl/2012/03/how-to-method-level-validation-in.html for an example, similar to Arpit's answer.
Updated title of question to reflect this latest JSR.

Extending a class throws UnsatisfiedDependencyException exception

I am new to building web services and I started using spring boot to build one. I created the following controller class
package controller;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import model.Time;
import service.FeedService;
#RestController
public class FeedController extends ScheduledThreadPoolExecutor{
public FeedController(int corePoolSize) {
super(corePoolSize);
// TODO Auto-generated constructor stub
}
int difference;
int a;
boolean schedule;
//static as the variable is accessed across multiple threads
#Autowired
static FeedService fs;
#RequestMapping(value="/test")
public String test(){
return "test";
}
#RequestMapping(value = "/schedule", method = RequestMethod.GET)
public int ScheduleFeed(#RequestParam(value = "difference",required = false) String y) throws InterruptedException, ExecutionException{
// if(y != null){
// difference = Integer.parseInt(y);
difference = 0;
NewScheduledThreadPoolTest.mymethod(difference);
return difference;
// }else{
// return -1;
// }
}
#RequestMapping(value = "/inquireSchedule", method = RequestMethod.GET)
public ResponseEntity<Time> RequestFeed(){
if(schedule == true){
schedule = fs.setFalse();
return new ResponseEntity<Time>(HttpStatus.OK);
}
return new ResponseEntity<Time>(HttpStatus.BAD_REQUEST);
}
//schedule the task to happen after a certain number of times
static class NewScheduledThreadPoolTest {
public static void mymethod(int difference, final String... args) throws InterruptedException, ExecutionException {
// creates thread pool with 1 thread
System.out.println("hello world");
final ScheduledExecutorService schExService = Executors.newScheduledThreadPool(2);
// Object creation of runnable thread.
final Runnable ob = new NewScheduledThreadPoolTest().new myclass();
// Thread scheduling ie run it after "difference" hours before and then after every 24 hours later on
schExService.scheduleWithFixedDelay(ob, difference, 24, TimeUnit.SECONDS);
// waits for termination for 30 seconds only
schExService.awaitTermination(30, TimeUnit.SECONDS);
// shutdown now.
schExService.shutdownNow();
System.out.println("Shutdown Complete");
}
class myclass implements Runnable{
#Override
public void run() {
try{
// the mechanism to give a positive feedback to the arduino service
fs.setTrue();
System.out.println("hello world");
}catch(Exception e){
System.out.println("task failed");
e.printStackTrace();
}
}}
}
}
Trying to run my web service causes it to throw the following exception:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'feedController' defined in file
[D:\Rishit\Java
workspaces\FeedNemo\target\classes\controller\FeedController.class]:
Unsatisfied dependency expressed through constructor parameter 0: No
qualifying bean of type [int] found for dependency [int]: expected at
least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations: {}; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [int] found for dependency [int]: expected at
least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations: {} at
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:189)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1143)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1046)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:776)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
~[spring-context-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
~[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:369)
[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:313)
[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1185)
[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
org.springframework.boot.SpringApplication.run(SpringApplication.java:1174)
[spring-boot-1.4.0.RELEASE.jar:1.4.0.RELEASE] at
com.example.DemoApplication.main(DemoApplication.java:17)
[classes/:na] Caused by:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type [int] found for dependency [int]: expected at
least 1 bean which qualifies as autowire candidate for this
dependency. Dependency annotations: {} at
org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1406)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1057)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1019)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] at
org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
~[spring-beans-4.3.2.RELEASE.jar:4.3.2.RELEASE] ... 19 common frames
omitted
However, If I remove the "ScheduledThreadPoolExecutor" and the constructor, it runs fine. Can someone please explain what is the problem with extending the class?
Note:
1) Extending the class was suggested in the below mentioned post as a solution to my initial problem. Initially, my runnable was not running without any sort of notification or error message
2) The below post makes use of abusive language. However this was the only one that provided a solution to my initial problem. The initial problem is specified just to give a clarity of why I extended the above class and may not be directly related to my current problem. Please do not open if you find such language offensive.
http://code.nomad-labs.com/2011/12/09/mother-fk-the-scheduledexecutorservice/
Do not make bean members static. The fact that they're referenced from multiple threads is irrelevant; it's Spring's job to make sure that the dependencies are populated.
Also, prefer constructor injection to field injection; it makes these sorts of issues dramatically less likely.

Spring - trouble with injecting validator bean

i couldn't find solution for my problem anywhere.
I'm trying to make validation working in spring web flow form. I need to
set validator in configuration, however it's located in another config file
and it seems spring can't find proper bean. How can I achieve successful injection here?
As far as I know, Autowiring should inject bean into validator reference.
Maybe it has something to do with order of loading configuration classes?
WebConfig.java:
#Configuration
#Import(godziszewski.patryk.ElectronicsStore.config.FlowConfiguration.class)
#EnableWebMvc
#ComponentScan(basePackages = "godziszewski.patryk")
public class WebConfig extends WebMvcConfigurerAdapter {
....
#Bean
public LocalValidatorFactoryBean validator()
{
LocalValidatorFactoryBean lv = new LocalValidatorFactoryBean();
lv.setValidationMessageSource(messageSource());
return lv;
}
}
FlowConfiguration.java:
#Configuration
public class FlowConfiguration extends AbstractFlowConfiguration {
#Autowired
Validator validator;
....
#Bean
public FlowBuilderServices flowBuilderServices()
{
FlowBuilderServices fbs = new FlowBuilderServices();
fbs.setValidator(validator);
return fbs;
}
}
The error i'm getting:
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'flowConfiguration':
Unsatisfied dependency expressed through field 'validator':
No qualifying bean of type [org.springframework.validation.Validator] found for dependency [org.springframework.validation.Validator]:
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)};
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [org.springframework.validation.Validator] found for dependency [org.springframework.validation.Validator]:
expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Im using spring 4.3.2.RELEASE
However, when I delete Validator dependency from FlowAdapter.class I get error :
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flowBuilderServices' defined in class path resource [godziszewski/patryk/ElectronicsStore/config/FlowConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: The ViewFactoryCreator is required
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:381)
at godziszewski.patryk.ElectronicsStore.config.FlowConfiguration$$EnhancerBySpringCGLIB$$b65e14d6.flowBuilderServices(<generated>)
at godziszewski.patryk.ElectronicsStore.config.FlowConfiguration.flowRegistry(FlowConfiguration.java:25)
at godziszewski.patryk.ElectronicsStore.config.FlowConfiguration$$EnhancerBySpringCGLIB$$b65e14d6.CGLIB$flowRegistry$3(<generated>)
at godziszewski.patryk.ElectronicsStore.config.FlowConfiguration$$EnhancerBySpringCGLIB$$b65e14d6$$FastClassBySpringCGLIB$$e5741e7e.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:356)
at godziszewski.patryk.ElectronicsStore.config.FlowConfiguration$$EnhancerBySpringCGLIB$$b65e14d6.flowRegistry(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)
... 24 more
Caused by: java.lang.IllegalArgumentException: The ViewFactoryCreator is required
Full FlowConfiguration class code, maybe I'm doing something wrong?
package godziszewski.patryk.ElectronicsStore.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.Validator;
import org.springframework.webflow.config.AbstractFlowConfiguration;
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
import org.springframework.webflow.executor.FlowExecutor;
import org.springframework.webflow.mvc.servlet.FlowHandlerAdapter;
import org.springframework.webflow.mvc.servlet.FlowHandlerMapping;
#Configuration
public class FlowConfiguration extends AbstractFlowConfiguration {
#Bean
public FlowDefinitionRegistry flowRegistry() {
return getFlowDefinitionRegistryBuilder()
.setBasePath("/WEB-INF/flows")
.setFlowBuilderServices(flowBuilderServices())
.addFlowLocationPattern("/**/*-flow.xml")
.build();
}
#Bean
public FlowExecutor flowExecutor() {
return getFlowExecutorBuilder(flowRegistry()).build();
}
#Bean
public FlowHandlerMapping flowHandlerMapping()
{
System.out.println("flowconfig");
FlowHandlerMapping fh = new FlowHandlerMapping();
fh.setFlowRegistry(flowRegistry());
return fh;
}
#Bean
public FlowHandlerAdapter flowHandlerAdapter()
{
FlowHandlerAdapter fh = new FlowHandlerAdapter();
fh.setFlowExecutor(flowExecutor());
return fh;
}
#Bean
public FlowBuilderServices flowBuilderServices()
{
FlowBuilderServices fbs = new FlowBuilderServices();
//fbs.setValidator(validator);
return fbs;
}
}
If i delete .setFlowBuilderServices(flowBuilderServices()) method, everything works fine
EDIT: I managed to get this working by deleting #Configuration annotation form flow config class, now it looks like this:
//#Configuration
public class FlowConfiguration extends AbstractFlowConfiguration {
#Autowired
Validator validator;
...
#Bean
public FlowBuilderServices flowBuilderServices()
{
System.out.println(validator.toString());
FlowBuilderServices fbs = new FlowBuilderServices();
fbs.setValidator(validator);
return fbs;
}
And now I can use injected LocalValidatorBean in this class.
I interpret that eventually you need a FlowBuilderServices which has a reference to Validator bean.
This can be achieved by using the Autowired tag inside FlowBuilderServices
public class FlowBuilderServices{
#Autowired
Validator validator
...
}
And then in FlowConfiguration you just need to define the bean
#Bean
public class FlowBuilderServices flowBuilderServices()
{
FlowBuilderServices fbs = new FlowBuilderServices();
return fbs;
}

Categories