Spring Social & JPA - Having two datasources pointing to the same database - java

I am currently working on a Java application that uses Spring Social to communicate with Twitter. The application uses Spring Data (JPA) to manage users locally.
When I authorize access on Twitter and Twitter makes a request to the OAuth1 callback URL, my application chokes and I see the following in my log file (I've shortened the stacktrace):
ERROR 2013-08-18 16:05:09,511 http-bio-8080-exec-44] org.springframework.transaction.interceptor.TransactionInterceptor [TransactionAspectSupport.completeTransactionAfterThrowing
(): "Application exception overridden by rollback exception"]
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [insert into UserConnection (userId, providerId, providerUserId, ra
nk, displayName, profileUrl, imageUrl, accessToken, secret, refreshToken, expireTime) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)]; SQL state [null]; error code [0]; You can't operate
on a closed Connection!!!; nested exception is java.sql.SQLException: You can't operate on a closed Connection!!!
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:603)
...
Caused by: java.sql.SQLException: You can't operate on a closed Connection!!!
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:118)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:77)
at com.mchange.v2.c3p0.impl.NewProxyConnection.prepareStatement(NewProxyConnection.java:171)
at org.springframework.jdbc.core.JdbcTemplate$SimplePreparedStatementCreator.createPreparedStatement(JdbcTemplate.java:1438)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:581)
... 94 more
Caused by: java.lang.NullPointerException
at com.mchange.v2.c3p0.impl.NewProxyConnection.prepareStatement(NewProxyConnection.java:135)
... 96 more
[WARN 2013-08-18 16:05:09,513 http-bio-8080-exec-44] org.springframework.social.connect.web.ConnectController [ConnectController.oauth1Callback(): "Exception while handling OAuth1 callback (Could not roll back JPA transaction; nested exception is javax.persistence.PersistenceException: unexpected error when rollbacking). Redirecting to twitter connection status page."]
After some research I believe I am essentially seeing the issue described here:
https://jira.springsource.org/browse/SOCIAL-384
For some reason the fact that Spring Social core uses a JdbcUsersConnectionRepository does not play nice with my JPA set up. I understand that a plugin is available; however I decided to experiment with the datasource configurations and created two essentially identical datasource bean configurations (with different names) and tied one to Spring Social and the other to my entity manager configuration.
With this setup the above error goes away and I am able to see my Twitter user connection get persisted to the database. My question is: is doing something like this a valid solution? What are some other scenarios that would require duplicate datasources? On the flip side - what are possible repercussions for using such a configuration?

Downside of this solution is that you need to reduce maximum capacity of connection pool.
Example: imagine that you have a connection pool with max 30 connections in it. Now you want to add another datasource for Spring Social. I suppose that each your user will use 2 datasources simultaneously. So you need 2 connection pools with max 15 connections in each. Now it will be much easier to hit the limit.

Related

Testing using HSQL DB in Spring - cached PreparedStatement error

Our backend app is Spring/Java based batch server. Our backend db is Oracle.
I am writing unit tests to use HSQL DB instead of Oracle. I inserted some test data and running Select query on it. Its not using any parameters.
Using a 'NamedJDBCTemplate', I call the
'query(String sql, RowCallBackHandler rch)' method to run the query and read results.
I get the error
org.springframework.jdbc.UncategorizedSQLException:
PreparedStatementCallback; uncategorized SQLException for SQL.... SQL
state [null]; error code [0]; A problem occurred while trying to
acquire a cached PreparedStatement in a background thread.; nested
exception is java.sql.SQLException: A problem occurred while trying to
acquire a cached PreparedStatement in a background thread
I wonder is this because of some config settings.. My settings are below
hibernate.hbm2ddl.auto=create
hibernate.connection.driver_class=org.hsqldb.jdbc.JDBCDriver
hibernate.connection.url=jdbc:hsqldb:mem:mers;sql.syntax_ora=true
hibernate.connection.username=mers hibernate.connection.password=mers
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.ejb.naming_strategy=org.hibernate.cfg.ImprovedNamingStrategy
hibernate.cache.use_query_cache=false hibernate.c3p0.minPoolSize=3
hibernate.c3p0.maxPoolSize=25 hibernate.c3p0.timeout=300
#hibernate.c3p0.maxStatements=50000 hibernate.c3p0.maxStatements=50000
#hibernate.c3p0.maxStatementsPerConnection=1000 hibernate.c3p0.maxStatementsPerConnection=1000
hibernate.c3p0.idleConnectionTestPeriod=1800
hibernate.c3p0.acquireIncrement=3 hibernate.cache.provider_class=
hibernate.cache.use_second_level_cache=false
hibernate.event.merge.entity_copy_observer=allow showSql=true
Any leads what could be causing it ? Is it because of 'prepared statement caching' ?

