How to run Destroy-method of Proxied Bean in Spring - java

I have a situation where I need to setup a Proxy of a Pooled DataSource, my code is as follows:
<bean id="dataSourceBean" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="properties">
<props>
<prop key="c3p0.minPoolSize">0</prop>
<prop key="hc3p0.maxPoolSize">100</prop>
<prop key="hc3p0.timeout">60000</prop>
<prop key="c3p0.acquire_increment">10</prop>
<prop key="c3p0.max_statement">50</prop>
<prop key="user">${jdbc.username}</prop>
<prop key="password">${jdbc.password}</prop>
</props>
</property>
</bean>
<bean id="dataSourceLockAdvice"
class="com.ndot2.datasource.DataSourceLockAdvice"/>
<bean id="dataSource" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="dataSourceBean"/>
<property name="interceptorNames">
<list>
<value>dataSourceLockAdvice</value>
</list>
</property>
</bean>
The problem that I'm having is that the connections aren't being closed anymore and it would seem that the destroy method of the proxied Datasource is no longer being called...
How would I call the Close method of the Proxied Bean? Or should I be implementing the Advice differently?
I've tried searching the Internet but I can't seem to find the answer to this, Help much appreciated!
EDIT:
As requested, here is my transaction management declarations (I'm using Appfuse)
<aop:config>
<aop:advisor id="userManagerTx" advice-ref="userManagerTxAdvice" pointcut="execution(* *..service.UserManager.*(..))" order="0"/>
<aop:advisor id="userManagerSecurity" advice-ref="userSecurityAdvice" pointcut="execution(* *..service.UserManager.saveUser(..))" order="1"/>
<aop:advisor id="managerTx" advice-ref="txAdvice" pointcut="execution(* *..service.*Manager.*(..))" order="2"/>
</aop:config>
<!-- Enable #Transactional support -->
<tx:annotation-driven/>
<!-- Enable #AspectJ support -->
<aop:aspectj-autoproxy/>
<!-- Activates scanning of #Autowired -->
<context:annotation-config/>
<!-- Activates scanning of #Service -->
<context:component-scan base-package="com.ndot2.service"/>
<tx:advice id="txAdvice">
<tx:attributes>
<!-- Read-only commented out to make things easier for end-users -->
<!-- http://issues.appfuse.org/browse/APF-556 -->
<!--tx:method name="get*" read-only="true"/-->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<tx:advice id="userManagerTxAdvice">
<tx:attributes>
<tx:method name="save*" rollback-for="UserExistsException"/>
</tx:attributes>
</tx:advice>
<bean id="userSecurityAdvice" class="com.ndot2.service.UserSecurityAdvice"/>
I don't have any #Transactional or #AspectJ driven Transaction management...

If you have the connection leaks in your application, the first step to do is to try to localize the place where the leaks occur, using the appropriate monitoring tools. As for c3p0, I believe it provides connection monitoring via JMX, as it's discussed in the related question.
So you can check with the debugging and monitoring tools if the leak occurs during some specific service call.
Then you should watch for different peculiarities: for example, in your configuration UserManager has more than one transaction advice, which could be the cause. In Spring container with annotated configuration a common error is that the bean in not being wrapped by transaction proxy, because the annotated transaction management is configured for the different IoC container. Another possible cause is that your method tries to manage transactions manually, and don't succeed in doing this correctly.

Related

Migrating from Spring MVC XML to Spring Boot Java based configuration with similar configuration

I am starting a new project. Previously I have used Spring MVC, XML based configuration. I am new to Spring Boot and tried to follow resources on web to start the new project, but I couldn't get it. Added required libraries and some simple setup but without success. Even Spring Security login is not successful, which I am doing of XML based one successfully.
My project setup is in Spring Boot 1.5.9 RELEASE, which includes Spring Data, Spring AOP/AspectJ, Spring Security, Spring WebMvc, Hibernate, MySQL, HikariCP, Transaction Management, Jackson and other relevant tech. I am not using ThymeLeaf. With the current configuration, I even can't access the static contents form resources/static/**.
I did tested 'aspect' for '#Controller' calls and works well. And now I tried Spring Security basic login with 'JSP' but couldn't get pass. I have uploaded the project setup in GitHubhttps://github.com/shakyasudeep/Spring-Boot-Setup-Config.
And I reviewed the #Transactional annotation for transaction management but it needs to be declared on every #Service which will be calling DAO #Repository, previously I implemented this one time in XML to reflect on the overall desired package.
The code is :
<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
<!-- MUST have transaction manager, using aop and aspects -->
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<jpa:repositories base-package="com.eeposit.hub.dao"/>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="find*" read-only="true" />
<tx:method name="*" propagation="REQUIRED" rollback-for="Throwable"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="userServicePointCut"
expression="execution(* com.eeposit.hub.service.impl.*ServiceImpl.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="userServicePointCut" />
</aop:config>
I used EntityManagerFactory previously but now will be using Spring Data. I couldn't find a good reference for this(i.e.Declarative Transaction using Java code). How can we implement with just Java Code ?
Also I will also need #Async as well as Scheduler yet to configure.
And need to use message converters using Jackson, previously implemented by following code :
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper">
<bean class="com.fasterxml.jackson.databind.ObjectMapper">
<property name="serializationInclusion" value="NON_NULL"/>
</bean>
</property>
<property name="supportedMediaTypes" value="application/json"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
File upload using :
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10000000" />
</bean>
And external resource mapping :
Please provide some help/advice by committing to the GitHub repo. I will be here to review your valuable advice.

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

When I execute the code, its showing org.springframework.transaction.UnexpectedRollbackException Transaction rolled back because it has been marked as rollback-only. But its not rolling back.
My Code:
Service level
public void checkTransaction(Users user) throws Exception {
adminDao.insertUser(user);
System.out.println("Transaction active :: " + TransactionSynchronizationManager.isActualTransactionActive());
throw (new Exception("Testing Transaction"));
}
xml
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<tx:annotation-driven proxy-target-class="true"
transaction-manager="transactionManager" />
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* myapp.admin.service.AdminService.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>
POJO
My POJO (Users) Bean is not a annotated one, its mapped to hbm file. But it is registered in mapping resources.
<bean id="mysessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="mappingResources">
<list>
<value>myapp/admin/vo/Users.hbm.xml</value></list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
I was suffering from the same problem. What happens is that in the Service layer you can not make a query of type select and after it, an insert.
You need to separate the processes. In my case, declare a component class and, through it, call the processes of my service separately.
I hope it is useful for you ;)

