No transactional EntityManager available; - spring

My app using spring and jpa, i have two config file:
AppConfig:
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = { "com.test.api" })
#EnableJpaRepositories("com.test.api.repository")
#PropertySource("classpath:application.properties")
public class AppConfig {
}
WebAppConfig:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.test.webservice" })
public static class WebAppConfig extends WebMvcConfigurerAdapter {
}
Almost work fine, but sometime it throw an exception: Caused by: java.lang.IllegalStateException: No transactional EntityManager available even I just select record (Not create, update or delete data.)
If I move annotation: #ComponentScan(basePackages = { "com.test.api" }) to Class WebAppConfig and remove: #ComponentScan(basePackages = { "com.test.webservice" }) then exception is disappear, but spring context load many time when server startup and spring beans are duplicate.
Or If I use entityManager.getEntityManagerFactory().createEntityManager().unwrap(Session.class) instead for entityManager.unwrap(Session.class) then exception also disappear.
How can I solve it?

Remove the ComponentScan on WebAppConfig and add the package in the ComponentScan annotation on AppConfig, that should solve your problem.

Related

Must #ComponentScan be placed with #Configuration? (Spring Core)

I read inside many articles that #ComponentScan should be placed with #Configuration on top of a class. Here some references:
we use the #ComponentScan annotation along with #Configuration
annotation to specify the packages that we want to be scanned
(https://www.baeldung.com/spring-component-scanning)
#ComponentScan(basePackages = "com.zetcode") #Configuration public
class Application { ... } (http://zetcode.com/spring/componentscan)
The #ComponentScan annotation is used with the #Configuration
annotation to tell Spring the packages to scan for annotated
components. (https://dzone.com/articles/spring-component-scan)
I was curious to try if without #Configuration an exception would have been thrown. Surprisingly everything works fine even without #Configuration. Here the code:
#ComponentScan
public class AppConfig {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
for (String beanDefinitionName : context.getBeanDefinitionNames()) {
System.out.println(beanDefinitionName);
}
}
}
I had just one sample bean which got printed.
#Component
public class Car {
}
This was the output of the main method:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
appConfig
car
Why does it work? and why do they tell to use it with configuration? was it an old requirement?
And even more surprisingly appConfig becomes a bean, even if it does not have any particular annotation such as #Configuration or #Component. So does that mean that anything that gets put as argument of new AnnotationConfigApplicationContext() gets turned into a bean no matter what annotation does it has or has not?
I probably miss some core spring behavior which would justify this. Any idea?
You are still using #Configuration together with #ComponentScan implicitly. By pasing the AppConfig.class as param to the context, it considers it configuration. That would explain the bean created for it as well

#EnableAutoConfiguration on AbstractIntegrationTest possible?

Having lots of Integration-Test Implementations like this:
// no #Annotations at all
class SomeIntegrationTest extends AbstractIntegrationTest {
...
}
using (Spring Boot 1.5, JUnit 5)
#SpringBootTest(classes = {CoreConfiguration.class, RestTemplateAutoConfiguration.class, JacksonAutoConfiguration.class})
#ExtendWith(SpringExtension.class)
#AutoConfigureMockMvc
#Transactional
public abstract class AbstractIntegrationTest {
...
}
this is always failing with
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'javax.persistence.EntityManagerFactory' available
unless I annotate every IntegrationTest-Implementation with
#EnableAutoConfiguration
class SomeIntegrationTest extends AbstractIntegrationTest {
...
}
I wonder why I cannot #EnableAutoConfiguration the AbstractIntegrationTest and be done with it.
(When doing so, it fails with IllegalArgumentException: No auto-configuration attributes found. Is package.SomeIntegrationTest annotated with EnableAutoConfiguration?)
Our normal Apps look like this:
#SpringBootApplication
#Import({CoreConfiguration.class, OtherConfiguration.class})
public class WebApp {
here the #SpringBootApplication obviously implies #EnableAutoConfiguration but I would like to avoid annotating each and every *IntegrationTest with this and instead configure it once on the AbstractIntegrationTest.
Is this fighting against spring-boot in any way or is there some way to achieve this? Thanks.
You could create update your AbstractIntegrationTest abstract class to have a small inner configuration class e.g. TestConfiguration which is loaded using the #Import(TestConfiguration.class) annotation.
#SpringBootTest(classes = {CoreConfiguration.class, RestTemplateAutoConfiguration.class, JacksonAutoConfiguration.class})
#ExtendWith(SpringExtension.class)
#AutoConfigureMockMvc
#Transactional
#Import(AbstractIntegrationTest.TestConfiguration.class) // <---- import the configuration
public abstract class AbstractIntegrationTest {
#EnableAutoConfiguration
// Any other applicable annotations e.g. #EntityScan
static class TestConfiguration {
}
....
}

adding #EnableAuthorizationServer throws exception on server startup

The following works fine
#Configuration
#EnableCaching
#EnableOAuth2Sso
#EnableWebSecurity
#EnableOAuth2Client
#SpringBootApplication
#Import({ AppConvConfig.class, AppPropConfig.class, AppSecConfig.class })
#EnableAspectJAutoProxy(proxyTargetClass = true)
#EnableTransactionManagement(proxyTargetClass = true)
#EntityScan(basePackages = { BeanConstants.SCAN_PKG_JDBC_ENTITY })
#EnableJpaRepositories(basePackages = { BeanConstants.SCAN_PKG_JDBC_REPO })
#ComponentScan(basePackages = { BeanConstants.SCAN_PKG_SERVI, BeanConstants.SCAN_PKG_FLICK_WEB })
public class AppConfig extends WebMvcConfigurerAdapter {
..
}
But if I add #EnableAuthorizationServer to the above, start seeing the following exception on startup
***************************
APPLICATION FAILED TO START
***************************
Description:
Method springSecurityFilterChain in org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration required a single bean, but 2 were found:
- remoteTokenServices: defined by method 'remoteTokenServices' in org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerTokenServicesConfiguration$RemoteTokenServicesConfiguration$TokenInfoServicesConfiguration
- defaultAuthorizationServerTokenServices: defined by method 'defaultAuthorizationServerTokenServices' in org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfiguration
Action:
Consider marking one of the beans as #Primary, updating the consumer to accept multiple beans, or using #Qualifier to identify the bean that should be consumed
Nevermind, #EnableOAuth2Sso & #EnableOAuth2Client were redundant, removed #EnableOAuth2Sso and it starts up fine.. testing the rest. Final list:
#Configuration
#EnableCaching
#EnableWebSecurity
#EnableOAuth2Client
#EnableAuthorizationServer
#SpringBootApplication
#Import({ AppConvConfig.class, AppPropConfig.class, AppSecConfig.class })
#EnableAspectJAutoProxy(proxyTargetClass = true)
#EnableTransactionManagement(proxyTargetClass = true)
#EntityScan(basePackages = { BeanConstants.SCAN_PKG_JDBC_ENTITY })
#EnableJpaRepositories(basePackages = { BeanConstants.SCAN_PKG_JDBC_REPO })
#ComponentScan(basePackages = { BeanConstants.SCAN_PKG_SERVI, BeanConstants.SCAN_PKG_FLICK_WEB })

Why Spring's AsyncConfigurer messes up context loading order

I'm experiencing a strange behavior with Spring context initialization ordering. I have the following configuration class:
#Configuration
#ComponentScan(basePackageClasses = foo.Bar.class, useDefaultFilters = false, includeFilters = #Filter(Service.class))
#Import({ PersistenceConfig.class, SecurityConfig.class })
#EnableAsync
#EnableScheduling
public class RootConfiguration {
#PostConstruct
public void done() throws Exception {
}
}
This works just fine. My done method gets executed AFTER PersistenceConfig and ServiceConfig.
But whey I make my Rootconfiguration implement AsyncConfigurer, the done method gets executed BEFORE PersistenceContext and SecurityContext, which is problematic in my case!
Any ideas of why such behavior?
Is it documented somewhere?
Any insight would be greatly appreciated.

Spring: Properly setup #ComponentScan

I have following set up for my Spring Application Context.
#Configuration
public class RmiContext {
#Bean
public RmiProxyFactoryBean service() {
RmiProxyFactoryBean rmiProxy = new RmiProxyFactoryBean();
rmiProxy.setServiceUrl("rmi://127.0.1.1:1099/Service");
rmiProxy.setServiceInterface(Service.class);
return rmiProxy;
}
}
#Configuration
public class LocalContext {
#Bean
public Controller Controller() {
return new ControllerImpl();
}
}
#Configuration
#Import({RmiContext.class, LocalContext.class})
public class MainContext {
}
The above setup works fine, but I want to enable #ComponentScan annotating Controllers with #Component as there are many Controllers in my application which is tedious when declared one by one using #Bean.
#Configuration
#ComponentScan(basePackageClasses = {Controller.class})
public class LocalContext {
/* ... */
}
The problem is that when I do #ComponentScan(basePackageClasses = {Controller.class}), the previously fine working RmiProxyFactoryBean are not recognized or can't be created.
So, How do I configure my MainContext so that both beans via RMI and local beans are created?
#Configuration is also a candidate for component scan, so you can scan all the beans in RmiContext and all controllers in your controller package by:
#Configuration
#ComponentScan(basePackages = {"org.example.controllers", "package.of.RmiContext"})
public class MainContext {
}
--edit--
#Configuration is a candidate for component scan, here is the test case that works in my pc:
package scan.controllers;
#Controller
public class ExampleController {
}
package scan;
public interface RMIService {
}
package scan;
#Configuration
public class RmiContext {
#Bean
public RmiProxyFactoryBean service() {
RmiProxyFactoryBean rmiProxy = new RmiProxyFactoryBean();
rmiProxy.setServiceUrl("rmi://127.0.1.1:1099/Service");
rmiProxy.setServiceInterface(RMIService.class);
rmiProxy.setLookupStubOnStartup(false);
return rmiProxy;
}
}
package scan;
#Configuration
//MainContext will auto scan RmiContext in package scan and all controllers in package scan.controllers
#ComponentScan(basePackages = {"scan", "scan.controllers"})
public class MainContext {
}
package scan;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes={MainContext.class})
public class TestContext {
#Autowired private RMIService rmi;
#Autowired private ExampleController controller;
#Test
public void test() {
//both controller and rmi service are autowired as expected
assertNotNull(controller);
assertNotNull(rmi);
}
}
May be you could try using the base packages of your classes (RMI, Controller):
#ComponentScan(basePackages = {"your controller package", "your rmi package"})
If the RMI classes package is different than controller then they will fail to instantiate by spring.
If I understand you correctly, you use "#ComponentScan(basePackageClasses" but it is not detecting and registering your spring beans?
I had the same issue a few minutes ago. I did not give up and tried all funny guesses. One guess did it.
I had to add an XML component-scan entry in XML. I just put a dummy package there, like below:
component-scan base-package="dummy.filler.to.enable.component.scan"
It seems that the component-scan in XML enables the #ComponentScan.
[Late Edit: I noticed, my spring xml schema is spring 2.5. Anyway, I dont know if this matters. Best Regards.]

Resources