Transaction is ended due to timeout due to updating same table using two Message Drive Beans

I am using two Message Drive Beans (MDB), to update same table. I am using EJB 3.0 and using transaction type as
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
some times one of the methods are getting error like "Transaction is ended due to timeout" and MDB is getting deactivated. Hence , I have to restart the server.
Can I use any other type of transaction attribute #TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) to avoid the timeout error ?
Here is my stacktrace.
[:] CWWMQ0007W: The message endpoint Rsme#RsmeEJB.jar#GemsInqMDB has been paused by the system. Message delivery failed to the endpoint more than 0 times. The last attempted delivery failed with the following error: javax.ejb.EJBTransactionRolledbackException: Transaction rolled back; nested exception is: javax.transaction.TransactionRolledbackException: Transaction is ended due to timeout
javax.transaction.TransactionRolledbackException: Transaction is ended due to timeout
at com.ibm.tx.jta.impl.EmbeddableTranManagerImpl.completeTxTimeout(EmbeddableTranManagerImpl.java:62)
at com.ibm.tx.jta.impl.EmbeddableTranManagerSet.completeTxTimeout(EmbeddableTranManagerSet.java:85)
at com.ibm.ejs.csi.TransactionControlImpl.completeTxTimeout(TransactionControlImpl.java:1347)
at com.ibm.ejs.csi.TranStrategy.postInvoke(TranStrategy.java:242)
at com.ibm.ejs.csi.TransactionControlImpl.postInvoke(TransactionControlImpl.java:579)
at com.ibm.ejs.container.EJSContainer.postInvoke(EJSContainer.java:4843)
at com.maybank.meaa.local.EJSLocal0SLMeaaEntityBean_877f3cd5.insertPD003Result(EJSLocal0SLMeaaEntityBean_877f3cd5.java)
at com.maybank.meaa.mdbs.GemsInqMDB.onMessage(GemsInqMDB.java:75)
at com.ibm.ejs.container.MessageEndpointHandler.invokeMdbMethod(MessageEndpointHandler.java:1163)
at com.ibm.ejs.container.MessageEndpointHandler.invoke(MessageEndpointHandler.java:842)
at $Proxy27.onMessage(Unknown Source)
at com.ibm.mq.connector.inbound.MessageEndpointWrapper.onMessage(MessageEndpointWrapper.java:131)
at com.ibm.mq.jms.MQSession$FacadeMessageListener.onMessage(MQSession.java:147)
at com.ibm.msg.client.jms.internal.JmsSessionImpl.run(JmsSessionImpl.java:2665)
at com.ibm.mq.jms.MQSession.run(MQSession.java:862)
at com.ibm.mq.connector.inbound.WorkImpl.run(WorkImpl.java:279)
at com.ibm.ejs.j2c.work.WorkProxy.run(WorkProxy.java:608)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1650)
javax.ejb.EJBTransactionRolledbackException: Transaction rolled back; nested exception is: javax.transaction.TransactionRolledbackException: Transaction is ended due to timeout
Caused by: javax.transaction.TransactionRolledbackException: Transaction is ended due to timeout
at com.ibm.tx.jta.impl.EmbeddableTranManagerImpl.completeTxTimeout(EmbeddableTranManagerImpl.java:62)
at com.ibm.tx.jta.impl.EmbeddableTranManagerSet.completeTxTimeout(EmbeddableTranManagerSet.java:85)
at com.ibm.ejs.csi.TransactionControlImpl.completeTxTimeout(TransactionControlImpl.java:1347)
at com.ibm.ejs.csi.TranStrategy.postInvoke(TranStrategy.java:242)
at com.ibm.ejs.csi.TransactionControlImpl.postInvoke(TransactionControlImpl.java:579)
at com.ibm.ejs.container.EJSContainer.postInvoke(EJSContainer.java:4843)
at com.maybank.meaa.local.EJSLocal0SLMeaaEntityBean_877f3cd5.insertPD003Result(EJSLocal0SLMeaaEntityBean_877f3cd5.java)
at com.maybank.meaa.mdbs.GemsInqMDB.onMessage(GemsInqMDB.java:75)
at com.ibm.ejs.container.MessageEndpointHandler.invokeMdbMethod(MessageEndpointHandler.java:1163)
at com.ibm.ejs.container.MessageEndpointHandler.invoke(MessageEndpointHandler.java:842)
at $Proxy27.onMessage(Unknown Source)
at com.ibm.mq.connector.inbound.MessageEndpointWrapper.onMessage(MessageEndpointWrapper.java:131)
at com.ibm.mq.jms.MQSession$FacadeMessageListener.onMessage(MQSession.java:147)
at com.ibm.msg.client.jms.internal.JmsSessionImpl.run(JmsSessionImpl.java:2665)
at com.ibm.mq.jms.MQSession.run(MQSession.java:862)
at com.ibm.mq.connector.inbound.WorkImpl.run(WorkImpl.java:279)
at com.ibm.ejs.j2c.work.WorkProxy.run(WorkProxy.java:608)
at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1650)
.
Create two different tables with the same structure to avoid the deadlock instead of using same table for two MDB
This error can be caused by normally 2 things
1- EJB Timeout
2- Datasource Timeout
You can configurate both to a greater value.
1 - WebSphere Application servers > <> container properties > Transaction service
Total transaction lifetime timeout - this will be the default value for EJB without this property
Maximum transaction timeout - this wil be the max value for any transaction managed by WAS
2 - Data sources > <> > Connection pools
Connection timeout
Unused timeout
Normally, the option 1 fix the problem.

