Inject java.sql.Connection into controller for Ninja Framework - java

I want to use JOOQ to access my database from the Ninja Framework. How can I get a JDBC connection from a controller?
Here's resources I found that didn't quite work.
How to retrieve the datasource used by a persistence unit programmatically - Tedious set of steps to get the connection from an EntityManager.
http://blog.jooq.org/2015/05/26/type-safe-queries-for-jpas-native-query-api/ - works by building a query in JOOQ and passing to EntityManager.createNativeQuery. It's functional, but it's not as nice as just having the connection.
Could I inject the connection into a controller like so:
public Result myController(#DBConnection Connection connection) {
List<String> articles = DSL.using(connection).selectFrom(ARTICLE).fetch(ARTICLE.TITLE);
return Results.html().render("template", articles);
}
DropWizards has a plugin that looks like a winner: https://github.com/benjamin-bader/droptools/tree/master/dropwizard-jooq
public BlogPost getPost(#QueryParam("id") int postId, #Context DSLContext database) {
BlogPostRecord post = database
.selectFrom(POST)
.where(POST.ID.equal(postId))
.fetchOne();
// do stuff
}

Following up on #LukasEder's answer this is the approach:
HibernateEntityManagerFactory hibernateEntityManagerFactory = ((EntityManagerImpl) entityManager).getFactory();
SessionFactoryImpl sessionFactoryImpl = (SessionFactoryImpl) hibernateEntityManagerFactory.getSessionFactory();
C3P0ConnectionProvider c3P0ConnectionProvider = (C3P0ConnectionProvider) sessionFactoryImpl.getConnectionProvider();
Connection connection = c3P0ConnectionProvider.getConnection();
This is obviously very very strange and bad code.
A clean solution is to provide access to Connection / DataSource by Ninja directly (separating the connection pool from Hibernate or any implementation). That is not too hard and is partly done in the ebeans plugin. Let's discuss that on our mailing list if you are interested in contributing code :)

Short of any option to retrieve a JDBC Connection or DataSource from ninja framework directly, the standard approach should be to "unwrap" it from the EntityManager:
Connection connection = em.unwrap(Connection.class);
See also: How to get DataSource or Connection from JPA2 EntityManager in Java EE 6
A Hibernate-specific approach is documented here: How to retrieve the datasource used by a persistence unit programmatically

Related

