How to access multiple remote redis with JedisConnectionFactory? - java

I made a manager/Service Server system.
Manager server collects data from database and send that data to multiple Service servers.
My code works nice when I have only 1 server. My configuration like below.(root-context.xml)
<bean id="connectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="127.0.0.1"/>
<property name="port" value="6379"/>
</bean>
The Problem is Service servers should be multiple. Is there any way to set multiple connection list with spring configurations? Thanks:D
P.S
I know the way to use JedisHelper.java which can be found easily in github. However, what I want to do is figure this out in spring root-context.xml.

you need to use a Jedis Pool.
http://docs.spring.io/spring-data/redis/docs/1.0.6.RELEASE/api/org/springframework/data/redis/connection/jedis/JedisConnectionFactory.html
You need to specify a pool and set it up with all your servers.

Related

Redis Token Store

I want to deploy my REST API on a clustered environment. For that, I need to store my OAuth 2.0 tokens in a shared Token store. Currently I'm using Spring Security's InMemoryTokenStore, which can't be shared on multi node cluster. I'm planning to store tokens using Redis.
I found that the latest release of Spring-Security OAuth i.e. 2.8.0 provides RedisTokenStore also. I've some doubts regarding this:
What changes are required for using RedisTokenStore in the existing spring-security xml configuration. Currently I'm using InMemoryTokenStore.
How to make RedisTokenStore shareable with all nodes in the cluster.
Can I use a Redis cluster to store the tokens, in case yes How?
About first question:
First, give you spring-security xml example about redis token store to reference
<!--Use Redis Token Store-->
<beans:bean id="tokenStore"
class="org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore">
<beans:constructor-arg name="connectionFactory" ref="redisConnectionFactory"/>
</beans:bean>
<!--create redis connection factory and set db 1-->
<beans:bean id="redisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<beans:property name="hostName" value="localhost"/>
<beans:property name="port" value="6379"/>
<beans:property name="password" value=""/>
<beans:property name="database" value="1"/>
</beans:bean>
Second, you need add spring data redis and jedis jar into your project, I use gradle, add items in dependencies like:
......
compile 'org.springframework.data:spring-data-redis:1.6.2.RELEASE'
compile 'redis.clients:jedis:2.8.0'
......
About sencond question:
If your all nodes of one cluster use one reids server or cluster, your access token will share among all nodes. You can check your redis db data, and track access process to verify this. So you don't worry about it.

Spring transaction boundary and DB connection holding

I am using spring boot and hibernate over jpa with tomcat connection pooling. Can you please help me understanding how spring uses DB connections during transactions. For example consider following scenario:
We have DB connection pool of 2 connections.
Spring starts a transaction i.e. call method decorated with #Transactional annotation.
This method do a DB update
The calls an external service
As response is received from the external service, it updates DB and return.
Spring commits the transaction
Assuming the external service(step 4) takes 1 minute to complete, how many DB connections will be available in the DB pool?. Assuming, spring keeps hold of DB connection until the transaction completes, there will be only 1 DB connection available for any request received during this time and if we received more than 1 requests, they will have to wait for DB connection.
Please confirm my understanding and if it is correct, suggest how I can handle this situation in a high transaction volume system.
Thanks
First your understanding is correct. See the spring documentation about declarative transaction management.
I guess you do the external service call within the transaction, because you want the database changes to be rollbacked in case of an exception. Or in other words you want the db updates to reflect the state of the external service call.
If so you can't move it out the transaction boundary. In this case you should either increase your connection pool size or maybe you can delegate long running transactions to a dedicated server node that handles them. This would keep e.g. a "main" server node that handles user requests away from long running transactions.
And you should think about the data consistency. Is it really necessary that the db update must be synchronized with the external service call? Can the external service call be moved out of the transaction boundary?
You can specify initial size and maximum size of connection pool as per your requirement(depends on the performance of your application).
For example,
<bean id="springDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
<property name="url" value="jdbc:oracle:thin:#localhost:1521:SPRING_TEST" />
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="username" value="root" />
<property name="password" value="root" />
<property name="removeAbandoned" value="true"/>
<property name="initialSize" value="20" />
<property name="maxActive" value="30" />
</bean>
this will create 20 database connection as initialSize is 20 and goes up to 30 Database connection if required as maxActive is 30. you can customize your database connection pool by using different properties provided by Apache DBCP library. Above example is creating connection pool with Oracle 11g database and i am using oracle.jdbc.driver.OracleDriver comes along with ojdbc6.jar or ojdbc6_g.jar

