I'm trying to get connection for my web application
I'm using DataSource object and it's injected by #Resource
#Resource(name="jdbc/name")
private DataSource dataSource;
and then in method getConnection() trying to get connection from DataSource object by
private Connection getConnection() {
Connection con = null;
try {
con = dataSource.getConnection();
} catch (SQLException e) {
LOGGER.error(e.getMessage());
}
return con;
}
But my dataSource is null and I'm getting a NullPointerException. By the way, the same code works fine in class, that extends HttpServlet. I need to use this code in simple DBManager class.
Help please, what I have to do?
P.S. I have configured context.xml and web.xml
Autowiring only works when Spring creates the bean for you. If you use new DBManager() to create the instance, then Spring won't care.
So you need to create or get the application context (which should be configured to contain a DBManager bean) and then use that.
Related
I have a data source that is setup & then, used by a third party software to execute sql. After the sql is run I have another bean that executes & closes the connection.
#Bean
public DataSource datasource() {
HikariConfig myconfig = new HikariConfig();
...
return new HikariDataSource(myconfig);
}
#Bean
#DependsOn("sqlproject")
public void closeConnection() throws SQLException {
Connection c = datasource().getConnection();
try {
c.close();
}
finally {
System.out.println(c.isClosed());
}
}
However, I can clearly still make local calls using that datasource connection to particular data. Should I not be calling datasource() because this creates a new instance ? What am I doing wrong ?
You're right, when you're calling datasource from configuration class, new instance is created because Spring AOP doesn't support self invocation via this.
Moreover, even if you have used this AOP correctly, this wouldn't have closed DataSource, since you're creating new connection (via getConnection() and then closing it.
If you want to close HikariDataSource, then you need to call HikariDataSource#close.
Also, you don't need #Bean annotation on your void method since it makes no sense.
I'm using SQLServer along with Springs JtaTransactionManager.
Given a method like this:
#Transactional
public void something() {
try (final Connection conn1 = getConnection()) {
//insert/update stuff in database
}
try (final Connection conn2 = getConnection()) {
//insert/update stuff in database
}
}
Will this method actually be transactional? What happens to the changes made when conn1 gets closed, are they commited to the database? What happens if an exception occurs while working with conn2, can the changes made through a closed connection be rolled back?
You shouldn't load/get connection or datasource manually inside #Transactional, especially when using JtaTransactionManager
The JtaTransactionManager does not need to know about the DataSource, or any other specific resources, because it uses the container’s global transaction management infrastructure.
I want to alter Oracle session for every connection that I get from the connection pool.
I found that it can be done by simply execute a statement. See here.
Is there a way to hook into the jdbc template or the datasource and execute a statement after the connection pool creates a new connection.
I'm using Spring Boot and creating the datasource that way:
#Bean
#ConfigurationProperties(prefix="datasource.local")
public DataSource localDataSource() {
return DataSourceBuilder.create().build();
}
There are a lot of ways to do so.
The first one:
DataSource is an interface, so why don't you implement it yourself (use Proxy pattern)? Create something like this:
class MyDataSource implements DataSource {
private DataSource realDataSource;
public Connection getConnection() {
Connection c = realDataSource.getConnection();
// do whatever you want to do and
return c;
}
}
All other methods will delegate directly to realDataSource.
This proxy can be used in a provided code snippet.
You can use some AOP - just provide an advice that after get connection is created will run and do whatever you need there. Basically it's the same proxy but automatically created by Spring.
I have an EntityManager bean object called in service classes as autowired object.
Spring Config class:
#EnableWebMvc
#Configuration("myWebConfiguration")
#ComponentScan(basePackages = {"org.my.app"})
#EnableScheduling
public class MyWebConfiguration extends WebMvcConfigurerAdapter {
....
private static EntityManager entityManager;
#Bean
public EntityManager entityManager() {
if (entityManager == null) {
entityManager = managerFactoryBean().getObject().createEntityManager();
}
return entityManager;
}
....
private Properties hibernateProperties() {
Properties properties = new Properties();
properties.setProperty("hibernate.hbm2ddl.auto", "update");
properties.setProperty("hibernate.show_sql", "true");
properties.setProperty("hibernate.format_sql", "true");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQL9Dialect");
return properties;
}
....
}
Sample Service class:
#Service("sampleService")
public class SampleService {
#Autowired
protected EntityManager entityManager;
public Object find(Class entityClass, Object id) {
return entityManager.find(entityClass, id);
}
....
}
And the problem:
If connection between WebApp server and DB server get lost, JPA and spring cannot reconnect to the DB Server and calling entityManager methods causes exceptions such as org.postgresql.util.PSQLException: This connection has been closed. and org.hibernate.exception.JDBCConnectionException: could not inspect JDBC autocommit mode.
Is it possible to detect connection loss automatically and re-establishing the connection in case of connection loss?
That is possible and that is a responsibility fulfilled by connection pooling (or datasource that supports connection pooling) libraries.
For example, If you use DBCP, you can set parameters like validationQuery="SELECT 1" and testOnBorrow="true" that allows detect the connection status and reopen if needed.
Similarly, c3p0 allows to configure such parameters using c3p0.testConnectionOnCheckout=true etc.
Other connection pooling libraries would expose similar configuration.
If you are already using a connection pooling library (or datasource that uses connection pool) you may want to check its documentation to get the relevant configuration properties to be set. If not, you may want to consider using a connection pooling library or a data source that uses connection pooling and exposes those parameters.
UPDATE:
For c3p0 can you add the following properties and test:
properties.setProperty("hibernate.c3p0.preferredTestQuery","SELECT 1");
properties.setProperty("hibernate.c3p0.testConnectionOnCheckout","true");
I want to create instances of a class which will have access to the underlying Embedded derby database and pass this class to each bundle binding to my database bundle using declarative services.
I have seen in the derby documentation that sharing one connection for multiple threads has many pitfalls. So I was thinking to create a connection for each instance of the class I am creating. Since I only want a very simple way to just create multiple connections and manage them, using "MiniConnectionPoolManager" here seems like a good option. The sample code for derby is shown below:
org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource dataSource = new org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource();
dataSource.setDatabaseName("c:/temp/testDB");
dataSource.setCreateDatabase("create");
MiniConnectionPoolManager poolMgr = new MiniConnectionPoolManager(dataSource, maxConnections);
...
Connection connection = poolMgr.getConnection();
...
connection.close();
But the documentation does not cover many things plus I am a beginner in using Database. My questions are:
When I am creating a new class that will need database connection to perform insert,update & other actions. Shall I pass the 'poolMgr' and call poolMgr.getConnection() from the newly created class?
When should I close this connection? I don't know for how long the bundle (user) will use the new class so shall I save the newly created connection in a private global variable and force the user to execute unregister class where I could then close the connection? Or shall I just close all connections when my database bundle is being deactivated.
Other suggestions are also appreciated to manage different classes accessing one database. Thank you in advance.
Edit:
The main class in my database bundle is always active as long as the application is running. It is the bundles requesting for an instance of a new class(performing database operation) that come and go. And also since it will be deployed in embedded system, I can only use small footprint applications.
You should get a connection from a connection pool when you need it and close the connection as soon as you can. It is the job of the connection pool to re-use connections, not yours.
In other words: Do not keep a connection alive until your consumer bundle is deactivated.
Connection pools normally implement DataSource interface, you should use the pools via it. In that case you can replace the pool implementation easily without changing your code. E.g:
#Component
public class MyComponent {
// Connection pool based DataSource
#Reference
DataSource dataSource;
public void myFunction() {
try (Connection c = dataSource.getConnection()) {
// Database operations
} catch (SQLException e) {
// TODO
}
}
}
When you find yourself repeating the same code many times (getting connection, catching SQLException), you can write a simple component that accepts functional interfaces. E.g.:
#Component
#Service
public class SQLHelper {
#Reference // This is a connection pool DataSource
private DataSource dataSource;
public <R> R execute(Callback<R> callback) {
try (Connection c = dataSource.getConnection()) {
return callback.call(c);
} catch (SQLException e) {
throw new UncheckedSQLException(e);
}
}
}
Your functional interface would look like this:
public interface Callback<R> {
R call(Connection connection);
}
And you would use it like this:
sqlHelper.execute((Connection c) -> {
// Do some stuff with the connection
});
Using transactions
If you want to use atomic transactions, I suggest that you should use org.apache.derby.jdbc.EmbeddedXADataSource together with org.apache.commons.dbcp.managed.BasicManagedDataSource from commons-dbcp. After that, you can handle transactions via JTA.
It is hard to use the JTA API directly. You should choose a library that helps you propagating transactions.
A small guide based on Declarative Services:
Install derby jar into your OSGi container
Install pax-derby bundle as well! By doing that, you will have a DataSourceFactory OSGi service
Install everit-dsf-bundle with its dependencies! You will see two new DS components. Create a configuration for the one called XADataSource via the webconsole! All configuration options have descriptions.
Install a JTA Transaction Manager into the OSGi container! You have several choices. I
Install everit-commons-dbcp-component with its dependencies! You will see two new DS components. Configure the Managed one in the webconsole and set the previously created XADataSource as the target! The transactional pool will take care of providing the same connection if you request-and-close connections whitin the scope of the same transaction.
normally use Aries Transaction Manager that embeds Geronimo TM.
Install everit-transaction-helper to your OSGi container! You will see a new OSGi service with the interface TransactionHelper (that is provided by a configurable DS component).
Now you have everything to write your code. Your component would similar to the following:
#Component
#Service
public class MyComponent {
#Reference
private DataSource dataSource;
#Reference
private TransactionHelper th;
public void myFunction() {
th.required(() -> {
try (Connection c = dataSource.getConnection()) {
// My SQL statements
} catch (SQLException e) {
// TODO
}
}
}
}
In case you do not need transaction handling, you can:
use the standard EmbeddedDataSource
use any non-transactional connection pool
skip the installation of the TransactionManager and TransactionHelper bundles
skip the usage of TransactionHelper from the code
A more complex guide (that also takes care of schema creation and uses OO based queries) is available at http://cookbook.everit.org/persistence/index.html.
Update
You do not have to get a connection for every SQL statement. You should get a connection, execute as many SQL statements that you can within a "moment" and than call close on the connection.
If you have to run three SQL statements right behind each other, you should request a connection, execute the three SQL statements and than call close on the connection
If you close the requested connection within the same function you requested it from the pool, you probably do things right. You might call other functions passing the connection as a parameter, but they should only use it to run SQL statements and than return.
You should not keep alive a connection and wait for another user action. That is the job of the connection pool. When you call close on a connection that is provided by a pool, the connection is not closed physically, but only retrieved to the pool.
You should keep the connection object in a local variable. If you use a member variable for your connection object, you should suspect that something is wrong with your code (the only exception is if you pass the Connection to an object that lives for a very short time and that object holds the connection in a member variable to have cleaner code).
Please note that if you use Java 6 or earlier, you should close the connection in a finally block to avoid unclosed connections.
MiniConnectionPoolManager might be a great solution for embedded devices as it is really "mini". The only issue is that it does not implement the DataSource interface so your business code shuold directly use the MiniCPM classes. By doing that, it will be much harder to switch to other Connection pool if you find a bug or you need a more complex pool later.
If you decide to use MiniCPM, I suggest that you should write a component that implements DataSource and delegates the getConnection() function to a MiniCPM instance. E.g.:
#Component
#Service
public class MiniCPMDataSourceComponent implements DataSource {
#Reference
protected ConnectionPoolDataSource cpDataSource;
private MiniConnectionPoolManager wrapped;
#Activate
public void activate() {
this.wrapped = new MiniConnectionPoolManager(cpDataSource);
}
#Override
public Connection getConnection() {
return wrapped.getConnection();
}
#Override
public Connection getConnection(String user, String password) {
throw new UnsupportedOperationException();
}
#Deactivate
public void deactivate() {
wrapped.dispose();
}
}
You can decorate this component with configuration possibilities like the max connection number and timeout (that is supported by MiniCPM). If you use the service that is provided by this component, you will be able to switch the connection pool without changing your business code. Also, your business bundle will not be wired directly to MiniCPM.