C3p0 connection pooling Tomcat Apache concept - java

1) Difference between the constructors of InitialContext.
public InitialContext(Hashtable<?,?> environment)
what does this constructor do and what will environment parameter do .
2)
Hashtable<Object, String> environment= new Hashtable<Object, String> (2);
--
--
Context ctx = new InitialContext( environment);
ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
comboPooledDataSource.setJdbcUrl(----);
comboPooledDataSource.setDriverClass(----);
ctx.bind (__);
please explain each line what does it do..
3)Why to create combopooldatasource object ,instead we can create datasource object..??

Answer for 3rd question : Datasource can not be created for ordinary domains,its only for JNDI domains.
For 1st : InitialContext is used to set the environment to create the pooled datasource by creating .bindings file
For 2nd : Context sets the environment.
ComboPooledDataSource object is created.
For that object the url and jdbc driver class wll be set to take the connections from DB to the Pool.
Above set things will be binded to the context and it will be wriiten in .bindings file in encoded format

Related

How to set the jdbc ClientInfo in a MySQL DataSource

In Java with MySQL we want to add the jdbc ClientInfo to identify the source of each query. Currently we can do something like:
try(Connection connection = dataSource.getConnection()){
connection.setClientInfo("ApplicationName", "MyApp");
}
But I need to add it to every connection created and means checking all the source code for places where a new connection is created. I will like to set it to the DataSource level.
So far what works for me is to extends the DataSource with a custom overriden getConnection method that calls setClientInfo. This is not only a dirty workarround but datasource specific.
I have seen that mysql driver has ClientInfoProviders like the default com.mysql.cj.jdbc.CommentClientInfoProvider. A custom ClientInfoProvider can be configured like:
Properties properties = new Properties();
properties.setProperty(PropertyKey.clientInfoProvider.getKeyName(), "foo.bar.CustomClientInfoProvider");
properties.setProperty(APPLICATION_NAME, "MyApp");
HikariConfig dataSourceConfig = new HikariConfig();
dataSourceConfig.setDataSourceProperties(properties);
...
But it is only called if someone calls the getClientInfo in the connection anyway.
So I will like to know:
Is there support in the MySql driver to set the clientInfo in the DataSource just by setting properties?
If there is a way. How can it be done?
I think you can use AspectJ as a possible solution for it. You can create an aspect which will intercept calls of the DataSource.getConnection method and then call the setClientInfo method with configured parameters when the connection is established.

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.

How to dynamically change Spring JdbcTemplate DataSource?

I have a config file with default settings for JDBC connection.
Is there any option to edit this default connection details once application is running? After all beans has been created (edit connection details in the controller).
Scenario:
user starts the application, and can edit connection details by going to
localhost:8080/myapp/db/edit
fills in connection details and saves new database details
This should then find existing connections, update connection details and reinstantiate beans.
You can try removing beans from Spring Container and re initiating them.
Demo demo = getBean(context);
ConfigurableListableBeanFactory configurableListableBeanFactory = context
.getBeanFactory();
BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) configurableListableBeanFactory;
// Removing the bean from container
beanDefinitionRegistry.removeBeanDefinition("demo");
// Trying to obtains bean again from container. This will throw a null
demo = getBean(context);
//demo object will be null here
// Creating and registering bean to the container
BeanDefinition beanDefinition = new RootBeanDefinition(Demo.class);
beanDefinition.setAttribute("name", "name");
beanDefinitionRegistry.registerBeanDefinition("demo", beanDefinition);
context.refresh();
//Obtaining from container again
demo = getBean(context);

Getting NullPointerException when running simple JMS

Am trying to run a simple JMS app, sadly got NullPointException . following are the links to the files of the app :
1. Producer.java
2. SynchConsumer.java
Tools used : Eclipse & GlassFish
following is the exception
Exception in thread "main" java.lang.NullPointerException
at coreservlets.Producer.main(Producer.java:96)
Any flash put into this shall be appreciated .
If you run your stand-alone application without any container around it, the #Resource injections will not work. Instead you have to do manual JNDI lookups for both the connection factory and the queue/topic:
Example:
final Properties initialContextProperties = new Properties();
final String factory = "jms/ConnectionFactory";
final String queueName = "jms/Queue";
//
final InitialContext ic = new InitialContext(initialContextProperties);
final QueueConnectionFactory qcf = (QueueConnectionFactory) ic
.lookup(factory);
final Queue queue = (Queue) ic.lookup(queueName);
As for the configuration of the InitialContext, look here: Glassfish V3.x and remote standalone client
connectionFactory.createConnection();
connectionFactory, even if static, is never initialized. For this reason it is null and you get the null pointer when you try to access the method inside it.
Two way of fixing.
If the method is static, don't declare the var, just call:
ConnectionFactory.createConnection();
If the method is not static (strange, for a class that is static), you have to do something like:
private ConnctionFactory connectionFactory = new ConnectionFactory();

Java: Multiple Data Resources inside the same servlet

"javax.naming.Context" is commonly used inside Java EE development. It's quite convenient to use it to establish dynamical database connection by calling its lookup function with given names of resources inside context.xml. The sample code is shown as following where "db_name" is the name you used to identify the database resource.
Context ctx = new InitialContext();
DataSource ds = ctx.lookup("java:comp/env/jdbc/db_name");
My concern is what are the differences between lookup resources by using the same context and lookup resources by using different contexts. And which approach makes more sense or suitable? Suppose all database resources are defined inside the same context.xml file. For example:
Context ctx = new InitialContext();
DataSource ds1 = ctx.lookup("java:comp/env/jdbc/db_name_ds1");
DataSource ds2 = ctx.lookup("java:comp/env/jdbc/db_name_ds2");
and
Context ctx_ds1 = new InitialContext();
Context ctx_ds2 = new InitialContext();
DataSource ds1 = ctx_ds1.lookup("java:comp/env/jdbc/db_name_ds1");
DataSource ds2 = ctx_ds2.lookup("java:comp/env/jdbc/db_name_ds2");
Thank you for your sharing.
there is no difference except you created an unnecessary extra java object. however, if the jndi server was remote, you would have created two different network connections and iverhead of managing them - definetly not what one should do.

Categories