dynamic name for broker in ActiveMQ to run 2 or more instances in same machine

I need run 2 instances of a standalone application which uses JMS with a local ActiveMQ in the same machine. I have a jms-context configuration file that is loaded when the application starts. I use KahaDB as persistence adapter
File jms-context of both instances is the same, so property "brokerName" of the localBroker has the same name.
<bean id="broker" class="org.apache.activemq.xbean.XBeanBrokerService">
<property name="useJmx" value="true"/>
<property name="brokerName" value="fileProcessorLocalBroker"/>
<property name="persistent" value="true"/>
<property name="destinationPolicy" ref="destinationPolicy"/>
<property name="managementContext" ref="managementContext"/>
<property name="persistenceAdapter" ref="persistenceAdapter"/>
...
</bean>
When I run the second instance of my application I get the following:
2014-07-21 12:37:04,377 INFO [org.apache.activemq.store.SharedFileLocker] - <Database activemq-data\fileProcessorLocalBroker\KahaDB\lock is locked... waiting 10 seconds for the database to be unlocked. Reason: java.io.IOException: File 'activemq-data\fileProcessorLocalBroker\KahaDB\lock' could not be locked.>
Is there anyway of use a dynamic name for the property brokerName of localbroker?
Regards
ActiveMQ itself doesn't have support for starting up with dynamic Broker names. You can however use property expressions to read the name from some ENV value or other source which you define. See this article for some clues:

help me avoid connection timeout with JPA, Hibernate & MySQL