Spring boot with transactional configuration

I am new to Spring Boot. I was trying to use Spring Boot with hibernate and mysql DB. I was trying to search for how to use spring's transactional configuration using spring boot. In normal spring application where you have xml files you define transaction using aop as below
<!-- this is the service object that we want to make transactional -->
<bean id="fooService" class="x.y.service.DefaultFooService"/>
<!--the transactional advice (what 'happens'; see the
<aop:advisor/>bean below)-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!--the transactional semantics...-->
<tx:attributes>
<!--all methods starting with 'get' are read-only-->
<tx:method name="get*" read-only="true"/>
<!--other methods use the default transaction settings (see below)-->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<!--ensure that the above transactional advice runs for any execution
of an operation defined by the FooService interface-->
<aop:config>
<aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
</aop:config>
<!--don't forget the DataSource-->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:#rj-t42:1521:elvis"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
</bean>
<!--similarly, don't forget the PlatformTransactionManager-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
Using above config you can ask spring to attach a read-only transaction to only get* method and default transaction to all other methods.
How do you achieve this(defining transaction aop on methods using wildcard) using Spring Boot?
Tried searching this on google but couldn't find anything. :(
Please guide me to the solution or any preexisting link.
Thanks
From the reference doc, You can do this
#Configuration
#EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
public class MyConfiguration {
}
In you case you can disable the configuration altogether.
Link here.
http://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-auto-configuration.html
As M. Deinum commented that if you can not skip the xml configuration then you can use it using #ImportResource annotation and provide your xml file name. The xml should be available on the classpath.