NullPointerException when calling registerOutputParamater on CallableStatement

In my application I use a Stored Procedure, called SearchSubscriptionData, to lookup a number in two different subscription tables.
Database is accessed via a JDBC Configuration (MySQL drivers) on WebLogic 10.3.3. I only use one user (root, no password).
The code snippet that I use is:
Connection con = getConnection(); // perform lookup on JDBC Driver
CallableStatement cst = con.prepareCall("{CALL SearchSubscriptionData(?,?,?,?,?,?,?)}");
cst.setString("numTel", aBnumber); // input param (B-Number)
cst.registerOutParameter("numberFoundFlag", Types.INTEGER);
cst.registerOutParameter("radixFound", Types.VARCHAR); // <-- this instruction generates a NullPointerException
cst.registerOutParameter("outRoutingId", Types.VARCHAR);
...// plus three more parameters, not important now
Exception is:
[#|2013-09-16T14:35:51.340+0200|SEVERE|ece|com.ericsson.core.db.DBManager|_ThreadID=451;_ThreadName=[ACTIVE] ExecuteThread: '19' for queue: 'weblogic.kernel.Default(self-tuning)';ClassName=com.ericsson.core.db.DBManager;MethodName=searchSubscriptionData;_RequestID=<unavailable>|Exception: java.lang.NullPointerException
at com.mysql.jdbc.CallableStatement.getNamedParamIndex(CallableStatement.java:1250)
at com.mysql.jdbc.CallableStatement.registerOutParameter(CallableStatement.java:1668)
at weblogic.jdbc.wrapper.CallableStatement_com_mysql_jdbc_CallableStatement.registerOutParameter(Unknown Source)
at com.ericsson.core.db.DBManager.searchSubscriptionData(DBManager.java:139)
at com.ericsson.jee.ngin.services.screening.service.Screening.getSubscriptionDataWithStoreProcedure(Screening.java:2481)
at com.ericsson.jee.ngin.services.screening.service.Screening.onInitialDP(Screening.java:1463)
at com.ericsson.jee.ngin.services.screening.service.Screening.handleMessage(Screening.java:384)
at com.ericsson.cba.cs1plus.traffic.impl.CallSession.dispatchEvent(CallSession.java:1303)
at com.ericsson.cba.cs1plus.traffic.impl.CallSession.doInitialDpEvent(CallSession.java:537)
at com.ericsson.cba.cs1plus.traffic.impl.CallSession.doHandleNetworkEvent(CallSession.java:331)
at com.ericsson.cba.cs1plus.traffic.impl.CallSession.handleMessage(CallSession.java:234)
at com.ericsson.jee.ngin.services.screening.service.Screening.handleEvent(Screening.java:327)
at com.ericsson.jee.ngin.services.screening.service.Screening.onCreate(Screening.java:236)
at com.ericsson.ngin.session.mdb.DefaultServiceMDB.onCreate(DefaultServiceMDB.java:56)
at sun.reflect.GeneratedMethodAccessor677.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
[...more stack trace here...]
Does anyone see anything familiar here? Important to highlight that the same error happens if the stored procedure is removed from MySQL DB, like if the error would be an access error to store procedure itself: but which kind of error?
What is indeed strange to me is why the NullPointerException applies to "second" registerOutParameter call and not to the first one already.
Any suggestion?

Hibernate get action cause an update action

We use HibernateTemplate to get an object, but it cause an update action.Our database are read-only, because we don't need to update data.
Why that happen? Please Help me..
My code:
public <T> T get(Class<T> clasz, Serializable id) {
return (T) getHibernateTemplate().get(clasz, id);
}
The error message as follow:
org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: Could not execute JDBC batch update; uncategorized SQLException for SQL [update kytv_resource_station set area=?, create_id=?, create_time=?, display=?, modify_id=?, modify_time=?, nature=?, partner=?, showDomain=?, status=?, tv_character=?, tv_desc=?, tv_elogo=?, tv_elogo_id=?, tv_keyword=?, tv_logo=?, tv_logo_id=?, tv_name=?, tv_order=?, tv_short_name=?, tv_show_name=?, tv_tvm_name=? where id=?]; SQL state [HY000]; error code [1290]; The MySQL server is running with the --read-only option so it cannot execute this statement; nested exception is java.sql.BatchUpdateException: The MySQL server is running with the --read-only option so it cannot execute this statement
at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.translate(SQLStateSQLExceptionTranslator.java:124)
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.translate(SQLErrorCodeSQLExceptionTranslator.java:322)
at org.springframework.orm.hibernate3.HibernateAccessor.convertJdbcAccessException(HibernateAccessor.java:424)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:410)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:424)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.get(HibernateTemplate.java:522)
at org.springframework.orm.hibernate3.HibernateTemplate.get(HibernateTemplate.java:516)
Your program has error because of this query
update kytv_resource_station set area=?, create_id=?, create_time=?, display=?, modify_id=?, modify_time=?, nature=?, partner=?, showDomain=?, status=?, tv_character=?, tv_desc=?, tv_elogo=?, tv_elogo_id=?, tv_keyword=?, tv_logo=?, tv_logo_id=?, tv_name=?, tv_order=?, tv_short_name=?, tv_show_name=?, tv_tvm_name=? where id=?
Your program displays MySql Error 1290, in mysql documentation it means
The MySQL server is running with the %s option so it cannot execute this statement.
You mean Our database are read-only, so why do you make update operation.If you need correct answer, post your code with edit question.

Firebird query is crashing with org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544364. request synchronization error

I am using JdbcTemplate.queryForInt to insert a Row into the DB, and then get the ID back.
The Query is "INSERT INTO metadocs(NAME) values (?) RETURNING METADOCID". If I run the statement in Flamerobin, it works fine.
However, if I run it from Java, I get the following error:
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [INSERT INTO metadocs(NAME) values (?) RETURNING METADOCID]; SQL state [HY000]; error code [335544364]; GDS Exception. 335544364. request synchronization error; nested exception is org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544364. request synchronization error
Caused by: org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544364. request synchronization error
Does anyone have an idea what this could be caused by?
Unlike Oracle, I'm not sure that the Jaybird JDBC driver supports the RETURNING syntax. Alternatively, you might look at the getGeneratedKeys() method , discussed here.

Categories

Resources