I'm using JPA (Hibernate as provider), Glassfish and MySQL. Everything works great in development, but when I deploy the app to a test server and let it run (largely idle) overnight, I'm usually greeted with this in the morning:
[#|2011-03-09T15:06:00.229+0000|INFO|glassfish3.0.1|javax.enterprise.system.std.com.sun.enterprise.v3.services.impl|_ThreadID=23;_ThreadName=Thread-1;|ERROR [htt\
p-thread-pool-8080-(1)] (JDBCTransaction.java:91) - JDBC begin failed
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 41,936,868 milliseconds ago. The last packet \
sent successfully to the server was 41,936,868 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expirin\
g and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connec\
tion property 'autoReconnect=true' to avoid this problem.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:532)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1118)
at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3321)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1940)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2113)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2562)
at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:4956)
at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:87)
at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1473)
at org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:60)
I tried using the following in my persistence.xml, but it didn't help:
<property name="hibernate.c3p0.min_size" value="5"/>
<property name="hibernate.c3p0.max_size" value="20"/>
<property name="hibernate.c3p0.idleTestPeriod" value="30"/>
<property name="hibernate.c3p0.timeout" value="0"/>
<property name="hibernate.c3p0.max_statements" value="0"/>
So that's the C3p0 configuration; it's entirely possible I'm missing the part that actually tells hibernate "hey, use c3p0".
I'm about to try the suggestion that's right there in the error message: add autoReconnect=true to my JDBC URL, but this is really starting to feel like cargo-cult development at this point. I would appreciate some guidance on the proper way to address this issue. It's hard to debug, because the test cycle is effectively "run it overnight, see what happens in the morning".
I should probably mention how I'm actually using connections in my app. I have a custom Servlet Filter that intercepts all requests. It creates an EntityManager, stores it in a ThreadLocal, and is closed by the filter in a catch/finally block. All my entities obtain a reference to the EntityManager from the ThreadLocal.
It's entirely possible that my filter is at fault, but as it only seems to happen after idle periods, I suspect something else is wrong. I do intend to move to Seam/Weld when I have a chance to catch my breath, but for now I'm relying on this filter.
Edit: here's the TL;DR solution:
use your container's connection pool, if you can (thanks, #partenon)
make sure your connection pool uses connection validation (thanks, #matt b)
In my case, I had to go into the Glassfish console under Resources/JDBC/Connection Pools, Advanced Tab, and then enable Connection Validation:
This was really the crucial step. You also probably want to set Validate At Most Once to something reasonable, say 100 seconds. If you're using C3P0 or similar, make sure you configure idle_test_period and preferredTestQuery.
Whatever you end up doing, it's important to test out your changes to see if they have the desired effect. To make the timeout happen faster in MySQL, you can temporarily set the wait_timeout to something low like 30 seconds by editing my.cnf. This was a tremendous help in debugging this problem, as it allowed me to test changes in seconds, rather than hours.
I think the real question is: why are you using an external connection pooling mechanism instead of using Glassfish' own pooling? Your app server is better suited to provide this kind of service to your application. "External" connection pooling mechanisms are better suited for standalone applications, not in-container applications.
You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.
Just a shot in the dark, but have you taken a look at setting the autoReconnect=true property in your JDBC driver? Or consider disabling the server-side setting for client connection timeouts.
I think the property to set the connection test period is idle_test_period, not idleTestPeriod as per C3P0 documentation here. So you should be using:
<property name="hibernate.c3p0.idle_test_period" value="30"/>
instead.
I was getting the same problem and it took time to figure out the solution.
I use Hibernate 4.0.1 and mysql 5.1(no spring framework) and I was facing the issue. First make sure that you configured the c3p0 jars properly which are essential.
I used these properties in hibernate.cfg.xml
<property name="hibernate.c3p0.validate">true</property>
<property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>
<property name="hibernate.c3p0.min_size">5</property>
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.max_statements">50</property>
<property name="hibernate.c3p0.preferredTestQuery">SELECT 1;</property>
<property name="hibernate.c3p0.testConnectionOnCheckout">true</property>
<property name="hibernate.c3p0.idle_test_period">10</property>
<property name="hibernate.c3p0.acquireRetryAttempts">5</property>
<property name="hibernate.c3p0.acquireRetryDelay">200</property>
<property name="hibernate.c3p0.timeout">40</property>
But it's of no use 'cause C3p0 was still taking the default properties not the properties which I set in hibernate.cfg.xml, You can check it in logs. So, I searched many websites for right solution and finally I came up with this. remove the C3p0 properties in cfg.xml and create c3p0-config.xml in the root path(along with cfg.xml) and set properties as follows.
<c3p0-config>
<default-config>
<property name="automaticTestTable">con_test</property>
<property name="checkoutTimeout">40</property>
<property name="idleConnectionTestPeriod">10</property>
<property name="initialPoolSize">10</property>
<property name="maxPoolSize">20</property>
<property name="minPoolSize">5</property>
<property name="maxStatements">50</property>
<property name="preferredTestQuery">SELECT 1;</property>
<property name="acquireRetryAttempts">5</property>
<property name="acquireRetryDelay">200</property>
<property name="maxIdleTime">30</property>
</default-config>
</c3p0-config>
but if you run, ORM takes the jdbc connection but not C3p0 connection pool 'cause we should add these properties in hibernate.cfg.xml
<property name="hibernate.c3p0.validate">true</property>
<property name="hibernate.connection.provider_class">org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider</property>
now everything works fine(At least it worked fine for me) and the issue is solved.
check the following for references.
http://www.mchange.com/projects/c3p0/index.html#configuring_connection_testing
https://community.jboss.org/wiki/HowToConfigureTheC3P0ConnectionPool
I hope this solves your problem.

Oracle connections in Spring

I am using Oracle 9 JDBC Thin Driver - the connection string I have used for standard JDBC was:
jdbcConn.connect("jdbc:oracle:thin:myDevDb/myDevDb#fooServer:1521:MYSIDNAME");
...just trying to get my head around using this kind of connection in Spring 2.5.
How do you wire up Spring to an Oracle connection - think it has something to do with an XML conifg file but not sure, there seems to be a couple of ways to do it.
Any help much appreciated...
LATEST EDIT
Thanks to those who have responded so far - but I need a bit of a "leg up" - on the part where you configure in the database connection string setup in your config, where do you put this info, and how?
I have an existing Java web application - and I am trying to get to grips with how I 'shoehorn' Spring into my existing app.
There are a few ways of doing this and it depends on what your environment is. If you're using Spring there's a fair chance you're deploying a Web application or you're otherwise in a J2EE environment. If this is the case (and arguably even if it isn't) you probably want to configure a DataSource.
This is a fairly minimal solution:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
The above is using the Apache (Jakarta Commons) database connection pooling but your appserver probably has an alternative you may want to use instead. Also, different database vendors have their own data source implementations too (eg OracleDataSource and OracleXADataSource for Oracle).
Note the use of properties like jdbc.username. This is a typical configuration because database configurations typically vary between environment. You can activate a property configurator with something like:
<bean id="jdbcConfiguration" class="org.springframework.beans.factory.config.PropertiesPlaceholderConfigurer">
<property name="location" value="classpath:jdbc.properties"/>
</bean>
Now you probably want transactions too I would imagine. The easiest way is to use a platform transaction manager but, like with most things Spring, there are multiple ways of doing it.
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
After this you can use this bean directly or (arguably more common) you can use declarative transactions with AOP (annotations).
More on these subjects in the (superb) Spring reference documentation.

Categories