I have an injected JDBCTemplate instance, and the code basically executes
private JdbcTemplate template;
public OutputType getOutput(InputType input) {
CallType call = new CallType(input);
CallbackType callback = new CallbackType(input);
OutputType output = (OutputType) template.execute(call, callback);
...
}
I assume the execute method actually connects to the database and retrieves the result. However, I am having trouble finding out how the control flow works from the documentation.
Is the response from execute blocking (thread occupies a CPU core the entire time waiting for the database response)? Is it synchronous, but not blocking (i.e. thread sleeps/is not scheduled until the response is ready)? Is it asynchronous (execute returns immediately but output is incomplete/null, all database processing logic is in the callback)?
I have used several different databases so I am unsure of what actually happens in JdbcTemplate. If my terminology is incorrect please let me know. Thanks!
The JDBC protocol itself is synchronous and blocking - it will block on socket I/O awaiting the database response. While this doesn't mean you couldn't asynchronously call a JDBC provider (manually spawn a separate thread, use actors, etc.), the actual connection to the database will always be synchronous.
JDBCTemplate is also fully synchronous and blocking, there is no thread magic going on under the hood.
Related
I have to write an operation to database only if a subsequent (non transactional) operation succeeds.
The condition is that the operation (let's say, send an e-mail) is slow, and I want to rollback de transaction if this operation fails. The structure is very simple:
#Transactional // A transaction starts and a connection is taken.
public void doStuff(String text) {
writeToDataBase(text);
sendEmail(text); //Rollback previous operation if this fails.
}
It works fine like this, the problem is that if the "sendEmail(text)" operation is slow, then the database connection keeps blocked until this operation finishes, the transaction is commited and the connection released.
I am performing load tests and the connection seems to be behaving in a way that I dont understand, it throws this error:
Connection oracle.jdbc.driver.T4CConnection#50e5e340 marked as broken because of SQLSTATE(72000), ErrorCode(1013)
How should this kind of logic be managed?
Thanks!
I am trying to implement hystrix with #Transactional on a method in spring boot.
#Transactional(transactionManager="primaryTrnsManager")
#HystrixCommand(commandKey ="createRecord", fallbackMethod="createRecordFallback", commandProperties={
#HystrixProperty(name="execution.siolation.thread.timeoutInMilliseconds",value="1000"),
#HystrixProperty(name="circuitBreaker.requestVoulumeThreshold",value="20"),
#HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="5000"),
#HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="50")})
public String createRecord(String name){
...............
//Dbcall
}
#Transactional(transactionManager="backUptranManager",propagation=propagation.REQUIRES_NEW)
public String createRecordFallback(){
//dbcall
}
What what is happeneing is when the hystrix timeout happens the call i made to database is not getting rollback and the hystrix is falling back to secondary and again calling the database with same sql query. In case of timeout, i want to abort the previous transaction and start another one. Usually #Transactional does that but with hystrix,i am inserting dubplicate records.
Any Help?
This happen because the HistryxCommand is ran in a completely different thread, so, when the "Histryx Admin Thread" (the one which is watching your command thread) reaches the timeout, it's marking the command thread to be interrupted, but what happen inside of it can't be managed by Hyxtrix.
So, the best approach to reach out the behaviour that you want, is set the timeout for the transaction or even at the jdbc library level, so, the timeout will be managed from inside the command thread, if it's reached out, the Timeout Exception will be throwed from inside the command thread, and Hyxtrix will manage it properly.
I have a NIFI-Processor that subscribes to a few tags on a OPC UA server.
I'm struggling to find a way to terminate the subscription. My plan was to just keep it running until I decide to stop the processor.
I tried defining functions for #OnStopped, #OnUnscheduled and #OnDisabled, but they never get called when I stop or disable the processor.
I'm on NIFI 1.7 so I can terminate the processor's thread, but my #OnStopped, #OnUnscheduled and #OnDisabled functions still don't get called.
Does terminating the thread mean that the thread won't return from onTrigger in a fashion that allows calling the above mentioned lifecycle methods?
EDIT: As requested, my method with annotation:
#OnStopped
private void OnStopped() {
getLogger().info("Subscriptions cleared - stopped");
miloOpcUAService.clearSubscriptions();
}
Your method has to have public visibility, otherwise the scheduler (which uses reflection) can't find it to invoke it.
I have a controller action that does the following things:
Gets a domain object from the database
Uses info on that object to find a data file (on disk) and writes contents of that file to the response output stream.
My problem is that the database connection is reserved for the duration of the action, including the (long) time required to stream the data. This results in a lot of unnecessary database connections when there are several users streaming data at the same time.
def stream() {
StreamDetails sd = StreamDetails.get(params.id)
// Extract info needed to read the stream
String filename = sd.filename
// The database connection is no longer needed, how to properly release it?
// Start writing the data stream to response output
// This may take a long time and does not use a db connection
streamService.writeToOutput(filename,response.getOutputStream())
}
I have tried:
Injecting the sessionFactory bean to the controller and calling sessionFactory.currentSession.close() before calling the service. However this causes a SessionException on the line calling the service, ie. before entering the writeToOutput() method (and nothing in that method needs a database connection). AND I don't think the session should be really closed, just released to the pool.
Copy-pasting the code from streamService.writeToOutput(...) to the controller to avoid the service call. In this case all the code gets executed but a SessionException is still thrown after the action is complete.
How to properly release the connection early?
Have you tried to inject the dataSource? You could use the DataSourceUtils to create a new connection that you can then use to get the filename. You can then manually close() this connection.
I don't know if you can use this connection in combination with gorm, so you might have to create a custom sql query as well.
We have our JBoss and Oracle on separate servers. The connections seem to be dropped and is causing issues with JBoss. How can I have the JBoss reconnect to Oracle if the connection is bad while we figure out why the connections are being dropped in the first place?
Whilst you can use the old "select 1 from dual" trick, the downside with this is that it issues an extra query each and every time you borrow a connection from the pool. For high volumes, this is wasteful.
JBoss provides a special connection validator which should be used for Oracle:
<valid-connection-checker-class-name>
org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker
</valid-connection-checker-class-name>
This makes use of the proprietary ping() method on the Oracle JDBC Connection class, and uses the driver's underlying networking code to determine if the connection is still alive.
However, it's still wasteful to run this each and every time a connection is borrowed, so you may want to use the facility where a background thread checks the connections in the pool, and silently discards the dead ones. This is much more efficient, but means that if the connections do go dead, any attempt to use them before the background thread runs its check will fail.
See the wiki docs for how to configure the background checking (look for background-validation-millis).
There is usually a configuration option on the pool to enable a validation query to be executed on borrow. If the validation query executes successfully, the pool will return that connection. If the query does not execute successfully, the pool will create a new connection.
The JBoss Wiki documents the various attributes of the pool.
<check-valid-connection-sql>select 1 from dual</check-valid-connection-sql>
Seems like it should do the trick.
Not enough rep for a comment, so it's in a form of an answer. The 'Select 1 from dual' and skaffman's org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker method are equivalent , although the connection check does provide a level of abstraction. We had to decompile the oracle jdbc drivers for a troubleshooting exercise and Oracle's internal implementation of the ping is to perform a 'Select 'x' from dual'. Natch.
JBoss provides 2 ways to Validate connection:
- Ping based AND
- Query based
You can use as per requirement. This is scheduled by separate thread as per duration defined in datasource configuration file.
<background-validation>true</background-validation> <background-validation-minutes>1</background-validation-minutes>
Some time if you are not having right oracle driver at Jboss, you may get classcast or related error and for that connection may start dropout from connection pool. You can try creating your own ConnectionValidator class by implementing org.jboss.resource.adapter.jdbc.ValidConnectionChecker interface. This interface provides only single method 'isValidConnection()' and expecting 'NULL' in return for valid connection.
Ex:
public class OracleValidConnectionChecker implements ValidConnectionChecker, Serializable {
private Method ping;
// The timeout (apparently the timeout is ignored?)
private static Object[] params = new Object[] { new Integer(5000) };
public SQLException isValidConnection(Connection c) {
try {
Integer status = (Integer) ping.invoke(c, params);
if (status.intValue() < 0) {
return new SQLException("pingDatabase failed status=" + status);
}
}
catch (Exception e) {
log.warn("Unexpected error in pingDatabase", e);
}
// OK
return null;
}
}
A little update to #skaffman's answer. In JBoss 7 you have to use "class-name" attribute when setting valid connection checker and also package is different:
<valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.oracle.OracleValidConnectionChecker" />
We've recently had some floating request handling failures caused by orphaned oracle DBMS_LOCK session locks that retained indefinitely in client-side connection pool.
So here is a solution that forces session expiry in 30 minutes but doesn't affect application's operation:
<check-valid-connection-sql>select case when 30/60/24 > sysdate-LOGON_TIME then 1 else 1/0 end
from V$SESSION where AUDSID = userenv('SESSIONID')</check-valid-connection-sql>
This may involve some slow down in process of obtaining connections from pool. Make sure to test this under load.