Play Framework with Spring, #Transactional not working - spring

I'm using Play Framework (2.2.2) in combination with Spring (using this template: https://github.com/jamesward/play-java-spring).
If I annotate the Application Controller with #Transactional it's working fine:
#org.springframework.stereotype.Controller
#Transactional
public class Application {
// ...
}
However, if I also extend from Play's Base Controller I get the following error:
[NoSuchBeanDefinitionException: No qualifying bean of type [controllers.Application] is defined]
Code:
#org.springframework.stereotype.Controller
#Transactional
public class Application extends play.mvc.Controller{
// ...
}
So for some reason the #TransactionalAnnotation combined with extends play.mvc.Controller leads to a NoSuchBeanDefinitionException.
Using either #Transactional OR extends play.mvc.Controller (not both combined) and Spring can instantiate the controller bean just fine.
How can I make them both work together?
This is the full stackstrace:
play.api.Application$$anon$1: Execution exception[[NoSuchBeanDefinitionException: No qualifying bean of type [controllers.Application] is defined]]
at play.api.Application$class.handleError(Application.scala:293) ~[play_2.10.jar:2.2.2]
at play.api.DefaultApplication.handleError(Application.scala:399) [play_2.10.jar:2.2.2]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.2]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.2]
at scala.Option.map(Option.scala:145) [scala-library.jar:na]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2.applyOrElse(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.2]
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [controllers.Application] is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:296) ~[spring-beans.jar:3.2.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1125) ~[spring-context.jar:3.2.3.RELEASE]
at Global.getControllerInstance(Global.java:21) ~[na:na]
at play.core.j.JavaGlobalSettingsAdapter.getControllerInstance(JavaGlobalSettingsAdapter.scala:46) ~[play_2.10.jar:2.2.2]
at Routes$$anonfun$routes$1$$anonfun$applyOrElse$1$$anonfun$apply$1.apply(routes_routing.scala:57) ~[na:na]
at Routes$$anonfun$routes$1$$anonfun$applyOrElse$1$$anonfun$apply$1.apply(routes_routing.scala:57) ~[na:na]

Actually the controller itself should not be transactional, as transactionality is a concern of the service layer and not the presentation/web layer or the repository layer.
There are several reasons for this, for example the controller layer might trigger several business transactions. It's possible to make a controller transactional but it's not recommended practice, if you move the #Transactional annotation from the controller to the #Service layer, it will surely work.

Related

#ConditionalOnBean not work for spring boot test