Spring 3 and hibernate 4.X facing a transaction Manager Exception in destroy-method

We are currently using Spring 3 with hibernate 4.4 in our project.
A snippet of my database config xml looks as follows
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass">
<value>${jdbc.driver.className}</value>
</property>
<property name="jdbcUrl">
<value>${jdbc.url}</value>
</property>
<property name="user">
<value>${jdbc.username}</value>
</property>
<property name="password">
<value>${jdbc.password}</value>
</property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource">
<ref bean="dataSource" />
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.hibernate.dialect}</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
<prop key="hibernate.current_session_context_class">managed</prop>
</props>
</property>
<property name="packagesToScan" value="com.sample.entity" />
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<tx:annotation-driven />
While we were testing our war , we came across this exception .
13:27:19,511 ERROR TransactionInterceptor:419 - Application exception overridden by rollback exception
org.springframework.beans.factory.BeanCreationNotAllowedException:
Error creating bean with name 'transactionManager': Singleton bean creation not allowed
while the singletons of this factory are in destruction (Do not request a bean from a
BeanFactory in a destroy method implementation!)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:212)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:248)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:100)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
I am unable to figure out if this is because of the destroy-method =close mentioned in the config file . I am also using the #Transactional annotation at both the Service layer and the database layer . Will this cause any issue?
We were trying to test a scenario where in multiple people (around 150) are all trying to access our application at the same time.
Kindly help me out.. Please do let me know, If more details are needed.
Thanks
As the spring doc says in Section 3.6.1.5
The order of startup and shutdown invocations can be important. If a "depends-on" relationship exists between any two objects, the dependent side will start after its dependency, and it will stop before its dependency. However, at times the direct dependencies are unknown. You may only know that objects of a certain type should start prior to objects of another type. In those cases, the SmartLifecycle interface defines another option, namely the getPhase() method as defined on its super-interface, Phased.
So you need the bean to implement the SmartLifeCycle, Javadoc for SmartLifeCycle Interface 1: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-factory-lifecycle-processor.
Hope this helps !!

Spring 3.1 + Hibernate 4.1 Propagation.Supports issue

I'm migrating my project from Spring 3.0 +hibernate 3.6.x to S3.1 + H4.1
my new code is the following
<context:component-scan base-package="x.y.z">
</context:component-scan>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.x</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="annotatedClasses">
<list>
<value>x.y.z.entities.Student</value>
</list>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<aop:config>
<aop:pointcut id="daoServicePoint"
expression="execution(* x.y.z.StudentDao.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="daoServicePoint"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
When running getStudent method marker as SUPPORTS and read only I'm getting
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1024)
It used to be ok with Spring 3.0 and Hibernate 3.6.x now it was changed. I undestood from Spring forums that mow I need mark transaction REQUIRED if I need to use sessionFactory.getCurrentSession();
I used lower level technique in order to get maximum concurrent speed in my code.
When performing operations which require several get/save/update/ queries i did it the following way:
called method marked as SUPPORTS.
Performed all get queries which are also marked as SUPPORTS inside
first method.
then started queries which marked as REQUIRED inside the same method and this is a point
where my roll-able back transaction begins.
I got good performance improvement using this technique, but marking all my methods as REQUIRED destroys it.
How can work around it?
I encountered the same issue when experimenting with Spring and Hibernate 3 / 4.
It looks like this is a known issue, which is described in the following JIRA link.
https://jira.springsource.org/browse/SPR-9020
It looks like Hibernate 4 version of SpringSessionContext does not open a new session if there is no existing transaction/session open and the called method #Transactional is configured with propagation = Propagation.SUPPORTS.
i think you can still mark transaction as readonly. not sure if it has performance impact.

Categories