#EnableJpaRepositories will not work with JPA Data repository - spring-boot

I'm trying to run Spring Boot with two data sources. So far so good, but the problem occurred when I tried to use Spring JPA Data. SimpleJPARepository do not reflect the transaction manager set by
#EnableJpaRepositories(
basePackages = "cz.data.external",
entityManagerFactoryRef = "externalEntityManagerFactory",
transactionManagerRef = "externalTransactionManager")
It seems it still uses the one marked as primary.
The javadoc says
transactionManagerRef - Configures the name of the {#link PlatformTransactionManager} bean definition to be used to create repositories discovered through this annotation.
Am I doing something wrong or is it not supported by Data JPA? To change the transaction manager.

Are you using Spring 4.1.4 by accident? It seems you're running into this regression. We recommend to use Spring 4.1.3 (by explicitly setting the spring.version property in case of a Boot project) until 4.1.5 is released.

Related

Spring boot Jpa is not working with Spring batch and spring integration

I am working with spring batch. I needed to add some jpa repositories. So previously i was using JDBCTemplate which was working fine.
But when I started working with JPA, the spring boot application could not find the repos. Which were there.
#Autowired
ClassLevelConfigRepo clcr;
I checked these things as the best practices.
Added #EnableJpaRepositories in springBoot application class.
Added #Repostiories to the repository interfaces.
extended the interfaces with JpaRepository<Account, String>
Added #Entity to the entity classes and defined the #Table and # Column annotations properly.
But I am still getting below error.
Field clcr in com.cloudtask.batchconfig.util.LhmUtility required a bean of type 'com.cloudtask.batchconfig.repo.ClassLevelConfigRepo' that could not be found.
I tried checking all the dependencies in pom.xml it was as per recommended. And I have all the tables defined properly in data base.
I was expecting the application to return the Autowired clcr object propely.
Edit 1 : spring boot application annotations
#SpringBootApplication
#ComponentScan({"com.cloudtask"})
#EnableAsync
#IntegrationComponentScan({"com.cloudtask"})
#EnableIntegrationManagement(defaultLoggingEnabled = "true")
#EnableJpaRepositories
#EntityScan
public class imclassApplication ```
When you work with Spring Data Jpa with those basic points you should also keep track of below points.
you have added spring-boot-starter-data-jpa in your pom.xml
you have added the entity and repo package below one level of the application package.
If you the package is at same level you should specify the exact package details in the annotation. in your case it should be like :
#EnableJpaRepositories("com.cloudtask.batchconfig.repo")
#EntityScan(basePackages = {"com.cloudtask.batchconfig.entity"})
Happy programming!

How to minimize and speed up Spring Boot project for development enviroment?

I'm working on a Spring Boot Rest project with 500~ entity in it. But it is slow on start up duration (about 3 minutes) because of the EntityManagerFactory initialization. And it has 5GB~ memory allocation.
Using profiles I want to open a lightweighted version of my project. I'm trying to avoid some of the entities to be mapped via EntityManagerFactory. And related beans via ComponentScan.
Do you have any solution related this issue?
For example I wanna hide some of the packages from hibernate & spring boot auto configuration.
If the class path scanning takes to long you can narrow it down to specific packages
#ComponentScan(basePackages = "com.your.project")
#EntityScan(basePackages = "com.your.project.model")
#EnableJpaRepositories(basePackages = "com.your.project.repository")
You also have an option to create a custom EntityManagerFactory as explained in this answer with a custom ConnectionProvider.

Why AutoConfigurationPackages not consider #ComponentScan?

Spring Boot's support for Spring data configuration is generally by org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport, and this class use the follow code to determine what packages to scan for repositories:
AutoConfigurationPackages.get(this.beanFactory)
So, basically Spring Data with Spring Boot only scan the package which contains the #EnableAutoConfiguration or #ImportAutoConfiguration, but not consider the #ComponentScan, Is this correct ?
The #ComponentScan annotation is a core Spring Framework feature to search for classes annotated with #Component. Since Spring Data repositories are interfaces (and not annotated), the #ComponentScan annotation won't pick them up.
If you are using Spring Data outside of Spring Boot, you can scan for Spring Data repositories using #EnableJpaRepositories with the basePackages attribute set.
When it comes to Spring Boot, there's usually no need to use either #ComponentScan or #EnableJpaRepositories. If you structure your code as suggested, both components and repositories will be picked up.
To get back to your original question about AbstractRepositoryConfigurationSourceSupport. If you look at the source of #SpringBootApplication you'll see it's annotated with #ComponentScan (to find #Components) and #AutoConfigurationPackage (via #EnableAutoConfiguration). The #AutoConfigurationPackage sets up AutoConfigurationPackages with the value that's later retrieved.
If you want to override the packages the Spring Data searches for repositories (for example in tests) you'll need to use #EnableJpaRepositories to completely override auto-configuration. I usually don't do this, but instead use #DataJpaTest and pick up my main configuration.

Spring Boot multiproject Spring Data Jpa

I have a three module Spring Boot App. I've a problem when I try to add a Custom repositoryFactoryBeanClass and when i do that i get the following error:
No constructor with 0 arguments defined in class
'org.springframework.data.jpa.datatables.repository.DataTablesRepositoryFactoryBean'
My annotation is:
#EnableJpaRepositories(repositoryFactoryBeanClass =
DataTablesRepositoryFactoryBean.class, basePackages =
"xxx.xxxxxxx.xxxx.xxxxx.repositories")
I have three modules: web, entity/repository and service.
Thanks.
I was able to solve this by upgrading Spring Boot version to 1.5.4.RELEASE. Please refer this thread for more details https://github.com/darrachequesne/spring-data-jpa-datatables/issues/50
Finally,I changed #EnableJpaRepositories to
#EnableJpaRepositories(basePackages = "xxxx.xxxx.xxxxx.repositories", repositoryBaseClass = DataTablesRepositoryImpl.class)

#EnableTransactionManagement in Spring Boot

Is #EnableTransactionManagement required in Spring Boot?
I did some research. Some folks say you don't need it, as Spring Boot has it already enabled, others say you do have to use it explicitly. So how is it?
Probably you're also using Spring Data. Calls on Spring Data repositories are by default surrounded by a transaction, even without #EnableTransactionManagement. If Spring Data finds an existing transaction, the existing transaction will be re-used, otherwise a new transaction is created.
#Transactional annotations within your own code, however, are only evaluated when you have #EnableTransactionManagement activated (or configured transaction handling some other way).
You can easily trace transaction behavior by adding the following property to your application.properties:
logging.level.org.springframework.transaction.interceptor=TRACE
(see Showing a Spring transaction in log)
According to > https://spring.io/guides/gs/managing-transactions/
Spring Boot will detect spring-jdbc on the classpath and h2 and will create a DataSource and a JdbcTemplate for you automatically. Because such infrastructure is now available and you have no dedicated configuration, a DataSourceTransactionManager will also be created for you: this is the component that intercepts the #Transactional annotated method.
You can also use spring-boot-starter-actuator to list your beans created in your context and you will find it
bean": "transactionManager"
Little old post but the answers given previously were not straight forward when I was searching for it.
#EnableTransactionManagement is optional in Spring boot, provided that spring-data* or spring-tx are found in classpath. How it works? As below:
Spring boot adds a spring-boot-autoconfigure.jar in the classpath. Go to the META-INF's spring.factories file and you can see org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration entry there. This initializes the transaction auto configuration for you.
Note that the class has following lines: (snippet)
#Configuration
#ConditionalOnClass({PlatformTransactionManager.class})
#AutoConfigureAfter({JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class})
#EnableConfigurationProperties({TransactionProperties.class})
public class TransactionAutoConfiguration {
..
}
Have a look at TransactionAutoConfiguration to see that it enables transaction support if the PlatformTransactionManager is available in classpath. EnableTransactionManagementConfiguration is also configured there.
No. #EnableTransactionManagement is on by default, see that: https://github.com/jkubrynski/spring-boot/commit/9d219ef7a004c58a88bbbef82a520a22961c9402
#EnableTransactionManagement is conditionally turned on/off based of the dependency jars we add in the classpath. If we use spring data jpa starter it is turned on.
In the class org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, there is such code(Spring Boot 1.5+):
#Configuration
#EnableTransactionManagement(proxyTargetClass = false)
#ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {
}
#Configuration
#EnableTransactionManagement(proxyTargetClass = true)
#ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
public static class CglibAutoProxyConfiguration {
}
The default is spring.aop.proxy-target-class=true, enabling CGLIB proxy by default.
If you want to use JDK proxy, set spring.aop.proxy-target-class=false instead.

Resources