Hy everyone! I'm trying to solve the problem for a very long time.
There is very simple spring boot test
public class ApplicationTest {
#Test
void testContext() {
SpringApplication.run(Application.class);
}
}
And several beans...
#Service
#ConditionalOnBean(CommonService.class)
#RequiredArgsConstructor
public class SimpleHelper {
...
#Service
#RequiredArgsConstructor
#ConditionalOnBean(CommonFeignClient.class)
public class CommonService {
...
#FeignClient(
name = "CommonClient",
url = "localhost:8080"
)
public interface CommonFeignClient {
And the main class look as
#SpringBootApplication
#EnableFeignClients(clients = AnotherFeignClient.class)
public class Application {
When the spring application starts everything works ok. SimpleHelper does not created.
But in the spring boot test throw the exception:
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'simpleHelper' defined in URL [...]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'foo.bar.CommonService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Please help, I don't understand what's going on anymore =)
Spring boot version is 2.3.0.RELEASE.
To use #ConditionalOnBean correctly, CommonService needs to be an auto-configuration class or defined as a bean by an auto-configured class rather than a service that's found by component scanning. This ensures that the bean on which CommonService is conditional has been defined before the condition is evaluated. The need for this is described in the annotation's javadoc:
The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only. If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after.

Spring Data: Can't Autowire #Repository JpaRepository Interface: "expected at least 1 bean which qualifies as autowire candidate"

My question is almost identical to this one but not the same, because I'm NOT using Spring Boot.
Can't Autowire #Repository annotated interface in Spring Boot
So I can't do #EnableJpaRepositories there's no Spring Boot Runner in my case. I have SpringMVC Controllers inside a Web app.
I'm using Spring Data independently, in a regular old-school SpringMVC application.
I'm getting the error
Caused by: No qualifying bean of type 'com.myapp.dao.QuestionsDAO' available:
expected at least 1 bean which qualifies as autowire candidate.
DAO Interface for Spring Data, note #Repository:
#Repository
public interface QuestionsDAO extends JpaRepository<Question, Long> {
public String findById(Long id);
}
A Service should then use this DAO, autowired:
Component
public class SchedulingService {
#Autowired
QuestionsDAO questionsDAO;
public String findLabelById(Long id) {
return questionsDAO.findById(id);
}
}
Component Scan is enabled, works for everything else.
<context:component-scan base-package="com.myapp" />
Is Spring Data only allowed with Spring Boot?
The annotation #EnableJpaRepositories comes from Spring Data, it has nothing to do with Spring Boot. So it would be enough, to have one class annotated with #Configuration and #EnableJpaRepositories.
If you want to do it in XML, you have to add
<jpa:repositories base-package="com.acme.repositories" />
You also don't need the #Repository annotation on your interfaces, that annotation has another purpose.

BeanCurrentlyInCreationException when spring starts

I am getting the BeanCurrentlyInCreationException when I start my spring application.
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.datayes.bdb.rrp.business.service.impl.StockModelBaseService com.datayes.bdb.rrp.business.service.impl.StockModelV3ServiceImpl.stockModelBaseService; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'stockModelBaseService': Bean with name 'stockModelBaseService' has been injected into other beans [researchFrameworkCommonServiceImpl] 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.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:561)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 71 more
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'stockModelBaseService': Bean with name 'stockModelBaseService' has been injected into other beans [researchFrameworkCommonServiceImpl] 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:568)
And here are the code snippets I have found caused this issue:
#Component public class KafkaConsumerServer implements MessageListener<String, String> {
#Autowired StockModelV3Service stockModelV3Service;
#Autowired FinanceIndicatorService financeIndicatorService;
......
}
#Service public class FinanceIndicatorServiceImpl implements FinanceIndicatorService {
#Autowired StockModelV3Service stockModelV3Service;
#Autowired IndustryResearchFrameworkService industryResearchFrameworkService;
......
}
#Service public class IndustryResearchFrameworkServiceImpl implements IndustryResearchFrameworkService {
#Autowired ResearchFrameworkCommonService commonService;
......
}
#Service public class ResearchFrameworkCommonServiceImpl implements ResearchFrameworkCommonService {
#Autowired StockModelBaseService stockModelBaseService;
......
}
I found some thing interesting in the following article may have explained why.
https://blog.imaginea.com/spring-bean-creation-is-not-thread-safe/
As both my StockModelV3Service and FinanceIndicatorService depends on stockModelBaseService(FinanceIndicatorService -> industryResearchFrameworkService -> researchFrameworkCommonService -> stockModelBaseService), during spring bean creation, they have raced against each other. Which caused BeanCurrentlyInCreationException. As the above article noted, spring bean creation is not thread safe.
To solve this problem seems easy. I changed autowire order as below:
public class KafkaConsumerServer implements MessageListener<String, String> {
#Autowired FinanceIndicatorService financeIndicatorService;
#Autowired StockModelV3Service stockModelV3Service;
As FinanceIndicatorService also depends on StockModelV3Service, so when financeIndicatorService is loaded, it will wait till stockModelV3Service is loaded then load itself. Thus avoid BeanCurrentlyInCreationException.
After all, it has nothing to do with circular reference. As StockModelBaseService doesn't depends on other services.

#Autowired not working for interface

I am trying all the solutions from Google from last 4 days. but not working.
I am trying to autowire below Interface -
#Qualifier("roleAccessRepository")
#Repository
public interface RoleAccessRepository extends BaseJPACrudRepository<RoleAccess, Long> {
in PermissionEvaluator in following way.But its not working.
#Scope(proxyMode = ScopedProxyMode.INTERFACES, value = "prototype")
public class PermissionEvaluator implements org.springframework.security.access.PermissionEvaluator
{
#Autowired
RoleAccessRepository roleAccessRepository;
..........
Giving me error -
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: net.pa
ger.lrs.sql.db.RoleAccessRepository net.pager.lrs.security.PermissionEvaluator.roleAccessRepository;
nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying
bean of type [net.pager.lrs.sql.db.RoleAccessRepository] found for dependency: expected at least 1 b
ean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springf
But Repository defined in the same package and autowired in service class are working good.
#Service
#Transactional
public class AccountService extends BaseCrudService<Account> {
/** The account db. */
#Autowired
private AccountRepository accountDB;
}
My security.xml is as follows - which has base package net.pager.lrs which is parent directory.
<bean id="permissionEvaluator" class="net.pager.lrs.security.PermissionEvaluator">
<constructor-arg index="0">
Please help me.
Ok,
From the discussions above, I still think that the problem is with not having the concrete implementation of the Autowired interfaces. Just for the sake of common sense, if you do not provide an implementation, what will you execute using the reference of the Autowired interface.
There is a way where you do not define the implementation, spring can generate proxy beans and autowire, but that is of no use.
You might end up providing an anonymous implementation of the interface as well.

Dependency Injection in JSR-303 ConstraintValidator

I have the same problem that the guy from this thread has.
More precisely I get the following error, when trying to inject a bean in my custom validator that implements CustomValidator interface (it's a NPE when accessing the bean i wanted to inject):
javax.validation.ValidationException: HV000028: Unexpected exception during isValid call.
at org.hibernate.validator.internal.engine.ConstraintTree.validateSingleConstraint(ConstraintTree.java:294)
at org.hibernate.validator.internal.engine.ConstraintTree.validateConstraints(ConstraintTree.java:164)
at org.hibernate.validator.internal.engine.ConstraintTree.validateConstraints(ConstraintTree.java:125)
at org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:86)
...
Caused by: java.lang.NullPointerException
Do you have a solution for this? Maybe an example? Because I tried the solutions offered on the other thread and nothing worked.
Any help is appreciated. Thanks.
You should not create validator factory on your own (Validation.buildDefaultValidatorFactory()) if you want to use Spring based constraint validators.
You should let Spring autowire correct factory to your bean:
#Controller
public class MyController {
#Autowired
private ValidatorFactory validatorFactory;
// ... handler methods
}

Resources