I would like to integrate Kotlin Exposed into a Kotlin application that is already using Spring Data JPA. The problem I have is that only want to use one Transaction Manager for my application, but currently I have to have two (one for JPA and another for Exposed). Is there a way to only have one Transaction Manager?
I didn't work with kotlin-exposed library before, but based on your question
,Just you have to create your own transaction-manager bean. After that spring will use your bean, and you need to configure kotlin-exposed to use it.
sample:
#Primary
#Bean("appTransactionManager")
fun appTransactionManager(
#Qualifier("appEntityManagerFactory") appEntityManagerFactory: LocalContainerEntityManagerFactoryBean
): PlatformTransactionManager {
return JpaTransactionManager(eccTransactionManager.getObject()!!)
}
Related
I am creating a Springboot application with OpenJPA.
My requirement is that I need to connect to multiple datasources dynamically and the datasource credentials are obtained at runtime by calling some rest-endpoints.
Here is the controller class:
#RestController
public class StationController {
#Autowired
BasicDataSource dataSource;
I have a service which returns me the jdbc_url depending on the customer name:
public String getDSInfo(String customername){
// code to get the datasource info (JDBC URL)
}
My questions are:
Is there a way in which I can create datasources at runtime by getting datasource credentials by calling some other service (which takes the customer id and returns the customer specific datasource) ?
Since my application is a web based application, many customers will be accessing it at the same time, so how to create and handle so many different datasources?
NOTE:
The code will get information about the customer specific data source only by firing some service at the runtime, so I cannot hardcode the datasource credentials in the XML configuration file.
I found some implementations with Hibernate but i am using Springboot with OpenJPA. So need OpenJPA specific help.
It sounds like you want a multi-tenancy solution.
Datasources are easy to create programmatically, just use a DataSourceBuilder with your connection details pulled in from a central source (e.g. a central config database or Spring Config Server).
Then you'll need to look at a multi-tenancy framework to tie the datasources back to clients.
See here:
https://www.youtube.com/watch?v=nBSHiUTHjWA
and here
https://dzone.com/articles/multi-tenancy-using-jpa-spring-and-hibernate-part
The video is a long watch but a good one. Basically you have a map of customer data sources (from memory) that allow an entityManager to pick up a datasource from the map by using a thread scoped custom spring scope of "customer" which is set when a user for a particular customer somehow logs into your app.
I like Spring Data REST but I need to explore the possibility to use it without exposing directly our JPA Entities. Furthermore, our access layer is currently build using GenericDAO instead of repository (or Spring Data JPA).
So the idea is to build a custom spring data module that implementing the Repository interfaces allow me to benefit of all the other functionalities of Spring Data REST. The entities managed by our custom spring data module will be at the end DTOs of the original JPA entities.
I'm currently looking to spring-data-ldap as implementation to mimic as it looks as the most simple data module available but I'm facing with the following issue
we get an exception at the application startup saying
Parameter 0 of constructor in org.springframework.data.dspace.repository.support.DSpaceRepositoryFactoryBean required a bean of type 'java.lang.Class' that could not be found.
Action:
Consider defining a bean of type 'java.lang.Class' in your configuration.
DSpaceRepositoryFactoryBean is our implementation that just return a very simple DSpaceFactoryBean that always return a banal implementation of the CrudRepository (all methods return null)
#Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return SimpleDSpaceRepository.class;
}
have sense this approach? or will be better to give up with Spring Data REST and just use Spring MVC + HATEOS?
I am trying to implement Spring Data Crate API in a project. Following the instructions provided here:
https://crate.io/a/using-sprint-data-crate-with-your-java-rest-application/
Inserts/Updates/FindById methods are covered. My question is how to create custom queries using this API.
Have you looked at our Spring Data adapter?
Declared Queries
It's also possible to use the #Query annotation to define queries:
public interface UserRepository extends CrateRepository<User, String> {
#Query("select * from users")
List<User> getAllUsers();
}
https://github.com/crate/spring-data-crate#declared-queries
please note that the crate java-client is not supported anymore since v0.57 unfortunately.
https://crate.io/docs/clients/java/
This leaves us with the java-jdbc:
https://github.com/crate/crate-sample-apps/blob/master/java/documentation.md
Spring data adapter is using the java-client.
Here is a Spring Boot application that is using JDBC in order to access CrateDB (> v0.57.0) https://github.com/klearchos/crate
And here are the official samples in order to access CreateDB through JDBC (using the Spark framework). https://github.com/crate/crate-sample-apps/tree/master/java
I really like the simplicity of spring data repository, however need to use hibernate as persistence provider for consistency and few other factors. (I am using mongodb but not using mongo template). Few things I noticed --
The HibernateJpaVendorAdapter uses "org.springframework.orm.jpa.vendor.SpringHibernateEjbPersistenceProvider"
The provider configured with the persistence unit ( ""org.hibernate.ogm.jpa.HibernateOgmPersistence" ) is not considered, while constructing the EntityManagerFactory through a "org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" bean.
If there are multiple persistence units configured for the project there is no apparent way to associate a persistence unit for a repository.
Questions:
Is there a way to use the configured persistence provider , instead of the default one ? The default provider is not working with mongodb.
Is there a way to associate a repository with a specific persistence unit ?
A partial solution was to
implement
org.springframework.orm.jpa.vendor.AbstractJpaVendorAdapter and
return an instance of
org.hibernate.ogm.jpa.HibernateOgmPersistence in
getPersistenceProvider() method
Source the jpaVendorAdapter property for entityManagerFactory
bean in spring config
However it still doesn't work good wherever there is reference to Pageable. Some design change can circumvent the issue.
I realized after writing this question I could sum it up in a few sentences. How can I manage transactions in Spring-Data-JPA with CDI the same way you would by using #Transactional in Spring itself?
First thing I did was set up Spring Data JPA CDI based on the documentation here. http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/jpa.repositories.html#jpd.misc.cdi-integration
I set this up and it is working fine for read operations but not write operations
For Example, Their example in the docs would work fine.
List<Person> people = repository.findAll();
So I have the basic setup complete.
Written by hand may have typos. This is similar to the code I execute.
#Inject
UserRepository userRepository;
User user;
#Transactional
public void signUpUserAction() {
userRepository.saveAndFlush(user);
}
Then I receive this error
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
At first I realized I did not have the #Transactional so I added it and still did not work.(I believe in spring you need to use the AOP xml file to set up #Transactional so it makes sense this does not work in EE out of the box, I just do not know how to make it work.)
FYI annotating with this does not work
#TransactionAttribute(TransactionAttributeType.REQUIRED)
Something I tried while I was writing this post and I got it to work sort of... but I don't like the code and am still interested in using #Transactinoal, this code feels dirty, I'm pretty sure #Transactional handles calling other methods that are transactional in a clean way while this code would not.
This saves and I verify it's in the database.
#Inject
EntityManager em;
#Inject
UserRepository userRepository;
private User user;
public void signUpUserAction() {
em.getTransaction().begin();
userRepository.saveAndFlush(user);
em.getTransaction().commit();
}
So in short, how can I use #Transactional or something similar to manage my transactions?
Thank you for any help.
If you run Spring Data in a CDI environment, you're not running a Spring container at all. So you'll need to use EJB session beans to work with the repositories as CDI currently does not have support for transactions out of the box. The CDI extensions shipping with Spring Data is basically providing an entry point into the JavaEE world and you'll use the standard transaction mechanisms you can use in that environment.
So you either inject a repository into an #Stateless bean directly or you inject the CDI bean into one. This will allow you to use EJB transaction annotations on the EJB then.
for everyone who have this question yet.
I have this experimental project that support #Transactional in a CDI environment.
This project uses a custom code of Narayana as interceptor and provide compatibility with it and Spring Data Jpa implementation.
Key points to take in consideration:
Custom (Spring Data) Cdi Configuration -> add a Custom Transactional Post Processor custom spring data cdi configuration
Implement a custom Transactional Post Processor:
sample of a Custom Transactional Post Processor
Implement a custom Transactional Interceptor sample of a custom transactional interceptor
Add a Cdi Producer for your custom Tx Interceptor cdi producers
Create your custom repository fragments using #Transactional (JTA) custom fragments
Compose your Repository interface extending Repository interface and your fragments with #NoRepositoryBean annotation custom repositories
Take a look at this link that have some tips:
tips
Regards,