Handling Datastax Java driver CqlSession in Spring Boot - spring

Datastax Java driver documentation says to create a single instance of CqlSession for your Spring Boot application as building a session is a costly operation.
I want to manage the CqlSession in an effective way in Spring Boot such that CqlSession instance should be closed and not kept open in order to free underlying resources(TCP connections, thread pools…).
Driver documentation URL: https://docs.datastax.com/en/developer/java-driver/4.13/manual/core/
Here is my CqlSession Instance class. I use the Cqlsession instance to run Cql queries all over my Spring Boot application by injecting it as a Dependency in my #Service and #Repository classes.
Also I never close my Cql session manually but let the Spring handle it using #PreDestory annotation. Should session be closed as soon as a cql query is executed or should I allow spring to handle it as mentioned in the below code? I have realised that doing so, it takes a latency about 1-1.5 seconds for building cqlsession again and queries are ran super slow due to this.
#Configuration
public class CqlSessionInstance {
private CqlSession session;
#PostConstruct
private void initSession() {
getSession();
}
public final CqlSession getSession() {
if(session == null || session.isClosed()) {
session = CqlSession.builder().build();
}
return session;
}
#PreDestroy
public final void closeSession() {
if (session != null && !session.isClosed()) session.close();
}
}
Let me know if there are better ways to manage a CqlSession in Spring Boot

In my opinion, I suggest that you close the CqlSession yourself, since you know when you are executing as a specific request, and you know when to close it.
If you use the annotation #PreDestroy, you are depending on the Spring Life Cycle Management and as such it is hard to determine "when" exactly your component will be destroyed, and as such your session closed.

Related

SpringBatch #Async method not working in persistent layer (JPAItemWriter)

SpringBoot Application with SpringBatch and JPA, without #Async all working fine but with #Async added in the REST API the job is completed but JPAItemWriter is not persisting the objects in the DB. looks like Transactional problem as am getting this exception.
Transaction Manager [org.sringframework.batch.support.transaction.ResourcelessTransactionManager] does not support transaction suspension.
I tried with different approaches like changing Propagation.Requires_New (Required, Supports) but nothing works, tried searching all the forums but no luck.
#Service
public class SampleWriter extends JpaItemWriter<TestEntity> {
#Autowired
EntityManager entityManager;
#Transactional(readOnly=false, propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
#Override
public void write(List<TestEntity> entities) {
this.doWrite(entityManager, entities);
}
}
It seems that you are configuring and using Spring Batch in a wrong way.
Firstly, it is using the default BatchConfigurer which the TransactionManager is ResourcelessTransactionManager that is mainly use for testing or acts as a "no-op" TransactionManager for the batch job that does not require any transaction which is definitely not your case now.
Secondly, Spring Batch will internally take care of managing the transaction boundary for processing each chunk , you do not need to extend JpaItemWriter and control the transaction behaviour using #Transactional by yourself.
So , read this section for how to configure Spring Batch , especially the part related to BatchConfigurer
On the other hand if you are using Spring-boot , it should already configure a JpaBatchConfigurer for you.

How to use ObjectDB properly in spring boot application?

I have a spring boot application with objectdb embedded database.
I am manually handling connection and transaction operations as described at http://www.objectdb.com/java/jpa/persistence/overview
Below is a sample code that I am using: (taken from objecdb documentation):
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("myDbFile.odb");
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
// Operations that modify the database should come here.
em.getTransaction().commit();
}
finally {
if (em.getTransaction().isActive())
em.getTransaction().rollback();
}
It works but the code has become uggly since I had to use try catch finally blocks in order to properly close connections.
I want to refactore my application so that database operations are done in JpaRepositories or Dao classes with #Transactional methods (as described in http://spring.io/guides/gs/accessing-data-jpa/)
I had a research on the web but could not find any solution that works.
What I am looking for is a very simple spring boot sample application with:
spring-boot-starter-data-jpa
Objectdb (embedded)
Maven
Uses annotation based configuration (no xml file)
A dummy entity class (e.g: Customer(id,firstname) )
A JpaRepository class or dao class with list() and #Transactional persist(Customer) methods
Note: I already tried this post but could not make it work.
ObjectDB support answered my question
https://www.objectdb.com/forum/2328#item-6

Spring #Transactional timeout not timing out