Spring Transaction (#Transaction) with Plain JDBC without JdbcTemplate

I have plain JDBC code which is doing transaction management using Connection Interface. I wanted to switch to Spring Transaction Management in small steps.
Firstly I want to provide PlatformTransactionManager for my datasource and annotate my class / methods with #Transaction and keep my other logic same ie. using connection / PreparedStatement etc.
All the examples, which I see use JdbcTemplate. I was wondering can Spring Transaction be used without JdbcTemplate?
Technically it is possible to use #Transactional without JdbcTemplate . But if you try to do it , you will sooner or later find that you are re-inventing what the things that are already done by JdbcTemplate.
What #Transactional does is that before executing a #Transactional method , it will help you to get a JDBC Connection from the DataSource , and start a transaction on this Connection .The JDBC Connection will then stored in a ThreadLocal.
That means if you do it without JdbcTemplate , you have to manually get this Connection from that ThreadLocal such that you can create a JDBC Statement from it for executing your SQL. Not to mention you have to manually release the JDBC resources such Statement , ResultSet etc. properly by yourself which all of these things are already take care by JdbcTemplate.
But if you have already implemented these JDBC codes manually and just want to let #Transactional to handle the transaction , you could try to inject the DataSource to your bean and then use the following method to get the Connection for your JDBC codes use :
Connection connection = DataSourceUtils.getConnection(dataSource);
Also checkout JdbcTemplate#execute(ConnectionCallback<T> action) , it is useful for migrating the existing JDBC codes that expects a JDBC Connection to work on to JdbcTemplate.
Yes it's possible. Adding a #Transactional annotation to your methods, as long as they follow the correct procedure should make your methods transactional. But as others have mentioned if you're in the process of updating your app you might as well ditch plain JDBC and move across to Spring JPA/JDBC (depending on which version of Spring you're using).

Create SqlSession from existing Connection directly

I'm working with existing Java code wherein there is an existing JDBC connection pooling mechanism on deployed systems and an already existing setup to get JDBC connections. I'd like to leverage this to create a MyBatis SqlSession object without creating a Configuration, DataSource, and other things
I have code that already creates a java.sql.Connection object is given the desired resource. I'd like to leverage this and get that SqlSession object and use MyBatis from that point onwards.
I don't want MyBatis to manage connection pooling, determining which data source to use, etc. Is this possible?
I'm afraid you can't avoid creation of the Configuration object. It is used by the internal mybatis machinery like executors. But even if you could it will not help you much. In this case you will need to implement most of Configuration functionality yourself so it does not make sense to do that.
You main goal is to be able to use SqlSessionFactory.openSession(Connection connection) method. To do this you need to have SqlSessionFactory. The easiest way for you is to create Configuration like it is descried in mybatis documentation:
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development", transactionFactory, dataSource);
Configuration configuration = new Configuration(environment);
// set properties to configuration here
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(configuration);
Now if your connection pool does implement DataSource you use it directly to create environment. If it does not you need to create an adapter around your pool which implements javax.sql.DataSource.
My solution is similar to Roman's above, but I needed to create an Oracle datasource. For various reasons, the connection needs to be created using the Class.forName type sequence
Class.forName("oracle.jdbc.driver.OracleDriver");
String connectionString = "jdbc:oracle:thin:#//yadayada";
String username = "myusername";
String password = "mypassword";
OracleDataSource oracleDataSource = new OracleDataSource();
oracleDataSource.setURL(connectionString);
oracleDataSource.setPassword(password);
oracleDataSource.setUser(username);
environment = new Environment("dev",transactionFactory,oracleDataSource);
configuration = new Configuration(environment);
configuration.addMappers("MyMybatisMapper");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
return sqlSessionFactory.openSession();
What I was missing was the OracleDataSource object.

Get the url that the Connection uses to connect the database

I'm trying to get the url that the Connection uses to connect the database as following :
getEntityManager().unwrap(SessionImplementor.class).connection().getMetaData().getURL();
But I get this error :
java.lang.IllegalStateException: No transactional EntityManager available
How can I solve this ?
Edit:
I don't understand why this question was considered as duplicated to a Hibernate solution, I'm using JPA, so I'm trying to get the url using entityManager and not sessionFactory.
The solution was to add the #Transactional annotation.
The SessionImplementor Interface is form Hibernate, so which JPA Implementation are you using then?

AutoCommit did not work with jOOQ 2.6.1 and Tomcat pooling

I use jOOQ 2.6.1 and the pooling from Tomcat (docs) and I have set autocommit to true.
PoolProperties p = new PoolProperties();
p.setDefaultAutoCommit(true);
p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;" +
"org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
p.setRemoveAbandoned(true);
p.setRemoveAbandonedTimeout(10);
then I created an Apache DataSource object:
org.apache.tomcat.jdbc.pool.DataSource dataSource = new DataSource
dataSource.setPoolProperties(p);
and I use the LazyConnectionDataSourceProxy from Spring:
LazyConnectionDataSourceProxy lazyConnection = new LazyConnectionDataSourceProxy(dataSource);
From jOOQ 2.6.1 is use the Factory:
public Factory createFactory() {
Settings settings = new Settings();
settings.getExecuteListeners().add(
"de.si.srv.data.SpringExceptionTranslationExecuteListener");
return new Factory(dataSource, SQLDialect.POSTGRES, settings);
}
if I do for example a select like this:
createFactory().select().from().fetch()
... jOOQ should close the connection automatically! But jOOQ does not close the connection.. All connections are after some time Abandoned.
Does anybody know a solution for my problem? I want that jOOQ closes the connections automatically! Or should I use an other pooling framework?
Which works better with jOOQ?
There have been quite a few changes and fixes around that area in jOOQ 3.x, the most important one being:
https://github.com/jOOQ/jOOQ/issues/2373
or should i use an other pooling framework ?
I don't think another pooling framework will help, here.
If you want to continue working with jOOQ 2.6.1 (instead of upgrading to jOOQ 3.2), I guess you might need to either:
Patch jOOQ and fix this issue
Handle the DataSource / Connection lifecycle yourself and pass a Connection to jOOQ

Jboss AP6 Transaction Manager Implementation

I'm just starting to learn Jboss AP6 and I have a few questions:
I created Local Tx Datasource (MySql Database)and can access it in my code using JNDI.
Now I would like to create kind of Transaction Management resource inside of my Jboss AP.
1) Is there any JTA feature built in Jboss AP6?
2) Can I apply it to my local DataSource which I created?
3) Can you please point me to any documentation which explains how to configure it and use it in my code, ot is there any article which coversthese topics in depth?
I googled it for some period of time, but haven't found any useful documentation. I don't want to use Spring/Hibernate out of the box solution just Mysql and plain JTA.
JBoss AP6 support JTA 1.1
Yes you can
If you declareLocalTxDatasource, this is mean, than whenever you get
connection from this datasource this connection will participate in "current" transaction.
If you want to manupulate transaction yourself, without EJB for example, you must enject TransactionManager from JNDI.
Example
TransactionManager tm = (TransactionManager)context.lookup("java:/TransactionManager");
tm.begin();
try{
DataSource ds = context.lookup("java:/testDS");
connection = ds.getConnection()
//do useful work
connection.close();
tm.commit();
}catch(Exception e){
tm.rollback()
}

Categories