After upgrading from Spring 3.0.0.M4 to 3.0.0.RC1 and Spring Security 3.0.0.M2 to 3.0.0.RC1, I've had to use a security:authentication-manager tag instead of defining an _authenticationManager like I used to in M4/M2. I've done my best at defining it, and ended up with this:
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider user-service-ref="userService">
<security:password-encoder hash="plaintext"/>
</security:authentication-provider>
</security:authentication-manager>
When I do my unit tests one at a time, this works great, and for most AJAX requests it works fine as well, but seemingly randomly, I get weird errors in my transactions where my database session seems to get closed midway in the work. The way I can provoke these errors is just sending a lot of different AJAX requests to my different controllers from the same client, then at least one of them will fail at random. Next time I try, that one will work and another will fail.
The error happens most frequently in my userDAO, but also quite frequently in other DAOS, and the exceptions include at least the following:
"java.sql.SQLException: Operation not allowed after ResultSet closed"
"org.hibernate.impl.AbstractSessionImpl:errorIfClosed(): Session is closed!"
"java.lang.NullPointerException at com.mysql.jdbc.PreparedStatement.fillSendPacket(PreparedStatement.java:2439)"
"java.util.ConcurrentModificationException at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(Unknown Source)"
"org.hibernate.LazyInitializationException: illegal access to loading collection"
etc...
Before, I used to define an _authenticationManager bean, and the same requests worked like a charm. But with RC1, I'm no longer allowed to define it. It used to look like this:
<bean id="_authenticationManager" class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<list>
<bean class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userService"/>
<property name="passwordEncoder">
<bean class="org.springframework.security.authentication.encoding.PlaintextPasswordEncoder" />
</property>
</bean>
</list>
</property>
</bean>
Have I defined my security:authentication-manager incorrectly so that it will share transactions for multiple requests from the same client? Should I define it differently, or should I define some other security: beans?
Is there something I have misunderstood that makes my database sessions close? In my head, each request has its own database connection and transaction. All getters and setters are synchronized methods, so I really shouldn't have any concurrency issues. All the REST controllers that the UI makes requests against are GET-requests and do read-only work. To my knowledge, not a single INSERT/UPDATE/DELETE is done during any of these requests, and I've inspected the database logs to verify this.
I look forward to hearing your suggestions on how to avoid these race-conditions.
Cheers
Nik
PS, my I've updated the question to be more specific that the problem is with the security:authentication-manager (or so it seems to me, if you have tips that it could be something else that would be great) that I'm forced to use instead of my own _authenticationManager starting with 3.0.0.RC1
PPS, here is the thread that made me understand I could no longer define an _authenticationManager: SpringSource Forum Post
It seems that I had a big problem in database session handling in my DAO, so I've made a write-up of my problem and posted the solution in another thread here at StackOverflow and asked for people's opinion on the solution. I hope it doesn't give more issues :-)
Cheers
Nik
Related
There is a service that connects to Oracle DB for reading data and it uses Hibernate-3.6 and SpringData-JPA-1.10.x. Heap dumps are getting generated frequently which results in out of memory on the hosts.
After analyzing few heapdumps using Eclipse MAT, found that the majority of the memory is accumulated in one instance of org.hibernate.engine.StatefulPersistenceContext -> org.hibernate.util.IdentityMap -> java.util.LinkedHashMap.
And the leak suspect says
The thread java.lang.Thread # 0x84427e10 ... : 29 keeps local
variables with total size 1,582,637,976 (95.04%) bytes.
The memory is accumulated in one instance of "java.util.LinkedHashMap"
loaded by "".
Searched it on StackOverflow and it says SessionFactory should be singleton and session.flush() and session.clear() should be invoked before each call to clear the cache. But SessionFactory is not explicitly initialized or used in the code.
What's causing the memory leak here (looks like the result of each query is cached and not cleared) and how to fix it?
More info about the Spring Data configuration:
TransactionManager is initialized as:
<tx:annotation-driven mode='proxy' proxy-target-class='true' />
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
....
</bean>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" depends-on="...">
....
</bean>
To interact with the table, an interface is declared extending Spring Data Repository and JpaSpecificationExecutor. Both are typed into the domain class that it will handle.
API activity method has the annotation #Transactional(propagation = Propagation.SUPPORTS, readOnly = true).
From what you describe this is what I expect to be going on:
Hibernate (actually JPA in general) keeps a reference to all entities it loads or saves for the lifetime of the session.
In a typical web application setup, this isn't a problem, because. A new session starts with each request and gets closed once the request is finished and it doesn't involve that many entities.
But for your application, it looks like the session keeps growing and growing.
I can imagine the following reasons:
something runs in an open session all the time without it ever closing. Maybe something like a batch job or a scheduled job which runs at regular intervals.
Hibernate is configured in such a way that it reuses the same session without ever closing it.
In order to find the culprit enable logging for opening and closing the session. Judging from https://hibernate.atlassian.net/browse/HHH-2425 org.hibernate.impl.SessionImpl should be the right log category and you probably need trace level logging.
Now test the various requests to your server and see if there are any sessions that get opened but not closed.
The question contains information about the creations of some beans. But the problem doesn't lie there. The problem is in your code, where have you use these beans.
Please check your code. Probably you are loading items in a loop. And the loop is wrapped with a transaction.
Hibernate creates huge intermediate objects, and it doesn't clean these before the transaction being completed (commit/rollback).
We are changing our ldap from the java ldap library to spring's to take advantage of the rollback. It mostly works. Mostly.
One of our problems is that whenever an exception is thrown, instead of the exception bubbling out, we get this:
Caused by: java.lang.ClassCastException: org.springframework.ldap.transaction.compensating.manager.ContextSourceAndHibernateTransactionManager$ContextSourceAndHibernateTransactionObject incompatible with org.springframework.orm.hibernate3.HibernateTransactionManager$HibernateTransactionObject
at org.springframework.orm.hibernate3.HibernateTransactionManager.doSetRollbackOnly(HibernateTransactionManager.java:696) ~[spring-orm-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:852) ~[spring-tx-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:822) ~[spring-tx-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:410) ~[spring-tx-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:114) ~[spring-tx-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90) ~[spring-aop-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.2.0.RELEASE.jar:3.2.0.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631) ~[spring-aop-3.2.0.RELEASE.jar:3.2.0.RELEASE]
This swallows up the exceptions. Yet, it doesn't seem to prevent the rollback from actually happening.
Relevant parts of our spring config:
<ldap:context-source
url="${LDAP_URL_SSL}"
base="${SEARCHBASE_DC}"
referral="follow"
authentication-source-ref="afmsAuthenticationSource" />
<ldap:ldap-template id="ldapTemplate" />
<bean id="txManager" name="txManager transactionManager" class="my.package.hibernate.HibernateTransactionManager">
<property name="sessionFactory" ref="enoteSessionFactory" />
<property name="defaultUserName" value="umc.not.provided" />
<property name="defaultApplicationId" value="umc" />
</bean>
<ldap:transaction-manager id="ldapTransactionManager" session-factory-ref="sessionFactory" >
<ldap:default-renaming-strategy />
</ldap:transaction-manager>
What you'll notice is that we have both a hibernate transaction manager (which we customized a long time ago and has worked forever) and the new contextsource transaction manager. Both are invoked via either AOP or #Transactional depending on which part of the code one is in.
We have a little disagreement in house as to whether we are supposed to REPLACE the existing tx manager with the ldap one (which might do both jobs) or ADD TO it. The dev doing the work thinks ADD TO. I think REPLACE, and i think this exception is a symptom of having both in play.
Anyway, can someone give advice on what might be causing this exception, and whether having one or both tx manager is the right way to use this library?
First of all I want to mention that I fully agree to only make the service layer transactional, but sometimes world is not perfect, and right now I´m in the middle of that situation.
Basically I have been assigned into a wonderful project with a legacy code of 4+ years. The thing is that the developers did not follow any pattern where to introduce the bussines logic so you can image multiples services call from the controller and after that some extra call to private method into the controller.
No budget to refactor, and we have many issues with ACID so the only solution that I found is make the controllers transactional and at least then have a full rollback if something in the middle of the request/response go wrong.
The problem is that I cannot make it works. I will describe you my configuration to see if you can help me out guys.
I have a DispatcherServlet that invoke webmvc-config.xml where I have the declaration of the controllers
<context:component-scan base-package="com.greenvalley.etendering.web.controller**" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
Then the contextConfiguration invoke my applicationContext.xml where I have all the rest of my Spring configuration.
After read so many tickets I tried many convination, for example try to declare again my controllers into the application context.
<tx:annotation-driven mode="aspectj"/> I tried with proxy as well
<context:component-scan base-package="com.greenvalley.etendering.web.controller.*" />
But still nothing.
In the configuration of my txManager I dont do nothing fancy, just add the reference to the entityManagerFactory and that´s it
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
In my controller I add the #Transactional, but nothing every time that I made a request to the #transactional class/method I dont see that the breakpoint into JpaTransactionalManager doBegin method stop
any suggestion please!
Regards
We are using Spring 2.6 and we use jdbcTemplate as well as NamedparameterJdbcTemplate in our system and configurations are as follows.
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
<property name="fetchSize" value="500>
</bean>
<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"></constructor-arg>
</bean>
While jdbcTemplate has a property "fetchSize", namedParameterJdbcTemplate does not have. I want to set the fetchSize for this so i came up with another constructor for namedParameterJdbcTemplate which accepts "jdbcTemplate", so i configured my bean as follows to use fetchSize of 500 which is already configured for jdbcTemplate:
<bean id="namedParameterJdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="jdbcTemplate"></constructor-arg>
</bean>
But after this i am getting following exceptions for few queries :
com.sybase.jdbc3.jdbc.SybSQLException: Cursor 'jconnect_implicit_16' was declared with a FOR UPDATE clause. This cursor was found to be read only.
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.translate(SQLStateSQLExceptionTranslator.java:121)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.translate(SQLErrorCodeSQLExceptionTranslator.java:322)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:582)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:616)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:641)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:657)
at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:123)
at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.query(NamedParameterJdbcTemplate.java:127)
Can someone please suggest its solution?
Unfortunately the above workaround has strange side effects.
Use of JdbcTemplate.query(...) to perform selects which occasionally result in 0 rows now throw the exception
Caused by: java.sql.SQLException: JZ0R2: No result set for this query.
Another obscure problem with few results on Google (and no helpful ones).
I'm now using the solution of creating a StreamingStatementCreator as described in an answer to this question How to manage a large dataset using Spring MySQL and RowCallbackHandler
This creates a Statement that has ResultSet.CONCUR_READ_ONLY set, but you can still use JdbcTemplate, rather than reverting back to Connections, Statements and ResultSets.
I'm also getting this exception.
It's related to Sybase jConnect for JDBC.
I found this workaround.
To quote the Sybase Programmers Reference jConnect for JDBC 6.05
There is no known advantage to setting LANGUAGE_CURSOR to true,
but the option is provided in case an application displays unexpected
behavior when LANGUAGE_CURSOR is false.
Go through all your mappings and make sure they are ok! Look for the proper types. This issue is normally caused by a lower level exception that is thrown up and caught by the SQLStateSQLExceptionTranslator. Normally it has something to do with the improper map object type.
I'm trying to use a JDBC Job Store in Quartz with the following code:
DateTime dt = new DateTime().plusHours(2);
JobDetail jobDetail = new JobDetail(identifier, "group", TestJob.class);
SimpleTrigger trigger = new SimpleTrigger(identifier, dt.toDate());
trigger.setJobName(identifier);
trigger.setJobGroup("group");
quartzScheduler.addJob(jobDetail, true);
quartzScheduler.scheduleJob(trigger);
And am configuring the scheduler as follows:
<bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
<property name="autoStartup" value="true" />
<property name="waitForJobsToCompleteOnShutdown" value="false" />
<property name="dataSource" ref="schedulerDataSource" />
<property name="nonTransactionalDataSource" ref="nonTXdataSource" />
<property name="quartzProperties">
<props>
<!--Job Store -->
<prop key="org.quartz.jobStore.driverDelegateClass">
org.quartz.impl.jdbcjobstore.StdJDBCDelegate
</prop>
<prop key="org.quartz.jobStore.class">
org.quartz.impl.jdbcjobstore.JobStoreCMT
</prop>
<prop key="org.quartz.jobStore.tablePrefix">QRTZ_</prop>
</props>
</property>
</bean>
The schedulerDataSource is a standard JNDI data source, the nonTXdataSource is configured via a simple org.springframework.jdbc.datasource.DriverManagerDataSource I have specified the job store class to be: org.quartz.impl.jdbcjobstore.JobStoreCMT and was hoping that the code:
quartzScheduler.addJob(jobDetail, true);
quartzScheduler.scheduleJob(trigger);
would not commit the job to the database when the each method is called. Basically when I call addJob the job is immediately saved to the database, the scheduleJob method causes the trigger information to be immediately saved in the database as well, but this tends to happen over two separate transactions already.
There is a fair bit of subsequent logic in the code that needs to be committed to the database together with the scheduled jobs in one transactions, however no matter what I try the jobs are committed by the scheduler to the database as soon as they methods are called. I tried in various environments Testing/Tomcat/Glassfish and various configurations of data sources but to no avail.
Can somebody point me into the direction of where I am going wrong?
Thank you.
Having thought this over a bit, now i believe you can achieve this providing your own wrapping DataSource but you should not do this. I think Quartz maintains some internal state in memory that must be in sync with the database (or at least it can do so). If you rollback a transaction or otherwise modify database state not notifying Quartz about this fact, it may not work as expected.
On the other hand you can use Quartz's pausing of the jobs to achieve similar effect: you simply create new job and pause it before adding any triggers. Then, you resume it only after you commit your transaction.
---------------------- my original answer ----------------------
I think, but I'm not sure, not tried this, that you can try the following:
You need a transaction around a code that uses DataSource.getConnection internally. To achieve that you have to use data source that'd be aware of global transaction state. I suppose that JBoss application server gives you just that (even with plain data source).
JBoss comes with a transaction manager (Arjuna) and data sources wrappers (JBoss app server internal) that are at least aware of global transaction state.
Other options include Atomikos and a XA data source, but i have less experience here.
Edit: if Quartz uses explicit COMMIT or setAutocommit(true) internally, both my suggestions would not work.
When you set datasource on SchedulerFactoryBean, spring uses below class as JobStore ( extension to Quartz's JobStoreCMT )
LocalDataSourceJobStore
This supports both transactional and non-transactional DataSource access.
Please try following
Remove property org.quartz.jobStore.class [Edit : Its ignored ,anyways]
Make sure the method which does addJob / ScheduleJob is in spring managed transaction.