I have set transaction timeout in my application as #Transactional(propagation=Propagation.REQUIRED,timeout=30)
ActiveMQXAConnectionFactory and Oracle XA Datasource are two resources of my Distributed transaction. after reading a message from queue my transaction begins and while processing the application is taking more than 30 seconds and still transaction is not timed out. Only when committing the transaction its throwing timeout exception. I wanted immediately after 30 seconds the transaction should time out and throw the exception and make that thread available to consume another message from queue. Is this possible?
Without seeing your configuration it will be hard to say. If you are just adding an #Transactional, it is not going to do anything. You going to need both an EntityManager and a TransactionManager, then you need to turn on annotation based transaction management, and Spring needs to be controlling your datasource if I recall correctly.
Another, probably unnecessary side note, #Transactional will only work on public methods. Spring will proxy your method in order to manage the transaction and Spring can only proxy public methods. Also, it will only be able to work on calls from another class to that method, if you are calling that method from another method inside the same class, Spring cannot proxy either, thus no transaction management. Spring is sneakily deceptive here.
#Service
public class A{
#Autowired
Datasource datasource;
#Transactional
public void save(){
datasource.doStuff();
}
public void callSave(){
save();
}
}
#Service
public class B{
#Autowired
A a;
public void callSave(){
a.save();
}
}
Here, if a.save() is called from a.callSave(), no proxy will occur, thus you will have no transaction management. But in the exact same application, if you call b.callSave(), you will have transaction management, since Spring can then proxy the method call to a.save().
Are you using Spring Boot or vanilla Spring? We can probably give you more of a direction if you divulge that.
Hopefully that helped a bit!

reload in play framework 2.2 java giving exceptions when used with spring data jpa and hibernate

I am using Play Framework 2.2, Hibernate as JPA provider (4.2.8.Final), Spring (4.0.1.RELEASE) and Spring Data JPA (1.4.3.RELEASE).
I am using spring to instantiate to the controllers and using context:component-scan at the application load time to collect and configure all the required dependencies(repositories etc).
The way I have configured spring with play framework is
public class Global extends GlobalSettings {
private ApplicationContext applicationContext;
#Override
public void onStart(Application arg0) {
String configLocation = Play.application().configuration().getString("spring.context.location");
applicationContext = new ClassPathXmlApplicationContext(configLocation);
}
#Override
public <A> A getControllerInstance(Class<A> type) throws Exception {
return applicationContext.getBean(type);
}
}
and relevant section in application-context.xml is
Everything works extremely good when application loads for the first time. How ever as soon as I make any changes either in views or controllers and application reloads, Spring Data Jpa breaks and complains that my models are not of managed types.
Caused by: java.lang.IllegalArgumentException: Not an managed type: class models.User
Though it is not a problem in general, restarts works fine, I would really appreciate if someone can provide any inputs to reload the applicationContext completely on play reload.
I've had the same problem. Changing Spring Data JPA 1.4.3.RELEASE to 1.4.2.RELEASE solved it. I didn't have time to look further into the problem, so I don't know what is the cause.
This project is a good starting point: https://github.com/typesafehub/play-spring-data-jpa but it uses 1.3 version of Spring Data JPA.

Using PersistenceContext in a Quartz Job

We're using Spring 3.1, JPA (via Hibernate) and Quartz. Typically we interact with the DB via #PersistenceContext annotation on Service beans, and either SpringMVC controllers, or GraniteDS-managed service invocation.
I'm working on writing a Quartz job that needs to interact with the database. I've tried everything I can find to get this working. I tried passing in a Spring-managed component (annotated with #PersistenceContext and #Transactional) via the jobMap, the call to entityManager.persist(o) executes, but nothing happens in the database. I also tried similar to this answer, creating a factory class to call autowireBean() on the job object. I set up the job class like so:
public class CreateAlertJob implements Job {
#PersistenceContext
EntityManager entityManager;
#Override
#Transactional
public void execute(JobExecutionContext context) throws JobExecutionException {
SomeEntity entity = new SomeEntity();
entityManager.persist(entity);
}
}
Same result, the method executes but the database is unaltered. I found this blog post which references a GitHub project. There he is using JpaInterceptor to establish a Hibernate session, but this uses the DAO pattern and I'd like to stick with using #PersistenceContext.
Clearly there is something about the Quartz thread that is preventing this from working properly? I'm about out of ideas and considering making a web service call to a SpringMVC controller just to get this working.
Since your CreateAlertJob is not created by Spring, #Transactional in it doesn't take effect.
You have the following options:
Delegate actual work to Spring bean and put #Transactional there
Use programmatic transaction management
Use AspectJ-based AOP implementation instead of Spring default implementation (but it would be overkill for such a simple problem)

Resources