transactional not working in spring data neo4j - java

I am using spring-data-neo4j for my neo4j database in my application,i want to have transactional APIs in my service layer but it seems that #transaction is not working.
Service Layer:
#Transactional('neo4jTransactionManager')
def savePerson(){
Person person=new Person()
person.setName("prabh")
person.setDistance(100)
PersonRepository.save(person)
int i=10/0;
}
Configuration :
<context:component-scan base-package="neo4j"></context:component-scan>
<bean id="graphDatabaseService"
class="org.springframework.data.neo4j.rest.SpringRestGraphDatabase">
<constructor-arg value="http://localhost:7474/db/data" />
</bean>
<neo4j:config graphDatabaseService="graphDatabaseService"
base-package="neo4j" />
<neo4j:repositories base-package="neo4j" />
<bean id="neo4jTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="org.neo4j.kernel.impl.transaction.SpringTransactionManager">
<constructor-arg ref="graphDatabaseService" />
</bean>
</property>
<property name="userTransaction">
<bean class="org.neo4j.kernel.impl.transaction.UserTransactionImpl">
<constructor-arg ref="graphDatabaseService" />
</bean>
</property>
</bean>
<tx:annotation-driven mode="aspectj"
transaction-manager="neo4jTransactionManager" />
</beans>
I am using rest server of neo4j database.

That's what the documentation says, for remote access there is no transactionality due to Neo4j's REST API not exposing transactions over the wire in the past
In the next milestone (and the current 3.3.0.BUILD-SNAPSHOT) build a new remoting integration is used, which exposes transactions over the wire and is also much faster than the existing one.

Related

Loading application configuration properties from database in spring based application using java based configuration

Its better to store the configuration properties in a database table so that it can be managed easily for different environments. The approach to store and retrieve the configuration properties from database table in xml based configuration is like below :
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
<property name="properties">
<bean class="org.apache.commons.configuration.ConfigurationConverter" factory-method="getProperties">
<constructor-arg>
<bean class="org.apache.commons.configuration.DatabaseConfiguration">
<constructor-arg>
<ref bean="dbDataSource" />
</constructor-arg>
<constructor-arg value="DOMAIN_CONFIG" />
<!-- DB Table -->
<constructor-arg value="CONFIG_NAME" />
<!-- DB Key Column -->
<constructor-arg value="CONFIG_VALUE" />
<!-- DB Value Column -->
</bean>
</constructor-arg>
</bean>
</property>
</bean>
But the same thing i'm trying to achieve using java based configuration but no luck.
Can anyone please help me.
I found answer for my question.
Thanks to this post : https://gist.github.com/jeffsheets/8ab5f3aeb74787bdb051
This exactly suits to my problem. Thanks.!

Transaction boundary is not properly set in JpaTransactionManager

Im using JPA with Hibernate implementation and using JpaTransactionManager to mange transactions.
Below is my application context file
<bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocations">
<list>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
<property name="defaultDataSource" ref="dataSource" />
</bean>
<bean id="entityManagerFactory" primary="true"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="persistenceUnitManager" />
<property name="persistenceUnitName" value="infra_services" />
</bean>
<bean
class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<tx:annotation-driven transaction-manager="transactionManager"
proxy-target-class="true" />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
I have defined my service class as below
#Service
#Transactional
public class ComponentService {
I execute queries in dao layer as below
Query q = entityManager.createQuery(
"SELECT cc.component FROM "
+ this.typeParameterClass.getSimpleName()
+ " cc WHERE cc.caseload.id = ? ").setParameter(1,
caseloadId);
Collection<Component> ddd =q.getResultList();
for (Component c : ddd) {
System.out.println(c.getComponentId());
System.out.println(c.getComponentRelationships2());
}
return ddd;
I started with select queries. While executing the line System.out.println(c.getComponentRelationships2()); getting could not initialize proxy - no Session] with root cause exception
Not sure why the session is not available here. Please help me on this.
If your service is not in the same context as the one where <tx:annotation-driven /> then it's not working. Because it only look for bean in the same context. Extract from spring doc:
#EnableTransactionManagement and only looks for #Transactional on beans in the same application context they are defined in. This means that, if you put annotation driven configuration in a WebApplicationContext for a DispatcherServlet, it only checks for #Transactional beans in your controllers, and not your services. See Section 21.2, “The DispatcherServlet” for more information.

Atomikos / Spring - Global Transaction over two DBs

I am using Spring and trying to setup a global transaction spanning over two MS SQL Server DBs. The app is running inside Tomcat 6.
I have these definitions:
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
....
</bean>
<bean id="sessionFactory1"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource1"/>
....
</bean>
<bean id="hibernateTransactionManager1"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory1"/>
</property>
</bean>
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
....
</bean>
<bean id="sessionFactory2"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource2"/>
....
</bean>
<bean id="hibernateTransactionManager2"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="sessionFactory2"/>
</property>
</bean>
Then also, each DAO is linked either to sessionFactory1 or to sessionFactory2.
<bean name="stateHibernateDao" class="com.project.dao.StateHibernateDao">
<property name="sessionFactory" ref="sessionFactory1"/>
</bean>
Also, I recently added these two.
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
<property name="forceShutdown" value="false" />
<property name="transactionTimeout" value="300" />
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout" value="300" />
</bean>
I am trying to programmatically manage the global transaction
(this is some old legacy code and I don't want to change it too
much so I prefer keeping this managed programmatically).
So now I have this UserTransaction ut (injected from Spring), so I call ut.begin(), do some DB/DAO operations to the two DBs through the DAOs, then I call ut.commit().
The thing is that even before the ut.commit() call, I can see the data is already committed to the DBs?!
I don't think Atomikos is aware of my two DBs, their data sources, session factories, etc. I don't think it starts any transactions on them. Looks like they are not enlisted at all in the global transaction.
To me it seems that each DB/DAO operation goes to the SQL Server on its own, so SQL Server creates an implicit transaction for just that DAO/DB operation, applies the operation and commits the implicit the transaction.
But 1) and 2) are just guesses of mine.
My questions:
Do I need to start the two DB transactions myself (but OK, this is what I am currently doing and I am trying to get rid of; that's why I am trying to use Atomikos to start with)?
How I can configure all this correctly so that when I call ut.begin() it begins a global transaction to the two DBs and when I call ut.commit() it commits it?
I haven't played with JTA recently so seems to me I am missing something quite basic here. What is it?
Edit 1
<bean id="globalTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="userTransaction" ref="atomikosUserTransaction"/>
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="allowCustomIsolationLevels" value="true" />
<property name="transactionSynchronization" value="2" />
</bean>

How to force disable JSR-303 support in Spring 3?

I have some legacy Spring MVC code mixed with gwt code in same artifact (built using maven) and I cannot make it run. It wants validation provider at runtime which i do not need (since I'm not using any JSR-303 validation annotations) and do not want in CP (it may conflict with some app containers this artifact will be deployed in)
How to force spring not to do any JSR-303 validations and get rid of runtime dependency on validation provider?
PS artifact has validation-api in CP since GWT is using it somehow
PPS
Seems like removing <mvc:annotation-driven/> from Spring config fixes this.
Binding and classic validations still works (I have <context:annotation-config/> enabled)
As you already discovered, <mvc:annotation-driven/> sets a lot of features including JSR-303. The equivalent is
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="0" />
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean class="org.springframework.web.bind.support.ConfigurableWebBindingInitializer">
<property name="validator" ref="validator" />
</bean>
</property>
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
<bean class="org.springframework.http.converter.FormHttpMessageConverter" />
<bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter" />
</list>
</property>
</bean>
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
<bean id="conversion-service"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean" />
So you may substitute the tag onto this xml configuration and remove parts you don't need.

Using a DAO on a Bean used by a Spring Scheduled Task

I'm developing a web application using Struts2 + Spring, and now I'm trying to add a scheduled task. I'm using Spring's task scheduling to do so. In my applicationContext I have:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
...
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL" />
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
And then I have my DAO that uses this entityManagerFactory:
<bean id="dao" class="data.GenericDAO" />
So this works flawlessly within the web application. But now I have a problem when creating the scheduled task:
<task:scheduled-tasks scheduler="notifier">
<task:scheduled ref="emailService" method="sendMail" fixed-rate="30000" />
</task:scheduled-tasks>
<task:scheduler id="notifier" pool-size="10" />
<bean id="emailService" class="services.emailService" >
<property name="dao" ref="dao" />
</bean>
This executes the method sendMail on my emailService class every 30 seconds. And my emailService has the DAO injected correctly. The thing is that I can fetch objects with my DAO using the findById named queries, but when I try to access any property mapped by Hibernate, such as related collections or entities, I get an "LazyInitializationException: could not initialize proxy - no Session ". I don't know what's wrong, since I believe the scheduled task is being managed by Spring, so it should have no problem using a Spring managed DAO. I must say that I'm using the openSessionInView filter on my struts actions, so maybe I need something similar for this scheduled task.
Any help or suggestion will be appreciated, thanks!
Edit: Finally I found a way to fix this. I changed my regular Dao with one where I can decide when to start and commit the transaction. So before doing anything I start a transaction and then everything works OK. So I still don't know exactly what causes the problem and if someday I'll be able to use my regular DAO, for the moment I'm staying with this solution.
OpenSessionInView won't help you, because you don't have a web context. You need Spring's Declarative Transaction Management.
In most cases, what you need to do is just this XML:
<!-- JPA, not hibernate -->
<bean id="myTxManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="myTxManager" />
<!-- without backing interfaces you probably also need this: -->
<aop:config proxy-target-class="true">
(Annotate your EmailService class as #Transactional to enable this)

Categories